Open2

LangChainメモ

cygkichicygkichi

トークン数と課金額の確認

from langchain.callbacks import get_openai_callback
with get_openai_callback() as cb:

    # ここでOpen AIを使用した処理

    print(cb)
	Prompt Tokens: 393449
	Completion Tokens: 132951
Successful Requests: 900
Total Cost (USD): $1.712150999999997
cygkichicygkichi

LangGraphをさわる

概要

LangChain v0.1.0, LCELでエージェントを作ってみようと思ってLangGraphをさわってみた。
本当は、中間ステップを書き出してほしいだけなのだが。
主に以下のgithubの内容をなぞる。

各要素の定義

エージェントを構成する要素を順番に作成する。

  • ツールの定義
  • プロンプトの定義

ツールの定義

githubではTavilyを使用していますがAPI取得が面倒なので、お手軽なWikipedia検索のツールを使用。

from langchain_community.tools import WikipediaQueryRun
from langchain_community.utilities import WikipediaAPIWrapper
api_wrapper = WikipediaAPIWrapper(top_k_results=1, doc_content_chars_max=100)
tool = WikipediaQueryRun(api_wrapper=api_wrapper)
tools = [tool]

プロンプトの定義

  • hub.pull("hwchase17/openai-functions-agent")でいいのだが、中身をある程度理解したいため書き出す。
  • 要はinput(質問文)agent_scratchpadを入力として、4つの会話を準備してくれるっぽい。
"""
以下2行と同じ
from langchain import hub
prompt = hub.pull("hwchase17/openai-functions-agent")
"""
from langchain.prompts import (
    ChatPromptTemplate,
    SystemMessagePromptTemplate,
    MessagesPlaceholder,
    HumanMessagePromptTemplate
)
from typing import List, Union
import langchain_core
prompt = ChatPromptTemplate(
    input_variables=['agent_scratchpad', 'input'],
    input_types={
        'chat_history': List[
            Union[
                langchain_core.messages.ai.AIMessage,
                langchain_core.messages.human.HumanMessage,
                langchain_core.messages.chat.ChatMessage,
                langchain_core.messages.system.SystemMessage,
                langchain_core.messages.function.FunctionMessage,
                langchain_core.messages.tool.ToolMessage
            ]
        ],
        'agent_scratchpad': List[
            Union[
                langchain_core.messages.ai.AIMessage,
                langchain_core.messages.human.HumanMessage,
                langchain_core.messages.chat.ChatMessage,
                langchain_core.messages.system.SystemMessage,
                langchain_core.messages.function.FunctionMessage,
                langchain_core.messages.tool.ToolMessage
            ]
        ]
    },
    messages=[
        SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=[], template='You are a helpful assistant')),
        MessagesPlaceholder(variable_name='chat_history', optional=True),
        HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], template='{input}')),
        MessagesPlaceholder(variable_name='agent_scratchpad')
    ]
)

モデルの定義

v0.1.0よりlangchain_openaiからインポートするのが良いらしい。

from langchain_openai.chat_models import ChatOpenAI
llm = ChatOpenAI(model="gpt-3.5-turbo-1106")

Azure OpenAI Serviceを使用する場合は以下の通り。
function-calling使うんだろうか?

from langchain_openai.chat_models import AzureChatOpenAI
llm = AzureChatOpenAI(
    openai_api_version="2023-07-01-preview",
    azure_deployment="<デプロイ名称>",
)

OpenAI Functions エージェントの定義

普通のエージェントとは、なにか違うのだろうか?とりあえずRunnableクラスになってるらしい。

agent_runnable = create_openai_functions_agent(llm, tools, prompt)

agent_runnable.get_graph().print_ascii()でチェインの構造を見ると、LCELでよく見るグラフ構造が見える。Lambdaの所は、data = RunnableLambda(lambda x: format_to_openai_function_messages(x['intermediate_steps'])))

                        +---------------------------------+             
                        | Parallel<agent_scratchpad>Input |             
                        +---------------------------------+             
                              ***                   ***                 
                          ****                         ****             
                        **                                 **           
+---------------------------------------+               +-------------+ 
| Lambda(lambda x: format_to_openai_... |               | Passthrough | 
+---------------------------------------+              *+-------------+ 
                              ***                   ***                 
                                 ****           ****                    
                                     **       **                        
                        +----------------------------------+            
                        | Parallel<agent_scratchpad>Output |            
                        +----------------------------------+            
                                          *                             
                                          *                             
                                          *                             
                               +--------------------+                   
                               | ChatPromptTemplate |                   
                               +--------------------+                   
                                          *                             
                                          *                             
                                          *                             
                                +-----------------+                     
                                | AzureChatOpenAI |                     
                                +-----------------+                     
                                          *                             
                                          *                             
                                          *                             
                        +----------------------------------+            
                        | OpenAIFunctionsAgentOutputParser |            
                        +----------------------------------+            
                                          *                             
                                          *                             
                                          *                             
                     +----------------------------------------+         
                     | OpenAIFunctionsAgentOutputParserOutput |         
                     +----------------------------------------+         

エージェントの定義

通常のエージェントを定義する。

from langchain_core.runnables import RunnablePassthrough

agent = RunnablePassthrough.assign(
    agent_outcome = agent_runnable
)

ツール実行関数の定義

# ツールを実行する関数を定義する
def execute_tools(data):
    # Get the most recent agent_outcome - this is the key added in the `agent` above
    agent_action = data.pop('agent_outcome')
    # Get the tool to use
    tool_to_use = {t.name: t for t in tools}[agent_action.tool]
    # Call that tool on the input
    observation = tool_to_use.invoke(agent_action.tool_input)
    # We now add in the action and the observation to the `intermediate_steps` list
    # This is the list of all previous actions taken and their output
    data['intermediate_steps'].append((agent_action, observation))
    return data

# Define logic that will be used to determine which conditional edge to go down
def should_continue(data):
    # If the agent outcome is an AgentFinish, then we return `exit` string
    # This will be used when setting up the graph to define the flow
    if isinstance(data['agent_outcome'], AgentFinish):
        return "exit"
    # Otherwise, an AgentAction is returned
    # Here we return `continue` string
    # This will be used when setting up the graph to define the flow
    else:
        return "continue"