Blog

Giữ các lượt agent dài trong cửa sổ ngữ cảnh

Một model chỉ đọc được một lượng nhất định trong một lần — đó là cửa sổ ngữ cảnh của nó. Agent của Mythex làm các công việc dài: đọc nhiều file, chạy lệnh, giao các việc có giới hạn cho sub-agent. Chúng tôi phát hiện ba cách khiến công việc dài bị hỏng: sub-agent phình to đến mức model từ chối mọi request, một sub-agent dừng sớm vì nó nghĩ mình đã hết chỗ, và cách đếm token của chúng tôi sai rất nhiều với văn bản tiếng Nga, tiếng Trung và tiếng Nhật. Dưới đây là những gì chúng tôi đã thay đổi.

Một vài thuật ngữ trước

  • Token là các đoạn mà model đọc. Giới hạn và chi phí được tính theo token, không phải theo ký tự hay từ.
  • Cửa sổ ngữ cảnh là lượng tối đa model có thể đọc trong một request. Chúng tôi cũng đặt một ngân sách thấp hơn cho mỗi request, để chi phí và tốc độ ở mức hợp lý.
  • Kết quả công cụ là những gì agent nhận lại từ các công cụ của nó: nội dung của một file nó đã đọc, đầu ra của một lệnh nó đã chạy. Trong các công việc dài, chúng chiếm phần lớn những gì được gửi đi.
  • Sub-agent là một trợ lý mà agent chính khởi động cho một việc độc lập, chẳng hạn “đối chiếu các chương này với ghi chú”. Nó nhận một chỉ dẫn, rồi tự làm việc qua nhiều lần gọi công cụ.

Vấn đề 1: sub-agent phình to đến mức model từ chối

Mỗi bước, agent gửi cho model phần hội thoại đến lúc đó. Khi phần này quá lớn, code của chúng tôi sẽ cắt bớt — nhưng chỉ ở đầu một tin nhắn người dùng, để một lần gọi công cụ và kết quả của nó không bao giờ bị tách rời. Nó giữ lại tin nhắn đầu tiên, thêm một ghi chú rằng hội thoại trước đó đã bị cắt bớt, và giữ các lượt mới nhất còn nguyên vẹn vừa khít.

Một sub-agent chỉ có đúng một tin nhắn người dùng: chỉ dẫn của nó. Không có chỗ nào để cắt. Vì vậy nó gửi toàn bộ lịch sử của mình ở mỗi bước, và lịch sử cứ lớn dần, cho đến khi request lớn hơn mức model chấp nhận — khoảng một triệu token. Trong một bài kiểm thử với 8 sub-agent như vậy, cả 8 đều bị từ chối.

Cách sửa: xóa các kết quả công cụ cũ trước

Giờ các request được đưa vào ngân sách theo ba bước, mỗi bước chỉ thử khi bước trước chưa đủ:

  1. Xóa các kết quả công cụ cũ nhất. Nội dung của chúng được thay bằng một ghi chú ngắn: kết quả đã bị xóa để giữ hội thoại trong ngữ cảnh của model, và agent có thể chạy lại công cụ nếu cần. Một file được đọc từ một giờ trước thường là thứ lớn nhất và ít hữu ích nhất trong request, và file vẫn còn đó để đọc lại. Các kết quả mới nhất vẫn nguyên vẹn.
  2. Giữ nguyên các lượt người dùng. Như trước: tin nhắn đầu tiên, một ghi chú, và các lượt đầy đủ mới nhất vừa khít.
  3. Giữ nguyên các vòng công cụ. Bên trong một lượt dài — loại duy nhất mà sub-agent có — giữ tin nhắn đầu tiên, một ghi chú, và các vòng “gọi một công cụ, nhận kết quả” đầy đủ mới nhất.

Chỉ có phần gửi đi bị thay đổi hình dạng. Lịch sử đã lưu của agent vẫn giữ mọi thứ. Trong cùng bài kiểm thử, 0 trên 8 bị từ chối và cả 8 đều hoàn thành.

Xóa theo lô, để bộ nhớ đệm vẫn hoạt động

Các nhà cung cấp model có thể tái sử dụng công việc ở phần đầu của một request nếu nó giống hệt request trước — một prefix cache. Nếu chúng tôi xóa thêm một kết quả ở mỗi lần gọi, phần đầu của request sẽ thay đổi ở mỗi lần gọi và cache sẽ không bao giờ giúp được gì.

Vì vậy, các kết quả cũ nhất được xóa bốn cái một lần, không phải từng cái. Phần đã xóa khi đó giữ nguyên qua nhiều lần gọi. Một kết quả không lớn hơn ghi chú bao nhiêu sẽ được giữ nguyên: xóa nó chỉ tiết kiệm được gần như không có gì mà vẫn làm thay đổi phần đầu của request. Mức nào được giữ nguyên được quyết định theo kích thước chứ không theo số lượng: các kết quả mới nhất vừa trong một phần tư ngân sách được giữ lại, và luôn ít nhất một kết quả. Một phiên bản trước giữ cố định sáu kết quả nguyên vẹn, điều này đúng với đầu ra lệnh ngắn nhưng, với các lần đọc file dài, lại để phần lớn ngân sách cho các kết quả cũ.

Từ chối giờ được nói rõ

Một request mà model từ chối là không hợp lệ sẽ không còn được thử lại; gửi lại đúng request đó sẽ nhận đúng câu trả lời như cũ. Nếu hội thoại quá dài với model, người dùng sẽ thấy: “Cuộc trò chuyện này đã quá dài để model đọc trong một lần. Hãy bắt đầu một chat mới cho bước tiếp theo — mọi thứ đã xây dựng vẫn được giữ lại.” Đây là việc của người dùng để xử lý, không phải một sự cố, nên nó không gửi cảnh báo cho chúng tôi.

Vấn đề 2: agent dừng lại để “tiết kiệm chỗ”

Một sub-agent được yêu cầu đọc 40 chương dài đã dừng lại sau 2 chương, nói rằng nó muốn tiết kiệm chỗ. Nó đã dùng khoảng 100.000 token trên ngân sách 400.000 token.

Nó không có cách nào biết rằng các kết quả cũ sẽ được xóa để nhường chỗ cho nó. Vì vậy chúng tôi đã nói cho nó biết. Chỉ dẫn của agent giờ nói rằng khi một hội thoại phình ra vượt quá những gì model có thể nhận, các kết quả công cụ cũ nhất sẽ bị xóa và các kết quả mới nhất được giữ nguyên — vì vậy đừng dừng một tác vụ dài để tiết kiệm chỗ; hãy tiếp tục, và đọc lại một file nếu bạn cần nội dung đã bị xóa.

Một bản sửa mà model không thể thấy thì không phải là bản sửa theo quan điểm của model. Cơ chế chỉ có ích khi agent tin tưởng nó.

Vấn đề 3: đếm token như thể mọi thứ đều là tiếng Anh

Chúng tôi ước lượng token mà không chạy bộ tokenizer, bằng cách lấy số ký tự chia cho bốn. Đó là quy tắc kinh nghiệm hợp lý cho tiếng Anh. Nhưng nó không đúng với các hệ chữ viết khác: tiếng Nga khoảng 2,2 ký tự mỗi token, còn tiếng Trung hay tiếng Nhật khoảng một ký tự mỗi token.

Vì vậy, một sub-agent đọc các chương tiếng Nga đã gửi một request khoảng 640.000 token, trong khi ước lượng của chúng tôi nói rằng nó dưới ngân sách 400.000. Ước lượng đó cũng có thể đẩy một request vượt qua giới hạn cứng của model.

Giờ ước lượng đếm theo hệ chữ viết: ASCII thuần là bốn ký tự mỗi token, tiếng Trung, tiếng Nhật và tiếng Hàn là một ký tự mỗi token, và mọi thứ khác — chữ Cyrillic, Hy Lạp, Ả Rập, chữ có dấu, emoji — là hai ký tự mỗi token. Cách này được thiết kế để ước lượng cao hơn một chút. Với một chương tiếng Nga, nó ước lượng 43.423 token so với khoảng 44.600 đo được; trước đây, nó cho ra 25.023. Vì một message không thay đổi sau khi được viết, ước lượng của nó chỉ được tính một lần và ghi nhớ, thay vì tính lại ở mỗi bước.

Chúng tôi rút ra điều gì

  • Cắt bớt đúng nơi kích thước thực sự nằm. Trong công việc của agent, đó là kết quả công cụ, không phải tin nhắn người dùng.
  • Hãy cho agent biết về các lưới an toàn của chính nó. Nếu không, nó sẽ lên kế hoạch dựa trên những giới hạn không còn áp dụng nữa.
  • “Ký tự chia 4” là một giả định của tiếng Anh. Bất cứ thứ gì đếm token cho người dùng đa ngôn ngữ đều cần đếm theo hệ chữ viết, hoặc dùng một tokenizer thật.
  • Chú ý bộ nhớ đệm. Một request thay đổi ở phần đầu trong mỗi lần gọi sẽ tốn nhiều hơn và chạy chậm hơn.

Nếu bạn đang đưa tính năng AI vào app của riêng mình, các hướng dẫn về LLM là gì và cách dùng API LLM đề cập đến cửa sổ ngữ cảnh và token ngay từ đầu. Thêm về cách sub-agent hoạt động trong Mythex có trong tài liệu sub-agent.

Mythex · Pricing · Xây dựng mọi thứ với AI · Mẫu website và ứng dụng · So sánh Mythex · Thuật ngữ xây dựng ứng dụng bằng AI · Công cụ miễn phí để xây dựng ứng dụng bằng AI · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو 简体中文 繁體中文(香港) 繁體中文(台灣)