Spaces:
Runtime error
Runtime error
shigeru saito
commited on
Commit
·
04b2d94
1
Parent(s):
d06c4af
init
Browse files- .gitignore +1 -0
- app.py +161 -0
- folklore.csv +85 -0
- openai_function_calling_sample_code.py +299 -0
- requirements.txt +4 -0
.gitignore
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
.env
|
app.py
ADDED
@@ -0,0 +1,161 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# 必要なモジュールをインポート
|
2 |
+
import os
|
3 |
+
import sys
|
4 |
+
import json
|
5 |
+
import csv
|
6 |
+
import dotenv
|
7 |
+
import openai
|
8 |
+
from langchain.chat_models import ChatOpenAI
|
9 |
+
from langchain.agents import initialize_agent, Tool
|
10 |
+
from langchain.schema import (
|
11 |
+
AIMessage,
|
12 |
+
HumanMessage,
|
13 |
+
FunctionMessage
|
14 |
+
)
|
15 |
+
from langchain.chat_models import ChatOpenAI
|
16 |
+
from langchain.agents import AgentType
|
17 |
+
|
18 |
+
# .envファイルから環境変数をロード
|
19 |
+
dotenv.load_dotenv(".env")
|
20 |
+
|
21 |
+
# OpenAIキーをosモジュールで取得
|
22 |
+
openai.api_key = os.environ.get("OPENAI_API_KEY")
|
23 |
+
|
24 |
+
# 民間伝承を取得する関数
|
25 |
+
def fetch_folklore(location):
|
26 |
+
folklore_lookup = {}
|
27 |
+
# CSVファイルからデータを読み取り、地点をキー、伝承を値とする辞書を作成
|
28 |
+
with open('folklore.csv', 'r') as f:
|
29 |
+
reader = csv.DictReader(f)
|
30 |
+
folklore_lookup = {row['location']:row['folklore'] for row in reader}
|
31 |
+
|
32 |
+
# 指定された地点の伝承を返す。存在しない場合は不明を返す。
|
33 |
+
return folklore_lookup.get(location, "その地域の伝承は不明です。")
|
34 |
+
|
35 |
+
# LangChainエージェントからレスポンスを取得する関数
|
36 |
+
def get_response_from_lang_chain_agent(query_text):
|
37 |
+
# ChatOpenAIを使用して言語モデルを初期化
|
38 |
+
language_model = ChatOpenAI(model_name='gpt-3.5-turbo-0613')
|
39 |
+
tools = [
|
40 |
+
# 民間伝承を取得するToolを作成
|
41 |
+
Tool(
|
42 |
+
name = "Folklore",
|
43 |
+
func=fetch_folklore,
|
44 |
+
description="伝承を知りたい施設や地名を入力。例: 箱根寄木細工",
|
45 |
+
)
|
46 |
+
]
|
47 |
+
# エージェントを初期化してから応答を取得
|
48 |
+
agent = initialize_agent(tools, language_model, agent="zero-shot-react-description", verbose=True, return_intermediate_steps=True)
|
49 |
+
response = agent({"input": query_text})
|
50 |
+
return response
|
51 |
+
|
52 |
+
# 関数呼び出しからレスポンスを取得する関数
|
53 |
+
def get_response_from_function_calling(query_text):
|
54 |
+
function_definitions = [
|
55 |
+
# 関数の定義を作成
|
56 |
+
{
|
57 |
+
"name": "fetchFolklore",
|
58 |
+
"description": "伝承を調べる",
|
59 |
+
"parameters": {
|
60 |
+
"type": "object",
|
61 |
+
"properties": {
|
62 |
+
"location": {
|
63 |
+
"type": "string",
|
64 |
+
"description": "伝承を知りたい施設や地名。例: 箱根寄木細工",
|
65 |
+
},
|
66 |
+
},
|
67 |
+
"required": ["location"],
|
68 |
+
},
|
69 |
+
}
|
70 |
+
]
|
71 |
+
messages=[HumanMessage(content=query_text)]
|
72 |
+
language_model = ChatOpenAI(model_name='gpt-3.5-turbo-0613')
|
73 |
+
# 言語モデルを使ってメッセージを予測
|
74 |
+
message = language_model.predict_messages(messages, functions=function_definitions)
|
75 |
+
|
76 |
+
if message.additional_kwargs:
|
77 |
+
# 関数の名前と引数を取得
|
78 |
+
function_name = message.additional_kwargs["function_call"]["name"]
|
79 |
+
arguments = message.additional_kwargs["function_call"]["arguments"]
|
80 |
+
|
81 |
+
# JSON 文字列を辞書に変換
|
82 |
+
arguments = json.loads(arguments)
|
83 |
+
|
84 |
+
# 関数を実行してレスポンスを取得
|
85 |
+
function_response = fetch_folklore(location=arguments.get("location"))
|
86 |
+
# 関数メッセージを作成
|
87 |
+
function_message = FunctionMessage(name=function_name, content=function_response)
|
88 |
+
# 関数のレスポンスをメッセージに追加して予測
|
89 |
+
messages.append(function_message)
|
90 |
+
second_response = language_model.predict_messages(messages=messages, functions=function_definitions)
|
91 |
+
content = "AIの回答: " + second_response.content
|
92 |
+
else:
|
93 |
+
content = "AIの回答: " + message.content
|
94 |
+
return content
|
95 |
+
|
96 |
+
# Function Call Agentからレスポンスを取得する関数
|
97 |
+
def get_response_from_function_calling_agent(query_text):
|
98 |
+
language_model = ChatOpenAI(model_name='gpt-3.5-turbo-0613')
|
99 |
+
tools = [
|
100 |
+
# 民間伝承情報を提供するツールの追加
|
101 |
+
Tool(
|
102 |
+
name = "Folklore",
|
103 |
+
func=fetch_folklore,
|
104 |
+
description="伝承を知りたい施設や地名を入力。例: 箱根寄木細工"
|
105 |
+
)
|
106 |
+
]
|
107 |
+
# エージェントの初期化とレスポンスの取得
|
108 |
+
agent = initialize_agent(tools, language_model, agent=AgentType.OPENAI_FUNCTIONS, verbose=True, return_intermediate_steps=True)
|
109 |
+
response = agent({"input": query_text})
|
110 |
+
return response
|
111 |
+
|
112 |
+
# メインの実行部分
|
113 |
+
def main(query_text):
|
114 |
+
print(f"Input: {query_text}")
|
115 |
+
|
116 |
+
# LangChainエージェントからのレスポンス
|
117 |
+
response = get_response_from_lang_chain_agent(query_text)
|
118 |
+
print(f"Output of LangChain Agent: {response}")
|
119 |
+
|
120 |
+
# 関数呼び出しからのレスポンス
|
121 |
+
response = get_response_from_function_calling(query_text)
|
122 |
+
print(f"Output of Function Calling: {response}")
|
123 |
+
|
124 |
+
# Function Callingエージェントからのレスポンス
|
125 |
+
response = get_response_from_function_calling_agent(query_text)
|
126 |
+
print(f"Output of Function Calling Agent: {response}")
|
127 |
+
|
128 |
+
import gradio as gr
|
129 |
+
|
130 |
+
def main(query_text):
|
131 |
+
# LangChainエージェントからのレスポンス
|
132 |
+
response1 = get_response_from_lang_chain_agent(query_text)
|
133 |
+
|
134 |
+
# 関数呼び出しからのレスポンス
|
135 |
+
response2 = get_response_from_function_calling(query_text)
|
136 |
+
|
137 |
+
# Function Callingエージェントからのレスポンス
|
138 |
+
response3 = get_response_from_function_calling_agent(query_text)
|
139 |
+
|
140 |
+
return response1, response2, response3
|
141 |
+
|
142 |
+
# gr.Interface()を使ってユーザーインターフェースを作成します
|
143 |
+
# gr.inputs.Text()はテキスト入力ボックスを作成し、
|
144 |
+
# gr.outputs.Textbox()は出力テキストを表示するためのテキストボックスを作成します。
|
145 |
+
iface = gr.Interface(fn=main, inputs=gr.inputs.Textbox(lines=5, placeholder="質問を入力してください"),
|
146 |
+
outputs=[gr.outputs.Textbox(label="LangChain Agentのレスポンス"),
|
147 |
+
gr.outputs.Textbox(label="関数呼び出しのレスポンス"),
|
148 |
+
gr.outputs.Textbox(label="Function Calling Agentのレスポンス")])
|
149 |
+
|
150 |
+
# インターフェースを起動します
|
151 |
+
iface.launch()
|
152 |
+
|
153 |
+
# # スクリプトが直接実行された場合にmain()を実行
|
154 |
+
# if __name__ == "__main__":
|
155 |
+
# try:
|
156 |
+
# query_text = sys.argv[1]
|
157 |
+
# except IndexError:
|
158 |
+
# print("使い方: python app.py '質問の文字列'")
|
159 |
+
# print(" 例) python app.py '醍醐寺の伝承を教えて'")
|
160 |
+
# sys.exit()
|
161 |
+
# main(query_text=query_text)
|
folklore.csv
ADDED
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
location,folklore
|
2 |
+
箱根,箱根山の自然環境を生かした芸術として、箱根寄木細工は江戸時代から伝わる工芸品です。
|
3 |
+
日下部民藝館,日本各地の美しい民芸品が集められ、展示されている美術館です。ここでは地元の人々が代々受け継いできた伝統的な技術が生かされた作品を見ることができます。
|
4 |
+
醍醐寺,平安時代に創建され、豪華な仏像や絵画が数多く保存されている世界遺産です。春には醍醐の花見として知られる見事な桜の景色を楽しむことができます。
|
5 |
+
京都, 元々日本の首都であり、古い伝統や文化が残る観光地として有名です。祇園祭、時代祭といった古くからの伝統行事が今もなお毎年行われています。
|
6 |
+
奈良, 奈良時代に日本の首都となった歴史的な町で、多くの仏教寺院や古代の遺跡があります。奈良公園では鹿と触れ合うことができ、これは古代の神使との交流を象徴しています。
|
7 |
+
金閣寺, 美しい金色の外装で知られる仏教寺院で、観光名所として人気です。金閣寺はあらゆる方位から見て美しく、これは武将足利義満が自身の死後でも名を残したいという願いからきています。
|
8 |
+
鹿児島, 鹿児島県の県庁所在地であり、桜島や種子島などの自然美や温泉地が魅力です。また、江戸時代後期の大久保利通や西郷隆盛らを輩出し確立された「薩摩の薩摩っ子精神」は今も地元に息づいています。
|
9 |
+
石垣島, 沖縄県の離島で、美しいビーチやダイビングスポットがあります。また、島特有の方言で歌われる「防人の詩」は古くから島民によって受け継がれてきたもので、夜の集まりでは未だに歌われています。
|
10 |
+
竹田城址, 天守閣が再建されている日本の城跡で、歴史や風景が楽しめます。
|
11 |
+
佐渡,焚く火祭は年に一度、佐渡島で行われる伝統的なお祭りで、邪気を払う象徴とされています。
|
12 |
+
信州, 長野県の愛称で、美しい自然や温泉地、歴史的な町並みがあります。
|
13 |
+
富士山, 世界遺産に登録されている富士山は、日本を代表する山で観光名所です。
|
14 |
+
松本城, 長野県松本市にある日本の山城で、美しい姿と風景が楽しめます。
|
15 |
+
高野山, 和歌山県にある密教の聖地であり、修行道場としても有名です。
|
16 |
+
東京ディズニーランド, 日本で最も有名なテーマパークで、国内外から多くの観光客が訪れます。
|
17 |
+
大阪城, 大阪府大阪市にある歴史的な城で、美しい姿と広大な敷地が魅力です。
|
18 |
+
名古屋城, 愛知県名古屋市にある城で、美しい姿と歴史的価値があります。
|
19 |
+
長崎, 長崎県の県庁所在地であり、歴史的な町並みやグラバー園、長崎平和公園などがあります。
|
20 |
+
滋賀, 滋賀県は琵琶湖を有する地域で、自然や観光名所が豊富です。
|
21 |
+
稲佐山, 佐賀県唐津市にある活火山で、美しい景色と温泉が楽しめます。
|
22 |
+
宮島, 広島県の島で、厳島神社や大鳥居といった観光名所があります。
|
23 |
+
能登半島, 石川県七尾市にある半島で、美しい海岸や温泉地が人気です。
|
24 |
+
四国, 四国は香川、愛媛、高知、徳島の四県からなる地域で、四国八十八ヶ所巡りが有名です。
|
25 |
+
知床, 北海道の知床半島は世界自然遺産に登録された地域で、豊かな自然が楽しめます。
|
26 |
+
洞爺湖, 北海道の湖で、美しい景色や温泉地があります。
|
27 |
+
那覇, 沖縄県の県庁所在地であり、首里城や国際通りが観光名所です。
|
28 |
+
石垣市, 沖縄県の石垣島にある市で、美しいビーチやリゾートがあります。
|
29 |
+
日光, 栃木県の観光地で、日光東照宮や奥日光の自然と歴史を楽しめます。
|
30 |
+
伊勢神宮, 三重県の伊勢市にある神社で、日本最古の神宮として有名です。
|
31 |
+
大山, 鳥取県と島根県にまたがる山で、登山や自然観察が楽しめます。
|
32 |
+
小豆島, 香川県の離島で、オリーブの産地として有名です。
|
33 |
+
輪島, 石川県輪島市の日本海に面した町で、輪島塗などの伝統的な工芸品が楽しめます。
|
34 |
+
鳴門, 徳島県の鳴門市にある地域で、鳴門の渦潮や大塔宮などが見どころです。
|
35 |
+
高千穂峡, 宮崎県の渓谷で、美しい自然景観や滝が楽しめます。
|
36 |
+
大山寺, 京都府八幡市にある寺院で、美しい庭園や古い建築物があります。
|
37 |
+
道後温泉, 愛媛県松山市にある温泉地で、国内外から多くの観光客が訪れます。
|
38 |
+
北谷町, 沖縄県北谷町の美しい海岸とリゾート地が魅力です。
|
39 |
+
札幌, 北海道の都市で、大通公園や時計台などの観光名所があります。
|
40 |
+
青森, 青森県の県庁所在���であり、ねぶた祭りや津軽三味線が有名です。
|
41 |
+
函館, 北海道の港町で、函館山や五稜郭公園が人気の観光地です。
|
42 |
+
富士急ハイランド, 山梨県富士吉田市にある遊園地で、絶叫マシンが楽しめます。
|
43 |
+
姫路城, 兵庫県姫路市にある歴史的な城で、美しい姿と広大な敷地が魅力です。
|
44 |
+
和歌山城, 和歌山県和歌山市にある山城で、美しい姿と歴史的価値があります。
|
45 |
+
高知城, 高知県高知市にある城で、歴史的な価値と美しい風景が楽しめます。
|
46 |
+
浅草, 東京都台東区にある観光地で、浅草寺や仲見世通りが有名です。
|
47 |
+
広島平和記念公園, 広島県広島市にある原爆ドームや平和記念資料館があります。
|
48 |
+
奈良公園, 奈良県の奈良市にある公園で、多くの鹿が自由に歩いています。
|
49 |
+
秋田犬, 秋田県の秋田市周辺で飼育されている日本の特産犬種です。
|
50 |
+
八甲田山, 青森県と秋田県にまたがる山で、美しい自然景観やハイキングが楽しめます。
|
51 |
+
長崎バイオパーク, 長崎県長崎市にある動物園で、多種多様な動物が飼育されています。
|
52 |
+
高野山, 和歌山県にある密教の聖地であり、修行道場としても有名です。
|
53 |
+
小倉城, 福岡県北九州市にある城で、美しい姿と歴史的な価値があります。
|
54 |
+
湯布院, 大分県由布市にある温泉地で、美しい自然と温泉が楽しめます。
|
55 |
+
天橋立, 京都府宮津市にある景勝地で、美しい景色や自然が楽しめます。
|
56 |
+
姫路市立動物園, 兵庫県姫路市にある動物園で、多種多様な動物が飼育されています。
|
57 |
+
稚内, 北海道の最北端に位置する市で、海の幸や美しい風景が魅力です。
|
58 |
+
宮古島, 沖縄県の島で、美しいビーチやダイビングスポットがあります。
|
59 |
+
黄金千枚田, 新潟県十日町市にある田園景観で、美しい風景が楽しめます。
|
60 |
+
阿寒湖, 北海道釧路市にある湖で、美しい湖と自然景観が楽しめます。
|
61 |
+
山中渓谷, 富山県中新川郡にある景勝地で、美しい渓谷や滝があります。
|
62 |
+
高松城, 香川県高松市にある城で、美しい庭園と歴史的な価値があります。
|
63 |
+
知床五湖, 北海道斜里町にある湖群で、美しい湖と自然が楽しめます。
|
64 |
+
泊まらない温泉, 鳥取県岩美町にある日帰り温泉施設で、美肌効果があると言われています。
|
65 |
+
鹿角市, 青森県の市で、美しい自然と観光名所が魅力です。
|
66 |
+
龍馬のすまい, 高知県高知市にある坂本龍馬ゆかりの地で、歴史的な建造物があります。
|
67 |
+
徳島県立阿波踊り会館, 徳島県徳島市にある会館で、日本の踊りや伝統文化が体験できます。
|
68 |
+
松江城, 島根県松江市にある歴史的な城で、美しい姿と広大な敷地が魅力です。
|
69 |
+
岩手山, 岩手県にある活火山で、美しい山岳景観が楽しめます。
|
70 |
+
長瀞, 埼玉県秩父市にある渓谷で、美しい景観とウミウの天然記念物が魅力です。
|
71 |
+
高尾山, 東京都八王子市にある山で、ハイキングや紅葉が楽しめます。
|
72 |
+
浮島, 滋賀県大津市にある湖上に浮かぶ島で、美しい自然景観が楽しめます。
|
73 |
+
富山湾, 富山県にある湾で、新鮮な海の幸が味わえます。
|
74 |
+
日本平, 静岡県静岡市にある山で、美しい景観と富士山が楽しめます。
|
75 |
+
笠間, 茨城県笠間市にある観光地で、陶磁器や伝統工芸などが楽しめます。
|
76 |
+
宮津市, 京都府宮津市にある町で、天橋立や網野などの観光名所があります。
|
77 |
+
青春18きっぷ, JRが提供する乗り放題切符で、観光列車などの利用が可能です。
|
78 |
+
湯島天神, 東京都台東区にある神社で、学問の神様として知られています。
|
79 |
+
星野リゾート, 北海道や長野県などにある高級リゾートで、自然を満喫できます。
|
80 |
+
忍者寺, 岐阜県可児市にある寺院で、忍者の隠れ家として有名です。
|
81 |
+
耶馬溪, 島根県の山間地に位置する渓谷で、美しい自然景観が楽しめます。
|
82 |
+
鳥取砂丘, 鳥取県にある砂丘で、広大な砂漠のような風景が広がっています。
|
83 |
+
由布院湯布院温泉, 大分県由布市にある温泉地で、美しい自然と温泉が楽しめます。
|
84 |
+
鞆の浦, 広島県福山市にある港町で、昔ながらの町並みや美しい風景が魅力です。
|
85 |
+
小田原城, 神奈川県小田原市にある城で、歴史的な価値と美しい風景が楽しめます。
|
openai_function_calling_sample_code.py
ADDED
@@ -0,0 +1,299 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# -*- coding: utf-8 -*-
|
2 |
+
"""openai_function_calling_sample_code.ipynb
|
3 |
+
|
4 |
+
Automatically generated by Colaboratory.
|
5 |
+
|
6 |
+
Original file is located at
|
7 |
+
https://colab.research.google.com/drive/1FBRyZ2hTn04o_nvNDaZFtroebmN4jiz-
|
8 |
+
|
9 |
+
# Function Calling について LangChain Agent と比較しながら試してみた
|
10 |
+
|
11 |
+
こちらの記事のサンプルコードになります:https://qiita.com/yu-Matsu/items/12b686fe4cab343f50b3
|
12 |
+
|
13 |
+
## 必要なライブラリのインストール
|
14 |
+
"""
|
15 |
+
|
16 |
+
# !pip install openai==0.27.6
|
17 |
+
# !pip install langchain==0.0.205
|
18 |
+
|
19 |
+
"""## 一部ライブラリのインポート、APIキーの設定"""
|
20 |
+
|
21 |
+
import json
|
22 |
+
import os
|
23 |
+
import sys
|
24 |
+
import openai
|
25 |
+
import dotenv
|
26 |
+
|
27 |
+
dotenv.load_dotenv(".env")
|
28 |
+
openai.api_key = os.environ.get("OPENAI_API_KEY")
|
29 |
+
# print("OPENAI_API_KEY: ", openai.api_key)
|
30 |
+
|
31 |
+
print("""## 普通にChatGPTに天気を聞いてみる""")
|
32 |
+
|
33 |
+
def chat_gpt_without_functions(text):
|
34 |
+
response = openai.ChatCompletion.create(
|
35 |
+
model="gpt-3.5-turbo-0613",
|
36 |
+
messages=[
|
37 |
+
{"role": "user", "content": text},
|
38 |
+
]
|
39 |
+
)
|
40 |
+
|
41 |
+
content = response["choices"][0]["message"]["content"]
|
42 |
+
print(content)
|
43 |
+
|
44 |
+
return content
|
45 |
+
|
46 |
+
print("""# 挨拶は普通に返ってくるが...""")
|
47 |
+
chat_gpt_without_functions("こんにちは")
|
48 |
+
|
49 |
+
print("""# 天気を聞いても返してくれない""")
|
50 |
+
chat_gpt_without_functions("東京の天気を教えて")
|
51 |
+
|
52 |
+
print("""## 今回利用する天気を返す関数""")
|
53 |
+
|
54 |
+
print("""# locationに応じて固定値で天気を返すだけの簡単な関数""")
|
55 |
+
def weather_function(location):
|
56 |
+
match location:
|
57 |
+
case "東京" | "Tokyo":
|
58 |
+
weather = "晴れ"
|
59 |
+
case "大阪" | "Osaka":
|
60 |
+
weather = "曇り"
|
61 |
+
case "北海道" | "Hokkaido":
|
62 |
+
weather = "雪"
|
63 |
+
case _ :
|
64 |
+
weather = "不明"
|
65 |
+
|
66 |
+
weather_answer = [
|
67 |
+
{"天気": weather}
|
68 |
+
]
|
69 |
+
|
70 |
+
return json.dumps(weather_answer)
|
71 |
+
|
72 |
+
print("""# 実際に Function callingを動かしてみる""")
|
73 |
+
|
74 |
+
def chat_gpt_with_function(text):
|
75 |
+
# AIが呼び出せる関数の定義
|
76 |
+
functions = [
|
77 |
+
# 何をする関数かについて記述
|
78 |
+
{
|
79 |
+
"name": "weather",
|
80 |
+
"description": "天気を調べる",
|
81 |
+
"parameters": {
|
82 |
+
"type": "object",
|
83 |
+
"properties": {
|
84 |
+
# location引数についての情報を記述
|
85 |
+
"location": {
|
86 |
+
"type": "string",
|
87 |
+
"description": "天気を知りたい場所を入力。例: 東京",
|
88 |
+
},
|
89 |
+
},
|
90 |
+
"required": ["location"],
|
91 |
+
},
|
92 |
+
}
|
93 |
+
]
|
94 |
+
|
95 |
+
# ユーザーの入力から、Functions Callingが必要かどうか判断する
|
96 |
+
response = openai.ChatCompletion.create(
|
97 |
+
model="gpt-3.5-turbo-0613",
|
98 |
+
messages=[
|
99 |
+
{"role": "user", "content": text},
|
100 |
+
],
|
101 |
+
functions=functions,
|
102 |
+
function_call="auto",
|
103 |
+
)
|
104 |
+
|
105 |
+
# Function Callingが必要なければ、そのままAIの回答になる
|
106 |
+
message = response["choices"][0]["message"]
|
107 |
+
|
108 |
+
# Functions Callingが必要な場合は、messageに関数名と引数を格納されている
|
109 |
+
if message.get("function_call"):
|
110 |
+
|
111 |
+
|
112 |
+
print("------function_callの中身------")
|
113 |
+
print(message["function_call"])
|
114 |
+
print("--------------------------------------")
|
115 |
+
|
116 |
+
# messageから実行する関数と引数を取得
|
117 |
+
function_name = message["function_call"]["name"]
|
118 |
+
arguments = json.loads(message["function_call"]["arguments"])
|
119 |
+
|
120 |
+
# 関数を実行
|
121 |
+
if function_name == "weather":
|
122 |
+
function_response = weather_function(
|
123 |
+
location=arguments.get("location"),
|
124 |
+
)
|
125 |
+
|
126 |
+
# 関数の実行結果を元にAIの回答を生成
|
127 |
+
second_response = openai.ChatCompletion.create(
|
128 |
+
model="gpt-3.5-turbo-0613",
|
129 |
+
messages=[
|
130 |
+
{"role": "user", "content": text},
|
131 |
+
message,
|
132 |
+
{
|
133 |
+
"role": "function",
|
134 |
+
"name": function_name,
|
135 |
+
"content": function_response,
|
136 |
+
},
|
137 |
+
],
|
138 |
+
)
|
139 |
+
|
140 |
+
content = "AIの回答: " + second_response.choices[0]["message"]["content"]
|
141 |
+
else:
|
142 |
+
content = "AIの回答: " + message["content"]
|
143 |
+
|
144 |
+
print(content)
|
145 |
+
return content
|
146 |
+
|
147 |
+
print("""# 挨拶をした場合は、Functionを呼び出す必要がないと判断される""")
|
148 |
+
chat_gpt_with_function("こんにちは")
|
149 |
+
|
150 |
+
print("""# 天気を聞いた場合、Functionを呼び出す必要があると判断され、関数名と引数の情報が「function_call」に格納されている""")
|
151 |
+
chat_gpt_with_function("東京の天気を教えて")
|
152 |
+
|
153 |
+
print("""## LangChain の Agent の場合""")
|
154 |
+
|
155 |
+
from langchain.llms import OpenAI
|
156 |
+
from langchain.agents import initialize_agent, Tool
|
157 |
+
from langchain.agents.mrkl import prompt
|
158 |
+
|
159 |
+
def lang_chain_agent(text):
|
160 |
+
llm = OpenAI(model_name='gpt-3.5-turbo-0613')
|
161 |
+
# toolsに利用したいToolを格納する。LangChainで用意されたToolを利用することも出来る。
|
162 |
+
# 代表的なTool一覧:https://book.st-hakky.com/docs/agents-of-langchain/
|
163 |
+
tools = [
|
164 |
+
Tool(
|
165 |
+
name = "Weather",
|
166 |
+
func=weather_function,
|
167 |
+
description="天気を知りたい場所を入力。例: 東京",
|
168 |
+
)
|
169 |
+
]
|
170 |
+
|
171 |
+
# エージェントの準備
|
172 |
+
agent = initialize_agent(
|
173 |
+
tools,
|
174 |
+
llm,
|
175 |
+
agent="zero-shot-react-description",
|
176 |
+
agent_kwargs=dict(suffix='Answer should be in Japanese.' + prompt.SUFFIX),
|
177 |
+
verbose=True,
|
178 |
+
return_intermediate_steps=True)
|
179 |
+
|
180 |
+
response = agent({"input": text})
|
181 |
+
|
182 |
+
return response
|
183 |
+
|
184 |
+
print("""
|
185 |
+
# 東京の天気について質問すると、toolsで用意した「Weather」が利用され、その結果を元にAIの回答が生成されていることが分かる
|
186 |
+
# 動作が安定しない可能性があるため、失敗する場合は何度か実行してみて下さい
|
187 |
+
lang_chain_agent("東京の天気を教えて")
|
188 |
+
""")
|
189 |
+
|
190 |
+
print("""## LangChain で Function Calling を利用してみる""")
|
191 |
+
|
192 |
+
from langchain.schema import (
|
193 |
+
AIMessage,
|
194 |
+
HumanMessage,
|
195 |
+
FunctionMessage
|
196 |
+
)
|
197 |
+
from langchain.chat_models import ChatOpenAI
|
198 |
+
|
199 |
+
def lang_chain_with_function_calling(text):
|
200 |
+
# AIが利用する関数の定義
|
201 |
+
functions = [
|
202 |
+
# 何をする関数かについて記述
|
203 |
+
{
|
204 |
+
"name": "weather",
|
205 |
+
"description": "天気を調べる",
|
206 |
+
"parameters": {
|
207 |
+
"type": "object",
|
208 |
+
"properties": {
|
209 |
+
# location引数についての情報を記述
|
210 |
+
"location": {
|
211 |
+
"type": "string",
|
212 |
+
"description": "天気を知りたい場所を入力。例: 東京",
|
213 |
+
},
|
214 |
+
},
|
215 |
+
"required": ["location"],
|
216 |
+
},
|
217 |
+
}
|
218 |
+
]
|
219 |
+
|
220 |
+
# ユーザーの入力をmessagesに格納
|
221 |
+
messages=[HumanMessage(content=text)]
|
222 |
+
|
223 |
+
llm=ChatOpenAI(model_name='gpt-3.5-turbo-0613')
|
224 |
+
|
225 |
+
# ユーザーの入力内容から、Functions Callingが必要かどうか判断する
|
226 |
+
# Function Callingが必要なければ、こちらの結果がAIの回答になる
|
227 |
+
message = llm.predict_messages(
|
228 |
+
messages, functions=functions
|
229 |
+
)
|
230 |
+
|
231 |
+
print("==================")
|
232 |
+
print(message)
|
233 |
+
print("==================")
|
234 |
+
|
235 |
+
# Functions Callingが必要な場合は、additional_kwargsに関数名と引数を格納されている
|
236 |
+
if message.additional_kwargs:
|
237 |
+
|
238 |
+
# messageから実行する関数と引数を取得
|
239 |
+
function_name = message.additional_kwargs["function_call"]["name"]
|
240 |
+
arguments = json.loads(message.additional_kwargs["function_call"]["arguments"])
|
241 |
+
|
242 |
+
# 関数を実行
|
243 |
+
function_response = weather_function(
|
244 |
+
location=arguments.get("location"),
|
245 |
+
)
|
246 |
+
|
247 |
+
# 実行結果をFunctionMessageとしてmessagesに追加
|
248 |
+
function_message = FunctionMessage(name=function_name, content=function_response)
|
249 |
+
messages.append(function_message)
|
250 |
+
|
251 |
+
# FuncitonMessageを元に、AIの回答を取得
|
252 |
+
second_response = llm.predict_messages(
|
253 |
+
messages=messages, functions=functions
|
254 |
+
)
|
255 |
+
content = "AIの回答: " + second_response.content
|
256 |
+
else:
|
257 |
+
content = "AIの回答: " + message.content
|
258 |
+
|
259 |
+
print(content)
|
260 |
+
return content
|
261 |
+
|
262 |
+
print("""# 挨拶の場合は、contentにAIのレスポンスが格納されており、Functionの情報は含まれていない""")
|
263 |
+
lang_chain_with_function_calling("こんにちは")
|
264 |
+
|
265 |
+
print("""# 天気を聞いた場合、contentにAIのレスポンスは含まれず、additional_kwgargsに呼び出すFunctionの情報が格納されている""")
|
266 |
+
lang_chain_with_function_calling("東京の天気を教えて")
|
267 |
+
|
268 |
+
print("""# Agent にも対応""")
|
269 |
+
|
270 |
+
from langchain.agents import AgentType
|
271 |
+
|
272 |
+
def lang_chain_agent_with_function_calling(text):
|
273 |
+
llm = ChatOpenAI(model_name='gpt-3.5-turbo-0613')
|
274 |
+
# カスタムツールの登録は従来のAgentと同様
|
275 |
+
tools = [
|
276 |
+
Tool(
|
277 |
+
name = "Weather",
|
278 |
+
func=weather_function,
|
279 |
+
description="天気を知りたい場所を入力。例: 東京"
|
280 |
+
)
|
281 |
+
]
|
282 |
+
|
283 |
+
# エージェントの準備
|
284 |
+
agent = initialize_agent(
|
285 |
+
tools,
|
286 |
+
llm,
|
287 |
+
agent=AgentType.OPENAI_FUNCTIONS, # ここで、AgentType.OPENAI_FUNCTIONSを指定する
|
288 |
+
verbose=True,
|
289 |
+
return_intermediate_steps=True)
|
290 |
+
|
291 |
+
response = agent({"input": text})
|
292 |
+
print(response)
|
293 |
+
return response
|
294 |
+
|
295 |
+
print("""# 挨拶の場合はFunctionが利用されていないことが実行結果(intermediate_steps)から分かる""")
|
296 |
+
lang_chain_agent_with_function_calling("こんにちは")
|
297 |
+
|
298 |
+
print("""# 天気を聞いた場合、intermediate_stepsに��AIMessageとしてFunctionが呼び出されていることが分かる""")
|
299 |
+
lang_chain_agent_with_function_calling("今日の東京の天気を教えて")
|
requirements.txt
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
openai
|
2 |
+
langchain
|
3 |
+
python-dotenv
|
4 |
+
gradio
|