Skip to Content

37e RAG 知识库搭建

上一篇: 37d Agent 管理与 Skill 体系 | 下一篇: 37f 产品研发工作流 Agent

本篇搭建团队 RAG(Retrieval-Augmented Generation)知识库:从飞书知识库和文档中提取内容,经过分块和 Embedding 存入向量数据库,通过 RAG 检索 Skill 实现智能问答。目标是将团队的隐性知识(技术方案、历史决策、排错经验)转化为可检索的知识资产。


1. 知识源梳理

1.1 HackQuest 团队知识分布

知识源内容类型数据量估算更新频率
飞书知识库技术方案、架构文档、API 文档~200 篇每周 2-3 篇
飞书文档会议纪要、评审记录、复盘报告~500 篇每天 1-2 篇
GitHub README/Wiki项目说明、部署文档、开发规范~50 篇每月更新
飞书群聊精华问题解答、排错经验~1000 条持续积累
OpenClaw 记忆Agent 执行历史、决策记录持续增长实时

1.2 知识分类

分类示例检索场景
技术架构系统架构图、技术选型文档”我们的支付系统用的什么方案?“
开发规范代码规范、Git 工作流、CR 标准”提交 PR 的流程是什么?“
业务知识课程体系、用户画像、产品路线图”Solana 课程的目标用户是谁?“
排错经验故障复盘、常见问题解决方案”上次数据库连接池满了怎么解决的?“
流程制度入职流程、请假制度、报销规范”新员工入职需要准备什么?“

2. 向量数据库选型与配置

2.1 选型对比

维度ChromaWeaviatepgvector
定位轻量级,适合开发和小团队生产级,功能丰富PostgreSQL 扩展
安装复杂度pip installDocker 部署PostgreSQL 扩展安装
数据持久化本地文件内置持久化PostgreSQL 存储
最大数据量~100 万向量数十亿向量取决于 PostgreSQL
混合搜索向量 + 元数据过滤向量 + BM25 + 过滤向量 + SQL
多租户通过 Collection 隔离原生多租户通过 Schema 隔离
月成本¥0(自托管)¥0(自托管)/ Cloud 按量¥0(复用现有 PG)
推荐场景30 人团队,知识库 < 10 万文档大规模生产环境已有 PostgreSQL 的团队

HackQuest 推荐:起步用 Chroma(简单快速),知识库超过 10 万文档后迁移到 Weaviate 或 pgvector。

2.2 Chroma 安装与配置

# 安装 Chroma pip install chromadb # 启动 Chroma Server(生产模式) chroma run --host 0.0.0.0 --port 8000 --path /data/chroma

Python 客户端连接:

import chromadb client = chromadb.HttpClient(host="localhost", port=8000) # 创建 Collection(按知识分类) tech_collection = client.get_or_create_collection( name="tech_docs", metadata={"description": "技术架构和开发规范文档"} ) business_collection = client.get_or_create_collection( name="business_docs", metadata={"description": "业务知识和产品文档"} ) experience_collection = client.get_or_create_collection( name="experience_docs", metadata={"description": "排错经验和复盘报告"} )

2.3 pgvector 方案(备选)

如果团队已有 PostgreSQL,可以直接使用 pgvector 扩展,省去额外部署向量数据库:

-- 安装 pgvector 扩展 CREATE EXTENSION IF NOT EXISTS vector; -- 创建知识库表 CREATE TABLE knowledge_chunks ( id SERIAL PRIMARY KEY, source_type VARCHAR(50) NOT NULL, -- feishu_wiki, feishu_doc, github_readme source_id VARCHAR(200) NOT NULL, -- 飞书文档 token 或 GitHub 路径 source_title VARCHAR(500), chunk_index INTEGER NOT NULL, content TEXT NOT NULL, embedding vector(1536), -- OpenAI text-embedding-3-small 维度 metadata JSONB, -- 额外元数据 created_at TIMESTAMP DEFAULT NOW(), updated_at TIMESTAMP DEFAULT NOW() ); -- 创建向量索引(IVFFlat,适合中等数据量) CREATE INDEX idx_knowledge_embedding ON knowledge_chunks USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100); -- 创建元数据索引 CREATE INDEX idx_knowledge_source ON knowledge_chunks(source_type, source_id);

3. Embedding 管道

3.1 整体流程

飞书知识库/文档 内容提取(lark-mcp) 文本清洗(去除格式标记、空白) 文本分块(按标题/段落/滑动窗口) 生成 Embedding(OpenAI API) 存入向量数据库(Chroma/pgvector)

3.2 Embedding 模型选择

模型维度价格性能推荐场景
OpenAI text-embedding-3-small1536$0.02/1M tokens良好性价比首选
OpenAI text-embedding-3-large3072$0.13/1M tokens优秀高精度需求
Cohere embed-v4.01024$0.10/1M tokens优秀多语言场景
BGE-M3(本地部署)1024免费良好数据敏感场景

HackQuest 推荐text-embedding-3-small,中文效果好,成本低。200 篇文档约 50 万 tokens,Embedding 成本约 ¥0.07。

3.3 文本分块策略

策略适用场景块大小重叠
按标题分块结构化文档(技术方案)按 H2/H3 标题切分
按段落分块叙述性文档(会议纪要)每段一块
固定大小 + 滑动窗口长文档500 tokens50 tokens
语义分块混合内容按语义边界切分自适应

推荐组合策略:

  1. 优先按标题分块(保留文档结构)
  2. 如果单块超过 800 tokens,使用滑动窗口二次切分
  3. 每个块附加元数据:文档标题、章节标题、来源链接

3.4 Embedding 管道脚本

""" 飞书知识库 → Chroma 向量数据库 Embedding 管道 """ import os import re import chromadb from openai import OpenAI # 初始化客户端 openai_client = OpenAI(api_key=os.environ["OPENAI_API_KEY"]) chroma_client = chromadb.HttpClient(host="localhost", port=8000) collection = chroma_client.get_or_create_collection("tech_docs") def extract_feishu_doc(doc_token: str) -> dict: """ 通过 lark-mcp 提取飞书文档内容。 实际使用时通过 OpenClaw Skill 调用 lark-mcp 工具。 这里展示数据结构。 """ return { "token": doc_token, "title": "文档标题", "content": "文档正文内容...", "url": f"https://xxx.feishu.cn/docx/{doc_token}" } def chunk_by_heading(content: str, max_tokens: int = 800) -> list[dict]: """按标题分块,超长块二次切分""" sections = re.split(r'\n(#{1,3}\s+)', content) chunks = [] current_heading = "" current_text = "" for i, section in enumerate(sections): if re.match(r'^#{1,3}\s+', section): current_heading = section.strip() else: text = f"{current_heading}\n{section.strip()}" if current_heading else section.strip() if not text: continue # 粗略估算 token 数(中文约 1.5 字/token) estimated_tokens = len(text) / 1.5 if estimated_tokens > max_tokens: # 滑动窗口二次切分 words = text.split('\n') sub_chunk = "" for line in words: if len(sub_chunk + line) / 1.5 > max_tokens: if sub_chunk: chunks.append({"heading": current_heading, "content": sub_chunk.strip()}) sub_chunk = line + "\n" else: sub_chunk += line + "\n" if sub_chunk.strip(): chunks.append({"heading": current_heading, "content": sub_chunk.strip()}) else: chunks.append({"heading": current_heading, "content": text}) return chunks def generate_embeddings(texts: list[str]) -> list[list[float]]: """批量生成 Embedding""" response = openai_client.embeddings.create( model="text-embedding-3-small", input=texts ) return [item.embedding for item in response.data] def index_document(doc: dict): """索引单个文档""" chunks = chunk_by_heading(doc["content"]) if not chunks: return # 批量生成 Embedding texts = [chunk["content"] for chunk in chunks] embeddings = generate_embeddings(texts) # 批量写入 Chroma collection.upsert( ids=[f"{doc['token']}_chunk_{i}" for i in range(len(chunks))], embeddings=embeddings, documents=texts, metadatas=[{ "source_type": "feishu_wiki", "source_id": doc["token"], "source_title": doc["title"], "source_url": doc["url"], "chunk_heading": chunk["heading"], "chunk_index": i } for i, chunk in enumerate(chunks)] ) print(f"✅ Indexed {doc['title']}: {len(chunks)} chunks") # 使用示例 if __name__ == "__main__": # 实际使用时,文档列表从飞书知识库 API 获取 doc_tokens = ["doccnxxxxxxxxxx", "doccnyyyyyyyyyy"] for token in doc_tokens: doc = extract_feishu_doc(token) index_document(doc)

4. RAG 检索 Skill

4.1 检索 Skill 完整示例

创建 skills/knowledge/knowledge-rag-search.md

# knowledge-rag-search 根据用户问题检索知识库,结合检索结果生成回答。 ## 触发条件 - 用户消息包含"知识库"、"查一下"、"有没有文档"、"之前怎么做的" - 其他 Skill 无法匹配时的兜底(知识库问答) ## 执行步骤 1. 提取用户问题的核心关键词 2. 将用户问题转换为 Embedding 向量 3. 在向量数据库中检索最相关的 5 个文档块(top_k=5,相似度阈值 > 0.7) 4. 将检索到的文档块作为上下文,结合用户问题生成回答 5. 在回答末尾附上参考文档链接 6. 将本次问答写入记忆,积累常见问题 ## 检索参数 - top_k: 5 - 相似度阈值: 0.7(低于此阈值的结果不使用) - 搜索范围: 所有 Collection(tech_docs, business_docs, experience_docs) ## Prompt 模板 你是 HackQuest 团队的知识助手。根据以下检索到的文档内容回答用户问题。 规则: 1. 只基于检索到的文档内容回答,不要编造信息 2. 如果检索结果不足以回答问题,明确告知用户"知识库中暂无相关信息" 3. 回答末尾列出参考文档链接 4. 使用简洁清晰的中文回答 检索到的文档: {retrieved_chunks} 用户问题:{user_question} ## 输出格式 回答正文(2-5 段) 📚 参考文档: - [文档标题1](链接1) - [文档标题2](链接2) ## 示例输出 **用户问题**: 我们的支付系统用的什么方案? **回答**: HackQuest 的支付系统采用 Stripe 作为主要支付网关,支持信用卡和加密货币支付。 核心架构: - 前端使用 Stripe Elements 组件 - 后端通过 Stripe Node.js SDK 处理支付意图 - Webhook 接收支付状态回调,更新订单状态 - 加密货币支付通过 Coinbase Commerce API 集成 详细的技术方案见架构文档。 📚 参考文档: - [支付系统架构设计](https://xxx.feishu.cn/docx/xxx) - [Stripe 集成指南](https://xxx.feishu.cn/wiki/xxx) ## 权限要求 - 向量数据库读取权限 - OpenAI Embedding API 调用权限 ## 错误处理 - 向量数据库连接失败:回复"知识库服务暂时不可用,请稍后再试" - 检索结果为空:回复"知识库中暂无相关信息,建议联系 [相关负责人]" - Embedding API 调用失败:使用关键词匹配作为降级方案

4.2 检索参数调优

参数默认值调优建议
top_k5简单问题用 3,复杂问题用 7-10
相似度阈值0.7精确匹配场景提高到 0.8,模糊搜索降低到 0.6
搜索范围全部 Collection根据问题类型限定 Collection 提高精度
重排序检索结果多时,用 LLM 对 top_k 结果重排序

4.3 上下文拼接策略

[系统 Prompt] 你是 HackQuest 团队的知识助手... [检索结果 - 按相似度降序] --- 文档 1 (相似度: 0.92) --- 来源: 支付系统架构设计 内容: ... --- 文档 2 (相似度: 0.85) --- 来源: Stripe 集成指南 内容: ... [用户问题] 我们的支付系统用的什么方案?

5. 知识自动更新

5.1 增量更新方案

飞书文档变更 Webhook OpenClaw 接收事件 knowledge-auto-update Skill ├─→ 提取变更文档内容 ├─→ 删除旧的文档块 ├─→ 重新分块和 Embedding └─→ 写入向量数据库

创建 skills/knowledge/knowledge-auto-update.md

# knowledge-auto-update 监听飞书文档变更事件,自动更新向量数据库中的对应文档。 ## 触发条件 飞书文档变更事件(文档编辑保存后触发)。 ## 执行步骤 1. 从事件中提取文档 token 2. 通过 lark-mcp 读取文档最新内容 3. 删除向量数据库中该文档的所有旧块(通过 source_id 匹配) 4. 对新内容执行分块和 Embedding 5. 将新块写入向量数据库 6. 记录更新日志到记忆 ## 过滤规则 - 只处理知识库和指定文件夹下的文档 - 忽略草稿状态的文档 - 忽略 5 分钟内的重复变更(防抖) ## 权限要求 - 飞书文档读取权限 - 向量数据库读写权限 - OpenAI Embedding API

5.2 全量重建策略

定期全量重建,确保数据一致性:

# knowledge-full-rebuild 每周日凌晨 2:00 全量重建知识库索引。 ## 触发条件 定时触发:每周日 02:00 ## 执行步骤 1. 通过 lark-mcp 获取知识库所有文档列表 2. 清空向量数据库中所有 Collection 3. 逐个文档执行分块 → Embedding → 入库 4. 统计重建结果(文档数、块数、耗时) 5. 发送重建报告到运维群 ## 预计耗时 - 200 篇文档约 30 分钟 - 主要耗时在 Embedding API 调用(受限于 API rate limit)

5.3 更新监控

监控项说明告警条件
增量更新成功率文档变更后是否成功更新索引连续 3 次失败
全量重建耗时每周重建的执行时间超过 2 小时
索引文档数向量数据库中的文档总数与飞书文档数差异 > 10%
Embedding API 调用量每日 API 调用 token 数超过预算阈值

6. 效果评估与优化

6.1 评估指标

指标定义目标值评估方法
检索准确率返回的 top_k 结果中包含正确答案的比例> 80%人工标注测试集
回答准确率LLM 基于检索结果生成的回答是否正确> 85%人工评审
回答完整性回答是否覆盖了问题的所有方面> 75%人工评审
幻觉率回答中包含检索结果中不存在的信息的比例< 5%人工对比
响应时间从提问到回答的端到端时间< 5s自动监控

6.2 构建评估测试集

为 HackQuest 场景构建 50 个标准问答对:

[ { "question": "我们的支付系统用的什么方案?", "expected_sources": ["支付系统架构设计"], "expected_answer_contains": ["Stripe", "Coinbase Commerce"], "category": "tech_architecture" }, { "question": "新员工入职第一天需要做什么?", "expected_sources": ["入职流程指南"], "expected_answer_contains": ["飞书账号", "GitHub 权限", "开发环境"], "category": "process" }, { "question": "上次数据库连接池满了怎么解决的?", "expected_sources": ["2026-06 数据库故障复盘"], "expected_answer_contains": ["连接池", "max_connections", "pgbouncer"], "category": "experience" } ]

6.3 常见问题与优化策略

问题原因优化策略
检索结果不相关分块太大,语义稀释减小块大小,按标题分块
回答不完整top_k 太小,遗漏关键信息增大 top_k 到 7-10
回答包含幻觉Prompt 约束不够强化”只基于检索结果回答”的指令
中文检索效果差Embedding 模型中文能力弱换用 BGE-M3 或 Cohere embed-v4.0
响应时间长Embedding + 检索 + LLM 三次调用缓存高频问题的 Embedding,使用更快的模型
知识过时文档更新后索引未同步确保增量更新 Skill 正常运行

7. 工具与资源推荐

工具用途价格链接
Chroma轻量级向量数据库开源免费官网 
Weaviate生产级向量数据库开源免费 / Cloud 按量官网 
pgvectorPostgreSQL 向量扩展开源免费GitHub 
OpenAI Embeddings文本向量化$0.02/1M tokens文档 
BGE-M3开源多语言 Embedding免费(本地部署)HuggingFace 

下一篇: 37f 产品研发工作流 Agent — 实现从需求到上线的完整研发流程自动化

Last updated on