参照例の使用
LLMに参照例を提供することで、抽出の品質を高めることができます。
ヒント: このチュートリアルでは、モデルを呼び出すツールで例を使用する方法に焦点を当てていますが、このテクニックは一般的に適用可能であり、JSONやプロンプトベースの技術とも使用できます。
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
prompt = ChatPromptTemplate.from_messages(
[
(
"system",
"あなたは抽出アルゴリズムのエキスパートです。"
"テキストから関連する情報のみを抽出してください。"
"抽出する属性の値がわからない場合は、その属性の値にはnullを返してください。",
),
MessagesPlaceholder("examples"), # <-- 例!
("human", "{text}"),
]
)
テンプレートを試してみる:
from langchain_core.messages import (
HumanMessage,
)
prompt.invoke(
{"text": "これはテストテキストです", "examples": [HumanMessage(content="テスト1 2 3")]}
)
ChatPromptValue(messages=[SystemMessage(content="あなたは抽出アルゴリズムのエキスパートです。テキストから関連する情報のみを抽出してください。抽出する属性の値がわからない場合は、その属性の値にはnullを返してください。"), HumanMessage(content='テスト1 2 3'), HumanMessage(content='これはテストテキストです')])
スキーマの定義
クイックスタートから人のスキーマを再利用しましょう。
from typing import List, Optional
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_openai import ChatOpenAI
class Person(BaseModel):
"""人物に関する情報。"""
name: Optional[str] = Field(..., description="人物の名前")
hair_color: Optional[str] = Field(
..., description="わかっている場合は人物の髪の色"
)
height_in_meters: Optional[str] = Field(..., description="メートル単位の身長")
class Data(BaseModel):
"""人物に関する抽出データ。"""
people: List[Person]
参照例の定義
例は、入出力のペアのリストとして定義することができます。
それぞれの例には、例の input
テキストと、テキストから抽出されるべき内容を示す output
が含まれます。
情報
これは少し専門的な内容なので、理解できない場合は無視しても構いません!
例のフォーマットは使用されるAPI(例:ツールの呼び出しやJSONモードなど)に一致する必要があります。
ここでは、ツールの呼び出しAPIに期待されるフォーマットに一致するようにフォーマットされた例が示されます。
import uuid
from typing import Dict, List, TypedDict
from langchain_core.messages import (
AIMessage,
BaseMessage,
HumanMessage,
SystemMessage,
ToolMessage,
)
from langchain_core.pydantic_v1 import BaseModel, Field
class Example(TypedDict):
"""テキスト入力と予想されるツール呼び出しで構成される例の表現。
抽出のために、ツールの呼び出しはpydanticモデルのインスタンスとして表されます。
"""
input: str # これは例のテキストです
tool_calls: List[BaseModel] # 抽出されるべきpydanticモデルのインスタンス
def tool_example_to_messages(example: Example) -> List[BaseMessage]:
"""例をLLMに供給できるメッセージのリストに変換します。
このコードは、例をチャットモデルに供給できるメッセージのリストに変換するアダプターです。
例ごとのメッセージリストは以下のものに対応しています:
1) HumanMessage: 抽出すべき内容を含む
2) AIMessage: モデルから抽出された情報を含む
3) ToolMessage: モデルに対して正しくツールが要求されたことを確認する
一部のチャットモデルは抽出ユースケースではなくエージェント向けに過剰最適化されているため、ToolMessageが必要です。
"""
messages: List[BaseMessage] = [HumanMessage(content=example["input"])]
openai_tool_calls = []
for tool_call in example["tool_calls"]:
openai_tool_calls.append(
{
"id": str(uuid.uuid4()),
"type": "function",
"function": {
"name": tool_call.__class__.__name__,
"arguments": tool_call.json(),
},
}
)
messages.append(
AIMessage(content="", additional_kwargs={"tool_calls": openai_tool_calls})
)
tool_outputs = example.get("tool_outputs") or [
"You have correctly called this tool."
] * len(openai_tool_calls)
for output, tool_call in zip(tool_outputs, openai_tool_calls):
messages.append(ToolMessage(content=output, tool_call_id=tool_call["id"]))
return messages
次に、例を定義し、それらをメッセージ形式に変換します。
examples = [
(
"大洋は広大で青いです。深さは2万フィート以上あります。多くの魚がいます。",
Person(name=None, height_in_meters=None, hair_color=None),
),
(
"フィオナはフランスからスペインまで遠く旅行しました。",
Person(name="Fiona", height_in_meters=None, hair_color=None),
),
]
messages = []
for text, tool_call in examples:
messages.extend(
tool_example_to_messages({"input": text, "tool_calls": [tool_call]})
)
プロンプトをテストしてみましょう。
prompt.invoke({"text": "これはテキストです", "examples": messages})
ChatPromptValue(messages=[SystemMessage(content="抽出アルゴリズムの専門家です。テキストから関連情報のみを抽出します。抽出される属性の値がわからない場合は、その属性の値にはnullを返してください。"), HumanMessage(content="海は広大で青いです。深さは2万フィート以上です。たくさんの魚がいます。"), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'c75e57cc-8212-4959-81e9-9477b0b79126', 'type': 'function', 'function': {'name': 'Person', 'arguments': '{"name": null, "hair_color": null, "height_in_meters": null}'}}]}), ToolMessage(content='このツールを正しく呼び出しました。', tool_call_id='c75e57cc-8212-4959-81e9-9477b0b79126'), HumanMessage(content='フィオナはフランスからスペインまで遠く旅行しました。'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': '69da50b5-e427-44be-b396-1e56d821c6b0', 'type': 'function', 'function': {'name': 'Person', 'arguments': '{"name": "Fiona", "hair_color": null, "height_in_meters": null}'}}]}), ToolMessage(content='このツールを正しく呼び出しました。', tool_call_id='69da50b5-e427-44be-b396-1e56d821c6b0'), HumanMessage(content='これはテキストです')])
エクストラクターの作成
ここでは、gpt-4 を使用してエクストラクターを作成します。
llm = ChatOpenAI(
model="gpt-4-0125-preview",
temperature=0,
)
runnable = prompt | llm.with_structured_output(
schema=Data,
method="function_calling",
include_raw=False,
)
/Users/harrisonchase/workplace/langchain/libs/core/langchain_core/_api/beta_decorator.py:86: LangChainBetaWarning: 関数 `with_structured_output` はベータ版です。積極的に取り組んでいるため、API が変更される可能性があります。
warn_beta(
例なし
gpt-4 を使用しているにもかかわらず、非常に簡単な テストケースでも失敗していることに注意してください!
for _ in range(5):
text = "太陽系は広大ですが、地球は月がたった1つしかありません。"
print(runnable.invoke({"text": text, "examples": []}))
people=[]
people=[Person(name='earth', hair_color=None, height_in_meters=None)]
people=[Person(name='earth', hair_color=None, height_in_meters=None)]
people=[]
people=[]
例を含む
参考例は失敗を修正するのに役立ちます!
for _ in range(5):
text = "太陽系は広大ですが、地球は月がたった1つしかありません。"
print(runnable.invoke({"text": text, "examples": messages}))
people=[]
people=[]
people=[]
people=[]
people=[]
runnable.invoke(
{
"text": "私の名前はHarrisonです。私の髪は黒です。",
"examples": messages,
}
)
Data(people=[Person(name='Harrison', hair_color='black', height_in_meters=None)])