2024-11-19
5 分钟阅读

2024年10月,我们谈到存储数十亿条日志使用 AI Gateway 从您的 AI 应用程序中获取数据,以及我们如何使用 Cloudflare 的开发者平台来实现此目的。
AI网关已处理超过30亿条日志,且增长迅速,平台连接数持续稳定增长。为了帮助开发人员更有效地管理这种规模,我们希望提供一种替代方案来实现 HTTP/2 keep-alive 来维护持久的 HTTP(S) 连接,从而避免重复握手和TLS 协商每个与 AI Gateway 的新 HTTP 连接。我们知道,实现 HTTP/2 可能会带来挑战,特别是当许多库和工具默认情况下可能不支持它,并且大多数现代编程语言都有完善的 WebSocket 库可用时。
考虑到这一点,我们使用 Cloudflare 的开发者平台和 Durable Objects(是的,再次!)来构建一个WebSockets API建立单一、持久的连接,实现持续通信。”
通过此 API,AI 网关支持的所有 AI 提供程序都可以通过 WebSocket 进行访问,从而允许您在客户端或服务器应用程序与 AI 网关之间维护单个 TCP 连接。最好的部分?即使您选择的提供商不支持 WebSockets,我们也会为您处理,管理对您首选 AI 提供商的请求。

通过通过 WebSocket 连接到 AI Gateway,我们使用提供商支持的协议(HTTPS、WebSocket 等)向推理服务发出请求,您可以保持连接打开以执行尽可能多的推理请求如您所愿。
为了让您与AI网关的连接更加安全,我们还引入了AI网关的身份验证功能。新的 WebSockets API 将需要身份验证。您需要做的就是创建 Cloudflare API 令牌具有权限“AI Gateway:运行”并将其发送到cf-aig-授权
标头。

在上面的流程图中:
1、启用身份验证网关并包含有效令牌后,请求将成功通过。
2、如果启用了身份验证网关,但请求不包含所需的内容cf-aig-授权
如果标头带有有效令牌,则请求将失败。这可确保只有经过验证的请求才能通过网关。
3、当验证网关被禁用时,cf-aig-授权
标头被完全绕过,并且任何令牌(无论有效还是无效)都会被忽略。
我们最近使用持久对象 (DO) 来扩展 AI 网关的日志记录解决方案,因此在同一 DO 中使用 WebSocket 是很自然的选择。
当我们的 Cloudflare Workers 收到新的 WebSocket 连接时,我们以两种方式实施身份验证,以支持 WebSocket 客户端的不同功能。主要方法涉及通过以下方式验证 Cloudflare API 令牌:cf-aig-授权
标头,确保令牌对于连接帐户和网关有效。
但是,由于浏览器 WebSocket 实现的限制,我们还支持通过“sec-websocket-protocol”标头进行身份验证。浏览器 WebSocket 客户端不允许在其标准 API 中使用自定义标头,这使得在请求中添加身份验证令牌变得复杂。虽然我们不建议您在浏览器中存储 API 密钥,但我们决定添加此方法,以便为所有 WebSocket 客户端增加更多灵活性。
// 浏览器内置WebSocket客户端const socket = new WebSocket("wss://gateway.ai.cloudflare.com/v1/my-account-id/my-gateway/", [“cf-aig-授权。${AI_GATEWAY_TOKEN}”]);// ws npm 包从“ws”导入WebSocket;const ws = new WebSocket("wss://gateway.ai.cloudflare.com/v1/my-account-id/my-gateway/",{标题:{"cf-aig-authorization": "承载 AI_GATEWAY_TOKEN",},});
在这个初始验证步骤之后,我们将连接升级到持久对象,这意味着它现在将处理该连接的所有消息。在新连接被完全接受之前,我们会生成一个随机的 UUID,因此该连接在持久对象接收到的所有消息中都是可识别的。在开放连接期间,通过标头传递的任何 AI 网关设置 — 例如cf-aig-跳过缓存
(设置为 true 时会绕过缓存) - 被存储并应用于会话中的所有请求。但是,这些标头仍然可以在每个请求的基础上被覆盖,就像通用端点今天。
一旦建立连接,持久对象就开始侦听传入消息。从此时起,用户可以通过 WebSocket 以 AI Gateway 通用格式发送消息,从而简化应用程序从现有 HTTP 设置到基于 WebSocket 的通信的转换。
从“ws”导入WebSocket;const ws = new WebSocket("wss://gateway.ai.cloudflare.com/v1/my-account-id/my-gateway/",{标题:{"cf-aig-authorization": "承载 AI_GATEWAY_TOKEN",},});ws.send(JSON.stringify({类型:“universal.create”,要求: {"eventId": "我的请求",“提供者”:“工人-ai”,“端点”:“@cf/meta/llama-3.1-8b-instruct”,“标题”:{"授权": "不记名WORKERS_AI_TOKEN",“内容类型”:“应用程序/json”},“询问”: {“prompt”:“给我讲个笑话”}}}));ws.on("消息", 函数传入(消息) {console.log(消息.toString())});
当新消息到达持久对象时,它会使用支持 HTTP 通用端点的相同代码进行处理,从而实现跨工作线程和持久对象的无缝代码重用 - 这是构建持久对象的主要优势之一在 Cloudflare 上。
对于非流式请求,响应被包装在 JSON 信封中,使我们能够包含 AI 推理本身之外的其他信息,例如该请求的 AI 网关日志 ID。
以下是上述请求的响应示例:
{"type":"universal.created",“元数据”:{"cacheStatus":"未命中","eventId":"我的请求","logId":"01JC3R94FRD97JBCBX3S0ZAXKW",“步骤”:“0”,“内容类型”:“应用程序/json”},“回复”:{“结果”:{"response":"为什么这本数学书很难过?因为它的问题太多了。你想再听一本吗?"},“成功”:真实,“错误”:[],“消息”:[]}}
对于流请求,AI Gateway 会发送一条初始消息,其中包含请求元数据,告诉开发人员流正在启动。
{"type":"universal.created",“元数据”:{"cacheStatus":"未命中","eventId":"我的请求","logId":"01JC40RB3NGBE5XFRZGBN07572",“步骤”:“0”,“contentType”:“文本/事件流”}}
在此初始消息之后,所有流数据块在从推理提供程序到达时都会实时中继到 WebSocket 连接。请注意,只有事件ID
字段包含在这些流块的元数据中(有关此新字段的更多信息如下)。
{"type":"universal.stream",“元数据”:{"eventId":"我的请求",}“回复”:{“回应”:“会”}}
这种方法有两个目的:首先,所有请求元数据已在初始消息中提供。其次,它解决了同时处理多个流请求的并发挑战。
处理异步事件
通过WebSocket连接,客户端和服务器可以随时异步发送消息。这意味着客户端在发送另一条消息之前不需要等待服务器响应。但是,如果客户端在 WebSocket 连接打开后立即发送多个流式推理请求,会发生什么情况?
在这种情况下,服务器将所有推理响应同时传输到客户端。由于一切都是异步发生的,客户端没有内置方法来识别每个请求对应的响应。
为了解决这个问题,我们在通用格式中引入了一个新字段,称为事件ID
,它允许 AI Gateway 在每条消息中包含客户端定义的 ID,即使在流式 WebSocket 环境中也是如此。
因此,要完全回答上述问题:服务器以并行块的形式传输两个响应,并且客户端可以根据事件ID
。
一旦请求的所有数据块都已流式传输,AI Gateway 就会发送一条最终消息来表明请求已完成。为了增加灵活性,该消息再次包含所有元数据,即使它也是在流处理开始时提供的。
{"type":"universal.done",“元数据”:{"cacheStatus":"未命中","eventId":"我的请求","logId":"01JC40RB3NGBE5XFRZGBN07572",“步骤”:“0”,“contentType”:“文本/事件流”}}
AI Gateway 的实时 Websocket API 现已进入测试阶段并向所有人开放!
要尝试一下,请复制您的网关通用端点 URL,并将“https://”替换为“wss://”,例如这:
wss://gateway.ai.cloudflare.com/v1/my-account-id/my-gateway/

然后使用您的通用端点打开 WebSocket 连接,并保证它通过 AI Gateway 的 Cloudflare 令牌进行身份验证跑步允许。
这是使用以下示例代码ws npm 包:
从“ws”导入WebSocket;const ws = new WebSocket("wss://gateway.ai.cloudflare.com/v1/my-account-id/my-gateway/", {标题:{"cf-aig-authorization": "承载 AI_GATEWAY_TOKEN",},});ws.on("打开", 函数 open() {console.log("已连接到服务器。");ws.send(JSON.stringify({类型:“universal.create”,要求: {“提供者”:“工人-ai”,“端点”:“@cf/meta/llama-3.1-8b-instruct”,“标题”:{"授权": "不记名WORKERS_AI_TOKEN",“内容类型”:“应用程序/json”},“询问”: {“流”:真实,“prompt”:“给我讲个笑话”}}}));});ws.on("消息", 函数传入(消息) {console.log(消息.toString())});
以下是使用内置浏览器 WebSocket 客户端的示例代码:
const socket = new WebSocket("wss://gateway.ai.cloudflare.com/v1/my-account-id/my-gateway/", [“cf-aig-授权。${AI_GATEWAY_TOKEN}”]);socket.addEventListener("打开", (事件) => {console.log("已连接到服务器。");socket.send(JSON.stringify({类型:“universal.create”,要求: {“提供者”:“工人-ai”,“端点”:“@cf/meta/llama-3.1-8b-instruct”,“标题”:{"授权": "不记名WORKERS_AI_TOKEN",“内容类型”:“应用程序/json”},“询问”: {“流”:真实,“prompt”:“给我讲个笑话”}}}));});socket.addEventListener("消息", (事件) => {console.log(事件.数据);});
在 2025 年第一季度,我们计划支持 WebSocket 到 WebSocket 连接(使用 DO),让您可以直接通过我们的平台连接到 OpenAI 的新实时 API。在此期间,您可以部署这位工人在您的帐户中自行代理请求。
如果您有任何疑问,请联系我们不和谐频道。我们还在招聘 AI Gateway,请查看里斯本的 Cloudflare 职位!
Cloudflare 的连接云保护整个企业网络,帮助客户构建高效的互联网规模应用,加速任何网站或互联网应用程序,抵御 DDoS 攻击, 保持黑客陷入困境,并且可以帮助您您的零信任之旅。
访问1.1.1.1从任何设备开始使用我们的免费应用程序,让您的互联网更快、更安全。