Rig — 架构与原理
30 秒导读: Rig 是一个 Rust 库,用一套统一抽象把「20+ 个 LLM 供应商 + 10+ 个向量库」包在同一个接口后面,让你用最少的样板代码搭出从「一句话问答」到「带工具、带知识库的多轮 agent」的应用。它最出彩的一手,是把 agent 的多轮循环抽成一台完全不做 IO、可以序列化到磁盘再换个进程恢复的状态机。
本页是整套文档的入口:先讲清「Rig 是什么」(零基础),再给一张顶 层全景图看懂大盘,最后给一张阅读地图告诉你哪一章讲什么、按什么顺序读。
1. 这是什么(零基础也能懂)
一句话定义
Rig 是一个 Rust 语言的 LLM 应用框架:你写业务逻辑,它负责把「调用哪个大模型、怎么发请求、怎么解析回复、怎么循环调用工具、怎么查知识库」这些脏活标准化。
解决什么问题 / 给谁用
假设你要用 Rust 写一个「会查资料、会调用工具的 AI 助手」,不用 Rig 你会遇到三件麻烦事:
- 每个供应商 API 都不一样。 OpenAI 的请求体、Anthropic 的请求体、Cohere 的请求体字段全不同;换个模型就得重写一遍。
- 工具调用要手写循环。 模型说「我要调
search工具」,你得解析出来、真的去执行、把结果塞回对话、再问一次模型……这个循环容易写错。 - 接向量库做 RAG 又是一套。 MongoDB、Qdrant、Postgres 的向量检索 API 各不相同。
Rig 把这三件事分别用**三个统一特征(trait)**盖住,你只依赖抽象,不依赖具体供应商。给谁用:Rust 后端 / agent / RAG 系统的开发者。
它能做什么(功能)
- 一套接口调 20+ 供应商的 completion(文本生成)和 embedding(向量化)模型。
- 高层
Agent类型:系统提示 + 上下文文档 + 工具 + 多轮循环,开箱即用。 - 一套接口接 10+ 向量库,直接当 agent 的知识库(RAG)。
- 结构化输出(让模型返回能反序列化成 Rust 结构体的 JSON)。
- 流式输出、多轮流式、对话记忆、生命周期 hooks、OpenTelemetry 遥测。
- 转录、音频生成、图像生成等多模态能力。核心库还能编译到 WASM。
用起来什么样
最小示例——三行核心逻辑就能问一次模型(源码地图见 crates/rig-core/src/lib.rs 顶部文档注释):
// 示意,改编自 crates/rig-core/src/lib.rs 顶部文档示例
use rig_core::{client::ProviderClient, completion::Prompt, providers::openai};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let openai = openai::Client::from_env()?; // 从环境变量读 API key
let agent = openai.agent(openai::GPT_5_2).build(); // 造一个 agent
let answer = agent.prompt("Who are you?").await?; // 问一句,拿到字符串
println!("{answer}");
Ok(())
}
注意最后一行 .prompt("...").await?:从「一句话」到「一个 String」,中间那套「发请求 / 解析 / 可能还要循环调工具」全被 Rig 藏起来了。
一句话直觉 / 类比
把 Rig 想成 LLM 世界的 ORM + 连接池:ORM 让你不管底层是 MySQL 还是 Postgres 都用同一套查询接口;Rig 让你不管底层是 OpenAI 还是 Anthropic 都用同一套 agent.prompt(...)。你换供应商,只改一行 Client。
本节到此不碰任何底层代码。你只要记住:Rig = 「LLM / 工具 / 向量库」三件事的统一抽象层 + 一个能自己跑多轮循环的 agent。
2. 顶层全景(它大概怎么转)
怎么读这张图
从上到下是「你的代码 → 高层抽象 → 三大统一特征 → 具体后端」。中间那层的三个特征是整个库的承重墙;换后端只换最底下那层。
你的应用代码 (agent.prompt / extractor.extract / index.top_n)
│
┌──────────────────────────┼───────────────────────────┐
▼ ▼ ▼
┌─────────┐ ┌──────────────┐ ┌──────────────┐
│ Agent │ 多轮循环 │ Extractor │ 结构化抽取 │ EmbeddingsBuilder │
│ (高层封装)│─────┐ │ (结构化输出) │ │ (批量向量化) │
└─────────┘ │ └──────────────┘ └──────────────┘
│ │ 都往下落到 ↓ │
┌────┴──────────┴────────────────┐ ┌──────────────┐ ┌──┴───────────────┐
│ CompletionModel (特征) │ │ Tool (特征) │ │ EmbeddingModel/ │
│ 统一的「请求→回复」接口 │ │ 统一的工具接口 │ │ VectorStoreIndex │
└────────────────┬────────────────┘ └──────┬───────┘ └──────┬───────────┘
▼ ▼ ▼
OpenAI / Anthropic / Gemini / 你的 Rust 函数 / MongoDB / Qdrant /
Cohere / Ollama … 20+ 供应商 MCP server Postgres … 10+ 向量库
部件一句话职责
| 部件 | 干什么 | 在哪 |
|---|---|---|
Agent<M> | 把模型 + 系统提示 + 上下文 + 工具 + 多轮循环打包成一个可反复调用的对象 | crates/rig-core/src/agent/completion.rs(Agent) |
AgentRun | agent 多轮循环的「大脑」:一台不做 IO 的可序列化状态机,只决策不执行 | crates/rig-core/src/agent/run/mod.rs(AgentRun) |
CompletionModel | 所有 completion 模型的统一特征:把 Rig 的规范请求变成回复 | crates/rig-core/src/completion/request.rs:613(CompletionModel) |
CompletionRequest | Rig 的规范请求表示,provider 负责翻译 成自家请求体 | crates/rig-core/src/completion/request.rs:668(CompletionRequest) |
Message | provider 无关的消息模型(System/User/Assistant + 多模态内容) | crates/rig-core/src/completion/message.rs:22(Message) |
Tool | 所有工具的统一特征:名字 + JSON schema + 执行函数 | crates/rig-core/src/tool/mod.rs:116(Tool) |
VectorStoreIndex | 向量检索的统一特征:top_n 查最相近的 N 条 | crates/rig-core/src/vector_store/mod.rs:84(VectorStoreIndex) |
providers::* | 每个供应商一个模块,实现上面几个特征 | crates/rig-core/src/providers/(约 25 个) |
主线走一遍(高层,不进代码)
以 agent.prompt("查一下天气然后总结") 为例,端到端是这样一条链:
输入 prompt
│
▼
Agent 组装规范请求 CompletionRequest(塞进 preamble / 工具定义 / 上下文文档)
│
▼
AgentRun 状态机说:"下一步该调模型" (CallModel)
│
▼
选中的 provider 把 CompletionRequest 翻译成自家 HTTP 请求,发出、收回、翻译回 Message
│
▼
模型回复里有工具调用?
├─ 有 → 状态机说 "下一步该执行工具" (CallTools) → 执行 → 结果塞回对话 → 回到调模型
└─ 没有 → 状态机说 "完成" (Done) → 返回最终文本
关键点:「决策」和「执行 IO」是分开的。 AgentRun 只吐出「下一步该干嘛」,真正发 HTTP、跑工具由外层驱动器(driver)做。这条设计线是第 2 章的主角,也是 Rig 最值得学的地方。
3. 阅 读地图(各章讲什么,建议顺序)
建议按顺序读,每章都建立在前一章的抽象上:
| 顺序 | 章节 | 讲什么 | 读完你能 |
|---|---|---|---|
| 1 | 01-completion-providers.md | 最底层的统一抽象:CompletionModel 特征、Message 数据模型、CompletionRequest 规范请求、provider 怎么实现 | 说清「一次 completion 从 Rig 请求到 provider 回复」怎么走 |
| 2 | 02-agent-loop.md | Agent 类型 + AgentRun 无 IO 状态机 + 「决策/执行分离」的驱动循环 | 说清 Rig 的多轮 agent 循环为什么能序列化、能换进程恢复 |
| 3 | 03-tools.md | Tool 特征、ToolDyn 动态分发、ToolSet、非法工具调用的 Fail/Retry/Repair/Skip 恢复、MCP 接入 | 自己写一个工具,理解模型「乱调工具」时框架怎么兜底 |
| 4 | 04-rag-embeddings.md | Embed 特征、EmbeddingsBuilder、VectorStoreIndex、动态上下文/动态工具(RAG)、Extractor 结构化抽取 | 搭一个带知识库的 RAG agent,让模型返回结构化数据 |
| 5 | 05-advanced-and-map.md | hooks 生命周期、流式与多轮流式、对话记忆、OutputMode(issue #1928)、边界局限、横向对比、代码地图 | 掌控高级特性并知道 Rig 的取舍与边界 |
如果你只想快速定位
- 想知道「怎么换供应商」 → 第 1 章(
CompletionModel+providers)。 - 想知道「多轮循环怎么实现的、能不能持久化」 → 第 2 章(
AgentRun),这是全库最精华的一章。 - 想知道「工具乱调怎么办」 → 第 3 章(非法工具调用恢复)。
- 想搭 RAG → 第 4 章。
- 想接遥测 / 流式 / 记忆 → 第 5 章。
说明:本文档只解剖
rig-core(核心库)。仓库里另有rig-mongodb、rig-qdrant、rig-bedrock等约 18 个伴生 crate,它们只是针对具体后端实现核心库定义的特征,原理在核心库里都讲清楚了。