Content Enhancement 与嵌入(中文译文)
原始 DeepWiki 页面:https://deepwiki.com/infiniflow/ragflow/6.3-content-enhancement-and-embedding
翻译时间:2026-05-27T08:44:37.286Z
翻译模型:deepseek-chat
原文字符数:17281
项目:RAGFlow (ragflow)
---
内容增强与嵌入
相关源文件
以下文件被用作生成此维基页面的上下文:
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)操作。
flowchart TB
subgraph Input["已解析片段输入"]
Chunks["包含 content_with_weight 的片段"]
end
subgraph Enhancement["基于大语言模型(LLM)的增强(可选)"]
Keywords["关键词提取<br/>`keyword_extraction`"]
Questions["问题生成<br/>`question_proposal`"]
Metadata["元数据提取<br/>`gen_metadata`"]
Tagging["内容标签标注<br/>`content_tagging`"]
end
subgraph Embedding["嵌入过程(强制)"]
PrepText["文本准备"]
TitleEmbed["标题嵌入<br/>`emb_mdl.encode`"]
ContentEmbed["内容嵌入<br/>`emb_mdl.encode`"]
WeightedVec["加权组合<br/>`filename_embd_weight`"]
end
subgraph Storage["片段实体存储"]
ImportantKwd["`important_kwd` + `important_tks`"]
QuestionKwd["`question_kwd` + `question_tks`"]
MetadataObj["`metadata_obj`"]
TagFld["`tag_fld`"]
EmbVec["`q_N_vec`"]
end
Chunks -->|输入| Keywords
Chunks --> Questions
Chunks --> Metadata
Chunks --> Tagging
Keywords --> ImportantKwd
Questions --> QuestionKwd
Metadata --> MetadataObj
Tagging --> TagFld
Chunks --> PrepText
PrepText --> TitleEmbed
PrepText --> ContentEmbed
TitleEmbed --> WeightedVec
ContentEmbed --> WeightedVec
WeightedVec --> EmbVec
ImportantKwd --> Storage
QuestionKwd --> Storage
MetadataObj --> Storage
TagFld --> Storage
EmbVec --> Storage
来源: 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() 进行分词后的关键词,用于全文搜索索引。
sequenceDiagram
participant build_chunks as "task_executor.build_chunks"
participant cache as "graphrag.utils.get_llm_cache"
participant chat_llm as "prompts.generator.keyword_extraction"
participant chunk as "文档片段"
build_chunks->>build_chunks: 如果 auto_keywords > 0
build_chunks->>cache: get_llm_cache(llm_name, content, "keywords", topn)
alt 缓存命中
cache-->>build_chunks: 缓存的关键词
else 缓存未命中
build_chunks->>chat_llm: keyword_extraction(mdl, content, topn)
chat_llm-->>build_chunks: 关键词字符串,例如 "keyword1,keyword2,..."
build_chunks->>cache: set_llm_cache(...)
end
build_chunks->>chunk: important_kwd = split(",")
build_chunks->>chunk: important_tks = rag_tokenizer.tokenize(keywords)
来源: 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控制。 - 工作流:
flowchart LR
subgraph ChunkLevel["片段"]
Chunk1["片段 1 metadata_obj"]
Chunk2["片段 2 metadata_obj"]
ChunkN["片段 N metadata_obj"]
end
subgraph Merge["元数据聚合"]
updateMeta["update_metadata_to(metadata_agg, metadata_obj)"]
existingMeta["DocMetadataService.get_metadata_for_documents()"]
finalMeta["DocMetadataService.update_document_metadata()"]
end
Chunk1 --> updateMeta
Chunk2 --> updateMeta
ChunkN --> updateMeta
updateMeta --> existingMeta --> finalMeta
- 使用
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
---
内容标签标注
- 功能: 使用从指定知识库词汇表中派生的标签来标注片段。
- 实现:
- 标签存储在片段的
tag_fldJSON 字段中。
- 首先尝试通过 settings.retriever.tag_content() 进行基于向量的标签标注;与现有已标注片段足够相似的片段会继承其标签。 - 对于没有向量匹配的剩余片段,通过大语言模型(LLM)使用少量样本示例进行 content_tagging() 调用。
来源: 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)和片段内容分别生成嵌入向量,然后使用可配置的权重将它们组合起来。
flowchart TB
subgraph TitleEmbedding["标题嵌入"]
DocTitle["文档标题:docnm_kwd"]
TitleEnc["emb_mdl.encode([docnm_kwd])"]
TitleVec["标题嵌入向量"]
end
subgraph ContentEmbedding["内容嵌入"]
PrepText["准备好的片段文本"]
BatchEnc["emb_mdl.encode(文本批次)"]
ContentVec["片段内容向量"]
end
subgraph Combination["组合"]
TitleW["权重:filename_embd_weight(默认 0.1)"]
Formula["最终向量 = title_w * title_vec + (1 - title_w) * content_vec"]
FinalVec["q_N_vec"]
end
DocTitle --> TitleEnc --> TitleVec
PrepText --> BatchEnc --> ContentVec
TitleVec --> Formula
ContentVec --> Formula
TitleW --> Formula --> FinalVec
- 默认权重参数
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
---
向量字段命名约定
- 嵌入向量使用编码其维度的动态字段名存储:
- 此命名用于文档存储以及检索系统查询向量。
Dealer类根据嵌入向量长度计算这些名称。
- 示例字段名:q_1536_vec(其中 1536 是向量维度)。
来源: rag/svr/task_executor.py:622-625, rag/nlp/search.py:59-61
---
大语言模型(LLM)增强的缓存策略
- 大语言模型(LLM)生成的增强数据会被缓存,以最小化 API 成本和延迟。
- 缓存管理方式:
- 缓存键包括模型标识符、文本内容、操作类型("keywords"、"question" 等)以及要提取的数量等参数。
- 使用 get_llm_cache() 检查输入是否命中缓存。 - 在生成新数据后,使用 set_llm_cache() 设置新的缓存条目。
来源: 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)调用,通过并发控制维持吞吐量,并集成多种类型的元数据来增强片段的可搜索性,使其超越单纯的关键词匹配。输出是一个增强后的片段索引,支持结合稠密语义和稀疏文本信号的强大混合搜索。
---
连接自然语言空间与代码实体空间的图表
flowchart LR
subgraph "自然语言空间"
keywords["关键词提取(keywords)"]
questions["问题生成(questions)"]
metadata["元数据提取(metadata)"]
tagging["内容标签标注(tags)"]
embedding["嵌入(vectors)"]
end
subgraph "代码实体空间"
build_chunks["rag.svr.task_executor.build_chunks()"]
llm_cache["rag.graphrag.utils.get_llm_cache/set_llm_cache"]
keyword_extraction["rag.prompts.generator.keyword_extraction()"]
question_proposal["rag.prompts.generator.question_proposal()"]
gen_metadata["rag.prompts.generator.gen_metadata()"]
content_tagging["rag.prompts.generator.content_tagging()"]
emb_encode["api.db.services.llm_service.LLMBundle.encode()"]
rag_tokenize["rag.nlp.rag_tokenizer.tokenize()"]
end
keywords --> keyword_extraction
questions --> question_proposal
metadata --> gen_metadata
tagging --> content_tagging
embedding --> emb_encode
build_chunks -.-> llm_cache
build_chunks --> keyword_extraction
build_chunks --> question_proposal
build_chunks --> gen_metadata
build_chunks --> content_tagging
build_chunks --> emb_encode
build_chunks --> rag_tokenize
flowchart LR
subgraph "自然语言处理"
rag_tokenizer["rag.nlp.rag_tokenizer.tokenize()"]
llm_cache["缓存:graphrag.utils.get_llm_cache/set_llm_cache"]
prompt_gen["rag.prompts.generator 函数"]
end
subgraph "任务执行器与嵌入"
task_executor["rag.svr.task_executor.build_chunks()"]
llm_service["api.db.services.llm_service.LLMBundle"]
search_dealer["rag.nlp.search.Dealer"]
end
rag_tokenizer --> task_executor
llm_cache --> task_executor
prompt_gen --> task_executor
task_executor --> llm_service
task_executor --> search_dealer
---
参考
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
来源: 以上所有文件