☰
Java工程师的电商LLM应用开发实战:从工具调用到生产落地
2026/10/19 9:53:18 网站建设 项目流程

做电商后端开发的Java工程师,最近这半年几乎所有的业余时间都搭进去了,核心就一件事:把大语言模型真正接进业务场景里。准确说,这是一次完整的LLM开发实践——不是搭个Demo聊天机器人,而是把大模型能力嵌进商品导购、客服应答、售后工单这些真实链路,让它能调用我们现有的交易、库存、优惠券系统,替用户解决实际问题。

这篇文章适合两类人看:一类是在Java技术栈里写业务代码、想切入LLM应用的工程师,另一类是已经在做AI应用、但被“模型输出不稳定”“上下文爆炸”“生产环境没人敢接”这些问题折磨过的朋友。我不会去讲那些到处都能搜到的基础概念,只聊我踩过的坑、验证过的方式,以及为什么在电商这种高并发、强一致、处处是规则的场景里,LLM应用开发和外面看到的“Prompt调优”完全不是一回事。

1. 先说清楚:电商业务里LLM到底解决什么问题

1.1 那些看起来智能、实际上很脆弱的客服机器人

很多电商平台早就有客服机器人,但用户的实际体验大家都懂:你问“我前几天买的那个蓝色的杯子怎么还没发货”,老式机器人先做分词,命中“发货”关键词,然后把物流模板甩给你。至于“蓝色杯子是哪一单”“为什么发这么慢”“要不要我自己去找快递”,它完全帮不上忙。

这里面的核心矛盾在于:传统规则系统把用户意图拆成“关键词+模板”,但在真实对话里,用户表达是模糊的、多轮依赖的、充满指代和省略的。而LLM的价值恰恰体现在这里——它能理解“那单”“这个”“红色的那款”指代的是什么,能把“还没发货”拆成“查询订单物流状态”这个明确动作。但注意,它只是“理解”,真正去查订单、查物流、催发货,必须由我们自己的系统完成。

这就是我理解的电商LLM实践的第一性原则:LLM不是来替代搜索和规则的,而是来当“调度中枢”的。理解用户意图、拆解多轮需求、生成自然回复,这些事情交给模型;查库存、算优惠、改地址、提单,这些确定性动作必须走原有系统。

1.2 我不是来“搞个AI”,我是来降本提效的

聊技术之前,先泼一盆冷水。老板让你搞LLM,通常不是因为“别人都有所以我们也要”,而是因为两个KPI:人工客服成本下降,以及用户问题解决率上升。

在这两个指标倒逼下,我总结出电商场景里LLM最适合先切入的三块业务:

  • 售前导购:用户带着模糊需求进来,比如“送女朋友生日礼物,预算500左右”,系统通过多轮对话拆解出品类、价位、品牌偏好,再推荐商品。这个场景里,自然语言交互比搜索框高好几个量级。
  • 售中订单服务:查物流、改地址、催发货、开发票。需求高频、规则明确,适合交给LLM驱动工具调用完成。
  • 售后工单处理:用户投诉“衣服有异味”,系统自动归类、判断严重程度、推荐处理方案,客服只需要确认即可。这个场景能直接省掉大量人工分类时间。

这三个场景有一个共同特征:用户意图可以被结构化成“动作+参数”,而不是开放式生成。也就是说,模型的核心任务不是“创造”,而是“理解+拆分+调度”,这正是Java工程师最擅长的领域——把复杂流程编排成确定性的服务调用。

2. 技术选型:为什么是Java,为什么是LangChain4j

2.1 Java生态做LLM应用并没有想象中别扭

刚开始团队里也吵过:做LLM应用不应该用Python吗?LangChain最成熟的版本就是Python的,生态丰富,案例多,社区讨论也大部分是Python。

但冷静下来想,我们是电商Java团队,整个技术栈是Spring Cloud、Dubbo、RocketMQ、MyBatis这一套。如果引入Python微服务作为AI入口,意味着两条技术线之间要维护RPC通信、鉴权、链路追踪、监控告警,还要会两套语言的开发和运维。最要命的还是工程协作问题:AI侧的同学改了Prompt、换了模型,Java侧就得跟着改接口,两边节奏完全对不上。

Java生态做LLM真正的优势不是“AI能力强”,而是工程复用。限流、熔断、降级、灰度发布、日志链路、配置中心,这些沉淀了多年的能力都能直接用在AI调用链路上。说白了,LLM只是我们的一个外部依赖,和调用数据库、调用缓存没有本质区别,只是它更“笨”也更“贵”一些。

2.2 框架选型对比:LangChain4j、Spring AI Alibaba还是自研

市面上Java领域的LLM编排框架,我实际用下来比较成熟的有三个方向。用一个表格就能看明白它们的位置:

框架核心特点适合谁
LangChain4j偏底层抽象,支持向量存储、工具调用、流式输出,和Spring Boot集成不错项目组懂Java、愿意读源码,需要高度定制编排逻辑
Spring AI Alibaba背靠Spring生态,提供Spring风格API,对AI Gateway、通义系列模型适配好本身就是Spring Cloud技术栈,希望快速接入模型和工具
自研封装直接调HTTP接口,自己管理Prompt、上下文、工具路由场景少而明确,不想被框架绑架,团队有较强的LLM认知

我们最后选了LangChain4j + Spring Boot的组合,原因是它的AiServices把“模型、工具、记忆、检索”这些东西组合得非常干净,而且不强迫你使用它的全套组件——我只用到了它的模型接入、工具调用、流式输出,其余都是自己封装。

这里有个选型心得:不要因为框架“功能多”就全盘引入。LLM应用的业务编排逻辑和传统CRUD差别很大,框架给的默认行为往往不符合你的真实场景。比如默认的对话记忆策略、默认的向量检索参数,都需要根据电商场景重新调。选框架的核心是选“能让你方便地改掉默认行为”的框架,而不是选“什么都能干”的框架。

2.3 模型和Embedding选型的取舍

模型选型我分两层看。

第一层是“主力对话模型”。电商场景高并发、大调用量,单次推理成本必须精打细算。我们采用分级模型策略:日常导购这类开放式对话,用综合能力均衡的国产商用模型;涉及订单查询、物流跟踪这种需要严格工具调用的场景,用指令遵循更强、JSON输出更稳的模型;到了大促高峰,还会自动降级到更轻量的小参数量模型,保证可用性优先。

第二层是“Embedding模型”。做RAG必用的文本向量化模型,我们选的是国产开源的双语Embedding模型。选它的核心原因是中文场景表现好,对电商商品标题、用户口语化提问的语义捕捉能力强,而且支持本地化部署,不产生按量计费成本。

关于模型选型有个经验之谈:不要只看模型排行榜,一定要拿自己的典型Case集去测。比如我们的场景里有大量口语化表达:“有没有那种上班穿的,显得正式点的”“不要黑色的”“有没有和这个差不多的”……排行榜上的高分模型在这些场景未必比腰部模型好。真金白银的评测比任何榜单都可靠。

3. 核心架构设计:把LLM当成编排中心,而不是大脑

3.1 工具调用是实现业务闭环的关键

电商场景里聊LLM,绕不开一个本质问题:模型再怎么聪明,它也不知道用户的订单在数据库哪一行,不知道今天哪个仓库有货。所以,模型的定位必须从“所有答案的提供者”变成“调度员”——它负责理解用户说什么,然后把任务拆解成一个或多个“工具调用”,从我们的系统里拿真实数据,再组织语言回复用户。

整个链路的核心是Function Calling(工具调用)。比如用户说“帮我取消明天到期的那个预约安装单”,模型先识别意图是“取消预约单”,提取参数“订单时间:明天到期”,然后调用cancelServiceOrder(orderId, reason)这个工具,由我们的系统完成真正的取消操作,再把结果生成给用户。

这里要特别强调一个边界:模型只能决定调用哪个工具、传什么参数,不能直接执行动作。取消订单、修改地址这些操作,必须经过我们原有系统的校验规则——订单状态是否允许取消、是否过了可修改时限,这些判断永远由系统代码完成,模型只能把参数解析出来。

3.2 RAG解决“模型不知道”的问题

电商客服场景里有一个高频需求:用户问“你们家支持7天无理由退货吗?”“这个能开发票吗?”。这类问题的答案不是模型凭空生成的,而是来自我们自己的售后政策、商品页面说明。如果用纯Prompt硬压给模型,效果很差,因为政策条款长、细节多,且经常随活动变化。

我们的方案是RAG。核心流程:

  1. 把售后政策、商品FAQ、活动规则等文档切片,离线生成Embedding存入向量库。
  2. 用户提问时,先用Embedding检索出最相关的3~5个片段。
  3. 把这些片段组装进Prompt,让模型基于“参考材料”回答。

这里最容易被低估的是切分策略。刚开始我只是按固定长度切文档,结果切出来的片段经常把一条完整规则从中间截断,导致模型回答丢条件。后来改成按语义边界切分,每条政策条款独立成片,检索准确率明显提升。另外,不同来源的文档要打上不同的元数据标签(如“售后政策”“活动规则”“商品页说明”),这样可以在检索时做条件过滤,比如只搜售后政策不搜商品页。

3.3 请求链路全貌

把上面的思路串在一起,我们生产环境的请求链路长这样:

  • 用户发消息,通过网关进入Agent服务。
  • Agent服务先做基础过滤(风控、敏感词、路由判断),决定走规则引擎还是LLM链路。
  • 进入LLM链路后,加载会话记忆、检索RAG参考片段,组装Prompt。
  • 模型经过推理输出“意图判断+工具调用列表+回复需要的摘要信息”。
  • Agent服务解析模型输出,逐条调用注册好的业务工具,拿到结果后拼装最终答案。
  • 答案返回到客户端前,还要过一层内容合规过滤和敏感信息脱敏。

这个链路看起来长,但只要每一跳设计得清楚,延迟是可以压到可接受范围的。真正容易出问题的,恰恰是链路里那些“模型输出不符合预期”的环节,我在第5章会展开讲。

3.4 记忆管理:不要什么都往Prompt里塞

多轮对话让LLM“记住”上下文,最简单的做法是把所有历史消息都塞进Prompt。但电商场景对话动辄十几轮,中间还穿插着商品卡片、价格计算等结构化数据,全塞进去会撑爆上下文窗口,还会让模型注意力涣散。

我们最后用的是“结构化记忆 + 滚动窗口”的组合:

  • 结构化记忆:把用户的历史关键信息(偏好类目、预算区间、排除的品牌)抽成一组键值对,每次对话前注入。
  • 滚动窗口:只保留最近N轮原始对话,更早的内容不再进Prompt,如果需要可以检索历史摘要。
  • 业务上下文:当前正在浏览的商品、当前购物车内容,通过业务接口实时取,而不是从历史里翻。

这套组合的记忆策略下来,模型输出的稳定性和一致性好了很多,token成本也降下来了。记忆管理本质上是在“让模型知道足够多”和“别让它被噪声干扰”之间找平衡点。

4. 从0到1落地一个导购Agent的实操拆解

4.1 定义场景边界:导购能做什么、不能做什么

动手写代码之前,我们花了整整两天梳理场景边界。导购Agent要接得住这样一句话:

“我想给老爸买个生日礼物,他平时喜欢钓鱼,预算两三百吧。”

但同时,这个Agent绝对不能做这些事:

  • 不能替用户直接下单支付,必须跳转人工确认。
  • 不能承诺库存数量,只能说“当前有货/无货”,因为库存实时变动。
  • 不能凭空捏造优惠信息,所有优惠计算必须走优惠服务。
  • 不能讨论超出导购范围的话题,比如问“你觉得我该不该辞职钓鱼”。

边界梳理这段看起来不性感,但它是整个项目里最值钱的部分。边界定义不清楚,后面调Prompt、调工具都会变成打地鼠——今天压住一个问题,明天又冒出一个新问题。

4.2 把业务能力变成工具

在LangChain4j里,工具就是普通的Java方法加一个注解。我们最早实现的四个工具:

@Tool("根据关键词检索在售商品,返回商品标题、价格、简介") public List<ProductBrief> searchProducts(String keyword) { return productSearchService.search(keyword, 10); } @Tool("查询商品实时库存状态,返回是否有货") public StockStatus queryStock(Long skuId) { return stockService.queryAvailable(skuId); } @Tool("根据商品列表和用户选择的优惠券,计算最优优惠组合后的总价") public PriceResult calcPrice(List<Long> skuIds, String couponCode) { return priceService.calculateBestPrice(skuIds, couponCode); } @Tool("把当前会话转接给人工客服") public String transferToHuman(String reason) { return conversationService.transfer(reason); }

这里有一个特别值得说的细节:工具的“描述”写得越具体、越像人话,模型的工具选择准确率越高。我一开始写的描述是“商品搜索”,模型经常在用户问“有没有红色的”时不去调用它,后来改成“根据用户描述的商品特征或关键词,在商品库中检索匹配的在售商品列表,支持颜色、品牌、品类等描述”,准确率立刻上来了。工具描述就是模型的API文档,写得不清楚,调用方当然一脸懵。

4.3 组装Agent的代码骨架

用LangChain4j的AiServices组装服务,核心代码量其实不大:

@Slf4j @Service public class ShoppingAgent { private final AiService assistant; public ShoppingAgent(ChatLanguageModel chatModel, ShoppingTools shoppingTools) { assistant = AiServices.builder(ShoppingAssistant.class) .chatLanguageModel(chatModel) .tools(shoppingTools) .chatMemoryProvider(chatMemoryProvider()) .build(); } public Flux<String> chat(String userId, String userMessage) { return Flux.fromStream(assistant.chat(userId, userMessage)) .onErrorResume(e -> Flux.just(fallbackReply(e))); } public interface ShoppingAssistant { String chat(@MemoryId String userId, @UserMessage String message); } }

这里面@MemoryId是关键:同一个用户的多轮对话,会按这个ID自动关联记忆。onErrorResume是兜底:模型调用失败、工具抛异常、超时,都不能把错误原样甩给用户,必须返回一条安全回复,比如“系统刚刚开小差了,请您稍后重试或转人工客服”。

4.4 提示词工程的电商化改造

网上那些通用Prompt模板搬到电商场景基本都要重写。我们最后打磨出的导购Prompt结构大致是:

  • 角色定义:你是电商平台的专业导购,你的任务是理解用户需求并推荐合适的商品,不是闲聊。
  • 行为约束:只能使用查询工具返回的数据来描述商品;无法确定的信息必须向用户确认,禁止猜测;不得承诺库存和价格。
  • 推荐逻辑:如果用户给出预算,优先在预算范围内推荐;如果用户表达了偏好,优先匹配偏好;推荐时要说明推荐理由。
  • 兜底策略:如果没有搜到合适商品,必须主动询问是否需要放宽条件,不得强行推荐不相关商品。

Prompt写得好不好,不看文采,看它能不能把模型稳定地限制在业务规则里。我们的做法是:每写一版Prompt,就拿几十条真实对话去跑回归,看它对边界Case的处理是否符合预期。不要相信感觉,要相信测试集。

4.5 流式输出提升体验

电商用户等不了5秒钟才看到第一个字。我们把响应改成流式输出,用户侧看到的是打字机式的回复效果,第一屏内容1秒左右就能出现。实现上就是标准SSE(Server-Sent Events),后端把模型的流式输出分量推给前端。

流式输出有个额外的麻烦:如果中间模型要调用工具,比如先检索商品再生成推荐语,那用户看到的可能是“让我看看……”卡住1~2秒。我们的处理方案是,工具调用阶段先给前端推一条“正在为您筛选商品”的状态消息,等工具返回后再继续推流式文本。虽然是小细节,但用户的等待体感差别很大。

5. 生产环境最难的不是模型,是这些坑

5.1 模型输出不是稳定代码,要有解析兜底

Java工程师做AI应用最容易踩的第一个坑就是:把模型输出当成JSON接口响应来解析。模型偶尔会输出多余的回车、Markdown标记、甚至突然开始和你闲聊。我们早期线上就出过一个事故:模型在返回工具参数时多了一段解释性文字,解析器直接报错,用户那边看到的是“系统繁忙”,客服工单瞬间爆掉。

现在我们的做法是三层防御:

  1. 尽量用模型的原生JSON模式输出,约束返回格式为合法JSON,从源头降低乱格式概率。
  2. 解析失败自动重试一次,带上前一轮的提示“请严格只输出JSON,不要包含任何其他文字”。
  3. 如果重试还是失败,走规则兜底,直接返回“没听清您的问题”或者转人工,绝不能让报错暴露给用户。

这里再补一个经验:不要过度相信模型的“输出稳定性评测”。哪怕是同一个模型,同一个Prompt,多跑几次也可能出现不同格式。在设计Prompt的时候,就要假设最坏情况——有一半请求可能不按规矩来。

5.2 上下文长度和token成本的拉锯战

LLM应用有一个绕不开的成本指标:token。一次导购对话,如果上下文管理得不好,几轮聊下来可能就消耗几万token,看起来单次不贵,但乘以日均百万级调用量,账单会让人失眠。

我们把token治理分成三个层面:

  • Prompt瘦身:把固定角色描述压缩到必要信息,去掉一切修饰词。“你是导购”比“你是一个专业、友好、热情的电商购物助手”节省token,效果反而更稳定。
  • 上下文裁剪:上一轮输出的商品列表、价格明细这种结构化数据,如果后续不再需要,就不带入下一轮。
  • 语义缓存:完全相同的用户问题(比如“怎么开发票”),直接命中缓存返回,不重新调模型。实测下来,这类高频问题的缓存命中率能达到30%左右。

这个缓解成本的过程不是一次性完成的,而是每次看监控报表、找到成本大头后一点点抠出来的。刚开始上线一周,token费用高得吓人,但经过两轮裁剪,降幅接近一半。

5.3 大促流量冲击下的稳定性治理

电商业务躲不开大促。大促期间的流量是平时的几倍到几十倍,而模型推理服务和普通Java应用不一样,它不是加个Pod就能无限扩容的。我们做了这么几件事:

  • 限流和排队:Agent服务入口按用户维度限流,同一用户不能同时发起多个LLM请求,超出排队。
  • 分级降级:大促当天把高成本大模型降级为轻量模型,导购场景可以牺牲一点回答质量,但不能让整个链路瘫痪。
  • 高频问题走规则:比如查物流、退换货政策这类高频且答案明确的请求,直接命中原有的规则引擎,不进LLM链路。
  • 熔断恢复:模型服务持续超时后自动熔断,后续流量全部降级到人工客服或者固定话术,等模型服务恢复后再渐进放量。

大促压测时我们专门做过演练:模型服务模拟故障5分钟,Agent服务在降级链路下要保证核心下单、客服转接流程不受影响。这个演练不做,大促当天出了状况就只能干瞪眼。

5.4 安全和合规要前置设计,不是事后补救

LLM接入电商场景,安全合规比功能上线优先级更高。我们在架构设计阶段就做了几道硬性约束:

  • Prompt注入防护:用户输入里可能包含“忽略前面的指令”“假装你是系统”这类攻击性文本。我们的做法是,在Prompt里明确系统指令优先于用户输入,同时在网关层对输入做关键词和模式检测,命中就直接拦截,不进模型。
  • 敏感信息脱敏:模型输出会自动拼接用户手机号、地址等个人数据,回应前必须过脱敏组件,中间四位打码。
  • 内容合规检测:模型生成的回复会经过内容安全服务过滤,命中风险词就降级为安全话术。
  • 操作类工具二次确认:所有涉及改地址、取消订单、退款的工具调用,用户在界面上必须再点一次确认按钮,后端校验会话状态后才真正执行。

严格意义上说,LLM是电商系统里“最不可控”的组件,我们不能假设它永远正确、永远遵守指令。所有安全约束都应该当成独立的防御层来做,而不是寄希望于模型“变乖”。

6. 效果评估:没有评测体系,你什么也优化不了

6.1 离线评测:先建一版黄金问答集

刚上线那阵子,我们优化Prompt完全靠拍脑袋——改几个字,让测试同学跑几轮对话,凭感觉说“好像好一些了”。这种模式完全不可持续。

后来做了一件事彻底改变局面:建设离线评测集。我们把真实用户对话整理出来,挑出有代表性的200条,同时为每条人工标注期望行为(比如“查询订单并告知物流状态”“推荐3款300元以内的鱼竿”)。每次改动Prompt、换模型、调工具描述,都拿这200条跑一遍,计算通过率。

这个“通过率”怎么算?跑完一轮后,把模型输出交给另一个大模型来打分,再抽取一部分人工复核校准。虽然自动打分不够完美,但作为回归基准足够了。有了它,我们就敢做高频实验了,每版Prompt改完都知道是好是坏。

6.2 线上监控与Badcase回流

离线评测解决“方向对不对”,线上监控解决“有没有翻车”。我们在Agent服务里埋了以下几类指标:

  • 工具调用成功率:模型发起调用后,工具是否成功返回数据。
  • 链路兜底率:有多少请求走了异常兜底话术,这是最重要的健康度指标,兜底率飙升基本等于系统在“带病运转”。
  • 用户反馈指标:对话结束后用户是否点了“有帮助”,是否主动转人工,是否在会话后马上关闭页面。
  • 资源消耗:token消耗、平均时延、模型服务错误码。

线上收集到的问题Case会每天自动回流到分析队列。我们有个固定的复盘流程:每天抽出15个左右的Badcase,人工打标签归类,看是意图理解错、工具调用错、还是知识回答错,然后针对性调整。

6.3 效果调优的三个方向

根据Badcase的归类,优化手段也无非这三个方向:

  • 改Prompt:占优化动作的大头。意图边界不够清楚、约束不够强、输出格式说明不明确,都靠Prompt修。
  • 换模型:某个模型在“多轮指代理解”上总是犯傻,换成另一个模型后可能大幅改善。模型换代带来的效果波动,有时候比Prompt改动还大。
  • 加RAG材料:回答不如预期,很多时候是参考知识不够。补充高质量FAQ、规范术语表,往往能立竿见影。

这三个方向听起来朴素,但在我的经验里,90%的效果问题都能通过这三板斧解决,真正需要上微调的场景少之又少。微调成本高、周期长、维护难,在业务规则频繁变化的电商场景里性价比很低。

7. 最后分享一点个人体会

整套系统上线之后,我最深的感受是:LLM开发实践,难点从来不是“让模型变聪明”,而是“让模型在工程边界内稳定地变聪明”。模型的能力上限决定了体验的上限,但工程能力决定了这个上限能兑现多少。Java工程师做这件事有天然优势——我们天生习惯定义边界、设计兜底、控制流程,这些在LLM应用里恰恰是最关键的环节。

如果你也准备在团队里启动类似的实践,我的建议是:先选一个足够窄、业务收益足够明确的场景做透,比如“售后工单自动分类”,把工具调用、上下文管理、评测体系这一整套流程跑通,再横向复制到其他场景。不要一开始就憋大招做一个“全能助手”,那大概率会拖垮整个项目。

另外还有一个小技巧:多让模型“说人话”。电商用户不会关心你的Agent用了什么框架、调了什么工具,他们只关心问题有没有被解决。把模型的回复风格从“客服八股文”调成自然顺畅的口语化表达,真的是提升用户好评率最立竿见影的手段——这个调整成本极低,但收益比很多花哨的功能都大。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询