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 — Bộ nhớ chung, chống trôi context và kiểm soát chi phí

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

Đội càng lớn, quản lý thông tin và ngân sách càng quan trọng

Khi có 4 agent chạy qua nhiều task, hai vấn đề nảy sinh: (1) thông tin bị trôi — agent quên ràng buộc từ task trước; (2) chi phí phình to — mỗi lượt gọi nhồi cả lịch sử dài. Bài này bàn cách xây bộ nhớ chung gọn và kiểm soát token.

Ba tầng thông tin

Tách rõ thông tin thành ba tầng, chỉ nạp đúng thứ mỗi agent cần:

  • Bất biến (project memory): quy ước code, kiến trúc, tiêu chuẩn bảo mật. Ngắn, ổn định, đưa vào system prompt.
  • Trạng thái task (shared board): task nào xong, diff hiện tại, issue mở. Dạng cấu trúc, cập nhật liên tục.
  • Ngữ cảnh tức thời: chỉ diff + issue của task đang làm. Vứt bỏ sau khi xong.
{
  "project_memory": {"lang":"python","style":"pep8","rule":"no plaintext secret"},
  "board": {
    "T1": {"status":"done"},
    "T2": {"status":"in_review","open_issues":1}
  }
}

Nguyên tắc chống trôi context

  • Không truyền toàn bộ lịch sử chat. Truyền bản tóm tắt trạng thái từ board.
  • Tóm tắt sau mỗi task: ghi lại quyết định quan trọng ("đã chọn hash bằng bcrypt") vào memory để task sau không mâu thuẫn.
  • Neo lại ràng buộc trong mỗi prompt quan trọng (nhắc lại 2-3 rule cốt lõi), vì agent dễ quên khi context dài.

Các bước xây bộ nhớ chung

  • Tạo một "board" dạng JSON/DB lưu trạng thái mọi task.
  • Viết hàm context_for(role, task) chỉ trả về đúng thông tin vai trò cần.
  • Sau mỗi task, chạy một bước tóm tắt: cập nhật memory bằng quyết định mới.
  • Đặt ngân sách token cho mỗi task; nếu vượt, dừng và escalate.
  • Đo và log token theo từng vai trò để biết ai "ngốn" nhất.
def context_for(role, task, board, memory):
    base = memory["project_memory"]
    if role == "coder":
        return {"rules": base, "task": task, "feedback": task.get("issues")}
    if role == "reviewer":
        return {"rules": base, "task": task, "diff": board[task["id"]]["diff"]}
    ...

Kiểm soát chi phí

  • Dùng model rẻ cho vai trò dễ, model mạnh cho vai trò khó: ví dụ Reviewer/Planner cần suy luận sâu dùng model mạnh; định dạng/tóm tắt dùng model rẻ.
  • Cache phần bất biến: project memory giống nhau mọi lượt → tận dụng prompt caching.
  • Giới hạn độ dài diff truyền đi; nếu quá lớn, đó là dấu hiệu task chia chưa đủ nhỏ (quay lại Bài 4).

Khung tư duy: "Agent này cần biết TỐI THIỂU những gì?"

Với mỗi lượt gọi, liệt kê thông tin thật sự cần để hành động, rồi cắt phần còn lại. Context tối thiểu = rẻ hơn, nhanh hơn, ít trôi hơn.

Sai lầm thường gặp

  • Nhồi toàn bộ lịch sử vào mỗi lượt gọi: chi phí bùng nổ, chất lượng giảm vì nhiễu.
  • Không tóm tắt quyết định: task sau mâu thuẫn task trước (task 2 dùng bcrypt, task 5 lại dùng md5).
  • Dùng model mạnh nhất cho mọi vai trò: đốt tiền vô ích ở việc dễ.
  • Không đo token theo vai trò: không biết tối ưu ở đâu.
  • Diff quá lớn: dấu hiệu Planner chia task chưa đạt, cần quay lại sửa gốc.
<!--les-append-->

Trôi context: dấu hiệu nhận ra trước khi nó gây hại

Trôi context không thông báo. Bốn dấu hiệu cụ thể:

Dấu hiệuVí dụ
Agent mâu thuẫn quyết định cũTask 2 dùng bcrypt, task 5 dùng md5
Agent hỏi lại điều đã được trả lời"Dự án dùng framework nào?" ở task thứ tám
Chất lượng giảm khi task về sauTask 1–3 tốt, task 7–9 lệch quy ước
Chi phí mỗi task tăng dầnDấu hiệu lịch sử đang bị nhồi vào mỗi lượt
Dấu hiệu cuối là dấu hiệu đo được và nó thường xuất hiện sớm nhất. Nếu token mỗi task tăng đều theo số task đã làm, bạn đang truyền toàn bộ lịch sử — và cả chi phí lẫn chất lượng sẽ xấu đi cùng nhau.

Sổ quyết định: cấu trúc tối thiểu

"Tóm tắt sau mỗi task" cần một hình thức cố định, kẻo nó thành một khối văn bản không ai đọc được. Bốn cột:

CộtVí dụ
Quyết địnhBăm mật khẩu bằng bcrypt, cost 12
Vì saoChuẩn của đội; argon2 chưa có trong môi trường
Phạm vi ràng buộcMọi chỗ xử lý mật khẩu
Task nào quyếtT-02
Cột "vì sao" là cột giữ cho sổ này không bị ghi đè bởi một agent sau này nghĩ khác. Không có nó, task 5 sẽ đổi sang md5 và không ai thấy lý do phản đối.

Sổ này nên ngắn và có giới hạn cứng — ví dụ tối đa 30 dòng. Khi đầy, phải hợp nhất, không được nối thêm. Một sổ quyết định 300 dòng bằng với không có sổ, vì nó không vào được prompt.

Chọn model theo vai trò: bảng cụ thể

Vai tròModelVì sao
Planner, ReviewerMạnhSuy luận nhiều bước, đánh đổi kiến trúc
CoderTrung–mạnhCần đúng, nhưng có test làm lưới
TesterTrungSinh test theo mẫu
Định tuyến, phân loại, tóm tắtRẻViệc cơ học, có thể kiểm bằng cấu trúc
Hàng cuối thường chiếm nhiều lượt gọi nhất và tốn ít nhất — nên đây là chỗ tiết kiệm lớn nhất, và nó không đổi chất lượng. Đo token theo vai trò là điều kiện để biết mình đang đốt tiền ở đâu; không có con số đó, mọi tối ưu là đoán.

Diff quá lớn là một tín hiệu về Planner

Nhấn lại ý ở cuối bài vì nó là ý dễ bỏ: nếu diff của một task lớn tới mức phải cắt bớt khi truyền đi, vấn đề không ở tầng ngữ cảnh. Nó ở Planner — task chia chưa đủ nhỏ.

Đặt một ngưỡng cứng và coi việc vượt ngưỡng là lỗi của bước lập kế hoạch: "Task nào cho diff trên 300 dòng được trả về Planner để chia lại, không được xử lý bằng cách nén ngữ cảnh." Nén ngữ cảnh ở đây là chữa triệu chứng, và nó làm Reviewer đánh giá trên thông tin thiếu. <!--/les-append-->

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