首页 /
实操教程 /
普通开发者如何搭一套个人知识库Agent:从RAG到记忆机制 普通开发者如何搭一套个人知识库Agent:从RAG到记忆机制
技术开发RAGAgent知识库向量数据库LangChainLlamaIndex私有化2026-09-06
封面图由AI生成,仅用于示意。本文为原创实战教程,文中出现的产品/框架商标归各自所有者所有,不构成商业推荐。
先问你一个问题:如果个人知识库里只有几十篇文档,为什么还需要一套“Agent”?因为你要的不是搜索引擎,而是能“读懂”你文档的助手。这个助手最少包含:加载与解析、向量检索、生成、短期会话记忆、长期用户画像。
1. 选型对照:LangChain vs LlamaIndex vs 自研
| 对比项 | LangChain | LlamaIndex | 自研 |
|---|
| 定位 | 快速编排 Agent/多工具 | 专注知识库检索管线 | 结构最简单、可控性最强 |
| 上手速度 | 中 | 高 | 低 |
| 链路复杂度 | 高 | 中 | 低 |
| 适合场景 | 需要接外部工具 | 文档问答、知识Agent | 研究学习或轻量固定场景 |
我的建议是:如果你的核心场景只是“私有文档问答”,先用 LlamaIndex 把原型跑通,再逐步把高频模块改成自研。LangChain 适合需要接多个外部工具或复杂 Agent 循环时再引入。不要为了用框架而用框架;你的第一个知识库也许不需要一条 2000 行的 Chain。
2. 嵌入模型与向量数据库的取舍
| 嵌入模型 | 维度 | 本地推理 | 中文表现 | 适合情况 |
|---|
| bge-m3 | 1024 | 可用 | 强 | 不追求小体积 |
| bge-small-zh-v1.5 | 512 | 省内存 | 较好 | CPU/小内存原型 |
| text-embedding-3-small | 1536 | API | 好 | 可接受外发文本 |
向量库方面,个人知识库没必要一上来就部署 Milvus。我这里给出一条务实路径:
| 向量库 | 资源占用 | 适合规模 | 一句话 |
|---|
| Chroma | 低 | 100 万级 | 嵌入式,快速起步 |
| LanceDB | 低 | 千万级 | 文件型列式存储 |
| Milvus | 高 | 十亿级 | 更适合团队/企业 |
个人项目建议试 Chroma 或 LanceDB。选择时看两件事:是否支持 metadata filter(比如按日期、目录过滤),以及增量写入是否稳定。
3. 解决“召回正确但答案错误”的分块与重排技巧
“向量检索到了正确文档,但答案仍然错”通常不是 embedding 的问题,而是上下文结构错乱。常见原因:
- 按固定 512 token 硬切,把一段完整业务逻辑切到两个块里。
- 没有保留标题与段落层级,LLM 不知道这段文字来自“2026年报”还是“Q1管理层问答”。
- Top-K 取太大,次要文本淹没了关键文本。
我建议使用“父子块 + 重排”的组合方案:
- 小块负责匹配,如 200~250 token;
- 父块负责交给模型生成,如 600~1200 token;
- 先向量召回 Top50,再用 rerank 模型压缩到 Top3~5。
flowchart LR
A[原始文档] --> B[解析标题与段落]
B --> C[父子块索引]
Q[查询] --> D[向量召回 Top50]
C --> D
D --> E[Rerank Top5]
E --> F[重排后的父块]
F --> G[LLM 生成]
分块小技巧:Markdown 文件先按 `##` 分节,再对一节中长度过大的段落继续切;如果一段是表格,不要切成两半。Rerank 使用本地 `bge-reranker-v2-m3` 即可,个人场景性价比很高。
4. 加入会话记忆与长期用户画像的简单实现
一个没有记忆的知识库是“一次性百宝箱”。我建议记忆分为两层:
短期层:保存最近 10~20 轮对话,用于多轮澄清和追问。
长期层:定期抽取用户画像,比如关注领域、术语习惯、历史结论。使用 SQLite 保存,避免引入强依赖。
表结构可以这样设计:
CREATE TABLE chat_history (
session_id TEXT,
role TEXT,
content TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE user_profile (
user_id TEXT PRIMARY KEY,
profile_json TEXT,
updated_at TIMESTAMP
);
Python 示例:
# memory.py 示例:SQLite 版短期记忆
import sqlite3
DB_PATH = './agent_memory.db'
def init_db():
conn = sqlite3.connect(DB_PATH)
conn.execute('''
CREATE TABLE IF NOT EXISTS chat_history (
session_id TEXT,
role TEXT,
content TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
conn.commit()
conn.close()
def save_message(session_id, role, content):
conn = sqlite3.connect(DB_PATH)
conn.execute(
'INSERT INTO chat_history(session_id, role, content) VALUES(?, ?, ?)',
(session_id, role, content)
)
conn.commit()
conn.close()
当 token 预算不够时,加载最近消息后做一轮“摘要改写”:把超过 10 轮的历史压缩成 3 条 summary,再放进 system prompt。用户画像的更新不需要频繁,可以在每次会话结束后异步触发一次。
5. 私有化部署成本估算与性能瓶颈
先给一个“本地个人版”的成本量级。假设你手上有一台 16GB 内存的 PC 或 Mini 主机,只服务自己一个人:
| 模块 | 选用 | 额外硬件成本 | 说明 |
|---|
| 向量库 | Chroma | 0 元 | 写入本地磁盘 |
| Embedding | bge-small-zh-v1.5 | 0 元 | CPU 即可 |
| 生成模型 | Ollama + qwen2.5:7b-instruct-q4 | 0 元 | 需要约 6~8GB 内存 |
| Rerank | bge-reranker-v2-m3 | 0 元 | 必要时只处理 Top20 |
通常瓶颈不在“容量”,而在这 4 处:
- PDF 解析慢,尤其扫描版需要 OCR;
- Embedding 首次建索引慢,但后续增量可以接受;
- Rerank 和 LLM 在本地抢内存,容易 OOM;
- Prompt 过大导致首 token 延迟升高。
如果你是租云服务器,建议先跑 API 验证,再购买 GPU 实例。具体价格随地域与活动变化,这里不做报价;只是提醒:个人知识库的主要费用往往是“调试时间”,不是硬件费。
6. 示例代码与常见坑
下面是一个能直接改造成后台任务的最小骨架:
# mini_agent.py
import sqlite3
DB_PATH = './agent_memory.db'
def init_db():
conn = sqlite3.connect(DB_PATH)
conn.execute('''
CREATE TABLE IF NOT EXISTS chat_history (
session_id TEXT,
role TEXT,
content TEXT
)
''')
conn.commit()
conn.close()
先用一段普通文本代替真实向量检索
def fake_retrieve(query):
return ['片段一:项目背景', '片段二:技术方案']
def build_context(retrieved, query):
parts = []
parts.append('Knowledge base:')
parts.extend(['- ' + p for p in retrieved])
parts.append('Question: ' + query)
return '\n'.join(parts)
if __name__ == '__main__':
init_db()
q = '2026年总结论是什么?'
docs = fake_retrieve(q)
ctx = build_context(docs, q)
print(ctx)
这份代码的要点是:先有一个可跑的 shell,再把 `fake_retrieve` 替换成 Chroma + bge,最后接 Ollama。
常见坑:
- 把标题、来源、时间写入 chunk 的 metadata,而不是只存文本。
- 不要选太复杂的向量库,除非确有必要。
- 中文文本请使用带中文分词的加载器,否则会把一句话从中间切开。
- 不要把“用户提问”和“历史对话”拼成同一个字符串,建议保留 role 字段。
- 本地并发访问 SQLite 记得开启 WAL 模式,避免锁库。
推荐视频(出处标注)
注:视频出处以各平台播放页实际作者为准;本文只提供检索入口。
操作清单
避坑指南
- 别相信默认分块器;先用 3 个文件人工验证召回片段。
- 别把 metadata 放在 prompt 最后,LLM 会忽略它;建议放在 system 开头或紧跟用户问题。
- 别盲目调 Top-K;K 越大,模型越容易被噪声带走。
- 别在没做 rerank 前就换更大的基础模型,多加优化可能更有效。
- 别把用户画像写成百科全书,每次只更新变化字段,避免 profile 越来越长。
免责声明
本文仅代表个人开发经验总结,不构成任何购买或商用建议。文中涉及的代码仅供学习参考,使用前请根据自身数据和模型许可证进行合规审查。如你在真实项目中复用,请自行承担部署安全与数据隐私责任。PREMIUM需要完整版教程?
包含详细步骤、视频演示、提示词模板和可下载资料包。微信支付即时获取。
购买完整版 ¥29.90