这个网站上的助手,最初只有一个很窄的任务:访客可以问我的经历和项目,它要根据我真正发布过的内容回答,并给出可以点开的来源。看起来,这只是给网站加了一个聊天框。可做到后来,它逼我回答了一个更重要的问题:当 AI 开始使用我的数据时,围绕这些数据的检索、权限和工具,究竟应该放在哪里?
现在我的答案是 Kioku,也就是这个网站背后的个人数据系统。公开助手依然存在,但它只是 Kioku 的一个客户端。我自己使用的 AI 则通过另一条 MCP 通道,搜索私人知识、查询结构化记录、保存新材料,以及发起受控的工作流。两条路径最终使用同一份数据,却不会获得相同的权限。
对我来说,这个区别比选了哪一家模型、哪一种向量数据库更重要。模型会不断替换,个人数据的边界不应该跟着一起重做。
它最初只是网站上的问答助手
大语言模型知道很多公开知识,却不会自动知道我上个月做了什么、为什么选择某个架构,或简历上的哪段描述才是最新版本。让它只凭模型记忆回答,往往会得到语言流畅的猜测;每次都把整个网站塞进提示词,又会越来越慢、越来越贵,内容多起来后也根本放不下。
RAG,也就是“检索增强生成”,解决思路其实很朴素:在请模型回答之前,先从我控制的内容里找出几段真正相关的材料,再把这些材料连同问题一起交给模型。它不是重新训练一个“懂我”的模型,而是为眼前这个问题补上模型原本没有的上下文。
Embeddings(向量表示)让搜索不必只依赖完全相同的关键词。它会把文字转换成大致保留语义关系的坐标,因此“职业变化”也有机会找到写着“从一个岗位转到另一个岗位”的段落。PostgreSQL 仍是主要数据库,pgvector 只负责在其中补上向量相似度搜索。找到材料之后,模型根据这些段落组织答案,并把来源页面附在回答里。
引用并不是回答末尾的装饰,而是这个功能最重要的约束之一。访客应该能从一句结论回到支持它的原文。如果公开资料不足,克制地说“我不知道”,比生成一个看起来很专业的答案更有价值。
访客看到的交互仍然很简单:问题发往 /ask,答案逐步出现,相关来源随后到达。SSE 是一种从服务端持续向浏览器发送事件的方式,让用户不必等完整答案生成后才看到第一句话。屏幕后面可以很复杂,但它和访客的约定只有一句:回答要来自可以检查的公开资料。
为什么 RAG 应该搬进 Kioku
最早的实现把检索当成网站自身的功能。当时只有网站会使用它,这个决定很自然。后来 Kioku 开始保存文章、项目、知识条目,以及越来越多结构化的个人记录,问题就出现了。
如果索引由网站拥有,每增加一个客户端,都要依赖网站或重新实现一遍检索规则。可见性修改后,多个地方都要同步;后台导入已经更新了 Kioku,网站却可能仍在搜索昨天的副本。负责展示数据的网站,慢慢变成了必须理解所有数据的后端。
所以我把语料整理、切块、向量化、检索和回答编排都移进 Kioku。网站只保留真正属于网站的职责:确认流量经过预期的边缘防护、限制单个访客的突发请求,再把 Kioku 返回的事件流原样交给浏览器。问题校验、公开检索、有限轮次的工具调用、模型网关和引用整理,都由 Kioku 完成。网站是客户端,不再是第二套知识后端。
最近一次后端重构又把这层关系明确了一步。REST、MCP 和命令行任务是并列的入口:它们分别处理自己的认证和通信格式,然后调用同一组与协议无关的 application use cases。MCP 不需要绕回去调用 REST,REST 也不需要复制一套业务逻辑。这听起来只是普通的应用分层,却带来一个很实际的结果:数据规则可以复用,同时不依附于某一种客户端协议。
访客 → misoto22.com /ask → Kioku 公开检索 → 带引用的回答
我的 AI → Kioku MCP → 私人搜索与结构化工具
↓
Kioku 共享服务与数据
同一份数据,通过两条可以强制执行的访问路径使用。
同一份数据,两条读取边界
“告诉公开助手只能搜索公开内容”并不是可靠的安全设计。模型可能误解提示词,应用参数可能传错,未来的代码也可能无意中放宽查询。我希望公开与私人的区别在对话层以下就已经成立。
因此,Kioku 里有两条独立的检索路径。公开 /ask 使用受限的数据库角色和只包含公开内容的视图;面向所有者的知识搜索,则通过另一项数据库能力读取私人索引。公开函数没有 include_private 这样的开关,也不存在一个传错就能把访客查询变成所有者查询的特殊参数。
它们仍然共享合适的基础设施:文本按照稳定规则切成段落,向量使用一致的方法生成,索引也都保存在同一个 PostgreSQL 实例中。但共享基础设施不等于共享权限。在模型看到任何上下文之前,数据库就已经决定了这条路径能接触什么。
这样一来,系统更容易解释,也更容易审查。公开模型当然仍会收到“不要泄露私人信息”的提示,但更关键的是,它根本收不到私人内容。有人尝试诱导它复述一条私人笔记时,公开检索没有任何私人段落可以返回。Kioku 的双语质量检查也会把这类隐私诱导问题,与普通问答、引用正确性和无答案场景放在一起测试。评估无法替代权限控制,但可以发现权限边界之上的体验是否退化。
外层限制也遵循同样的思路。网站最清楚访客从哪里来,因此先拦截异常流量,避免它浪费向量化和生成额度;Kioku 真正连接模型服务,所以全局并发与成本上限由 Kioku 执行。每一层只承担自己能够准确判断的限制。
这也让未来的新客户端必须诚实面对权限。移动应用、另一个网站或本地工具,以后都可以接入 Kioku,但它们仍需要明确的身份和能力。“使用同一份数据”不再自动意味着“能够看到同样的数据”。
MCP 让 AI 不只会搜索
答案藏在文章段落里时,RAG 很好用;问题需要精确、结构化结果时,它就不是最佳工具。“我写过哪些关于数据库所有权的想法”适合搜索,而“去年记录了多少次飞行”或“哪些项目使用 Rust”,应该从记录和关系中直接计算,不该让模型根据几段语义相近的文字估算。
MCP 改变了这个项目的形状。Model Context Protocol 让 AI 客户端看到一组有清晰描述的工具,而不是把大量个人数据塞进一个超长提示词。通过 Kioku 的私人 MCP 入口,我的 AI 可以搜索知识、读取权威记录、保存新笔记、连接相关条目,或启动一个后台工作。重点不是现在究竟有多少个工具,而是每项操作都有明确的输入、结果和权限。
连“搜索”本身也需要两种能力。语义搜索擅长找到用词不同但意思相关的内容;字面搜索更适合精确的人名、标识符或短语。Kioku 会合并两边的结果,而不是让模型在尚未看到答案前猜应该选哪一种。遇到数字、日期或分类问题时,结构化工具则可以完全绕过向量检索,直接查询相应领域的数据。
这让模型回到一个更健康的位置。它负责选择和组合能力,却不成为事实来源。数据库查询确定精确事实,检索提供用于解释的原文,模型把结果组织成对人有用的回答。每一层都做自己擅长的事情。
MCP 还让 Kioku 能参与工作过程,而不只是保存最终发布的文章。和 AI 讨论问题时,如果遇到值得留下的资料,对话可以把它保存到知识库,不必让它永远困在聊天记录里。系统之后可以建议相关条目,但真正建立关系仍是一项明确的写操作。类似模式也适用于个人记录和需要较长时间完成的任务。
私人客户端能力更强,却不会被当成一个无限制的所有者会话。它使用可单独撤销的凭据和数据库角色;每个工具都会声明它是读取、写入、启动任务,还是会产生外部影响;调用需要通过能力检查,危险动作可以等待确认,写入也留下审计记录。模型是代表我执行工作的 agent,但它并不等于我本人。
让数据保持新鲜,也保持私密
如果搜索索引只是某一天生成后就被忘记的快照,知识接口很快就会失去可信度。每次编辑都重新生成全部向量当然正确,却会浪费时间和调用额度;等到下一次部署才更新,又会让刚保存的内容像是“坏掉了”。
Kioku 会为每个索引来源记录内容哈希。文字或可见性变化时,只重新处理真正受影响的段落。新捕获的资料会安排后续索引,因此不需要发布新版本或重建全部内容,也能进入搜索。完整重建仍然保留,用于修复和验证,而不是每次小改动都必须经过的日常流程。
可见性也是索引身份的一部分。一条笔记从私人改为公开,即使正文一个字都没动,对检索来说也是重要变化。页面地址重命名时,旧身份会先被删除,再启用新身份,避免旧网址对应的公开结果长期残留。
数据新鲜只是信任的一半。新捕获内容默认是私人的;MCP agent 即使可以创建内容,也不能因此直接发布;公开检索始终走受限路径;有外部影响的操作可以要求确认;审计记录则让写入在事后仍可检查。这些并不是神奇的“AI 安全方案”,而是围绕 AI 接口重新应用了一组普通、明确而且可执行的控制。
模型服务也被留在数据所有权边界之外。Kioku 只发送向量化或回答当下所需的最少上下文,并通过可以替换的网关连接模型。长期保存的数据、可见性、条目关系、修订历史和结构化记录,仍留在我自己的数据库里。更换模型应该只是替换集成,而不是搬一次家。
系统当然仍有取舍。语义索引可能漏掉最合适的段落,流式生成可能在中途失败,一个真正有用的个人系统也必然包含绝不能公开的内容。目标不是用“AI”这个标签把风险藏起来,而是让每个风险都有看得见的边界、失败后的退路,以及可以持续检查的位置。
我做的已经不只是聊天机器人
/ask 仍是这项工作最容易被看到的部分,而且我希望它一直保持简单:询问我的公开项目,获得有来源的回答,需要完整上下文时再点进原文。但它背后的系统已经不再围绕一个聊天框设计。
Kioku 现在为同一份个人数据提供两种视图。公开视图范围很窄,回答必须带引用,也无法接触私人材料;所有者视图可以搜索更广的知识、使用精确的领域工具、保存内容,并协调受控任务。共享的 application layer 避免重复实现,分离的数据库能力则避免共享权限。
这也是我真正关心的 roadmap:不是为了记录而记录一切,也不是因为模型能够调用工具,就不断往里面堆工具。我想做的是一个耐久的个人知识接口——数据能够由我保留,规则能够由我检查,而不同的 AI 客户端始终可以被替换。
实现会继续在 Kioku↗︎ 中演进,公开客户端则位于 misoto22-site↗︎。比两个代码库都更持久的设计原则其实很简单:让智能靠近数据,让权限比智能离数据更近。