Output Parser

โมเดลภาษา LLM นำเสนอเนื้อหาในรูปแบบข้อความ แต่เมื่อพัฒนาแอปพลิเคชัน AI เราต้องการรับเนื้อหาที่จัดรูปแบบไว้ เช่น การแปลงผลลัพธ์เป็นออบเจ็กต์เป้าหมาย อาร์เรย์ ฯลฯ เพื่อความสะดวกในการประมวลผลโปรแกรม นี่จำเป็นต้องใช้งานตัวแยกผลลัพธ์ที่ถูกให้ไว้โดย LangChain เพื่อจัดรูปแบบเนื้อหาที่โมเดลส่งกลับมา

ฟังก์ชันของตัวแยกผลลัพธ์คือจัดรูปแบบผลลัพธ์ที่โมเดลภาษาส่งกลับมา ตัวแยกผลลัพธ์ต้องปฏิบัติตามวิธีการสองวิธีที่จำเป็น:

  • "get_format_instructions": คืนค่าสตริงที่บรรจุคำสั่งสำหรับรูปแบบที่โมเดลภาษาควรคืนค่า
  • "parse": แยกวิเคราะห์เนื้อหาที่โมเดลส่งกลับมาเป็นรูปแบบเป้าหมาย

ตอนนี้เรามาดูตัวแยกผลลัพธ์ที่มีอยู่ใน LangChain

ตัวแยกผลแบบ Pydantic

ด้านล่างนี้คือตัวแยกผลหลัก PydanticOutputParser ที่ถูกห่อหุ้มโดย LangChain ตัวแยกนี้อาศัยออนไลน์ไลบรารีของ Python pydantic และใช้สำหรับแปลงผลลัพธ์ที่ได้จากโมเดลเป็นออบเจกต์ของ Python

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="question to set up a joke")
    punchline: str = Field(description="answer to resolve the joke")

    @validator("setup")
    def question_ends_with_question_mark(cls, field):
        if field[-1] != "?":
            raise ValueError("Badly formed question!")
        return field

parser = PydanticOutputParser(pydantic_object=Joke)

prompt = PromptTemplate(
    template="Answer the user query.\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": "Tell me a joke."})
parser.invoke(output)

ตัวอย่างผลลัพธ์ที่คืนมา:

Joke(setup='Why did the chicken cross the road?', punchline='To get to the other side!')

อินเทอร์เฟซ LCEL

อินเทอร์เฟซ Runnable

ตัวแยกผลลัพธ์นำมาสมบูรณ์อินเทอร์เฟซ Runnable ซึ่งเป็นหนึ่งในตัวสร้างพื้นฐานของภาษาแสดงของ LangChain (LCEL) มันสนับสนุนวิธีการเรียกใช้งานเช่น invoke, ainvoke, stream, astream, batch, abatch, astream_log เป็นต้น

การประยุกต์ใช้ตัวแยกผลลัพธ์ใน LCEL

ตัวแยกผลลัพธ์สามารถรับข้อมูลสตริงหรือ BaseMessage เป็นข้อมูลนำเข้าและคืนข้อมูลที่มีโครงสร้างออกมาในรูปแบบใดก็ได้ เราสามารถสร้างและเรียกใช้ตามลำดับตัวแยกผลลัพธ์โดยการเพิ่มตัวแยกผลลัพธ์เข้าไปในสายวิ่งที่สามารถเรียกใช้ได้

chain = prompt | model | parser
chain.invoke({"query": "Tell me a joke."})

คืนค่า

Joke(setup='Why did the chicken cross the road?', punchline='To get to the other side!')

บางตัวแยกผลลัพธ์สามารถสตรีมวัตถุแยกผลย่อยได้ เช่น SimpleJsonOutputParser ในขณะที่อีกตัวแยกผลลัพธ์หนึ่งอาจจะไม่สนับสนุนการสตรีม ผลลัพธ์ที่สุดท้ายขึ้นอยู่กับว่าตัวแยกผลลัพธ์สามารถสร้างวัตถุแยกผลย่อยได้หรือไม่

from langchain.output_parsers.json import SimpleJsonOutputParser

json_prompt = PromptTemplate.from_template(
    "Return a JSON object with an `answer` key that answers the following question: {question}"
)
json_parser = SimpleJsonOutputParser()
json_chain = json_prompt | model | json_parser
list(json_chain.stream({"question": "Who invented the microscope?"}))
[{},
 {'answer': ''},
 {'answer': 'Ant'},
 {'answer': 'Anton'},
 {'answer': 'Antonie'},
 {'answer': 'Antonie van'},
 {'answer': 'Antonie van Lee'},
 {'answer': 'Antonie van Leeu'},
 {'answer': 'Antonie van Leeuwen'},
 {'answer': 'Antonie van Leeuwenho'},
 {'answer': 'Antonie van Leeuwenhoek'}]

ใน LCEL เราสามารถสร้างลูกศรกระบวนการประมวลผลข้อมูลที่ซับซ้อนโดยรวมตัวแยกผลลัพธ์ที่แตกต่างกันเข้าด้วยกันเพื่อตอบสนองความต้องการต่างๆ ได้อย่างครบครัน