基于RAG与PostgreSQL为AI编程助手构建持久化记忆库
1. 项目概述:为你的AI助手构建一个持久化、可关联的“第二大脑”
如果你和我一样,每天都在和Cursor、Claude Desktop这类AI编程助手打交道,那你肯定遇到过这个痛点:每次对话都是孤立的。你花半小时向AI解释清楚的项目背景、代码架构,或者你精心整理的技术文档,一旦关闭对话窗口,这些宝贵的“上下文”就消失了。下次再问,又得从头解释一遍。这就像每次开会都要重新介绍一遍自己,效率极低。
RAG Memory PostgreSQL MCP Server就是为了解决这个问题而生的。它是一个基于Model Context Protocol (MCP)标准的服务器,简单来说,它给你的AI助手(如Cursor, Claude, Windsurf)装上一个以PostgreSQL/Supabase为后端的“永久记忆体”。这个记忆体不是简单的聊天记录,而是一个结构化的知识图谱和文档向量数据库。
想象一下,你可以把项目文档、API说明、会议纪要、甚至是代码片段“喂”给它。它会自动理解内容,拆分成有意义的片段(Chunk),并转化为机器能理解的“语义向量”(Embedding)存储起来。之后,无论你在哪个对话中,只要AI助手集成了这个MCP服务器,它就能瞬间“回忆”起相关的所有信息。比如你问“我们项目的用户认证是怎么做的?”,AI不仅能从当前文件找答案,还能立刻从你之前存入的所有文档、笔记中,找到最相关的段落,甚至告诉你这个功能涉及哪些代码模块(实体)以及它们之间的关系。
这个项目的核心价值在于解耦与持久化。记忆不再绑定于某个特定的AI模型或对话,而是存储在你自己的PostgreSQL数据库中。这意味着:
- 记忆共享:团队所有成员使用的AI助手可以访问同一套知识库,确保信息一致。
- 跨会话记忆:今天处理的任务,下周的对话依然记得。
- 可关联搜索:不仅能搜文档,还能看到知识实体(如“React”、“用户服务”)之间的关联,回答更立体。
接下来,我将从一个实践者的角度,带你从零开始,深度拆解这个项目的部署、核心原理、高级用法以及我踩过的那些坑。
2. 核心架构与设计思路拆解
要玩转这个工具,不能只停留在“配置-使用”层面,理解其设计思路,才能更好地驾驭它,并判断它是否适合你的场景。
2.1 为什么是 MCP + PostgreSQL + RAG 这个组合?
这个项目的技术选型非常精准,每一层都解决了关键问题:
MCP (Model Context Protocol):这是Anthropic推出的一个开放协议,旨在让AI助手能安全、标准化地调用外部工具和数据源。你可以把它想象成AI世界的“USB标准”。通过MCP,Cursor等客户端无需为每个数据源开发定制插件,只需遵循协议就能连接各种服务器(如Git、数据库、本工具)。这保证了工具的通用性和未来兼容性。
PostgreSQL/Supabase:作为存储层,它提供了几个不可替代的优势:
- 结构化存储:不仅能存文档和向量,还能用关系表清晰地存储实体、关系,完美支撑知识图谱。
- pgvector扩展:这是PostgreSQL的“官方外挂”,让PostgreSQL原生支持向量类型和向量相似度搜索(如余弦相似度),性能经过优化,无需引入额外的向量数据库(如Pinecone, Weaviate),简化了架构。
- 实时与同步:基于数据库的写入,任何客户端更新的记忆都能被其他客户端实时读取,实现真正的多端同步。
- Supabase:它提供了开箱即用的、带pgvector的托管PostgreSQL,省去了自己部署和维护数据库的麻烦,是个人和小团队快速上手的最佳选择。
RAG (Retrieval-Augmented Generation):这是实现“记忆”检索的核心范式。流程是“检索-增强-生成”。本工具完美实现了前两步:
- 检索:当AI需要背景信息时,工具会将你的问题也转化为向量,然后在数据库中进行语义搜索(找意思相近的),或混合搜索(结合关键词)。
- 增强:将检索到的最相关的文档片段和知识图谱信息,作为“上下文”提供给AI模型。
- 生成:AI模型基于这个增强后的上下文生成回答。这一步由Cursor等客户端完成。
2.2 两种嵌入模式:本地与云端的速度与隐私权衡
项目提供了两种生成“语义向量”(Embedding)的模式,这是影响使用体验的核心配置。
MODE=local(默认):- 原理:在本地运行一个轻量级AI模型(Xenova/all-MiniLM-L12-v2)。当你存入文档时,工具会下载这个约50MB的模型,并在你的电脑上运行,将文本转化为384维的向量。
- 优点:完全免费,数据100%不出你的本地环境,隐私性最强。
- 缺点:速度慢,尤其是首次运行需要下载模型,且处理长文档时(比如上百页的PDF)会明显感到卡顿,因为消耗的是你本地的CPU/内存资源。
- 适用场景:处理文档量不大、对数据隐私有极高要求、或没有OpenAI API预算的用户。
MODE=openai:- 原理:调用OpenAI的
text-embedding-3-smallAPI,将文本发送到OpenAI的服务器,获取生成的向量后再存回数据库。 - 优点:速度极快,官方宣称比本地快10-100倍。不消耗本地计算资源,处理大批量文档时优势明显。
- 缺点:需要API Key,有费用(但目前embedding模型极便宜,约$0.02/百万token)。文本内容需要发送给OpenAI。
- 适用场景:需要频繁处理大量文档、追求极致响应速度、且信任OpenAI数据处理政策的用户。
- 原理:调用OpenAI的
实操心得:我建议初期使用
local模式快速验证和体验。当你确认工具价值,并开始有批量处理需求(例如导入整个项目文档库)时,再切换到openai模式。两种模式生成的向量维度都是384,所以切换后,之前存储的向量依然有效,无需重新处理,这个设计很贴心。
2.3 工具模式:按需加载,避免功能臃肿
TOOLS_MODE这个配置体现了良好的用户体验设计。一个MCP服务器可以向客户端暴露很多工具,但并非所有用户都需要所有功能。
full(默认):暴露全部21个工具。适合开发者或需要完全控制的管理员。client:仅暴露10个核心工具,如processDocument(处理文档)、hybridSearch(混合搜索)、知识图谱的增删改查等。这是最适合日常使用的模式,界面清爽,聚焦核心操作。maintenance:暴露11个维护工具,如批量删除、手动分块、重新生成嵌入向量等。用于数据清理和管理。
在Cursor中,不同的工具模式会直接影响你右键菜单或命令面板中出现的选项数量。设置为client可以让你更高效地找到常用功能。
3. 从零开始的完整部署与配置实战
理论讲完,我们动手。这里我会以最常用的Cursor + Supabase组合为例,给出保姆级步骤,并穿插关键注意事项。
3.1 第一步:准备基础设施 - Supabase 数据库
注册与创建项目:访问 Supabase官网 ,用GitHub账号登录。点击“New Project”,填写项目名称和数据库密码(务必记牢)。选择离你近的区域(如
Asia Southeast (Singapore)),免费计划足够初期使用。点击“Create new project”等待几分钟。获取连接信息:项目创建完成后,进入左侧菜单Settings -> API。这里你能找到关键信息:
SUPABASE_URL:就是Project URL,格式如https://xxxxxx.supabase.co。SUPABASE_SERVICE_KEY:在Project API Keys板块,找到service_role的secret值。注意:这个key权限很高,请像保管密码一样保管它,不要泄露在客户端代码中。在这里使用是安全的,因为MCP服务器运行在你的本地环境。
初始化数据库表:进入左侧菜单SQL Editor,点击“New query”。将项目README中的数据库Schema SQL(即创建
rag_entities,rag_relationships等表的语句)复制进去,点击运行。确保所有表成功创建。这一步是为工具创建它需要的“房子”。
踩坑记录:Supabase的免费计划有空间和流量限制,但对于文本和向量存储来说,容量相当充裕。主要注意的点是,免费计划下数据库有休眠机制,长时间无请求会暂停,下次连接时有几秒的冷启动延迟。对于个人使用,这通常不是问题。
3.2 第二步:配置 AI 助手客户端 - 以 Cursor 为例
Cursor 是目前集成 MCP 体验最好的IDE之一。配置分为全局配置和项目配置,这里推荐项目配置,更灵活。
创建项目配置文件:在你的项目根目录下,创建
.cursor文件夹(如果不存在),然后在该文件夹内创建mcp.json文件。路径是:你的项目/.cursor/mcp.json。编写配置文件:将以下配置填入
mcp.json。请替换SUPABASE_URL和SUPABASE_SERVICE_KEY为你自己的值。
{ "mcpServers": { "rag-memory-pg": { "command": "npx", "args": ["-y", "rag-memory-pg-mcp@latest"], "env": { "SUPABASE_URL": "https://your-project-id.supabase.co", "SUPABASE_SERVICE_KEY": "your-service-role-secret-key", "MODE": "openai", "OPENAI_API_KEY": "sk-your-openai-api-key-here", "TOOLS_MODE": "client" } } } }配置项详解:
command: "npx":使用npx直接运行最新版本的包,无需全局安装。args: ["-y", "rag-memory-pg-mcp@latest"]:-y表示自动确认,@latest确保总是使用最新版。env: 环境变量。MODE: "openai":我选择了速度更快的OpenAI模式。如果你用本地模式,设为"local"并可以移除OPENAI_API_KEY。OPENAI_API_KEY:你的OpenAI API Key,可以从 OpenAI平台 获取。TOOLS_MODE: "client":日常使用,这个模式最简洁高效。
重启与验证:保存配置文件后,完全关闭Cursor并重新打开。重启后,你可以通过快捷键
Cmd/Ctrl + Shift + P打开命令面板,输入“MCP”搜索,如果看到相关命令,或者在与AI对话时,它能引用你之前存储的文档,就说明配置成功了。
3.3 第三步:核心工具使用详解与避坑指南
配置好后,工具如何用?我们聚焦几个最核心的工具。
3.3.1 核心工具processDocument:一键注入知识
这是你最常用的工具。它完成了从存储、分块到生成嵌入向量的全流程。
如何使用:在Cursor中,你可以通过命令面板调用,或者更直观地,直接选中一段文本(可以是代码、文档、笔记),右键选择“MCP Servers”下的相关命令(具体名称取决于客户端实现)。你需要提供一个JSON结构:
{ "id": "project-readme-2024", "content": "# 我的项目\n这是一个示例项目文档,描述了系统架构...", "maxChunkSize": 1000, "overlap": 100, "metadata": { "project": "my-app", "type": "readme", "version": "1.0" } }id:文档的唯一标识符。如果重复,会覆盖旧文档。建议使用有意义的名称,如api-auth-spec,meeting-notes-2024-10。content:文档的纯文本内容。如果是PDF/Word,需要你先用其他工具提取文本。maxChunkSize和overlap:这是分块策略的核心参数。maxChunkSize:每个文本块的最大字符数。不是token数。对于代码,500-800比较合适;对于纯文本文档,1000-1500更好。太大则检索精度下降,太小则上下文碎片化。overlap:块与块之间重叠的字符数。这非常重要,可以防止一个完整的句子或概念被硬生生切在两块之间,保证检索时上下文的连贯性。通常设置为maxChunkSize的10%-20%。
metadata:可选的JSON对象,用于过滤和分类。例如,你可以按project、author、date来标记,后续搜索时可以基于元数据筛选。
避坑指南:
- 内容语言:项目明确要求,所有内容(文档、实体、查询)必须使用英文,因为底层的嵌入模型是在英文语料上训练的。用中文内容会导致生成的向量质量很差,搜索效果大打折扣。如果你的原始材料是中文,需要先翻译。
- 分块策略:没有银弹。对于技术文档,可以按章节或功能点分块;对于会议纪要,可以按议题分块。可能需要尝试几次才能找到最适合你材料大小的参数。一个技巧是,先用
listDocuments和查询数据库的方式,看看实际分块结果是否符合预期。- ID管理:使用有规律的ID,便于后期维护。如果文档更新了,用相同的ID重新
processDocument即可更新。
3.3.2 知识图谱工具:构建实体关系网
知识图谱让记忆不再是孤立的文档片段,而是互相关联的知识点。
createEntities:创建实体。比如,你可以创建技术栈实体。{ "entities": [ { "name": "Next.js", "entityType": "FRAMEWORK", "observations": ["React framework for production", "Supports SSR and SSG"] }, { "name": "Vercel", "entityType": "PLATFORM", "observations": ["Deployment platform for frontend apps", "Created by the team behind Next.js"] } ] }createRelations:创建实体间关系。{ "relations": [ { "from": "Next.js", "to": "Vercel", "relationType": "DEPLOY_ON" // 关系类型可以自定义 } ] }addObservations:为已有实体添加更多观察/描述。searchNodes/openNodes:查找实体。
使用场景:当你处理一份技术架构文档时,除了存入文档本身,还可以用这些工具提取出其中的关键技术组件(如“Kafka”、“Redis”、“UserService”)作为实体,并建立它们之间的关系(如“UserService USES Redis”)。这样,AI在回答“我们的系统如何保证高性能?”时,不仅能找到描述缓存策略的文档片段,还能直接告诉你:“系统使用了Redis作为缓存,它被UserService所使用。”
3.3.3 搜索工具:从记忆中精准召回
hybridSearch:混合搜索是默认的强力搜索方式。它同时进行语义搜索(基于向量相似度)和关键词搜索(基于文本匹配),并将结果融合排序。这能兼顾“意思相近”和“字面匹配”,效果最好。{ "query": "How to implement user authentication?", "limit": 5, "metadataFilter": {"project": "my-app"} // 可选,按元数据过滤 }getDetailedContext:这是更强大的“上下文获取”工具。它先进行混合搜索找到相关文档块,同时还会在知识图谱中搜索相关的实体和关系,最后将所有信息整合成一份丰富的上下文,直接供AI使用。你可以把它理解为hybridSearch的增强版。
性能提示:当你的文档数量超过1000份时,纯关键词搜索可能会变慢。此时,强烈建议按照README的指引,在Supabase中为你的
rag_chunks表启用PostgreSQL全文搜索 (FTS)。这会给content字段建立GIN索引,让关键词搜索飞起来。工具会自动检测FTS是否可用,并优先使用它。
4. 高级技巧与实战场景剖析
掌握了基础操作,我们来看看如何用它真正提升工作效率。
4.1 场景一:个人知识库与代码助手
这是我的主要使用场景。我将所有项目的README、设计文档、常用的代码片段(如“React自定义Hook模板”、“错误处理中间件”)都通过processDocument存了进去。
工作流:
- 在新项目里,当我需要设置一个类似的WebSocket连接时,我直接问Cursor:“给我一个之前项目中WebSocket客户端的实现例子。”
- Cursor通过MCP调用
hybridSearch,在我的记忆库中搜索“WebSocket client implementation”。 - 工具返回最相关的几个代码片段和其所在的文档上下文。
- Cursor将这些上下文融入它的回答,直接给我一个符合我以往编码风格的、可用的代码块,甚至告诉我当时为什么这么设计。
效果:我不再需要去翻找旧项目,或者重复编写相似的样板代码。AI成了我所有过往经验的“超级索引”。
4.2 场景二:团队项目上下文共享
对于团队,可以在团队的Supabase项目中部署这个工具,然后让每个成员的Cursor都配置连接到同一个数据库。
操作:
- 团队负责人初始化数据库,并将核心的架构文档、API规范、开发指南录入。
- 每个成员将自己的
.cursor/mcp.json中的SUPABASE_URL和SUPABASE_SERVICE_KEY指向这个共享数据库。 - 新成员加入时,AI能立刻基于团队知识库回答他的问题,比如“我们的代码提交规范是什么?”“订单服务的入口点在哪里?”,极大降低 onboarding 成本。
- 任何成员更新的文档或添加的新知识,都能实时被其他成员的AI感知。
注意事项:需要管理好SUPABASE_SERVICE_KEY的权限,并建立简单的文档命名和元数据规范(比如都用metadata: {team: "backend"}),避免混乱。
4.3 场景三:结合自动化脚本,批量构建知识库
手动添加文档效率低。我们可以写一个简单的Node.js脚本,利用工具提供的函数,批量处理一个文件夹下的所有Markdown或文本文件。
脚本思路:
- 使用
fs模块读取指定目录的所有.md文件。 - 为每个文件生成一个唯一ID(如
文件路径的哈希值)。 - 调用
processDocument工具(本质上,MCP工具可以通过Stdio调用),将文件内容、预设的分块策略和元数据提交。 - 记录处理日志,失败重试。
这样,你可以定期运行脚本,将你的笔记文件夹或项目文档目录同步到记忆库中,实现知识的自动积累。
5. 常见问题排查与优化实录
在实际使用中,你肯定会遇到一些问题。这里记录了我遇到的和社区常见的坑。
5.1 连接与启动问题
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| Cursor重启后提示MCP错误 | 1.npx网络问题。2. Supabase连接信息错误。 3. 数据库表未创建。 | 1. 检查网络,尝试在终端直接运行npx -y rag-memory-pg-mcp@latest看能否下载。2. 仔细核对 SUPABASE_URL和SUPABASE_SERVICE_KEY,确保没有多余空格。3. 登录Supabase SQL Editor,确认所有 rag_开头的表都已存在。 |
| 工具调用无反应或超时 | 1.MODE=local下首次运行下载模型慢。2. 文档太大,本地嵌入处理时间过长。 | 1. 耐心等待,或切换到MODE=openai。2. 对于大文档,尝试减小 maxChunkSize,或先手动拆分成多个小文档再处理。 |
| 搜索返回结果不相关 | 1. 文档内容非英文。 2. 分块大小不合适。 3. 查询语句太模糊。 | 1.确保所有内容为英文,这是最重要的因素。 2. 调整 maxChunkSize和overlap,查看实际分块结果。3. 尝试更具体、包含关键术语的查询语句。 |
5.2 性能优化建议
- 启用全文搜索 (FTS):如果你的文档库增长到上千条,务必执行README中的
supabase-fts-setup.sql脚本。这会对rag_chunks.content字段建立GIN索引,将关键词搜索从全表扫描变为索引查找,性能提升几个数量级。 - 合理使用元数据过滤:在
hybridSearch时使用metadataFilter。如果你为不同项目或类型的文档打上了元数据标签,搜索时加上过滤条件可以极大缩小搜索范围,提高速度和准确度。 - 定期清理测试数据:使用
maintenance模式下的工具(如deleteDocuments),清理那些旧的、无效的测试文档,保持数据库整洁。 - OpenAI模式是性能利器:如果速度是你首要考虑的因素,且不介意小额成本,直接使用
MODE=openai。它带来的流畅体验是值得的。
5.3 数据安全与隐私考量
- 本地模式 (
MODE=local):所有数据处理都在你的机器上完成,向量生成不依赖任何外部API,数据隐私性最高。适合处理公司内部代码、敏感技术文档。 - OpenAI模式 (
MODE=openai):你的文档文本需要发送到OpenAI的服务器以生成嵌入向量。根据OpenAI的数据使用政策,通过API发送的数据默认不会用于训练模型(但请务必查阅最新政策)。切勿用此模式处理任何敏感或机密信息。 - Supabase存储:你的所有数据(文本、向量、图谱)都存储在Supabase的PostgreSQL中。Supabase提供数据加密和网络隔离,但对于极其敏感的数据,你需要评估使用自托管PostgreSQL实例的必要性。
这个项目为我打开了一扇新的大门,它让我使用的AI助手从一个“健忘的天才”变成了一个“博闻强识的伙伴”。最大的体会是,工具的价值不在于它有多复杂,而在于它能否无缝融入并优化你现有的工作流。开始时,你可能需要刻意地去“喂”文档,但一旦习惯养成,它带来的上下文感知能力会让你的开发效率产生质变。我建议你先从一个具体的、封闭的场景开始(比如管理你的个人技术笔记库),感受其威力,再逐步扩展到团队和更大的项目中去。
