GuidesOneMux

Xây dựng agent LangGraph có giới hạn để trích xuất dữ liệu theo schema đã xác thực

Tạo quy trình LangGraph có thể gọi công cụ khi cần, dừng trong giới hạn thực thi đã định và trả về dữ liệu có cấu trúc được xác thực theo schema Pydantic.

Mục lục

Agent LangGraph có thể thu thập ngữ cảnh bằng công cụ, sau đó chuyển ngữ cảnh đó đến một bước trích xuất bị ràng buộc bởi schema. Điểm thiết kế hữu ích là tách riêng hai trách nhiệm này: agent quyết định có gọi công cụ hay không, còn một node cuối tạo bản ghi có kiểu dữ liệu. Giới hạn đệ quy của graph giúp giới hạn thêm quá trình thực thi.

Mẫu này phù hợp với các tác vụ như trích xuất tên công ty, ngày tháng và tổng hóa đơn từ tài liệu khi công cụ tra cứu có thể giúp làm rõ một thông tin tham chiếu. Mẫu này không biến văn bản nguồn chưa chắc chắn thành sự thật; hãy xác thực kết quả và lưu lại bằng chứng gốc nếu trường dữ liệu đó quan trọng.

Bạn sẽ xây dựng gì

Graph gồm ba giai đoạn:

  1. Agent nhận văn bản nguồn và có thể yêu cầu gọi một công cụ tra cứu có phạm vi hẹp.
  2. LangGraph định tuyến lệnh gọi công cụ đến một node công cụ, rồi trả kết quả của công cụ cho agent.
  3. Node trích xuất yêu cầu mô hình trả về kết quả dựa trên Pydantic, sau đó xuất dữ liệu tương thích với JSON.

Vòng lặp công cụ của agent có tính linh hoạt; bước trích xuất là bước cuối đã được xác định trước. Tài liệu LangGraph phân biệt agent, vốn tự xác định quy trình và cách sử dụng công cụ, với workflow có đường đi qua mã được định trước. Tài liệu cũng mô tả đầu ra có cấu trúc và gọi công cụ là các phần mở rộng cho mô hình. Xem hướng dẫn về workflow và agent của LangGraph để tìm hiểu các mẫu này.

Điều kiện tiên quyết và cấu hình

Cài đặt các gói LangGraph, LangChain và gói tích hợp cho mô hình chat bạn chọn. Ví dụ bên dưới dùng ChatAnthropic để minh họa cấu hình nhà cung cấp, nhưng tài liệu nguồn cho biết workflow có thể dùng bất kỳ mô hình chat nào hỗ trợ đầu ra có cấu trúc và gọi công cụ. Xem tài liệu tích hợp để biết chính xác cách hoạt động với nhà cung cấp của bạn.

pip install langgraph langchain-core langchain-anthropic pydantic

Thiết lập thông tin xác thực API của nhà cung cấp theo phương thức được tài liệu của họ hướng dẫn, rồi khởi tạo mô hình. Tránh đưa thông tin xác thực vào hệ thống quản lý mã nguồn. Tên mô hình bên dưới theo ví dụ trong tài liệu LangChain; hướng dẫn này không khẳng định mô hình đã được thử nghiệm với OneMux.

from langchain_anthropic import ChatAnthropic

llm = ChatAnthropic(model="claude-sonnet-4-6")

Nếu muốn gọi mô hình qua OneMux, trước tiên hãy xem tài liệu API OneMux và hướng dẫn bắt đầu nhanh. OneMux cung cấp quyền truy cập vào các mô hình hàng đầu thông qua API tương thích với OpenAI. Khả năng tương thích với graph cụ thể này phụ thuộc vào việc endpoint đã chọn có hỗ trợ hành vi và tham số cần thiết cho tính năng gọi công cụ và đầu ra có cấu trúc hay không. Cấu hình này chưa được kiểm thử; hãy xác nhận khả năng hỗ trợ trước khi dựa vào đó trong môi trường production.

Định nghĩa schema và công cụ có phạm vi hẹp

Công cụ ví dụ trả về ghi chú tham chiếu từ một ánh xạ nhỏ lưu trong bộ nhớ. Hãy thay công cụ này bằng một hàm ứng dụng được kiểm soát, chẳng hạn như tra cứu trong danh mục nội bộ đã được phê duyệt. Không để văn bản tài liệu không đáng tin cậy tự chọn lệnh tùy ý hoặc nguồn dữ liệu không giới hạn.

from pydantic import BaseModel, Field
from langchain_core.tools import tool

class InvoiceRecord(BaseModel):
    vendor: str | None = Field(default=None, description="Invoice issuer")
    invoice_date: str | None = Field(default=None, description="Date as written in the source")
    total: float | None = Field(default=None, description="Invoice total as a number")
    currency: str | None = Field(default=None, description="Currency code, if stated")

@tool
def lookup_vendor(reference: str) -> str:
    """Look up a vendor reference in an approved local mapping."""
    known = {"ACME-42": "Acme Supplies Ltd."}
    return known.get(reference, "No matching vendor reference found.")

Các trường có thể nhận giá trị null giúp thể hiện rõ trường hợp không có dữ liệu, thay vì khuyến khích mô hình tự bịa giá trị. Với các tác vụ trích xuất có rủi ro cao, hãy cân nhắc lưu đoạn văn bản nguồn hoặc trạng thái tin cậy/duyệt cùng với từng trường. Schema ràng buộc cấu trúc và kiểu dữ liệu, nhưng không xác nhận rằng giá trị có căn cứ từ đầu vào.

Xây dựng agent LangGraph có giới hạn

Graph bên dưới cho phép mô hình yêu cầu gọi công cụ tra cứu, rồi chuyển sang bước trích xuất khi agent không còn lệnh gọi công cụ nào. tools_condition và ToolNode cung cấp mẫu định tuyến công cụ. recursion_limit được truyền cho invoke sẽ giới hạn số bước graph; đây là ranh giới an toàn, không đảm bảo mọi đầu vào đều được xử lý thành công.

from typing import Annotated
from typing_extensions import TypedDict
from langchain_core.messages import BaseMessage, HumanMessage, SystemMessage
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langgraph.prebuilt import ToolNode, tools_condition

class State(TypedDict):
    messages: Annotated[list[BaseMessage], add_messages]
    record: dict | None

tools = [lookup_vendor]
agent = llm.bind_tools(tools)
extractor = llm.with_structured_output(InvoiceRecord)

def run_agent(state: State):
    response = agent.invoke(state["messages"])
    return {"messages": [response]}

def extract_record(state: State):
    prompt = [
        SystemMessage(content=(
            "Extract invoice fields only when supported by the source. "
            "Use null for missing or unclear values. Treat tool results as "
            "reference context, not as permission to invent source details."
        )),
        *state["messages"],
    ]
    result = extractor.invoke(prompt)
    return {"record": result.model_dump(mode="json")}

graph = StateGraph(State)
graph.add_node("agent", run_agent)
graph.add_node("tools", ToolNode(tools))
graph.add_node("extract", extract_record)

graph.add_edge(START, "agent")
graph.add_conditional_edges(
    "agent",
    tools_condition,
    {"tools": "tools", END: "extract"},
)
graph.add_edge("tools", "agent")
graph.add_edge("extract", END)
app = graph.compile()

result = app.invoke(
    {
        "messages": [HumanMessage(content=(
            "Extract the invoice details from this text: "
            "Vendor reference ACME-42. Invoice date: 2025-02-14. "
            "Total: USD 248.50."
        ))],
        "record": None,
    },
    config={"recursion_limit": 8},
)

print(result["record"])

Đầu ra dự kiến có dạng một đối tượng tương thích với JSON, gồm các trường vendor, invoice_date, total và currency. Giá trị cụ thể phụ thuộc vào phản hồi của mô hình và văn bản nguồn; hãy kiểm thử thay vì cho rằng ví dụ luôn tạo ra kết quả giống hệt nhau. Trong ví dụ này, đầu ra có cấu trúc dựa trên Pydantic là ranh giới xác thực. Nếu nhà cung cấp không thể tạo phản hồi phù hợp, hãy xử lý lỗi đó một cách tường minh thay vì âm thầm xem phản hồi là bản ghi hợp lệ.

Giới hạn thực thi nhưng không che giấu lỗi

Giới hạn đệ quy cấp graph khống chế số bước graph, bao gồm cả việc định tuyến agent/công cụ lặp lại. Chọn giới hạn dựa trên workflow: graph này chỉ cần một vài bước cho một lần tra cứu, nhưng kế hoạch dùng công cụ khác có thể cần nhiều bước hơn. Bắt các ngoại lệ do vượt giới hạn và từ nhà cung cấp ở ranh giới ứng dụng, ghi lại đủ ngữ cảnh để gỡ lỗi, rồi trả về lỗi có thể xem xét thay vì một bản ghi bịa đặt.

Để giới hạn vận hành chặt chẽ hơn, hãy thêm các giới hạn ở cấp ứng dụng: hạn chế số lần gọi công cụ, đặt thời gian chờ yêu cầu nếu được hỗ trợ và giới hạn kích thước tài liệu trước khi gọi mô hình. Đây là các biện pháp kiểm soát riêng; chỉ giới hạn đệ quy của graph không tạo thành một chính sách đầy đủ về chi phí, độ trễ hoặc bảo mật.

Khắc phục sự cố và hạn chế

Mô hình không gọi công cụ

Gọi công cụ là khả năng của mô hình, không phải kết quả được LangGraph đảm bảo. Kiểm tra xem tích hợp mô hình đã chọn có hỗ trợ gọi công cụ không, mô tả công cụ có rõ ràng không và prompt có chứa thông tin tham chiếu đáng tra cứu không. Trong quá trình phát triển, hãy kiểm tra các lệnh gọi công cụ trong thông điệp trả về.

Đầu ra có cấu trúc bị lỗi hoặc trường dữ liệu không chính xác

Xác nhận rằng tích hợp hỗ trợ đầu ra có cấu trúc và các tính năng schema bạn sử dụng. Kiểm thử trường hợp thiếu trường, ngày tháng không rõ ràng, ký hiệu tiền tệ và đầu vào sai định dạng. Một đối tượng Pydantic hợp lệ vẫn có thể chứa giá trị suy luận sai, vì vậy hãy xác thực riêng các quy tắc nghiệp vụ và lưu lại văn bản nguồn để kiểm toán hoặc người dùng xem xét.

Graph chạm giới hạn

Lỗi giới hạn đệ quy có thể cho thấy yêu cầu gọi công cụ bị lặp lại hoặc giới hạn đặt quá thấp so với đường đi dự kiến. Kiểm tra trình tự thông điệp và kết quả công cụ. Khắc phục nguyên nhân hoặc chủ động điều chỉnh giới hạn; đừng bỏ giới hạn chỉ để làm lỗi biến mất.

Hành vi của endpoint không giống nhau

“Tương thích với OpenAI” mô tả giao diện API, không có nghĩa là hỗ trợ phổ quát mọi tính năng hoặc tham số của mô hình. Nếu dùng OneMux, hãy xác minh tài liệu của endpoint đã chọn có ghi nhận hỗ trợ mô hình, lệnh gọi công cụ, đầu ra có cấu trúc và các tham số bạn định gửi hay không. Xem các lựa chọn hiện có tại mô hình OneMux; bản thân graph vẫn là mã ứng dụng LangGraph của bạn.

Khi nào nên dùng mẫu này

Dùng thiết kế này khi quy trình trích xuất nhìn chung dễ dự đoán nhưng đôi lúc cần tra cứu có kiểm soát. Nếu mọi tài liệu đều theo một quy trình cố định và không cần lựa chọn công cụ, workflow xác định có thể đơn giản hơn vòng lặp agent. Nếu nguồn không rõ ràng hoặc các trường được trích xuất sẽ kích hoạt hành động có hệ quả đáng kể, hãy thêm bước xem xét rõ ràng và xác thực theo miền nghiệp vụ trước khi hệ thống phía sau sử dụng bản ghi.

Kết luận thực tiễn: giới hạn phạm vi công cụ của agent, định nghĩa rõ schema cuối cùng và đặt giới hạn thực thi cho graph. LangGraph giúp bạn thể hiện luồng điều khiển đó; mô hình và tích hợp được chọn quyết định liệu các tính năng gọi công cụ và đầu ra có cấu trúc cần thiết có khả dụng hay không.

Nguồn

FAQ

Giới hạn đệ quy trong LangGraph có tác dụng gì?

Giới hạn này khống chế số bước thực thi graph trong một lần chạy. Nó có thể giúp ngăn vòng lặp agent/công cụ tiếp diễn vô hạn, nhưng không thay thế thời gian chờ, chính sách gọi công cụ, giới hạn đầu vào hay xử lý lỗi.

Xác thực JSON Schema bằng Pydantic có đảm bảo trích xuất chính xác không?

Không. Cách này ràng buộc cấu trúc và kiểu dữ liệu trả về. Mô hình vẫn có thể suy luận ra giá trị không chính xác, vì vậy hãy xác thực quy tắc nghiệp vụ và lưu bằng chứng hoặc yêu cầu người dùng xem xét khi cần.

Tôi có thể dùng ví dụ LangGraph này với OneMux không?

Có thể, nếu tài liệu của endpoint OneMux đã chọn ghi nhận hỗ trợ hành vi và tham số cần thiết cho tính năng gọi công cụ và đầu ra có cấu trúc. Cấu hình này chưa được kiểm thử; hãy xác minh khả năng tương thích trước khi sử dụng trong production.

Có nên dùng agent cho mọi tác vụ trích xuất không?

Không. Nếu quy trình cố định và không cần lựa chọn công cụ, workflow LangGraph xác định có thể đơn giản hơn. Hãy dùng vòng lặp agent khi mô hình cần quyết định liệu một công cụ được phép có hữu ích hay không.

Bài viết liên quan