Blog

Giữ các lượt agent nhiều ảnh trong giới hạn bộ nhớ

Một lượt agent trên production đã hết bộ nhớ ở mức 952 MB trong lúc cắt sản phẩm ra khỏi sáu bản quét catalogue và xem các đoạn đã cắt. Không phải chỉ có một chỗ rò rỉ — mà có ba. Mỗi lần gọi model đều gửi lại ảnh của lượt ở kích thước đầy đủ; thư viện chúng tôi dùng để gọi model giữ mọi request còn sống cho đến khi lượt kết thúc; và phần tracing của framework agent giữ đầu vào của mỗi lần gọi, kể cả ảnh, trong suốt lượt. Chúng tôi đã sửa cả ba: ảnh được thu nhỏ trước khi gửi, và ảnh của mỗi lần gọi được giải phóng ngay khi lần gọi đó xong.

Agent nhìn thấy ảnh như thế nào

Khi bạn xây trên Mythex, agent làm việc trong sandbox đám mây của dự án. Nó có thể xem ảnh — một ảnh chụp màn hình bạn đính kèm, một bản mockup, một file trong dự án, hoặc một ảnh chính nó vừa tạo — bằng cách gửi ảnh đó cho model cùng với cuộc trò chuyện.

Lượt là toàn bộ những gì agent làm để đáp lại một tin nhắn của bạn. Trong một lượt, agent gọi model nhiều lần: suy nghĩ, chạy một công cụ, xem kết quả, rồi suy nghĩ lại. Mỗi lần gọi đều gửi phần hội thoại đến lúc đó, và điều đó bao gồm các ảnh của lượt, được mã hóa thành văn bản (base64, làm chúng lớn hơn khoảng một phần ba).

Lượt bị crash đang làm một việc hợp lý. Nó lấy sáu bản quét catalogue, mỗi bản khoảng 2,4 MB, cắt từng sản phẩm riêng lẻ ra khỏi chúng, và liên tục đọc lại các đoạn đã cắt để kiểm tra. Đó là rất nhiều lần gọi model, mỗi lần mang theo nhiều ảnh lớn.

Nguyên nhân 1: mỗi lần gọi gửi lại ảnh kích thước đầy đủ

Mỗi lần gọi model dựng lại thân request với các ảnh của lượt ở kích thước đầy đủ — khoảng 20 MB base64 cho mỗi lần gọi. Thân request được tạo thành một chuỗi duy nhất trong bộ nhớ của agent, nên mỗi lần gọi cấp phát thêm khoảng 20 MB.

Gửi kích thước đầy đủ thậm chí chẳng mang lại lợi ích gì. Model tự thu ảnh về khoảng 1.300 pixel ở cạnh dài, nên những pixel thừa chỉ tốn bộ nhớ và thời gian tải lên.

Cách sửa: thu nhỏ một lần, gửi bản nhỏ

  • Ảnh trên 400 KB giờ được chuyển thành JPEG có cạnh dài tối đa 1.568 pixel trước khi gửi. Ảnh nhỏ hơn được gửi nguyên trạng.
  • Việc chuyển đổi dùng ImageMagick, có sẵn trong mọi sandbox của Mythex, và chỉ chạy một lần cho mỗi file. Một lượt hiển thị cùng các bản quét ở mỗi lần gọi sẽ tái sử dụng bản đã thu nhỏ. Bộ nhớ đệm đó được khóa theo đường dẫn, kích thước và thời điểm sửa đổi của file, nên một file đã chỉnh sửa sẽ được chuyển đổi lại, và nó có giới hạn kích thước riêng để không trở thành thứ làm đầy bộ nhớ.
  • Ngân sách cho ảnh trong một lần gọi model giảm từ 16 MB xuống 6 MB.

Sáu bản quét đó giờ tốn 4,4 MB mỗi lần gọi thay vì 19,7 MB.

Nguyên nhân 2: client model không bao giờ buông một request

Kích thước của mỗi request chỉ là một phần. Bộ nhớ cũng tăng lên qua từng lần gọi. Trên môi trường staging của chúng tôi, cùng một loại lượt giữ 369 MB bộ nhớ đang sống ngay cả sau khi đã chạy một lần thu gom rác đầy đủ — thời điểm mọi thứ không còn truy cập được đã được giải phóng. Lấy mẫu heap cho thấy toàn bộ phần tăng trưởng nằm ở phần thư viện client model mã hóa thân request.

Nguyên nhân là một listener abort. Khi bạn nhấn Dừng, abort signal của lượt được kích hoạt, và mọi request đang lắng nghe đều bị hủy. Chúng tôi truyền signal duy nhất cho cả lượt vào mọi request. Thư viện client gắn một listener “abort” vào bất kỳ signal nào nó được đưa, và không bao giờ gỡ nó ra.

Vì vậy, mọi request của một lượt đều vẫn truy cập được từ signal của lượt, trong suốt thời gian lượt kéo dài: listener giữ controller, controller giữ request, và request giữ toàn bộ thân request cùng các ảnh của nó.

Cách sửa: một signal cho mỗi request

Mỗi request giờ có signal riêng. Nó chỉ được liên kết với signal của lượt trong khi request đó đang chạy — với phản hồi dạng stream, cho đến khi đọc xong chunk cuối cùng — và được hủy liên kết ngay sau đó. Nút Dừng vẫn tác động đến request đang chạy, nhưng signal của lượt chỉ giữ một listener tại một thời điểm.

Các bài kiểm thử bao phủ cả ba phần:

  • Sau 12 lần gọi, không còn listener nào trên signal của lượt. Trước khi sửa, có 12.
  • Trên 15 request, mỗi request 8 MB, bộ nhớ giữ ổn định. Trước đây, nó tăng 128 MB.
  • Nhấn Dừng vẫn hủy được một request ngay giữa lúc đang stream.

Nguyên nhân 3: tracing giữ đầu vào của mọi lần gọi

Một ảnh chụp heap cho thấy một bên giữ thứ thứ ba: khoảng 6 MB cho mỗi lần gọi model. Điều này đến từ phần stream sự kiện của framework agent. Nó ghi lại mọi lần gọi model trong một lượt như một con của lượt, kể cả đầu vào, cho đến khi lượt kết thúc. Mọi ảnh đính kèm cho mọi lần gọi đều nằm trong bộ nhớ cùng với nó.

Cách sửa: xóa ảnh khi lần gọi trả về

Ảnh chỉ được đính vào các message được dựng cho một lần gọi model cụ thể. Chúng không bao giờ được lưu trong trạng thái hội thoại đã lưu. Vì vậy, khi một lần gọi trả về, việc làm rỗng dữ liệu ảnh trong các message đó là an toàn. Trace vẫn giữ bản ghi văn bản của lần gọi; phần điểm ảnh thì được giải phóng.

Có một chi tiết quan trọng: ảnh phải được làm rỗng tại chỗ. Tracer có thể truy cập cùng dữ liệu ảnh qua nhiều hơn một tham chiếu trên một message, nên nếu thay bằng một danh sách rỗng mới, bản gốc — kể cả các điểm ảnh — vẫn có thể truy cập được. Trạng thái hội thoại đã lưu không bao giờ bị sửa đổi.

Một bài kiểm thử chạy graph của agent dưới cùng cơ chế stream sự kiện với một ảnh 4 MB ở mỗi lần gọi. Không có bản sửa, bộ nhớ tăng 77 MB sau 16 lần gọi. Với bản sửa, bộ nhớ giữ ổn định.

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

  • Vấn đề bộ nhớ có thể đến theo từng lớp. Ba nguyên nhân riêng biệt đều giữ ảnh quá lâu, và cả ba phải được loại bỏ thì lượt mới nằm trong giới hạn bộ nhớ.
  • Bất cứ thứ gì bạn đưa cho một thư viện đều có thể bị giữ lại. Một signal và một trace đều sống lâu hơn các lần gọi mà chúng được đưa vào. Khi bộ nhớ tăng theo từng lần gọi, hãy xem những đối tượng sống lâu nào mà lần gọi chạm tới.
  • Đừng gửi những gì phía bên kia sẽ bỏ đi. Các điểm ảnh mà model vốn sẽ loại bỏ vẫn làm chúng tôi tốn bộ nhớ ở mỗi lần gọi.
  • Kiểm thử bộ nhớ trực tiếp. Mỗi bản sửa đi kèm một bài kiểm thử đo mức tăng heap hoặc số lượng listener, nên một hồi quy hiện ra dưới dạng con số, không phải một lần crash.

Đây là câu chuyện bộ nhớ thứ hai liên quan đến agent trong thời gian ngắn; câu chuyện đầu tiên là một nhãn tiến trình được gửi lại 41.000 lần. Nếu bạn muốn biết thêm agent là gì và nó hoạt động ra sao, hãy xem hướng dẫn của chúng tôi về AI agent và tài liệu về chat.

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