基于Vercel AI SDK在AWS Amplify部署时流式API响应失效问题
问题分析与解决方案
本地使用Vercel AI SDK实现流式API响应正常,但部署到AWS Amplify后仅能获取完整响应、无法流式传输,核心原因是Amplify默认的响应缓冲策略、Edge Runtime兼容性或HTTP头配置未适配流式传输需求,以下是针对性解决办法:
1. 调整Amplify部署配置(amplify.yml)
在项目根目录的amplify.yml中添加路由头配置,禁用缓存并强制分块传输:
version: 1 frontend: phases: preBuild: commands: - npm install build: commands: - npm run build artifacts: baseDirectory: .next files: - '**/*' cache: paths: - node_modules/**/* # 新增API路由专属头配置 headers: - pattern: '/api/*' headers: - key: Transfer-Encoding value: chunked - key: Cache-Control value: no-cache, no-store, must-revalidate - key: Connection value: keep-alive
2. 替换Edge Runtime为Node.js Runtime
Amplify对Vercel Edge Runtime的支持存在兼容性限制,修改API路由代码移除Edge声明并显式设置流式响应头:
import { StreamingTextResponse, LangChainStream, Message } from 'ai'; import { ChatOpenAI } from 'langchain/chat_models/openai'; import { AIMessage, HumanMessage } from 'langchain/schema'; // 移除该行:export const runtime = 'edge'; export async function POST(req: Request) { const { messages } = await req.json(); const { stream, handlers } = LangChainStream(); const llm = new ChatOpenAI({ streaming: true, }); llm .call( (messages as Message[]).map(m => m.role == 'user' ? new HumanMessage(m.content) : new AIMessage(m.content), ), {}, [handlers], ) .catch(console.error); // 显式添加流式响应头 return new StreamingTextResponse(stream, { headers: { 'Transfer-Encoding': 'chunked', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', }, }); }
3. 检查Amplify API网关设置
若使用Amplify API Gateway,需确保:
- 禁用响应压缩(压缩会触发响应缓冲)
- 开启分块编码(chunked encoding)支持
操作路径:Amplify控制台 → 目标项目 → API模块 → 对应API设置 → 调整压缩与编码配置
4. 前端调试验证
可在前端添加回调,确认流式响应是否正常传递:
'use client'; import { useChat } from 'ai/react'; export default function Chat() { const { messages, input, handleInputChange, handleSubmit } = useChat({ onResponse: (response) => { console.log('响应头:', response.headers); console.log('是否支持流式:', response.body instanceof ReadableStream); }, }); return ( <div className="mx-auto w-full max-w-md py-24 flex flex-col stretch"> {messages.length > 0 ? messages.map(m => ( <div key={m.id} className="whitespace-pre-wrap"> {m.role === 'user' ? 'User: ' : 'AI: '} {m.content} </div> )) : null} <form onSubmit={handleSubmit}> <input className="fixed w-full max-w-md bottom-0 border border-gray-300 rounded mb-8 shadow-xl p-2" value={input} placeholder="Say something..." onChange={handleInputChange} /> </form> </div> ); }
内容的提问来源于stack exchange,提问作者Anni
相关产品推荐
相关产品推荐

