Product Management
Đăng nhập
ESC

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

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

Bài 6 — Agent ngang hàng, song song và tổng hợp kết quả

Đã đọc 0/10 mục · còn khoảng 4 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.

Không phải hệ nào cũng cần một ông sếp. Đôi khi cách nhanh và mạnh hơn là để nhiều agent chạy song song rồi tổng hợp — hoặc để chúng tranh luận để lọc ra câu trả lời tốt hơn. Bài này bàn về tô-pô ngang hàng (peer) và mẫu fan-out/fan-in.

Fan-out / fan-in (phân tán rồi gom)

Ý tưởng: chia việc thành các phần độc lập, tung cho nhiều worker chạy đồng thời, rồi một agent aggregator gom lại. Đây là nơi multi-agent thắng đậm về tốc độ.

              +--> Worker A (mục 1) --+
Splitter -----+--> Worker B (mục 2) --+--> Aggregator --> kết quả
              +--> Worker C (mục 3) --+

Điều kiện áp dụng: các phần thực sự độc lập (không phần này cần đầu ra phần kia). Nếu có phụ thuộc, buộc phải tuần tự hoặc chia lại.

Ví dụ cụ thể: chấm 50 hồ sơ ứng viên

Mỗi hồ sơ chấm độc lập. Thay vì một agent chạy 50 lần tuần tự (rất chậm), tung 50 lời gọi song song, mỗi cái trả điểm + lý do, rồi aggregator xếp hạng.

import asyncio

async def score_all(cvs, rubric):
    tasks = [scorer.run(cv, rubric) for cv in cvs]   # fan-out
    results = await asyncio.gather(*tasks)            # chạy song song
    return aggregator.rank(results)                   # fan-in

Độ trễ giảm từ ~50x xuống ~1x (giới hạn bởi rate limit). Đây là lợi ích không thể có với một agent tuần tự.

Mẫu tranh luận (debate) / bỏ phiếu

Cho 3 agent độc lập cùng giải một bài, rồi:

  • Bỏ phiếu đa số (self-consistency): lấy đáp án xuất hiện nhiều nhất — mạnh cho bài có đáp án rời rạc.
  • Tranh luận: mỗi agent thấy đáp án của người khác và phản biện, một judge chọn lập luận tốt nhất — mạnh cho bài mở, cần lý lẽ.
Điểm cốt lõi: các agent phải độc lập ở lượt đầu, nếu không chúng hùa theo nhau (groupthink) và mất lợi ích đa dạng.

Khung tư duy: chọn tô-pô

Các phần độc lập, cần TỐC ĐỘ?          -> fan-out/fan-in
Bài khó, cần ĐỘ TIN CẬY cao?           -> bỏ phiếu / tranh luận
Cần điều phối THÍCH ỨNG theo kết quả?  -> supervisor (bài 4)
Quy mô lớn, nhiều lĩnh vực?            -> phân cấp (bài 5)

Các bước triển khai fan-out/fan-in

  • Xác nhận các phần độc lập thật (vẽ đồ thị phụ thuộc).
  • Viết Splitter chia việc thành các đơn vị đồng nhất.
  • Chạy worker song song có giới hạn đồng thời để không vượt rate limit.
  • Thiết kế schema kết quả để aggregator gom được.
  • Viết Aggregator: gộp/xếp hạng/khử trùng lặp/xử lý phần lỗi.
  • Xử lý lỗi cục bộ: một worker fail không được kéo sập cả mẻ.

Checklist

  • [ ] Đã xác nhận tính độc lập trước khi song song hóa.
  • [ ] Có giới hạn đồng thời + retry theo rate limit.
  • [ ] Aggregator xử lý được kết quả thiếu/lỗi.
  • [ ] Với debate/vote: agent độc lập ở lượt đầu.

Sai lầm thường gặp

  • Song song hóa việc có phụ thuộc. Worker B cần output của A nhưng chạy cùng lúc → B nhận dữ liệu rỗng/sai.
  • Quên giới hạn đồng thời. Tung 200 request cùng lúc → dính rate limit, hàng loạt fail.
  • Aggregator ngây thơ. Chỉ nối chuỗi kết quả, không khử trùng lặp hay xử lý phần lỗi.
  • Debate mà agent thấy nhau ngay từ đầu. Chúng hùa theo, mất đa dạng, vô ích.

Thiết kế Aggregator không ngây thơ

Aggregator là mắt xích quyết định chất lượng đầu ra của fan-in, nhưng hay bị làm qua loa. Một aggregator tốt phải xử lý được bốn tình huống: (1) trùng lặp — hai worker trả cùng một ý, cần khử; (2) mâu thuẫn — hai worker trả kết quả trái nhau, cần chọn theo confidence hoặc đánh dấu để người xem; (3) phần lỗi — một worker fail, không được kéo sập cả mẻ; (4) xếp hạng — gộp theo tiêu chí rõ ràng.

def aggregate(results):
    ok = [r for r in results if r.get("status") == "ok"]
    failed = [r for r in results if r.get("status") != "ok"]
    deduped = dedupe_by_key(ok, key="claim")
    ranked = sorted(deduped, key=lambda r: r["confidence"], reverse=True)
    return {"ranked": ranked, "skipped": len(failed)}

Cầm skipped báo cho người dùng biết có phần bị bỏ qua thay vì lặng lẽ trả kết quả thiếu — minh bạch quan trọng hơn giả vờ hoàn hảo.

Xử lý lỗi cục bộ trong mẻ song song

Khi tung 50 lời gọi song song, gần như chắc chắn vài cái sẽ fail (rate limit, timeout). Dùng cơ chế thu kết quả chịu lỗi (ví dụ gather với return_exceptions) rồi retry riêng phần fail với backoff, thay vì để một exception làm hỏng cả gather. Nguyên tắc: lỗi cục bộ phải ở lại cục bộ.

Bài 7 bước vào vận hành: quan sát (observability), chi phí và độ trễ của hệ multi-agent trong thực 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