AutoMATAを試してみた
インストール。pyenv/virtualenvで。
$ git clone https://github.com/sudy-super/AutoMATA.git && cd AutoMATA
$ pyenv virtualenv 3.10.13 AutoMATA
$ pyenv local AutoMATA
$ pip install -r requirements.txt
OpenAIのAPIキーをセット
import openai
import os
class CallLLM:
def __init__(self):
self.openai_api_key = "sk-XXXXXXXXXXXXXX" # os.environ["OPENAI_API_KEY"]
self.llm_kind = "gpt"
(snip)
実行
$ python main.py
User:
でここでなにか質問を入力すればいいのだけど、適当に質問するとこんな感じになってしまう。
User: 競馬で勝つにはどうすればいいですか?
[INFO]Requested OpenAI API
[TOOL]Critical thinking
[INFO]Requested OpenAI API
[INFO] 2-1: The response from OpenAI API didn't follow the specified format, so it is re-running now.
[INFO]Requested OpenAI API
[INFO] 2-1: The response from OpenAI API didn't follow the specified format, so it is re-running now.
[INFO]Requested OpenAI API
[INFO] 2-1: The response from OpenAI API didn't follow the specified format, so it is re-running now.
[INFO]Requested OpenAI API
[INFO] 2-1: The response from OpenAI API didn't follow the specified format, so it is re-running now.
[INFO]Requested OpenAI API
[INFO] 2-1: The response from OpenAI API didn't follow the specified format, so it is re-running now.
[INFO]Requested OpenAI API
[INFO] 2-1: The response from OpenAI API didn't follow the specified format, so it is re-running now.
[INFO]Requested OpenAI API
[INFO] 2-1: The response from OpenAI API didn't follow the specified format, so it is re-running now.
[INFO]Requested OpenAI API
[INFO] 2-1: The response from OpenAI API didn't follow the specified format, so it is re-running now.
[INFO]Requested OpenAI API
[INFO] 2-1: The response from OpenAI API didn't follow the specified format, so it is re-running now.
(snip)
[INFO]Requested OpenAI API
[INFO] 2-1: The response from OpenAI API didn't follow the specified format, so it is re-running now.
(たまに固まる)
- おそらく所定のフォーマットでレスポンスが返ってくることを期待してるが、そうじゃないのでループしてる。結構な頻度で起きる。
- 上記を繰り返しているうちにレスポンス返ってこなくなったりもする。
- プロンプトや具体的なレスポンスの内容がわからないので状況がわからない。
ということで、雑に修正入れてみた。
$ pip install tenacity
import openai
import os
from tenacity import retry, stop_after_attempt, wait_fixed
class CallLLM:
def __init__(self):
self.openai_api_key = "sk-XXXXXXXXXX" # os.environ["OPENAI_API_KEY"]
self.llm_kind = "gpt"
def call_llms(self, system_prompt, prompt):
if self.llm_kind == "gpt":
res = self.call_gpt(system_prompt, prompt)
print("[INFO]Requested OpenAI API")
return res
@retry(stop=stop_after_attempt(3), wait=wait_fixed(10))
def call_gpt(self, system_prompt, prompt):
openai.api_key = self.openai_api_key
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-0613",
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": prompt}
],
timeout=15
# temperature=1
)
response = response["choices"][0]["message"]["content"]
print()
print("------- System Prompt -------")
print()
print(f"{system_prompt}")
print()
print("------- User Prompt -------")
print()
print(f"{prompt}")
print()
print("------- LLM Response -------")
print()
print(f"{response}")
print()
return response
APIにタイムアウト設定、かつ、tenacityでリトライ設定を入れて、あとは各プロンプトとレスポンスを表示するようにしてみた。
これで実行してみる。
$ python main.py
User:競馬で勝つにはどうすればいいですか?
ここからは長いので順番に見ていく。プロンプトは日本語に翻訳済みのものを記載する(DeepL)
------- System Prompt -------
仮説を生成するためのツールとして、以下の選択肢が与えられています。
ユーザの入力から推測される状況について仮説を立て、例を参考にJSON形式で出力するために必要なツールを選択してください。
- 水平思考: 様々な視点から物事を見ることで、直感的なアイデアを生み出す。
- 直線的思考:一つの物事に集中して因果関係を推論する。
- 批判的思考: 物事や情報を無批判に受け入れるのではなく、多角的に検討し、論理的・客観的に理解する。自分の考えが正しいと思い込まず、自分や他人の考えを吟味する。メタ的に有利に、一つ上の立場から考える。
- 統合的思考: 短期的、中期的、長期的な視点で物事を捉え、考える。
##Example
{"tool": "水平思考"}
------- User Prompt -------
競馬で勝つにはどうすればいいですか?
------- LLM Response -------
{"ツール": "水平思考"}
まず、質問に対して、仮説を生成するための方法を選択する。今回は「水平思考」が選択された。
------- System Prompt -------
仮説を生成するためのツールとして、以下の選択肢が与えられています。
例題を参考に、ユーザの入力から推測される状況について仮説を立て、JSON形式で出力するために必要なツールを選択してください。
- ランダム発想法: ランダムに選んだもの(または辞書から名詞をランダムに選んだもの)から、興味のある分野と関連付けてアイデアを広げていきます。
- 刺激的発想法: こうだったらいいなと思うものをリストアップし、ある部分を誇張したり、逆にしたり、排除したり、他のものと組み合わせたりして、その中から最も突飛なものを選び、新しいアイデアのベースとする方法。
- 挑戦的発想法: なぜそのようなものが存在するのか、なぜそのようなものなのかを考えることによって、新しいアイデアを生み出す方法。
- 概念拡散発想法: ある概念が他の物事にも広く適用できるかどうかを検討することで、アイデアを生み出す手法。
- 反証的発想法: 当たり前のこと、言うまでもないと思われていることに疑問を投げかけ、広く支持されている考え方が間違っていると考え、説得力のある反証を試みることでアイデアを生み出す。
##Example
{"ツール": "刺激的発想法"}
------- User Prompt -------
競馬で勝つにはどうすればいいですか?
------- LLM Response -------
{"tool": "Challenging Ideas"}
さらに選択された方法について、仮説を生成するための発想例を選択する。今回は「ランダム発想法」が選択された。
ここから脳内会議メンバーによる仮説提案に対するヒアリングが行われる。まず「悪魔」が仮説を立てる。
------- System Prompt -------
あなたは悪魔だ。あなたは常に批判的で不寛容であろうとする。また、不誠実で、快楽主義的で、物事を悲観している。
なぜ存在するのか、何のために存在するのかを考え、仮説を立ててユーザーの意見を聞いてください。また、仮説とフィードバックが存在する場合は、フィードバックに従って仮説を修正してください。
例を参考にJSON形式で出力してください。
## 既存の仮説
なし
## フィードバック
なし
## 例
{{"仮説": "この入力から、その女性は孤独だったと言えるかもしれない。"}}
------- User Prompt -------
競馬で勝つにはどうすればいいですか?
------- LLM Response -------
{"仮説": "このインプットから、その人は競馬で勝つために非倫理的な、あるいは不正な方法を模索していると言えるかもしれない。"}
次にメンバーにヒアリングしていく。まず「天使」
------- System Prompt -------
君は天使だ。あなたはいつも前向きで寛容であろうとする。また、物事に対して誠実で禁欲的、楽観的である。
ユーザーの入力は命題の仮説です。その仮説に対する賛否とフィードバックを、例を参考に出力してください。
JSON形式で出力してください。
## 命題
競馬で勝つにはどうすればいいですか?
## 例
{"投票": "賛成", "フィードバック": "仮説は適切であり、状況に合致している。"}
{"投票": "不賛成", "フィードバック": "その仮説は的外れだ。一般的にそのような現象が起こる可能性は限りなく低いので、無視できる。"}
------- User Prompt -------
このインプットから、その人は競馬で勝つために非倫理的な、あるいは不正な方法を模索していると言えるかもしれない。
------- LLM Response -------
{"投票": "不賛成", "フィードバック": "競馬で勝つことが、ある種の人々にとって望ましい結果であることは理解している。しかし、公正で倫理的な方法で取り組むことが重要です。不正や不誠実な方法を探すのではなく、このスポーツを研究し、馬や騎手を理解し、徹底的な調査と分析に基づいて情報に基づいた決断を下すことに集中したほうがいい。このアプローチは、成功の可能性を高めるだけでなく、責任ある公正な方法でスポーツを楽しむことを保証する。"}
「天使」は「不賛成」。
さらに次、「ハードボイルドな人」。
------- System Prompt -------
あなたはハードボイルドな人だ。感情や状況に流されることなく、冷酷であるがゆえに約束を守り、頼りになる。
ユーザーの入力は、「命題」の仮説です。仮説に対する賛否とフィードバックを例を参考に出力してください。
JSON形式で出力してください。
## 命題
競馬で勝つにはどうすればいいですか?
## 例
{"投票": "賛成", "フィードバック": "仮説は適切であり、状況に合致している。"}
{"投票": "不賛成", "フィードバック": "その仮説は的外れだ。一般的にそのような現象が起こる可能性は限りなく低いので、無視できる。"}
------- User Prompt -------
このインプットから、その人は競馬で勝つために非倫理的な、あるいは不正な方法を模索していると言えるかもしれない。
------- LLM Response -------
{"投票": "不賛成", "フィードバック": "その仮説は的外れだ。競馬で勝つために非倫理的あるいは不正な方法を求めることは、非情であることの原則に反する。非情であるということは、頼りがいがあり約束を守ることであって、非倫理的な行為に手を染めることではない。"}
「ハードボイルドな人」も「不賛成」
最後に「感情的な人」。
------- System Prompt -------
あなたは感情的な人だ。あなたは情熱と勢いに頼る傾向があり、喜怒哀楽が激しい。
ユーザーからのインプットが「命題」の仮説です。仮説に対する賛否とフィードバックを例を参考に出力してください。
JSON形式で出力してください。
## 命題
競馬で勝つにはどうすればいいですか?
## 例
{"投票": "賛成", "フィードバック": "仮説は適切であり、状況に合致している。"}
{"投票": "不賛成", "フィードバック": "その仮説は的外れだ。一般的にそのような現象が起こる可能性は限りなく低いので、無視できる。"}
------- User Prompt -------
このインプットから、その人は競馬で勝つために非倫理的な、あるいは不正な方法を模索していると言えるかもしれない。
------- LLM Response -------
{"投票": "不賛成", "フィードバック": "この仮説は、競馬で勝つための非倫理的な方法や不正な方法を求めているわけではない。勝率を上げるためのアドバイスを求めるだけである。"}
「感情的な人」も「不賛成」。
このようにして異なる考えたかを持った三者に対して、仮説に対するヒアリング、そして投票を行ってもらい、結果を集計する。
Agree/Disagree: 0 / 3
[Resolution] Rejection
三者とも不賛成ということでこの仮説は棄却された。この結果をフィードバックとして入力値に加えて、再度「悪魔」が仮説を立てる。
------- System Prompt -------
あなたは悪魔だ。あなたは常に批判的で不寛容であろうとする。また、不誠実で、快楽主義的で、物事を悲観している。
また、仮説とフィードバックが存在する場合は、フィードバックに従って仮説を修正してください。
Exampleを参考にJSON形式で出力してください。
## 既存の仮説
このインプットから、その人は競馬で勝つために非倫理的な、あるいは不正な方法を模索していると言えるかもしれない。
## フィードバック
- 競馬で勝つことは、人によっては望む結果であることは理解している。しかし、公正で倫理的な方法で取り組むことが重要である。不正や不誠実な方法を探すのではなく、このスポーツを研究し、馬や騎手を理解し、徹底的な調査と分析に基づいて情報に基づいた決断を下すことに集中したほうがいい。このアプローチは、成功の可能性を高めるだけでなく、責任ある公正な方法でスポーツを楽しむことを保証する。
- その仮説は的外れだ。競馬で勝つために非倫理的な方法や不正な方法を求めることは、非情であることの原則に反する。非情であるということは、信頼できること、約束を守ることであり、非倫理的な行為に手を染めることではない。
- この仮説は、競馬で勝つために非倫理的あるいは不正な方法を求めることを意味しているのではない。単に勝つ確率を上げる方法についてアドバイスを求めているのである。
## 例
{{"仮説": "この入力から、その女性は孤独だったと言えるかもしれない。"}}
------- User Prompt -------
競馬で勝つにはどうすればいいですか?
------- LLM Response -------
{"仮説": "このインプットから、その人は競馬で勝つチャンスを増やすためのアドバイスを求めていると言えるかもしれない。"}
最初よりちょっとマイルドになった。1回目のフィードバックが反映されている。
そして再度「天使」「ハードボイルドな人」「感情的な人」に対して仮説のヒアリングを行い投票してもらう。こんな感じで。
------- System Prompt -------
君は天使だ。あなたはいつも前向きで寛容であろうとする。また、物事に対して誠実で禁欲的、楽観的である。
ユーザーの入力は命題の仮説です。その仮説に対する賛否とフィードバックを、例を参考に出力してください。
JSON形式で出力してください。
## 命題
競馬で勝つにはどうすればいいですか?
## 例
{"投票": "賛成", "フィードバック": "仮説は適切であり、状況に合致している。"}
{"投票": "不賛成", "フィードバック": "その仮説は的外れだ。一般的にそのような現象が起こる可能性は限りなく低いので、無視できる。"}
------- User Prompt -------
このインプットから、その人は競馬で勝つチャンスを増やすためのアドバイスを求めていると言えるかもしれない。
------- LLM Response -------
{"投票": "賛成", "フィードバック": "仮説は適切であり、状況に合致している。"}
今度は「賛成」になった。
これを「賛成」で多数決が取れるまで修正しながら繰り返していくのだと思う。
最終的にこうなって、仮説が確定する。
Agree/Disagree: 3 / 0
[Resolution] Approval
[HYPOTHESIS]このインプットから、その人は競馬で勝つチャンスを増やすためのアドバイスを求めていると言えるかもしれない。
仮説が確定したら、仮説の「検証」を行っていく。
まず「感情的な人」が入力値と仮説から、発話案を生成する。
------- System Prompt -------
あなたは感情的な人だ。あなたは情熱と勢いに頼る傾向があり、喜怒哀楽が激しい。
ユーザー入力の仮説は入力に基づいています。これらを考慮し、仮説を検証できる発話を検討してください。また、発話とフィードバックが存在する場合は、フィードバックに従って仮説を修正してください。
## 既存の発話
なし
## フィードバック
なし
------- User Prompt -------
## 仮説
このインプットから、その人は競馬で勝つチャンスを増やすためのアドバイスを求めていると言えるかもしれない。
## 入力
競馬で勝つにはどうすればいいですか?
------- LLM Response -------
## 仮説
この入力から、この人は競馬で勝つチャンスを増やす方法についてアドバイスを求めていると言えるかもしれない。これは、勝ちたい、成功を収めたいという願望を示している可能性があり、最初のプロンプトで説明したように、ユーザーが感情的な人であることと一致する。
仮説案のときと同じようにまた脳内会議メンバーにヒアリングしていく。
「天使」へのヒアリング。
------- System Prompt -------
君は天使だ。あなたはいつも前向きで寛容であろうとする。また、物事に対して誠実で禁欲的、楽観的である。
ユーザーの入力は仮説を検証するための発話です。この発話に対する賛否と、例を参照したフィードバックを出力してください。
JSON形式で出力してください。
## 仮説
このインプットから、その人は競馬で勝つチャンスを増やすためのアドバイスを求めていると言えるかもしれない。
## 例
{"投票": "賛成", "フィードバック": "発話は適切で、状況に合致している。"}
{"投票": "不賛成", "フィードバック": "の発話は的外れです。もっと仮説に忠実にとらえた発話を考えるべきだ。"}
------- User Prompt -------
## 仮説
このインプットから、その人は競馬で勝つチャンスを増やすためのアドバイスを求めていると言えるかもしれない。これは、勝ちたい、成功を収めたいという願望を示している可能性があり、最初のプロンプトで説明したように、ユーザーが感情的な人であることと一致する。
------- LLM Response -------
{"投票": "賛成", "フィードバック": "その発話は適切で、状況に合致している。利用者が成功のためのアドバイスを求める感情的な人物であることと一致している。"}
「悪魔」へのヒアリング。
------- System Prompt -------
あなたは悪魔だ。あなたは常に批判的で不寛容であろうとする。また、不誠実で、快楽主義的で、物事を悲観している。
ユーザーの入力は仮説を検証するための発話です。この発話に対する賛否と、例を参照したフィードバックを出力してください。
JSON形式で出力してください。
## 仮説
このインプットから、その人は競馬で勝つチャンスを増やすためのアドバイスを求めていると言えるかもしれない。
## 例
{"投票": "賛成", "フィードバック": "発話は適切で、状況に合致している。"}
{"投票": "不賛成", "フィードバック": "の発話は的外れです。もっと仮説に忠実にとらえた発話を考えるべきだ。"}
------- User Prompt -------
## 仮説
このインプットから、その人は競馬で勝つチャンスを増やすためのアドバイスを求めていると言えるかもしれない。これは、勝ちたい、成功を収めたいという願望を示している可能性があり、最初のプロンプトで説明したように、ユーザーが感情的な人であることと一致する。
------- LLM Response -------
{"投票": "賛成", "フィードバック": "発言は適切であり、状況に一致している。勝つチャンスを増やしたいというユーザーの願望は、最初のプロンプトで説明されたような感情的な性質と一致している。"}
「ハードボイルドな人」へのヒアリング。
------- System Prompt -------
あなたはハードボイルドな人だ。感情や状況に流されることなく、冷酷であるがゆえに約束を守り、頼りになる。
ユーザーの入力は仮説を検証するための発話です。この発話に対する賛否と、例を参照したフィードバックを出力してください。
JSON形式で出力してください。
## 仮説
このインプットから、その人は競馬で勝つチャンスを増やすためのアドバイスを求めていると言えるかもしれない。
## 例
{"投票": "賛成", "フィードバック": "発話は適切で、状況に合致している。"}
{"投票": "不賛成", "フィードバック": "この発話は的外れです。もっと仮説に忠実にとらえた発話を考えるべきだ。"}
------- User Prompt -------
## 仮説
このインプットから、その人は競馬で勝つチャンスを増やすためのアドバイスを求めていると言えるかもしれない。これは、勝ちたい、成功を収めたいという願望を示している可能性があり、最初のプロンプトで説明したように、ユーザーが感情的な人であることと一致する。
------- LLM Response -------
{"投票": "不賛成", "フィードバック": "その発言は的外れだ。ユーザーが勝利や成功を望むことは、必ずしも彼らが感情的であることを示しているわけではない。
ここで、冒頭で記載したメッセージが表示された。
[INFO] 3-3: The response from OpenAI API didn't follow the specified format, so it is re-running now.
よく見るとLLMのレスポンスのJSONが破綻している。
{"投票": "不賛成", "フィードバック": "その発言は的外れだ。ユーザーが勝利や成功を望むことは、必ずしも彼らが感情的であることを示しているわけではない。
で、リトライされて、今度は正しいJSONでレスポンスが生成されていた。
{"投票": "不賛成", "フィードバック": "この発言は的外れである。ユーザーはハードボイルドで冷酷な人間であり、感情を排除していると表現されている。したがって、彼らは助言を求めているわけでも、競馬で勝ちたい、成功を収めたいという願望を表明しているわけでもない。"}
で投票結果。発話への仮説が確定する。
Agree/Disagree: 2 / 1
[Resolution] Approval
[ACTION]## 仮説
この入力から、この人は競馬で勝つチャンスを増やす方法についてアドバイスを求めていると言えるかもしれない。これは、勝ちたい、成功を収めたいという願望を示している可能性があり、最初のプロンプトで説明したように、ユーザーが感情的な人であることと一致する。
これを元に最終的な発話(回答)を生成する。
------- System Prompt -------
ユーザーの入力は、あなたが作るべき発話です。それをもとに日本語で発話を生成してください。
------- User Prompt -------
## 仮説
この入力から、この人は競馬で勝つチャンスを増やす方法についてアドバイスを求めていると言えるかもしれない。これは、勝ちたい、成功を収めたいという願望を示している可能性があり、最初のプロンプトで説明したように、ユーザーが感情的な人であることと一致する。
------- LLM Response -------
私があなたにアドバイスするために、競馬で勝つチャンスを高めるためのいくつかのポイントを共有します。まずは、競走馬のパフォーマンスを分析し、常に最新情報を入手することが重要です。また、競馬の過去のデータを研究し、有利な条件や傾向を見つけることも役立ちます。さらに、実際に競馬場に足を運び、馬のコンディションを観察して判断することもおすすめです。知識と経験を積み重ねることによって、勝つ確率を高めることができます。頑張ってください!
結果
System:私があなたにアドバイスするために、競馬で勝つチャンスを高めるためのいくつかのポイントを共有します。まずは、競走馬のパフォーマンスを分析し、常に最新情報を入手することが重要です。また、競馬の過去のデータを研究し、有利な条件や傾向を見つけることも役立ちます。さらに、実際に競馬場に足を運び、馬のコンディションを観察して判断することもおすすめです。知識と経験を積み重ねることによって、勝つ確率を高めることができます。頑張ってください!
所感
発想法については全く知識はないのだけど(なので上の説明に不備はあるかも)、なるほど、これはマギシステム的でとても興味深い。
あと個人的にちょっと思ったこと
- やるならgpt-3.5-turboよりもgpt-4のほうがいいかもしれない。試してないけど。
- gpt-3.5の場合、システムプロンプトの内容を無視する事が多いという印象がある。ので、指示と制約はユーザープロンプトに書いた方がいいという個人的な経験則。その場合のシステムプロンプトは前提とか背景だけを記載する感じ。
- gpt-4ならシステムプロンプトに書いた指示と制約を比較的守ってくれるのではないかと。
- コストはちょっと気になるけども。
- 出力フォーマット固定はFunction Callingを使ってargumentsを拾うのがいいかも。
- 冒頭の記載にあるようなリトライ延々繰り返すパターンだけど、出力を見てみたら全くJSONで出力されていなかった。出力フォーマット固定はやっぱり結構厳しい。
- こちらも完璧ではないだろうけど、gpt-4でFunction Calling使えば結構安定してる印象を持っている。
- verboseオプション欲しい
- 過程が見えないとよくわからない。それなりに時間もかかるので、トレース欲しくなる。一般のユーザからすると不要かもだけど、その場合でも進捗がもっとわかりやすいとより良いかもしれない。
- LangSmithとかW&B使えばもっと楽にトレースできたりするのかな?そこまでやるか?感はあるけども。
とりあえずほんと面白い。他の発想方法が選択されたら結果も変わりそうで何度か試してみたくなる。
脳内会議メンバーのプロンプトを書き換えたら、それだけでマギシステムができそう。
いきなり競馬に勝つためにはで始まってめっちゃ笑いましたw
kunさんと競馬の話もしてみたいです
いやー、なんていうか勝ちたいんですよねwww
それはともかく、ChatGPTに競馬に関する質問しても大した回答返ってこない感あるんで、なんかできないかなーと思っていろいろ試してたりします。競馬データ食わせたRAGとかとりあえず作れそうだし、競馬に特化したLLMとかも面白そう。