استفاده از مثال‌های مرجع

کیفیت استخراج‌ها معمولاً با ارائه مثال‌های مرجع به LLM قابل بهبود می‌باشد.

نکته: اگرچه این آموزش بر روی استفاده از مثال‌ها با یک ابزار تحت عنوان مدل تماس می‌گیرد، این تکنیک به طور کلی قابل استفاده است و همچنین با تکنیک‌های مبتنی بر JSON و یا خطوط فرمانی نیز کار می‌کند.

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder

prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            "شما یک الگوریتم استخراج حرفه‌ای هستید. "
            "فقط اطلاعات مرتبط را از متن استخراج کنید. "
            "اگر ارزش یک ویژگی را که برای استخراج سوال شده نمی‌دانید، "
            "مقدار نال برای ارزش ویژگی را برگردانید.",
        ),
        MessagesPlaceholder("examples"),  # <-- مثال‌ها!
        ("human", "{text}"),
    ]
)

محتوای قالب را تست کنید:

from langchain_core.messages import (
    HumanMessage,
)

prompt.invoke(
    {"text": "این چندین متن است", "examples": [HumanMessage(content="تست ۱، ۲، ۳")]}
)
ChatPromptValue(messages=[SystemMessage(content="شما یک الگوریتم استخراج حرفه‌ای هستید. فقط اطلاعات مرتبط را از متن استخراج کنید. اگر ارزش یک ویژگی را که برای استخراج سوال شده نمی‌دانید، مقدار نال برای ارزش ویژگی را برگردانید."), HumanMessage(content='تست ۱، ۲، ۳'), 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]

تعریف نمونه‌های مرجع

نمونه‌ها می‌توانند به عنوان یک لیست از جفت ورودی-خروجی تعریف شوند.

هر نمونه شامل متن ورودی نمونه و خروجی مرتبط است که نشان می‌دهد چه چیزی باید از متن استخراج شود.

اطلاعات:

این موضوع یکم عمیق می‌شود، پس اگر متوجه نشدید می‌توانید نادیده بگیرید!

قالب نمونه باید با 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: شامل تأیید به مدل است که مدل به درستی یک ابزار را درخواست کرده است.

    این استفاده شده چون برخی از مدل‌های چت بهینه‌سازی شده‌اند برای عوامل بیشتر به جای موارد استخراجی.
    """
    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 = [
    (
        "اقیانوس بسیار بزرگ و آبی است. بیش از 20،000 فوت عمق دارد. در آن ماهی‌های زیادی وجود دارد.",
        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="اقیانوس وسیع و آبیه. بیش از ۲۰,۰۰۰ پا عمق داره. تعداد زیادی ماهی توش هستن."), 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: The function `with_structured_output` is in beta. It is actively being worked on, so the API may change.
  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": "نام من هریسون است. موهایم سیاه است.",
        "examples": messages,
    }
)
Data(people=[Person(name='Harrison', hair_color='black', height_in_meters=None)])