ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Rust构建AI Agent:多模态推理与工具调用实战指南

Rust构建AI Agent:多模态推理与工具调用实战指南 1. 先搞清楚 GAIA Level 1 测试到底在测什么如果你正在用 Rust 写 AI Agent或者对 Agent 的“智能”程度如何量化感到好奇那么 GAIA 的 Level 1 测试是一个非常好的、具体的切入点。它不是一个模糊的概念而是一套设计好的、可执行的基准测试任务。简单来说GAIA Level 1 测试的核心是评估一个 AI Agent 在处理多模态信息、执行精确推理和操作方面的基础能力。这里的“多模态”不只是文本还包括图像、表格、文档等。测试会给你一个任务描述比如“根据这张发票图片计算出总金额并填入表格”然后你需要让 Agent 去理解、分析并给出一个精确的、可验证的答案。这和我们平时用大语言模型LLM聊天或者生成文本有本质区别。LLM 的输出可以是开放性的、描述性的但 GAIA 测试要求的是确定性答案。答案对就是对错就是错没有“大概”“可能”。这对于检验一个 Agent 是否真的能“干活”而不是仅仅“能说会道”至关重要。所以当你准备用 Rust 来开发一个能通过这类测试的 Agent 时你面临的挑战就非常具体了你的 Agent 需要能稳定地接入多模态模型比如视觉理解模型、准确地解析任务指令、可靠地调用工具如计算器、文件读取、并严格按格式输出结果。整个过程必须可编程、可调试、可复现。Rust 在这类要求高性能、高可靠性和强类型安全的系统级任务中优势就体现出来了。2. 搭建 Rust 开发环境与核心依赖选择在动手写代码之前先把环境理顺。对于 AI Agent 开发尤其是涉及测试的环境的一致性比追求最新版本更重要。2.1 Rust 工具链与国内镜像配置首先确保 Rust 工具链安装正确。如果你在国内为了加速依赖下载务必配置镜像源。# 1. 安装 Rust如果尚未安装 # 官方推荐方式使用 rustup curl --proto ‘https’ --tlsv1.2 -sSf https://sh.rustup.rs | sh # 安装完成后需要重启终端或执行 source $HOME/.cargo/env # 2. 验证安装 rustc --version cargo --version # 3. 配置 Cargo 国内镜像以中科大源为例 # 编辑或创建 ~/.cargo/config 文件Linux/macOS或 %USERPROFILE%\.cargo\configWindows # 添加以下内容 [source.crates-io] replace-with ‘ustc’ [source.ustc] registry “git://mirrors.ustc.edu.cn/crates.io-index” # 如果你所在网络环境对 git 协议有限制也可以使用稀疏索引更快Rust 1.68 推荐 # 在 config 文件中添加 [registries] ustc { index “sparsehttps://mirrors.ustc.edu.cn/crates.io-index/” } [source.crates-io] replace-with ‘ustc’配置镜像后cargo build下载依赖的速度会有显著提升。这是后续所有工作的基础不要跳过。2.2 项目初始化与核心 Crate 选型我们用 Cargo 创建一个新项目并提前规划好需要的依赖。一个面向 GAIA 测试的 Agent 项目依赖会分为几层HTTP 客户端与异步运行时用于与模型 API如 OpenAI, Anthropic, 本地 Ollama通信。reqwesttokio是黄金组合。多模态处理处理图像、PDF等。image库用于基础图像操作pdf-extract或lopdf用于 PDF但更复杂的解析通常依赖外部服务或模型。工具调用与结构化输出让 LLM 的输出能被程序理解。serde和serde_json用于 JSON 序列化这是与 LLM 通信的主要格式。测试与日志logenv_logger用于记录运行过程anyhow和thiserror用于优雅的错误处理。我们来初始化项目并添加依赖cargo new rust-ai-agent-gaia --bin cd rust-ai-agent-gaia编辑Cargo.toml文件[package] name “rust-ai-agent-gaia” version “0.1.0” edition “2021” [dependencies] tokio { version “1”, features [“full”] } # 异步运行时 reqwest { version “0.12”, features [“json”] } # HTTP 客户端 serde { version “1”, features [“derive”] } # 序列化 serde_json “1” # JSON 处理 anyhow “1” # 便捷错误处理 log “0.4” # 日志接口 env_logger “0.11” # 日志实现 image “0.25” # 基础图像处理如需本地处理图片 # 暂时不添加复杂的 PDF 解析库初期可通过调用外部 API 解决 [dev-dependencies] # 测试相关依赖 # 后续可根据需要添加运行cargo build来拉取和编译依赖确保环境没问题。3. 设计 Agent 核心架构从单次对话到工具调用GAIA 测试不是一次简单的问答它要求 Agent 能按步骤执行任务。因此我们的 Agent 不能只是一个封装了 API 调用的函数它需要具备状态管理、工具调度和流程控制的能力。3.1 定义消息与对话历史与 LLM 交互的基本单元是消息。我们需要定义清晰的结构。// src/models.rs use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize)] pub enum Role { System, User, Assistant, Tool, // 用于工具调用的返回 } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Message { pub role: Role, pub content: String, // 可选用于 OpenAI 格式的 name 字段或工具调用的 tool_call_id } impl Message { pub fn new(role: Role, content: impl IntoString) - Self { Self { role, content: content.into(), } } } // 一个简单的对话历史管理 pub struct Conversation { messages: VecMessage, max_tokens: usize, // 用于粗略的上下文长度管理 } impl Conversation { pub fn new(system_prompt: Optionstr) - Self { let mut messages Vec::new(); if let Some(prompt) system_prompt { messages.push(Message::new(Role::System, prompt)); } Self { messages, max_tokens: 4096, // 示例值需根据模型调整 } } pub fn add_message(mut self, message: Message) { self.messages.push(message); // 简单的上下文窗口管理这里可以添加逻辑来限制总消息长度或条数 } pub fn get_messages(self) - [Message] { self.messages } }3.2 封装 LLM 客户端我们将与 LLM API 的交互封装起来这样后续切换模型提供商比如从 OpenAI 换到本地部署的 Llama会比较容易。// src/llm_client.rs use anyhow::{anyhow, Result}; use reqwest::Client; use serde_json::json; use log::{info, error}; use crate::models::{Conversation, Message, Role}; pub struct OpenAIClient { api_key: String, base_url: String, // 可用于指向 OpenAI 兼容的 API如 Ollama, LiteLLM client: Client, model: String, // 如 “gpt-4-turbo-preview”, “gpt-3.5-turbo” } impl OpenAIClient { pub fn new(api_key: impl IntoString, model: impl IntoString) - Self { Self { api_key: api_key.into(), base_url: “https://api.openai.com/v1”.to_string(), client: Client::new(), model: model.into(), } } // 设置自定义端点用于连接本地模型服务 pub fn with_base_url(mut self, base_url: impl IntoString) - Self { self.base_url base_url.into(); self } pub async fn chat_completion(self, conversation: Conversation) - ResultString { let url format!(“{}/chat/completions”, self.base_url); // 准备请求体 let messages: Vec_ conversation.get_messages() .iter() .map(|msg| { let role match msg.role { Role::System “system”, Role::User “user”, Role::Assistant “assistant”, Role::Tool “tool”, // 注意OpenAI 工具调用角色是 “tool” }; json!({ “role”: role, “content”: msg.content, }) }) .collect(); let body json!({ “model”: self.model, “messages”: messages, “temperature”: 0.1, // GAIA 测试需要低随机性追求精确 “max_tokens”: 1000, // 根据任务调整 }); let response self.client .post(url) .header(“Authorization”, format!(“Bearer {}”, self.api_key)) .header(“Content-Type”, “application/json”) .json(body) .send() .await?; if !response.status().is_success() { let error_text response.text().await?; error!(“API 请求失败: {}”, error_text); return Err(anyhow!(“API 请求失败: {}”, error_text)); } let response_json: serde_json::Value response.json().await?; info!(“API 响应: {:?}”, response_json); // 提取助手的回复内容 let content response_json[“choices”][0][“message”][“content”] .as_str() .ok_or_else(|| anyhow!(“响应中未找到 content 字段”))? .to_string(); Ok(content) } }3.3 实现基础工具调用框架GAIA 任务经常需要计算、查询、文件操作。我们需要让 Agent 能够“使用工具”。这里实现一个简单的工具注册和调用框架。// src/tools.rs use anyhow::Result; use async_trait::async_trait; use serde_json::Value; use log::info; // 工具 trait所有工具都必须实现这个接口 #[async_trait] pub trait Tool { // 工具的名称用于让 LLM 识别 fn name(self) - str; // 工具的描述用于构造系统提示词 fn description(self) - str; // 工具的输入参数模式可以用 JSON Schema 描述这里简化为字符串 fn parameters(self) - str; // 执行工具 async fn execute(self, input: Value) - ResultString; } // 一个具体的工具示例计算器 pub struct CalculatorTool; #[async_trait] impl Tool for CalculatorTool { fn name(self) - str { “calculator” } fn description(self) - str { “A calculator that can perform basic arithmetic operations (, -, *, /). Input should be a mathematical expression as a string.” } fn parameters(self) - str { r#“{“type”: “object”, “properties”: {“expression”: {“type”: “string”}}, “required”: [“expression”]}”# } async fn execute(self, input: Value) - ResultString { let expr input[“expression”] .as_str() .ok_or_else(|| anyhow::anyhow!(“Missing ‘expression’ field”))?; // 警告这里使用 eval 是极不安全的仅用于演示。 // 生产环境必须使用安全的数学表达式解析库如 meval。 info!(“CalculatorTool executing expression: {}”, expr); // 安全起见我们这里只做简单演示不实现 eval。 // 假设我们有一个安全的解析函数 safe_calculate let result safe_calculate(expr)?; Ok(result.to_string()) } } fn safe_calculate(_expr: str) - Resultf64 { // 此处应接入安全的数学库 // 例如meval::eval_str(expr).map_err(|e| anyhow!(e)) // 为演示我们返回一个固定值 Ok(42.0) } // 工具管理器负责注册和查找工具 pub struct ToolRegistry { tools: std::collections::HashMapString, Boxdyn Tool Send Sync, } impl ToolRegistry { pub fn new() - Self { Self { tools: std::collections::HashMap::new(), } } pub fn registerT: Tool Send Sync ‘static(mut self, tool: T) { self.tools.insert(tool.name().to_string(), Box::new(tool)); } pub fn get(self, name: str) - Optiondyn Tool { self.tools.get(name).map(|t| t.as_ref()) } pub fn list_descriptions(self) - VecString { self.tools.iter() .map(|(name, tool)| format!(“{}: {}”, name, tool.description())) .collect() } }我们需要在Cargo.toml中添加async-trait依赖。[dependencies] async-trait “0.1”4. 整合 Agent 并跑通第一个 GAIA 风格任务现在我们把对话、LLM 客户端和工具整合起来形成一个能执行简单多步骤任务的 Agent。4.1 构建系统提示词System Prompt系统提示词是 Agent 的“大脑”它定义了 Agent 的角色、能力和行为规范。对于 GAIA 测试提示词必须清晰指示 Agent 使用工具、逐步思考、并输出最终答案。// 这是一个示例系统提示词需要根据具体任务调整 const SYSTEM_PROMPT: str r#” 你是一个专门解决精确计算和推理任务的 AI 助手。 你的目标是准确理解用户的问题并给出最终的确切答案。 你必须遵循以下规则 1. 仔细分析用户的问题它可能包含文本、数字或对图像的描述。 2. 如果需要计算、查找信息或处理数据你必须使用我提供的工具。 3. 使用工具时请严格按照工具要求的格式提供输入。 4. 在得到工具返回的结果后结合结果继续推理直到得出最终答案。 5. 你的最终输出必须是纯粹的答案不要包含解释、推理过程或额外文本。 例如如果问题是“5加7等于多少”你只输出“12”。 “#;4.2 实现简单的任务执行循环我们实现一个简单的循环Agent 接收用户问题思考是否需要工具调用工具整合结果直到得出最终答案。// src/agent.rs use anyhow::{anyhow, Result}; use log::{info, warn}; use crate::llm_client::OpenAIClient; use crate::models::{Conversation, Message, Role}; use crate::tools::{Tool, ToolRegistry}; pub struct SimpleAgent { llm_client: OpenAIClient, tools: ToolRegistry, max_iterations: usize, // 防止无限循环 } impl SimpleAgent { pub fn new(llm_client: OpenAIClient, tools: ToolRegistry) - Self { Self { llm_client, tools, max_iterations: 10, } } pub async fn run(self, user_query: str) - ResultString { let mut conversation Conversation::new(Some(SYSTEM_PROMPT)); conversation.add_message(Message::new(Role::User, user_query)); for i in 0..self.max_iterations { info!(“第 {} 轮迭代”, i 1); // 1. 调用 LLM获取回复 let llm_response self.llm_client.chat_completion(conversation).await?; info!(“LLM 回复: {}”, llm_response); // 2. 分析回复是最终答案还是需要调用工具 // 这里是一个极度简化的逻辑。实际中你需要解析 LLM 的回复 // 判断是否包含工具调用请求例如特定的 JSON 格式或关键字。 // 为了演示我们假设 LLM 的回复如果包含 “ACTION:” 开头就是工具调用。 if let Some(tool_invocation) llm_response.strip_prefix(“ACTION:”) { // 解析工具调用这里简化实际应用需定义严格的格式如 JSON let parts: Vecstr tool_invocation.splitn(2, ‘|’).collect(); if parts.len() ! 2 { return Err(anyhow!(“工具调用格式错误: {}”, tool_invocation)); } let tool_name parts[0].trim(); let tool_input parts[1].trim(); info!(“尝试调用工具: {}输入: {}”, tool_name, tool_input); // 3. 执行工具 let tool self.tools.get(tool_name) .ok_or_else(|| anyhow!(“未知工具: {}”, tool_name))?; // 将输入解析为 JSON简化处理实际需要更健壮的解析 let input_json: serde_json::Value serde_json::from_str(tool_input) .map_err(|e| anyhow!(“工具输入不是有效 JSON: {}, 错误: {}”, tool_input, e))?; let tool_result tool.execute(input_json).await?; info!(“工具 ‘{}’ 返回结果: {}”, tool_name, tool_result); // 4. 将工具结果作为一条新消息加入对话历史 conversation.add_message(Message::new(Role::Tool, tool_result)); // 继续下一轮循环 } else { // 没有检测到工具调用假设 LLM 给出了最终答案 info!(“Agent 得出最终答案: {}”, llm_response); return Ok(llm_response.trim().to_string()); } } Err(anyhow!(“达到最大迭代次数 ({}) 仍未得出最终答案”, self.max_iterations)) } }4.3 运行一个完整的测试用例让我们在main.rs中把所有部分串联起来模拟一个 GAIA Level 1 风格的简单任务。// src/main.rs mod agent; mod llm_client; mod models; mod tools; use anyhow::Result; use env_logger; use log::info; use crate::agent::SimpleAgent; use crate::llm_client::OpenAIClient; use crate::tools::{CalculatorTool, ToolRegistry}; #[tokio::main] async fn main() - Result() { // 初始化日志 env_logger::init(); info!(“启动 Rust AI Agent GAIA 测试程序”); // 1. 初始化 LLM 客户端 // 注意在实际运行前你需要设置环境变量 OPENAI_API_KEY let api_key std::env::var(“OPENAI_API_KEY”) .expect(“请设置 OPENAI_API_KEY 环境变量”); let llm_client OpenAIClient::new(api_key, “gpt-3.5-turbo”); // 或 gpt-4 // 2. 初始化工具注册表并注册工具 let mut tool_registry ToolRegistry::new(); tool_registry.register(CalculatorTool); // 3. 创建 Agent let agent SimpleAgent::new(llm_client, tool_registry); // 4. 运行一个测试任务 // 任务描述一个简单的多步骤计算问题模仿 GAIA 的风格。 let test_query “我有一个购物清单苹果 3 元一个我买了 5 个香蕉 2 元一根我买了 4 根。我付了 50 元应该找回多少钱请逐步计算。”; info!(“执行测试任务: {}”, test_query); match agent.run(test_query).await { Ok(answer) { println!(“\n 任务完成 ”); println!(“问题: {}”, test_query); println!(“Agent 最终答案: {}”, answer); // 我们可以在这里添加答案验证逻辑 let expected “27”; // (3*5 2*4) 23, 50-2327 if answer.contains(expected) { println!(“✅ 答案正确包含预期结果 {}”, expected); } else { println!(“⚠️ 答案可能不正确。预期找到 ‘{}’但答案是 ‘{}’”, expected, answer); } } Err(e) { println!(“❌ 任务执行失败: {}”, e); } } Ok(()) }运行前准备将你的 OpenAI API Key 设置为环境变量export OPENAI_API_KEY‘sk-...’Linux/macOS或在运行命令前设置。运行cargo run。如果一切顺利你会看到日志输出并最终得到 Agent 计算出的答案。这个流程虽然简单但已经包含了 GAIA 测试 Agent 的核心骨架理解复杂指令、规划步骤通过 LLM 思考、调用工具计算器、整合结果、输出最终答案。5. 向真实 GAIA 测试迈进处理多模态与复杂任务我们上面的例子只处理了文本和计算。真实的 GAIA Level 1 测试会涉及图像、表格、文档。要应对这些我们需要升级我们的 Agent。5.1 集成视觉理解能力对于图像类任务我们不能直接将图片像素送给 GPT-3.5/4。我们需要图像预处理可能需要调整大小、格式转换。图像理解使用多模态模型如 GPT-4V、Claude 3 Opus、或开源的 LLaVA来生成图像的文本描述。将描述融入上下文把生成的描述作为文本信息连同原始问题一起交给负责推理的 LLM。我们可以创建一个VisionTool// 在 src/tools.rs 中添加 pub struct VisionTool { // 这里可以持有另一个专门处理图像的 LLM 客户端 // 或者直接使用支持多模态的同一个客户端如 GPT-4V } #[async_trait] impl Tool for VisionTool { fn name(self) - str { “describe_image” } fn description(self) - str { “Describes the content of an image file. Provide the local file path.” } fn parameters(self) - str { r#“{“type”: “object”, “properties”: {“file_path”: {“type”: “string”}}, “required”: [“file_path”]}”# } async fn execute(self, input: Value) - ResultString { let file_path input[“file_path”] .as_str() .ok_or_else(|| anyhow::anyhow!(“Missing ‘file_path’ field”))?; // 1. 读取图片文件 // 2. 编码如 base64或调用视觉 API // 3. 获取文本描述 // 这是一个伪实现 info!(“VisionTool processing image: {}”, file_path); // 假设我们调用了一个函数 call_vision_api let description call_vision_api(file_path).await?; Ok(format!(“图像描述: {}”, description)) } } async fn call_vision_api(_path: str) - ResultString { // 这里应集成真实的视觉 API 调用例如 // - 使用 reqwest 调用 OpenAI GPT-4V // - 使用本地部署的 LLaVA 模型 // 返回图像的文本描述 Ok(“这是一张发票的图片上面有项目、数量和单价。”.to_string()) }然后在系统提示词中告诉 Agent“如果你需要理解图片内容请使用describe_image工具并提供图片路径。”5.2 处理结构化数据表格、JSONGAIA 测试经常需要从表格或结构化文档中提取信息并计算。我们可以创建ExtractTableTool或QueryCSVTool。pub struct QueryCSVTool { // 可以预加载 CSV 文件到内存 } #[async_trait] impl Tool for QueryCSVTool { fn name(self) - str { “query_csv” } fn description(self) - str { “Queries a CSV file with a given condition and returns matching rows or computed results. Input: {\”file_path\”: \”data.csv\”, \”query\”: \”column_name value\”}” } fn parameters(self) - str { r#“{“type”: “object”, “properties”: {“file_path”: {“type”: “string”}, “query”: {“type”: “string”}}, “required”: [“file_path”, “query”]}”# } async fn execute(self, input: Value) - ResultString { let file_path input[“file_path”].as_str().unwrap(); let query input[“query”].as_str().unwrap(); // 使用 csv crate 读取文件并执行简单查询 // 这里简化处理 Ok(format!(“对文件 {} 执行查询 ‘{}’ 的结果是: …”, file_path, query)) } }在Cargo.toml中添加csv依赖。[dependencies] csv “1”5.3 优化 Agent 的推理流程我们之前的SimpleAgent中工具调用检测逻辑查找 “ACTION:”非常脆弱。生产级 Agent 应该使用 LLM 的函数调用Function Calling或工具调用Tool Calls原生支持。以 OpenAI 为例我们需要在请求 LLM 时将工具列表以特定格式JSON Schema发送。LLM 会在回复中指示它想调用哪个工具并提供参数。我们解析这个指示执行工具并将结果以特定角色tool和tool_call_id发回给 LLM。LLM 根据工具结果生成下一步回复或最终答案。这需要修改我们的llm_client和agent模块以支持 OpenAI 的工具调用格式。这是构建健壮 Agent 的关键一步代码量会增加但交互更可靠。6. 测试、评估与避坑指南开发完成后如何验证你的 Agent 确实能应对 GAIA 测试6.1 构建测试集与评估脚本不要手动一个个测试。创建一个小型的、本地的 GAIA 风格测试集。// tests/integration_test.rs use rust_ai_agent_gaia::agent::SimpleAgent; // … 初始化 agent … #[tokio::test] async fn test_gaia_style_arithmetic() { let test_cases vec![ (“买3个5元的苹果和2个4元的香蕉总价多少”, “23”), (“100减去35再除以5结果是多少”, “13”), // 更复杂的多步骤问题 ]; for (query, expected_answer) in test_cases { let result agent.run(query).await.unwrap(); assert!( result.contains(expected_answer), “Query: ‘{}’ | Expected: ‘{}’ | Got: ‘{}’”, query, expected_answer, result ); } }使用cargo test来运行这些集成测试。6.2 常见问题与排查顺序当你运行 Agent 遇到问题时按这个顺序排查认证与网络API Key 是否正确网络能否访问 API 端点OPENAI_API_KEY环境变量设置了吗如果是本地模型服务启动了吗输入格式用户的问题是否清晰系统提示词是否明确要求使用工具工具的描述 LLM 能理解吗输出解析LLM 的回复是否被正确解析是直接给出了答案还是发出了工具调用请求工具调用的格式解析对吗工具执行工具本身能正常工作吗输入参数格式对吗文件路径存在吗权限够吗上下文管理对话历史是否过长导致模型忘记了指令或早期信息我们的Conversation结构是否需要进行 Token 计数和截断模型能力你用的模型如 gpt-3.5-turbo是否足够完成多步骤推理和工具调用对于复杂任务可能需要升级到 GPT-4。迭代循环是否陷入了无限循环检查max_iterations和工具调用结果是否被正确加入历史。6.3 Rust 特有的优势与注意事项性能与安全Rust 的零成本抽象和内存安全使得构建长期运行、高并发的 Agent 服务更有信心。工具调用中的输入验证也更容易做得严谨。错误处理利用anyhow和thiserror构建清晰的错误传播链能快速定位是网络问题、API 问题、工具逻辑问题还是流程问题。依赖管理Cargo 让依赖管理非常清晰。但要注意一些 AI 相关的 Rust 库如llm用于本地模型推理可能还不成熟与 Python 生态相比有差距。很多时候用 Rust 做 Agent 的“大脑”流程控制、工具调度用 Python 或 HTTP 服务做“感官”调用成熟的 Python 模型库是更务实的架构。异步编程Agent 需要频繁进行网络 I/O调用 LLM API、工具 APItokio异步运行时是必备的。确保你的代码正确地await并且错误在异步上下文中得到处理。7. 总结从 Demo 到实用 Agent 的路径通过以上步骤我们用 Rust 搭建了一个能通过简单 GAIA 风格测试的 Agent 雏形。它具备了对话管理、工具调用和简单推理循环的能力。要让它真正能应对 GAIA Level 1 的挑战你还需要升级工具调用实现真正的 OpenAI 格式的函数调用这是稳定性的关键。丰富工具集集成 OCR用于图片文字提取、PDF 解析、网页抓取、数据库查询等工具。强化系统提示词工程针对不同类型的 GAIA 任务数学、表格、文档、图片设计更专业、约束更强的提示词。实现评估流水线自动化地运行测试集统计准确率并分析失败案例是因为视觉理解错误、推理错误还是工具使用错误。考虑本地化部署如果追求低成本和隐私可以研究用 Rust 绑定本地模型如通过llm库运行量化后的 Llama 3并用本地视觉模型如 LLaVA处理图像。这将是 Rust 大显身手的领域。最终一个强大的 AI Agent 不是一个魔法黑盒而是一个由可靠的编程框架、清晰的任务流程、精准的工具集和有效的提示词共同构成的系统工程。Rust 为这个工程的底层基础设施提供了性能和可靠性的保障而如何设计 Agent 的“思维链”则需要你深入理解具体任务如 GAIA 测试并不断迭代优化。从这个简单的示例开始逐步填充血肉你就能搭建出属于自己的、能解决实际问题的智能体。
返回列表