การสร้างสายงานด้วย LCEL
ใช้ตัวดำเนินการไปป์เพื่อเชื่อมแม่แบบพรอมต์ LLM และตัวแยกวิเคราะห์ผลลัพธ์เป็นลำดับ Runnable เรียกใช้ทั้งแบบพร้อมกันและแบบไม่พร้อมกัน และตรวจสอบผลลัพธ์ระหว่างทาง
การสร้างสายงานด้วย LCEL เป็นบทเรียน AI Engineering Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Engineering Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Engineering Academy มีบทเรียนทั้งหมด 4 บทเรียน
LCEL คืออะไร
LCEL (LangChain Expression Language) คือวิธีประกาศสำหรับประกอบองค์ประกอบของ LangChain ให้เป็นสายงาน แทนที่จะสร้างอินสแตนซ์ของคลาสสายงานที่มีรายละเอียดมาก คุณจะเชื่อมต่อ Runnable ด้วยตัวดำเนินการ | สายงาน LCEL รองรับการสตรีม การทำงานแบบอะซิงโครนัส การประมวลผลเป็นชุด และทางเลือกสำรองโดยอัตโนมัติ คุณจะได้รับความสามารถทั้งหมดนี้เพียงใช้ไวยากรณ์ไปป์
สร้างสายงาน LCEL แรกของคุณ
สายงาน LCEL ที่ง่ายที่สุดประกอบด้วย PromptTemplate, ChatModel และ OutputParser แต่ละองค์ประกอบเป็น Runnable และตัวดำเนินการไปป์จะเชื่อมองค์ประกอบเหล่านั้นเข้าด้วยกัน เมื่อคุณเรียกใช้ chain.invoke() อินพุตจะไหลผ่านแต่ละขั้นตามลำดับ โดยผลลัพธ์ของแต่ละขั้นจะกลายเป็นอินพุตของขั้นถัดไป
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
prompt = ChatPromptTemplate.from_template(
'Write a product description for: {product}'
)
model = ChatOpenAI(model='gpt-4o-mini', temperature=0.7)
parser = StrOutputParser()
chain = prompt | model | parser
result = chain.invoke({'product': 'noise-cancelling headphones'})
print(result)ตรวจสอบการทำงานภายในของสายงาน
สายงาน LCEL เปิดเผยโครงสร้างภายในอย่างโปร่งใส chain.steps แสดงรายการองค์ประกอบตามลำดับ คุณสามารถเรียกใช้ chain.input_schema และ chain.output_schema เพื่อตรวจสอบชนิดข้อมูลที่ไหลเข้าและออกได้ นอกจากนี้ การเรียก invoke() ยังรับพารามิเตอร์ config สำหรับส่งชื่อการทำงาน แท็ก และการเรียกกลับไปยังการเรียกใช้ครั้งเดียว โดยไม่ต้องเปลี่ยนคำจำกัดความของสายงาน
# Inspect chain structure
print('Steps:', chain.steps)
print('Input schema:', chain.input_schema.schema())
print('Output schema:', chain.output_schema.schema())
# Named run for observability
result = chain.invoke(
{'product': 'coffee maker'},
config={'run_name': 'product-desc-run', 'tags': ['production']}
)การเรียกใช้แบบพร้อมกันและแบบอะซิงโครนัส
สายงาน LCEL มีเมธอดทุกชนิดทั้งเวอร์ชันแบบทำงานพร้อมกันและแบบอะซิงโครนัส invoke() จะหยุดเธรดที่เรียกใช้ไว้ ainvoke() เป็นเวอร์ชันอะซิงโครนัสที่เทียบเท่ากัน และควรใช้ในตัวจัดการ FastAPI รวมถึงบริบทอะซิงโครนัสอื่น ๆ เพื่อไม่ให้ลูปเหตุการณ์ถูกบล็อก เวอร์ชันอะซิงโครนัสมีความหมายการทำงานเหมือนกัน ความแตกต่างของอินเทอร์เฟซมีเพียงการใช้ await
import asyncio
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
chain = ChatPromptTemplate.from_template('Explain {topic}') | ChatOpenAI() | StrOutputParser()
async def main():
# Async invocation
result = await chain.ainvoke({'topic': 'quantum computing'})
print(result)
asyncio.run(main())สตรีมโทเค็นผ่านสายงาน
สายงาน LCEL ส่งต่อการสตรีมไปตลอดทั้งสาย เรียกใช้ chain.stream() เพื่อรับโทเค็นทันทีที่โมเดลสร้างขึ้น StrOutputParser รองรับการสตรีมและส่งต่อส่วนย่อยของสตริงแต่ละส่วน แทนที่จะรอการตอบกลับทั้งหมด วิธีนี้ช่วยให้ผู้ใช้ได้รับผลตอบกลับทันที แทนที่จะต้องรอเป็นเวลานานแล้วจึงได้รับคำตอบทั้งหมด
chain = (
ChatPromptTemplate.from_template('Tell me about {topic} in detail.')
| ChatOpenAI(model='gpt-4o-mini')
| StrOutputParser()
)
# Print each token as it arrives
for chunk in chain.stream({'topic': 'neural networks'}):
print(chunk, end='', flush=True)
print() # newline at end
# Async streaming
async def stream_async():
async for chunk in chain.astream({'topic': 'transformers'}):
print(chunk, end='', flush=True)ประมวลผลอินพุตหลายรายการเป็นชุด
chain.batch() รับรายการพจนานุกรมอินพุตและประมวลผลด้วยการทำงานพร้อมกันที่กำหนดค่าได้ ภายใน LangChain จะเรียกใช้การทำงานในเธรดแบบขนาน ทำให้การประมวลผลเป็นชุดเร็วกว่าเรียก invoke() ในลูปมาก พารามิเตอร์ max_concurrency จำกัดจำนวนการเรียก API แบบขนาน เพื่อให้อยู่ภายในขีดจำกัดอัตราการเรียก ผลลัพธ์จะกลับมาในลำดับเดียวกับอินพุต
products = [
{'product': 'laptop'},
{'product': 'tablet'},
{'product': 'smartwatch'},
{'product': 'earbuds'},
]
# Process all 4 concurrently
results = chain.batch(products, config={'max_concurrency': 4})
for product, description in zip(products, results):
print(f'{product["product"]}: {description[:80]}...')RunnablePassthrough และ RunnableLambda
RunnablePassthrough ส่งต่ออินพุตโดยไม่เปลี่ยนแปลง เหมาะสำหรับส่งบริบทเดิมไปพร้อมกับข้อมูลที่ผ่านการแปลงแล้ว ส่วน RunnableLambda ห่อหุ้มฟังก์ชัน Python ใด ๆ ให้เป็น Runnable ทำให้คุณแทรกตรรกะใด ๆ ลงในสายงาน LCEL ได้ ทั้งสองอย่างช่วยให้จัดการข้อมูลระหว่างขั้นของสายงานได้โดยไม่ต้องเขียนคลาส Runnable แบบกำหนดเองทั้งหมด
from langchain_core.runnables import RunnablePassthrough, RunnableLambda
def word_count(text: str) -> str:
count = len(text.split())
return f'{text}\n\n[Word count: {count}]'
chain = (
ChatPromptTemplate.from_template('Write about {topic}')
| ChatOpenAI(model='gpt-4o-mini')
| StrOutputParser()
| RunnableLambda(word_count) # Add word count to output
)
result = chain.invoke({'topic': 'climate change'})
print(result)ส่งบริบทเพิ่มเติมด้วย RunnablePassthrough
รูปแบบที่พบบ่อยใน RAG คือการส่งทั้งเอกสารที่ค้นคืนมาและคำถามของผู้ใช้ไปยังพรอมต์สุดท้าย ใช้ RunnablePassthrough.assign() เพื่อเพิ่มฟิลด์ที่คำนวณแล้วลงในพจนานุกรมอินพุต โดยไม่สูญเสียคีย์เดิม วิธีนี้ช่วยเพิ่มข้อมูลให้กับออบเจ็กต์บริบทขณะที่ไหลผ่านสายงาน ทำให้ข้อมูลทั้งหมดพร้อมใช้งานในเทมเพลตพรอมต์
from langchain_core.runnables import RunnablePassthrough
# Fake retriever for illustration
def retrieve_docs(question: str):
return ['Doc 1 content', 'Doc 2 content']
retriever = RunnableLambda(retrieve_docs)
rag_chain = (
RunnablePassthrough.assign(context=retriever) # adds 'context' key
| ChatPromptTemplate.from_template(
'Context: {context}\n\nAnswer: {question}'
)
| ChatOpenAI()
| StrOutputParser()
)
result = rag_chain.invoke({'question': 'What is machine learning?'})เพิ่มทางเลือกสำรองให้สายงาน
สายงาน LCEL รองรับทางเลือกสำรอง ซึ่งเป็นสายงานทางเลือกที่จะลองใช้เมื่อสายงานหลักทำให้เกิดข้อยกเว้น เรียก chain.with_fallbacks([backup_chain]) เพื่อลงทะเบียนสายงานสำรองหนึ่งรายการหรือมากกว่า LangChain จะลองใช้สายงานหลักก่อน ดักจับข้อยกเว้นที่เกิดขึ้น แล้วลองใช้สายงานสำรองแต่ละรายการตามลำดับ นี่คือวิธีมาตรฐานในการรับมือกับการหยุดให้บริการของผู้ให้บริการหรือข้อผิดพลาดของโมเดลอย่างเหมาะสม
from langchain_openai import ChatOpenAI
from langchain_anthropic import ChatAnthropic
primary_chain = (
ChatPromptTemplate.from_template('Answer: {question}')
| ChatOpenAI(model='gpt-4o')
| StrOutputParser()
)
fallback_chain = (
ChatPromptTemplate.from_template('Answer: {question}')
| ChatAnthropic(model='claude-3-haiku-20240307')
| StrOutputParser()
)
robust_chain = primary_chain.with_fallbacks([fallback_chain])
# If OpenAI fails, automatically tries Anthropicแก้ไขข้อบกพร่องด้วย intermediate_steps
การแก้ไขข้อบกพร่องของสายงาน LCEL ทำได้ง่ายขึ้นด้วย config ของ invoke() และตัวเลือก verbose=True นอกจากนี้ คุณยังใช้ .with_config({'verbose': True}) กับสายงานใด ๆ เพื่อบันทึกอินพุตและเอาต์พุตของทุกขั้นได้ สำหรับการแก้ไขข้อบกพร่องแบบมีโครงสร้าง ให้ห่อสายงานด้วย set_verbose(True) ในระดับสากล หรือใช้การติดตามของ LangSmith เพื่อบันทึกค่าระหว่างทางทุกค่าในเครื่องมือสำรวจลำดับการทำงานแบบภาพ
from langchain.globals import set_verbose, set_debug
# Verbose: logs LLM inputs/outputs
set_verbose(True)
# Debug: logs everything including prompts, parsers, and runnables
set_debug(True)
result = chain.invoke({'product': 'smart watch'})
# Or per-chain verbose config
chain_debug = chain.with_config({'verbose': True})
result = chain_debug.invoke({'product': 'laptop'})กำหนดค่าสายงานขณะทำงาน
สายงาน LCEL รองรับการกำหนดค่าขณะทำงานผ่าน ConfigurableField คุณสามารถเปิดให้กำหนดพารามิเตอร์ของโมเดล เช่น temperature, ชื่อโมเดล และ max_tokens เป็นตัวเลือกที่ปรับได้ โดยไม่ต้องกำหนดค่าแบบตายตัว เมื่อเรียกใช้ ให้ส่ง config แบบ Configurable เพื่อแทนที่ค่าเริ่มต้น วิธีนี้ทำให้สายงานหนึ่งชุดรองรับผู้ใช้หลายคนที่มีการตั้งค่าต่างกัน หรือใช้ทดสอบการกำหนดค่าโมเดลแบบ A/B ได้
from langchain_core.runnables import ConfigurableField
llm = ChatOpenAI(model='gpt-4o-mini').configurable_fields(
temperature=ConfigurableField(
id='temperature',
name='LLM Temperature',
description='Controls output creativity'
)
)
chain = ChatPromptTemplate.from_template('Write about {topic}') | llm | StrOutputParser()
# Low temperature for factual output
factual = chain.invoke(
{'topic': 'history of Rome'},
config={'configurable': {'temperature': 0.0}}
)ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจของคุณเกี่ยวกับการสร้างสายงานด้วย LCEL
สรุปบทเรียน
ในบทเรียนนี้ คุณได้เรียนรู้ว่า การประกอบด้วยไปป์ของ LCEL เชื่อมต่อ Runnable ด้วย | ให้เป็นสายงานที่สะอาดและอ่านง่าย RunnablePassthrough และ RunnableLambda ช่วยให้คุณแทรกขั้นตอนจัดการข้อมูลได้โดยไม่ต้องออกจากแนวทางของ LCEL และ ทางเลือกสำรอง ทำให้สายงานมีความทนทาน โดยลองใช้สายงานสำรองโดยอัตโนมัติเมื่อเกิดข้อผิดพลาด บทถัดไปเราจะสำรวจสายงานแบบแตกแขนงและแบบขนาน เพื่อรองรับตรรกะการกำหนดเส้นทางที่ซับซ้อนยิ่งขึ้น
เรียนรู้ Python ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 30
- บทเรียน
- 120
คำถามที่พบบ่อย
บทเรียน “การสร้างสายงานด้วย LCEL” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การสร้างสายงานด้วย LCEL” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Engineering Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Engineering Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การสร้างสายงานด้วย LCEL”
ใช้ตัวดำเนินการไปป์เพื่อเชื่อมแม่แบบพรอมต์ LLM และตัวแยกวิเคราะห์ผลลัพธ์เป็นลำดับ Runnable เรียกใช้ทั้งแบบพร้อมกันและแบบไม่พร้อมกัน และตรวจสอบผลลัพธ์ระหว่างทาง คุณปฏิบัติ AI Engineering Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Engineering Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Engineering Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “การสร้างสายงานด้วย LCEL” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน AI Engineering Academy นี้ได้ไหม
ได้ บทเรียน AI Engineering Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- สถาปัตยกรรม LangChain และนามธรรมหลัก
- การสร้างสายงานด้วย LCEL
- สายงานแบบแยกแขนงและแบบขนาน
- การสตรีมผลลัพธ์ใน LangChain