很多人照着教程把 Dify 和 Ollama 连上了,能对话,就以为知识库搭完了。真丢进团队文档才发现:答非所问、找不到原文、同一份文件两种说法。问题通常不在模型,而在切片方式、嵌入与重排选型、检索参数这几处没定。这篇按搭建顺序给判断标准和排查动作,不谈榜单也不比谁强。
很多人照着教程把 Dify 和 Ollama 连上了,能对话,就以为知识库搭完了。真丢进团队文档才发现:答非所问、找不到原文、同一份文件两种说法。问题通常不在模型本身,而在切片方式、嵌入与重排选型、检索参数这几处没定下来。这篇按搭建顺序给判断标准和排查动作,不谈榜单也不比谁强。
先说一个容易踩的定位错误:Ollama 在这套组合里只干一件事,就是把模型跑在你自己的机器上并开一个本地接口。文档怎么切、向量存哪、召回几条、怎么拼上下文,全都是 Dify 侧的活。所以效果差的时候别急着换更大的模型,先分清是模型答不好,还是压根没把对的片段捞出来。
先把三块分工定下来:模型、检索、编排
先把职责边界划清楚,后面排查才有方向。Ollama 负责推理和提供本地接口,Dify 负责切片、向量存储、召回编排和提示词组装。两边各自有独立的配置位,尤其是对话模型和嵌入模型,是两个完全分开的设置,很多人只配了对话模型就以为完事了。
- 确认 Ollama 的监听地址能被 Dify 容器访问到,容器内的 localhost 指向的是容器自己而不是宿主机,这是最常见的连不通原因
- 对话模型和嵌入模型是两个独立配置位,别把同一个模型同时填进两个位置,嵌入模型有专门的用途
- 知识库答不对时先分诊:把原文直接贴进对话让它回答,能答对说明模型没问题,问题在检索;答不对才是模型或提示词的事
- 文档以表格、扫描件、图片为主的话,纯文本切片这条路不适用,得先做 OCR 或结构化解析再入库
- 分诊
- 先判断问题出在模型还是检索,两条路的修法完全不同,别一锅炖
- 适配边界
- 扫描件、图表、手写批注类的语料,先解决文字提取,再谈检索
切片是效果分水岭,先定切多大、留多少重叠
切片没有万能值,得按文档类型分别定。制度和说明书这类一节讲一个主题的,切片可以大一点,保住上下文;问答对、条款、条目式内容要切小,否则一个片段里混了好几个主题,模型抓不住重点。先拿几十篇有代表性的文档试,别一上来导全量。
| 文档类型 | 切片倾向 | 重叠倾向 | 原因 |
|---|---|---|---|
| 制度、说明书 | 偏大 | 中等 | 一节一义,需要保住前后语境 |
| 问答对、条目 | 偏小 | 偏小 | 避免一个片段混多个主题 |
| 长报告、手册 | 中等 | 中等 | 靠标题层级切比按字数切更稳 |
| 表格、扫描件 | 先解析 | 先不切 | 先解决文字提取再入库 |
重叠的作用是防止答案被切断,但重叠太大等于每个片段都被重复召回,反而挤掉真正相关的片段。另外给每个片段带上来源标记,比如文件名和章节路径,召回后能直接指回原文,团队复核时省很多扯皮。切片改完必须重建索引,只调参数不重建是最常见的白忙一场。
嵌入模型和重排:什么时候值得加一层
嵌入模型决定内容能不能被搜到,重排决定搜到的东西排不排得对,两者是串联关系,不是二选一。中文为主的语料,优先挑中文语义匹配表现稳的嵌入模型,选型口径可以到 /embeddings 页面核对当时的横向资料,别只按参数量挑,参数大不代表中文检索好。
- 文档量小、提问方式固定、召回的片段本来就在前几位时,不必加重排,加了只是徒增延迟
- 重度依赖长文档、同义表达多、用户问法千奇百怪的场景,重排往往能明显改善排序
- 加重排后要重跑同一批问题,对比命中片段的位置有没有前移,没变化说明这层在你这套语料上没产出价值
- 重排和嵌入别同时换,一次只动一个变量,否则出了变化也不知道是谁的功劳
检索参数怎么调:按现象改,别按感觉改
调参前先固定一批真实提问当基线,每次只改一个参数,记下命中片段的位置变化。召回条数调大能提高命中率,但会稀释上下文、抬高延迟,塞太多噪声进去,模型反而抓不住重点。上下文窗口也不是越大越好,历史对话塞满会挤占检索片段的位置。
| 现象 | 大概率原因 | 先动哪里 |
|---|---|---|
| 答非所问 | 召回条数太多夹杂噪声 | 先降召回条数,再看切片 |
| 答不全 | 切片过大或召回过少 | 先看切片粒度,再提召回条数 |
| 答错数字 | 没加重排或有版本冲突文档 | 加一层重排,再按版本过滤 |
| 答得像别的文档 | 嵌入模型不匹配或重叠过大 | 换嵌入模型,降重叠比例 |
多版本共存的团队,建议在元数据里区分版本,回答时限定生效版本,否则模型会把旧制度和新制度混着念。这种做法在文档更新频繁的团队里尤其值得做,不然每次改完文件都会出现新老说法打架。长会话场景要单独设截断策略,别让历史对话无限增长。
- 固定题集准备一批真实提问,一部分文档里能查到答案,一部分文档里明确没有,后者用来验证它会不会硬编答案。
- 记录失败类型把每类问题的失败原因记下来,分没召回、召回错、答偏、答编四类,按占比最高的先修。
- 改一个变量重跑每次只调整一个参数,重跑同一批问题,对比命中片段位置和回答质量的变化。
- 留反馈入口上线后放一个反馈入口,把答错的提问定期收回来补进题集,这是唯一能持续变好的机制。
常见问题
Dify 里连不上 Ollama,一般先查什么?
先分容器内外:Ollama 跑在宿主机,Dify 在容器里,写 localhost 必然不通,要换成宿主机的可访问地址或容器网络名。再确认 Ollama 是否对外监听,默认只绑本机。最后用同一台机器上的 curl 直接打接口,能把这一步打通,剩下的就只是填对地址。
本地知识库答不准,该换模型还是调检索?
先做分诊:把正确答案所在的原文片段手动贴进对话框问一遍,如果模型能答对,说明是检索没找到,问题在切片、嵌入或召回条数;如果贴了原文还是答错,才轮到考虑换模型。绝大多数人第一反应是换更大的模型,其实大部分问题出在召回这一层。
嵌入模型和对话模型必须用同一个吗?
不是,这两个是不同的配置位,可以各选各的。对话模型挑你机器跑得动、中文表达稳的;嵌入模型挑中文语义匹配好的,通常体积小很多,对显存压力不大。唯一要注意的是嵌入模型一旦换掉,已有向量索引必须全部重建,否则新旧向量不在一个空间里,检索会直接失效。