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

langchain4j 学习系列(7)-文本分类

继续我们的langchain4j学习之旅,很多“智能客服”之类的AI应用,“问题分类”是非常重要的功能之一。比如:客人进来咨询问题,得判断出客人的问题是“订单相关”(比如:我要取消订单),还是“支付相关”(比如:我要退款),还是“投诉相关”(比如:你们的服务太差了,我要投诉到相关部门)。识别出对应分类后,就可以交给相应的流程(或细分的sub agent)做进一步处理。

langchain4j 提供了2种分类方法:

一、基于LLM的语义理解

1.1 定义分类枚举

    enum CustomerServiceCategory {PRODUCT("产品相关"),ORDER("订单相关"),ACCOUNT("账户相关"),MEMBER("会员相关"),PAYMENT("支付相关"),OTHERS("其它问题");@Getterprivate final String desc;CustomerServiceCategory(String desc) {this.desc = desc;}}

1.2 定义AIService的接口

    interface CustomerServiceCategoryClassifier {@UserMessage("将客人遇到的问题【{{text}}】归类")CustomerServiceCategory classify(String text);}

1.3 测试

    @GetMapping(value = "/classify", produces = MediaType.APPLICATION_JSON_VALUE)public ResponseEntity<String> classify(@RequestParam String query) {try {CustomerServiceCategoryClassifier customerServiceClassifier = AiServices.create(CustomerServiceCategoryClassifier.class, ollamaChatModel);CustomerServiceCategory classify = customerServiceClassifier.classify(query);return ResponseEntity.ok(classify.getDesc());} catch (Exception e) {log.error("classify", e);return ResponseEntity.ok("{\"error\":\"classify error: " + e.getMessage() + "\"}");}}

效果:

image

image

观察日志的话,能看到与LLM的交互:

2025-12-09T21:00:57.280+08:00  INFO 5948 --- [langchain4j-study] [io-8080-exec-10] d.l.http.client.log.LoggingHttpClient    : HTTP request:
- method: POST
- url: http://localhost:11434/api/chat
- headers: [Content-Type: application/json]
- body: {"model" : "deepseek-v3.1:671b-cloud","messages" : [ {"role" : "user","content" : "将客人遇到的问题【我的退款为什么还没到账?】归类\nYou must answer strictly with one of these enums:\nPRODUCT\nORDER\nACCOUNT\nMEMBER\nPAYMENT\nOTHERS"} ],"options" : {"stop" : [ ]},"stream" : false,"tools" : [ ]
}

这种方法的准确性完全取决于模型能力的强弱,大多数情况下是OK的,但有些case可能会不太符合我们的预期,比如:

image

一些互联网平台,对于“积分”可能会归到【会员相关】(比如:积分累积到了一定程度,可以兑换成高等级会员),这时候就可以考虑第2种方法。

  

二、基于向量数据库的相似度计算

2.1 先梳理已知问题的归类

    Map<CustomerServiceCategory, List<String>> getExamples() {Map<CustomerServiceCategory, List<String>> examples = new HashMap<>();examples.put(PRODUCT, asList("怎么没有产品说明书?","产品的保修期过了怎么办?","我新买的东西用了一周就坏了?","产品无法使用?"));examples.put(ORDER, asList("我的订单现在到哪里了?","能给我一个快递单号吗?","我怎么知道我的订单已经发货了?","我可以更改配送方式吗?","你们提供次日达服务吗?","可以选择到店自提吗?","我的订单什么时候能到?","为什么我的配送延迟了?","我可以指定配送日期吗?","已经过了预计送达日期,我的订单在哪里?","如果出现延迟,我会收到通知吗?","天气原因会导致配送延迟多久?","我收到了订单,但少了一件商品。","包裹送达时是空的。","我收到的商品错了,该怎么办?","我所有的商品会同时送达吗?","为什么我只收到部分订单商品?","剩下的商品能更快送达吗?"));examples.put(PAYMENT, asList("能用支付宝吗?","微信支付可以吗?","支持信用卡吗?","付款时我遇到一个错误","可以通过银行转账付款吗?","为什么我的付款被拒绝了","可以给我发送上一笔订单的发票吗?","发票会自动发送到我的电子邮箱吗?","如何申请退款?"));examples.put(MEMBER, asList("我的会员等级变低了?","我的积分过期了?","我的优惠券不能用了?","能给我发个支付95折优惠券吗?","满减优惠券当次消费就能用吗?","能送100点优惠积分吗?"));examples.put(ACCOUNT, asList("如何注销账号?","我的密码过期了?","为什么无法登录","登录时手机收不到验证码","如果更换账号绑定的手机号"));examples.put(OTHERS, asList("厂商的联系电话是多少?","如何加盟?","你们公司还招人吗?"));return examples;}

2.2 使用embedding模型分类

    @GetMapping(value = "/classify/embed", produces = MediaType.APPLICATION_JSON_VALUE)public ResponseEntity<String> classifyEmbed(@RequestParam String query) {try {TextClassifier<CustomerServiceCategory> classifier = new EmbeddingModelTextClassifier<>(ollamaEmbeddingModel, getExamples());List<CustomerServiceCategory> categories = classifier.classify(query);String result = "";if (!CollectionUtils.isEmpty(categories)) {CustomerServiceCategory classify = categories.get(0);result += classify.getDesc() + ",";}return ResponseEntity.ok(StringUtils.trimTrailingCharacter(result, ','));} catch (Exception e) {log.error("classify", e);return ResponseEntity.ok("{\"error\":\"classify error: " + e.getMessage() + "\"}");}}

image

刚才的case符合预期了,但该方法有缺陷也十分明显,如果梳理的已知问题分类不够全面,会出现误判,比如:

image

这个问题不在事先准备好的问题列表中,计算出来的结果就差强人意了。实际应用中,如何取舍看业务场景,或者二者结合使用(比如:2个方法都跑一遍,看是否一致,然后再根据一定策略做处理。或者先用方法1,先做一轮分类,将结果人工复检后,用于完善方法2中的分类列表)

 

文中示例代码:GitHub - yjmyzz/langchain4j-study at day07

http://www.rkmt.cn/news/79947.html

相关文章:

  • 实用指南:OCR与AI赋能医药资质审核的全流程自动化方案
  • Spark的运行架构,RDD自带容错机制分析 - f
  • 解码多态、虚函数——动态行为扩展
  • 2025托福培训机构选择指南:精准匹配你的提分需求
  • 2025托福辅导机构优选指南:从口碑到提分的全方位攻略
  • 使用VSCode开发ESP32单片机基于MicroPython-12.8
  • 过碳酸钠选购指南:优质厂家推荐及欧盟标准供应商盘点
  • DBLens 连接数怎么限制?免费 3 个,订阅随便加
  • 轮询相关算法
  • 数据仓库和数据集市之ODS、CDM、ADS、DWD、DWS - 教程
  • 托福备考黄金期,如何精准锁定高性价比机构?
  • 2025年12月广州番禺佛山网站建设,营销网站建设,网站建设推广公司品牌推荐,定制能力与交付效率三维测评
  • 2025托福培训机构怎么选?6大高性价比机构测评+避坑指南
  • 2025雅思一对一机构推荐排行榜:精准提分攻略,考研必看!
  • 2025年12月深圳公装装修公司最新推荐:深圳办公室装修设计、深圳酒店装修设计、深圳展厅装修设计、深圳写字楼装修设计、深圳厂房装修设计、深圳公寓装修设计、八匹马装饰成企业优选
  • 12月8日总结 - 作业----
  • 微信小工具的uniapp-vue社团活动管理的高效的系统yagfy
  • 仿everything制作搞笑检索设计(是的,我没有打错字)
  • 平面上两点和方位角计算目标交点的算法(应该可用于 MC 末地传送门三角定位)
  • 大模型完整架构
  • 102302114_比山布努尔兰_作业4
  • Redis提供的原子性命令
  • 2025年12月室内水上乐园厂家推荐:山东汇川,儿童水上乐园、大型水上乐园、主题水上乐园、室外水上乐园、恒温泳池、室 泳池、全场景适配新标杆
  • Semaphore、CountDownLatch、ReentrantLock使用场景简单说说
  • 杂题选记
  • 2025年12月铝材厂家推荐榜:廊坊国美铝业,工业铝材、门窗铝材、3C铝材、通用铝材、多领域铝材定制与绿色生产标杆
  • 2025年12月包头保洁公司最新推荐:信达家政,包头保洁开荒、包头高空清洗保洁、包头保姆公司、包头保姆家政、包头保姆月嫂、包头保姆护工、服务品质新标准
  • 机器视觉测量与建模
  • [Java EE] 多线程 -- 初阶(1) - 详解
  • 2025 雅思培训班怎么选?5 大热门机构深度测评 + 避坑指南