本文面向想在重构前发现隐藏依赖、评估影响范围的开发者。预计阅读时间8 分钟最终效果掌握语义搜索 关系扩展的组合用法能通过知识图谱发现代码重构的隐藏依赖。重构的盲区假设你准备重构项目的认证模块——把 JWT 校验逻辑从中间件抽出来换成统一的 auth service。表面上看改动范围很清晰认证中间件、token 生成、几个需要保护的路由。但真正上线后你发现用户权限控制模块依赖了 token 里自定义字段的结构某个定时任务用旧方式刷新 token现在挂了第三方 Webhook 回调的验签逻辑和 JWT 共用了一段密钥管理代码这些依赖关系不会出现在grep结果里不会在 IDE 的 “Find References” 中显示因为它们存在于对话和知识的层面——你或你的同事在某次调试中踩过的坑、做过的决策、写过的方案散落在几十条 AI 对话记录里。ChatCrystal 的语义搜索加上知识图谱正是为了解决这个问题。语义搜索找到直接相关的笔记先从最基础的开始。假设你已经用 ChatCrystal 导入并总结了大量对话数据库里积累了丰富的知识笔记。直接搜索crystal searchJWT 认证 token 校验或者通过 APIGET /api/search?qJWT 认证 token 校验ChatCrystal 会用 Embedding 模型把你的查询转为向量然后在 vectra 向量索引中找出语义最相似的笔记。这个过程不依赖关键词匹配——即使你的笔记里写的是身份验证而不是认证只要语义接近就能命中。搜索返回的结果按相似度评分排序每条结果包含笔记 ID、标题、匹配的文本片段和所属项目。对于重构场景你可能直接找到“JWT 认证中间件实现”——评分 0.92“API 路由保护与权限验证”——评分 0.85“OAuth 第三方登录接入”——评分 0.78这些是直接命中语义和你的查询高度相关。但真正的价值在下一步。关系扩展沿着图谱边找到隐藏依赖ChatCrystal 维护了一个知识图谱。每篇笔记之间可以存在 8 种类型的关系存储在note_relations表中。当你搜索时传入expandtrue参数GET /api/search?qJWT 认证 token 校验expandtrue系统会在直接命中之后自动沿着关系边扩展搜索。核心逻辑如下// 伪代码关系扩展搜索for(constdirectHitofdirectResults){constrelationsdb.query(SELECT relation_type, confidence, linked_note_id FROM note_relations WHERE (source_note_id ? OR target_note_id ?) AND confidence 0.5,[directHit.noteId,directHit.noteId]);for(constrelofrelations){constdiscountedScoredirectHit.score*0.7*rel.confidence;// 添加到结果集标记 viaRelation}}关键设计置信度阈值 0.5只沿高置信度的边扩展过滤噪声分数衰减扩展结果的评分为原始分数 x 0.7 x 关系置信度确保直接命中始终排在前面viaRelation 标记每条扩展结果都标明是通过哪种关系类型找到的方便你判断关联强度实战重构认证模块的依赖发现让我们走一遍完整的流程。第一步直接搜索crystal searchJWT 认证--limit5命中 3 篇笔记笔记评分来源JWT 认证中间件实现0.92Claude Code 对话Token 刷新机制设计0.88Cursor 对话密钥轮换方案讨论0.81Claude Code 对话这三篇是你已经知道的——它们直接讨论了 JWT。第二步开启关系扩展# CLI 暂不支持 expand 参数通过 API 调用curlhttp://localhost:3721/api/search?qJWT%20认证expandtruelimit10结果集变成了 8 篇新增的 5 篇全部带有viaRelation标记笔记评分viaRelation说明JWT 认证中间件实现0.92—直接命中Token 刷新机制设计0.88—直接命中密钥轮换方案讨论0.81—直接命中API 请求限流策略0.54DEPENDS_ON中间件依赖限流模块用户权限 RBAC 实现0.50LEADS_TO认证之后的权限控制流程Webhook 回调验签0.45DEPENDS_ON共用密钥管理定时任务调度框架0.38REFERENCES定时刷新 token 的任务错误码统一规范0.30LEADS_TO认证失败的错误处理这些通过关系扩展找到的笔记就是你重构时需要关注的隐藏依赖。第三步查看完整关系图想看全局调用图谱 APIGET /api/relations/graph返回所有笔记节点和关系边{nodes:[{id:1,title:JWT 认证中间件实现,tags:[认证,中间件]},{id:5,title:用户权限 RBAC 实现,tags:[权限,RBAC]}],edges:[{source:1,target:5,type:LEADS_TO,confidence:0.85}]}你可以把这些数据导入任何可视化工具画出依赖关系图。红色高亮认证模块相关的节点和边一目了然。8 种关系类型在重构中的含义ChatCrystal 定义了 8 种关系类型每种在重构场景下都有独特的参考价值CAUSED_BY— 问题因果链。笔记 A 描述的问题是由笔记 B 中的内容引起的。重构时告诉你改了 BA 描述的问题可能会复现或消失。LEADS_TO— 流程延续。笔记 A 的内容导致了笔记 B 描述的结果。重构时告诉你改了 A 的流程下游的 B 可能需要跟着调整。RESOLVED_BY— 解决方案映射。笔记 A 描述的问题被笔记 B 的方案解决。重构时告诉你如果废弃 B 的方案A 的问题可能重新出现。SIMILAR_TO— 主题相似。两个笔记讨论类似的技术或问题。重构时告诉你这两个地方可能有重复代码值得统一处理。CONTRADICTS— 结论矛盾。两个笔记的方案互相冲突。重构时告诉你需要做取舍不能两套逻辑并存。DEPENDS_ON— 实现依赖。笔记 A 的内容依赖于笔记 B 的实现。这是重构时最危险的关系——改了 BA 一定会受影响。EXTENDS— 内容扩展。笔记 A 是对笔记 B 的深化。重构时告诉你B 是基础层A 是上层封装改 B 要考虑 A 的兼容性。REFERENCES— 内容引用。笔记 A 提及了笔记 B 相关的内容。重构时告诉你A 虽然不直接依赖 B但开发者在做 A 时参考了 B 的设计。批量发现关系知识图谱不会自动生长——你需要主动发现笔记间的关系。ChatCrystal 提供了批量发现 APIPOST /api/relations/batch-discover这个接口会找出所有尚未建立关系的笔记逐一加入队列进行 LLM 分析。队列采用并发控制每秒 1 次 LLM 调用自动重试失败的请求。工作流程查询数据库找出note_relations表中没有出现过的笔记 ID对每篇笔记调用discoverRelations()先用语义搜索找到 20 个候选笔记再让 LLM 分析它们之间的关系LLM 返回关系类型、置信度和简短描述过滤掉置信度低于 0.5 的结果写入note_relations表每篇笔记最多保存 5 条关系你也可以对单篇笔记触发关系发现POST /api/notes/{id}/discover-relations建议在导入一批新对话并完成总结后跑一次批量发现让知识图谱保持更新。搜索与图谱的协同效应语义搜索和知识图谱各自有局限但组合起来威力倍增语义搜索擅长找到——给定自然语言查询从海量笔记中找到语义相关的条目。但它是扁平的只返回一维的相似度排序。知识图谱擅长连接——记录笔记之间的逻辑关系形成有向图。但它是被动的需要你主动查询某个节点的邻居。两者结合的工作模式是搜索发现→ 找到直接相关笔记 ↓ 图谱扩展→ 沿关系边找到间接相关笔记 ↓ 分析判断→ 根据关系类型评估影响范围在重构场景中这意味着搜索帮你定位我要改的东西图谱帮你发现改了之后会波及的东西关系类型帮你判断波及的程度和方向下一步导入并总结你的对话crystal import crystal summarize --all积累知识库运行批量关系发现curl -X POST http://localhost:3721/api/relations/batch-discover构建图谱重构前先搜索用expandtrue查看完整的影响范围可视化依赖图调用GET /api/relations/graph获取图谱数据用 D3.js 或其他工具渲染重构不怕改动大怕的是漏掉依赖。语义搜索加上知识图谱让你的每一次重构都有据可依。项目地址github.com/ZengLiangYi/ChatCrystal如有疑问欢迎在 GitHub Issues 或私信交流很乐意解答。