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 — Xây pipeline agent tiết kiệm từng bước (case study)

Đã đọ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 kỹ thuật đã học vào một pipeline hoàn chỉnh cho agent hỗ trợ khách hàng, đi từ bản "đắt và chậm" tới bản tối ưu, đo từng bước.

Điểm xuất phát (baseline)

Agent v0: mọi lượt → model lớn, gửi toàn bộ 20 tool + toàn bộ lịch sử, không cache, gọi tool tuần tự.

  • Chi phí: ~$0,05/lượt · p95 latency: ~14s.

Kiến trúc tối ưu: pipeline 5 tầng

1. Cache tra cứu (exact + semantic)  -> hit thì trả ngay
2. Phân loại intent (model nhỏ)       -> chọn tool + tầng
3. Thu thập ngữ cảnh (song song, RAG siết)
4. Sinh trả lời (routing theo độ khó, streaming)
5. Kiểm tra + escalation nếu cần

Từng bước, kèm đòn bẩy tương ứng

Bước 1 — Cache (Bài 3).

if (hit := semantic_cache.lookup(q, threshold=0.93)):
    return stream(hit)   # 0 token model, ~50ms
Bắt ~20% câu lặp ý → cắt thẳng 20% chi phí và độ trễ nhóm đó.

Bước 2 — Phân loại intent bằng model nhỏ (Bài 4).

intent = call_llm("small", classify_prompt(q), "intent", tid)
tools  = select_tools(intent, ALL_TOOLS)   # tool gating (Bài 5)
Model nhỏ rẻ, và nhờ nó ta chỉ nạp 2–3 tool thay vì 20.

Bước 3 — Thu thập ngữ cảnh song song + RAG siết (Bài 5, 6).

docs, profile = await asyncio.gather(
    rag_search(q, top_k=3, rerank=True),
    get_profile(user_id),
)
history = build_context(session.history, k=6)  # cửa sổ + tóm tắt

Bước 4 — Sinh trả lời có routing + streaming (Bài 4, 6).

tier = "large" if intent in HARD else "medium"
msgs = fixed_prefix + [ctx(docs, profile, history), user(q)]  # prefix cache
resp = stream_llm(tier, msgs, "answer", tid)
Prefix cố định đặt đầu để hưởng prefix cache; phần động ở cuối.

Bước 5 — Kiểm tra + escalation (Bài 4).

if not passes_check(resp):
    resp = stream_llm("large", msgs, "answer_escalated", tid)
semantic_cache.store(q, resp)   # nuôi cache cho tương lai

Kết quả điển hình (minh họa)

Đòn bẩyCắt chi phíCắt p95 latency
Cache (20% hit)-20%-20% nhóm hit
Routing tầng-45%-30%
Tool gating + nén-25% inputnhẹ
Prefix cache-15% inputTTFT giảm
Song song hóa-35% bước ngữ cảnh
Tổng hợp (không cộng dồn tuyến tính vì chồng lấn): v1 đạt ~$0,015/lượt, p95 ~5s — rẻ hơn ~3x, nhanh hơn ~3x, kèm cổng chất lượng ở bước 5.

Các bước triển khai

  • Bắt đầu từ baseline có đo (Bài 1–2) — đừng tối ưu khi chưa có số.
  • Thêm một đòn bẩy mỗi lần, đo chi phí + chất lượng trước khi thêm cái kế.
  • Đặt cổng chất lượng ở mỗi thay đổi; rollback nếu tụt.
  • Ưu tiên theo ma trận ở Bài 1 (đánh ô đắt-chậm trước).
  • Ghi lại từng bước trong tracing để chứng minh cải thiện.

Khung tư duy: tối ưu là vòng lặp

Đo → Chọn đòn bẩy đắt nhất → Áp một thay đổi → Đo lại chất lượng+chi phí → Giữ hoặc rollback → Lặp.

Sai lầm thường gặp

  • Áp nhiều đòn bẩy cùng lúc → không biết cái nào giúp, cái nào hại.
  • Bỏ bước kiểm tra chất lượng → pipeline rẻ nhưng trả lời sai nhiều hơn.
  • Tối ưu bước rẻ trước → tốn công, ít tác động.
  • Không nuôi lại cache từ câu trả lời tốt → bỏ lỡ hit về sau.
  • Quên giới hạn số bước agent → một phiên lỗi có thể lặp vòng và đốt tiền không kiểm soát.
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