AI Engineering Academy · บทเรียน

การสร้างสายงานด้วย LCEL

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

บทเรียน 2 จาก 413 ขั้นตอน

การสร้างสายงานด้วย 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. สถาปัตยกรรม LangChain และนามธรรมหลัก
  2. การสร้างสายงานด้วย LCEL
  3. สายงานแบบแยกแขนงและแบบขนาน
  4. การสตรีมผลลัพธ์ใน LangChain
← กลับไปที่ AI Engineering Academy