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 เราสามารถสร้างลูกศรกระบวนการประมวลผลข้อมูลที่ซับซ้อนโดยรวมตัวแยกผลลัพธ์ที่แตกต่างกันเข้าด้วยกันเพื่อตอบสนองความต้องการต่างๆ ได้อย่างครบครัน