Blog

Lỗi hết bộ nhớ ẩn trong một nhãn tiến trình

Một buổi tối cuối tháng 9, agent AI trong một không gian làm việc của người dùng bị crash với lỗi hết bộ nhớ giữa chừng một lượt. Hai nghi phạm hiển nhiên — quá nhiều sub-agent chạy cùng lúc, hoặc ngữ cảnh đã phình quá lớn — đều sai. Nguyên nhân thật là một nhãn trạng thái: trong khi mô hình truyền một lệnh shell lớn từng vài ký tự, chúng tôi gửi lại toàn bộ lệnh cho đến lúc đó làm nhãn tiến trình trên mỗi đoạn. Một lệnh 124 KB trở thành khoảng 41.000 sự kiện và khoảng 690 MB chuỗi nằm trong hàng đợi.

Agent truyền công việc của nó như thế nào

Khi bạn xây trên Mythex, agent chạy bên trong sandbox đám mây riêng của dự án. Khi mô hình viết, đầu ra của nó được truyền về trình duyệt của bạn: văn bản hiện ra từng từ, và khi nó chạy một công cụ — chẳng hạn một lệnh shell ghi một file — bạn thấy nhãn của nó cập nhật trực tiếp, để bạn biết nó đang làm gì.

Mô hình truyền theo những đoạn nhỏ. Với mô hình chúng tôi đang chạy, các đoạn đó thường chỉ dài ba ký tự.

Những giả thuyết đầu tiên đều sai

Lỗi trông giống một vấn đề về quy mô, nên chúng tôi bắt đầu từ đó.

  • Sub-agent chạy song song? Lượt đó chỉ dùng hai cái, mỗi cái giữ khoảng 1,5 MB trạng thái. Không đủ.
  • Vết lưu giữ? Hệ thống theo dõi của chúng tôi giữ một cây lần chạy trong bộ nhớ, nhưng nó nhỏ hơn nhiều so với heap lúc crash.

Cả hai đều là những câu chuyện hợp lý, và cả hai đều dễ tin. Không cái nào tái hiện được crash. Bài học mà chúng tôi phải học đi học lại: một giả thuyết chưa phải nguyên nhân cho đến khi nó tái hiện được lỗi.

Tái hiện thật sự

Chúng tôi dựng một sandbox dùng một lần với cùng giới hạn bộ nhớ như production, và một mô hình giả truyền một file lớn theo những đoạn ba ký tự thực tế. Chúng tôi cũng làm cho phía đọc ở đầu kia của socket chậm, như một mạng thật.

Như vậy là đủ. Heap tăng lên và tiến trình chết với đúng lỗi đó.

Cơ chế thì đơn giản khi chúng tôi có thể quan sát nó. Trong khi mô hình viết một lệnh lớn — trong trường hợp này là một heredoc ghi một file 124 KB — mã truyền dữ liệu của chúng tôi cập nhật nhãn của công cụ trên mỗi đoạn. Nhãn không phải ba ký tự mới; nó là toàn bộ lệnh cho đến lúc đó. Vì vậy các sự kiện tăng lên: 3 ký tự, rồi 6, rồi 9, … đến 124 KB, khoảng 41.000 lần. Socket không gửi nhanh bằng tốc độ chúng được tạo ra, nên chúng dồn lại trong bộ đệm ghi của nó dưới dạng chuỗi — khoảng 690 MB.

Cách sửa

  • Giới hạn nhãn. Một nhãn trạng thái chỉ cần nói việc đang diễn ra là gì. Nó giờ bị giới hạn ở 200 ký tự, và chúng tôi tiết chế tần suất quét lại lệnh một phần.
  • Ngừng nối chuỗi bậc hai. Ghép các đoạn đã truyền bằng cách nối chuỗi lặp lại là O(n²) với đầu ra lớn. Chúng tôi chuyển sang cách dựa trên khối, nối theo thời gian tuyến tính.

Sau đó chúng tôi tìm mọi thứ khác có thể phình vô hạn khi có một luồng đầu ra dày đặc, và giới hạn chúng:

  • Đầu ra lệnh trực tiếp hiển thị trong chat được gom lại và chỉ giữ 8.000 ký tự cuối.
  • Mỗi dòng sự kiện được giới hạn ở 4 MB.
  • Bộ đệm phát lại mà trình duyệt dùng để bắt kịp sau khi kết nối lại được giới hạn ở 8 MB cho mỗi dự án.
  • Các điểm lưu cũ được cắt bớt khi một lượt tiến hành, giữ trạng thái mới nhất và các mốc mà các lượt trước cần.

Kiểm thử lũ dữ liệu một cách trung thực

Hai điều khiến việc kiểm thử này khó hơn mức cần thiết:

  1. Mô hình thật không hợp tác. Yêu cầu một mô hình in ra một file khổng lồ thì nó thường từ chối, tóm tắt, hoặc viết theo cách hợp lý hơn. Để kiểm thử lũ dữ liệu, bạn cần một mô hình giả có kịch bản, chạy qua mã agent thật.
  2. Script phải hành xử như mô hình. Mô hình giả đầu tiên của chúng tôi dùng lại cùng một ID phản hồi cho mọi lượt trả lời, nên framework agent coi mỗi phản hồi là thay thế cho phản hồi trước và kết thúc lượt sớm. Trông như một lỗi làm mới giao diện. Thực ra không phải — đó là khung kiểm thử đang nói dối chúng tôi. Chúng tôi cũng phải áp đặt giới hạn ngữ cảnh thật của mô hình trong script, nếu không các con số bộ nhớ sẽ không thực tế.

Chúng tôi rút ra gì

  • Giao diện truyền trực tiếp khuếch đại những lỗi nhỏ. Bất cứ thứ gì bạn gửi “theo từng đoạn” sẽ được gửi hàng chục nghìn lần. Hãy gửi phần thay đổi, hoặc giới hạn tải trọng.
  • Giới hạn mọi bộ đệm đi qua một ranh giới chậm. Socket, nhật ký phát lại và điểm lưu đều cần một trần.
  • Tái hiện trước khi sửa. Hai lời giải thích đầu tiên của chúng tôi nghe có vẻ đúng và đã sai.

Nếu gần đây bạn thấy một file rất dài xuất hiện trong chat Mythex mà agent không bị đứng, đây là một phần lý do.

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 Українська اردو 简体中文 繁體中文(香港) 繁體中文(台灣)