Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Bài 7 — Dự án thực chiến: Agent nghiên cứu tự sửa với tool, cycle và duyệt

Đã đọc 0/8 mục · còn khoảng 3 phút
Cách chúng tôi ghi nhận

Một mục được tính là đã đọc khi nó nằm giữa màn hình đủ lâu so với độ dài của nó (bảng và sơ đồ tính một nửa), bạn vẫn đang cuộn hoặc bấm phím, và bạn đã thấy tới cuối mục. Lướt nhanh hoặc để tab mở không được tính. Chúng tôi chỉ lưu thời gian đọc từng mục — không lưu gì khác.

Bài này ghép mọi thứ đã học thành một agent hoàn chỉnh: nhận yêu cầu, gọi tool tra cứu, tự đánh giá và lặp lại (cycle), rồi chờ người duyệt trước khi xuất bản (HITL) — tất cả có checkpoint để bền vững. Đây là kiến trúc bạn có thể tái dùng cho nhiều bài toán thật.

Đặc tả agent

Bài toán: viết bản tóm tắt một chủ đề, có kiểm chứng bằng công cụ tìm kiếm, tự sửa cho đến khi đủ chất lượng, rồi chờ người duyệt trước khi kết thúc.

Các node:

  • plan: phân tích yêu cầu, quyết định cần tra cứu gì.
  • search: gọi tool tìm kiếm, đưa kết quả vào state.
  • write: soạn bản tóm tắt từ ngữ cảnh đã có.
  • critique: tự chấm điểm bản tóm tắt.
  • human_review: chờ người duyệt trước khi kết thúc.
Luồng: plan → search → write → critique; nếu điểm thấp thì quay lại search; nếu đạt thì tới human_review → END.

Thiết kế State

from typing import Annotated, TypedDict
from operator import add

class State(TypedDict):
    topic: str
    findings: Annotated[list[str], add]   # cộng dồn qua các vòng
    draft: str
    score: int
    attempts: int
    approved: bool

findings dùng reducer add để tích lũy dữ liệu qua nhiều vòng tra cứu; attempts chặn vòng lặp; approved lưu quyết định của người dùng.

Các node then chốt

def search(state) -> dict:
    try:
        hits = tool_search(state["topic"])   # gọi tool thật
    except Exception:
        hits = []                            # lỗi có kiểm soát
    return {"findings": hits}

def critique(state) -> dict:
    score = score_draft(state["draft"])      # LLM chấm 0-10
    return {"score": score, "attempts": state["attempts"] + 1}

def route_after_critique(state) -> str:
    if state["score"] >= 8 or state["attempts"] >= 3:
        return "review"
    return "revise"

Lưu ý search bọc try/except để một lần API lỗi không giết cả graph, và critique luôn tăng attempts để cycle có ngưỡng dừng.

Lắp graph

from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import MemorySaver

b = StateGraph(State)
for name, fn in [("plan", plan), ("search", search),
                 ("write", write), ("critique", critique),
                 ("human_review", human_review)]:
    b.add_node(name, fn)

b.add_edge(START, "plan")
b.add_edge("plan", "search")
b.add_edge("search", "write")
b.add_edge("write", "critique")
b.add_conditional_edges("critique", route_after_critique,
                        {"review": "human_review", "revise": "search"})
b.add_edge("human_review", END)

app = b.compile(checkpointer=MemorySaver(),
                interrupt_before=["human_review"])

Cách ghép: cycle nằm ở critique → search, HITL ở interrupt_before=["human_review"], và checkpoint giữ toàn bộ tiến trình để có thể dừng/khôi phục.

Các bước chạy dự án

  • Khởi tạo config với thread_id riêng cho từng yêu cầu.
  • app.invoke({"topic": ..., "attempts": 0}, config) — chạy đến khi dừng ở human_review.
  • Xem app.get_state(config) để đọc bản nháp và điểm số hiện tại.
  • Nếu cần sửa tay: app.update_state(config, {"draft": ...}).
  • Resume: app.invoke(None, config) để hoàn tất và kết thúc.

Checklist nghiệm thu agent

  • [ ] Cycle có ngưỡng dừng kép (điểm hoặc số lần thử).
  • [ ] findings tích lũy đúng, không bị ghi đè giữa các vòng.
  • [ ] Dừng đúng trước human_review, không xuất bản khi chưa duyệt.
  • [ ] Đổi thread_id cho các yêu cầu khác nhau, không lẫn dữ liệu.
  • [ ] Tool có xử lý lỗi (timeout, rỗng) để node không chết.

Sai lầm thường gặp

  • Gọi tool trong node mà không bắt lỗi: một lần API lỗi làm cả graph chết. Bọc try/except, trả findings rỗng có kiểm soát.
  • Quên khởi tạo attempts: state["attempts"] + 1 sẽ lỗi KeyError. Đặt giá trị đầu khi invoke.
  • Để cycle không giới hạn khi tool luôn trả kết quả kém, đốt token vô ích. Ngưỡng attempts là bắt buộc.
  • Đặt interrupt_before sai node khiến agent xuất bản trước khi người kịp duyệt.
  • Trộn logic routing vào node critique: giữ quyết định trong hàm route riêng để dễ đọc và test.
Bạn đã có một agent thực chiến đủ tool, cycle, checkpoint và HITL. Bài 8 khép lại với vận hành production: debug, giám sát và tối ưu.

Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi