Skip to content

RAG 实战指南

RAG(Retrieval-Augmented Generation) 让你的 AI 基于私有文档回答问题,而不是依赖训练数据。


🎯 适用场景

场景说明案例
📚 企业知识库员工手册、产品文档、FAQ客服自动回答
📝 个人笔记Obsidian/Notion 笔记检索快速查找信息
📄 文档问答PDF/Word 文档内容检索合同/报告分析
💻 代码库检索项目文档、API 文档开发者助手

📦 方案对比

方案 A:本地部署(推荐)

技术栈

  • 向量数据库:LanceDB / ChromaDB
  • Embedding 模型:本地(embeddinggemma-300m)
  • LLM:本地 Ollama 或云端

优点

  • ✅ 数据完全本地,隐私安全
  • ✅ 零 API 成本
  • ✅ 离线可用

缺点

  • ⚠️ 需要 2GB+ 内存
  • ⚠️ 首次配置较复杂

适合:敏感数据、长期运行


方案 B:云端方案

技术栈

  • 向量数据库:Pinecone / Weaviate Cloud
  • Embedding:OpenAI / Voyage
  • LLM:云端 API

优点

  • ✅ 配置简单
  • ✅ 性能稳定
  • ✅ 免维护

缺点

  • ⚠️ 数据上传云端
  • ⚠️ 持续 API 成本

适合:快速验证、非敏感数据


🛠️ 本地部署实战

第一步:安装依赖

bash
# 安装向量数据库
npm install -g @lancedb/lancedb

# 安装 Embedding 模型(如果还没有)
npm install -g node-llama-cpp --build-from-source

第二步:准备文档

支持的格式

  • ✅ Markdown (.md)
  • ✅ PDF (.pdf)
  • ✅ Word (.docx)
  • ✅ 纯文本 (.txt)

文档结构

knowledge-base/
├── products/
│   ├── product-a.md
│   └── product-b.md
├── faq/
│   ├── general.md
│   └── technical.md
└── handbook/
    └── employee.md

第三步:创建索引脚本

bash
cat > index-docs.js << 'EOF'
const lancedb = require('@lancedb/lancedb');
const fs = require('fs');
const path = require('path');

async function indexDocuments() {
  // 连接数据库
  const db = await lancedb.connect('./knowledge-vector-db');
  
  // 读取文档
  const docs = [];
  const files = fs.readdirSync('./knowledge-base');
  
  for (const file of files) {
    const content = fs.readFileSync(`./knowledge-base/${file}`, 'utf8');
    docs.push({
      id: file,
      text: content,
      source: file
    });
  }
  
  // 创建向量表
  const table = await db.createTable('documents', docs);
  
  console.log(`✅ 已索引 ${docs.length} 个文档`);
}

indexDocuments();
EOF

第四步:创建问答脚本

bash
cat > rag-query.js << 'EOF'
const lancedb = require('@lancedb/lancedb');

async function query(question) {
  // 连接数据库
  const db = await lancedb.connect('./knowledge-vector-db');
  const table = await db.openTable('documents');
  
  // 搜索相关文档
  const results = await table
    .search(question)
    .limit(3)
    .execute();
  
  console.log('📚 相关文档:');
  results.forEach((r, i) => {
    console.log(`${i + 1}. ${r.source}`);
    console.log(r.text.substring(0, 200) + '...\n');
  });
  
  // TODO: 将结果发送给 LLM 生成答案
}

// 使用示例
query('如何配置 OpenClaw?');
EOF

第五步:运行

bash
# 索引文档
node index-docs.js

# 查询
node rag-query.js "如何配置 Telegram?"

🔌 集成到 OpenClaw

方案 1:作为技能安装

bash
# 创建 RAG 技能目录
mkdir -p ~/.openclaw/workspace/skills/rag-knowledge

# 创建技能文件
cat > ~/.openclaw/workspace/skills/rag-knowledge/SKILL.md << 'EOF'
---
name: rag-knowledge
description: 基于本地知识库的问答技能
---

# RAG 知识问答

当用户询问文档内容时,使用此技能。

## 用法

```bash
node ~/.openclaw/workspace/skills/rag-knowledge/query.js "问题"

EOF


### 方案 2:直接集成到对话

修改 `openclaw.json`:
```json
{
  "agents": {
    "defaults": {
      "tools": {
        "rag": {
          "enabled": true,
          "dbPath": "./knowledge-vector-db"
        }
      }
    }
  }
}

📊 性能优化

1. 分块策略

问题:长文档直接索引效果差

方案

javascript
// 按段落分块
function chunkDocument(text, chunkSize = 500) {
  const paragraphs = text.split('\n\n');
  const chunks = [];
  let currentChunk = '';
  
  for (const para of paragraphs) {
    if (currentChunk.length + para.length > chunkSize) {
      chunks.push(currentChunk);
      currentChunk = para;
    } else {
      currentChunk += '\n\n' + para;
    }
  }
  
  return chunks;
}

2. 混合检索

方案:向量相似度 + 关键词匹配

javascript
const results = await table
  .search(question)
  .where('category = "technical"')  // 过滤
  .limit(5)
  .execute();

3. 缓存热门问题

javascript
const cache = new Map();

async function queryWithCache(question) {
  if (cache.has(question)) {
    return cache.get(question);
  }
  
  const answer = await query(question);
  cache.set(question, answer);
  return answer;
}

🎯 最佳实践

文档准备

建议说明
✅ 结构化使用标题、列表等清晰结构
✅ 去重避免重复内容影响检索
✅ 更新定期重新索引最新文档
❌ 过长单文档最好 <10MB

检索优化

技巧效果
分块大小 300-500 字检索精度 +20%
限制返回 3-5 条减少 LLM 混淆
添加元数据过滤准确率 +30%

📚 相关资源


❓ 常见问题

Q: 支持中文吗?

A: 支持。使用中文 Embedding 模型:

bash
# 推荐模型
nomic-embed-text-v1.5  # 支持多语言

Q: 需要多少内存?

A:

  • 1000 文档:~500MB
  • 10000 文档:~2GB
  • 100000 文档:~8GB

Q: 可以实时更新吗?

A: 可以。LanceDB 支持增量更新:

javascript
await table.add([newDocument]);

提示:先从少量文档开始测试,验证效果后再扩展。

最后更新:

基于 OpenClaw 开源项目