1. 为什么要把向量数据库和图数据库放在一起用1.1 从一个真实需求说起去年下半年我接手了一个内部知识库的改造项目需求方给的原话是想让系统像人一样理解资料之间的关系。这句话听起来很虚但拆开看其实很具体他们有一批技术文档、会议纪要、项目复盘材料希望检索的时候不只是关键词匹配而是能理解语义同时希望系统能回答这个方案影响了哪些模块谁在什么背景下提出了这个改动这类需要顺着关系链条走的问题。一开始我图省事直接上了一套向量检索方案把文档切片、做嵌入、存进向量库查询的时候做相似度匹配。效果在找相似内容这个场景下确实不错但很快就撞墙了。用户问和A方案相关的所有决策记录向量检索返回的是一堆语义相近的片段但它不知道A方案和某个决策之间是被采纳被否决还是被替代的关系更没法顺着决策→参与人→其他决策这条链走下去。这就是问题的核心向量数据库擅长的是像不像图数据库擅长的是连没连。前者解决语义模糊匹配后者解决实体之间的显式关系推理。单用任何一个都会在另一类问题上瘸腿。后来我把两套东西拼到一起用大模型做中间的调度和生成层才把这个需求真正落地。这篇就把整个实践过程拆开讲清楚。1.2 两类数据库的能力边界到底在哪先把概念说透不然后面的选型没法聊。向量数据库本质是存高维向量的通过近似最近邻算法比如HNSW、IVF快速找到和查询向量距离最近的若干条记录。它的输入是一段文本经过嵌入模型转成的向量输出是语义上最接近的若干片段。它的强项是模糊语义匹配弱项是精确关系表达——你没法在向量库里表达张三属于A团队A团队负责B项目这种结构化事实。图数据库存的是节点和边节点代表实体边代表关系边上还能挂属性。它的强项是多跳关系查询比如找出所有和某方案间接相关且时间在某个区间内的决策用图查询语言几行就能表达。它的弱项是语义模糊性——你没法用图查询表达找和这段话意思相近的内容因为图里存的是离散的实体和关系不是连续语义空间。大模型在这里扮演的角色是把用户的自然语言问题翻译成对这两类数据库的调用再把两边返回的结果融合成一段人话。三者协同才构成一个完整的检索推理闭环。1.3 协同架构的整体设计思路我最终采用的架构分四层从下往上说。最底层是存储层向量库和图库并存。向量库存文档片段的嵌入向量和原文图库存实体、关系以及实体到文档片段的映射。这里有个关键设计同一个实体在两边的ID必须能对上否则融合的时候会断链。往上一层是索引与抽取层负责把原始文档处理成两边都能用的数据。这一步用大模型做实体识别和关系抽取把非结构化文本转成三元组喂给图库同时把文本切片喂给向量库。再往上是检索调度层接收用户问题判断该走向量检索、图检索还是两者都走然后并行执行、合并结果。最顶层是生成层把检索到的片段和关系路径一起塞进大模型的上下文生成最终回答。这个分层的好处是每一层职责单一出问题好定位。我踩过的坑基本都集中在抽取层和调度层后面会细说。2. 核心组件选型与数据建模细节2.1 向量库和图库的选型考量选型这块我不打算给具体产品名因为不同团队的技术栈和运维能力差别太大给死了反而误导。我说说选型的判断维度。向量库看几个点索引类型HNSW召回快但内存吃得多IVF省内存但需要训练、是否支持标量过滤很多场景要语义相似且时间在X之后纯向量库做不了、写入吞吐知识库更新频繁的话这点很关键、分布式能力数据量上亿之后单机扛不住。图库看几个点查询语言表达力多跳、路径、聚合是否顺手、是否支持属性图边上挂属性对知识图谱很重要、写入性能实体抽取是批量写入慢的话整个流水线会堵、和现有生态的集成度。我的经验是中小规模千万级向量、百万级节点优先选运维简单的别一上来就搞分布式集群复杂度会把迭代速度拖死。等数据量真的上来了再迁移迁移成本远低于前期过度设计的维护成本。2.2 实体与关系的建模方法这是整个项目里最费脑子的部分。建模建得好后面查询顺风顺水建得烂图库就是一堆查不动的垃圾数据。我的做法是先定实体类型再定关系类型最后定属性。实体类型不要贪多我一开始定义了十几种后来发现很多类型边界模糊抽取的时候模型老是分不清。收敛到五六个核心类型之后准确率明显上来了。关系类型同理宁可少而准不要多而乱。我最终保留的关系类型控制在十种以内每种都有明确的语义定义和抽取示例。这里有个技巧给每种关系写三到五个正例和反例作为抽取时的few-shot提示能显著降低误抽率。属性方面时间属性一定要有。知识库里的信息很多是有时效性的没有时间维度后面做某时间点之前的状态这类查询就抓瞎。2.3 向量与图数据的映射对齐这是协同的关键也是最容易出问题的地方。我的方案是给每个文档片段分配一个全局唯一的chunk_id给每个实体分配一个全局唯一的entity_id。在向量库里每条记录存chunk_id、原文、向量以及这段文本里出现的entity_id列表。在图库里每个实体节点存entity_id和实体名同时存一个source_chunk_ids属性记录这个实体是从哪些片段抽出来的。这样两边就通过entity_id和chunk_id双向打通了。查询的时候向量检索返回chunk_id可以顺着拿到相关实体图检索返回entity_id可以顺着拿到原始文本片段。这个双向映射是整个协同架构的地基建的时候一定要保证一致性我见过因为ID对不上导致检索结果残缺的案例排查起来非常痛苦。提示映射关系建议单独存一张表或者一个轻量级存储里不要只依赖两个库各自的字段方便做一致性校验和修复。3. 从原始文档到双库数据的完整流水线3.1 文档预处理与切片策略原始文档五花八门PDF、Word、Markdown、网页都有。第一步是统一转成纯文本这一步用现成的解析库就行但要注意表格和列表的处理很多解析器会把表格拍平成一坨丢失结构信息。我的做法是表格单独抽出来转成结构化的键值对作为独立片段处理。切片策略直接影响检索质量。我试过固定长度切片、按段落切片、按语义切片三种。固定长度最简单但会切断语义按段落切分保留了自然边界但长度不均语义切片效果最好但需要额外模型调用成本高。最终我用的是混合策略先按标题层级切大块大块超过阈值再按段落切段落还超就按句子切同时设置重叠窗口我用的重叠比例是15%左右。重叠是为了避免关键信息正好落在切分点上被割裂。这个比例不是拍脑袋定的我做过对比实验10%以下容易漏20%以上冗余太多影响检索精度15%是个比较平衡的点。3.2 用大模型做实体关系抽取抽取这一步我用的是提示工程结构化输出的方案。给大模型一段文本要求它输出符合预定义schema的JSON包含实体列表和关系列表。提示词的设计有几个要点。第一schema要写死在提示里包括实体类型、关系类型、每种类型的定义和示例。第二要求模型输出置信度低置信度的抽取结果可以人工复核或者直接丢弃。第三要求模型标注证据片段也就是这个实体或关系是从哪句话抽出来的方便溯源。抽取的准确率不可能100%我的实测是在规范文档上能到85%左右在口语化的会议纪要上会掉到70%以下。所以一定要有后处理对实体做归一化同义词合并、大小写统一对关系做冲突检测同一对实体出现矛盾关系时标记出来。这里有个省钱的技巧不是所有片段都值得抽取。可以先做一轮粗筛只对包含潜在实体信号的片段调用抽取模型能省下不少token成本。3.3 双库写入与一致性保障抽取完之后向量库和图库要分别写入。向量库写入相对简单把片段文本过一遍嵌入模型拿到向量连同chunk_id、原文、实体列表一起写进去。注意嵌入模型要和查询时用的保持一致换模型意味着所有向量都要重算这个坑我踩过血的教训。图库写入复杂一些因为要处理实体去重和关系合并。同一个实体在不同片段里可能表述不同需要先做实体链接把它们归并到同一个entity_id。关系合并的时候如果同一对实体之间有重复关系可以累加权重或者保留多条带不同来源的记录。一致性保障方面我加了一个校验任务定期扫描两个库检查entity_id和chunk_id的映射是否完整、是否有孤儿记录。发现问题就触发修复。这个任务看起来多余但实际运行中确实抓到过几次写入失败导致的映射缺失。4. 检索调度与关联推理的实现4.1 查询意图的识别与路由用户的问题进来第一步是判断该走哪条路。我把它分成三类纯语义查询找和X相似的资料、纯关系查询X和Y是什么关系、混合查询找出所有和X相关且涉及Y的决策。前两类分别走向量库和图库第三类两边都走。意图识别我用的是小模型分类加规则兜底。小模型负责粗分类规则负责处理一些明显的模式比如问题里出现关系关联影响这类词就倾向图检索出现相似类似相关内容就倾向向量检索。规则兜底很重要因为小模型在边界case上不稳定规则能兜住大部分明显情况。路由错了的代价很大走向量库的关系查询基本返回一堆无关片段所以我在路由层加了一个置信度阈值低于阈值的时候两条路都走宁可多查不可漏查。4.2 向量检索与图检索的并行执行确定路由之后两条检索并行跑。向量检索这边查询文本过嵌入模型拿向量然后做近似最近邻搜索返回top-k片段。k值我一般设10到20太少召回不够太多噪声大。如果支持标量过滤会把时间、类型等条件带上。图检索这边把自然语言问题转成图查询语句。这一步我用的是大模型生成查询模板再填充参数的方式而不是让模型直接生成查询语句因为直接生成容易出语法错误和注入风险。模板覆盖常见的几类查询模式模型只负责填实体名和条件。并行执行用异步任务两边都设超时避免一边卡住拖垮整个请求。超时的那边返回空结果另一边正常返回生成层会说明部分信息未能获取。4.3 结果融合与关联路径推理两边结果回来之后要融合。融合不是简单拼接而是按实体对齐。具体做法是向量检索返回的片段里带着entity_id列表图检索返回的路径里也带着entity_id。以entity_id为键做join把同一个实体相关的片段和关系聚到一起。这样生成层拿到的就是某个实体的原文描述它在图里的关系网络信息是完整的。关联路径推理是这套架构的亮点。图检索可以返回多跳路径比如A方案→被B决策采纳→B决策由C提出→C还提出了D决策。这条路径本身就是推理结果生成层把它翻译成人话就能回答这个方案的影响链条这类问题。多跳的深度要控制我一般限制在3跳以内再深的话路径爆炸而且相关性会急剧下降。5. 大模型在协同架构中的三重角色5.1 作为抽取器非结构化到结构化前面提过大模型在索引阶段负责实体关系抽取。这里补充几个实操细节。批量处理比单条处理效率高得多。我一开始一条一条调速度慢成本高。后来改成批量一次塞5到10个片段让模型分别输出吞吐量上去了成本也降了。但批量不能太大超过模型的上下文窗口或者让模型串味把不同片段的信息混在一起就得不偿失。输出格式要强约束。我用的是JSON schema校验模型输出不符合格式就重试重试两次还不行就丢弃。这个机制能过滤掉大部分格式错误。抽取结果要留痕。每条实体和关系都记录来源片段和置信度方便后续人工审核和问题追溯。5.2 作为调度器自然语言到查询语句查询阶段大模型负责把用户问题翻译成对两类数据库的操作。这里的关键是给模型足够的上下文。我会把图库的schema有哪些实体类型、关系类型和向量库的字段说明一起塞进提示让模型知道有哪些工具可用。然后要求模型输出一个结构化的查询计划包含走哪条路、用什么参数。模型有时候会自作主张生成不存在的查询模式所以我在后面加了一层校验检查生成的查询计划是否符合预定义的模式不符合就回退到默认策略。5.3 作为生成器检索结果到自然语言最后一步是把检索结果生成回答。提示词里我会明确要求只基于检索到的内容回答不要编造。检索结果里包含原文片段和关系路径模型要做的就是把它们组织成连贯的回答并标注信息来源。引用来源很重要一方面是可信度另一方面方便用户核查。我要求模型在回答里用[来源:chunk_id]的格式标注前端渲染的时候可以做成可点击的链接。如果检索结果不足以回答问题模型要明确说根据现有资料无法回答而不是硬编。这个约束能大幅降低幻觉。6. 实操中踩过的坑与排查技巧6.1 抽取质量不稳定的排查思路抽取质量波动是最常见的问题。我的排查顺序是先看输入文本质量再看提示词最后看模型。输入文本如果本身格式混乱、错别字多抽取质量肯定差。这种情况先做文本清洗。提示词的问题通常是schema定义不清或者示例不够补充示例往往能解决。模型的问题相对少见但如果换了模型版本后质量下降要考虑回滚。我整理了一个速查表现象可能原因排查动作实体漏抽严重提示词未覆盖该类型补充类型定义和示例关系方向搞反关系定义有歧义明确方向语义加反例同一实体多个ID未做实体链接加归一化步骤抽取结果格式错输出约束不够加schema校验和重试特定文档质量差文本本身问题先做文本清洗6.2 检索结果不相关的调优方法检索不相关先分清楚是向量检索的问题还是图检索的问题。向量检索不相关通常是嵌入模型不适合当前领域。通用嵌入模型在专业领域上表现会打折可以考虑用领域数据微调或者换一个在该领域表现更好的模型。另一个原因是切片粒度不对切片太大语义被稀释太小信息不完整。图检索不相关通常是查询模板覆盖不够或者图数据本身稀疏。前者补充模板后者要回头检查抽取环节是不是漏了太多关系。6.3 双库数据不一致的修复经验数据不一致的表现是向量库里有某个片段但图库里找不到对应的实体或者反过来。我的修复流程是先跑一致性校验脚本定位不一致的记录然后判断是写入失败还是抽取失败写入失败就重写抽取失败就重新抽取。修复的时候要注意幂等避免重复写入造成新的不一致。预防方面我在写入流程里加了事务性保障两个库的写入要么都成功要么都回滚。虽然实现起来麻烦点但比事后修复省心得多。7. 性能优化与成本控制的实战经验7.1 检索延迟的优化手段延迟主要花在三个地方嵌入计算、向量检索、图查询。嵌入计算可以缓存相同文本的向量算一次存起来。向量检索的延迟主要看索引类型和参数调小搜索范围能降延迟但会牺牲召回需要权衡。图查询的延迟看查询复杂度多跳查询要控制跳数必要时加索引。我实测下来一个中等规模的知识库百万级片段、十万级节点端到端延迟能控制在两秒以内其中大模型生成占了大头。如果对延迟敏感可以考虑用更小的生成模型或者流式输出。7.2 大模型调用成本的压缩策略成本主要花在抽取和生成两个环节。抽取环节批量处理和粗筛是两个有效的降本手段。生成环节控制上下文长度很关键检索结果不要一股脑全塞进去按相关性排序取top-n。还有一个技巧是缓存常见问题的回答。知识库里很多问题是重复的缓存命中能省下大量调用。7.3 增量更新与全量重建的取舍知识库是活的文档会不断更新。全量重建成本高但一致性好增量更新成本低但容易积累不一致。我的策略是增量为主、定期全量。日常更新走增量每周或每月做一次全量重建把增量过程中积累的碎片整理掉。全量重建安排在低峰期避免影响线上服务。增量更新的时候要特别注意删除和修改的处理。文档删了对应的向量和图数据也要删文档改了旧数据要失效。这块我一开始没处理好导致检索返回已删除的内容后来加了软删除标记才解决。8. 这套架构适合什么场景不适合什么场景8.1 高价值适用场景企业知识管理是这套架构最典型的应用。文档多、关系复杂、需要语义检索和关系推理三个条件都满足。技术文档问答也很合适。API文档、架构说明、故障复盘之间有关联关系用户的问题往往需要跨文档推理。合规与风控审查场景下需要顺着实体关系追查影响范围图检索的价值特别明显。8.2 需要谨慎评估的场景纯关键词检索能满足的场景上这套架构是杀鸡用牛刀成本和复杂度都不划算。数据量极小几千条以内的场景用简单的方案就行没必要引入两套数据库。对延迟极度敏感毫秒级的场景大模型生成这一环会成为瓶颈需要重新评估。8.3 后续可扩展的方向一个方向是多模态扩展把图片、表格里的信息也纳入进来向量库支持多模态嵌入图库支持多模态实体。另一个方向是时序推理给关系加上时间维度支持某时间点的状态和状态变化过程的查询。还有一个方向是主动学习把用户的反馈哪些回答有用、哪些没用收集起来反哺抽取和检索的优化形成闭环。我在实际项目里最先做的是时序推理这一块因为业务方对什么时候发生了什么变化这类问题需求很强烈。实现上就是在关系边上加时间戳查询的时候带上时间条件图查询语言对这类过滤支持得还不错。多模态那块我还在摸索主要是嵌入模型和图数据模型的适配比较麻烦等有成熟方案了再展开讲。