Browse Source

fix(app): 修复切换会话后用户提问被查询重写结果覆盖

RAG 查询重写(REWRITE 等策略)的润色产物被当作用户消息落库到
chat_message 会话记忆表,导致 ChatSDK 切换角色/对话后前端拉取
历史显示的是润色版而非原始提问。

ChatPipeline 在 RAG 分支将 finalMessage 由 rag.rewrittenQuery()
改为 ctx.message(),使查询重写仅服务于检索,用户消息(传给模型、
落库、前端展示)统一为原始提问。
Spring-AI-1.1.2
wanghanlin 3 weeks ago
parent
commit
081758128c
  1. 6
      src/main/java/com/wok/supportbot/app/ChatPipeline.java
  2. 2
      src/main/java/com/wok/supportbot/app/ChatRequest.java
  3. 4
      src/main/java/com/wok/supportbot/rag/RagContext.java

6
src/main/java/com/wok/supportbot/app/ChatPipeline.java

@ -66,7 +66,7 @@ public class ChatPipeline {
* <li>未启用 RAG普通对话 / 严格隔离下 KB 拒绝 用原始 message基础 system</li> * <li>未启用 RAG普通对话 / 严格隔离下 KB 拒绝 用原始 message基础 system</li>
* <li>寒暄/闲聊IntentRouter 或寒暄词命中 同上跳过 KB 检索</li> * <li>寒暄/闲聊IntentRouter 或寒暄词命中 同上跳过 KB 检索</li>
* <li>FAQ 命中 直接返回标准答案不调用 ChatClient</li> * <li>FAQ 命中 直接返回标准答案不调用 ChatClient</li>
* <li>RAG 生成 资料块注入 system重写后查询作为 user 消息</li>
* <li>RAG 生成 资料块注入 system原始 message 作为 user 消息重写查询仅用于检索</li>
* </ul> * </ul>
* *
* @param ctx 对话上下文 * @param ctx 对话上下文
@ -128,9 +128,9 @@ public class ChatPipeline {
globalPrompt, null, null, "FAQ", null, null, rag.faqMatchResult()); globalPrompt, null, null, "FAQ", null, null, rag.faqMatchResult());
} }
// RAG 生成资料块注入 system重写后查询作为 user 消息
// RAG 生成资料块注入 system原始 message 作为 user 消息重写查询仅用于检索
String finalSystem = baseSystem + ragPipeline.buildRagContextBlock(rag.contextText()); String finalSystem = baseSystem + ragPipeline.buildRagContextBlock(rag.contextText());
return new ChatRequest(ctx, rag.rewrittenQuery(), finalSystem, Optional.empty(),
return new ChatRequest(ctx, ctx.message(), finalSystem, Optional.empty(),
globalPrompt, rag.contextText(), rag.documents() != null ? rag.documents().size() : 0, "RAG", globalPrompt, rag.contextText(), rag.documents() != null ? rag.documents().size() : 0, "RAG",
rag.searchMode(), rag.documents(), null); rag.searchMode(), rag.documents(), null);
} }

2
src/main/java/com/wok/supportbot/app/ChatRequest.java

@ -15,7 +15,7 @@ import java.util.Optional;
* 字段含义 * 字段含义
* <ul> * <ul>
* <li>{@link #faqAnswer()}FAQ 命中时直接返回标准答案跳过 ChatClient 调用</li> * <li>{@link #faqAnswer()}FAQ 命中时直接返回标准答案跳过 ChatClient 调用</li>
* <li>{@link #finalMessage()}传给模型的用户消息RAG 场景为重写后的查询否则为原始 message</li>
* <li>{@link #finalMessage()}传给模型的用户消息始终为原始 message查询重写仅用于检索</li>
* <li>{@link #finalSystemPrompt()}传给模型的系统提示词角色人设 + RAG 资料块可为空</li> * <li>{@link #finalSystemPrompt()}传给模型的系统提示词角色人设 + RAG 资料块可为空</li>
* <li>{@link #globalPrompt()}全局提示词快照来自 system_config.ai_system_prompt可为空</li> * <li>{@link #globalPrompt()}全局提示词快照来自 system_config.ai_system_prompt可为空</li>
* <li>{@link #ragContextText()}RAG 资料块文本未注入时为空/null</li> * <li>{@link #ragContextText()}RAG 资料块文本未注入时为空/null</li>

4
src/main/java/com/wok/supportbot/rag/RagContext.java

@ -13,13 +13,13 @@ import java.util.Optional;
* <ul> * <ul>
* <li>{@link #faqAnswer()} 命中 直接返回标准答案跳过生成</li> * <li>{@link #faqAnswer()} 命中 直接返回标准答案跳过生成</li>
* <li>未命中 {@link #documents()} 展示引用来源 {@link #contextText()} 注入系统提示词 * <li>未命中 {@link #documents()} 展示引用来源 {@link #contextText()} 注入系统提示词
* {@link #rewrittenQuery()} 作为传给模型的用户消息</li>
* {@link #rewrittenQuery()} 仅用于检索作为传给模型的用户消息</li>
* </ul> * </ul>
* *
* @param faqAnswer FAQ 命中的标准答案未命中为 {@link Optional#empty()} * @param faqAnswer FAQ 命中的标准答案未命中为 {@link Optional#empty()}
* @param documents 检索命中的知识库片段 metadata可为空 * @param documents 检索命中的知识库片段 metadata可为空
* @param contextText 拼接后的资料文本 {@code "\n\n---\n\n"} 分隔无资料时为空串 * @param contextText 拼接后的资料文本 {@code "\n\n---\n\n"} 分隔无资料时为空串
* @param rewrittenQuery 传给模型的用户消息MULTI_QUERY 为原始 message其余策略为重写后的查询
* @param rewrittenQuery 检索用的改写查询MULTI_QUERY 为原始 message其余策略为重写后的查询仅用于检索不作为用户消息
* @param searchMode 真实检索模式VECTOR / KEYWORD / HYBRID当前主管道固定为 VECTOR * @param searchMode 真实检索模式VECTOR / KEYWORD / HYBRID当前主管道固定为 VECTOR
* @param faqMatchResult FAQ 命中详情 matchType/score未命中为 null * @param faqMatchResult FAQ 命中详情 matchType/score未命中为 null
*/ */

Loading…
Cancel
Save