本文电商系统常见问题为数据集,利用大模型自然语言理解能力实现智能客服系统
ChatGPT是如何回复
通过直接询问大模型美团常见问题
你:美团外卖中在线支付取消订单后钱怎么返还?
ChatGPT:
美团外卖中,当用户在线支付订单后如果需要取消订单,退款的处理方式通常如下:
1. 自动退款到支付账户:如果订单还未被餐厅接单或配送员接单,用户通常可以直接在美团外卖App
内取消订单,支付的款项会自动退回到用户的原支付账户中,例如微信支付、支付宝或银行卡
等。退款时间可能会有所不同,一般来说,支付宝和微信支付的退款较快,可以在几分钟到24小
可能需要1-7个工作日不等。 时内到账;如果是银行卡支付,
2. 客服介入处理:如果订单已经被餐厅或配送员接单,用户需要通过美团外卖的客服进行订单取消
和退款处理。在这种情况下,退款时间和是否能全额退款会根据订单的实际情况和美团的政策来
决定。美团外卖客服可能会先了解订单取消的原因,然后根据情况处理退款事宜。
3. 使用美团钱包:在某些情况下,用户可以选择将退款退到美团钱包中,这样退款速度会更快,用
户可以用于美团平台上的其他消费。
用户在申请取消订单和退款时,应仔细阅读美团外卖的退款政策和指引,以便更顺利地完成退款流
程。如果遇到问题,可以联系美团外卖的客服获取帮助。
直接利用ChatGPT来作为智能客服系统行不通,它能够理解你的问题,但是它并不能给你确切的答案,因为对于ChatGPT来说,它并不知道企业内部的专有数据
管理知识库
把现有的常见文件整理成文档,可以是txt、pdf、xlsx、markdown等格式:📎meituan-qa.txt
Q:在线支付取消订单后钱怎么返还?
订单取消后,款项会在一个工作日内,直接返还到您的美团账户余额。
Q:怎么查看退款是否成功?
退款会在一个工作日之内到美团账户余额,可在“账号管理——我的账号”中查看是否到账。
Q:美团账户里的余额怎么提现?
余额可到美团网(meituan.com)——“我的美团→美团余额”里提取到您的银行卡或者支付宝账号,另外,余额也可直接用于支付外卖订单(限支持在线支付的商家)。
Q:余额提现到账时间是多久?
1-7个工作日内可退回您的支付账户。由于银行处理可能有延迟,具体以账户的到账时间为准。
Q:申请退款后,商家拒绝了怎么办?
申请退款后,如果商家拒绝,此时回到订单页面点击“退款申诉”,美团客服介入处理。
Q:怎么取消退款呢?
请在订单页点击“不退款了”,商家还会正常送餐的。
Q:前面下了一个在线支付的单子,由于未付款,订单自动取消了,这单会计算我的参与活动次数吗?
不会。如果是未支付的在线支付订单,可以先将订单取消(如果不取消需要15分钟后系统自动取消),订单无效后,此时您再下单仍会享受活动的优惠。
Q:为什么我用微信订餐,却无法使用在线支付?
目前只有网页版和美团外卖手机App(非美团手机客户端)订餐,才能使用在线支付,请更换到网页版和美团外卖手机App下单。
Q:如何进行付款?
美团外卖现在支持货到付款与在线支付,其中微信版与手机触屏版暂不支持在线支付。
Q:如何查看可以在线支付的商家?
你可以在商家列表页寻找带有“付”标识的商家,提交订单时可以选择支付方式。
Q:美团外卖支持哪些支付方式?
现已支持美团余额、支付宝、网银(储蓄卡、信用卡)。
Q:在线支付订单如何退款?
商家接单前,您可以直接取消订单,订单金额会自动退款到美团余额;商家接单后,您在点击“申请退款”,在线申请。提交退款申请之后,商家有24小时处理您的退款申请。商家同意退款,或24小时内没有处理您的退款申请,您的支付金额会退款至您的美团余额。
Q:在线支付的过程中,订单显示未支付成功,款项却被扣了,怎么办?
出现此问题,可能是银行/支付宝的数据没有即时传输至美团,请您不要担心,稍后刷新页面查看。 如半小时后仍显示"未付款",请先联系银行/支付宝客服,获取您扣款的交易号,然后致电美团外卖客服4008507777,我们会协助您解决。
Q:哪些商家有优惠?都有些什么优惠?
有优惠的商家在商家列表页均含有优惠标识;具体的优惠可以查看活动详情或者商家详情页中的描述。
Q:在新用户享受的优惠中,新用户的条件是什么?
新用户是指第一次在美团外卖下单的用户(同一设备、同一手机号、同一账户仅可享受一次)。
Q:我达到了满赠、满减的优惠的金额,为什么没有享受相关的优惠?
满赠与满减优惠是以订单内菜品的总额来计算的,不包含配送费与包装费。
Q:超时赔付是什么意思?
超时赔付模式即:商家承诺一个送达时间和一个折扣,从用户下单时间开始计算,如果外卖超过了承诺时间才送到,该份外卖按照折扣价收取费用。由于恶劣天气、某些美食烹调时间过长、或者其他因素,商家会选择性的延长承诺时间或者不做承诺。预订单不参与超时赔付。
订单问题
Q:为什么提示我“账户存在异常,无法下单”?
包含(但不仅限于)以下行为者,系统将自动予以封禁(客服无权解封):
i)有过虚假交易(编造不存在真实买卖的订单);
ii)有过恶意下单行为;
Q:如何取消订单?
如果商家尚未接单,您可以在订单详情页通过“取消订单”功能进行取消;如果商家已接单,则需要您电话联系后由商家取消订单。
Q:我的订单为什么被取消了?
如果商家5分钟未接您的订单,为了保障您的权益,系统将会为您自动取消订单;商家接单后可能由于无法联系到您、菜品售完等原因无法配送,因而取消了您的订单,具体原因可查看系统发送的短信或通知。
Q:如何进行催单?
您可以在订单状态页面点击“电话催单”按钮向商家商家催单。
Q:刚下单发现信息填错了怎么办?
如果商家尚未接单,您可以自主取消订单;如果商家已经接单,您可以电话联系商家后由对方取消订单。然后重新下一单。
Q:我的订单是否被商家确认?
App用户可以在商家确认您的订单时收到推送通知,并且订单状态会实时更新;手机触屏版及微信用户可以刷新订单状态页查看。
Q:预计送达的时间为什么与我实际收餐的时间不符?
预计送达时间是系统根据用户评价的时间进行综合计算而得到的参考时间,餐厅的实际配送时间会受到当天的天气、订单量等外界因素影响。
Q:为什么会出现无法下单的情况?
无法下单有很多情况,可能是菜品售完、餐厅不在营业时间等,请查看无法下单时给的提示。
Q:为什么提示下单次数过多,已无法下单?
同一手机号在同一设备上一天最多可以成功提交7次订单(在线支付以完成支付为准,货到付款以提交订单为准)。
Q:如果对商家服务不满意如何进行投诉?
您可以在该订单完成评价后点击订单详情页中的意见反馈向客服投诉,或者拨打美团外卖的客服电话(400-850-7777)向客服进行投诉。
Q:如何联系客服解决问题?
您可以拨打美团外卖的客服电话(400-850-7777)或者在“我的”——>“意见反馈”页面提交反馈。
Q:我用的是手机客户端,为什么无法定位?
请先检查手机的网络以及是否开启定位功能。若确认正常,请试着在户外或wifi环境下进行定位。
Q:如何修改自己的账户信息?
美团外卖使用的是美团账号,您可以在“我的”页面修改个人账号信息,也可以在美团网账号页面修改个人账号。
Q:为什么有时需要输入短信验证码?
为了保障您的账号安全及商家利益,对于新用户及一些有异常行为的下单系统会提示您输入短信验证码。如果迟迟未接收到短信验证码,您同样可以选择接听语音验证码。
加载并解析文件
// 加载并解析文件
Document document;
try {
Path documentPath = Paths.get(CustomerServiceAgent.class.getClassLoader().getResource("meituan-qa.txt").toURI());
DocumentParser documentParser = new TextDocumentParser();
document = FileSystemDocumentLoader.loadDocument(documentPath, documentParser);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
使用FileSystemDocumentLoader来加载本地文件,利用TextDocumentParser来解析txt文件,最终得到"meituan-qa.txt"文件所对应的Document对象。
切分文件
public class CustomerServiceDocumentSplitter implements DocumentSplitter {
@Override
public List<TextSegment> split(Document document) {
List<TextSegment> segments = new ArrayList<>();
String[] parts = split(document.text());
for (String part : parts) {
segments.add(TextSegment.from(part));
}
return segments;
}
public String[] split(String text) {
return text.split("\\s*\\R\\s*\\R\\s*");
}
}
// 切分文件
DocumentSplitter splitter = new CustomerServiceDocumentSplitter() ;
List<TextSegment> segments = splitter.split(document);
使用正则表达式"\\s*\\R\\s*\\R\\s*"来进行切分,其中每个TextSegment对象就表示切分之后的一段文本,在本项目中就是一个问答对。
文本向量化
EmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder()
.apiKey(MY_API_KEY)
.baseUrl(MY_BASE_URL)
.build();
List<Embedding> embeddings = embeddingModel.embedAll(segments).content();
每个TextSegment,也就是每个问答对,对应了一个向量,而向量就是一个数字数组,如果简化一下数组的大小,比如大小为2,那么一个向量相当于一个(x,y)坐标点,放在坐标中就可以两个坐标点的距离,距离越近就表示坐标点越相似,也就是表示两个向量越相似。
也可以使用其他的向量模型来对文本进行向量化,比如使用AllMiniLmL6V2QuantizedEmbeddingModel这个向量化模型,使用它就需要通过网络请求去进行向量化了,因为这个模型可以直接部署在你当前的应用进程内,不过需要额外添加依赖:
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-embeddings-all-minilm-l6-v2-q</artifactId>
<version>0.25.0</version>
</dependency>
然后使用以下代码即可得到文本的向量:
EmbeddingModel embeddingModel = new AllMiniLmL6V2QuantizedEmbeddingModel();
List<Embedding> embeddings = embeddingModel.embedAll(segments).content();
不同的向量化模型效果肯定是有区别,比如A1、A2两个文本,open-ai计算出来的向量可能是比较相似的,而AllMiniLmL6V2QuantizedEmbeddingModel则可能计算出来的向量之间差别较大,所以在实际工作中还是建议使用效果更好的向量化模型。
向量存储
EmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>();
embeddingStore.addAll(embeddings, segments);
把向量和文本数据直接存在了JVM内存中,本质上就是一个CopyOnWriteArrayList,该List中存储的是Entry对象,而Entry对象则分别存储了文本和向量。
文本和向量存储可持久化的向量数据库中,选择Chroma、Milvus向量数据库,也可以使用Elasticsearch、Redis、PostgreSQL、MongoDb来存储,Redis存储向量数据需要额外的redisearch模块
使用docker来运行一个带有redisearch模块的redis容器:docker run -p 6379:6379 redis/redis-stack-server:latest
查看:redis-cli FT.SEARCH embedding-index "*" LIMIT 0 10
删除某个index和对应数据:redis-cli FT.DROPINDEX embedding-index DD
EmbeddingStore<TextSegment> embeddingStore = RedisEmbeddingStore.builder()
.host("127.0.0.1")
.port(6379)
.dimension(384)
.build();
embeddingStore.addAll(embeddings, segments);
dimension表示向量维度,也就是上面数组的大小,执行完以上代码后向量和文本就会存储到Redis中
实现
引入依赖
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>0.27.1</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>0.27.1</version>
</dependency>
<dependency>
<groupId>org.tinylog</groupId>
<artifactId>tinylog-impl</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.tinylog</groupId>
<artifactId>slf4j-tinylog</artifactId>
<version>2.6.2</version>
</dependency>
在main方法中进行简单测试:
private static final String MY_API_KEY = "demo";
private static final String MY_BASE_URL = "http://langchain4j.dev/demo/openai/v1";
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.baseUrl(MY_BASE_URL)
.apiKey(MY_API_KEY)
.build();
System.out.println(model.generate("你好"));
}
定义Agent
public interface CustomerServiceAgent {
String MY_API_KEY = "demo";
String MY_BASE_URL = "http://langchain4j.dev/demo/openai/v1";
// 用来回答问题的方案
String answer(String question);
// 利用AiServices创建一个CustomerServiceAgent的代理对象
static CustomerServiceAgent create() {
// 创建模型
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(MY_API_KEY)
.baseUrl(MY_BASE_URL)
.build();
// 指定模型,创建并返回代理对象
return AiServices.builder(CustomerServiceAgent.class)
.chatLanguageModel(model)
.build();
}
}
以上CustomerServiceAgent接口,提供了一个answer方法用来回答问题,同时提供了create方法用来利用AiServices生成CustomerServiceAgent代理对象
public static void main(String[] args) {
CustomerServiceAgent customerServiceAgent = CustomerServiceAgent.create();
System.out.println(customerServiceAgent.answer("你是谁?"));
}
我是一个人工智能助手,可以回答你的问题和提供帮助。你有什么问题需要我帮忙解答吗?
组装ContentRetriever
ContentRetriever contentRetriever = EmbeddingStoreContentRetriever.builder()
.embeddingStore(embeddingStore)
.embeddingModel(embeddingModel)
.maxResults(5) // 最相似的5个结果
.minScore(0.8) // 只找相似度在0.8以上的内容
.build();
将向量数据库和向量模型组装成了一个ContentRetriever,并指定ContentRetriever后续查找内容时,只返回相似度在0.8以上的前5个结果。
把整个TextSegment对象一起做的向量化,相当于“问题+答案”一起做的向量化:
List<Embedding> embeddings = embeddingModel.embedAll(segments).content();
EmbeddingModel embeddingModel = new AllMiniLmL6V2QuantizedEmbeddingModel();
// 将问题抽取出来单独进行向量化
List<TextSegment> questions = new ArrayList<>();
for (TextSegment segment : segments) {
questions.add(TextSegment.from(segment.text().split("\n")[0]));
}
List<Embedding> embeddings = embeddingModel.embedAll(questions).content();
整合Tool
public class DateCalculator {
@Tool("计算指定天数后的具体日期")
String date(Integer days) {
return LocalDate.now().plusDays(days).toString();
}
}
return AiServices.builder(CustomerServiceAgent.class)
.chatLanguageModel(model)
.contentRetriever(contentRetriever)
.chatMemory(chatMemory)
.tools(new DateCalculator())
.build();
这样大模型在得到初步答案后,会自动匹配到这个Tool,因为我问的是“最晚”,所以大模型能把“1-7”中的“7”提出来并传给我定义的Tool,从而算出具体的日期。
测试
完成Agent内容
public interface CustomerServiceAgent {
String MY_API_KEY = "demo";
String MY_BASE_URL = "http://langchain4j.dev/demo/openai/v1";
// 用来回答问题的方案
String answer(String question);
// 利用AiServices创建一个CustomerServiceAgent的代理对象
static CustomerServiceAgent create() {
// 创建模型
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(MY_API_KEY)
.baseUrl(MY_BASE_URL)
.build();
List<TextSegment> textSegments = splitText(inputInfo());
OpenAiEmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder().apiKey("demo").build();
InMemoryEmbeddingStore embeddingStore = new InMemoryEmbeddingStore();
embeddingStore.addAll(embeddingModel.embedAll(textSegments).content(), textSegments);
ContentRetriever contentRetriever = EmbeddingStoreContentRetriever.builder()
.embeddingStore(embeddingStore)
.embeddingModel(embeddingModel)
.maxResults(5) // 最相似的5个结果
.minScore(0.8) // 只找相似度在0.8以上的内容
.build();
// 指定模型,创建并返回代理对象
MessageWindowChatMemory messageWindowChatMemory = MessageWindowChatMemory.withMaxMessages(10);
return AiServices.builder(CustomerServiceAgent.class)
.chatMemory(messageWindowChatMemory)
.contentRetriever(contentRetriever)
.chatLanguageModel(model)
.tools(new DateCalculator())
.build();
}
static List<TextSegment> splitText(Document document) {
CustomerServiceDocumentSplitter splitter = new CustomerServiceDocumentSplitter();
return splitter.split(document);
}
static Document inputInfo() {
// 加载并解析文件
Document document;
try {
Path documentPath = Paths.get(CustomerServiceAgent.class.getClassLoader().getResource("meituan-qa.txt").toURI());
DocumentParser documentParser = new TextDocumentParser();
document = FileSystemDocumentLoader.loadDocument(documentPath, documentParser);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
return document;
}
}
问题:今天的余额提现,最晚什么时候能到账?
余额提现最晚会在7个工作日内到达您的支付账户。由于银行处理可能会有延迟,具体以账户到账时间为准。
问题:今天的余额提现,最晚哪天能到账?给我具体的日期
根据体现时间为1-7个工作日,最晚在2024年7月25日前到账。