Đặt timeout LLM theo thời hạn còn lại của người dùng
Chia sẻ một thời hạn cho truy xuất và sinh câu trả lời; kiểm tra ngân sách và quan sát hủy coroutine có thể vượt timeout.

Với kỹ sư đang cung cấp tính năng LLM, timeout nên dựa trên thời hạn còn lại của yêu cầu người dùng, thay vì bắt đầu lại ở mỗi bước nội bộ. Truy xuất, sinh câu trả lời, gọi công cụ và gửi phản hồi đều dùng chung ngân sách từ đầu đến cuối. Cấp toàn bộ ngân sách cho từng bước có thể khiến yêu cầu được cho là có giới hạn kéo dài gấp nhiều lần dự kiến.
Xét giao diện hỗ trợ giả định cho phép tám giây để phản hồi. Con số đó là lựa chọn sản phẩm trong ví dụ, không phải ngưỡng khuyến nghị chung. Ứng dụng giữ lại nửa giây để định dạng và gửi câu trả lời hoặc phương án thay thế hữu ích.
Tính ngược từ thời hạn
Khi nhận yêu cầu, ghi thời điểm bắt đầu bằng đồng hồ đơn điệu và tính thời hạn. Đồng hồ đơn điệu tránh nhầm lẫn do chỉnh đồng hồ lịch khi đo khoảng thời gian đã trôi qua. Mỗi giai đoạn nhận ngân sách còn lại, trừ phần dành cho phản hồi cuối trước khi bắt đầu công việc tốn kém.
Giả sử xác thực và định tuyến mất 0,5 giây, rồi truy xuất mất 1,5 giây. Đã trôi qua hai giây và còn sáu. Sau khi giữ nửa giây để gửi phản hồi, bước sinh có tối đa 5,5 giây theo chính sách này. Nó không được cấp lại timeout tám giây.
Total request budget: 8.0 seconds
Authentication and routing: 0.5 seconds
Retrieval: 1.5 seconds
Reserved response handling: 0.5 seconds
Remaining generation budget: 5.5 seconds
Đây là dấu vết minh họa, không phải độ trễ đã đo của dịch vụ. Khối lượng công việc thực cần phân bố, gồm cả trường hợp chậm, trước khi chọn thời hạn và chính sách dự phòng có ích.
Hình cho thấy ngân sách còn lại sau mỗi bước. Nếu truy xuất mất năm giây, bước sinh được ít thời gian hơn hoặc không bắt đầu. Quyết định đó cần tường minh để tránh khởi chạy một lần gọi đắt tiền khi ứng dụng đã biết không thể dùng kết quả.
Phân biệt đầu ra đầu tiên với kết quả hoàn chỉnh
Streaming cho phép người dùng nhìn thấy văn bản trước khi sinh xong. Nó không có nghĩa toàn bộ câu trả lời đã sẵn sàng hoặc hợp lệ. Kết quả trích xuất có cấu trúc có thể chưa dùng được cho đến khi nhận đủ đối tượng và kiểm tra thành công. Câu trả lời hội thoại có thể đọc được sớm nhưng vẫn cần trích dẫn hoặc điều kiện xuất hiện ở cuối.
Hướng dẫn tối ưu độ trễ của OpenAI, được đọc ngày 20 tháng 9 năm 2026, bàn về độ trễ của mô hình lẫn thiết kế ứng dụng. Chọn chỉ số phù hợp sản phẩm: thời gian đến token đầu tiên nhìn thấy, đến đối tượng đã kiểm tra, hoặc đến tác vụ hoàn thành. Chỉ báo cáo số nhanh nhất có thể che khuất trải nghiệm kém.
Khi người dùng hủy yêu cầu streaming, truyền tín hiệu hủy xuống dưới ở những nơi nhà cung cấp và giao thức hỗ trợ. Đóng kết nối trình duyệt không tự chứng minh mọi thao tác phía sau đã dừng. Ghi nhận kết quả hủy thực tế hoặc coi thao tác có thể vẫn chạy cho đến khi biết trạng thái.
Dành chỗ cho phương án thay thế trung thực
Phản hồi timeout hữu ích phụ thuộc tác vụ. Trợ lý tìm kiếm có thể trả liên kết tài liệu đã truy xuất khi không sinh được câu trả lời, nếu liên kết đúng quyền và liên quan. Hệ thống trích xuất tài chính không nên trả đối tượng điền dở như thể đã kiểm tra thành công. Nó có thể tạo mục chờ duyệt hoặc yêu cầu người dùng thử lại sau.
Phương án thay thế cần ngân sách thực thi nhỏ riêng. Nếu dùng hết từng mili giây để đợi mô hình, ứng dụng có thể không gửi được phản hồi kết thúc rõ ràng. Giữ thời gian xử lý phản hồi cũng cho phép ghi định danh thao tác để người dùng tham chiếu khi tiếp tục.
Tránh âm thầm đổi sang mô hình khác trừ khi mô hình đó đáp ứng yêu cầu tính năng. Các mô hình có thể khác khả năng schema, chất lượng hoặc cách dùng công cụ. Đánh giá đường dự phòng trước khi dùng trong sự cố và thể hiện hành vi suy giảm khi nó thay đổi điều người dùng có thể dựa vào.
Chỉ gọi lại khi yêu cầu còn khả năng thành công
Lỗi tạm thời có thể cho phép thử lại nếu còn đủ thời gian và thao tác an toàn để lặp. Hướng dẫn giới hạn tốc độ mô tả cách xử lý, gồm backoff. Chính sách backoff vẫn cần thời hạn tổng; nếu không, các lần gọi lại có thể tiếp tục sau khi người dùng đã nhận lỗi.
Với thao tác chỉ đọc qua mô hình, gọi lại có thể chủ yếu làm tăng phí. Với công cụ agent tạo bản ghi, lặp sau timeout không rõ kết quả có thể tạo hiệu ứng hai lần. Dùng định danh thao tác và bản ghi kết quả của công cụ để xác định điều đã xảy ra trước khi thử lại. Timeout mạng là thất bại trong việc quan sát, không phải rollback giao dịch.
Ghi các lần gọi lại vào cùng dấu vết với yêu cầu ban đầu. Theo dõi thời gian chờ, thời gian thực thi và kết quả cuối. Yêu cầu thành công ở lần thứ ba phải đóng góp toàn bộ chi phí và độ trễ vào chỉ số tính năng, không chỉ lần cuối thành công.
Kiểm tra thời hạn bằng độ trễ điều khiển được
Dùng dịch vụ truy xuất giả lập và endpoint mô hình giả lập có thể trì hoãn hoặc thất bại ở điểm đã biết. Kiểm tra truy xuất nhanh nhưng sinh chậm, truy xuất chậm đến mức không còn ngân sách sinh, người dùng hủy và một lần backoff sẽ vượt thời hạn. Xác nhận ứng dụng đi đến trạng thái kết thúc đã định trong từng trường hợp.
Cũng xem còn gì chạy sau khi phản hồi kết thúc. Công việc nền có thể là chủ đích nếu sản phẩm cho phép lấy kết quả sau, nhưng khi đó nó cần định danh bền vững và endpoint trạng thái rõ ràng. Một lần gọi đắt tiền bị bỏ lại mà không có nơi chịu trách nhiệm là kết quả khác.
Mục tiêu vận hành đầu tiên là dấu vết giải thích được: yêu cầu bắt đầu với một ngân sách, từng giai đoạn dùng một phần và ứng dụng phân bổ phần còn lại theo chính sách đã nêu. Bằng chứng đó biến timeout thành hành vi được thiết kế thay vì ngoại lệ tùy tiện cuối một lần chờ dài.
Quan sát quá trình hủy thực sự chờ điều gì
Cần kiểm tra hai khẳng định riêng: bên gọi ngừng nhận kết quả mô hình và thao tác mô hình đã dừng. Chúng không nhất thiết xảy ra cùng lúc. Tài liệu asyncio.wait_for của Python nêu rõ hàm chờ quá trình hủy hoàn tất, nên thời gian đã trôi qua có thể vượt timeout yêu cầu. Timeout của thư viện không phải cam kết thời gian cứng với người dùng.
Ví dụ chạy được này dùng coroutine cục bộ thay cho nhà cung cấp. Coroutine chờ mãi đến khi bị hủy, sau đó thực hiện một bước dọn dẹp bất đồng bộ ngắn. Timeout một mili giây được chọn để kích hoạt nhánh đó trong minh họa nhỏ, không phải khuyến nghị cho dịch vụ. Quan sát cần kiểm tra là thứ tự sự kiện; độ trễ do bộ lập lịch không được diễn giải thành phép đo hiệu năng.
import asyncio
import time
async def model_stub(events):
events.append("model_started")
try:
await asyncio.Event().wait()
except asyncio.CancelledError:
events.append("cancellation_observed")
await asyncio.sleep(0.02)
events.append("cleanup_finished")
raise
async def cancellation_trace():
events = []
started = time.monotonic()
try:
await asyncio.wait_for(model_stub(events), timeout=0.001)
except TimeoutError:
events.append("caller_received_timeout")
elapsed = time.monotonic() - started
assert events == ["model_started", "cancellation_observed",
"cleanup_finished", "caller_received_timeout"]
assert elapsed >= 0.02
print(events)
return elapsed
if __name__ == "__main__":
asyncio.run(cancellation_trace())
Bên gọi chỉ nhận timeout sau khi dọn dẹp hoàn tất. Ví dụ chủ ý phát sinh lại CancelledError; nuốt ngoại lệ đó sẽ đổi hợp đồng của coroutine. Lần chạy không có yêu cầu mạng, worker nền hoặc xác nhận hủy từ xa. Hàm chặn mà không nhường quyền có thể còn tệ hơn: cơ chế hủy phối hợp không thể buộc nó quan sát ngoại lệ khi nó vẫn đang chặn event loop.
Điều này cũng đổi cách hiểu phần dự phòng. Nửa giây giữ lại bằng phép tính không bảo đảm việc dọn dẹp không được kiểm soát, tuần tự hóa phản hồi hoặc socket bị kẹt sẽ xong trong khoảng đó. Thực thi chính sách phản hồi đòi hỏi quản lý các hoạt động ấy, giới hạn công việc khi có thể và quan sát phản hồi kết thúc. Nếu công việc từ xa có thể sống lâu hơn phản hồi, hãy giữ định danh thao tác và chủ động xử lý kết quả đến muộn.
Chương Handling Overload trong sách SRE của Google, được đọc ngày 21 tháng 9 năm 2026, giải thích rằng phản hồi suy giảm vẫn dùng tài nguyên và chính nó cũng có thể không phục vụ được. Đây là ràng buộc hữu ích cho đường dự phòng LLM: xác định kết quả rẻ hơn và tài nguyên cần để tạo nó. Câu trả lời cũ hoặc phạm vi tìm kiếm bị thu hẹp cũng phải đáp ứng yêu cầu về tính đúng của tính năng; rẻ hơn không làm nó phù hợp mọi tác vụ.
Kiểm tra phép tính ngay trước khi khởi chạy
Có thể kiểm tra phép tính thời hạn riêng với việc lập lịch. Hàm sau nhận các giá trị số hữu hạn từ cùng một đồng hồ đơn điệu và phần dự phòng không âm. Nó trả về cận thời gian, không cấp quyền bỏ qua giới hạn của nhà cung cấp và không bảo đảm coroutine kết thúc đúng giờ.
import math
def generation_budget(deadline, now, reserve):
values = (deadline, now, reserve)
if any(type(value) not in (int, float) for value in values):
raise ValueError("numeric times are required")
try:
deadline, now, reserve = map(float, values)
except OverflowError as error:
raise ValueError("times exceed this numeric representation") from error
if not all(math.isfinite(value) for value in (deadline, now, reserve)) or reserve < 0:
raise ValueError("finite times and a nonnegative reserve are required")
budget = deadline - now - reserve
if not math.isfinite(budget):
raise ValueError("budget exceeds this numeric representation")
return max(0.0, budget)
assert generation_budget(8.0, 2.0, 0.5) == 5.5
assert generation_budget(8.0, 7.5, 0.5) == 0.0
assert generation_budget(8.0, 9.0, 0.5) == 0.0
Tính lại ngay trước khi gửi thao tác, kể cả sau backoff. Đừng dùng lại số dương đã tính trước một khoảng chờ dài. Nếu cận bằng không, đi vào đường dự phòng mà không khởi chạy sinh. Cận dương rất nhỏ vẫn có thể không đủ để tạo câu trả lời hữu ích; ngưỡng nhận việc tùy sản phẩm đó tách biệt với phép tính ở đây.
Đừng gửi nguyên số deadline sang máy khác như thể đồng hồ đơn điệu chia sẻ cùng mốc gốc. Truyền cách biểu diễn thời hạn mà giao thức hỗ trợ hoặc khoảng thời gian còn lại, tính đến truyền tải và xử lý cục bộ theo quy tắc của giao thức đó. Ví dụ cục bộ không kiểm tra đồng bộ đồng hồ hoặc truyền thời hạn qua hệ phân tán. Nó cung cấp hai bằng chứng có thể xem xét: trừ ngân sách đúng và lý do cụ thể khiến quá trình hủy có thể lâu hơn ngân sách ấy.