การสร้างกระบวนการหลายเอเจนต์ด้วย LangGraph
ใช้ LangGraph กำหนดโหนดเอเจนต์ เส้นเชื่อมแบบมีเงื่อนไข และสถานะที่ใช้ร่วมกันในกราฟมีทิศทาง เพื่อรองรับกระบวนการทำงานหลายเอเจนต์ที่ซับซ้อนซึ่งมีลูป การแตกแขนง และจุดตรวจสอบโดยมนุษย์
การสร้างกระบวนการหลายเอเจนต์ด้วย LangGraph เป็นบทเรียน AI Engineering Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Engineering Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Engineering Academy มีบทเรียนทั้งหมด 4 บทเรียน
LangGraph คืออะไร
LangGraph เป็นไลบรารีที่สร้างต่อยอดจาก LangChain ซึ่งช่วยให้คุณกำหนดกระบวนการทำงานหลายตัวแทนเป็นกราฟมีทิศทางได้ โหนดในกราฟแทนตัวแทนหรือขั้นตอนการประมวลผล ส่วนเส้นเชื่อมแทนการไหลของสถานะระหว่างโหนด และเส้นเชื่อมแบบมีเงื่อนไขช่วยกำหนดเส้นทางแบบไดนามิกตามสถานะปัจจุบัน LangGraph จัดการกลไกการทำงาน การคงอยู่ของสถานะ และจุดตรวจสอบที่ให้มนุษย์เข้ามามีส่วนร่วม
# pip install langgraph
from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated
import operator
# Define your shared state schema
class AgentState(TypedDict):
messages: Annotated[list, operator.add] # append-only list
research: str
draft: str
status: strการกำหนดสถานะใน LangGraph
กระบวนการทำงานของ LangGraph ทุกแบบทำงานบน ออบเจ็กต์สถานะร่วม ที่โหนดทั้งหมดสามารถอ่านและเขียนได้ สถานะนี้คือพจนานุกรมแบบมีชนิดข้อมูล (TypedDict) ซึ่งนำข้อมูลผ่านกราฟ เมื่อโหนดทำงาน โหนดจะได้รับสถานะปัจจุบัน ดำเนินงานของตน แล้วส่งคืนพจนานุกรมรายการปรับปรุงเพื่อผสานเข้ากับสถานะ โมเดลสถานะร่วมนี้ทำให้ตัวแทนสื่อสารกันได้โดยไม่ต้องเชื่อมโยงกันโดยตรง
from typing import TypedDict
class ResearchState(TypedDict):
query: str # input from user
research_notes: str # filled by researcher node
written_draft: str # filled by writer node
review_feedback: str # filled by reviewer node
final_output: str # filled by synthesizer node
iteration_count: int # tracks how many revision loops occurred
# Each node returns a PARTIAL update - only the keys it modifies
def researcher_node(state: ResearchState) -> dict:
notes = do_research(state['query'])
return {'research_notes': notes} # only update this keyการสร้างโหนดตัวแทน
ใน LangGraph ตัวแทนแต่ละตัวคือ ฟังก์ชันโหนด ที่รับสถานะปัจจุบัน ดำเนินการเรียก LLM และเครื่องมือของตน แล้วส่งคืนการปรับปรุงสถานะ โหนดเป็นฟังก์ชันบริสุทธิ์ กล่าวคือไม่ได้จัดเก็บสถานะภายใน สถานะทั้งหมดอยู่ในออบเจ็กต์สถานะร่วมของกราฟ ทำให้ตรวจสอบ ดำเนินการต่อ และแก้ไขข้อบกพร่องของกระบวนการทำงานได้ง่าย
from langchain_openai import ChatOpenAI
from langchain_core.messages import SystemMessage, HumanMessage
llm = ChatOpenAI(model='gpt-4o')
def researcher_node(state: ResearchState) -> dict:
messages = [
SystemMessage(content='You are a research specialist. Find accurate information.'),
HumanMessage(content=f'Research this topic: {state["query"]}')
]
response = llm.invoke(messages)
return {'research_notes': response.content}
def writer_node(state: ResearchState) -> dict:
messages = [
SystemMessage(content='You are a technical writer. Write clear, engaging prose.'),
HumanMessage(content=f'Write a draft using these notes:\n{state["research_notes"]}')
]
response = llm.invoke(messages)
return {'written_draft': response.content}การสร้างกราฟด้วย StateGraph
หลังจากกำหนดฟังก์ชันโหนดแล้ว ให้เชื่อมโหนดเหล่านั้นเข้าด้วยกันด้วย StateGraph เพิ่มโหนดด้วย graph.add_node() เพิ่มเส้นเชื่อมระหว่างโหนดด้วย graph.add_edge() กำหนดจุดเริ่มต้นด้วย graph.set_entry_point() และคอมไพล์กราฟเป็นสิ่งที่เรียกใช้งานได้ด้วย graph.compile() กราฟที่คอมไพล์แล้วคือสิ่งที่เรียกใช้งานได้ ซึ่งรับสถานะเริ่มต้นและส่งคืนสถานะสุดท้าย
from langgraph.graph import StateGraph, END
# Build the graph
workflow = StateGraph(ResearchState)
# Add nodes
workflow.add_node('researcher', researcher_node)
workflow.add_node('writer', writer_node)
workflow.add_node('reviewer', reviewer_node)
# Add edges (sequential pipeline)
workflow.set_entry_point('researcher')
workflow.add_edge('researcher', 'writer')
workflow.add_edge('writer', 'reviewer')
workflow.add_edge('reviewer', END)
# Compile into an executable
app = workflow.compile()
# Run it
result = app.invoke({'query': 'What is RAG?', 'iteration_count': 0})
print(result['written_draft'])เส้นเชื่อมแบบมีเงื่อนไขสำหรับการกำหนดเส้นทางแบบไดนามิก
เส้นเชื่อมแบบมีเงื่อนไข ช่วยให้กราฟกำหนดเส้นทางไปยังโหนดต่าง ๆ ตามสถานะปัจจุบันได้ แทนที่จะใช้เส้นเชื่อมตายตัว คุณจะระบุฟังก์ชันกำหนดเส้นทางที่ตรวจสอบสถานะและส่งคืนชื่อของโหนดถัดไป วิธีนี้ช่วยให้สร้างวงจรแก้ไข ขั้นตอนตรวจสอบคุณภาพ ขั้นตอนขออนุมัติจากมนุษย์ และการแตกแขนงตามเนื้อหาผลลัพธ์ของตัวแทนได้
def should_revise(state: ResearchState) -> str:
'''Router function: returns the name of the next node.'''
if state['iteration_count'] >= 3:
return 'finalize' # Too many revisions - accept as is
if 'insufficient' in state.get('review_feedback', '').lower():
return 'researcher' # Need more research
if 'rewrite' in state.get('review_feedback', '').lower():
return 'writer' # Needs rewriting
return 'finalize' # Looks good
# Add conditional edge from reviewer
workflow.add_conditional_edges(
'reviewer', # from node
should_revise, # routing function
{
'researcher': 'researcher', # route name -> node name
'writer': 'writer',
'finalize': 'finalizer'
}
)ลูปและการทำซ้ำใน LangGraph
LangGraph รองรับ ลูป โดยตรง ตัวแทนหนึ่งตัวสามารถถูกเรียกกลับมาทำงานซ้ำได้หลายครั้ง ความสามารถนี้จำเป็นต่อวงจรแก้ไข รูปแบบการลองใหม่เมื่อเกิดความล้มเหลว และการปรับปรุงแบบทำซ้ำ ควรใส่เงื่อนไขยุติลูปไว้ในสถานะเสมอ เช่น ตัวนับรอบหรือค่าขีดจำกัดคะแนนคุณภาพ และบังคับใช้เงื่อนไขนั้นในตัวกำหนดเส้นทางของเส้นเชื่อมแบบมีเงื่อนไข เพื่อป้องกันลูปไม่สิ้นสุด
def researcher_node(state: ResearchState) -> dict:
notes = do_research(state['query'])
return {
'research_notes': notes,
'iteration_count': state['iteration_count'] + 1 # always increment
}
def should_continue_research(state: ResearchState) -> str:
# Terminate loop after 3 iterations regardless of quality
if state['iteration_count'] >= 3:
return END
# Continue if research is incomplete
if len(state.get('research_notes', '')) < 500:
return 'researcher' # loop back
return 'writer' # proceed to next stageการทำงานของโหนดแบบขนาน
LangGraph รองรับ แขนงแบบขนาน โดยใช้ RunnableParallel ภายในโหนด หรือแยกงานไปยังหลายโหนด เมื่อภารกิจย่อยที่เป็นอิสระต้องทำงานพร้อมกัน คุณสามารถสร้างการกระจายงานจากโหนดหนึ่งไปยังโหนดแบบขนานหลายโหนด จากนั้นใช้โหนดรวมงานที่รอให้ทุกโหนดทำงานเสร็จและผสานผลลัพธ์กลับเข้าไปในสถานะร่วม
# Fan-out: one node triggers multiple parallel ones
workflow.add_edge('planner', 'researcher_a')
workflow.add_edge('planner', 'researcher_b')
workflow.add_edge('planner', 'researcher_c')
# Fan-in: aggregator waits for all three
workflow.add_edge('researcher_a', 'aggregator')
workflow.add_edge('researcher_b', 'aggregator')
workflow.add_edge('researcher_c', 'aggregator')
workflow.add_edge('aggregator', 'writer')
# Aggregator merges parallel results
def aggregator_node(state: ResearchState) -> dict:
combined = state.get('notes_a', '') + '\n' + state.get('notes_b', '') + '\n' + state.get('notes_c', '')
return {'research_notes': combined}การบันทึกจุดตรวจสอบและการมีมนุษย์อยู่ในวงจร
LangGraph รองรับ การบันทึกจุดตรวจสอบ โดยผสานการทำงานกับส่วนหลังสำหรับจัดเก็บจุดตรวจสอบ (SQLite, Redis หรือ PostgreSQL) เมื่อเปิดใช้การบันทึกจุดตรวจสอบ สถานะของกราฟจะถูกบันทึกหลังการทำงานของแต่ละโหนด ทำให้หยุดชั่วคราว ตรวจสอบ และดำเนินกระบวนการทำงานระยะยาวต่อได้ นอกจากนี้ยังรองรับรูปแบบ การมีมนุษย์อยู่ในวงจร ซึ่งกราฟจะหยุดที่โหนดหนึ่งและรอให้มนุษย์อนุมัติหรือให้ข้อมูลก่อนดำเนินการต่อ
from langgraph.checkpoint.sqlite import SqliteSaver
# Use SQLite for persistent checkpoints
checkpointer = SqliteSaver.from_conn_string(':memory:')
app = workflow.compile(checkpointer=checkpointer, interrupt_before=['human_review'])
# First run - pauses at human_review node
thread = {'configurable': {'thread_id': 'my-workflow-1'}}
result = app.invoke({'query': 'Analyze competitors'}, config=thread)
# result.next == 'human_review' -- waiting for human input
# Human provides feedback and resumes
app.update_state(thread, {'review_feedback': 'Good research, proceed with writing'})
final = app.invoke(None, config=thread) # resume from checkpointการสตรีมผลลัพธ์ของ LangGraph
LangGraph รองรับโหมด การสตรีม ที่ส่งการปรับปรุงสถานะระหว่างทางเมื่อแต่ละโหนดทำงานเสร็จ แทนที่จะรอให้กระบวนการทำงานทั้งหมดเสร็จสิ้น โหมดนี้มีประโยชน์สำหรับกระบวนการทำงานขนาดยาวที่ต้องการแสดงความคืบหน้าบางส่วนให้ผู้ใช้เห็น ใช้ app.stream() เพื่อรับตัววนซ้ำของภาพสถานะจากแต่ละขั้นตอน
# Stream intermediate results as each node completes
for event in app.stream({'query': 'What is RAG?'}):
for node_name, node_output in event.items():
print(f'Node completed: {node_name}')
if 'research_notes' in node_output:
print('Research done:', node_output['research_notes'][:100])
if 'written_draft' in node_output:
print('Draft done:', node_output['written_draft'][:100])การแสดงภาพกราฟ
LangGraph สามารถ วาดกราฟ เป็นแผนภาพ Mermaid ได้ ซึ่งมีประโยชน์อย่างยิ่งต่อการทำความเข้าใจกระบวนการทำงานที่ซับซ้อนและมีโหนดหรือเส้นเชื่อมแบบมีเงื่อนไขจำนวนมาก เรียกใช้ app.get_graph().draw_mermaid_png() เพื่อรับภาพ PNG หรือใช้ app.get_graph().draw_mermaid() เพื่อรับไวยากรณ์ Mermaid ที่สามารถนำไปวางในตัวแสดงผล Mermaid ใดก็ได้
# Visualize the workflow graph
graph_image = app.get_graph().draw_mermaid_png()
with open('workflow.png', 'wb') as f:
f.write(graph_image)
# Or print Mermaid syntax
print(app.get_graph().draw_mermaid())
# Outputs:
# graph TD
# __start__ --> researcher
# researcher --> writer
# writer --> reviewer
# reviewer -->|Good| finalize
# reviewer -->|Needs work| researcherตัวอย่างตัวแทน LangGraph ตั้งแต่ต้นจนจบ
เมื่อนำทุกอย่างมารวมกัน กระบวนการทำงานหลายตัวแทนด้วย LangGraph ที่สมบูรณ์จะกำหนดสถานะ TypedDict สร้างฟังก์ชันโหนดสำหรับตัวแทนแต่ละตัว เชื่อมโหนดด้วย StateGraph เพิ่มเส้นเชื่อมแบบมีเงื่อนไขสำหรับวงจรแก้ไข คอมไพล์พร้อมส่วนจัดการจุดตรวจสอบ และเรียกใช้งานด้วยสถานะเริ่มต้น วิธีนี้ทำให้ได้กระบวนการทำงานหลายตัวแทนที่แข็งแกร่ง ตรวจสอบได้ และดำเนินการต่อได้ พร้อมโค้ดประกอบที่ไม่มาก
ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจเกี่ยวกับกระบวนการทำงานหลายตัวแทนของ LangGraph จากบทเรียนนี้
ทบทวนบทเรียน
ในบทเรียนนี้ คุณได้เรียนรู้ว่า LangGraph แทนกระบวนการทำงานหลายตัวแทนเป็นกราฟมีทิศทาง โดยโหนดคือตัวแทนและเส้นเชื่อมคือการไหลของข้อมูล เส้นเชื่อมแบบมีเงื่อนไข ช่วยให้กำหนดเส้นทางแบบไดนามิก สร้างลูป และสร้างวงจรแก้ไขตามสถานะปัจจุบัน และ การบันทึกจุดตรวจสอบ ช่วยให้กระบวนการทำงานระยะยาวหยุดชั่วคราวและดำเนินต่อได้ โดยมีการอนุมัติจากมนุษย์อยู่ในวงจร บทถัดไป เราจะสำรวจหน่วยความจำร่วมและการสื่อสารระหว่างตัวแทน
คำถามที่พบบ่อย
บทเรียน “การสร้างกระบวนการหลายเอเจนต์ด้วย LangGraph” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การสร้างกระบวนการหลายเอเจนต์ด้วย LangGraph” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Engineering Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Engineering Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การสร้างกระบวนการหลายเอเจนต์ด้วย LangGraph”
ใช้ LangGraph กำหนดโหนดเอเจนต์ เส้นเชื่อมแบบมีเงื่อนไข และสถานะที่ใช้ร่วมกันในกราฟมีทิศทาง เพื่อรองรับกระบวนการทำงานหลายเอเจนต์ที่ซับซ้อนซึ่งมีลูป การแตกแขนง และจุดตรวจสอบโดยมนุษย์ คุณปฏิบัติ AI Engineering Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Engineering Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Engineering Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “การสร้างกระบวนการหลายเอเจนต์ด้วย LangGraph” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน AI Engineering Academy นี้ได้ไหม
ได้ บทเรียน AI Engineering Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- เหตุใดเอเจนต์เดี่ยวจึงไปต่อไม่ได้
- รูปแบบผู้ประสานงาน-เอเจนต์ย่อย
- การสร้างกระบวนการหลายเอเจนต์ด้วย LangGraph
- หน่วยความจำร่วมและการสื่อสารระหว่างเอเจนต์