React调用AWS Bedrock Claude v2遇阻,求代码修复与流式响应指导
问题修复与实现方案
错误原因分析
1. "global is not defined" 错误
AWS SDK v2依赖Node.js环境的global对象,但浏览器中没有这个全局变量。之前的vite配置将global设为空对象,无法满足SDK的依赖需求。
2. "BedrockRuntimeClient is not a function" 错误
AWS SDK v2中,Bedrock Runtime客户端并非直接从aws-sdk包导出,且实例化客户端需要使用new关键字,你代码中直接调用BedrockRuntimeClient()而没有使用new,同时导入路径错误。
代码修复步骤
步骤1:修正Vite配置
更新vite.config.js,正确映射global到浏览器的window对象,并添加必要的polyfill:
import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' export default defineConfig({ plugins: [react()], define: { global: 'window', 'process.env': process.env }, resolve: { alias: { buffer: 'buffer/', }, }, })
同时安装缺失的polyfill依赖:
npm install buffer
步骤2:修正Message组件代码
核心修改点:
- 正确导入Bedrock Runtime客户端
- 使用
new关键字实例化客户端,并通过useMemo避免重复创建 - 修复变量名冲突(
input变量重复定义) - 绑定输入框的 onChange 事件,将用户输入同步到状态
- 添加调用API的触发逻辑(比如按钮点击)
import React, { useState, useMemo } from "react"; import { Input, Button, VStack } from "@chakra-ui/react"; import AWS from "aws-sdk"; export default function Message() { const [input, setInput] = useState(""); const [maxtoken, setMaxToken] = useState(300); const [temperature, setTemperature] = useState(1); const [topK, setTopK] = useState(250); const [topP, setTopP] = useState(0.999); const [response, setResponse] = useState(""); // 使用useMemo创建客户端,避免每次渲染重复实例化 const bedrockClient = useMemo(() => { return new AWS.BedrockRuntime({ region: "us-east-1", credentials: { accessKeyId: process.env.AWS_ACCESS_KEY_ID ?? "", secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY ?? "", }, }); }, []); async function makeBedRockCall() { if (!input.trim()) return; setResponse(""); const requestParams = { prompt: `\n\nHuman:${input}\n\nAssistant:`, max_tokens_to_sample: maxtoken, temperature: temperature, top_k: topK, top_p: topP, }; const params = { body: JSON.stringify(requestParams), contentType: "application/json", accept: "application/json", modelId: "anthropic.claude-v2", }; try { const result = await bedrockClient.invokeModel(params).promise(); const completion = JSON.parse(Buffer.from(result.body).toString("utf-8")); setResponse(completion.completion); } catch (error) { console.error("调用Bedrock API失败:", error); setResponse("错误:" + error.message); } } return ( <VStack spacing={4} className="pt-5"> <Input placeholder="输入问题..." value={input} onChange={(e) => setInput(e.target.value)} /> <Button colorScheme="blue" onClick={makeBedRockCall}> 发送请求 </Button> {response && <div className="w-full p-4 bg-gray-50 rounded"> {response} </div>} </VStack> ); }
流式响应实现思路
Bedrock Claude支持通过invokeModelWithResponseStream接口实现流式输出,以下是关键实现步骤:
1. 修改API调用逻辑
使用invokeModelWithResponseStream替代invokeModel,并处理流式返回的chunk数据:
async function makeStreamingBedRockCall() { if (!input.trim()) return; setResponse(""); const requestParams = { prompt: `\n\nHuman:${input}\n\nAssistant:`, max_tokens_to_sample: maxtoken, temperature: temperature, top_k: topK, top_p: topP, }; const params = { body: JSON.stringify(requestParams), contentType: "application/json", accept: "application/json", modelId: "anthropic.claude-v2", }; try { const stream = await bedrockClient.invokeModelWithResponseStream(params).promise(); // 处理流式数据 for await (const chunk of stream.body) { if (chunk.chunk) { const data = JSON.parse(Buffer.from(chunk.chunk.bytes).toString("utf-8")); setResponse(prev => prev + data.completion); } } } catch (error) { console.error("流式调用失败:", error); setResponse("错误:" + error.message); } }
2. 注意事项
- 浏览器环境中需要确保支持异步迭代器(
for await...of),现代浏览器已支持,若需兼容旧版本可引入polyfill - 流式响应会持续更新状态,注意React的状态更新频率,避免不必要的重渲染
- 重要安全提示:浏览器端直接暴露AWS密钥存在严重安全风险,POC阶段可临时使用,但生产环境必须通过后端代理请求Bedrock API,绝不允许在前端代码中嵌入AWS密钥
额外建议
- 使用TanStack Query管理API请求:将Bedrock调用逻辑封装为TanStack Query的
useQuery或useMutation,自动处理加载状态、缓存和错误重试 - 添加加载状态提示:在请求过程中显示加载动画,提升用户体验
- 错误边界:为组件添加错误边界,避免单个组件崩溃影响整个应用
内容的提问来源于stack exchange,提问作者LittleZoski
相关产品推荐
相关产品推荐

