构建AI聊天应用时,一个容易被忽视的问题正在悄悄消耗你的成本:当用户关闭浏览器标签页,服务器对LLM API的请求可能仍在继续运行并产生费用。
假设你搭建了一个AI聊天服务,用户提问后,服务器调用大模型API并开始流式返回答案。一切看起来都很正常,直到用户中途关闭了标签页——响应消失了,但后端的LLM请求是否也被取消了呢?
如果你的服务器没有显式传播取消信号,答案很可能是否定的。这不仅是正确性问题,对AI应用而言更是成本问题。用户可能在生成500个token后就放弃,而后端却要继续为剩余数千个token的生成买单。
两条独立的HTTP连接
这个场景中实际存在两条HTTP连接:浏览器与服务器之间的连接,以及服务器与LLM API之间的连接。浏览器控制着第一条连接,服务器控制着第二条。当浏览器关闭标签页时,第一条连接断开,但服务器与LLM API之间的连接并不会自动终止。
服务器需要显式地将两条连接的生命周期关联起来,才能实现取消传播。具体来说,需要构建这样一条取消链路:浏览器客户端断开连接后,通过AbortSignal机制传递取消信号,最终取消服务器对LLM API的fetch请求。
最简单的服务器实现及其局限
考虑一个最简单的服务器实现:接收POST请求后,直接调用fetch请求LLM API,并将响应流返回给浏览器。这种写法在正常场景下工作良好,但完全没有处理客户端断开连接的情况。
当浏览器关闭时,没有任何机制自动通知服务器取消对LLM API的请求。服务器和上游LLM请求被视为两个独立操作,除非显式连接它们的生命周期,否则取消信号不会自动传播。
对于TypeScript开发者而言,解决这个问题的核心在于利用AbortSignal机制,将浏览器端的断开事件与服务器端的fetch请求取消关联起来。通过正确实现取消传播路径,可以避免因用户中途放弃而造成的无谓API调用费用。
热门跟贴