Java基于大模型实现客服系统

2024-08-31 15:12
文章标签 java 实现 系统 模型 客服

本文主要是介绍Java基于大模型实现客服系统,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

如果你问大模型企业私有化的问题,大模型很可能就答非所问了,倘若让大模型结合企业内部数据回答, 用户满意度大幅提升 。以下基于RAG技术实现客服系统

1、引入相关包

    <properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><langchain4j.version>0.33.0</langchain4j.version></properties><dependencies><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j</artifactId><version>${langchain4j.version}</version></dependency><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-open-ai</artifactId><version>${langchain4j.version}</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></dependencies>    

官网链接: OpenAI | LangChain4j

2、文本转向量

向量是数学中的一个基本概念,表示具有大小(gpt的向量长度是1536位)和方向的量。在深度学习中,向量通常用于表示数据点或特征。

向量数据库是一种专门用于存储和查询向量数据的数据库系统。它能够高效地处理高维向量数据,支持基于向量相似性的搜索。

OpenAiEmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder().baseUrl("http://langchain4j.dev/demo/openai/v1").apiKey("demo").build();Response<Embedding> embeddingResponse = embeddingModel.embed("hello word");String string = embeddingResponse.content().toString();System.out.println(string);System.out.println('length:' + embeddingResponse.content().vector().length);

控制台输出:

Embedding { vector = [-0.014903838, 0.0013317588, -0.018488139, -0.031072723, -0.024273094, 0.0075046294, -0.023034403, -0.0010262037, -0.012795426, -0.022441411,
… … …
0.020333, 0.0042761234, -0.023324309, -0.034920577, 0.0142844925, 5.39457E-4, -0.0304402, -0.0035184128, -0.011095519] }
length:1536

3、保存向量

RAG(Retrieval-Augmented Generation,检索增强生成) 技术是一种结合信息检索(Retrieval)和生成(Generation)的混合模型方法,旨在通过检索相关信息来增强生成模型的性能。 RAG技术的核心思想是在生成回复时,不仅依赖模型自身的语言理解能力,还通过检索外部知识库(如产品手册等)来增强回复的准确性和丰富性。

基于客服系统需要涉及企业内部私有的信息,需要事先转为向量存储在向量数据库

向量数据库有很多,在LangChain4j中,EmbeddingStore表示向量数据库,它有20个实现类:

  1. AstraDbEmbeddingStore
  2. AzureAiSearchEmbeddingStore
  3. CassandraEmbeddingStore
  4. ChromaEmbeddingStore
  5. ElasticsearchEmbeddingStore
  6. InMemoryEmbeddingStore
  7. InfinispanEmbeddingStore
  8. MemoryIdEmbeddingStore
  9. MilvusEmbeddingStore
  10. MinimalEmbeddingStore
  11. MongoDbEmbeddingStore
  12. Neo4jEmbeddingStore
  13. OpenSearchEmbeddingStore
  14. PgVectorEmbeddingStore
  15. PineconeEmbeddingStore
  16. QdrantEmbeddingStore
  17. RedisEmbeddingStore
  18. VearchEmbeddingStore
  19. VespaEmbeddingStore
  20. WeaviateEmbeddingStore

比如redis,使用docker安装

docker run --name redis-stack-server -p 6379:6379 redis/redis-stack-server:latest

官网链接:https://redis.io/docs/latest/operate/oss_and_stack/install/install-stack/

删除索引和数据命令

redis-cli FT.DROPINDEX embedding-index DD

文档:https://redis.io/docs/latest/commands/ft.dropindex/#examples

maven中引入相关包

<dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-redis</artifactId><version>${langchain4j.version}</version>
</dependency>

以下以客服电话举例

OpenAiEmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder().baseUrl("http://langchain4j.dev/demo/openai/v1").apiKey("demo").build();RedisEmbeddingStore embeddingStore = RedisEmbeddingStore.builder().host("47.xxx.xxx.16").port(6379).dimension(1536)// 不设置默认:embedding-index
//                .indexName("test").build();TextSegment textSegment1 = TextSegment.textSegment("客服电话:95152");TextSegment textSegment2 = TextSegment.textSegment("客服时间:周一至周日 08:30-22:00");TextSegment textSegment3 = TextSegment.textSegment("违法和不良信息举报电话:400-140-2108");Response<Embedding> embed1 = embeddingModel.embed(textSegment1);Response<Embedding> embed2 = embeddingModel.embed(textSegment2);Response<Embedding> embed3 = embeddingModel.embed(textSegment3);// 把向量和对应的文本一并存入embeddingStore.add(embed1.content(), textSegment1);embeddingStore.add(embed2.content(), textSegment2);embeddingStore.add(embed3.content(), textSegment3);

查询,看下是否保存成功

redis-cli FT.SEARCH embedding-index "*" LIMIT 0 1

redis-cli FT.SEARCH embedding-index "*" LIMIT 0 1
1) (integer) 3
2) "embedding:c013b1ff-e20a-4124-895b-ebfc1abdca23"
3) 1) "$"2) "{\"vector\":[0.0077204346,-0.011896749,-0.0042433655,0.001396096,-0.017382152,0.018825343,-0.00072119647,0.011034666,-0.007969481............"

java查询

OpenAiEmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder().baseUrl("http://langchain4j.dev/demo/openai/v1").apiKey("demo").build();RedisEmbeddingStore embeddingStore = RedisEmbeddingStore.builder().host("47.xxx.xxx.16").port(6379).dimension(1536).build();Response<Embedding> embed = embeddingModel.embed("客服电话多少");List<EmbeddingMatch<TextSegment>> result = embeddingStore.findRelevant(embed.content(), 3);for (EmbeddingMatch<TextSegment> embeddingMatch : result){System.out.println(embeddingMatch.embedded().text() + ",分数为:" + embeddingMatch.score());}

代码指定了查询3条,第一条匹配度最高

控制台输出如下:

客服电话:95152,分数为:0.9283385276795
客服时间:周一至周日 08:30-22:00,分数为:0.924619972706
违法和不良信息举报电话:400-140-2108,分数为:0.912132680416

以上介绍了如何把文字转为向量,并存入数据库中

4、客服系统实现

4.1 知识库数据处理

假设知识是如下格式(myDocument.txt),一个问题紧接着一个答案,每个问答之间有一个空行

Q:余额提现到账时间是多久?
1-7个工作日内可退回您的支付账户。由于银行处理可能有延迟,具体以账户的到账时间为准。Q:申请退款后,商家拒绝了怎么办?
申请退款后,如果商家拒绝,此时回到订单页面点击“退款申诉”,美团客服介入处理。Q:怎么取消退款呢?
请在订单页点击“不退款了”,商家还会正常送餐的。
4.1.1 解析文件为document对象
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.DocumentParser;
import dev.langchain4j.data.document.DocumentSplitter;
import dev.langchain4j.data.document.loader.FileSystemDocumentLoader;
import dev.langchain4j.data.document.parser.TextDocumentParser;
....
Document document;
// 读取文本
Path documentPath = Paths.get("src/main/resources/myDocument.txt");
DocumentParser documentParser = new TextDocumentParser();
document = FileSystemDocumentLoader.loadDocument(documentPath, documentParser);
4.1.2 使用正则\\s*\\R\\s*\\R\\s*切分文件

先实现DocumentSplitter接口

class CustomerServiceDocumentSplitter implements DocumentSplitter {@Overridepublic 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*");}}

调用方法切分

import dev.langchain4j.data.segment.TextSegment;
....
CustomerServiceDocumentSplitter splitter = new CustomerServiceDocumentSplitter();
List<TextSegment> segments = splitter.split(document);

TextSegment对象有个属性text存储了我们的问答对

4.2 问答对向量存储

把知识库的文本向量化并存储至向量数据库中

// 文本向量化
EmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder()
.apiKey("demo")
.baseUrl("http://langchain4j.dev/demo/openai/v1")
.build();
List<Embedding> embeddings = embeddingModel.embedAll(segments).content();
System.out.println("向量化完毕");// 存redis
EmbeddingStore<TextSegment> embeddingStore = RedisEmbeddingStore.builder()
.host("47.xxx.xxx.16")
.port(6379)
.dimension(1536)
.build();
embeddingStore.addAll(embeddings, segments);
System.out.println("向量存储完毕");

4.3 从向量库中检索内容

创建了一个ContentRetriever对象,用于从向量库中检索内容

 // 内容查找ContentRetriever contentRetriever = EmbeddingStoreContentRetriever.builder()// 指定模型.embeddingModel(embeddingModel)// 指定向量库.embeddingStore(embeddingStore)// 最多返回5条数据.maxResults(5)// 最低匹配分数为0.8.minScore(0.8).build();Query query = Query.from("余额什么时候到账?");
List<Content> retrieve = contentRetriever.retrieve(query);
// 输出检索到的内容数量:5
System.out.println("size:" + retrieve.size());
// 打印第一条检索结果的文本内容
System.out.println(retrieve.get(0).textSegment().text());

4.4 借助大模型和向量数据库查询答案

根据以上知识,使用AiServices编写代码
AiServices基础参考

    interface CustomerServiceAgent {String answer(String question);// 利用AiServices创建一个CustomerServiceAgent的代理对象static CustomerServiceAgent create() {// 构造ChatMemory,用来保存历史聊天记录ChatMemory chatMemory = MessageWindowChatMemory.withMaxMessages(10);EmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder().apiKey("demo").baseUrl("http://langchain4j.dev/demo/openai/v1").build();EmbeddingStore<TextSegment> embeddingStore = RedisEmbeddingStore.builder().host("47.xxx.xxx.16").port(6379).dimension(1536).build();ContentRetriever contentRetriever = EmbeddingStoreContentRetriever.builder().embeddingModel(embeddingModel).embeddingStore(embeddingStore).maxResults(3).minScore(0.8).build();ChatLanguageModel model = OpenAiChatModel.builder().apiKey("demo").baseUrl("http://langchain4j.dev/demo/openai/v1").build();return AiServices.builder(CustomerServiceAgent.class).chatLanguageModel(model).chatMemory(chatMemory).contentRetriever(contentRetriever).build();}}

写个main函数测试

    public static void main(String[] args) {String answer = CustomerServiceAgent.create().answer("余额什么时候到账?");System.out.println("-------answer:" +answer);}

控制台输出:

-------answer:余额提现到账时间是1-7个工作日内,具体以账户的到账时间为准。

这篇关于Java基于大模型实现客服系统的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1124257

相关文章

windos server2022里的DFS配置的实现

《windosserver2022里的DFS配置的实现》DFS是WindowsServer操作系统提供的一种功能,用于在多台服务器上集中管理共享文件夹和文件的分布式存储解决方案,本文就来介绍一下wi... 目录什么是DFS?优势:应用场景:DFS配置步骤什么是DFS?DFS指的是分布式文件系统(Distr

NFS实现多服务器文件的共享的方法步骤

《NFS实现多服务器文件的共享的方法步骤》NFS允许网络中的计算机之间共享资源,客户端可以透明地读写远端NFS服务器上的文件,本文就来介绍一下NFS实现多服务器文件的共享的方法步骤,感兴趣的可以了解一... 目录一、简介二、部署1、准备1、服务端和客户端:安装nfs-utils2、服务端:创建共享目录3、服

SpringBoot使用Apache Tika检测敏感信息

《SpringBoot使用ApacheTika检测敏感信息》ApacheTika是一个功能强大的内容分析工具,它能够从多种文件格式中提取文本、元数据以及其他结构化信息,下面我们来看看如何使用Ap... 目录Tika 主要特性1. 多格式支持2. 自动文件类型检测3. 文本和元数据提取4. 支持 OCR(光学

Java内存泄漏问题的排查、优化与最佳实践

《Java内存泄漏问题的排查、优化与最佳实践》在Java开发中,内存泄漏是一个常见且令人头疼的问题,内存泄漏指的是程序在运行过程中,已经不再使用的对象没有被及时释放,从而导致内存占用不断增加,最终... 目录引言1. 什么是内存泄漏?常见的内存泄漏情况2. 如何排查 Java 中的内存泄漏?2.1 使用 J

JAVA系统中Spring Boot应用程序的配置文件application.yml使用详解

《JAVA系统中SpringBoot应用程序的配置文件application.yml使用详解》:本文主要介绍JAVA系统中SpringBoot应用程序的配置文件application.yml的... 目录文件路径文件内容解释1. Server 配置2. Spring 配置3. Logging 配置4. Ma

Golang的CSP模型简介(最新推荐)

《Golang的CSP模型简介(最新推荐)》Golang采用了CSP(CommunicatingSequentialProcesses,通信顺序进程)并发模型,通过goroutine和channe... 目录前言一、介绍1. 什么是 CSP 模型2. Goroutine3. Channel4. Channe

2.1/5.1和7.1声道系统有什么区别? 音频声道的专业知识科普

《2.1/5.1和7.1声道系统有什么区别?音频声道的专业知识科普》当设置环绕声系统时,会遇到2.1、5.1、7.1、7.1.2、9.1等数字,当一遍又一遍地看到它们时,可能想知道它们是什... 想要把智能电视自带的音响升级成专业级的家庭影院系统吗?那么你将面临一个重要的选择——使用 2.1、5.1 还是

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

C#使用yield关键字实现提升迭代性能与效率

《C#使用yield关键字实现提升迭代性能与效率》yield关键字在C#中简化了数据迭代的方式,实现了按需生成数据,自动维护迭代状态,本文主要来聊聊如何使用yield关键字实现提升迭代性能与效率,感兴... 目录前言传统迭代和yield迭代方式对比yield延迟加载按需获取数据yield break显式示迭

Python实现高效地读写大型文件

《Python实现高效地读写大型文件》Python如何读写的是大型文件,有没有什么方法来提高效率呢,这篇文章就来和大家聊聊如何在Python中高效地读写大型文件,需要的可以了解下... 目录一、逐行读取大型文件二、分块读取大型文件三、使用 mmap 模块进行内存映射文件操作(适用于大文件)四、使用 pand