· 6 phút · Tác nhân

Ngăn vòng lặp tác tử tiêu tốn ngân sách API của bạn

Ngăn vòng lặp tác tử tiêu tốn ngân sách API của bạn

Tôi sẽ soạn trực tiếp bài viết, với các chiến thuật kỹ thuật cụ thể, bảng so sánh và ví dụ thực tế. Tôi sẽ bám sát hành vi thực tế của vòng lặp và các biện pháp kiểm soát chi phí, đồng thời bảo đảm bài viết kết thúc bằng những điểm đúc kết có thể áp dụng.## Cách nhanh nhất để đốt sạch ngân sách API

Tôi từng chứng kiến một tác nhân lập trình “đơn giản” biến yêu cầu 400 token của người dùng thành một khoản mục 28,000 token trên hóa đơn trong chưa đầy hai phút.

Kịch bản ấy quen thuộc đến mức đáng ngán: tác nhân gọi một công cụ tìm kiếm, tóm tắt kết quả, đọc lại bản tóm tắt của chính mình, gọi lại cùng công cụ đó với cách diễn đạt hơi khác, rồi mở rộng ngữ cảnh cho đến khi mỗi lượt đều mang theo toàn bộ cuộc trò chuyện, một nửa kho mã và hàng loạt kế hoạch thất bại. Mô hình không có vấn đề gì. Thiết kế vòng lặp mới là thứ có vấn đề.

Đó là vấn đề cốt lõi của các hệ thống tác nhân: chi phí không tăng theo câu lệnh của người dùng, mà tăng theo hành vi của vòng lặp. Chỉ một vòng lặp kém cũng có thể làm tăng gấp nhiều lần:

  • token đầu vào do ngữ cảnh ngày càng phình to,
  • token đầu ra do quá trình “suy nghĩ” dài dòng,
  • chi phí công cụ do các lần gọi lặp lại,
  • và độ trễ do các lần thử lại nối tiếp.

Nếu bạn đang xây dựng tác nhân cho môi trường vận hành thực tế, công việc thực sự không phải là “làm cho mô hình thông minh hơn”. Mà là “làm cho vòng lặp ít tốn kém hơn, ngắn hơn và khó vượt khỏi tầm kiểm soát hơn”.

Vì sao vòng lặp tác nhân làm chi phí tăng vọt

Một lượt trò chuyện thông thường có một đầu vào và một đầu ra. Vòng lặp tác nhân có một chuỗi như sau:

  1. người dùng đặt câu hỏi,
  2. mô hình lập kế hoạch,
  3. mô hình gọi công cụ,
  4. công cụ trả về dữ liệu,
  5. mô hình đọc dữ liệu,
  6. mô hình quyết định bước tiếp theo,
  7. lặp lại.

Mỗi lần lặp bổ sung token mới vào câu lệnh của lần lặp tiếp theo. Nếu bạn cứ nối thêm toàn bộ đầu ra của công cụ và các suy nghĩ trước đó, câu lệnh sẽ tăng dần theo dạng bậc thang.

Trong thực tế, điều đó tạo ra ba yếu tố làm chi phí tăng gấp nhiều lần:

  • Tích lũy ngữ cảnh: mỗi bước mang theo các bước trước đó.
  • Gọi công cụ liên tục: cùng một công cụ được gọi với các đối số hơi khác nhau.
  • Thử lại mất kiểm soát: mô hình cứ tiếp tục “thử thêm một cách nữa” dù đã làm đủ.

Một điểm dễ mắc phải là sự lãng phí token thường không thể thấy được cho đến khi bạn xem dấu vết của từng lần chạy. Câu trả lời cuối cùng có thể ngắn gọn, nhưng chuỗi xử lý ẩn có thể lớn hơn 10x so với đầu ra mà người dùng nhìn thấy.

Một mô hình chi phí đơn giản

Nếu một vòng lặp chạy N bước, mỗi bước có:

  • C token ngữ cảnh được mang theo,
  • I token đầu ra của công cụ được đưa trở lại,
  • O token đầu ra của mô hình,

thì tổng ước tính là:

total_tokens ≈ N * (C + I + O)

Đó là ước tính lạc quan, vì C thường tăng lên khi vòng lặp tiếp tục. Với một tác nhân thực tế, các lượt sau thường tốn kém nhất.

Những biện pháp kiểm soát thực sự quan trọng

Có một vài điểm bạn có thể tác động. Bí quyết là kết hợp chúng.

Biện pháp kiểm soátGiảm điều gìTrường hợp sử dụng phù hợp nhấtĐánh đổi
Giới hạn số bướcVòng lặp mất kiểm soátMọi tác nhân có dùng công cụCó thể dừng sớm với tác vụ khó
Cắt gọn ngữ cảnhToken đầu vàoTác vụ kéo dài nhiều bướcNguy cơ mất lịch sử hữu ích
Tác nhân phụ ít tốn kém hơnChi phí cho công việc thường lệTìm kiếm, trích xuất, phân loạiChi phí điều phối
Lưu kết quả công cụ vào bộ nhớ đệmChi phí gọi công cụ lặp lạiNguồn ổn định, truy vấn lặp lạiDữ liệu lỗi thời và việc vô hiệu hóa bộ nhớ đệm
Khả năng quan sát chi phíHóa đơn tăng bất ngờHệ thống vận hành thực tếCần triển khai cơ chế đo lường
Điều kiện dừng vòng lặpVòng lặp vô hạn hoặc gần như vô hạnTác nhân thiếu tin cậyPhải định nghĩa thế nào là “đủ tốt”

Những cấu hình hiệu quả nhất trong môi trường vận hành thực tế sử dụng tất cả các biện pháp này.

1) Siết chặt giới hạn số bước

Đây là cách khắc phục đơn giản nhất và bị đánh giá thấp nhất: nếu không đặt mức tối đa cứng, bạn đang tin rằng mô hình sẽ tự dừng.

Tôi thường bắt đầu với:

  • 3–5 bước cho các tác vụ có phạm vi hẹp,
  • 6–8 bước cho các tác vụ có độ phức tạp vừa phải,
  • chỉ tăng thêm khi có lý do thuyết phục.

Một giới hạn tốt không chỉ là van an toàn. Nó buộc tác vụ phải được chia nhỏ hợp lý hơn. Nếu tác nhân chỉ có bốn bước hành động, nó có xu hướng:

  • yêu cầu đúng công cụ sớm hơn,
  • tránh những hướng khám phá vòng vo,
  • và nhanh chóng đi đến câu trả lời dùng được.

Ví dụ về bộ điều khiển vòng lặp

MAX_STEPS = 5

for step in range(MAX_STEPS):
    action = model.next_action(state)

    if action.type == "final":
        return action.final_answer

    observation = run_tool(action.tool_name, action.arguments)
    state = update_state(state, action, observation)

raise RuntimeError("Agent stopped after step cap")

Một điểm dễ mắc phải: giới hạn số bước nên áp dụng cho toàn bộ kế hoạch, chứ không áp dụng độc lập cho từng chương trình con. Nếu không, bạn chỉ chuyển tình trạng bùng nổ chi phí từ tác nhân cấp cao nhất sang các thành phần hỗ trợ lồng bên trong.

2) Cắt gọn ngữ cảnh ở mỗi lượt

Hầu hết tác nhân mang theo quá nhiều lịch sử. Chúng không cần mọi phản hồi trước đó của công cụ, nhất là khi phản hồi dài nhưng chỉ có một chi tiết quan trọng.

Trong thực tế, tôi đạt kết quả tốt nhất với chính sách bộ nhớ nhiều lớp:

  • Giữ nguyên văn: yêu cầu của người dùng, mục tiêu hiện tại, các quyết định cuối cùng, những ràng buộc chưa được giải quyết.
  • Tóm tắt: suy luận trước đó, các hướng đã thử, đầu ra dài của công cụ.
  • Loại bỏ: các giả thuyết đi vào ngõ cụt, kết quả công cụ trùng lặp, các bản nháp trung gian cũ.

Những gì cần giữ lại

Một đối tượng trạng thái gọn nhẹ hiệu quả hơn việc đưa lại nguyên văn bản ghi hội thoại:

{
  "goal": "Find the failing endpoint and propose a fix",
  "constraints": [
    "No schema changes",
    "Must preserve backward compatibility"
  ],
  "known_facts": [
    "500s started after deploy 1842",
    "Only /v1/search is affected"
  ],
  "open_questions": [
    "Is the new cache layer returning stale payloads?"
  ],
  "step": 3
}

Cách này rẻ hơn nhiều so với việc đưa cho mô hình 20 lượt “suy nghĩ thành lời”.

Cách tinh gọn trong thực tế

Sử dụng ba bộ đệm:

  • working_set: lượt hiện tại, đầu ra của công cụ, kế hoạch đang thực hiện.
  • summary_memory: lịch sử đã nén.
  • archive: mọi thứ bạn có thể cần để kiểm tra sau này, nhưng không cần đưa vào ngữ cảnh của prompt.

Tác tử chỉ thấy working_set + summary_memory. Khi working_set trở nên quá lớn, hãy tóm tắt vào summary_memory.

Điểm dễ mắc phải ở đây là bản tóm tắt bị lệch ý. Nếu bộ tóm tắt làm mất thông tin, nó có thể xóa bỏ các ràng buộc và khiến tác tử lặp lại sai lầm. Tôi thường giữ riêng các dữ kiện có cấu trúc với các bản tóm tắt tự do để mô hình không phải suy ra chúng từ văn xuôi.

3) Dùng tác tử phụ rẻ hơn cho công việc đơn giản

Không phải bước nào cũng cần đến mô hình tốt nhất của bạn.

Nếu tác vụ là:

  • trích xuất các trường từ JSON,
  • phân loại một yêu cầu hỗ trợ,
  • kiểm tra xem một tệp có thay đổi hay không,
  • hoặc tạo một truy vấn tìm kiếm ngắn,

thì một mô hình nhỏ hơn, rẻ hơn thường là đủ. Hãy dành mô hình đắt tiền cho việc lập kế hoạch, tổng hợp và xử lý những điểm chưa rõ ràng.

Cách phân chia phổ biến

  • Tác tử chính: suy luận về tác vụ, quyết định khi nào cần dừng.
  • Tác tử phụ: thực hiện công việc có phạm vi hẹp như tìm kiếm, trích xuất hoặc chuẩn hóa.
  • Bộ xác minh: kiểm tra định dạng, tính đầy đủ hoặc các lỗi rõ ràng trong đầu ra.

Một kiến trúc thực tế:

User
  -> Orchestrator (strong model)
      -> Search agent (cheap model)
      -> Extract agent (cheap model)
      -> Final synthesis (strong model)

Vì sao cách này hiệu quả

Mô hình chính tập trung vào luồng điều khiển thay vì tự làm mọi việc. Tác tử phụ có thể được ràng buộc bằng prompt và áp dụng giới hạn token nghiêm ngặt.

Ví dụ về prompt cho một tác tử phụ tìm kiếm:

Return only:
1. the best search query,
2. 3 likely source categories,
3. no explanation.

Kiểu quy định có phạm vi hẹp như vậy giúp đầu ra ngắn gọn và dễ dự đoán.

Nếu nền tảng của bạn cung cấp quyền truy cập nhiều mô hình với chi phí hợp lý, đây chính là lúc lợi ích đó phát huy: một mô hình mạnh để điều phối, một mô hình rẻ hơn cho các tác vụ phụ lặp đi lặp lại, và không có lý do gì để tiêu tốn token cao cấp cho việc phân tích cú pháp thông thường.

4) Lưu kết quả công cụ vào bộ nhớ đệm một cách nghiêm túc

Các vòng lặp tác tử thường phải trả tiền nhiều lần cho cùng một thông tin:

  • đọc lại cùng một tệp,
  • tra cứu lại cùng một dữ liệu trong cơ sở dữ liệu,
  • lặp lại các tìm kiếm trên web,
  • lặp lại các lệnh gọi tạo embedding hoặc truy xuất.

Lưu đầu ra của công cụ vào bộ nhớ đệm là một trong những thay đổi mang lại hiệu quả đầu tư cao nhất mà bạn có thể thực hiện.

Dùng khóa ngữ nghĩa cho bộ nhớ đệm, thay vì văn bản thô

Bộ nhớ đệm dựa trên prompt thô sẽ không khớp nếu cách diễn đạt thay đổi đôi chút. Các khóa tốt hơn dựa trên ý định đã chuẩn hóa:

def cache_key(tool_name, args):
    normalized = normalize_args(args)
    return f"{tool_name}:{hash(normalized)}"

Ví dụ về một mục trong bộ nhớ đệm:

{
  "tool": "repo_search",
  "query": "auth middleware rate limit bug",
  "result": {
    "files": ["src/middleware/auth.py", "src/api/routes.py"],
    "ts": 1710001123
  }
}

Khi nào bộ nhớ đệm hữu ích nhất

  • Các tác tử khảo sát kho mã,
  • tìm kiếm tài liệu,
  • các kho tri thức ổn định,
  • các phép biến đổi có tính xác định,
  • truy xuất lặp lại trong các quy trình nhiều lượt.

Khi nào bộ nhớ đệm có thể gây bất lợi

  • dữ liệu thay đổi nhanh,
  • kết quả riêng cho từng người dùng,
  • bất kỳ nội dung nào có yêu cầu về độ cập nhật phụ thuộc vào thời gian.

Một điểm dễ mắc phải là lưu đầu ra của công cụ vào bộ nhớ đệm nhưng không cho tác tử biết mức độ cập nhật của dữ liệu. Nếu mô hình cho rằng nó nhận được dữ liệu trực tiếp trong khi thực tế là dữ liệu từ bộ nhớ đệm, nó có thể đưa ra quyết định sai. Hãy thêm dấu thời gian hoặc khoảng thời gian hiệu lực vào siêu dữ liệu của công cụ.

5) Đưa chi phí lên bảng điều khiển

Nếu chỉ theo dõi độ trễ và tỷ lệ thành công, bạn sẽ bỏ sót kiểu thất bại thực sự: thành công với chi phí quá cao.

Bạn cần khả năng quan sát từng lần chạy đối với:

  • token đầu vào,
  • token đầu ra,
  • các lệnh gọi công cụ,
  • độ trễ của công cụ,
  • tổng chi phí,
  • số bước,
  • lý do dừng.

Lược đồ sự kiện tối thiểu

{
  "run_id": "r_8f2c",
  "step": 4,
  "model": "gpt-5.5",
  "input_tokens": 1842,
  "output_tokens": 221,
  "tool_name": "repo_search",
  "tool_latency_ms": 312,
  "estimated_cost_usd": 0.087,
  "stop_reason": "step_cap"
}

Những gì cần theo dõi trong thực tế

  • Số token cho mỗi tác vụ thành công: chỉ báo chi phí rõ ràng nhất.
  • Số token mỗi bước: giúp phát hiện prompt phình to.
  • Các lệnh gọi công cụ lặp lại: thường là lỗi lập kế hoạch.
  • Phân bố lý do dừng: nếu nhiều lần chạy kết thúc do chạm giới hạn, tác tử của bạn chưa lập kế hoạch đủ kỹ.

Một trong những biểu đồ hữu ích nhất là chi phí theo loại tác vụ. Một số loại đương nhiên sẽ tốn kém. Điều đó không sao. Điều bạn cần phát hiện là những tác vụ đáng lẽ ít tốn kém nhưng thực tế lại không như vậy.

6) Dừng sớm các vòng lặp mất kiểm soát

Một vòng lặp cần có nhiều lý do để dừng hơn là chỉ “đã chạm giới hạn số bước”.

Các điều kiện dừng hữu ích gồm:

  • mô hình đã tạo ra câu trả lời cuối cùng,
  • cùng một lệnh gọi công cụ lặp lại mà không có thông tin mới,
  • mức thay đổi về độ tin cậy hoặc độ hữu ích thấp hơn ngưỡng,
  • bộ xác minh xác nhận tác vụ đã được giải quyết,
  • kế hoạch không còn tiến triển.

Ví dụ về cơ chế ngắt vòng lặp

seen_calls = set()

for step in range(MAX_STEPS):
    action = model.next_action(state)
    signature = (action.tool_name, canonicalize(action.arguments))

    if signature in seen_calls:
        return fail("repeated tool call with no new information")
    seen_calls.add(signature)

    observation = run_tool(action.tool_name, action.arguments)
    state = update_state(state, action, observation)

    if verifier_says_done(state):
        return finalize(state)

Cách này phát hiện một kiểu thất bại rất phổ biến: mô hình “muốn giúp ích” và cứ diễn đạt lại cùng một truy vấn.

Một cơ chế bảo vệ hữu ích khác: kiểm soát việc tiếp tục theo độ hữu ích

Nếu một bước không làm trạng thái thay đổi đủ nhiều, đừng tiếp tục. Điều đó có thể đơn giản là:

  • không tìm thấy tệp mới,
  • không trích xuất được thực thể mới,
  • độ tin cậy của câu trả lời không cải thiện,
  • không bổ sung được bằng chứng mới.

Chỉ số cụ thể tùy thuộc vào tác vụ, nhưng nhất thiết phải có một cách đánh giá lợi ích tăng thêm.

Điều gì thực sự xảy ra khi bạn tinh chỉnh tốt

Khi bạn kiểm soát vòng lặp chặt chẽ hơn, tác tử thường cải thiện theo những cách ban đầu dễ bị bỏ qua:

  • Nó ít dài dòng hơn và quyết đoán hơn.
  • Nó yêu cầu đúng công cụ sớm hơn.
  • Nó tạo ra ít chu kỳ “Tôi vẫn đang tìm hiểu” hơn.
  • Nó trở nên ít tốn kém hơn và nhanh hơn vì ít lượt hơn đồng nghĩa với ít ngữ cảnh hơn và độ trễ thấp hơn.

Sự đánh đổi quan trọng là các giới hạn cứng và việc tinh gọn mạnh tay có thể khiến hệ thống kém linh hoạt khi gặp những tác vụ thực sự khó. Vì vậy, đừng giả vờ rằng tác tử đang “giải quyết” những vấn đề mà thực ra nó chỉ đang hết thời gian xử lý. Hãy phản ánh điều đó trung thực trong nhật ký và các thông báo hiển thị cho người dùng.

Nguyên tắc thực tế của tôi: ưu tiên năng lực trong phạm vi giới hạn hơn việc dò dẫm không hồi kết.

Một cấu hình thực tế cho môi trường sản xuất

Nếu phải đưa một tác nhân vào vận hành ngay ngày mai, tôi sẽ bắt đầu với:

  • MAX_STEPS = 5
  • trạng thái có cấu trúc, thay vì phát lại toàn bộ lịch sử hội thoại
  • bộ nhớ tóm tắt sau mỗi lượt
  • các tác nhân phụ chi phí thấp để tìm kiếm và trích xuất
  • bộ nhớ đệm kết quả công cụ kèm siêu dữ liệu về độ mới
  • ghi nhật ký token và chi phí cho từng lần chạy
  • bộ phát hiện lệnh gọi lặp lại
  • lý do dừng rõ ràng

Cấu hình đó không hào nhoáng, nhưng chính nó giúp hóa đơn không tăng nhanh hơn sản phẩm.

Những điểm thực tiễn cần ghi nhớ

  • Giới hạn số bước trước tiên; đây là biện pháp ít tốn kém nhất để ngăn các vòng lặp mất kiểm soát.
  • Cắt giảm mạnh ngữ cảnh và giữ trạng thái có cấu trúc tách biệt với các bản tóm tắt.
  • Dùng các tác nhân phụ rẻ hơn cho những tác vụ có phạm vi hẹp, thay vì dùng token cao cấp ở mọi nơi.
  • Lưu vào bộ nhớ đệm các đầu ra công cụ có thể tái sử dụng, nhưng hiển thị độ mới để mô hình không tin tưởng mù quáng vào dữ liệu cũ.
  • Ghi nhật ký chi tiêu theo từng lần chạy, từng bước và từng lệnh gọi công cụ để phát hiện ngay các trường hợp chi phí tăng ngoài dự kiến.
  • Dừng vòng lặp khi có sự lặp lại, không tiến triển hoặc đã xác minh hoàn thành — không chỉ khi cạn ngân sách.
  • Thiết kế để đạt năng lực trong phạm vi giới hạn: đủ tốt, nhanh và dễ dự đoán luôn hiệu quả hơn thông minh nhưng đắt đỏ.
A

AI Prime Tech xuất bản blog này. Các bài viết được soạn với sự hỗ trợ của AI; hãy đối chiếu những chi tiết phụ thuộc vào phiên bản như ID mô hình, giá và giới hạn với tài liệu chính thức trước khi dựa vào chúng.

Truy cập Claude API với chi phí thấp hơn

Một khóa API cho Claude Opus 5.5, Sonnet 5, Haiku 4.5 và Fable 5.1, cùng GPT-6 mô hình. Thanh toán theo mức sử dụng, không cần đăng ký thuê bao.

Nhận khóa API của bạn →
AI Prime Tech là cổng API bên thứ ba độc lập. Claude™ và Anthropic® là các nhãn hiệu của Anthropic, PBC. Không hàm ý có sự liên kết hay chứng thực.