使用 Hono 构建 AI SDK 流式 API 服务器:从文本流到 Agent 集成的完整实战

发布时间:2026/9/11 21:38:03
使用 Hono 构建 AI SDK 流式 API 服务器:从文本流到 Agent 集成的完整实战
使用 Hono 构建 AI SDK 流式 API 服务器从文本流到 Agent 集成的完整实战【免费下载链接】aiThe AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and agents项目地址: https://gitcode.com/GitHub_Trending/ai/ai导读本文基于 examples/hono 示例讲解如何在 Hono 服务器中接入 AI SDK实现文本生成、UI 消息流式传输、自定义数据流注入以及基于 Agent 的联网搜索对话。读完本文你将掌握 AI SDK 各流式响应工具createTextStreamResponse、createUIMessageStreamResponse、toUIMessageStream、createUIMessageStream、createAgentUIStreamResponse的用途与底层原理并能独立搭建一个可供useChat等前端 UI 直接消费的流式 API 服务。示例概览一个 Hono 驱动的 AI 流式服务器AI SDK 本身是框架无关的 TypeScript 库可以运行在任意 Web 框架之上。本示例选择 Hono——一个轻量、快速、跨平台的 TypeScript Web 框架——配合hono/node-server在 Node.js 中启动服务展示了两种典型的流式输出模式纯文本流直接返回text/plain的流式文本适合命令行或简单消费端UI 消息流返回结构化消息块start、text-delta、data-custom、finish 等与 AI SDK 的前端useChat等 hook 天然对接适合浏览器交互应用。示例的完整目录结构如下examples/hono/ ├── src/ │ ├── server.ts # Hono 应用入口5 个路由端点 │ └── openai-web-search-agent.ts # 基于 ToolLoopAgent 的联网搜索 Agent ├── package.json ├── tsconfig.json └── README.md其中 server.ts 是服务端核心openai-web-search-agent.ts 定义了/chat端点使用的 Agent。环境准备与启动步骤1. 配置环境变量在示例目录或仓库根目录创建.env文件至少写入你所用 Provider 的密钥。若使用 OpenAI内容如下OPENAI_API_KEYYOUR_OPENAI_API_KEYserver.ts 中通过import dotenv/config加载环境变量因此除了 OpenAI你也可以按需增加其他 Provider 的密钥配置。2. 安装依赖并构建示例通过 pnpm workspace 引用仓库内的ai与ai-sdk/openai源码包见 tsconfig.json 中的references配置因此需要在 AI SDK 仓库根目录依次执行pnpm install pnpm build3. 启动开发服务器在仓库根目录运行pnpm dev该命令对应 package.json 中的脚本tsx watch src/server.ts借助tsx直接运行 TypeScript 源码并开启文件监听热重载。启动后服务监听在http://localhost:8080。4. 用 Curl 验证端点curl -i -X POST http://localhost:8080/text该命令返回 HTTP 状态行、响应头以及流式输出的文本内容。你也可以直接运行pnpm curlpackage.json 中已预置该脚本达到同样效果。核心端点逐个拆解server.ts 共定义了 5 个路由覆盖了 AI SDK 在服务端的主要流式用法。根路径/UI 消息流的基本形态app.post(/, async c { const result streamText({ model: openai(gpt-4o), prompt: Invent a new holiday and describe its traditions., }); return createUIMessageStreamResponse({ stream: toUIMessageStream({ stream: result.stream }), }); });这里streamText立即返回一个结果对象不会阻塞等待完整生成其.stream属性是TextStreamPart类型的流toUIMessageStream将其转换为UIMessageChunk流createUIMessageStreamResponse再包装为 HTTPResponse。这种立即返回、边生成边推送的模式是 AI SDK 流式编程的核心思想。/text纯文本流app.post(/text, async c { const result streamText({ model: openai(gpt-4o), prompt: Write a short poem about coding., }); return createTextStreamResponse({ stream: toTextStream({ stream: result.stream }), }); });toTextStream从完整流中提取纯文本增量createTextStreamResponse将其编码为 UTF-8 分块发送并设置Content-Type: text/plain; charsetutf-8。查看源码 create-text-stream-response.ts 可以看到其实现非常简洁通过stream.pipeThrough(new TextEncoderStream())作为 Response body同时支持自定义status、statusText与headers参数。这是最简单、与任何 HTTP 客户端都兼容的流式输出方式。/stream-data手动编排 UI 消息流const stream createUIMessageStream({ execute: ({ writer }) { writer.write({ type: start }); writer.write({ type: data-custom, data: { custom: Hello, world! }, }); const result streamText({ model: openai(gpt-4o), prompt: Invent a new holiday and describe its traditions., }); writer.merge( toUIMessageStream({ stream: result.stream, sendStart: false, onError: error { // Error messages are masked by default for security reasons. // 若需向客户端暴露具体错误信息可在此返回 error.message return error instanceof Error ? error.message : String(error); }, }), ); }, }); return createUIMessageStreamResponse({ stream });createUIMessageStream是比直接转换更底层的工具它接受一个execute({ writer })回调由你决定何时写入什么消息块。writer.write用于手动推送自定义块如type: start、type: data-customwriter.merge则可将另一条流如streamText转换后的 UI 消息流合并进来。从源码 create-ui-message-stream.ts 可以确认几个关键设计返回的是一个ReadableStreamInferUIMessageChunk并在内部维护所有ongoingStreamPromises即使execute已返回只要还有合并中的流未结束就不会提前关闭输出流onError的默认值是() An error occurred.刻意避免把服务端错误细节泄露给客户端示例中通过自定义onError展示了如何按需暴露error.message支持originalMessages传入后进入持久化模式并为响应消息提供 ID、onStepEnd多步 Agent 运行中每步结束时的回调可用于持久化中间消息以及generateId等参数。值得留意的是sendStart: false的用法因为外层已经手动写过type: start块转换流就不再重复发送 start 块避免重复消息。/chatAgent 驱动的对话流app.post(/chat, async c { const { messages } await c.req.json(); return createAgentUIStreamResponse({ agent: openaiWebSearchAgent, uiMessages: messages, }); });该端点接收前端传来的messages即useChat维护的 UI 消息数组交给openaiWebSearchAgent执行多步工具循环并将结果以 UI 消息流形式返回。这正是服务端 Agent 前端useChat的端到端链路前端无需关心 Agent 内部调用了多少次模型、多少次工具。Agent 定义基于 ToolLoopAgent 的联网搜索openai-web-search-agent.ts 展示了如何声明一个带工具循环能力的 Agentimport { openai, type OpenAILanguageModelResponsesOptions } from ai-sdk/openai; import { ToolLoopAgent } from ai; export const openaiWebSearchAgent new ToolLoopAgent({ model: openai(gpt-5-mini), tools: { web_search: openai.tools.webSearch({ searchContextSize: low, userLocation: { type: approximate, city: San Francisco, region: California, country: US, }, }), }, providerOptions: { openai: { reasoningEffort: medium, reasoningSummary: detailed, } satisfies OpenAILanguageModelResponsesOptions, }, });要点说明ToolLoopAgent是 AI SDK 提供的内置 Agent 类源码位于 packages/ai/src/agent/tool-loop-agent.ts负责模型推理 → 调用工具 → 将结果回传模型 → 继续推理的循环直到模型不再请求工具为止web_search工具直接取自openai.tools.webSearch可配置searchContextSize如low以及近似用户位置userLocation让搜索结果更贴近地域语境providerOptions.openai透传给 OpenAI 的底层请求参数示例设置了reasoningEffort: medium与reasoningSummary: detailed并通过satisfies OpenAILanguageModelResponsesOptions获得类型检查保障。CORS 配置对接前端useChat为了允许运行在localhost:3000的前端页面如 Next.js 开发服务器调用/chat/*接口示例为聊天路径配置了 CORSapp.use( /chat/*, cors({ origin: http://localhost:3000, allowMethods: [GET, POST, PUT, PATCH, DELETE, OPTIONS], allowHeaders: [Content-Type, Authorization], maxAge: 86400, }), );origin限定了允许的前端来源生产环境应替换为你的实际域名allowHeaders覆盖了Content-TypeJSON 请求必需与Authorization如需携带鉴权令牌maxAge: 86400让浏览器缓存预检请求结果一天减少 OPTIONS 请求次数其余端点如/text若同样需要跨域调用可参照此配置扩大app.use的匹配路径。此外GET /health提供了一个简单的存活探测c.text(Hono AI SDK example server is running!)便于部署后验证服务状态。流式响应的底层原理速览结合源码可以总结出本示例背后两条核心链路文本链路streamText().streamTextStreamPart流→toTextStream()提取纯文本 →createTextStreamResponse()以text/plain逐块下发。适用于日志、终端、简单渲染场景。UI 消息链路streamText().stream→toUIMessageStream()将文本增量、工具调用、完成事件等转换为UIMessageChunk块 →createUIMessageStreamResponse()包装为 HTTP 响应。toUIMessageStream内部通过TransformStream逐块转换见 to-ui-message-stream.ts并依据part.type维护流的最终状态completed / aborted / failed。两条链路的共同点都是创建后立即返回 Response、生成过程异步推进的流式模型因此模型首字延迟TTFT之后的内容可以持续、增量地到达客户端这也是对话体验流畅的关键。小结通过 examples/hono 这个示例你可以在一套 Hono 服务中同时获得最简文本流/text适合快速验证与通用消费端结构化 UI 消息流/、/chat可直接对接 AI SDK 前端useChat手动控制消息块/stream-data便于注入自定义数据或编排多条流基于ToolLoopAgent的联网搜索 Agent/chat演示了工具循环与 Provider 选项透传。如需在此基础上扩展可以参照 next-agentNext.js Agent 组合或 express、fastify其他 Node 框架的 AI SDK 接入方式对比学习AI SDK 各流式工具的完整参数定义可进一步查阅 packages/ai/src/ui-message-stream 与 packages/ai/src/text-stream 目录下的源码与类型注释。【免费下载链接】aiThe AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and agents项目地址: https://gitcode.com/GitHub_Trending/ai/ai创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考