Team Ai
Apppublic

shigel/langchain-function-calling

sourceHugging Faceupdated 3y agoView on Hugging Face
1likes
app.py209 linesDownload Raw Back to root
1# 必要なモジュールをインポート2import gradio as gr3import os4import sys5import json6import csv7import dotenv8import openai9from langchain.chat_models import ChatOpenAI10from langchain.agents import initialize_agent, Tool11from langchain.schema import (12    AIMessage,13    AgentAction,14    HumanMessage,15    FunctionMessage16)17from langchain.chat_models import ChatOpenAI18from langchain.agents import AgentType19 20# .envファイルから環境変数をロード21dotenv.load_dotenv(".env")22 23# OpenAIキーをosモジュールで取得24openai.api_key = os.environ.get("OPENAI_API_KEY")25 26# 民間伝承を取得する関数27def fetch_folklore(location):28    folklore_lookup = {}29    # CSVファイルからデータを読み取り、地点をキー、伝承を値とする辞書を作成30    with open('folklore.csv', 'r') as f:31        reader = csv.DictReader(f)32        folklore_lookup = {row['location']: row['folklore'] for row in reader}33        type_lookup = {row['type']: row['folklore'] for row in reader}34 35    # 指定された地点の伝承などを返す。存在しない場合は不明を返す。36    folklore = folklore_lookup.get((location), f"その地域の伝承は不明です。")37    type = type_lookup.get((location), f"その地域の伝承は不明です。")38    print("type:", type)39    return folklore40 41def serialize_agent_action(obj):42    if isinstance(obj, AgentAction):43        return { "tool": obj.tool, "tool_input": obj.tool_input, "log": obj.log}44    if isinstance(obj, _FunctionsAgentAction):45        return { "tool": obj.tool, "tool_input": obj.tool_input, "log": obj.log, "message_log": obj.message_log}46    if isinstance(obj, AIMessage):47        return { "content": obj.content, "additional_kwargs": obj.additional_kwargs, "example": obj.example}48    raise TypeError(f"Type {type(obj)} not serializable")49 50# LangChainエージェントからレスポンスを取得する関数51def get_response_from_lang_chain_agent(query_text):52    # ChatOpenAIを使用して言語モデルを初期化53    language_model = ChatOpenAI(model_name='gpt-3.5-turbo-0613')54    tools = [55        # 民間伝承を取得するToolを作成56        Tool(57            name="Folklore",58            func=fetch_folklore,59            description="伝承を知りたい施設や地名を入力。例: 箱根",60        )61    ]62    # エージェントを初期化してから応答を取得63    agent = initialize_agent(tools, language_model, agent="zero-shot-react-description",64                             verbose=True, return_intermediate_steps=True)65    response = agent({"input": query_text})66    print(type(response))67    response = json.dumps(response, default=serialize_agent_action, indent=2, ensure_ascii=False)68 69    return response70 71# Function Callingからレスポンスを取得する関数72def get_response_from_function_calling(query_text):73    function_definitions = [74        # 関数の定義を作成75        {76            "name": "fetch_folklore",77            "description": "伝承を調べる",78            "parameters": {79                "type": "object",80                "properties": {81                    "location": {82                        "description": "伝承を知りたい施設や地名。例: 箱根",83                    },84                },85                "required": ["location"],86            },87        }88    ]89    messages = [HumanMessage(content=query_text)]90    language_model = ChatOpenAI(model_name='gpt-4')91    # 言語モデルを使ってメッセージを予測92    message = language_model.predict_messages(93        messages, functions=function_definitions)94 95    if message.additional_kwargs:96        # 関数の名前と引数を取得97        function_name = message.additional_kwargs["function_call"]["name"]98        arguments = message.additional_kwargs["function_call"]["arguments"]99 100        # JSON 文字列を辞書に変換101        arguments = json.loads(arguments)102        location=arguments.get("location")103        # type=arguments.get("type")104 105        # 関数を実行してレスポンスを取得106        function_response = fetch_folklore(location=location)107        # 関数メッセージを作成108        function_message = FunctionMessage(109            name=function_name, content=function_response)110        # 関数のレスポンスをメッセージに追加して予測111        messages.append(function_message)112        second_response = language_model.predict_messages(113            messages=messages, functions=function_definitions)114        content = second_response.content115    else:116        content = message.content117    return content118 119# Function Call Agentからレスポンスを取得する関数120def get_response_from_function_calling_agent(query_text):121    language_model = ChatOpenAI(model_name='gpt-3.5-turbo-0613')122    tools = [123        # 民間伝承情報を提供するツールの追加124        Tool(125            name="Folklore",126            func=fetch_folklore,127            description="伝承を知りたい施設や地名を入力。例: 箱根"128        )129    ]130    # エージェントの初期化とレスポンスの取得131    agent = initialize_agent(tools, language_model, agent=AgentType.OPENAI_FUNCTIONS,132                             verbose=True, return_intermediate_steps=True)133    response = agent({"input": query_text})134    response = json.dumps(response, default=serialize_agent_action, indent=2, ensure_ascii=False)135    return response136 137# メインの実行部分138 139 140def main(query_text, function_name="all"):141 142    response1 = ""143    response2 = ""144    response3 = ""145    146    if function_name == "all" or function_name == "langchain":147        # LangChainエージェントからのレスポンス148        response1 = get_response_from_lang_chain_agent(query_text)149        print(response1)150 151    if function_name == "all" or function_name == "functioncalling":152        # Function Callingからのレスポンス153        response2 = get_response_from_function_calling(query_text)154        print(response2)155 156    if function_name == "all" or function_name == "functioncallingagent":157        # Function Callingエージェントからのレスポンス158        response3 = get_response_from_function_calling_agent(query_text)159        print(response3)160 161    return response1, response2, response3162 163 164# スクリプトが直接実行された場合にmain()を実行165if __name__ == "__main__":166    if len(sys.argv) == 2:167        query_text = sys.argv[1]168        main(query_text=query_text)169    elif len(sys.argv) > 2:170        query_text = sys.argv[1]171        function_name = sys.argv[2]172        main(query_text=query_text, function_name=function_name)173    else:174        import time175 176        # インプット例をクリックした時のコールバック関数177        def click_example(example):178            # クリックされたインプット例をテキストボックスに自動入力179            inputs.value = example180            time.sleep(0.1)  # テキストボックスに文字が表示されるまで待機181            # 自動入力後に実行ボタンをクリックして結果を表示182            execute_button.click()183 184        # gr.Interface()を使ってユーザーインターフェースを作成します185        # gr.Text()はテキスト入力ボックスを作成し、186        # gr.Textbox()は出力テキストを表示するためのテキストボックスを作成します。187        iface = gr.Interface(188            fn=main,189            examples=[190                ["葛飾区の伝承を教えてください。"],191                ["千代田区にはどんな伝承がありますか?"],192                ["江戸川区で有名な伝承?"],193            ],194            inputs=gr.Textbox(195                lines=5, placeholder="質問を入力してください"),196            outputs=[197                gr.Textbox(label="LangChain Agentのレスポンス"),198                gr.Textbox(label="Function Callingのレスポンス"),199                gr.Textbox(label="Function Calling Agentのレスポンス")200            ],201            title="日本各地の伝承AI (東京23区版)",202            description="最新のGPTモデルを使用し、LangChain, Function Calling, Function Calling + LangChain Agentの対話モデルのAIから回答を取得するシステムです。以下のインプット例をクリックすると入力欄に自動入力されます。",203            example_columns=3,204            example_callback=click_example205        )206 207        # インターフェースを起動します208        iface.launch()209