Product Management
Đăng nhập
ESC

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

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

Bài 5 — Nén prompt & quản lý context: trả ít token hơn cho cùng kết quả

Đã đọc 0/9 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.

Input token là chi phí lặp lại mỗi lượt, và với agent nhiều bước nó nhân lên chóng mặt. Nén prompt là cắt phần thừa mà không làm mất thông tin model cần. Đây là kỹ thuật tinh tế: cắt quá tay thì chất lượng rơi, cắt không đủ thì phí tiền.

Nguồn phình to của prompt

  • System prompt dài dòng: hướng dẫn lặp, ví dụ thừa.
  • Tool schema cồng kềnh: 20 tool luôn gửi kèm dù lượt này chỉ cần 2.
  • Lịch sử hội thoại: chồng chất theo thời gian, đa phần không còn liên quan.
  • RAG nhồi nhét: top-20 đoạn tài liệu trong khi 3 đoạn đã đủ.

Chiến lược nén (từ an toàn tới quyết liệt)

  • Cắt phần thừa hiển nhiên: bỏ lời chào, đoạn lặp, ví dụ dư trong system prompt. Rủi ro thấp.
  • Tool gating: chỉ nạp tool liên quan tới intent hiện tại, không gửi cả 20 tool.
  • Cửa sổ lịch sử + tóm tắt: giữ N lượt gần nhất nguyên văn, tóm tắt phần cũ thành vài dòng.
  • Siết RAG: giảm top-k, rerank để giữ đoạn thật sự liên quan, cắt ngắn mỗi đoạn.
  • Nén ngữ nghĩa: dùng model nhỏ (hoặc thuật toán) rút gọn tài liệu dài trước khi đưa vào model chính.

Ví dụ: cửa sổ trượt + tóm tắt

def build_context(history, k=6):
    recent = history[-k:]                 # giữ nguyên văn
    old = history[:-k]
    if old:
        summary = summarize_small(old)    # model nhỏ, rẻ
        return [{"role": "system",
                 "content": f"Tóm tắt trước đó: {summary}"}] + recent
    return recent

Một hội thoại 40 lượt (12.000 token lịch sử) có thể co còn ~2.500 token: 6 lượt gần + 1 đoạn tóm tắt, mà agent vẫn nhớ ngữ cảnh chính.

Tool gating

def select_tools(intent, all_tools):
    mapping = {"order": ["get_order", "cancel_order"],
              "billing": ["get_invoice", "refund"]}
    names = mapping.get(intent, ["handoff_human"])
    return [t for t in all_tools if t.name in names]

Gửi 2 tool thay vì 20 có thể cắt vài nghìn token input mỗi lượt.

Các bước triển khai

  • Đo tỉ trọng token của từng phần prompt (system / tool / history / RAG) — thường một phần chiếm áp đảo.
  • Cắt phần thừa hiển nhiên trước rồi đo lại.
  • Bật tool gating theo intent.
  • Áp cửa sổ + tóm tắt cho lịch sử dài.
  • Siết RAG: hạ top-k, thêm rerank, cắt độ dài đoạn.
  • Kiểm định chất lượng sau mỗi bước (đừng nén nhiều thứ cùng lúc rồi không biết cái nào làm hỏng).

Khung tư duy: "Model có thật sự dùng đoạn này không?"

Với mỗi khối token, hỏi: nếu bỏ nó đi, câu trả lời có sai không? Nếu không sai → cắt. Ưu tiên cắt theo tỉ trọng token × mức độ ít-liên-quan.

Sai lầm thường gặp

  • Nén hết cỡ ngay từ đầu → mất thông tin quan trọng, chất lượng rơi mà không biết vì đâu.
  • Tóm tắt bằng model đắt → phần tiết kiệm bị chi phí tóm tắt ăn mất; hãy dùng model nhỏ.
  • Cắt lịch sử làm mất ràng buộc quan trọng (yêu cầu "luôn trả lời tiếng Việt" nói ở lượt 1) → giữ các ràng buộc dai dẳng trong system, đừng để trôi khỏi cửa sổ.
  • Giảm top-k RAG mà không rerank → bỏ nhầm đoạn liên quan nhất.
  • Quên rằng nén phần đầu phá prefix cache: nếu bạn đang cache prefix, đừng thay đổi phần cố định mỗi lượt chỉ để nén vài token.

Ví dụ đo tỉ trọng token

Trước khi nén, hãy 'mổ' một prompt điển hình để biết cắt đâu cho đáng. Ví dụ một lượt 8.000 token có thể phân bố: system 1.500, tool schema 2.500, lịch sử 3.000, RAG 1.000. Ở đây tool schema và lịch sử chiếm áp đảo — nên tool gating và cửa sổ+tóm tắt sẽ mang lại nhiều nhất, còn việc gọt system 1.500 token là công sức nhỏ đổi lại lợi ích nhỏ. Luôn nén theo tỉ trọng, đừng nén theo cảm giác 'chỗ nào trông dài'.

def token_breakdown(parts, count):
    return {name: count(text) for name, text in parts.items()}
# In ra để xếp hạng phần nào đáng nén trước

Sau mỗi bước nén, chạy lại eval golden set (Bài 8) để chắc chắn bạn chỉ cắt phần dư thừa, không cắt vào thông tin model thực sự cần.

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