تجزیه‌کننده خروجی

مدل زبانی LLM محتوا را به صورت متن ارائه می‌دهد، اما هنگام توسعه برنامه‌های هوش مصنوعی، ما می‌خواهیم محتوای قالب‌بندی شده مانند تبدیل نتایج به اشیاء مقصد، آرایه‌ها و غیره را دریافت کنیم تا پردازش برنامه را آسان‌تر کند. برای این کار، نیاز به تجزیه‌کننده خروجی ارائه شده توسط LangChain داریم تا محتوای بازگشتی مدل را قالب‌بندی کند.

تابع تجزیه‌کننده خروجی برای قالب‌بندی نتایج بازگشتی توسط مدل زبانی است. یک تجزیه‌کننده خروجی باید دو متد ضروری زیر را پیاده‌سازی کند:

  • "get_format_instructions": یک رشته شامل دستورالعمل برای اینکه مدل زبانی باید به چه شکلی بازگردانی را برگرداند.
  • "parse": محتوای بازگشتی از مدل را به قالب مقصد تجزیه می‌کند.

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

تجزیه‌کننده Pydantic

در زیر، تجزیه‌کننده خروجی هسته ای PydanticOutputParser که توسط LangChain بسته‌بندی شده است آمده است. این تجزیه‌کننده بر اساس کتابخانه پایتون pydantic استفاده می‌شود و برای تبدیل نتیجه خروجی مدل به اشیاء پایتون استفاده می‌شود.

from langchain.output_parsers import PydanticOutputParser
from langchain.prompts import PromptTemplate
from langchain_core.pydantic_v1 import BaseModel, Field, validator
from langchain_openai import OpenAI

model = OpenAI(model_name="gpt-3.5-turbo-instruct", temperature=0.0)

class Joke(BaseModel):
    setup: str = Field(description="سوال برای تعریف یک شوخی")
    punchline: str = Field(description="پاسخ برای حل شوخی")

    @validator("setup")
    def question_ends_with_question_mark(cls, field):
        if field[-1] != "؟":
            raise ValueError("سوال بد شکل!")
        return field

parser = PydanticOutputParser(pydantic_object=Joke)

prompt = PromptTemplate(
    template="پاسخی به درخواست کاربر دهید.\n{format_instructions}\n{query}\n",
    input_variables=["query"],
    partial_variables={"format_instructions": parser.get_format_instructions()},
)

prompt_and_model = prompt | model
output = prompt_and_model.invoke({"query": "یک شوخی بهم بگو."})
parser.invoke(output)

نمونه نتیجه بازگشتی:

Joke(setup='چرا مرغ خیابان را عبور کرد؟', punchline='تا به سوی دیگر برود!')

رابط LCEL

رابط Runnable

تجزیه‌کننده خروجی رابط Runnable را پیاده‌سازی می‌کند که یکی از انشعاب‌های اصلی زبان بیان LangChain (LCEL) است. این رابط از متدهای فراخوانی مانند invoke، ainvoke، stream، astream، batch، abatch، astream_log و غیره پشتیبانی می‌کند.

کاربرد تجزیه‌کننده‌های خروجی در LCEL

تجزیه‌کننده خروجی می‌تواند یک رشته یا BaseMessage را به عنوان ورودی قبول کرده و داده‌های ساختار یافته از هر نوع را برمی‌گرداند. ما می‌توانیم یک زنجیره تجزیه‌کننده را با اضافه کردن تجزیه‌کننده به یک دنباله Runnable بسازیم و آن را فراخوانی کنیم.

chain = prompt | model | parser
chain.invoke({"query": "یک شوخی بهم بگو."})

بازگشت

Joke(setup='چرا مرغ خیابان را عبور کرد؟', punchline='تا به سوی دیگر برود!')

برخی از تجزیه‌کننده‌ها می‌توانند اشیاء تجزیه‌کننده جزئی را ایجاد کنند مانند SimpleJsonOutputParser، در حالی که دیگران از پشتیبانی از استریم صرف نظر می‌کنند. خروجی نهایی به وابستگی از این است که آیا تجزیه‌کننده می‌تواند اشیاء تجزیه کننده جزئی را ایجاد کند یا خیر.

from langchain.output_parsers.json import SimpleJsonOutputParser

json_prompt = PromptTemplate.from_template(
    "یک شی JSON با کلید 'پاسخ' که سوال زیر را جواب می‌دهد، برگردانید: {question}"
)
json_parser = SimpleJsonOutputParser()
json_chain = json_prompt | model | json_parser
list(json_chain.stream({"question": "چه کسی میکروسکوپ را اختراع کرد؟"}))
[{},
 {'answer': ''},
 {'answer': 'مورچه'},
 {'answer': 'آنت'},
 {'answer': 'آنتون'},
 {'answer': 'آنتونی'},
 {'answer': 'آنتونی ون'},
 {'answer': 'آنتونی ون لی'},
 {'answer': 'آنتونی ون لیو'},
 {'answer': 'آنتونی ون لیون'},
 {'answer': 'آنتونی ون لیونه'},
 {'answer': 'آنتونی ون لیونهوک'}]

در LCEL، ما می‌توانیم با ترکیب تجزیه‌کننده‌های مختلف، جریان‌های پردازش داده پیچیده را بسازیم تا نیازهای مختلف را برآورده کنیم.