
假设用户问了一个问题:
"公司内网的 VPN 连接不上,错误代码 807,怎么办?"
Agent:您好,VPN 连接问题可能有多种原因,建议您:
如需更多帮助,请提供详细信息。
问题: 这个回答太泛泛了,没有针对错误代码 807 给出具体解决方案。
Agent:您好!错误代码 807 通常表示 VPN 连接超时。根据公司 IT 手册,建议您: 解决方案:
参考文档: IT 手册第 3 章 - VPN 故障排查 如果以上方法都不行,我可以帮您开一个工单。
区别: 有 RAG 的 Agent 能从知识库中找到具体的解决方案,回答更准确、更有用!
RAG = Retrieval-Augmented Generation(检索增强生成)
简单说,就是让 AI 在回答问题之前,先去"查资料"。
用户提问
│
▼
┌─────────────┐
│ 1. 检索 │ ← 在知识库中查找相关内容
└─────────────┘
│
▼
┌─────────────┐
│ 2. 整合 │ ← 把找到的内容整合成上下文
└─────────────┘
│
▼
┌─────────────┐
│ 3. 生成 │ ← 基于上下文生成回答
└─────────────┘
│
▼
回答用户问题 | RAG 的解决方案 |
|---|---|
AI 可能"胡说八道" | 有知识库支撑,回答有据可查 |
AI 不知道公司内部信息 | 把公司文档加入知识库 |
信息可能过时 | 更新知识库即可,不用重新训练模型 |
想象你在图书馆找书:
用户问题:"VPN 错误 807 怎么办?"
│
▼
[Embedding 模型]
│
▼
问题向量 [0.2, 0.8, 0.1, ...]
│
▼
┌─────────────────────────────────────┐
│ 知识库向量存储 │
│ ┌─────────────────────────────┐ │
│ │ VPN 错误 807 解决方案 [0.21, 0.79, 0.12, ...] │ ← 相似度高!
│ │ VPN 配置指南 [0.5, 0.3, 0.7, ...] │
│ │ 打印机故障排查 [0.1, 0.2, 0.9, ...] │
│ └─────────────────────────────┘ │
└─────────────────────────────────────┘
│
▼
返回最相关的内容需要收集的内容:
数据类型 | 示例 |
|---|---|
IT 手册 | VPN 配置指南、打印机使用说明 |
故障记录 | 历史故障及解决方案 |
FAQ | 常见问题及答案 |
操作文档 | 软件安装步骤、系统配置 |
把长文档切成小块,方便检索:
原始文档(5000 字)
│
▼
分成多个小块(每块 200-500 字)
│
├── 块 1:VPN 连接问题排查
├── 块 2:VPN 错误代码说明
├── 块 3:VPN 配置步骤
└── ...用 Embedding 模型把每个块变成向量:
"VPN 错误 807 通常表示连接超时..."
│
▼
[Embedding 模型]
│
▼
[0.21, 0.79, 0.12, 0.35, ...]把向量和原文存入数据库(如 Qdrant、Pinecone、Chroma)。
Agent:打印机卡纸是很常见的问题。建议您:
如果问题持续,请联系 IT 部门。
Agent:您好!根据公司 IT 手册,打印机卡纸的处理步骤如下: 公司常用打印机 HP LaserJet Pro 的处理方法:
注意事项:
参考: IT 手册 - 打印机维护章节
区别明显: 有 RAG 的回答更具体、更实用,还包含公司特定的信息!
下面是用 Rust 实现简单向量存储的核心代码:
/// 文档片段
pub struct DocumentChunk {
pub id: String,
pub content: String,
}
/// 检索结果
pub struct RetrievalResult {
pub chunk: DocumentChunk,
pub score: f32,
}
/// 简单的 RAG 引擎
pub struct SimpleRagEngine {
chunks: Vec<DocumentChunk>,
}
impl SimpleRagEngine {
pub fn new() -> Self {
Self { chunks: Vec::new() }
}
/// 添加文档到知识库
pub fn add_document(&mut self, id: &str, content: &str) {
self.chunks.push(DocumentChunk {
id: id.to_string(),
content: content.to_string(),
});
}
/// 搜索相关内容
pub fn search(&self, query: &str, top_k: usize) -> Vec<RetrievalResult> {
// 简化版:实际项目用向量相似度计算
let mut results = Vec::new();
for chunk in &self.chunks {
if chunk.content.contains(query) {
results.push(RetrievalResult {
chunk: chunk.clone(),
score: 1.0,
});
}
}
results.truncate(top_k);
results
}
}实际项目中:
这一篇,我们学习了:
下一篇预告:为什么选 Rust 写 Agent
我们会总结整个项目,展示完整效果,并讲解 Rust 在 Agent 场景的优势。