你和 AI 聊了上千轮,这些知识都去哪了?

3 阅读6分钟

痛点:AI 对话是一次性的

作为一个重度 AI 编程用户,我每天和 Claude Code、Cursor、Codex CLI 的对话少则十几轮,多则上百轮。解决了一个棘手的 bug、搞清楚了一个架构方案、摸索出了一套部署流程……然后呢?

关掉终端,这些知识就消失了。

下次遇到类似问题,我发现自己在做同样的事:重新问一遍 AI、重新搜索一遍 Google。明明三天前刚解决过,但就是找不到当时的对话了。

Claude Code 的对话散落在 ~/.claude/projects/ 下几百个 JSONL 文件里;Cursor 的藏在 SQLite 数据库深处;Codex CLI 的又是另一套格式。手动翻?不现实。

我做了什么

所以我写了 ChatCrystal —— 一个把 AI 对话「结晶」成个人知识库的桌面工具。

核心思路很简单:

 散落的 AI 对话 → 统一采集 → LLM 提炼 → 结构化笔记 → 语义搜索 + 知识图谱

对话浏览

它能做什么

1. 多数据源自动采集

支持 Claude Code、Codex CLI、Cursor 三种数据源,自动扫描并导入对话记录。基于 chokidar 实现文件监听,新对话产生后实时同步,不用手动操作。

2. LLM 智能摘要

通过 Vercel AI SDK 接入你手头的任意 LLM,将一段冗长的对话提炼为结构化笔记:

  • 标题和摘要
  • 关键结论(一句话总结核心收获)
  • 代码片段(提取对话中的关键代码)
  • 自动标签

笔记摘要

3. 语义搜索

不再靠关键词碰运气。基于 Embedding 向量索引(vectra),按语义相关度检索笔记。「那次解决内存泄漏的方案」—— 搜「memory leak cleanup」就能找到,即使笔记里写的是中文。

语义搜索

4. 知识图谱

这是我觉得最有意思的功能。LLM 会自动分析笔记之间的关系——因果、依赖、引用、扩展等 8 种关系类型,用力导向图可视化呈现。

比如你会发现:「登录失败的 bug」是由「Token 过期逻辑重构」引起的,而那次重构又依赖于「Auth 中间件改造」。这些隐藏在时间线里的知识脉络,图谱帮你串起来了。

知识图谱

技术实现

作为技术文章,聊聊架构和实现细节。

整体架构

 ChatCrystal/
 ├── electron/          # Electron 主进程
 ├── shared/types/      # 共享 TypeScript 类型
 ├── server/src/        # Fastify 后端
 │   ├── parser/        # 插件式数据源适配器
 │   ├── services/      # 核心服务(导入、摘要、Embedding、关系发现)
 │   ├── routes/        # REST API
 │   └── queue/         # p-queue 任务队列
 ├── client/src/        # React SPA
 └── data/              # 运行时数据
技术选型
后端Node.js + Fastify v5 + TypeScript
前端Vite v8 + React 19 + Tailwind CSS v4 + TanStack Query v5
桌面Electron + electron-builder
数据库sql.js(WASM SQLite,零依赖)
LLMVercel AI SDK v6
向量搜索vectra

数据源适配:插件式设计

不同 AI 工具的数据格式完全不同,我抽象了一个 SourceAdapter 接口:

 interface SourceAdapter {
   name: string;
   displayName: string;
   detect(): Promise<SourceInfo | null>;
   scan(): Promise<ConversationMeta[]>;
   parse(meta: ConversationMeta): Promise<ParsedConversation>;
 }

目前三个内置适配器:

适配器数据格式难点
Claude Code~/.claude/projects/**/*.jsonl需要过滤 <system-reminder> 等系统标签噪音
Codex CLI~/.codex/sessions/**/*.jsonl事件流格式,需从 event 重建对话
CursorworkspaceStorage/state.vscdbSQLite KV 存储,需解析 composer 元数据

想接入新数据源?实现这个接口就行,放到 server/src/parser/adapters/ 下注册即可。

摘要生成:截断 + 结构化提取

AI 对话动辄几万 token,直接丢给 LLM 不现实。我的做法是:

  1. 预处理截断:保留开头和结尾,中间按重要度采样,控制在 ~8000 token
  2. 结构化 Prompt:要求 LLM 输出严格 JSON 格式(标题、摘要、结论、代码、标签)
  3. 后处理:正则提取 JSON,容错处理 LLM 输出不规范的情况
  4. 自动触发 Embedding:摘要生成后自动生成向量索引,无需手动操作

语义搜索:分块 + 向量检索 + 关系扩展

Embedding 部分我用了 vectra(纯 JS 的本地向量索引),实现思路:

 笔记文本 → 按段落分块(500字/块) → Embedding → vectra 索引
                                                     ↓
 搜索查询 → Embedding → vectra.queryItems → 去重 → 沿关系边扩展

关系扩展是亮点:搜到一条笔记后,会沿知识图谱的边找到关联笔记,用折扣系数(原始分数 × 0.7 × 置信度)加入结果。这样搜「部署失败」可能还会带出「Docker 镜像优化」的笔记——因为它们有依赖关系。

多 Provider 支持

通过 Vercel AI SDK v6 统一了 LLM 调用接口,支持运行时热切换:

  • Ollama(本地推理,免费,隐私友好)
  • OpenAI / Anthropic / Google AI / Azure OpenAI
  • 任意 OpenAI 兼容服务(OpenRouter、Poe 等)

⚠️ 一个踩坑点:LLM 和 Embedding 必须分开配置。大语言模型(Claude、GPT-4)不能当 Embedding 模型用,它们不支持 /v1/embeddings 端点。Embedding 得用专用模型,比如 nomic-embed-texttext-embedding-3-small

任务队列

批量摘要和 Embedding 生成通过 p-queue 排队执行(并发=1,限速 1 req/s),避免打爆 LLM 服务。支持实时进度追踪和取消操作,前端通过轮询 /api/queue/status 展示进度条。

快速上手

最简方案:Ollama 本地运行

 # 1. 安装 Ollama 并拉取模型
 ollama pull qwen2.5:7b          # 用于摘要
 ollama pull nomic-embed-text     # 用于 Embedding
 ​
 # 2. 克隆并启动
 git clone https://github.com/ZengLiangYi/ChatCrystal.git
 cd ChatCrystal
 npm install
 cp .env.example .env
 npm run dev:electron             # 桌面应用开发模式

用云端 API

.env 或设置页面配置即可:

 # 用 OpenAI
 LLM_PROVIDER=openai
 LLM_API_KEY=sk-...
 LLM_MODEL=gpt-4o
 ​
 EMBEDDING_PROVIDER=openai
 EMBEDDING_API_KEY=sk-...
 EMBEDDING_MODEL=text-embedding-3-small

启动后的操作流程:

  1. 点击侧边栏「导入对话」→ 自动扫描本地 AI 对话
  2. 「批量生成」→ LLM 把对话提炼为笔记
  3. 「搜索」页 → 按语义找到你需要的知识
  4. 「图谱」页 → 可视化知识之间的关联

为什么是本地优先

ChatCrystal 所有数据都存在本地(SQLite + 文件系统),不上传任何对话内容到第三方服务(除了你自己配置的 LLM Provider)。

对于经常和 AI 讨论公司代码、内部架构的开发者来说,这一点很重要。配合 Ollama 使用,整个流程可以完全离线运行。

后续规划

  • macOS / Linux 支持
  • 更多数据源适配器(ChatGPT、Windsurf 等)
  • 笔记编辑和手动创建
  • 导出为 Markdown / Obsidian vault
  • 对话内嵌搜索(直接在对话中查找历史知识)

总结

如果你也是 Claude Code / Cursor / Codex 的重度用户,应该能感受到这个痛点——和 AI 的对话产生了大量有价值的知识,但它们散落在各处,无法复用。

ChatCrystal 要做的就是把这些知识「结晶」下来,变成可搜索、可关联的个人知识库。

项目完全开源,欢迎 Star 和 PR:

👉 GitHub: ZengLiangYi/ChatCrystal

有问题或建议欢迎在 Issue 区交流,中英文都可以。