背景介绍
之前深入源码对 Dify 的 完整流程 进行了解读,基本上梳理了 Dify 的实现流程与主要组件。
但是在实际部署之后,发现 Dify 现有的 RAG 检索效果没有那么理想。因此个人结合前端页面,配置信息与实现流程,深入查看了私有化部署的 Dify 的技术细节。
将核心内容整理在这边,方便大家根据实际的业务场景调整 Dify 知识库的配置,或者根据需要进行二次开发调优。
技术细节
本次重点介绍的是 Dify docker 私有化部署 默认情况的技术方案,个人本地部署使用的 Dify + Xinference,感兴趣可以查看 Dify 与 Xinference 最佳组合 GPU 环境部署全流程。
RAG 涉及的核心流程如下所示:
下面对各个模块的机制与优化方案进行深入介绍。
Extractor
Extractor
对应的 Dify 中的文件解析模块,用于从原始文件中提取文字内容。核心的文件解析流程在 api/core/rag/extractor/extract_processor.py
中实现。
从用户视角来看,目前存在两类解析方案:
- 基于 Unstructured 的文件解析方案,支持接入付费的 Unstructured 服务,部分的格式解析只有付费版本才支持,比如
.ppt
; - 常规的 Dify 文件解析方案,基于开源库进行文件解析;
目前私有化部署时默认使用的是 Dify 文件解析方案,可以通过修改 .env
配置调整为 Unstructured 解析,但是使用 Unstructured 解析时需要配置对应的 Unstructured API 和 API Key,对应的配置如下所示:
// 文件解析类型,可以设置为 dify 或 Unstructured
ETL_TYPE=dify
UNSTRUCTURED_API_URL=
UNSTRUCTURED_API_KEY=
如果希望调整为 Unstructured
解析,可以修改 ETL_TYPE
字段。考虑到 Unstructured
解析可能需要付费,一般情况下可能直接使用 Dify 解析方案就好。可以看看默认 Dify 解析方案下的具体解析实现:
- pdf 目前的解析是基于 pypdfium2 直接提取内容;
- html 目前的解析是基于 BeautifulSoup 简单提取内容;
都属于极其常规的开源方案,如果希望具备更好的效果,可以考虑针对特定类型实现自定义的解析方案。
Cleaner
Cleaner
对应的解析内容的清洗模块,可以去除无关的字符,减少后续 token 的消耗。最核心的清洗流程在 api/core/rag/cleaner/clean_processor.py
中,目前主要是基于特定规则进行过滤:
def clean(cls, text: str, process_rule: dict) -> str:
# 默认清洗,必然会执行
text = re.sub(r'<\|', '<', text)
text = re.sub(r'\|>', '>', text)
text = re.sub(r'[\x00-\x08\x0B\x0C\x0E-\x1F\x7F\xEF\xBF\xBE]', ''