Files
MemoryBear/docs/rag/pipeline/05-reranking-prompt-llm.md
Multica PM Agent 343a5eebe3
Some checks failed
Sync to Gitee / sync (push) Has been cancelled
docs(rag): add MemoryBear RAG implementation docs v1.0
Submit the formed RAG documentation set produced across Sprint-1/2/3
(WS-12 through WS-26) under docs/rag/. Includes:

- README.md / INDEX.md: landing + total index (responsibility matrix,
  review verdicts, dual-link to source issues)
- overview/: full-pipeline architecture (4 .mmd diagrams),
  11-stage boundary contracts, doc map, source-code inventory
- pipeline/: 5 deep-dives (Loader/Parser/Chunking, Embedding,
  VDB & retrieval, GraphRAG, Rerank/Prompt/LLM)
- graphrag/, end-to-end/: v1.0 formal versions with full source
  retained as reference
- evolution/: 11 architecture-refactor proposals,
  6-direction roadmap, capability map
- review/: S3-T1 / S3-T2 final reviews, S2-T7 final summary
- _indexes/: glossary (81 terms), source->doc reverse index, chart index
- _release/: v1.0-RC1 release manifest, versioning convention,
  ops & freshness plan
- _meta/README.md: placeholder noting WS-12 governance assets gap

Aggregate review score 92.6/100 (8/8 PASS, 31/31 source-code spot
checks hit). The legacy docs/ ignore in .gitignore is narrowed to
docs/* with an explicit allowlist for docs/rag/.

Refs: WS-26
Co-authored-by: multica-agent <github@multica.ai>
2026-05-09 10:51:48 +08:00

17 KiB
Raw Blame History

# [S2-T5] 检索后处理与生成Reranking / Prompt 工程 / LLM 调用 / 后处理)实现详解 author: Python 开发工程师
source-commit: feae2f2e (Merge PR #1033 release/v0.3.2)
reviewer: 待 [S2-T7] 评审
last-reviewed-at: 2026-05-08

一句话定位

本文档覆盖 MemoryBear RAG 链路的后半段:从检索结果进入系统,到最终 LLM 生成答案并输出给用户的全过程包括重排序、Prompt 组装、多模型 LLM 调用、流式输出、工具调用及生成后处理。

设计目标与适用场景

  • 设计目标:在多知识库、多检索策略(关键词 / 向量 / 混合 / GraphRAG返回的原始结果上通过重排序提升相关性通过 Prompt 工程高效利用上下文,通过多提供商 LLM 封装实现高可用调用,最终输出带引用溯源、支持流式/非流式的答案。
  • 适用场景
    • Agent 聊天(app_chat_service.py / draft_run_service.py
    • Workflow 知识检索节点(workflow/nodes/knowledge/node.py
    • 独立 chunk 检索 APIchunk_controller.py

关键概念与术语表

术语 含义
Rerank 在初步召回后对 chunk 进行精细重排序
RedBearRerank 基于 LangChain BaseDocumentCompressor 的 rerank 封装
Dealer 底层检索调度器,负责混合搜索、内置 rerank、引用插入
KnowledgeRetrievalNode Workflow 引擎中的知识检索节点
LangChainAgent 基于 create_agent 的 ReAct Agent负责工具调用循环
citation 生成后处理阶段向答案文本中插入 [ID:N] 引用标记
rank_feature 基于 tag 特征和 PageRank 的辅助排序分

实现概览Mermaid 流程图)

检索结果输入
    │
    ▼
┌─────────────────┐
│  Rerank 层       │
│  A:内置混合      │
│  B:外部模型      │
│  C:RedBearRerank │
│  D:ES层封装      │
└────────┬────────┘
         │
         ▼
┌─────────────────────────┐
│ Prompt 工程与上下文组装   │
│ 系统 Prompt + 技能 Prompt │
│ 知识上下文拼接             │
│ Token 预算管理             │
└────────┬────────────────┘
         │
         ▼
┌─────────────────────────┐
│ LLM 调用层 (LangChainAgent)│
│ ReAct 工具调用循环         │
│ 流式/非流式               │
│ 多模态 + 深度思考          │
└────────┬────────────────┘
         │
         ▼
┌─────────────────────────┐
│ 生成后处理               │
│ 引用过滤 + 下载链接       │
│ 引用插入 (embedding 匹配) │
│ JSON 结构化校验           │
└─────────────────────────┘

1. Reranking 章节

1.1 是否使用显式 Rerank

。MemoryBear 在多处实现了 rerank采用"多方案并存、按场景选择"策略。

1.2 Rerank 方案全景

方案 A内置混合 RerankDealer.rerank

源码api/app/core/rag/nlp/search.py:606-643

核心融合公式:

score = tkweight * token_similarity + vtweight * vector_similarity + rank_feature
  • tkweight 默认 0.3vtweight 默认 0.7
  • token_similarity:基于 rag_tokenizer 分词后的 Jaccard 风格相似度
  • vector_similarityquery_vector 与 chunk 向量的余弦相似度
  • rank_featuretag 特征 TF-IDF 余弦 + PageRank缩放 10 倍(search.py:579-604
  • token 权重分配:content_ltks + title_tks*2 + important_kwd*5 + question_tks*6

方案 B外部 Rerank 模型Dealer.rerank_by_model

源码api/app/core/rag/nlp/search.py:645-666

将向量相似度替换为外部 rerank 模型的 similarity() 输出,保留 token 相似度和 rank_feature。

方案 CRedBearRerankLCEL 兼容封装)

源码api/app/core/models/rerank.py:11-84

  • 继承 langchain_core.documents.BaseDocumentCompressor
  • 支持 XINFERENCE / GPUSTACKJinaRerank
  • 支持 DASHSCOPEDashScopeRerank
  • 端点自动规范化:补齐 /v1/rerank

使用场景:

  • Workflow KnowledgeRetrievalNode.rerank()node.py:108-155
  • ElasticSearchVector.rerank()elasticsearch_vector.py:560-607
  • nlp/search.py:rerank()search.py:284-343

方案 DElasticSearchVector 层 Rerank

ES Vector 初始化时注入 reranker_configrerank() 中调用 self.reranker.compress_documents()

1.3 阈值与延迟

  • 内置 rerank:本地 numpy 计算,毫秒级延迟
  • 外部 rerank:网络调用,本地 Xinference <10ms远程 DashScope 100-500ms
  • 相似度阈值similarity_threshold 默认 0.2,低于此值的 chunk 被过滤(search.py:674-768

1.4 为什么没有统一使用 Cross-Encoder

  • Cross-Encoder 需额外部署,对小型部署不友好
  • 内置 Dealer.rerank 在多数场景已足够
  • RedBearRerank 作为可选增强,仅在显式配置 reranker_id 时启用

2. Prompt 工程与上下文组装

2.1 Prompt 模板组织

目录api/app/core/rag/prompts/

模板文件 用途
ask_summary.md 知识库问答主 Prompt
citation_prompt.md 引用标注规范([ID:i] 格式)
citation_plus.md 引用回填 Agent Prompt
question_prompt.md 文本生成问题
keyword_prompt.md 关键词提取
structured_output_prompt.md JSON Schema 约束
cross_languages_*.md 跨语言查询扩展
analyze_task_*.md 任务分析与工具选择

加载机制api/app/core/rag/prompts/template.py:9-20,启动时加载并缓存。

2.2 上下文组装流程

Agent 层api/app/core/agent/langchain_agent.py:230-271

def _prepare_messages(self, message, history, context, files):
    messages = []
    for msg in history:
        if msg["role"] == "user": messages.append(HumanMessage(...))
        elif msg["role"] == "assistant": messages.append(AIMessage(...))
    user_content = message
    if context:
        user_content = f"参考信息:\n{context}\n\n用户问题:\n{user_content}"
    messages.append(HumanMessage(content=user_content))
    return messages

2.3 知识检索工具中的 Chunk 拼接

源码api/app/services/draft_run_service.py:227-255

retrieve_chunks_result = knowledge_retrieval(query, kb_config)
retrieval_knowledge = [i.page_content for i in retrieve_chunks_result]
context = '\n\n'.join(retrieval_knowledge)
return f"检索到以下相关信息:\n\n{context}"
  • chunk 间用 \n\n 分隔
  • 引用信息document_id、file_name、score由外部 citations_collector 收集,与上下文字符串分离
  • 属于"隐式引用"策略LLM 看不到 [ID:N],引用回填在生成后完成

2.4 Token 预算管理

源码api/app/core/rag/prompts/generator.py:46-80

策略:

  1. 计算总 token未超限直接返回
  2. 超限后保留 system + 最后一条消息,丢弃中间历史
  3. 仍超限则按比例截断 system 或 user 内容

2.5 System / User 分层结构

system: {用户自定义 system_prompt} + {技能 Prompt} + {文档图片识别指令}
user:  {历史消息...}
user:  参考信息:\n\n{chunks}\n\n用户问题\n{query}

System Prompt 组装见 app_chat_service.py:77-96:先变量替换,再追加 skill_prompts。


3. LLM 调用

3.1 支持的模型与切换机制

核心封装api/app/core/rag/llm/chat_model.py:52-63

Base 类基于 OpenAI 兼容 API子类覆盖

类名 提供商
GptTurbo OpenAI
XinferenceChat Xinference
HuggingFaceChat HuggingFace
ModelScopeChat ModelScope
AzureChat Azure OpenAI
BaiChuanChat 百川
LocalAIChat LocalAI
VolcEngineChat 火山引擎
OpenAI_APIChat VLLM / OpenAI-API-Compatible
GPUStackChat GPUStack

切换机制ModelApiKeyService.get_available_api_key() 根据 model_id 从数据库读取 provider/api_key/base_url/model_name运行时动态实例化。

3.2 流式 vs 非流式

非流式Base._chat()chat_model.py:122-150

  • stream=False,返回 (text, total_tokens)
  • QWQ 推理模型强制内部走流式聚合,过滤 <think> 标签

流式Base._chat_streamly()chat_model.py:152-185

  • stream=Trueyield (delta, token_count)
  • 支持 reasoning_content 提取
  • finish_reason == "length" 时自动追加截断提示(中英文自适应)

Agent 流式LangChainAgent.chat_stream()

  • agent.astream_events(version="v2")
  • 处理 on_chat_model_stream / on_llm_stream
  • 支持多模态响应解析OpenAI + 通义千问格式)

3.3 超时、重试、降级

源码chat_model.py:64-89, 192-215

  • 超时:LLM_TIMEOUT_SECONDS(默认 600s
  • 重试:LLM_MAX_RETRIES(默认 5+ 随机抖动延迟
  • 仅对 RATE_LIMIT / SERVER_ERROR 重试
  • 降级:无自动模型降级,失败返回 "**ERROR**: ..."

3.4 函数调用 / 工具使用

源码chat_model.py:251-303, 335-436

  • 最多 max_rounds(默认 5轮工具调用循环
  • 工具参数解析使用 json_repair.loads() 增强容错
  • 流式工具调用:chat_streamly_with_tools()

Agent 工具循环LangChainAgent

  • create_agent(model, tools, system_prompt)
  • max_iterations = 5 + len(tools) * 2
  • 单个工具最大连续调用:max_tool_consecutive_calls = 3
  • _wrap_tools_with_tracking() 防循环

3.5 CV 模型与序列到文本模型

CV 模型cv_model.pyQWenCVAzureGptV4 — 用于图片/版面分析。

序列到文本sequence2txt_model.pyQWenSeq2txt(带时间戳 ASRGPTSeq2txtWhisper— 用于音视频预处理。


4. 生成后处理

4.1 引用回填Citation Insertion

源码api/app/core/rag/nlp/search.py:489-577

流程:

  1. 将答案按句子切分(避开代码块 ```
  2. 对每句话 embedding与 chunk embeddings 计算 hybrid similarity
  3. 阈值从 0.63 开始动态衰减×0.8),最低 0.3
  4. 每句最多引用 4 个 chunk句末插入 [ID:N]

4.2 引用过滤与下载链接

源码api/app/services/draft_run_service.py:474-490

  • features_config.citation.enabled 开关控制
  • allow_download=True 时附加 download_url

4.3 安全过滤

当前版本无显式敏感词过滤模块。安全依赖:

  • LLM 提供商自带内容过滤
  • ERROR_CONTENT_FILTER 错误码捕获

4.4 输出结构化JSON Schema

源码api/app/core/agent/langchain_agent.py:85-92

通过 system prompt 注入 "\n请以JSON格式输出。" 实现(非 response_format API因为 LangChain Agent 有工具时无法使用原生 API。


5. 端到端示例

场景Agent 聊天触发知识库检索

Step 1 — 用户提问:"MemoryBear 的 Rerank 策略是什么?"

Step 2 — System Prompt 组装:

你是一个专业的 AI 知识库助手,名为 Miss R。
任务:根据知识库中的信息回答用户问题。
要求:不要编造信息;使用 Markdown用用户提问的语言回答。

(来自 ask_summary.md

Step 3 — LLM 判断调用 knowledge_retrieval_tool

工具内部:

retrieve_chunks_result = knowledge_retrieval(query, kb_config)
context = '\n\n'.join([i.page_content for i in retrieve_chunks_result])
return f"检索到以下相关信息:\n\n{context}"

Step 4 — 若配置 reranker_id,执行 RedBearRerank

reranker = RedBearRerank(RedBearModelConfig(...))
reranked_docs = list(reranker.compress_documents(documents, query))

Step 5 — Agent 组装消息并调用 LLM

system: 你是一个专业的 AI 知识库助手...
user:   参考信息:\n\nChunk 0...\n\nChunk 1...\n\n用户问题\nMemoryBear 的 Rerank 策略是什么?

Step 6 — 输出后处理:

filtered_citations = _filter_citations(features_config, citations_collector)

最终返回content + citations含 document_id、file_name、score、可选 download_url


6. 关键源码索引

功能 文件 类/函数 行号
Rerank 封装 api/app/core/models/rerank.py RedBearRerank 11-84
内置混合 Rerank api/app/core/rag/nlp/search.py Dealer.rerank 606-643
外部模型 Rerank api/app/core/rag/nlp/search.py Dealer.rerank_by_model 645-666
rank_feature api/app/core/rag/nlp/search.py _rank_feature_scores 579-604
独立 rerank api/app/core/rag/nlp/search.py rerank() 284-343
知识检索入口 api/app/core/rag/nlp/search.py knowledge_retrieval() 36-147
ES Vector rerank api/app/core/rag/vdb/elasticsearch/elasticsearch_vector.py ElasticSearchVector.rerank 560-607
Workflow 节点 rerank api/app/core/workflow/nodes/knowledge/node.py KnowledgeRetrievalNode.rerank 108-155
Workflow 执行 api/app/core/workflow/nodes/knowledge/node.py KnowledgeRetrievalNode.execute 303-378
LLM 基类 api/app/core/rag/llm/chat_model.py Base 52-319
流式 LLM api/app/core/rag/llm/chat_model.py _chat_streamly 152-185
工具调用 api/app/core/rag/llm/chat_model.py chat_with_tools 251-303
流式工具调用 api/app/core/rag/llm/chat_model.py chat_streamly_with_tools 335-436
错误分类 api/app/core/rag/llm/chat_model.py _classify_error 69-89
CV 模型 api/app/core/rag/llm/cv_model.py QWenCV, AzureGptV4 1-497
音频转录 api/app/core/rag/llm/sequence2txt_model.py QWenSeq2txt, GPTSeq2txt 1-215
Prompt 加载 api/app/core/rag/prompts/template.py load_prompt 9-20
Prompt 生成器 api/app/core/rag/prompts/generator.py message_fit_in 1-744
Agent 封装 api/app/core/agent/langchain_agent.py LangChainAgent 26-641
Agent 消息准备 api/app/core/agent/langchain_agent.py _prepare_messages 230-271
知识检索工具 api/app/services/draft_run_service.py create_knowledge_retrieval_tool 195-263
引用过滤 api/app/services/draft_run_service.py _filter_citations 474-490
聊天服务 api/app/services/app_chat_service.py agnet_chat 43-239
流式聊天 api/app/services/app_chat_service.py agnet_chat_stream 340-550
引用插入 api/app/core/rag/nlp/search.py Dealer.insert_citations 489-577

7. 配置项与可调参数

环境变量

变量 默认值 说明
LLM_TIMEOUT_SECONDS 600 LLM 超时
LLM_MAX_RETRIES 5 最大重试
LLM_BASE_DELAY 2.0 重试基础延迟

知识检索配置

配置项 默认值 说明
retrieve_type participle participle/semantic/hybrid/graph
similarity_threshold 0.2 关键词相似度阈值
vector_similarity_weight 0.3 向量权重
top_k 4 单次检索 chunk 数
reranker_id None Rerank 模型 ID
reranker_top_k 4 Rerank 后最终返回数

Agent 参数

配置项 默认值 说明
max_iterations 5 + len(tools) * 2 Agent 最大迭代
max_tool_consecutive_calls 3 单工具最大连续调用
max_rounds 5 LLM 工具调用最大轮数
temperature 0.7 生成温度
max_tokens 2000 最大生成 token
json_output False 强制 JSON 输出
deep_thinking False 深度思考

8. 边界条件与已知限制

  1. 外部 Rerank 延迟高RedBearRerank 调用 Jina/DashScope API无本地缓存。
  2. Token 裁剪较粗糙message_fit_in 丢弃中间历史,可能丢失上下文;按比例截断可能切断语义。
  3. 引用回填非 LLM 原生:基于 embedding 相似度匹配,表述不同可能漏引。
  4. JSON 输出兼容性差:通过 system prompt 注入实现,可靠性低于原生 response_format
  5. 无模型降级LLM 失败返回错误文本,不自动切换备用模型。
  6. 混合检索融合简单:仅去重取并集,无 RRF 或加权分数融合。
  7. GraphRAG 结果前置:始终 insert(0, ...),优先级最高但无分数参与 rerank。

9. 优化建议与未来扩展点

  1. Rerank 缓存:对高频 query 做 LRU 缓存,降低外部 API 成本。
  2. 引用增强:将 citation_prompt.md 注入 system prompt让 LLM 生成阶段就输出 [ID:N]
  3. Token 预算精细化:引入 tiktoken 精确计数,实现滑动窗口历史管理。
  4. 模型降级:在 Base.chat() 中增加 fallback 模型链。
  5. 混合检索 RRF:在 ES 查询层面实现 Reciprocal Rank Fusion。
  6. 流式引用:在 on_tool_end 事件中实时 emit citation 元数据。
  7. 输出校验中间件:对 json_output=True 增加 JSON Schema 强制校验层。

以上为 [S2-T5] 初版全文,请评审。