- AI Agent
- Agent 框架
- RAG
- 后端
【免费下载链接】rig
⚙️🦀 Build modular and scalable LLM Applications in Rust
rig-gemini-grpc 是 Rig 项目中负责接入 Google Gemini gRPC API 的独立 companion crate,相比 REST 通道具备更优的性能与更强的类型安全(见 README 的定位说明)。本文以该 crate 的 CHANGELOG 为主线,结合仓库内 client.rs、completion.rs、streaming.rs、embedding.rs 等源码,讲解从零接入、核心能力、底层实现原理到关键演进路径,帮助你完整掌握在 Rust 生态中使用 Gemini gRPC 完成对话补全、流式输出、Embedding 与工具调用的实战方案。
一、模块定位:Rig 生态中的 Gemini gRPC 通道
rig-gemini-grpc 是 Rig 工作区中的一个 companion crate,将 Google Gemini 的 gRPC 接口(google.ai.generativelanguage.v1beta)封装为 Rig 统一的Model/Transport抽象。它的包描述为 "Google Gemini gRPC API integration for Rig",依赖rig-core(版本 0.42.0),并通过tonic栈完成传输层工作(见 Cargo.toml):
[dependencies] rig-core = { path = "../rig-core", version = "0.42.0", default-features = false } tonic = { workspace = true, features = ["transport", "tls-ring", "tls-webpki-roots", "zstd", "gzip"] } tonic-prost = { workspace = true }其中tonic的 feature 组合(transport、tls-ring/tls-webpki-roots、zstd/gzip压缩)保证了信道建立、TLS 与流式传输的能力;tonic-build+protoc-bin-vendored作为 build-dependencies,在编译期把 proto/gemini.proto 生成 Rust 类型。
该 proto 文件只声明了三个 RPC(见 gemini.proto):
service GenerativeService { rpc GenerateContent(GenerateContentRequest) returns (GenerateContentResponse); rpc StreamGenerateContent(GenerateContentRequest) returns (stream GenerateContentResponse); rpc EmbedContent(EmbedContentRequest) returns (EmbedContentResponse); } package google.ai.generativelanguage.v1beta;文件头部注释特别强调:字段编号与 wire 类型刻意与 Google 官方 proto 对齐,保证生成的 Rust 类型在 gRPC 线上兼容。生成的模块在 lib.rs 中以proto公开导出,并 re-export 了Content、Part、GenerateContentRequest、GenerateContentResponse、GenerativeServiceClient等常用类型。
二、快速上手:从环境变量到第一个 Agent
1. 添加依赖
按照 README 的说明,在你的Cargo.toml中加入:
[dependencies] rig-gemini-grpc = "0.2.5" rig-core = "0.36.0"也可以直接执行cargo add rig-gemini-grpc rig-core添加最新版本。
2. 配置 API Key
将 Gemini API Key 写入环境变量:
export GEMINI_API_KEY=your_api_key_here3. 第一个对话 Agent
参考 examples/gemini_grpc_agent.rs 与 README 的示例:
use rig_agent::prelude::*; use rig_gemini_grpc::GeminiGrpc; #[tokio::main] async fn main() -> Result<(), anyhow::Error> { // 初始化 Gemini gRPC transport(读取 GEMINI_API_KEY) let transport = GeminiGrpc::from_env().map_err(|err| anyhow::anyhow!("{err}"))?; // 创建 Agent:指定模型、preamble 与温度 let model = transport.completion("gemini-2.5-flash"); let agent = AgentBuilder::new(model) .preamble("Be creative and concise. Answer directly and clearly.") .temperature(0.5) .build(); let response = agent .prompt("How much wood would a woodchuck chuck if a woodchuck could chuck wood? Infer an answer.") .await?; println!("{}", response.output); Ok(()) }三、Transport 与底层实现:tonic 信道 + API Key 拦截器
GeminiGrpc是唯一的传输层类型,核心实现位于 client.rs。它持有一个共享的 tonicChannel和 API Key,因此可以被 clone 到多个模型上复用同一连接:
pub struct GeminiGrpc { api_key: String, channel: Channel, }关键设计点:
- 固定端点:
GEMINI_GRPC_ENDPOINT = "https://generativelanguage.googleapis.com",通过Endpoint::from_static(...).tls_config(...)建立 TLS,并显式指定with_webpki_roots()与域名generativelanguage.googleapis.com。 - API Key 拦截器:
ApiKeyInterceptor实现tonic::service::Interceptor,为每个出站请求注入两个元数据头:x-goog-api-key与x-goog-api-client(客户端标识rig-grpc/0.1.0)。 - 调试安全:
Debug实现将 API Key 打码为******,避免日志泄露密钥。 - 三种构造方式:
GeminiGrpc::new(api_key).await:异步构造,返回 TLS 或连接错误;GeminiGrpc::from_env():同步封装,从GEMINI_API_KEY环境变量读取;文档注明在 Tokio 运行时之外或 current-thread 运行时内会 panic;GeminiGrpc::from_val(api_key):显式传 Key 的同步封装。
模型工厂方法同样在 client 上:
pub fn completion(&self, model: impl Into<String>) -> Model<GenerateContent, Self> pub fn embedding(&self, model: impl Into<String>, dims: Option<usize>) -> Model<Embeddings, Self>四、Completion 补全与工具调用
补全线路实现在 completion.rs,内置模型常量包括:
| 常量 | 模型 ID |
|---|---|
GEMINI_2_5_FLASH | gemini-2.5-flash |
GEMINI_2_0_FLASH | gemini-2.0-flash |
GEMINI_2_0_FLASH_LITE | gemini-2.0-flash-lite |
GenerateContent结构体实现rig_core::wire::Wire:Payload为GenerateContentRequest,Frame为GenerateContentResponse。在Transport的send中按Mode分发:
Mode::Unary:调用client.generate_content(request),把单个响应包装成单元素流;Mode::Streaming:调用client.stream_generate_content(request),逐 chunk 产出;遇到 tonic 失败时 yield 错误并立即break停止接收。
请求编码要点
create_grpc_request(见 completion.rs)把 Rig 的CompletionRequest映射为 proto 请求:
- system 消息:从历史中拆出,合并进
system_instruction字段——注意 Rig 消息中的System类型在此线路被拒绝,源码明确要求 "System messages must be sent via Gemini gRPC system_instruction"; - generation_config:仅在设置了
temperature或max_tokens时生成(temperature转f32,max_tokens转i32); - tools:非空时将每个工具映射为
FunctionDeclaration { name, description, parameters },参数 JSON Schema 通过共享的tool_parameters_to_schema再转为 protoSchema(空对象 schema 映射为None); - model 字段:格式化为
models/{model}。
工具参数 Schema 的类型映射(json_type_to_proto_type)覆盖string / number / integer / boolean / array / object / null,未知类型落到Type::Unspecified。
图像输入
用户消息中的图片按媒体类型处理(completion.rs):支持 JPEG / PNG / WEBP / HEIC / HEIF,URL 来源映射为FileData,原始字节或 base64 数据映射为InlineData(Blob { mime_type, data }),且 base64 解码会剥离data:<mime>;base64,前缀并依次尝试四种引擎。图像出现在工具结果中则被拒绝("Gemini gRPC does not support images in tool results")。
五、流式解码与 Reasoning/Thought Signature
流式线路的响应解码由GrpcAdapter承担,位于 streaming.rs。它实现rig_core::wire::Decoder,把GenerateContentResponse帧转为 Rig 的补全事件:
- 文本分块:同一 response 内的多个 text part 各自独立;跨 response 的连续 text chunk 合并为一个 text part(
previous_text标记控制close_text); - thought part:
part.thought == true的文本进入Thoughts片段流,其thought_signature(base64)通过Thoughts::signature关闭思考块;CHANGELOG 0.42.0 特别提到:携带在尾随非 thought part 上的thought_signature不再被丢弃,而是通过共享的ReasoningSignature生命周期事件挂到它所签署的 reasoning 块上; - FunctionCall part:转为
ToolCall;工具名不再是工具调用 ID 的替代品(见 CHANGELOG 0.42.0 行为修复:当线上未下发 ID 时,无 ID 的调用携带缺失 ID 并保持相互区分); - InlineData part:输出为 base64 图片内容;
- 未知 part.data:oneof 解码为
None时走共享的warn_unmodeled红action 策略(warn-skip),而非静默丢弃(对应 CHANGELOG 0.42.0 的 Changed 条目)。
eof收尾逻辑值得注意:若无 provider 的 finish reason 则报ProviderError::Truncated;若未交付任何内容且非截断,则报空响应错误;最终以Finish事件携带usage(来自UsageMetadata)、response_id、model_version收束。
错误处理:协议级 finish reason
CHANGELOG 0.42.0 的核心修复之一是:gRPC 面现在会把MALFORMED_FUNCTION_CALL、UNEXPECTED_TOOL_CALL、TOO_MANY_TOOL_CALLS上报为错误并停止流,与 REST 行为对齐——此前被中断的 turn 会被误报为完成,且finish_message从未被读取。对应实现为 completion.rs 的tool_protocol_finish_reason_error,在 decoder 的decode中被优先检查。
六、Embedding:向量化与维度控制
Embedding 线路在 embedding.rs,内置常量EMBEDDING_004 = "text-embedding-004"。Embeddings::new(model, dims)中dims缺省为 768(text-embedding-004 的默认向量宽度),编码时写入output_dimensionality字段。
发送侧对每个文本依次调用client.embed_content(request)(顺序执行,首个 RPC 错误即终止整批);解码器EmbeddingsDecoder收集每个文本的向量,eof时若无 embedding 则报错,否则一次性产出EmbeddingResponse。descriptor 中声明的能力为Capabilities::embedding(100, self.ndims)。
gRPC 面与 REST 的差异在代码注释中有明确交代:原生响应是 prost 消息而非 JSON,且EmbedContent不报告 usage 或 response id,因此raw保持Null。
七、RPC 错误的归一化与重试判定
completion.rs 提供统一的 RPC 错误转换:
rpc_error:保留 tonicStatus的原始文本,附带归一化后的 gRPC 码名(如RESOURCE_EXHAUSTED)与瞬时性标记;transient_grpc_code:只有Unavailable、ResourceExhausted、DeadlineExceeded、Aborted被判定为可重试;- 单元测试(embedding/tests.rs)验证:
resource_exhausted错误is_retryable()且 code 为RESOURCE_EXHAUSTED,而invalid_argument不可重试且 code 为INVALID_ARGUMENT;同时由于 gRPC 非 HTTP 传输,provider_response_status()恒为None。
八、版本演进:从 0.1.0 到 0.42.0 的关键脉络
CHANGELOG 完整记录了该 crate 的演进,核心节点如下:
0.1.0(2026-01-14)——初始发布
能力清单即本文前述功能的集合:Gemini gRPC 补全、Embedding、流式补全、工具调用、带 thought signature 的 Reasoning、图像输入,以及从 rig-core 的gemini_grpc模块迁移的指南。
0.2.x(2026-03 至 2026-05)——功能补全期
- 0.2.2:preamble 内部改为 system 消息(对应上文
system_instruction的编码路径); - 0.2.3:OTel GenAI semconv 修复;
- 0.2.5:引入 clippy no-panic lints;
- 0.2.7:
FunctionDeclaration.parameters从ToolDefinition填充(#1763),并暴露流式响应元数据(#1790); - 0.2.6:修复 token usage 正确性(#1761)。
0.38.x 之后——工作区整合与架构演进
- 0.38.1:统一工作区 crate 版本(#1853),这也是版本号从 0.2.x 直接跳到 0.38.x 的原因;
- 0.39.0:引入 sans-IO 的
AgentRun状态机,两个 agent 循环变为薄驱动(#1899); - 0.40.0:全工作区拓宽 provider 错误响应检查(#1944);
- 0.41.0:在 rig facade 后拆分 rig-core 与 rig-agent(#2197),telemetry 敏感 span 内容改为 opt-in(#2151)。
0.42.0(2026-08-16)——流式语法与线缆身份治理
这是 CHANGELOG 中最密集的一个版本,围绕"流部件实体化"与"工具身份在每一层边界成立"展开:
- breaking:
OneOrMany<T>变为Vec<T>(#2273),completion 消息与工具结果内容的转换随之跟进,但 wire 载荷不变; - 流式行为修复:流式函数调用携带单一 wire 身份——只有 wire 的 id 作为 part id 传输,
provider为{call_id, item_id: None},填充两个槽位会伪造线上从未发出的双身份(与 rig-core gemini 修复镜像一致); - 规范流语法:强制身份、单一累加器、decode-then-validate,以及 wire 一致性语料(#2258);
- 共享驱动:gRPC 流改走共享的
WireAdapter驱动,streaming::stream_from_events成为 events-first 的一致性接缝,生成的proto模块公开以支持它; - 另有全工作区 LOC 精简(pass 6/8,净减数千行)等工程性改动。
九、质量保障:一致性测试套件
streaming_conformance.rs 是该 crate 的 wire 一致性测试套件:它以 events-first(WireInput::Event)方式,把已经类型化的 protobuf 响应帧经脚本化 transport 重放,走完GenerateContentwire 的共享驱动、规范语法与终止归一化,全程不建立真实 gRPC 信道。测试中通过downcast_event::<proto::GenerateContentResponse>()校验帧类型,并以gemini-2.5-pro模型实例驱动Model::new(...).stream(...)。CHANGELOG 0.42.0 中"live cassette recording 发现的四个响应映射 bug"(#2328)正是经由这类录制-重放机制定位并修复的。
十、迁移与注意事项小结
- 从 rig-core 的
gemini_grpc模块迁移到本 crate,入口由模块内类型改为rig_gemini_grpc::GeminiGrpc,模型工厂方法不变(completion/embedding); GeminiGrpc::from_env/from_val是同步便捷封装,依赖当前 Tokio 运行时,误用场景会 panic,需要异步场景请用GeminiGrpc::new(...).await;- 系统消息必须走
system_instruction,嵌入到对话历史中的 System 消息会被拒绝; - 工具结果中的图片、未知图片媒体类型、非 Gemini 签发的 reasoning 重放均会报编码错误;
- gRPC 非 HTTP 传输,错误模型以 tonic
Status+ 归一化 code 为准,只有四个瞬时码可重试,对应重试策略请结合 rig-core 的 driver 语义使用。
无论是构建对话 Agent、RAG 向量化管线,还是需要 Reasoning 与工具调用的复杂智能体,rig-gemini-grpc 都提供了类型安全、性能更优的 Gemini 接入路径;其 examples 目录与 README 提供了可直接运行的参考实现。
- AI Agent
- Agent 框架
- RAG
- 后端
【免费下载链接】rig
⚙️🦀 Build modular and scalable LLM Applications in Rust
相关推荐
终极指南:如何快速在浏览器中实现gRPC通信——gRPC-Web完整入门教程
终极指南:如何快速在浏览器中实现gRPC通信——gRPC Web完整入门教程 gRPC Web是一款专为浏览器客户端设计的gRPC解决方案,它突破了传统gRPC
后端微服务Argo Workflows 中 CustomTrigger 的完整指南:通过 gRPC 扩展事件驱动触发器
Argo Workflows 中 CustomTrigger 的完整指南:通过 gRPC 扩展事件驱动触发器 CustomTrigger 是 Argo 事件驱动
云原生容器编排工作流自动化任务调度后端Gemini CLI SDK 实战指南:用 @google/gemini-cli-sdk 在 Node.js 中构建可编程的 Gemini Agent
Gemini CLI SDK 实战指南:用 @google/gemini cli sdk 在 Node.js 中构建可编程的 Gemini Agent 本篇指南
人工智能AI Agent交互助手CLIMCP Clients
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考