Closed1

LangChainのPandas Dataframe Agentで遊んでみる

kun432kun432

LangChainにはPandas Dataframe Agentというのがある。

https://python.langchain.com/en/latest/modules/agents/toolkits/examples/pandas.html

どうやらpandasのデータフレームとLLMをつなぐものの様子。

これはちょっと面白そうということで試してみた。こういうデータフレームを用意する。

from langchain.agents import create_pandas_dataframe_agent
from langchain.llms import OpenAI

llm = OpenAI(temperature=0.9, max_tokens=2048)

agent = create_pandas_dataframe_agent(llm, df_race, verbose=True)

agent.run("データフレームは、中山競馬場で行われた2023年有馬記念(GI・芝2500m)のレース結果です。「着順」がレースの最終順位を表しています。「枠」・「馬番」は発走ゲートの番号で、数字の小さいほうから内枠、大きいほうが外枠となります。人気、単勝オッズは各馬の単勝馬券の売れ行きとオッズを表しており、数字が小さいほうが人気となります。後3Fおよび後3F順位はレースの後半3ハロン(600m)の走破時計とその順位を表しており、馬の能力を測る指標として重視されていますが、最終順位ではありません。コーナー通過順は、コースの各コーナー時点での順位を表しており、各コーナーごとにハイフンで区切られて表現されます。例えば、4-2-1であれば、2コーナーでは4番手、3コーナーでは2番手、4コーナーでは先頭、ということになります。プロの競馬評論家になりきって、レース全体の展開、1〜3番人気馬および1〜3着馬のレース内容について、それぞれ説明してください。ステップバイステップで。")

結果。中間回答も表示しました。

> Entering new AgentExecutor chain...

Thought: 指定された結果をもとにレースの展開や1〜3番人気馬、1〜3着馬のレース内容を考えていく。
Action: python_repl_ast
Action Input: print(df)    着順  枠  馬番         馬名  人気  単勝オッズ   後3F      コーナー通過順  後3F順位
0    1  5   9    イクイノックス   1    2.3  35.4      8-9-6-3      2
1    2  2   3   ボルドグフーシュ   6   14.1  35.2   14-14-15-6      1
2    3  3   5   ジェラルディーナ   3    7.4  35.7  14-14-11-12      3
3    4  1   2  イズジョーノキセキ  13  152.0  36.1      7-7-8-6      4
4    5  4   7    エフフォーリア   5   10.1  36.3      5-5-4-3      6
5    6  4   8   ウインマイティー  15  199.6  36.2  10-10-11-12      5
6    7  5  10  ジャスティンパレス   7   18.9  36.6      3-3-4-5      7
7    8  8  16    ディープボンド   8   37.3  36.8      3-3-2-2      8
8    9  7  13   タイトルホルダー   2    3.6  37.6      1-1-1-1     15
9   10  3   6    ヴェラアズール   4   10.0  36.8   11-11-11-9      8
10  11  7  14     ボッケリーニ  14  183.8  37.5      5-5-6-6     12
11  12  6  12       ポタジェ  12  136.9  37.3      8-7-8-9     10
12  13  6  11    ラストドラフト  16  215.3  37.5   11-11-8-11     12
13  14  2   4    アリストテレス  10   85.0  37.5  11-11-11-16     12
14  15  1   1      アカイイト   9   79.0  37.4  16-16-15-15     11
15  16  8  15    ブレークアップ  11  118.6  39.4     2-2-2-12     16

Observation: None
Thought: 頭から順番に展開を考えていく。
Action: python_repl_ast
Action Input: print(df.sort_values("着順"))    着順  枠  馬番         馬名  人気  単勝オッズ   後3F      コーナー通過順  後3F順位
0    1  5   9    イクイノックス   1    2.3  35.4      8-9-6-3      2
1    2  2   3   ボルドグフーシュ   6   14.1  35.2   14-14-15-6      1
2    3  3   5   ジェラルディーナ   3    7.4  35.7  14-14-11-12      3
3    4  1   2  イズジョーノキセキ  13  152.0  36.1      7-7-8-6      4
4    5  4   7    エフフォーリア   5   10.1  36.3      5-5-4-3      6
5    6  4   8   ウインマイティー  15  199.6  36.2  10-10-11-12      5
6    7  5  10  ジャスティンパレス   7   18.9  36.6      3-3-4-5      7
7    8  8  16    ディープボンド   8   37.3  36.8      3-3-2-2      8
8    9  7  13   タイトルホルダー   2    3.6  37.6      1-1-1-1     15
9   10  3   6    ヴェラアズール   4   10.0  36.8   11-11-11-9      8
10  11  7  14     ボッケリーニ  14  183.8  37.5      5-5-6-6     12
11  12  6  12       ポタジェ  12  136.9  37.3      8-7-8-9     10
12  13  6  11    ラストドラフト  16  215.3  37.5   11-11-8-11     12
13  14  2   4    アリストテレス  10   85.0  37.5  11-11-11-16     12
14  15  1   1      アカイイト   9   79.0  37.4  16-16-15-15     11
15  16  8  15    ブレークアップ  11  118.6  39.4     2-2-2-12     16

Observation: None
Thought: 1〜3番人気馬のレース内容を考える。
Action: python_repl_ast
Action Input: print(df.loc[(df['人気'] <= 3)])   着順  枠  馬番        馬名  人気  単勝オッズ   後3F      コーナー通過順  後3F順位
0   1  5   9   イクイノックス   1    2.3  35.4      8-9-6-3      2
2   3  3   5  ジェラルディーナ   3    7.4  35.7  14-14-11-12      3
8   9  7  13  タイトルホルダー   2    3.6  37.6      1-1-1-1     15

Observation: None
Thought: 1〜3着馬のレース内容を考える。
Action: python_repl_ast
Action Input: print(df.sort_values("着順").iloc[0:3])   着順  枠  馬番        馬名  人気  単勝オッズ   後3F      コーナー通過順  後3F順位
0   1  5   9   イクイノックス   1    2.3  35.4      8-9-6-3      2
1   2  2   3  ボルドグフーシュ   6   14.1  35.2   14-14-15-6      1
2   3  3   5  ジェラルディーナ   3    7.4  35.7  14-14-11-12      3

Observation: None
Thought: I now know the final answer
Final Answer: 
2023年有馬記念のレース展開は、5番枠から発走したイクイノックスが先頭を守り、脚質の良いボルドグフーシュ、ジェラルディーナと続き、後半位置取りのイズジョーノキセキを抑え、3着争いに入っていった。1〜3番人気馬としては、イクイノックス、ジェラルディーナ、ボルドグフーシュがそれぞれ人気を占めており、最後はイクイノックスが差し切りの一着を果たした。1〜3着馬ではイクイノックス、ボルドグフーシュ、ジェラルディーナがそれぞれ最終順位を占め、コーナー通過順をいち早く把握して上位の争いに入った。

> Finished chain.
2023年有馬記念のレース展開は、5番枠から発走したイクイノックスが先頭を守り、脚質の良いボルドグフーシュ、ジェラルディーナと続き、後半位置取りのイズジョーノキセキを抑え、3着争いに入っていった。1〜3番人気馬としては、イクイノックス、ジェラルディーナ、ボルドグフーシュがそれぞれ人気を占めており、最後はイクイノックスが差し切りの一着を果たした。1〜3着馬ではイクイノックス、ボルドグフーシュ、ジェラルディーナがそれぞれ最終順位を占め、コーナー通過順をいち早く把握して上位の争いに入った。

それっぽくまとめてくれてはいるものの、色々間違っているところもある。

ちなみに関係ないけど参考までに実際の隊列はこんな感じ(コーナー通過順をplotlyで可視化してます。)

ではGPT-4だとどうなるか。GPT-4の場合はChatModelになるので、少し書き換える必要がある様子。

from langchain.agents import create_pandas_dataframe_agent
from langchain.chat_models import ChatOpenAI

chat = ChatOpenAI(model="gpt-4", temperature=0.9, max_tokens=2048)

agent = create_pandas_dataframe_agent(chat, df_race, verbose=True)

agent.run("データフレームは、中山競馬場で行われた2023年有馬記念(GI・芝2500m)のレース結果です。「着順」がレースの最終順位を表しています。「枠」・「馬番」は発走ゲートの番号で、数字の小さいほうから内枠、大きいほうが外枠となります。人気、単勝オッズは各馬の単勝馬券の売れ行きとオッズを表しており、数字が小さいほうが人気となります。後3Fおよび後3F順位はレースの後半3ハロン(600m)の走破時計とその順位を表しており、馬の能力を測る指標として重視されていますが、最終順位ではありません。コーナー通過順は、コースの各コーナー時点での順位を表しており、各コーナーごとにハイフンで区切られて表現されます。例えば、4-2-1であれば、2コーナーでは4番手、3コーナーでは2番手、4コーナーでは先頭、ということになります。プロの競馬評論家になりきって、レース全体の展開、1〜3番人気馬および1〜3着馬のレース内容について、それぞれ説明してください。ステップバイステップで。")

どうもcreate_pandas_dataframe_agentはChatModelを想定していないか、もしくはPythonReplの問題なのか、最終的にパースエラーになってしまう。ただパースエラーになった出力でもある程度はLLMの回答がわかる。

ValueError: Could not parse LLM output: `I now have all necessary data about 1 - 3 top popular horses and 1 - 3 final ranking horses to analyze the race.

The race was won by the most popular horse, イクイノックス (Iquinox), with an odds of 2.3. It finished the race with a 35.4s time for the last 3 furlongs, ranking 2nd in that aspect. Throughout the race, it gradually moved up from the 8th position at the 1st corner to the 3rd position at the 4th corner.

Second place went to ボルドグフーシュ (Bold Gouache), which was the 6th favorite horse with odds of 14.1. Its last 3 furlongs time was 35.2s, ranking 1st in that aspect. Its race was remarkable as it made a significant move from the 14th position at the 1st corner to the 6th position at the 4th corner.

The third-place finisher was ジェラルディーナ (Geraldina), the 3rd favorite horse with odds of 7.4. It had a last 3 furlongs time of 35.7s, ranking 3rd in that aspect. It moved up from the 14th position at the 1st corner to the 12th position at the 4th corner, showing steady progress throughout the race.

The race's overall development was characterized by the strong performance of the favorite horses, especially イクイノックス (Iquinox), which showed great ability in maintaining and improving its position throughout the race. Other favorite horses, such as タイトルホルダー (Title Holder), who was the 2nd favorite with odds of 3.6, did not perform as expected and finished in 9th place. Notably, an unexpected strong performance was seen from ボルドグフーシュ (Bold Gouache), which overcame its initial position and managed to reach the 2nd place.`

DeepL訳

これで、人気上位馬1~3頭、最終順位馬1~3頭について、レース分析に必要なデータが揃った。

レースは1番人気のイクイノックスが2.3倍のオッズで優勝。ラスト3ハロン35.4秒の好タイムで2着。1コーナーの8番手から徐々に順位を上げ、4コーナーで3番手に浮上した。

2着はボルドグフーシュで、オッズは14.1倍と6番人気だった。ラスト3ハロンのタイムは35.2秒で、この点では1位。1コーナーの14番手から4コーナーの6番手まで大きく順位を上げたレースぶりは目を見張るものがあった。

3着はオッズ7.4倍の3番人気ジェラルディーナ。ラスト3ハロン35.7秒の好タイムで3番手。1コーナーの14番手から4コーナーの12番手まで順位を上げ、終始安定した走りを見せた。

レース全体の展開としては、人気馬の活躍が目立ち、特にイクイノックスは終始ポジションを維持・向上させる高い能力を持っていた。一方、オッズ3.6倍で2番人気に推されたタイトルホルダーなどは、期待に反して9着に終わった。特に、ボルドグフーシュは、当初のポジションを覆して2着に食い込むなど、予想外の健闘を見せている。

かなり適切な感じになったのではないか。プロンプトの与え方なども工夫の余地はあるけど、可視化ではない方法でサマリーしてくれるというのはなかなか面白い。

このスクラップは2023/04/07にクローズされました