当前位置: 首页 > article >正文

用 Spring AI Alibaba 打造智能查询增强引擎

用 Spring AI Alibaba 打造智能查询增强引擎系列导读在上一篇文章《基于 Spring AI Alibaba 构建混合 RAG Agent》中我们描绘了一套融合“侦探的灵活”与“会计的严谨”的架构蓝图。其中查询增强Query Enhancement被置于六大核心步骤之首。很多开发者会有疑问“大模型上下文窗口那么大直接把历史对话丢进去不就行了为什么还要多此一举去改写问题”本文将深入代码一线通过真实的QueryEnhancementHook实现为你揭示没有查询增强的 RAG就像让一个记忆力超群但耳朵背的专家去工作——他记得住所有书却听不清你在问什么。一、为什么“丰富的上下文”救不了检索在 RAG检索增强生成的流程中存在一个致命的时序错位用户提问“它多少钱”依赖上文检索阶段(Retrieval)系统拿着“它多少钱”去向量数据库搜索。失败数据库里没有“它”只有“iPhone 15”。生成阶段(Generation)系统把检索到的可能是错误的文档 完整的历史对话丢给 LLM。LLM 回答LLM 看着历史对话说“哦你刚才问的是 iPhone所以它是 8999 元。”发现问题了吗虽然 LLM 在最后一步通过上下文猜对了答案但检索阶段已经失败了。LLM 是基于“错误检索到的文档”在强行解释或者完全依靠它训练时的内部知识在回答这会导致幻觉且无法利用企业私有知识库。查询增强的核心价值就是在第 2 步检索发生之前把“它多少钱”改写成“iPhone 15 Pro Max 最新价格是多少”。只有问题清晰了检索才能精准只有检索精准了RAG 才有意义。二、代码实战Spring AI Alibaba 中的QueryEnhancementHook基于 Spring AI Alibaba 强大的AgentHook机制我们可以轻松在 Agent 执行前拦截请求完成“翻译”工作。以下是我们生产环境中的核心实现。1. Hook 的定义与入口我们定义了一个QueryEnhancementHook它继承自AgentHook并标注HookPositions({HookPosition.BEFORE_AGENT})确保它在任何工具调用或检索发生之前执行。Slf4jRequiredArgsConstructorHookPositions({HookPosition.BEFORE_AGENT})publicclassQueryEnhancementHookextendsAgentHook{privatefinalChatClientchatClient;// 用于执行重写的小模型OverridepublicStringgetName(){returnquery_enhancement;}OverridepublicCompletableFutureMapString,ObjectbeforeAgent(OverAllStatestate,RunnableConfigconfig){// ... 核心逻辑见下文拆解}}2. 核心三步走策略在beforeAgent方法中我们并没有盲目地调用大模型而是执行了严密的三步走策略第一步精准提取“当前意图”用户的消息列表里可能包含多轮对话我们需要锁定最后一条用户消息。// 提取历史消息ListMessagemessages(ListMessage)state.value(messages).orElse(List.of());// 【关键】获取最后一个有效的用户查询StringoriginalQuerymessages.stream().filter(msg-msginstanceofUserMessage).map(msg-((UserMessage)msg).getText()).reduce((first,second)-second)// 取最后一条.orElse();if(originalQuery.trim().isEmpty()){returnCompletableFuture.completedFuture(Map.of());// 无内容则跳过}第二步注入“长期记忆” (User Profile)这是本架构的亮点之一。传统的查询重写只依赖短期对话历史而忽略了用户是谁。我们通过config.store()加载用户的长期画像如职位、偏好、过往关注点。用户画像更新以及持久化应该在每次与LLM交互后进行后面会有详细介绍。// 加载长期记忆用户档案 偏好StringuserContextloadUserContext(config);// loadUserContext 内部逻辑// 1. 从 Store 获取 user_profiles/{userId}_profile// 2. 获取 user_profiles/{userId}_preferences// 3. 格式化为 prompt 的一部分例如// 【用户档案】// - 职位: 高级Java架构师// - 偏好: 喜欢简洁的代码示例不喜欢长篇理论场景举例用户问“推荐个方案。”无画像重写为“推荐一个技术方案。”太泛有画像重写为“为高级Java架构师推荐一个高并发微服务架构方案要求简洁的代码示例。”精准命中知识库第三步LLM 智能重写 (The Magic)构造一个精心设计的 Prompt调用chatClient进行重写。这里我们采用了降级策略如果 LLM 挂了直接返回原查询保证系统可用性。privateStringenhanceQueryLogic(StringcurrentQuery,ListMessagehistory,StringuserContext){// 构建对话历史上下文StringconversationHistoryhistory.stream().map(m-m.getMessageType(): m.getText()).collect(Collectors.joining(\n));// 动态指令长文本压缩 vs 短文本补全StringinstructioncurrentQuery.length()500?用户输入过长请压缩至 500 字以内保留关键实体消除歧义。:结合【对话历史】和【用户背景】消除指代歧义如它补充隐含主语使查询成为独立完整的陈述句。;StringpromptTextString.format( ### 角色 你是一个专业的查询重写专家。 ### 用户背景来自长期记忆 %s ### 对话历史短期记忆 %s ### 当前用户输入 %s ### 任务指令 %s ### 输出要求 1. 仅输出重写后的查询文本不要任何解释。 2. 必须利用【用户背景】补全缺失的主语或偏好。 3. 必须保留所有具体参数日期、ID、版本。 4. 如果原句已清晰则原样输出。 ### 重写后的查询 ,userContext,conversationHistory,currentQuery,instruction);try{// 调用 LLM 执行重写StringresultchatClient.prompt().user(promptText).call().content();returnresult!null?result.trim():currentQuery;}catch(Exceptione){log.warn(LLM 查询增强失败降级使用原始查询,e);returncurrentQuery;// 故障安全}}这里会从短期记忆中加载对话历史并注入上下文长对话可能超过 LLM 的上下文窗口。常见的解决方案包括修剪消息。在调用 LLM 之前移除前 N 条或后 N 条消息删除消息。从 Graph 状态中永久删除消息总结消息。总结历史中较早的消息并用摘要替换它们【推荐】自定义策略。自定义策略例如消息过滤等这允许 Agent 在 reasoning-acting 循环中持续跟踪对话而不超过 LLM 的上下文窗口。后面会介绍我的实现。3. 状态更新无缝替换一旦获得增强后的查询我们不是把它放在一边而是直接替换state中的消息列表。这样后续的 RAG 节点、Tool Router 拿到的就是已经“翻译”好的完美问题无需任何额外适配。if(!enhancedQuery.equals(originalQuery)){log.info(查询已增强[{}] - [{}],originalQuery,enhancedQuery);// 构建新消息列表仅替换最后一条 UserMessageListMessageenhancedMessagesnewArrayList(messages);intlastUserIndexfindLastUserMessageIndex(messages);// 辅助方法倒序查找if(lastUserIndex!-1){enhancedMessages.set(lastUserIndex,newUserMessage(enhancedQuery));}// 返回修改后的 stateSpring AI 会自动应用returnCompletableFuture.completedFuture(Map.of(messages,enhancedMessages));}三、效果对比有无增强的天壤之别让我们看两个真实场景的对比感受查询增强的威力。场景 A多轮对话中的指代消解步骤用户行为无增强 (传统 RAG)有增强(混合 RAG)Round 1用户“2026年的病假流程是什么”检索“2026年病假流程” ✅ 成功检索“2026年病假流程” ✅ 成功Round 2用户“那事假呢”检索“那事假呢” ❌失败(向量库无此句) 结果胡乱匹配或返回空重写“2026年的事假申请流程是什么” ✅成功(精准命中)Round 3用户“需要审批吗”检索“需要审批吗” ❌失败(不知道指哪个流程)重写“2026年事假申请流程需要审批吗” ✅成功(上下文完整)场景 B个性化偏好注入维度无增强有增强用户画像(系统未知)职位运维工程师偏好只要 Shell 脚本不要 Python用户提问“怎么重启服务”“怎么重启服务”重写结果“怎么重启服务”“Linux 环境下重启服务的Shell 脚本命令是什么”检索结果混杂了 Java、Python、Windows 的通用教程精准命中Linux Shell 相关文档最终体验用户需要二次追问“我要 Shell 版的”一次命中用户感觉 AI“懂我”四、避坑指南与最佳实践在实现过程中我们也踩过一些坑总结以下几点供参考不要过度重写如果用户的问题已经很清晰如“什么是 Spring Boot”LLM 可能会画蛇添足。对策在 Prompt 中明确强调“如果当前输入已经非常清晰且无指代则原样输出”。性能与成本的平衡查询增强需要额外调用一次 LLM。对策使用小模型如 Qwen-Turbo 或本地部署的 7B 模型专门做重写速度快、成本低。配合语义缓存本系列下一篇重点高频问题直接缓存根本不需要触发重写和检索。容错设计LLM 可能会超时或报错。对策务必像代码中那样做try-catch降级。增强是“锦上添花”不能因为增强失败导致整个对话不可用。Fail-fast, fallback to original.五、结语查询增强Query Enhancement绝不是多余的步骤它是连接人类模糊语言与机器精准检索的唯一桥梁。通过 Spring AI Alibaba 的AgentHook我们不仅实现了指代消解更将长期用户画像融入到了检索的源头。这使得我们的 RAG 系统不再是一个冷冰冰的搜索引擎而是一个能听懂“弦外之音”、记得住“老客喜好”的智能助手。下一步预告问题清楚了检索也精准了但如果每次都要重新查一遍速度够快吗下一篇我们将深入语义缓存Semantic Cache的实现揭秘如何让高频问题实现“毫秒级”响应进一步降低 Token 成本

相关文章:

用 Spring AI Alibaba 打造智能查询增强引擎

用 Spring AI Alibaba 打造智能查询增强引擎 系列导读:在上一篇文章《基于 Spring AI Alibaba 构建混合 RAG Agent》中,我们描绘了一套融合“侦探的灵活”与“会计的严谨”的架构蓝图。其中,查询增强(Query Enhancement&#xff0…...

【OpenClaw 全面解析:从零到精通】第 011 篇:OpenClaw 多模型支持与接入配置:OpenAI、Claude、国产大模型全指南

系列说明:本系列共计 20 篇,全面介绍 OpenClaw 开源 AI 智能体框架,从历史背景到核心原理,从安装部署到应用生态。本文为系列第 011 篇,聚焦于 OpenClaw 的多模型接入配置体系,详解如何灵活接入并管理各类大…...

阿里云代理商:阿里云无影云电脑部署 OpenClaw 接入钉钉机器人全攻略

在数智化办公时代,将 AI 助手与办公工具深度集成已成为企业提效的关键。阿里云无影云电脑支持 OpenClaw 部署后,接入钉钉机器人可实现智能问答、任务处理等自动化场景。以下为详细接入指南,助您一步到位!一、准备工作阿里云无影云…...

北大数字普惠金融指数省市县2011-2024面板数据

北大数字普惠金融指数简介北大数字普惠金融指数由北京大学数字金融研究中心编制,旨在衡量中国各地区数字普惠金融发展水平。该指数覆盖省、市、县三级行政区,时间跨度为2011年至2024年,包含总指数及多个分维度指标(如覆盖广度、使…...

TikTok如何变现?2026主流变现方式全解析(从0到1)

TikTok已经成为全球最大的短视频平台之一,拥有超过15亿月活用户。对于个人、团队或商家来说,是一个重要的流量入口与变现场景。很多人卡在“有流量但不会变现”,或者“不知道从哪里开始”。这篇文章将从实际路径出发,梳理当前主流…...

AxureRP11实例-手机号提交验证交互功能JH110002

实例说明:这里提示一下,教程里的每个交互都是区别提示,实际可以放在一个条件下判定。根据自己的需求来调整即可。实例原理:对于 国内手机号的验证有以下几个条件:1、纯数字判定2、11位字符长度判定(已包含空…...

【收藏】网络安全接单渠道大揭秘:从零开始的项目获取指南

【收藏】网络安全接单渠道大揭秘:从零开始的项目获取指南 网络安全接单渠道包括:漏洞赏金平台(如补天、漏洞盒子)可获高奖金并积累声誉;IT兼职平台(如程序员客栈)提供担保保障;安全社区投稿可获稿费并吸引客户;CTF竞赛…...

ChatGPT开发实战:从API调用到生产级应用的最佳实践

ChatGPT开发实战:从API调用到生产级应用的最佳实践 最近在做一个需要集成智能对话能力的项目,直接调用ChatGPT的API时,遇到了不少“坑”。从简单的对话Demo到稳定可靠的生产级应用,中间需要跨越的鸿沟比想象中要大。今天就来分享…...

【深度解析】映翰通5G CPE02:赋能企业分支联网,打造高效灵活的分布式办公网络

为什么这款5G CPE正在成为连锁门店、分支机构和分布式团队的网络首选? 引言:分布式办公时代的网络挑战 在数字化转型加速的今天,企业组织形态正从集中式向分布式演进。连锁门店、分支机构、远程团队等分布式架构成为常态,但传统的…...

Chatbot界面开发实战:如何高效设置中文按钮名称

在开发面向中文用户的Chatbot界面时,按钮名称的设置看似简单,却常常成为项目后期维护的“阿喀琉斯之踵”。你是否也遇到过这样的场景:产品经理临时要求将“提交”按钮改为“确认提交”,或者为了A/B测试需要快速切换不同的按钮文案…...

靠谱的液体颗粒计数器选哪个型号

普洛帝(PULUODY)液体颗粒计数器在工业领域以高精度和可靠性著称,核心技术和传感器(如第八代双激光窄光检测器)是其品质的保证。选择哪款型号,主要取决于您的具体应用场景和预算。以下是几款主流型号的对比分…...

导师要“综”更要“述”?百考通AI不仅梳理文献,更提炼观点、指出争议

在高校学术写作中,文献综述是连接已有研究与创新探索的关键桥梁。它不仅体现作者对领域现状的掌握程度,更直接影响后续研究的深度与可行性。然而,对许多学生而言,撰写一篇专业、规范、有逻辑的综述常常令人望而却步——资料庞杂、…...

STP 生成树协议课程课后总结

今天的《STP 生成树协议》课程已圆满结束,课程承接此前以太网交换、VLAN 技术的二层知识体系,围绕二层环路的成因与危害、STP 协议的核心概念、工作原理、选举机制与工程化配置展开全面系统的讲解。通过本次学习,我彻底理解了二层冗余组网中环…...

我用 OpenClaw 做了一个“自动运维助手”,效率直接翻倍

最近在折腾 AI Agent 自动化运维,试了不少方案,最终稳定用下来的反而是一个比较冷门的组合:OpenClaw GMSSHGM Claw。 简单说一下我的使用场景: 每天自动巡检服务器状态 自动分析日志异常 定时推送报告到企业微信 一、为什么选…...

高效洽谈订单:用3分钟时间说清楚产品如何帮助工厂节省人工

高效洽谈订单:用3分钟时间说清楚产品如何帮助工厂节省人工制造业的客户并不会关心你的产品有多么先进,他们只关心一件事情:能不能帮助他们减少雇佣人数、减少加班时间、减少需要操心的事情。如果销售人员能够在3分钟之内清晰地计算出“能够节…...

受Cloudflare限制的可能原因和解决方法

在进行数据收集等网络活动时,有时会碰到Cloudflare的限制,导致网络活动无法正常进行。了解遭遇Cloudflare限制的原因、解决方案和预防方法,更好地应对限制。一、受到Cloudflare限制的可能原因1.IP问题Cloudflare会看访问者的IP及其相关指标情…...

非标零件销售难拓客?天下工厂精准定位机加工、模具厂老板!

从事非标零件销售工作,像定制轴套、异形支架、治具夹具、精密结构件这些产品,遇到的最大困难从来都不是加工能力存在问题,而是没办法找到那些真正有需求、有产能并且能够做决策的客户。你在1688上发出询盘,回复你的却是贸易商&…...

GPT-5.4降价血战:mini当老大,nano做小弟,独立开发者的省钱攻略

GPT-5.4 mini 价格降了不少,GPT-5.4 nano 更像便宜好使的打杂小弟。我是这样安排的:mini 当主力,nano 打配合。 为什么我偏 mini OpenAI 官方把 mini 定位成最强 mini 模型,主打 coding、computer use 和 subagents,而…...

Linux系统基础安全2

声明:本文中所有操作均在合法合规的靶场环境、虚拟环境中进行。任何个人和组织不得从事非法侵入他人网络、干扰他人网络正常功能、窃取网络数据等危害网络安全的活动;不得提供专门用于从事侵入网络、干扰网络正常功能及防护措施、窃取网络数据等危害网络…...

YouTube视频翻译全攻略:自动字幕、手动翻译到AI配音实战指南

YouTube 作为全球领先的视频平台,月活跃用户已超过 27 亿(2025 年数据)。这一庞大的受众群体为内容创作者提供了触达世界各地观众的绝佳机遇。然而,语言障碍往往限制了内容的传播潜力,使得优质内容难以被更广泛的观众访…...

导师严选!全网爆红的降AIGC软件 —— 千笔·降AI率助手

在AI技术快速发展的今天,越来越多的学生和研究者开始依赖AI工具来提升论文写作效率。然而,随着学术审查标准的不断升级,AI生成内容的痕迹越来越容易被检测出来,导致论文面临“AI率超标”的风险。面对这一挑战,许多人在…...

通过LangChain Agent模拟实现美团外卖下单场景

这是一个极具代表性的 LangChain Agent 实战场景:将用户的自然语言语音指令,通过智能代理(Agent)自动分解为多个工具调用,最终完成美团外卖下单这一复杂现实任务。下面我将为你提供一个 端到端、可落地、安全合规 的完…...

PHP什么是接口幂等性,有哪些实现方式?

“接口幂等性” (Idempotency),常被误解为“防止重复提交”或“加个锁就行了”。 但本质上,它是分布式系统中保证数据一致性的基石,是对“同一操作执行多次与执行一次效果完全相同”这一数学特性的工程化实现。 在 PHP 这种无状态、常配合消息…...

mysql 索引失效场景的庖丁解牛

"MySQL 索引失效”,常被误解为“建了索引没用”或“数据库抽风了”。 但本质上,它是优化器在“使用索引(随机 I/O)”与“全表扫描(顺序 I/O)”之间,经过成本估算后做出的“理性放弃”&…...

MySQL的limit 10 和 limit 1000000 的区别的庖丁解牛

“LIMIT 10"和"LIMIT 1000000, 10”,常被误解为“只是取的数据位置不同”或“无非是多扫描几行”。 但本质上,它们是两种截然不同的 I/O 消耗模型: LIMIT 10 是**“浅层扫描”**,是数据库最喜欢的操作,几乎零…...

mysql 回表、索引覆盖、索引下推的庖丁解牛

这三个概念常被误解为“晦涩的底层术语”或“只有 DBA 才需要关心的细节”。 但本质上,它们是MySQL 优化器在“减少磁盘 I/O"和“减少 CPU 计算”这两大核心目标上,进化出的三种生存智慧。 回表 (Table Lookup):是代价,是不得…...

Spring AOP 进阶:揭秘 @annotation 参数绑定的底层逻辑

Spring AOP 进阶:揭秘 annotation 参数绑定的底层逻辑 在使用 Spring AOP 开发自定义注解(如 RateLimit)时,我们经常会看到这样一种“神奇”的写法: Around("annotation(rateLimit)") public Object checkLi…...

用 autoresearch 优化万物

Karpathy的推文在一个周五晚上发布。一个链接,一条损失曲线向下复合的截图,一句话:代理在你睡觉时做实验。 我在十分钟内读完了README。然后我又读了一遍。不是因为代码复杂——它特意只有630行。我再读一遍是因为代码不是重点。 要点在于约…...

2026怎么选猫粮?实测揭秘世界十大顶级猫粮品牌希喂怎么样

换粮对于养猫的朋友来说,是最大的一个大难题。每次挑猫粮的时候,都小心翼翼的,生怕选错了,误选到毒猫粮;可是不换粮,有会因为摄入的营养过于单一导致营养不良。2026怎么选猫粮?这几年&#xff0…...

LA04-Abaqus嵌合体退火仿真案例教程:完全热力耦合分析的实践与解析

LA04-Abaqus嵌合体退火热力耦合仿真案例教程 在Abaqus中创建304钢-铜缝-304钢焊接的2D平板模型,赋予密度、弹性参数、热导率、比热容和线膨胀系数后,给定梯度变化温度载荷曲线,对装配体进行退火模拟的完全热力耦合分析,输出温度场…...