新闻详情

新闻详情

首页 / 资讯中心 / 详情

大模型+数据库查询:最小闭环实现客服工单自动分类与检索

发布时间:2026/9/28 13:52:17来源:尧图网络
大模型+数据库查询:最小闭环实现客服工单自动分类与检索
做客服运维的同学估计都有同感每天收到一堆“我的订单怎么还没发货”“系统提示错误代码10086”之类的文字工单有的长有的短掺杂着截图、标点错乱和口语。过去我试过用规则匹配关键词但是人家换个说法规则就废了纯人工分吧几百条能分到人麻。后来我琢磨出一套最简单的组合大模型负责把文字工单读懂抽取成结构化字段再丢给一个数据库查询工具去检索历史同类工单的解决办法。不要一上来就搞微调、搞Agent框架先把最小闭环跑通看效果再迭代。这篇就记录我这个“先跑起来”的完整过程适合手里有几百条工单、想快速自动化分类和支持的小团队。1. 项目背景与整体思路拆解1.1 文字工单的本质短文本、口语化、变化万端文字工单很难处理不是因为它数据量大而是因为它“不听话”。规则引擎处理的是标准化语言可真实工单充满了口语、错别字、缩写和临时约定。比如用户说“东西坏掉了能不能换”另一条说“我买的这个裂了想退货”两条意思相近但关键词完全不同。这种情况下传统的关键词匹配要么漏掉太多要么误判太多。你加了一堆“坏、裂、退货”又遇到“商品有问题”“质量不太行”这种新说法规则又得改。而大模型理解的是语义不是字面它能抓住真实意图还能顺手把工单里的订单号、用户ID、问题类型、紧急程度都提取出来变成结构化字段。1.2 为什么选“大模型查询工具”组合而不是传统规则引擎单靠大模型也不行。大模型记性再好也不可能把你过去半年处理过的工单和对应方案都记在脑子里。它擅长理解和生成但“查历史记录”“统计某一类问题出现多少次”“找出之前处理过某个订单的备注”这些活交给数据库查询工具才是正路。所以整个思路是先让大模型把非结构化的工单文字解析成结构化字段再把字段写入自己的系统用查询工具去检索历史工单和知识库最后生成分类标签和处理建议。这样一来大模型干它擅长的“语义理解”查询工具干它擅长的“结构化检索”各管一段互不拖累。1.3 最小可用闭环半天内先跑起来的路线图很多人一听到“大模型”就想着部署、微调、写Agent那是后面的事。先跑起来只需要三步。第一步选一个大模型接口能传一段文字、返回一段JSON就行。第二步建一张工单表把历史工单和未来生成的工单都存进去。第三步写一个脚本读一条工单调大模型抽字段然后查数据库拿相似案例拼接成结论。我第一版连Web界面都没做在命令行里跑起来效果有了再往上加东西。这个路线图一个人半天基本能走完。2. 核心细节解析与工具选型2.1 大模型怎么选先API后本地模型第一批项目不需要纠结模型大小。我建议直接选一个带免费额度或低价的国产大模型开放API注册后拿个Key就能用。主要看两点能不能返回JSON格式响应速度是否稳定。如果你想完全本地化也可以用Ollama跑一个Qwen系列的开源7B模型本地起个HTTP服务接口风格和大多数云端API相似。这样就不用考虑数据外发问题但需要机器至少有8GB可用内存最好有一张消费级显卡没有的话CPU也能跑只是慢一点。我的建议是先拿云端API把流程跑通再根据数据隐私和成本决定要不要切本地模型。一开始不用把“本地部署大模型”当成前提条件。2.2 查询工具怎么选SQLite起步MySQL过渡这里说的查询工具不是某个具体软件而是能执行SQL、快速检索结构化数据的方案。对于数据量在几万条以内的工单SQLite完全够用它就是一个文件不需要装服务Python自带的sqlite3模块就能操作零安装成本。如果你的团队已经有MySQL或PostgreSQL直接用现成的更好。因为工单往往还会关联订单表、用户表后面要做统计报表SQL数据库是通用方案。我自己的偏好是先用SQLite把逻辑跑顺等后面要多人维护了再迁到MySQL毕竟SQL语句基本通用切换成本很低。还有一类工具是可视化数据库客户端比如DBeaver、Navicat它们能让你像看Excel一样看工单表调试查询语句很方便。但它们解决不了“自动查询”的问题核心还是要有代码去连数据库执行SQL。2.3 Prompt是关键稳定输出结构化数据的四个细节大模型能不能提供“稳定输出”完全取决于Prompt怎么设计。我踩过几次坑后总结出四个细节照着写基本不会翻车。第一个细节明确告诉模型“只输出JSON不要任何解释”。不然它会在JSON前后加一段“好的我来帮你处理”这类废话解析的时候很麻烦。第二个细节给出字段定义和示例。比如“请从工单中提取以下字段problem_type、urgency、order_id、user_message_summary”然后给一个真实样例让模型照着样子输出。第三个细节用“few-shot”把格式演示一遍。一次性给它两条工单和对应的JSON结果它就能模仿输出准确率会明显提升。第四个细节限定取值枚举。比如“problem_type只能是物流问题、售后质量、订单操作、账号权限、投诉建议、其他”这样分类结果整齐划一后面按类型查询很舒服。3. 实操过程与核心环节实现3.1 环境准备与基础依赖这个项目的运行环境非常简单只用Python 3.9以上版本和两个依赖requests和pandas。如果你决定用SQLite连pandas都可以不用但为了后面批量处理CSV工单更方便我还是装上。python -m venv venv source venv/bin/activate # Windows 下是 venv\Scripts\activate pip install requests pandas然后在项目目录里建一个.env文件存放API Key用python-dotenv读取或者直接在代码里设置环境变量但千万不要把Key提交到Git仓库。3.2 写个最小脚本单条工单自动分类与信息提取核心脚本的逻辑就三步接收一条文本工单把Prompt和文本拼在一起发给大模型拿到JSON后解析并打印。这里我写了一个可运行的示例接口地址和模型名占了占位符你换成自己的就行。import os import json import requests MODEL_API_URL os.getenv(MODEL_API_URL, https://your-llm-api.example.com/v1/chat/completions) MODEL_API_KEY os.getenv(MODEL_API_KEY, your-api-key) MODEL_NAME os.getenv(MODEL_NAME, your-model-name) def extract_ticket(text: str) - dict: prompt f 请从下面的文字工单中提取信息并只输出JSON不要输出其他内容。 字段定义: - problem_type: 问题类型只能是[物流问题,售后质量,订单操作,账号权限,投诉建议,其他] - urgency: 紧急程度只能是[高,中,低] - order_id: 订单号没有则填null - user_id: 用户ID没有则填null - user_message_summary: 用一句话概括用户问题 示例 工单我昨天下的订单今天还没发货单号2024001帮我催一下。 输出{{problem_type:物流问题,urgency:高,order_id:2024001,user_id:null,user_message_summary:用户催发货}} 工单文字 {text} payload { model: MODEL_NAME, messages: [{role: user, content: prompt}], temperature: 0, } resp requests.post( MODEL_API_URL, headers{Authorization: fBearer {MODEL_API_KEY}}, jsonpayload, timeout30, ) resp.raise_for_status() content resp.json()[choices][0][message][content] return json.loads(content) if __name__ __main__: ticket 东西收到了但屏幕有一条裂纹想退货。订单号是10086。 result extract_ticket(ticket) print(json.dumps(result, ensure_asciiFalse, indent2))运行之后我实际拿到的输出是{ problem_type: 售后质量, urgency: 中, order_id: 10086, user_id: null, user_message_summary: 用户反馈屏幕裂纹要求退货 }这一步先不用管数据库把单条工单的结构化解析跑通整个项目就有底子了。3.3 将结果落库并用查询工具做相似工单检索光能提取字段还不够落地到数据库才算真正能用。我建了一张工单表字段和模型输出对齐再额外加一个created_at和solution字段solution用来存历史处理结果。CREATE TABLE IF NOT EXISTS tickets ( id INTEGER PRIMARY KEY AUTOINCREMENT, problem_type TEXT, urgency TEXT, order_id TEXT, user_id TEXT, user_message_summary TEXT, solution TEXT, created_at TEXT DEFAULT CURRENT_TIMESTAMP );接下来把上一步的结构化结果写入SQLite然后执行一条查询找出同类问题下最近的处理方案import sqlite3 conn sqlite3.connect(tickets.db) cur conn.cursor() cur.execute( INSERT INTO tickets (problem_type, urgency, order_id, user_id, user_message_summary) VALUES (?, ?, ?, ?, ?) , (result[problem_type], result[urgency], result[order_id], result[user_id], result[user_message_summary])) conn.commit() # 查找同类问题最近的处理方案 cur.execute( SELECT user_message_summary, solution, created_at FROM tickets WHERE problem_type ? AND solution IS NOT NULL ORDER BY created_at DESC LIMIT 3 , (result[problem_type],)) rows cur.fetchall() for row in rows: print(row)这一步就是“用查询工具处理文字工单”的精髓模型负责把文字变成可查询的字段数据库负责把历史经验捞出来。两条线一拼结果就很有参考价值。3.4 批量处理几十条工单一键跑完单条没问题就批量。我通常先把工单存成CSV然后用脚本循环处理每处理一条写入数据库再顺带输出一份结果表格。import pandas as pd df pd.read_csv(incoming_tickets.csv) # 必须有 text 列 results [] for idx, row in df.iterrows(): try: parsed extract_ticket(row[text]) results.append(parsed) # 这里可以同步写入数据库代码和上面一致 except Exception as exc: results.append({ problem_type: 解析失败, urgency: 未知, order_id: None, user_id: None, user_message_summary: f异常{exc}, }) result_df pd.DataFrame(results) result_df.to_csv(parsed_tickets.csv, indexFalse)批量处理时要注意频率控制。如果接口没有很高的并发限制就加一个time.sleep(0.3)别一口气打几十个请求否则很容易触发限流。实测下来加上0.3秒的间隔一分钟能处理接近200条工单对中小团队完全够用。4. 常见问题与排查技巧实录4.1 接口超时、限流与网络抖动怎么处理大模型接口不是每次都稳。直接抛错有两个常见原因一是单次请求耗时过长超过了本地timeout设置二是单位时间内请求次数太多服务端返回429限流。我的处理比较简单把timeout调成30秒写一个带重试的装饰器遇到网络或5xx错误就退避重试最多试三次。限流的时候重试间隔按指数增长比如第一次等2秒第二次等4秒第三次等8秒。日常跑批60秒内请求数控制在200以下基本不会触发限流。4.2 模型输出JSON不合法或字段缺失怎么补救即使Prompt写得再清楚模型还是偶尔会输出带Markdown代码块标记的JSON或者少一个逗号导致无法解析。我第一版就直接json.loads结果崩溃了好几次。现在我是这么兜底的先尝试json.loads失败后就用正则把代码块标记剥掉再解析还是失败就用json_repair这个库它能把残缺的JSON补全。如果你不想引入额外依赖也可以让模型输出前先加一行“现在开始输出JSON”同时设定temperature0能降低不少随机性。另外字段缺失也很常见。我会在解析后对每个字段做默认值处理缺什么补什么不直接中断流程。这样才能保证大批量处理时一条失败不会拖垮全部。4.3 查询匹配不准可能是标签粒度问题当你发现查出来的历史工单跟当前问题不相关问题往往不在SQL而在problem_type分类粒度太粗。比如你把“订单地址修改”和“订单合并支付”都归到“订单操作”那查询时就混在一起拿到的处理方案自然不精准。解决办法是在Prompt中进一步细分二级标签或者增加一两个业务属性字段。比如给“订单操作”加一个子字段operation_type取值“改地址、改支付方式、取消订单、合并订单”等。查询时先用一级类型过滤再用二级类型精查准确率会明显提升。我实际跑下来标签越细查询工具的价值越大。因为大模型分类粗了以后查询结果全是噪音再好的数据库也救不回来。4.4 从几十条到几万条扩展时的几个注意点当工单量从几十条涨到几万条会出现几个新问题。第一SQLite单表扫描变慢需要给problem_type、order_id这些查询字段加索引。第二每次调大模型处理实时工单会越来越慢可以考虑把处理任务丢到队列里异步执行或提前用每日的工单文件批量预处理。第三历史数据不能无限存SQLite文件数据量达到几百万条之后迁移到MySQL或PostgreSQL是合理选择。迁移的时候只要保持表结构不变查询代码不需要大改。我建议从第一天开始就在代码里写好SQLCREATE语句后续切换数据库只要调整连接驱动就行。我个人在实际操作中最大的体会是不要高估大模型的记忆也不要低看查询工具。把“语义理解”和“数据检索”拆开整个系统才能既聪明又可靠。如果你手里也有被文字工单逼疯的经历不妨先按这个流程跑一遍哪怕只处理了50条工单你也会立刻发现哪些环节最值钱哪些环节是真正的时间黑洞。下一步再考虑加Web端、加自动回复、加告警通知都是后端的事情了。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

OpenCV+Deepface实战:人脸情绪识别原理与工程落地 2026/9/28 15:48:45

OpenCV+Deepface实战:人脸情绪识别原理与工程落地

简介:面向计算机视觉初学者与情绪识别应用开发者,这套项目整合OpenCV与Deepface实现人脸面部情绪识别的完整流程,覆盖人脸检测、特征提取、情绪分类以及模型优化等关键环节,代码结构清晰,便于对照学习。压缩包共4个文件…

阅读更多 →
ARM板卡部署Foxglove Studio:ROS 2可视化的高效实践指南 2026/9/28 15:48:45

ARM板卡部署Foxglove Studio:ROS 2可视化的高效实践指南

如果你在实验室里用树莓派4B或者RK3588顶着ARM架构的板卡跑机器人,大概率经历过这样的场面:编译完一版ROS 2功能包,兴冲冲地打开rviz准备看激光扫描和点云,结果界面卡得拖不动,鼠标操作一次要等两秒。更麻烦的是很多板…

阅读更多 →
基于AgentArts的金融信贷智能体实践:从流程拆解到部署运维 2026/9/28 15:48:45

基于AgentArts的金融信贷智能体实践:从流程拆解到部署运维

金融信贷这个场景,我一直觉得是大模型落地最“实在”的领域之一。原因很简单:信贷流程天然是结构化的——有明确的步骤、明确的输入输出、明确的风险控制要求,而且每一个环节都伴随着大量的人力重复劳动。正因为如此,它特别适合用…

阅读更多 →
金融信贷智能体实战:华为云AgentArts搭建、调优与合规落地 2026/9/28 15:48:45

金融信贷智能体实战:华为云AgentArts搭建、调优与合规落地

做金融信贷场景的AI智能体,不是光接一个大模型API就完事。去年年底我带着团队在华为云AgentArts上把一套信贷审批辅助和贷前咨询的智能体从原型推到了生产,整个过程踩了不少坑,也沉淀下来一套可复用的搭建方法。这篇就围绕这次实战&#xff0…

阅读更多 →
多智能体辩论式AI:让AI互相质证,挖掘A股深度分析价值 2026/9/28 15:48:45

多智能体辩论式AI:让AI互相质证,挖掘A股深度分析价值

搞投资的朋友都知道,分析一家公司有多痛苦:财报、公告、研报、舆情,信息量大到爆炸,而且观点互相打架。看多看空都各有理由,普通人根本不知道信谁。这个项目的出发点很简单:既然AI大模型能读文档、能做推理…

阅读更多 →
AgentScope深度实战:多智能体协作、RAG服务化与Java版落地全解析 2026/9/28 15:48:38

AgentScope深度实战:多智能体协作、RAG服务化与Java版落地全解析

AgentScope这个东西,我认真研究了两周,也把它拉进真实项目里跑了几个多智能体场景。今天这篇不是给你念官方README,而是从一个实际动手折腾过的人角度,说说它到底牛在哪、2.0版本改了什么、Java版到底是不是噱头、以及我踩过的那些…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉