使用 AWS SDK for Rust 调用 Amazon Bedrock Runtime:Converse、流式输出与工具调用实战指南

发布时间:2026/9/29 9:20:26
使用 AWS SDK for Rust 调用 Amazon Bedrock Runtime:Converse、流式输出与工具调用实战指南
示例工程教程后端【免费下载链接】aws-doc-sdk-examplesWelcome to the AWS Code Examples Repository. This repo contains code examples used in the AWS documentation, AWS SDK Developer Guides, and more. For more information, see the Readme.md file below.项目地址https://gitcode.com/gh_mirrors/aw/aws-doc-sdk-examples点击查看免费下载本篇技术指南以仓库rustv1/examples/bedrock-runtime目录下的官方示例为核心系统讲解如何用 AWS SDK for Rust 对接 Amazon Bedrock Runtime 的基础模型包括单轮 Converse 调用、ConverseStream 流式输出以及一个完整的模型 外部天气工具的工具调用Tool Use场景。读完本文你将掌握 Converse API 的请求构造、流式分块解析、JSON Schema 工具声明、多轮对话与工具结果回填的完整实现方式可直接在本仓库代码基础上运行和二次开发。一、概述这是关于什么的示例集Amazon Bedrock Runtime 是一项全托管的 AWS 服务它让开发者能够方便地使用来自第三方提供商和 Amazon 自家的基础模型Foundation Models。本示例集展示了如何通过AWS SDK for Rust与该服务交互对应的官方描述位于 rustv1/examples/bedrock-runtime/README.md其代码全部位于 rustv1/examples/bedrock-runtime/src/bin 目录下。整个示例集只包含一个 Cargo 包package 名为bedrock-runtime参见 rustv1/examples/bedrock-runtime/Cargo.toml由三个独立的二进制程序组成二进制源文件说明converseconverse.rs使用 Converse API 发起一次单轮文本对话converse-streamconverse-stream.rs使用 ConverseStream API 以流式方式接收模型输出tool-usetool-use.rs场景示例用 Converse API 结合外部天气工具实现应用—模型—工具三方协作二、运行前提Prerequisites根据 rustv1/README.md运行这些示例需要满足AWS 账户与凭证已按 AWS SDK for Rust 官方入门指南配置好默认凭证Credentials和默认区域Region可通过AWS_PROFILE、AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY、AWS_REGION等环境变量注入rustv1/README.mdRust 工具链安装 Cargo通常随 rustup 一并安装区域与模型权限示例源码中硬编码了区域us-east-1与模型 IDanthropic.claude-3-haiku-20240307-v1:0如 converse.rs。运行前需确认你的账号在该区域已开通 Anthropic Claude 模型的访问权限否则会收到模型访问相关的错误响应。示例的依赖在 Cargo.toml 中声明核心包括[dependencies] aws-config 1.5.4 # 加载 SDK 默认配置 aws-sdk-bedrockruntime 1.40.0 # Bedrock Runtime 服务 SDK aws-smithy-runtime-api 1.7.1 # Smithy 运行时 APIHTTP Response 类型等 aws-smithy-types 1.2.0 # Smithy 数据类型如 Document reqwest 0.12.5 # 用于工具场景中请求外部天气 API serde 1.0.204 serde_json 1.0.120 tokio { version 1.38.1, features [full] } # 异步运行时 tracing 0.1.40 tracing-subscriber 0.3.18 # 结构化日志输出三、示例一Converse 单轮对话converse.rs 演示了最基础的 Bedrock Runtime 调用方式通过ConverseAPI 向 Claude 发送一条用户消息并打印模型回复。3.1 请求构造核心调用逻辑在main函数中converse.rs#L43-L77let sdk_config aws_config::defaults(BehaviorVersion::latest()) .region(CLAUDE_REGION) .load() .await; let client Client::new(sdk_config); let response client .converse() .model_id(MODEL_ID) .messages( Message::builder() .role(ConversationRole::User) .content(ContentBlock::Text(USER_MESSAGE.to_string())) .build() .map_err(|_| failed to build message)?, ) .send() .await;关键点解读aws_config::defaults(BehaviorVersion::latest())按最新行为版本加载 SDK 配置随后通过.region(...)显式指定区域这里固定为us-east-1Client::new(sdk_config)基于配置构建 Bedrock Runtime 客户端converse()请求链.model_id()指定基础模型 ID.messages()传入对话消息列表每条消息由Message::builder()构造通过.role(ConversationRole::User)声明角色、.content(ContentBlock::Text(...))填充文本内容.send().await发起请求并等待响应返回ResultConverseOutput, SdkErrorConverseError。3.2 解析响应文本响应解析通过辅助函数get_converse_output_text完成converse.rs#L79-L92fn get_converse_output_text(output: ConverseOutput) - ResultString, BedrockConverseError { let text output .output() // 取 ConverseOutput 的 output 字段 .ok_or(no output)? // 可能是空 .as_message() // 转换为 Message 联合类型 .map_err(|_| output not a message)? .content() // 取消息内容块列表 .first() .ok_or(no content in message)? .as_text() // 只接受纯文本内容块 .map_err(|_| content is not text)? .to_string(); Ok(text) }这里体现了 Converse 响应模型的结构ConverseOutput → Message → 内容块列表 → ContentBlock::Text逐层解包并做类型检查任何一层不符合预期都会返回明确的中文化错误信息。3.3 错误处理模式示例自定义了BedrockConverseError错误类型converse.rs#L19-L40并针对ConverseError的服务端错误做了映射impl FromConverseError for BedrockConverseError { fn from(value: ConverseError) - Self { BedrockConverseError::from(match value { ConverseError::ModelTimeoutException(_) Model took too long, ConverseError::ModelNotReadyException(_) Model is not ready, _ Unknown, }) } }也就是说当模型响应超时或模型尚未就绪时程序会给出可读的错误提示其余未知错误统一归类为 Unknown。这种自定义错误类型 From转换 服务端错误枚举匹配的写法是 SDK for Rust 项目中推荐采用的错误处理范式。四、示例二ConverseStream 流式输出converse-stream.rs 演示了流式调用模型一边生成一边返回内容增量token适合构建打字机式输出体验。4.1 发起流式请求调用入口同样在main中converse-stream.rs#L70-L98与 Converse 的唯一区别是使用converse_stream()方法let response client .converse_stream() .model_id(MODEL_ID) .messages( Message::builder() .role(ConversationRole::User) .content(ContentBlock::Text(USER_MESSAGE.to_string())) .build() .map_err(|_| failed to build message)?, ) .send() .await; let mut stream match response { Ok(output) Ok(output.stream), // ConverseStreamOutput 中携带事件流 Err(e) Err(BedrockConverseStreamError::from( e.as_service_error().unwrap(), )), }?;4.2 逐块消费事件流拿到output.stream后通过recv().await循环接收流式事件converse-stream.rs#L100-L116loop { let token stream.recv().await; match token { Ok(Some(text)) { let next get_converse_output_text(text)?; print!({}, next); // 增量打印形成打字机效果 Ok(()) } Ok(None) break, // 流结束 Err(e) Err(e .as_service_error() .map(BedrockConverseStreamError::from) .unwrap_or(BedrockConverseStreamError( Unknown error receiving stream.into(), ))), }? }Ok(Some(event))收到一个流事件立即提取文本并print!注意用print!而非println!因为内容是连续增量最后再统一补一个换行Ok(None)流已结束跳出循环Err(e)流传输过程中出错转换为自定义错误类型。4.3 增量事件的类型匹配流事件的类型是ConverseStreamOutput需要在辅助函数中按事件变体匹配converse-stream.rs#L123-L133fn get_converse_output_text( output: ConverseStreamOutputType, ) - ResultString, BedrockConverseStreamError { Ok(match output { ConverseStreamOutputType::ContentBlockDelta(event) match event.delta() { Some(delta) delta.as_text().cloned().unwrap_or_else(|_| .into()), None .into(), }, _ .into(), // 其他事件类型如消息开始/结束标记不产出文本 }) }只有当事件是ContentBlockDelta内容块增量且其delta携带文本时才输出内容其余事件类型返回空字符串从而保证只打印模型真正生成的文字。4.4 流式专用错误处理流式场景的错误分为两类示例分别处理converse-stream.rs#L37-L67ConverseStreamError请求阶段的错误同样区分ModelTimeoutException、ModelNotReadyExceptionConverseStreamOutputError流内事件级别的错误细分ValidationException、ThrottlingException等并通过message()方法提取具体错误文本该类型要求引入error::ProvideErrorMetadatatrait。五、场景示例使用 Converse API 的工具调用Tool Use工具调用场景核心逻辑起始于 tool-use.rs#L242是本示例集中最完整、也最有实战价值的示例。它展示了应用程序—生成式 AI 模型—外部工具/API之间典型的交互闭环模型本身不直接访问外界而是通过声明好的工具本例为一个天气查询工具向外部世界获取实时数据从而基于用户输入提供真实、实时的天气信息。5.1 场景架构与调用闭环整个tool-use场景在ToolUseScenario结构体中封装tool-use.rs#L246-L251它持有四份关键状态struct ToolUseScenario { client: Client, // Bedrock Runtime 客户端 conversation: VecMessage, // 完整的多轮对话历史 system_prompt: SystemContentBlock, // 系统提示词 tool_config: ToolConfiguration, // 工具配置声明可用工具 }其运行闭环如下由run→send_to_bedrock→process_model_response→handle_tool_use→invoke_tool组成交互式读取用户输入get_input输入以x开头即退出把用户消息追加进conversation连同系统提示词与工具配置一起发送给模型检查响应中的stop_reasontool-use.rs#L333-L342StopReason::ToolUse模型要求调用工具进入工具执行分支StopReason::EndTurn模型已给出最终答复打印文本并结束本轮执行工具后将ToolResultBlock以User角色的消息回填给模型继续下一轮对话循环上限为MAX_RECURSIONS 5防止无限循环。5.2 工具声明JSON Schema 输入定义工具通过ToolConfigurationToolSpecification声明tool-use.rs#L253-L274let tool_config ToolConfiguration::builder() .tools(Tool::ToolSpec( ToolSpecification::builder() .name(TOOL_NAME) // Weather_Tool .description(TOOL_DESCRIPTION) // 工具用途说明 .input_schema(ToolInputSchema::Json(make_tool_schema())) .build() .unwrap(), )) .build() .unwrap();其中make_tool_schema()以aws_smithy_types::Document构造标准的 JSON Schematool-use.rs#L53-L91完整声明了工具入参结构{ type: object, properties: { latitude: { type: string, description: Geographical WGS84 latitude of the location. }, longitude: { type: string, description: Geographical WGS84 longitude of the location. } }, required: [latitude, longitude] }这段 schema 是模型决定何时调用、用什么参数调用的依据required字段确保模型必须同时给出经纬度两个参数。5.3 系统提示词约束SYSTEM_PROMPT常量为模型的行为划定了边界tool-use.rs#L30-L44例如只使用Weather_Tool获取数据、由模型自行从地点名推断经纬度、绝不编造或猜测信息、只回答天气相关问题等。这类提示词约束是让工具调用结果可控的关键工程实践。5.4 工具执行对接 Open-Meteo 天气 API模型一旦发起ToolUse程序便执行invoke_tooltool-use.rs#L376-L398根据tool.name()分发到fetch_weather_datatool-use.rs#L188-L240const ENDPOINT: str https://api.open-meteo.com/v1/forecast; async fn fetch_weather_data( tool_use: ToolUseBlock, ) - ResultToolResultBlock, ToolUseScenarioError { // 1. 从模型的 tool_use 输入中解析 latitude / longitude let input tool_use.input(); let latitude input.as_object().unwrap().get(latitude).unwrap().as_string().unwrap(); let longitude input.as_object().unwrap().get(longitude).unwrap().as_string().unwrap(); // 2. 用 reqwest 请求 Open-Meteo 预报接口 let params [ (latitude, latitude), (longitude, longitude), (current_weather, true), ]; let response reqwest::Client::new() .get(ENDPOINT) .query(params) .send() .await .map_err(|e| ToolUseScenarioError(format!(Error requesting weather: {e:?})))? .error_for_status() .map_err(|e| ToolUseScenarioError(format!(Failed to request weather: {e:?})))?; // 3. 将响应文本封装为 ToolResultBlock 返回 let result String::from_utf8(bytes.to_vec())?; Ok(ToolResultBlock::builder() .tool_use_id(tool_use.tool_use_id()) // 关联到本次工具调用 .content(ToolResultContentBlock::Text(result)) .build()?) }执行过程中会打印工具调用与响应信息如Executing tool: Weather_Tool with input: ...方便观察模型与工具的交互过程。5.5 把工具结果回填给模型handle_tool_use负责组装工具结果消息tool-use.rs#L350-L374遍历模型返回的内容块遇到ContentBlock::Text就打印给用户遇到ContentBlock::ToolUse就执行工具并把ToolResult收集起来最后以User角色构造一条新消息ContentBlock::ToolResult追加进对话历史再次调用send_to_bedrock()把结果交回模型让模型基于真实天气数据生成最终答复。注意tool_use_id必须与模型发来的工具调用 ID 保持一致Bedrock 才能把结果与对应的工具请求正确关联。5.6 递归上限保护MAX_RECURSIONS: i8 5tool-use.rs#L48用于限制单轮用户请求触发的最大模型→工具→模型循环次数防止模型陷入反复调用工具的无限循环若超过上限程序会以Exceeded MAX_ITERATIONS when calling tools错误终止。5.7 交互体验程序启动与结束时分别打印header()与footer()tool-use.rs#L156-L186支持诸如以下自然语言查询Whats the weather like in New York?Current weather for latitude 40.70, longitude -74.01Is it warmer in Rome or Barcelona today?输入x并回车即可退出程序。六、如何运行示例与测试6.1 运行二进制根据 rustv1/README.md 的说明每个示例对应src/bin下的一个二进制可在rustv1/examples/bedrock-runtime目录下用cargo run --bin执行cargo run --bin converse cargo run --bin converse-stream cargo run --bin tool-use6.2 运行测试与日志控制单元测试cargo test不会对 AWS 账号产生任何变更或费用集成测试cargo test -- --ignored此类测试可能产生费用具体以各示例目录说明为准日志级别RUST_LOG示例使用tracing_subscriber输出结构化日志rustv1/README.md常用取值包括info显示程序常规输出{crate_name}debug显示更有用的逐操作细节aws_smithy_http_tower::dispatchtrace打印每次 AWS API 调用的完整 HTTP 请求aws_smithy_http::middlewaretrace打印每次调用的完整 HTTP 响应。6.3 费用与安全注意事项按照官方 README 的明确提醒rustv1/examples/bedrock-runtime/README.md运行这些代码可能产生 AWS 费用运行测试同样可能产生费用具体请查阅 AWS 定价与免费套餐说明建议为代码授予最小权限least privilege只授予完成任务所需的最低权限这些代码未经所有 AWS 区域测试请结合各区域的服务可用情况使用由于工具场景会请求 Open-Meteo 这一外部服务运行tool-use时还需要具备访问外部网络的网络环境。七、小结与进一步探索从 converse.rs 的单轮调用到 converse-stream.rs 的流式输出再到 tool-use.rs 完整的工具调用场景这套 Rust 示例覆盖了 Bedrock Runtime 最常用的三种交互形态。核心要点可以归纳为统一入口Client::converse()与Client::converse_stream()承担全部文本交互模型由model_id指定消息结构一切交互都围绕Message(role content)展开ContentBlock支持文本、工具调用、工具结果等多种变体工具调用闭环用 JSON Schema 声明工具 → 模型返回StopReason::ToolUse→ 程序执行工具 → 以User角色回填ToolResultBlock→ 继续对话直至EndTurn工程化细节自定义错误类型、流式事件匹配、递归上限与系统提示词约束都是生产级应用的必备要素。如需继续深入研究可对照阅读rustv1/README.md全部 Rust 示例的通用前提、测试与日志说明rustv1/examples/bedrock-runtime/Cargo.toml依赖与版本rustv1/examples/bedrock-runtime/src/bin/tool-use.rs工具调用场景完整实现Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: Apache-2.0赞分享示例工程教程后端【免费下载链接】aws-doc-sdk-examplesWelcome to the AWS Code Examples Repository. This repo contains code examples used in the AWS documentation, AWS SDK Developer Guides, and more. For more information, see the Readme.md file below.项目地址https://gitcode.com/gh_mirrors/aw/aws-doc-sdk-examples点击查看免费下载相关推荐使用 AWS SDK for JavaScript (v3) 调用 Amazon Bedrock RuntimeConverse、流式输出与工具调用实战指南使用 AWS SDK for JavaScript v3 调用 Amazon Bedrock RuntimeConverse、流式输出与工具调用实战指南 本文示例工程教程后端使用 AWS SDK for .NET 调用 Amazon Bedrock RuntimeConverse、工具调用与图像生成实战指南使用 AWS SDK for .NET 调用 Amazon Bedrock RuntimeConverse、工具调用与图像生成实战指南 导读 本文以开源仓库示例工程教程后端AWS SDK for Go V2 调用 Amazon Bedrock RuntimeConverse 与 InvokeModel 实战指南AWS SDK for Go V2 调用 Amazon Bedrock RuntimeConverse 与 InvokeModel 实战指南 Amazon B示例工程教程后端上一篇Pomelo.EntityFrameworkCore.MySql故障排除手册解决10个最常见的连接和性能问题下一篇彻底清除Loop窗口管理工具残留文件从根源解决Mac卸载难题创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考