英语轻松读发新版了,欢迎下载、更新

再做一遍:我们如何使用 Durable Objects 向 AI Gateway 添加 WebSockets 支持和身份验证

2024-11-19 15:22:30 英文原文

作者:Catarina Pires MotaGabriel Massadas

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 提供商的请求。

BLOG-2617 2

通过通过 WebSocket 连接到 AI Gateway,我们使用提供商支持的协议(HTTPS、WebSocket 等)向推理服务发出请求,您可以保持连接打开以执行尽可能多的推理请求如您所愿。 

为了让您与AI网关的连接更加安全,我们还引入了AI网关的身份验证功能。新的 WebSockets API 将需要身份验证。您需要做的就是创建 Cloudflare API 令牌具有权限“AI Gateway:运行”并将其发送到cf-aig-授权标头。

BLOG-2617 3

在上面的流程图中:

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/

BLOG-2617 4

然后使用您的通用端点打开 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从任何设备开始使用我们的免费应用程序,让您的互联网更快、更安全。

要详细了解我们帮助建立更好的互联网的使命,从这里开始。如果您正在寻找新的职业方向,请查看我们的空缺职位

人工智能人工智能网关开发商开发者平台敏捷开发者服务JavaScript

关于《再做一遍:我们如何使用 Durable Objects 向 AI Gateway 添加 WebSockets 支持和身份验证》的评论


暂无评论

发表评论

摘要

### Cloudflare AI Gateway WebSocket API 功能介绍总结:Cloudflare 在 2025 年第一季度的 AI 网关功能中引入了基于 WebSocket 的高级连接,允许实时双向通信,无需建立长期、持久的连接,简化了 HTTP 轮询或批处理请求的处理。以下是详细实施和使用说明中的要点:#### 主要特点:- **WebSocket 到 WebSocket 代理:** Cloudflare 的 AI 网关将在单个 WebSocket 连接中路由响应,有效管理多个实时流数据,可以处理并发开销,以了解哪个响应对应于哪个请求。为了解决这个问题,响应元数据中的每个消息结构:“eventId”——每条消息中每个事件 ID 的唯一标识符。这有助于客户端跟踪其异步请求-响应对,准确地关联响应:1. **初始化:**发送单个WebSocket连接时,客户端根据eventId匹配关联每个块。2. **消息结构示例:**- 请求已发送,服务器发送一个包含该流完成的所有元数据的信封。#### 实现示例:**Node.js(ws 包)**:```javascriptconst WebSocket = require('ws');const ws = new WebSocket("wss://gateway.ai.cloudflare.com/v1/my-account-id/my-gateway:","eventId":"我的请求",“logId”:“01JC40RB3N2B5X5XFRZGBNB757V”}}成功”:真实,“内容类型”:“应用程序/json”````**浏览器 WebSocket API 示例:```javascriptconst socket = new WebSocket("wss://gateway.ai.cloudflare.com/v1/my-account-id/gateway", [“cf-aig-authorization.”将主机替换为 wss:” 前缀并删除 â/v://â 在浏览器或任何 WebSocket 库中使用它。````### 附加功能:- **WebSocket 到 WebSocket 直接连接:** 在 2025 年第一季度 API 密钥作为授权标头。- **API 密钥(cf-aigateway):````jsconst socket = new WebSocket("wss://gateway.ai.cloudflare.com/v1/my-account-id/my-gateway/", {标题:{"cf-aig-authorization": "持有者 YOUR_API_KEY",},});````### 立即尝试!为了进行测试,请使用提供的 Cloudflare 端点并按照以下步骤建立 WebSocket 连接。此设置将允许您发送人工智能推理的实时请求。**注意:** 确保您的 API 密钥和端点的格式正确,并根据最佳实践进行保护。如需进一步帮助或问题,请联系 Discord 或查看里斯本 Cloudflare 开发者平台团队的职位空缺。````jssocket.onopen = 函数(事件) {console.log("WebSocket 连接已建立。");};// 发送请求socket.send(JSON.stringify({类型:“universal.create”,要求: {"provider": "workers-ai", // 示例“端点”:“@cf/meta/llama-3.1-8b-instruct”,“标题”:{"授权": "持有者YOUR_TOKEN",“内容类型”:“应用程序/json”},"query": {"prompt":"给我讲个笑话"}}}));socket.onmessage = 函数(事件) {console.log("响应:", event.data);};````请联系 Cloudflare 支持或 Discord 频道,获取有关 WebSocket 设置和 API 调用的更多详细帮助或问题。