สร้างเอเจนต์ Customer Support ด้วย LangGraph พร้อมการเรียกใช้เครื่องมือ การอนุมัติโดยมนุษย์ และข้อจำกัดการทำงาน
แนวทาง LangGraph เชิงปฏิบัติสำหรับคัดแยกคำขอฝ่ายสนับสนุนลูกค้า: จัดเส้นทางคำขอ เรียกใช้เครื่องมือค้นข้อมูล หยุดคำขอคืนเงินเพื่อรอการอนุมัติจากมนุษย์ และจำกัดการทำงานของกราฟ
ในหน้านี้
การตัดสินใจด้านการออกแบบ: ให้เอเจนต์ค้นหาได้ แต่ไม่ให้ยืนยันการคืนเงินเอง
เอเจนต์ฝ่ายสนับสนุนควรสามารถรวบรวมรายละเอียดการซื้อและค้นหารายการที่ตรงกันได้ แต่ไม่ควรมีสิทธิ์ออกคำสั่งคืนเงินด้วยตัวเอง ใน LangGraph เราสามารถแสดงความแตกต่างนี้ผ่านเวิร์กโฟลว์ได้ โดยจัดเส้นทางคำขอ เรียกใช้เครื่องมือค้นข้อมูลแบบอ่านอย่างเดียวเมื่อจำเป็น จากนั้นหยุดก่อนการดำเนินการคืนเงินเพื่อให้มนุษย์อนุมัติหรือปฏิเสธ
บทช่วยสอนนี้สร้างรูปแบบดังกล่าวสำหรับการคัดแยกคำขอฝ่ายสนับสนุนลูกค้า โดยใช้ LangGraph สำหรับการจัดการลำดับงาน ใช้แชตโมเดลที่รองรับการเรียกใช้เครื่องมือสำหรับค้นข้อมูล ใช้จุดตรวจสอบโดยมนุษย์ก่อนถึงโหนดที่มีผลกระทบ และใช้ recursion limit เพื่อจำกัดการทำงานของกราฟ โค้ดนี้เป็นรูปแบบสำหรับนำไปปรับใช้ ไม่ใช่การผสานรวม OneMux ที่ผ่านการทดสอบแล้ว
บทช่วยสอน LangSmith ที่ใช้เป็นแหล่งข้อมูลสำหรับบทความนี้สร้างบอตฝ่ายสนับสนุนร้านเพลงดิจิทัล โดยแยกซับกราฟสำหรับการค้นข้อมูลและการคืนเงินออกจากกัน เนื้อหาอธิบายการดึงรายละเอียดลูกค้าและการซื้อ การขอข้อมูลที่ขาดหาย และการประเมินคำตอบสุดท้าย เส้นทางการเรียกใช้เครื่องมือ และขั้นตอนแต่ละรายการ ตัวอย่างการคืนเงินใช้การลบข้อมูลจากฐานข้อมูล และระบุอย่างชัดเจนว่าไม่ได้ครอบคลุมการยืนยันตัวตนและมาตรการรักษาความปลอดภัยอื่น ๆ สำหรับระบบจริง อย่านำพฤติกรรมการลบข้อมูลของเดโมนี้ไปใช้กับระบบสนับสนุนที่ใช้งานจริง อ่านบทช่วยสอนการประเมินเอเจนต์ซับซ้อนของ LangSmith
ข้อกำหนดเบื้องต้นและขอบเขต
ติดตั้ง LangGraph และการผสานรวม LangChain ที่เกี่ยวข้องกับผู้ให้บริการโมเดลที่คุณเลือก บทช่วยสอนต้นฉบับใช้ langgraph และ langchain[openai] แต่ตัวอย่างด้านล่างตั้งใจไม่ระบุรายละเอียดการเริ่มต้นโมเดล เนื่องจากขึ้นอยู่กับผู้ให้บริการ นอกจากนี้ คุณต้องมีฐานข้อมูลหรือบริการที่รองรับการค้นหาการซื้อแบบอ่านอย่างเดียว และมีการดำเนินการคืนเงินที่แอปพลิเคชันของคุณควบคุม
ก่อนเชื่อมต่อโมเดล ให้กำหนดความสามารถของเครื่องมือแต่ละรายการ:
- การค้นข้อมูล: ส่งคืนเฉพาะรายการที่ลูกค้าที่ผ่านการยืนยันตัวตนมีสิทธิ์ดู
- การเตรียมคืนเงิน: ระบุธุรกรรมและจำนวนเงินที่แน่นอน โดยไม่เปลี่ยนแปลงข้อมูล
- การดำเนินการคืนเงิน: ดำเนินการที่ได้รับอนุมัติในโค้ดของแอปพลิเคชัน พร้อมการตรวจสอบสิทธิ์และบันทึกข้อมูลตรวจสอบย้อนหลัง
ให้การยืนยันตัวตนลูกค้า การกำหนดสิทธิ์ idempotency และนโยบายการคืนเงินอยู่นอกดุลยพินิจของโมเดล ชื่อลูกค้าหรือ invoice ID ที่โมเดลสร้างขึ้นไม่ใช่หลักฐานยืนยันตัวตน
สร้างกราฟพร้อมจุดตรวจสอบโดยมนุษย์
ตัวอย่างนี้ใช้โมเดลที่รองรับการเรียกใช้เครื่องมือ เครื่องมือค้นข้อมูล และโหนดคืนเงินแยกต่างหาก ให้แทนที่ฟังก์ชันของแอปพลิเคชันที่ทำเครื่องหมายไว้ด้วยการเรียกบริการที่มีการกำหนดสิทธิ์ของคุณเอง โมเดลและสคีมาของเครื่องมือต้องได้รับการรองรับจาก endpoint ที่คุณกำหนดค่าไว้ ความเข้ากันได้ขึ้นอยู่กับการรองรับ endpoint และพารามิเตอร์ตามเอกสาร ตัวอย่างโค้ดนี้ไม่ได้ยืนยันว่าโมเดลหรือการกำหนดค่า OneMux ใด ๆ ผ่านการทดสอบแล้ว
from typing import Annotated, Literal
from langchain.tools import tool
from langchain_core.messages import AnyMessage
from langgraph.graph import END, START, StateGraph
from langgraph.graph.message import add_messages
from langgraph.prebuilt import ToolNode, tools_condition
from langgraph.checkpoint.memory import MemorySaver
from langgraph.types import interrupt
from typing_extensions import TypedDict
# Replace with your provider's documented LangChain model setup.
# Confirm that the chosen endpoint supports tool calling and the parameters used.
model = make_your_chat_model().bind_tools([]) # bind the tools below in your application
class State(TypedDict):
messages: Annotated[list[AnyMessage], add_messages]
refund_request: dict | None
approval: str | None
@tool
def find_purchases(customer_reference: str) -> list[dict]:
"""Find purchases for an already authenticated customer."""
return authorized_purchase_lookup(customer_reference)
tools = [find_purchases]
model = make_your_chat_model().bind_tools(tools)
def assistant(state: State):
return {"messages": [model.invoke(state["messages"])]}
def prepare_refund(state: State):
# Build this from validated application data, not model-invented values.
request = build_validated_refund_request(state["messages"])
decision = interrupt({
"type": "refund_approval",
"request": request,
"instruction": "Approve or reject this exact refund request.",
})
if decision != "approve":
return {"approval": "rejected", "refund_request": request}
return {"approval": "approved", "refund_request": request}
def execute_refund(state: State):
if state.get("approval") != "approved":
return {"messages": [{"role": "assistant", "content": "The refund was not approved."}]}
result = issue_refund_safely(state["refund_request"])
return {"messages": [{"role": "assistant", "content": format_refund_result(result)}]}
builder = StateGraph(State)
builder.add_node("assistant", assistant)
builder.add_node("tools", ToolNode(tools))
builder.add_node("prepare_refund", prepare_refund)
builder.add_node("execute_refund", execute_refund)
builder.add_edge(START, "assistant")
builder.add_conditional_edges("assistant", tools_condition)
builder.add_edge("tools", "assistant")
builder.add_edge("prepare_refund", "execute_refund")
builder.add_edge("execute_refund", END)
graph = builder.compile(checkpointer=MemorySaver())
นี่เป็นตัวอย่างเชิงโครงสร้าง ไม่ใช่กราฟการจัดเส้นทางที่สมบูรณ์ แอปพลิเคชันของคุณต้องจัดเส้นทาง intent การคืนเงินที่ผ่านการตรวจสอบแล้วไปยัง prepare_refund และส่งคำถามทั่วไปไปยังเส้นทาง assistant/lookup การเรียก interrupt() จะหยุดกราฟและส่งข้อมูลการอนุมัติกลับไปยังผู้เรียก อินเทอร์เฟซตรวจสอบโดยมนุษย์ควรแสดงลูกค้า ธุรกรรม จำนวนเงิน และบริบทของนโยบายก่อนส่งการตัดสินใจ ให้ทำงานต่อในเธรดเดิมด้วยกลไก Command(resume=...) ของ LangGraph และใช้ตัวระบุเธรดเดียวกัน จัดเก็บจุดตรวจสอบอย่างเหมาะสม โดยการจัดเก็บในหน่วยความจำเหมาะสำหรับการพัฒนา ไม่ใช่เวิร์กโฟลว์จริงที่ต้องการความคงทน
รายละเอียดสำคัญด้านลำดับการควบคุมคือ interrupt เป็นเพียงการหยุดชั่วคราว ไม่ใช่ระบบจัดการสิทธิ์ ให้ตรวจสอบค่า approval ซ้ำในโหนดดำเนินการคืนเงิน และตรวจสอบให้บริการคืนเงินตรวจสอบการกำหนดสิทธิ์ สิทธิ์ในการทำธุรกรรม และคำขอซ้ำด้วยตัวเอง
จำกัดการทำงานและทำให้ความล้มเหลวปรากฏชัด
ส่งค่า recursion limit เมื่อเรียกใช้กราฟ ค่านี้จำกัด superstep ของกราฟ แต่ไม่ได้จำกัดโทเค็นของโมเดล เวลาทำงานของเครื่องมือ ค่าใช้จ่ายในการค้นฐานข้อมูล หรือจำนวนคำขอจากผู้ใช้ ให้กำหนด timeout และขีดจำกัดทรัพยากรแยกต่างหากสำหรับการเรียกโมเดลและเครื่องมือ
from langgraph.errors import GraphRecursionError
config = {
"configurable": {"thread_id": "support-case-123"},
"recursion_limit": 12,
}
try:
result = graph.invoke(
{"messages": [{"role": "user", "content": "I need help with a purchase."}]},
config=config,
)
except GraphRecursionError:
# Return a safe handoff or ask for clarification; log the trace for review.
result = {"status": "needs_human_review"}
เลือกขีดจำกัดตามเวิร์กโฟลว์ที่คาดไว้ จากนั้นทดสอบทั้งการทำงานจนเสร็จตามปกติและอินพุตที่อาจทำให้เกิดลูป หลีกเลี่ยงการลองใหม่โดยไม่แสดงให้เห็นเมื่อกราฟใช้ขีดจำกัดหมด เพราะการลองใหม่อาจทำให้เกิดการเรียกใช้เครื่องมือซ้ำ เว้นแต่เครื่องมือของคุณจะเป็น idempotent เครื่องมือค้นข้อมูลแบบอ่านอย่างเดียวปลอดภัยต่อการลองใหม่มากกว่าการดำเนินการที่มี side effect
ประเมินเส้นทาง ไม่ใช่แค่คำตอบ
บทช่วยสอน LangSmith ที่ให้มาแบ่งเป้าหมายการประเมินที่มีประโยชน์ออกเป็นสามแบบ ได้แก่ คำตอบสุดท้าย (คำตอบของลูกค้าเหมาะสมหรือไม่), trajectory (เอเจนต์ใช้เส้นทางการเรียกใช้เครื่องมือที่คาดไว้หรือไม่) และ ขั้นตอนเดียว (เอเจนต์เลือกเครื่องมือที่ถูกต้องสำหรับการตัดสินใจหนึ่ง ๆ หรือไม่) สำหรับการคัดแยกการคืนเงิน ให้สร้างกรณีทดสอบสำหรับรายละเอียดตัวตนที่ขาดหาย การซื้อหลายรายการที่ตรงกัน การค้นข้อมูลที่ไม่พบผลลัพธ์ การปฏิเสธการอนุมัติ และการคืนเงินที่ได้รับอนุมัติ
ตรวจสอบว่าเอเจนต์ขอข้อมูลที่จำเป็นแทนการสร้างข้อมูลขึ้นเอง การค้นข้อมูลไม่ทำให้เกิดการคืนเงิน และไม่สามารถดำเนินการได้หากไม่มีการอนุมัติ ใช้บริการจำลองหรือบริการทดสอบสำหรับการประเมิน เพื่อไม่ให้การทดสอบเปลี่ยนแปลงข้อมูลลูกค้าจริง บทช่วยสอนต้นฉบับใช้โหมดจำลองสำหรับการดำเนินการกับฐานข้อมูล แต่เป็นการอธิบายการตั้งค่าเดโมของตนเอง ไม่ใช่การรับประกันความปลอดภัยสำหรับระบบจริง
ใช้ OneMux เพื่อเข้าถึงโมเดล
OneMux ให้เข้าถึงโมเดล AI ชั้นนำผ่าน API ที่เข้ากันได้กับ OpenAI หากต้องการ API เดียวสำหรับการเข้าถึงโมเดล โปรดดู คู่มือเริ่มต้นใช้งาน OneMux, เอกสาร API และ โมเดลที่พร้อมใช้งาน ความเข้ากันได้สำหรับเวิร์กโฟลว์นี้ขึ้นอยู่กับการรองรับการเรียกใช้เครื่องมือและพารามิเตอร์ที่ยอมรับได้ตามเอกสารของ endpoint โมเดลที่เลือก โปรดยืนยันรายละเอียดดังกล่าวก่อนนำไปใช้งาน บทความนี้ไม่ได้อ้างว่าตัวอย่าง LangGraph ผ่านการทดสอบกับ OneMux
ข้อจำกัดและการแก้ไขปัญหา
- โมเดลไม่เรียกใช้เครื่องมือ: ตรวจสอบว่า endpoint ที่เลือก รองรับการเรียกใช้เครื่องมือ และส่งสคีมาของเครื่องมือในรูปแบบที่เอกสารระบุ
- กราฟเกิดลูป: ตรวจสอบการเปลี่ยนผ่านระหว่าง assistant กับ tools จำกัดจำนวนขั้นตอนของกราฟ และตรวจสอบว่าผลลัพธ์ของเครื่องมือที่เสร็จสมบูรณ์ทำให้การตัดสินใจถัดไปเปลี่ยนแปลง
- การอนุมัติทำให้กลับไปยังเคสผิดรายการ: ใช้ตัวระบุเธรดที่เสถียรและผูกกับเคสฝ่ายสนับสนุน พร้อมตรวจสอบจุดตรวจสอบก่อนทำงานต่อ
- คืนเงินซ้ำสองครั้ง: เพิ่ม idempotency ที่ขอบเขตบริการ และบันทึกคำขอที่ได้รับอนุมัติรวมถึงผลลัพธ์
- เอเจนต์เปิดเผยข้อมูลของลูกค้ารายอื่น: แก้ไขการกำหนดสิทธิ์ในบริการค้นข้อมูล เพราะคำสั่งในพรอมต์ไม่ใช่การควบคุมการเข้าถึง
สรุป
LangGraph ช่วยให้แสดงการคัดแยกคำขอฝ่ายสนับสนุนเป็นขั้นตอนของเวิร์กโฟลว์ที่ชัดเจน แทนการไว้วางใจคำตอบเดียวจากโมเดลให้เป็นผู้ตัดสินใจและดำเนินการ เก็บการค้นข้อมูลไว้เป็นแบบอ่านอย่างเดียว หยุดก่อนคืนเงิน ตรวจสอบการอนุมัติขณะดำเนินการ และจำกัดจำนวนขั้นตอนของกราฟ จากนั้นประเมินทั้งคำตอบและเส้นทางที่เอเจนต์ใช้ มาตรการเหล่านี้ทำให้ตรวจสอบเวิร์กโฟลว์ได้ง่ายขึ้น แต่การรักษาความปลอดภัยและการบังคับใช้นโยบายในระบบจริงยังคงเป็นความรับผิดชอบของแอปพลิเคชัน
แหล่งข้อมูล
- LangSmith: ประเมินเอเจนต์ซับซ้อน — แหล่งข้อมูลสำหรับตัวอย่างฝ่ายสนับสนุนร้านเพลง โครงสร้างการค้นข้อมูล/คืนเงิน โหมดจำลอง และเป้าหมายการประเมินทั้งสามแบบ
คำถามที่พบบ่อย
จะกำหนดให้มีมนุษย์อนุมัติก่อนที่เอเจนต์ LangGraph จะออกคำสั่งคืนเงินได้อย่างไร
หยุดกราฟก่อนถึงโหนดดำเนินการคืนเงินด้วย LangGraph interrupt แสดงคำขอที่ผ่านการตรวจสอบแล้วให้ผู้ตรวจสอบ และทำงานต่อจากจุดตรวจสอบเดิมก็ต่อเมื่อได้รับการตัดสินใจอย่างชัดเจน นอกจากนี้ ให้ตรวจสอบการอนุมัติซ้ำภายในโหนดดำเนินการ และบังคับใช้นโยบายในบริการคืนเงิน
recursion limit ของ LangGraph จำกัดเวลาทำงานของเครื่องมือหรือโทเค็นของโมเดลหรือไม่
ไม่จำกัด ค่านี้จำกัด superstep ของกราฟ ไม่ใช่การใช้โทเค็นของโมเดล ระยะเวลาทำงานของเครื่องมือ ค่าใช้จ่ายฐานข้อมูล หรือจำนวนคำขอขาเข้า ให้เพิ่ม timeout และขีดจำกัดทรัพยากรแยกต่างหาก
โมเดลสามารถตัดสินใจได้หรือไม่ว่าลูกค้ามีสิทธิ์ได้รับเงินคืน
ไม่ได้ ให้ถือว่าผลลัพธ์จากโมเดลเป็นอินพุตที่ไม่น่าเชื่อถือ ยืนยันตัวตนลูกค้า และตรวจสอบสิทธิ์เข้าถึงธุรกรรมรวมถึงคุณสมบัติในการคืนเงินด้วยโค้ดของแอปพลิเคชันและบริการ
ควรประเมินอะไรในเอเจนต์ฝ่ายสนับสนุนลูกค้า
ประเมินคำตอบสุดท้าย ลำดับการเรียกใช้เครื่องมือ และขั้นตอนการเลือกเครื่องมือแต่ละรายการ รวมกรณีข้อมูลไม่ครบ การซื้อคลุมเครือ การปฏิเสธการอนุมัติ และการคืนเงินที่ได้รับอนุมัติ โดยใช้บริการทดสอบสำหรับ side effect
บทความที่เกี่ยวข้อง
Guides
สร้าง LangGraph Agent ที่มีขอบเขตการทำงาน พร้อมดึงข้อมูลตาม Schema ที่ตรวจสอบได้
สร้างเวิร์กโฟลว์ LangGraph ที่เรียกใช้เครื่องมือเมื่อจำเป็น หยุดภายในขีดจำกัดการทำงานที่กำหนด และส่งคืนข้อมูลแบบมีโครงสร้างที่ตรวจสอบกับ Pydantic schema แล้ว
Guides
LangGraph Agentic RAG: การเรียกใช้เครื่องมือ การระบุแหล่งที่มา และการประมวลผลแบบมีขอบเขต
สร้างเอเจนต์ตอบคำถามจากเอกสารด้วย LangGraph ที่ตัดสินใจได้ว่าควรค้นคืนข้อมูลหรือไม่ ประเมินบริบท ลองค้นหาใหม่เมื่อผลลัพธ์ไม่เพียงพอ และตอบพร้อมระบุแหล่งที่มาโดยไม่ประมวลผลแบบไร้ขอบเขต
Guides
สร้าง Workflow ใน n8n สำหรับแก้ไขโค้ดโดยให้มนุษย์อนุมัติและตรวจสอบด้วยการทดสอบ
ออกแบบ workflow ใน n8n ที่เสนอการเปลี่ยนแปลง repository ให้มนุษย์อนุมัติก่อนเขียน และตรวจสอบ commit ที่ได้ด้วยการทดสอบ
Guides
Cline กับผู้ให้บริการที่เข้ากันได้กับ OpenAI สำหรับคัดแยกคำขอฝ่ายสนับสนุนโดยมีมนุษย์อนุมัติ
กำหนดค่า Cline ร่วมกับผู้ให้บริการที่เข้ากันได้กับ OpenAI และ OneMux เพื่อคัดแยกคำขอฝ่ายสนับสนุนลูกค้า โดยให้ทุกการดำเนินการที่มีผลต่อลูกค้าต้องผ่านการอนุมัติจากมนุษย์