内容增强与嵌入
内容增强与嵌入
相关源文件
本章引用的主要源码文件:
api/db/__init__.pyapi/db/db_models.pyapi/db/services/dialog_service.pyapi/db/services/document_service.pyapi/db/services/file_service.pyapi/db/services/knowledgebase_service.pyapi/db/services/llm_service.pyapi/db/services/task_service.pyapi/db/services/user_service.pydeepdoc/parser/excel_parser.pydeepdoc/parser/paddleocr_parser.pyrag/app/book.pyrag/app/laws.pyrag/app/manual.pyrag/app/naive.pyrag/app/one.pyrag/app/paper.pyrag/app/presentation.pyrag/app/qa.pyrag/app/table.pyrag/nlp/__init__.pyrag/nlp/search.pyrag/prompts/meta_filter.mdrag/raptor.pyrag/svr/task_executor.pytest/unit_test/common/test_apply_semi_auto_meta_data_filter.pyweb/src/components/metadata-filter/index.tsxweb/src/components/metadata-filter/metadata-filter-conditions.tsxweb/src/components/metadata-filter/metadata-semi-auto-fields.tsxweb/src/components/originui/time-range-picker.tsxweb/src/components/paddleocr-options-form-field.tsxweb/src/components/ui/input-select.tsxweb/src/pages/user-setting/setting-model/modal/paddleocr-modal/index.tsx
目的与范围
本文档详细介绍了 RAGFlow 文档处理管线中的内容增强与嵌入阶段。在文档解析和片段切分(详见页面 6.1 和 6.2)之后,提取出的片段会经过可选的大语言模型(LLM)驱动增强(包括关键词提取、问题生成、元数据提取、内容标签标注),随后进行强制性的向量嵌入。这些经过增强和嵌入的片段最终被存储在文档存储中,为高效的检索和知识查询做好准备。
关于涉及层次聚类和知识图谱提取的高级增强技术,请参见 6.5。关于使用这些嵌入向量的检索管线的详细信息,请参见 9。
架构总览
内容增强与嵌入管线使用大语言模型(LLM)生成的语义信息来丰富已解析的片段,并将其编码为稠密向量以供检索。系统采用并发控制机制来高效管理大语言模型(LLM)调用和嵌入过程,并维护缓存以优化成本高昂的大语言模型(LLM)操作。
来源: rag/svr/task_executor.py:343-626
基于大语言模型(LLM)的增强功能
增强功能通过解析器和知识库配置来控制。每个功能都使用聊天大语言模型(LLM)调用从片段文本中推导出语义增强信息,并将其存储到片段字段中,以方便检索和过滤。
关键词提取
- 功能: 提取总结片段内容的关键词。
- 配置: 由数据集和解析器配置中的
auto_keywords控制。 - 实现要点:
- 使用
chat_limiter信号量限制并发的大语言模型(LLM)调用。 - 使用以
(llm_name, content, "keywords", topn)为键的大语言模型(LLM)缓存,避免重复开销。 - 调用
rag.prompts.generator中的keyword_extraction(mdl, content, topn)函数。 - 解析逗号分隔的关键词,进行拆分,并存储在:
important_kwd:原始关键词列表。important_tks:使用rag_tokenizer.tokenize()进行分词后的关键词,用于全文搜索索引。
- 使用
来源: rag/svr/task_executor.py:343-375, rag/prompts/generator.py:45-46, rag/graphrag/utils.py:44-44
问题生成
- 功能: 生成片段内容可以回答的问题,以提高检索相关性。
- 配置: 由文档/数据集级别的
parser_config中的auto_questions控制。 - 实现要点:
- 使用相同的缓存方法,键为
(llm_name, content, "question", topn)。 - 调用大语言模型(LLM)函数
question_proposal(chat_mdl, content, topn)。 - 按行拆分接收到的问题文本,形成
question_kwd列表。 - 将生成的问题分词为
question_tks,以兼容 BM25 搜索。
- 使用相同的缓存方法,键为
| 字段 | 用途 |
|---|---|
question_kwd | 生成的问题列表,原始文本 |
question_tks | 用于索引的问题分词文本 |
来源: rag/svr/task_executor.py:377-408, rag/prompts/generator.py:45-46, api/db/db_models.py:530
元数据提取
- 功能: 从片段内容中提取结构化元数据字段,以实现过滤和分面搜索。
- 配置: 由解析器和数据集中的
enable_metadata控制。 - 工作流:
- 使用
update_metadata_to()将各个片段的metadata_obj字典合并到一个聚合字典中,该函数会智能地合并值。 - 从数据库中获取现有的文档元数据,并与聚合结果合并。
- 通过
DocMetadataService.update_document_metadata()将合并后的元数据存储回数据库。
来源: rag/svr/task_executor.py:410-452, common/metadata_utils.py:38, api/db/services/doc_metadata_service.py:1
内容标签标注
- 功能: 使用从指定知识库词汇表中派生的标签来标注片段。
- 实现:
- 首先尝试通过
settings.retriever.tag_content()进行基于向量的标签标注;与现有已标注片段足够相似的片段会继承其标签。 - 对于没有向量匹配的剩余片段,通过大语言模型(LLM)使用少量样本示例进行
content_tagging()调用。
- 首先尝试通过
- 标签存储在片段的
tag_fldJSON 字段中。
来源: rag/svr/task_executor.py:454-517, rag/prompts/generator.py:45-46
嵌入过程
所有片段都必须经过嵌入,以支持稠密向量检索。
用于嵌入的文本准备
- 如果片段存在生成的问题,则将这些问题拼接起来作为嵌入输入。
- 否则,使用片段的
content_with_weight原始文本。 - 移除与表格相关的 HTML 标签以减少噪声。
c = "\n".join(d.get("question_kwd", []))
if not c:
c = d["content_with_weight"]
c = re.sub(r"</?(table|td|caption|tr|th)( [^<>]{0,12})?>", " ", c)
来源: rag/svr/task_executor.py:579-587
双重嵌入:标题与内容融合
RAGFlow 会为文档标题(docnm_kwd)和片段内容分别生成嵌入向量,然后使用可配置的权重将它们组合起来。
- 默认权重参数
filename_embd_weight为 0.1(标题占 10% 的影响)。 - 这种加权融合通过将文档标识与片段内容一起嵌入,有助于提高相关性。
来源: rag/svr/task_executor.py:589-625
批处理与并发
- 嵌入过程是并行化的,批次大小由
BATCH_SIZE(默认 64)定义。 embed_limiter信号量控制并发嵌入过程,可通过MAX_CONCURRENT_CHUNK_BUILDERS配置。- 异步工作以优化吞吐量,同时尊重资源限制。
来源: rag/svr/task_executor.py:83-129, rag/svr/task_executor.py:595-609
向量字段命名约定
- 嵌入向量使用编码其维度的动态字段名存储:
- 示例字段名:
q_1536_vec(其中 1536 是向量维度)。
- 示例字段名:
- 此命名用于文档存储以及检索系统查询向量。
Dealer类根据嵌入向量长度计算这些名称。
来源: rag/svr/task_executor.py:622-625, rag/nlp/search.py:59-61
大语言模型(LLM)增强的缓存策略
- 大语言模型(LLM)生成的增强数据会被缓存,以最小化 API 成本和延迟。
- 缓存管理方式:
- 使用
get_llm_cache()检查输入是否命中缓存。 - 在生成新数据后,使用
set_llm_cache()设置新的缓存条目。
- 使用
- 缓存键包括模型标识符、文本内容、操作类型("keywords"、"question" 等)以及要提取的数量等参数。
来源: rag/svr/task_executor.py:350-357, rag/svr/task_executor.py:384-391, rag/graphrag/utils.py:44
与检索管线的集成
增强后的片段字段在检索中扮演多种角色:
| 字段 | 用途 | 相关代码实体 |
|---|---|---|
q_N_vec | 稠密向量相似度搜索 | MatchDenseExpr in search.py |
content_ltks | 稀疏全文匹配 | FulltextQueryer in search.py |
question_tks | 稀疏问题查询匹配 | FulltextQueryer in search.py |
important_tks | 稀疏关键词搜索 | FulltextQueryer in search.py |
检索系统使用 FusionExpr 来融合稠密和稀疏信号。
来源: rag/nlp/search.py:53-168, api/db/services/dialog_service.py:44-46
性能与监控
并发控制
多个信号量限制了增强和嵌入过程中的并行度,以避免过载:
task_limiter:限制并发的总片段任务数。chunk_limiter:限制片段构建的并发度。embed_limiter:限制嵌入 API 调用的并发度。
通过环境变量(如 MAX_CONCURRENT_TASKS 和 MAX_CONCURRENT_CHUNK_BUILDERS)进行配置。
进度报告
函数 set_progress(task_id, ...) 会更新数据库中的任务状态和进度消息,在增强和嵌入过程中提供实时反馈。
来源: rag/svr/task_executor.py:125-131, rag/svr/task_executor.py:143-168
总结
这个内容增强与嵌入阶段是一个关键的中间步骤,它将解析器转换后的原始文档片段转化为语义丰富且向量化的实体。系统通过缓存优化大语言模型(LLM)调用,通过并发控制维持吞吐量,并集成多种类型的元数据来增强片段的可搜索性,使其超越单纯的关键词匹配。输出是一个增强后的片段索引,支持结合稠密语义和稀疏文本信号的强大混合搜索。
连接自然语言空间与代码实体空间的图表
参考
rag/svr/task_executor.py:343-626rag/prompts/generator.py:40-65rag/graphrag/utils.py:40-50rag/nlp/search.py:37-118api/db/services/llm_service.py:80-150api/db/services/doc_metadata_service.py:1-1
来源: 以上所有文件