Closed9
langchainでfunction calling
langchain==0.0.310
サンプルプログラム
from langchain.chat_models import ChatOpenAI
from langchain.schema import HumanMessage
from langchain.tools import MoveFileTool, format_tool_to_openai_function
from dotenv import load_dotenv
load_dotenv()
model = ChatOpenAI(model="gpt-3.5-turbo-0613")
tools = [MoveFileTool()]
functions = [format_tool_to_openai_function(t) for t in tools]
message = model.predict_messages(
[HumanMessage(content="move file foo to bar")], functions=functions
)
print(message)
実行結果
content='' additional_kwargs={'function_call': {'name': 'move_file', 'arguments': '{\n "source_path": "foo",\n "destination_path": "bar"\n}'}}
Langsmithでの表示
積み残し
- カスタムツールの作成方法
- predict_messagesのfunctionsに渡せる型の調査
- メモリの追加方法調査
これを読む
より生のfunction callingに近いやり方
# https://python.langchain.com/docs/modules/chains/how_to/openai_functions
from typing import Optional
from langchain.chains.openai_functions import (
create_structured_output_chain,
)
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from dotenv import load_dotenv
from langchain.pydantic_v1 import BaseModel, Field
load_dotenv()
class Person(BaseModel):
name: str = Field(..., description="The name of the person")
age: int = Field(..., description="The age of the person")
fav_food: Optional[str] = Field(None, description="The favorite food of the person")
llm = ChatOpenAI(model="gpt-4", temperature=0)
prompt = ChatPromptTemplate.from_messages(
[
(
"human",
"Use the given format to extract information from the following input: {input}",
),
("human", "Tip: Make sure to answer in the correct format"),
]
)
chain = create_structured_output_chain(Person, llm, prompt, verbose=True)
result: Person = chain.run("Sally is 13")
print(result)
from langchain.chains.openai_functions import (
create_structured_output_chain,
)
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.pydantic_v1 import BaseModel, Field
from langchain.chains import SimpleSequentialChain
from typing import List
from dotenv import load_dotenv
load_dotenv()
llm = ChatOpenAI(model="gpt-4", temperature=1.0)
class IngredientList(BaseModel):
ingredients: List[str] = Field(..., description="食材のリスト")
# 創作料理のクラス定義。料理名と説明文を持つ
class CreativeDish(BaseModel):
name: str = Field(..., description="料理名")
description: str = Field(..., description="料理の説明文")
suggest_ingedients_prompt = ChatPromptTemplate.from_messages(
[
(
"human",
"{input}に適した食材を5つ提案してください",
),
]
)
suggest_creative_dish_prompt = ChatPromptTemplate.from_messages(
[
(
"human",
"以下を食材として利用した創作料理を提案してください: {input}",
),
]
)
# 食材の提案チェーン
suggest_ingredients_chain = create_structured_output_chain(
IngredientList, llm, suggest_ingedients_prompt, verbose=True
)
# 創作料理の提案チェーン
suggest_creative_dish_chain = create_structured_output_chain(
CreativeDish, llm, suggest_creative_dish_prompt, verbose=True
)
overall_chain = SimpleSequentialChain(
chains=[suggest_ingredients_chain, suggest_creative_dish_chain], verbose=True
)
dish = overall_chain.run("闇鍋")
# 結果の表示
print(dish)
> Entering new SimpleSequentialChain chain...
> Entering new LLMChain chain...
Prompt after formatting:
Human: 闇鍋に適した食材を5つ提案してください
> Finished chain.
ingredients=['豚肉', 'ネギ', 'キムチ', '豆腐', 'エノキ']
Prompt after formatting:
Human: 以下を食材として利用した創作料理を提案してください: ingredients=['豚肉', 'ネギ', 'キムチ', '豆腐', 'エノキ']
> Finished chain.
name='豚肉とキムチのホットポット' description='テーブル上で温まりながら楽しむ、豚肉とキムチのホットポットで温まりましょう。まずは豚肉を炒めてから、ネギ、キムチ、豆腐、エノ キを加えて煮込みます。豚肉の旨味とキムチの辛さが絶妙に絡み合い、また豆腐とエノキはその旨味を吸い上げます。ご飯と一緒に食べても、そのままスープとして楽しんでも美味しい一品です。'
> Finished chain.
name='豚肉とキムチのホットポット' description='テーブル上で温まりながら楽しむ、豚肉とキムチのホットポットで温まりましょう。まずは豚肉を炒めてから、ネギ、キムチ、豆腐、エノ キを加えて煮込みます。豚肉の旨味とキムチの辛さが絶妙に絡み合い、また豆腐とエノキはその旨味を吸い上げます。ご飯と一緒に食べても、そのままスープとして楽しんでも美味しい一品です。'
batchで並列で色々やれるの便利
from langchain.chains.openai_functions import (
create_structured_output_chain,
)
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.pydantic_v1 import BaseModel, Field
from typing import List
from dotenv import load_dotenv
import random
load_dotenv()
llm = ChatOpenAI(model="gpt-4", temperature=1.0)
class IngredientList(BaseModel):
ingredients: List[str] = Field(..., description="食材のリスト")
# 創作料理のクラス定義。料理名と説明文を持つ
class CreativeDish(BaseModel):
name: str = Field(..., description="料理名")
description: str = Field(..., description="料理の説明文")
suggest_ingedients_prompt = ChatPromptTemplate.from_messages(
[
(
"human",
"創作料理に適した食材を{input}個提案してください",
),
]
)
suggest_creative_dish_prompt = ChatPromptTemplate.from_messages(
[
(
"human",
"以下を食材として利用した創作料理を提案してください: {input}",
),
]
)
# 食材の提案チェーン
suggest_ingredients_chain = create_structured_output_chain(
IngredientList, llm, suggest_ingedients_prompt, verbose=True
)
# 創作料理の提案チェーン
suggest_creative_dish_chain = create_structured_output_chain(
CreativeDish, llm, suggest_creative_dish_prompt, verbose=True
)
num_of_ingredients_for_dish = 3
num_of_dish = 5
ingredients: IngredientList = suggest_ingredients_chain.run("10")
ingredients_list = [
random.sample(ingredients.ingredients, num_of_ingredients_for_dish)
for _ in range(num_of_dish)
]
dishes = suggest_creative_dish_chain.batch(
[{"input": ingredients} for ingredients in ingredients_list]
)
# 結果の表示
for dish in dishes:
print(dish["input"])
print(dish["function"])
トレースをとることを考えると、suggest_ingredients_chainとsuggest_creative_dish_chainもまとめて一つのRuunableにまとめたいなー。
LangChain Expression Language (LCEL)をもうちょっと掘るか。
一つのチェーンにまとめられそう
from langchain.schema.runnable import RunnableLambda, RunnableMap
def length_text(text: str) -> int:
return len(text)
def double_text(text: str) -> str:
return text + text
chain = RunnableLambda(length_text) | RunnableLambda(double_text)
result = chain.invoke("hello")
print(result)
chain1 = RunnableLambda(length_text)
chain2 = RunnableLambda(double_text)
map_chain = RunnableMap({"length": chain1, "double": chain2})
total_chain = RunnableLambda(double_text) | map_chain
result2 = total_chain.invoke("hello")
print(result2)
10
{'length': 10, 'double': 'hellohellohellohello'}
LCEL版はこちら
このスクラップは2023/10/07にクローズされました