免费公司主页网站,php网站开发简历,专门做网站公司,简单的企业网站模板简介 2024年5月30号Spring AI 的 1.0.0 里程碑 1 版本发布。表明版本已正在巩固#xff0c;并且大部分主要错误和问题已经解决#xff0c;API基本已确定#xff0c;不会发生很大的变化。 在与大模型集成方面#xff0c;继LangChain4j之后#xff0c;又一重大的框架诞生。标…简介 2024年5月30号Spring AI 的 1.0.0 里程碑 1 版本发布。表明版本已正在巩固并且大部分主要错误和问题已经解决API基本已确定不会发生很大的变化。 在与大模型集成方面继LangChain4j之后又一重大的框架诞生。标志着在人工智能的浪潮中Java不会因此被边缘化让生成式人工智能应用程序不仅适用于Python也适用于Java。
Spring Ai官网Spring AI 前置准备 Spring Ai除了支持国外的大模型外也支持国内很多大模型比如清华的智普Ai百度的千帆和月之暗面的 kimi。集成Spring Ai需要用到 api-key大家按照自己的需要去Ai开放平台申请。 下面我主要用到OpenAi和智普Ai来讲解案例代码OpenAi是国外的需要我们要有个国外手机号亚洲很多被封了用不了登录OpenAi官网创建apikey需要用到魔法软件科学上网。下面给出各个注册渠道.
Open-AI: OpenAi-HK GPT4.0 API KEY By OPENAI HK 中转ChatGPT (本文用这种不用翻) AiCore API New API OpenAi购买平台 首页 | OpenAI_GPT4_购买平台_OpenAI API - eylink官网
ZhiPu-AI:
官网 智谱AI开放平台 概念和案例实践 新建SpringBoot工程然后添加以下依赖
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion3.2.4/version/parentmodelVersion4.0.0/modelVersiongroupIdorg.gorgor/groupIdartifactIdspring-ai-demo/artifactIdversion1.0-SNAPSHOT/versionpropertiesmaven.compiler.source17/maven.compiler.sourcemaven.compiler.target17/maven.compiler.targetproject.build.sourceEncodingUTF-8/project.build.sourceEncoding/propertiesdependencyManagementdependenciesdependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-bom/artifactIdversion1.0.0-M1/versiontypepom/typescopeimport/scope/dependency/dependencies/dependencyManagementdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-openai-spring-boot-starter/artifactId/dependencydependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-zhipuai-spring-boot-starter/artifactId/dependency/dependenciesrepositoriesrepositoryidspring-milestones/idnameSpring Milestones/nameurlhttps://repo.spring.io/milestone/urlsnapshotsenabledfalse/enabled/snapshots/repositoryrepositoryidspring-snapshots/idnameSpring Snapshots/nameurlhttps://repo.spring.io/snapshot/urlreleasesenabledfalse/enabled/releases/repository/repositories
/project 添加application.yml配置文件 需要配置智普api-key和openai api-key.
server:port: 10096
spring:application:name: ai-demoai:zhipuai:api-key: ${ZHIPUAI_API_KEY}chat:options:model: glm-3-turboembedding:enabled: falseopenai:api-key: ${OPENAI_API_KEY}base-url: https://api.openai-hk.comchat:options:model: gpt-4o-miniembedding:enabled: true 1. ChatClient 和 ChatModel ChatClient是SpringAI 0.8.0版本的概念到1.0.0版本变成了ChatModel但同时保留了ChatClientChatClient底层还是调用ChatModelChatClient支持Fluent ApiChatModel不支持。两者都是表示某个模型具体是什么模型需要看配置。 基于ChatClient 和 ChatModel 实现聊天效果
Configuration
public class ChatConfig {Autowiredprivate OpenAiChatModel openAiChatModel;Beanpublic ChatClient chatClient() {return ChatClient.builder(openAiChatModel).build();}
}
Controller层代码
RestController
public class ChatDemoController {Autowiredprivate ChatClient chatClient;Autowiredprivate ZhiPuAiChatModel chatModel;Autowiredprivate OpenAiChatModel openAiChatModel;/*** openAi 聊天** param message* return*/GetMapping(/ai/openAiChat)public Map openAiChat(RequestParam(value message, defaultValue Tell me a joke) String message) {return Map.of(generation, openAiChatModel.call(message));}/*** zhipuAi 聊天** param message* return*/GetMapping(/ai/generate)public Map generate(RequestParam(value message, defaultValue Tell me a joke) String message) {return Map.of(generation, chatModel.call(message));}/*** ChatClient使用(流式调用)* param message* param voice* return*/GetMapping(/ai/chatClient)MapString, String completion(RequestParam(value message, defaultValue Tell me a joke) String message, String voice) {return Map.of(completion,chatClient.prompt().system(sp - sp.param(voice, voice)).user(message).call().content());}
}
2. 文生图
RestController
public class ChatDemoController {Autowiredprivate OpenAiImageModel imageModel;/*** 图片生成(文生图)** param message* return*/GetMapping(/ai/imageGeneration)public Map imageGeneration(RequestParam(value message, defaultValue Tell me a joke) String message) {OpenAiImageOptions imageOptions OpenAiImageOptions.builder().withQuality(hd).withN(1).withHeight(1024).withWidth(1024).build();ImagePrompt imagePrompt new ImagePrompt(message, imageOptions);ImageResponse response imageModel.call(imagePrompt);return Map.of(generation, response.getResult().getOutput().getUrl());}
}
3. 多模态
多模态Multimodal指的是数据或信息的多种表现形式。在人工智能领域我们经常会听到这个词尤其是在近期大型模型如GPT-4开始支持多模态之后。 模态模态是指数据的一种形式例如文本、图像、音频等。每一种形式都是一种模态。多模态多模态就是将不同模态的数据结合起来以更全面、更丰富的方式来处理信息。比如我们可以同时处理文本、图像、语音等多种类型的数据。
举个例子如果我想告诉你“我有一个苹果”我可以用文字写出来也可以用语言说出来还可以用图片画出来。这就是相同信息的多种模态表现形式。
同样地给大模型一副图片可以上大模型对这张图片进行详细地描述。给大模型一段文本可以让大模型进行概要提取内容总结等。
RestController
public class ChatDemoController {Autowiredprivate OpenAiChatModel openAiChatModel;/*** 多模态** param message* return* throws MalformedURLException*/GetMapping(/ai/multimodal)public String Multimodal(RequestParam(value message, defaultValue 解释一下你在这张图片上看到了什么?) String message) throws MalformedURLException {var userMessage new UserMessage(message,List.of(new Media(MimeTypeUtils.IMAGE_PNG,new URL(https://docs.spring.io/spring-ai/reference/1.0-SNAPSHOT/_images/multimodal.test.png))));ChatResponse response openAiChatModel.call(new Prompt(List.of(userMessage),OpenAiChatOptions.builder().withModel(OpenAiApi.ChatModel.GPT_4_O.getValue()).build()));return response.getResult().getOutput().getContent();}
}
4. 语音转文字 语音文件需要在spring-ai中下载spring-ai/models/spring-ai-openai/src/test/resources/speech at main · spring-projects/spring-ai · GitHubAn Application Framework for AI Engineering. Contribute to spring-projects/spring-ai development by creating an account on GitHub.https://github.com/spring-projects/spring-ai/tree/main/models/spring-ai-openai/src/test/resources/speech
RestController
public class ChatDemoController {Autowiredprivate OpenAiAudioTranscriptionModel openAiAudioTranscriptionModel;Value(classpath:/speech/jfk.flac)private Resource audioFile;/*** 语音转文字*/GetMapping(/ai/audioTranscription)private String audioTranscription(){OpenAiAudioTranscriptionOptions transcriptionOptions OpenAiAudioTranscriptionOptions.builder().withResponseFormat(OpenAiAudioApi.TranscriptResponseFormat.TEXT).withTemperature(0f).build();AudioTranscriptionPrompt transcriptionRequest new AudioTranscriptionPrompt(audioFile, transcriptionOptions);AudioTranscriptionResponse response openAiAudioTranscriptionModel.call(transcriptionRequest);return response.getResult().getOutput();}
}
5. Function Calling 工具调用 大模型是基于历史数据进行训练的,回答我们的问题也是基于历史数据进行回复, 如果你想要大模型具备获取最新消息的能力, 此时,就需要用到工具机制,它能帮助大模型获取最新的数据消息.
Function Calling 工作原理图: 执行流程如下图 首先当我们发送问题给大模型的时候比如“今天是几号”大模型会响应一个结果给我们这个结果不是问题的答案而是大模型告诉我们需要执行哪个工具。我们执行工具后才能得到问题的答案但这个答案可能不太像人回复的不太符合自然语言的样子比如工具结果是“2024-07-13 11:23:00”此时我们需要把问题执行工具请求和工具执行结果一起发给大模型得到最好的答案。
工具定义:
实现 java.util.function.Function 接口 Description注解: 注释是可选的它提供了一个函数描述帮助模型理解何时调用函数。它是一个重要的属性可以帮助AI模型确定要调用的客户端函数。 JsonClassDescription注解: 对方法进行描述. JsonPropertyDescription注解: 对参数进行描述. 代码实现:
Component
Description(先获取指定地点,再获取当前时间)
public class DateService implements FunctionDateService.Request, DateService.Response {JsonClassDescription(地点请求)public record Request(JsonPropertyDescription(地点)String address) { }public record Response(String date) { }Overridepublic Response apply(Request request) {System.out.println(request.address);return new Response(String.format(%s的当前时间是%s, request.address, LocalDateTime.now()));}
}
工具调用:
RestController
public class ChatDemoController {Autowiredprivate OpenAiChatModel openAiChatModel;/*** 工具调用*/GetMapping(/ai/function)public String function(RequestParam String message) {Prompt prompt new Prompt(message, OpenAiChatOptions.builder().withFunction(dateService).build());
// Prompt prompt new Prompt(message, OpenAiChatOptions.builder().withFunctionCallbacks(
// List.of(FunctionCallbackWrapper.builder(new DateService())
// .withName(dateService)
// .withDescription(获取指定地点的当前时间).build())
// ).build());Generation generation openAiChatModel.call(prompt).getResult();return (generation ! null) ? generation.getOutput().getContent() : ;}
}
6. Embeddings文本向量化 什么叫向量? 向量可以理解为平面坐标中的一个坐标点(x,y),在编程领域一个二维向量就是一个大小为float类型的数组。也可以用三维坐标系中的向量表示一个空间中的点. 而文本向量化是指利用大模型可以把一个字一个词或一段话映射为一个多维向量. 为什么要向量化? 当我们把所有的文本生成向量后, 就可以利用向量的特点,进行相似度搜索.这种搜索算法比elasticsearch的分词算法更好.
Spring AI 支持的向量数据库 Azure Vector Search - The Azure vector store. Apache Cassandra - The Apache Cassandra vector store. Chroma Vector Store - The Chroma vector store. Elasticsearch Vector Store - The Elasticsearch vector store. GemFire Vector Store - The GemFire vector store. Milvus Vector Store - The Milvus vector store. MongoDB Atlas Vector Store - The MongoDB Atlas vector store. Neo4j Vector Store - The Neo4j vector store. PgVectorStore - The PostgreSQL/PGVector vector store. Pinecone Vector Store - PineCone vector store. Qdrant Vector Store - Qdrant vector store. Redis Vector Store - The Redis vector store. SAP Hana Vector Store - The SAP HANA vector store. Weaviate Vector Store - The Weaviate vector store. SimpleVectorStore - A simple implementation of persistent vector storage, good for educational purposes.
以下我们使用Redis作为向量数据库
然后需要注意的是普通的Redis是不支持向量存储和查询的需要额外的redisearch模块我这边是直接使用docker来运行一个带有redisearch模块的redis容器的命令为
docker run -p 6379:6379 redis/redis-stack-server:latest
注意端口6379不要和你现有的Redis冲突了。
引入redis依赖 dependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-redis-store/artifactId/dependencydependencygroupIdredis.clients/groupIdartifactIdjedis/artifactIdversion5.1.0/version/dependency 定义向量模型和Redis向量数据库 Bean
Configuration
public class RedisConfig {Autowiredprivate EmbeddingModel openAiEmbeddingModel;Beanpublic RedisVectorStore vectorStore() {RedisVectorStore.RedisVectorStoreConfig config RedisVectorStore.RedisVectorStoreConfig.builder().withURI(redis://127.0.0.1:6379)
// .withIndexName(rag_index)
// .withPrefix(rag:).withMetadataFields(RedisVectorStore.MetadataField.text(filename),RedisVectorStore.MetadataField.text(question)).build();return new RedisVectorStore(config, openAiEmbeddingModel,true);}Beanpublic EmbeddingModel openAiEmbeddingModel() {// Can be any other EmbeddingModel implementation.return new OpenAiEmbeddingModel(new OpenAiApi(System.getenv(OPENAI_API_KEY)));}
} 定义向量存储和搜索核心逻辑代码
文本读取解析和存储SpringAi提供了以下核心概念
Document
DocumentReader用来读取TXT、PDF等文件内容 JsonReader读取JSON格式的文件 TextReader读取txt文件PagePdfDocumentReader使用Apache PdfBox读取PDF文件TikaDocumentReader使用Apache Tika来读取PDF, DOC/DOCX, PPT/PPTX, and HTML等文件DocumentTransformer用来解析文件内容 tokenTextSplitter按照token进行解析。 DocumentWriter用来写入文件内容到向量数据库 VectorStoreDocumentWriter的子类。
流程如下 /**
*
*文本解析
*/
public class CustomerTextSplitter extends TextSplitter {Overrideprotected ListString splitText(String text) {return List.of(split(text));}public String[] split(String text) {return text.split(\\s*\\R\\s*\\R\\s*);}
}
Component
public class DocumentService {Value(classpath:meituan-qa.txt)private Resource resource;Autowiredprivate RedisVectorStore vectorStore;/*** 向量存储* return*/public ListDocument loadText() {//文本读取TextReader textReader new TextReader(resource);textReader.getCustomMetadata().put(filename, meituan-qa.txt);ListDocument documents textReader.get();CustomerTextSplitter customerTextSplitter new CustomerTextSplitter();ListDocument list customerTextSplitter.apply(documents);// 把问题存到元数据中list.forEach(document - document.getMetadata().put(question, document.getContent().split(\\n)[0]));// 向量存储文本存储vectorStore.add(list);return list;}/*** 向量搜索* param message* return*/public ListDocument search(String message) {ListDocument documents vectorStore.similaritySearch(message);return documents;}/*** 元数据搜索* param message* param question* return*/public ListDocument metadataSearch(String message, String question) {return vectorStore.similaritySearch(SearchRequest.query(message)
// .withTopK(5).withSimilarityThreshold(0.1).withFilterExpression(String.format(question in [%s], question)));}
} 需要向量的文本 meituan-qa.txt
Q在线支付取消订单后钱怎么返还
订单取消后款项会在一个工作日内直接返还到您的美团账户余额。Q怎么查看退款是否成功
退款会在一个工作日之内到美团账户余额可在“账号管理——我的账号”中查看是否到账。Q美团账户里的余额怎么提现
余额可到美团网meituan.com——“我的美团→美团余额”里提取到您的银行卡或者支付宝账号另外余额也可直接用于支付外卖订单限支持在线支付的商家。Q余额提现到账时间是多久
1-7个工作日内可退回您的支付账户。由于银行处理可能有延迟具体以账户的到账时间为准。Q申请退款后商家拒绝了怎么办
申请退款后如果商家拒绝此时回到订单页面点击“退款申诉”美团客服介入处理。Q怎么取消退款呢
请在订单页点击“不退款了”商家还会正常送餐的。Q前面下了一个在线支付的单子由于未付款订单自动取消了这单会计算我的参与活动次数吗
不会。如果是未支付的在线支付订单可以先将订单取消如果不取消需要15分钟后系统自动取消订单无效后此时您再下单仍会享受活动的优惠。Q为什么我用微信订餐却无法使用在线支付
目前只有网页版和美团外卖手机App(非美团手机客户端)订餐才能使用在线支付请更换到网页版和美团外卖手机App下单。Q如何进行付款
美团外卖现在支持货到付款与在线支付其中微信版与手机触屏版暂不支持在线支付。 Controller层代码实现
RestController
public class ChatDemoController {Autowiredprivate DocumentService documentService;/*** 向量存储*/GetMapping(/ai/vectorStore)public Map vectorStore() {ListDocument documents documentService.loadText();return Map.of(generation, documents);}/*** 向量搜索* param message* return*/GetMapping(/ai/documentSearch)public ListDocument documentSearch(RequestParam String message) {return documentService.search(message);}/*** 元数据搜索* param message* param question* return*/GetMapping(/ai/metadataSearch)public ListDocument documentMetadataSearch(RequestParam String message, RequestParam String question) {return documentService.metadataSearch(message, question);}
}
7. RAG 检索增强生成 RAG是什么检索增强生成又是什么意思大模型的知识仅限于它所训练的数据如果你问大模型你们公司的xxx产品有什么作用大模型肯定会回答不出来。如果你想让大模型拥有你们公司知识库的数据 此时就可以用到RAG。 简单的讲RAG的原理是根据用户输入的问题先从你们公司的知识库查询出答案再把用户输的问题和搜索出来的答案让大模型根据我们的答案回复用户的问题。 而根据用户问题从知识库搜索问题需要用到上面所说的文本向量化。根据文本的相识度从知识库中搜索出符合用户问题的答案出来。 RAG的工作原理
RAG的工作原理可以分为以下几个步骤
1.接收请求首先系统接收到用户的请求例如提出一个问题。
2.信息检索R)系统从一个大型文档库中检索出与查询最相关的文档片段。这一步的目标是找到那些可能包含答案或相关信息的文档。
3.生成增强A将检索到的文档片段与原始查询一起输入到大模型如chatGPT中注意使用合适的提示词比如原始的问题是XXX检索到的信息是YYY给大模型的输入应该类似于请基于YYY回答XXXX。
4.输出生成G)大模型基于输入的查询和检索到的文档片段生成最终的文本答案并返回给用户。
RAG代码实现
RestController
public class ChatDemoController {Autowiredprivate OpenAiChatModel openAiChatModel;Autowiredprivate DocumentService documentService;/*** RAG* param message* return*/GetMapping(/ai/customerService)public String customerService(RequestParam String message) {// 向量搜索ListDocument documentList documentService.search(message);// 提示词模板PromptTemplate promptTemplate new PromptTemplate({userMessage}\n\n 用以下信息回答问题:\n {contents});// 组装提示词Prompt prompt promptTemplate.create(Map.of(userMessage, message, contents, documentList));// 调用大模型return openAiChatModel.call(prompt).getResult().getOutput().getContent();}
} 8. Advisor机制 Advisor是Spring AOP中的概念, 一个Advisor表示一个切面, 由Advice和PointCut组成,Advice表示切面的逻辑, PointCut表示切点, 也就是切那些方法.而Spring AI也用了Advisor的设计思想, 也具备前置切面和后置切面.
8.1 QuestionAnswerAdvisor
QuestionAnswerAdvisor的作用是对问题请求进行增强增强逻辑为
根据原始问题进行相似度搜索得到匹配知识点拼接RAG提示词模板
评估模型代码如下
RestController
public class ChatDemoController {Autowiredprivate ChatClient chatClient;Autowiredprivate RedisVectorStore vectorStore;Autowiredprivate OpenAiChatModel chatModel;/*** 模型评估*/GetMapping(/ai/evaluation)public EvaluationResponse evaluation(String message) {//RAGChatResponse response chatClient.prompt().advisors(new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults())).user(message).call().chatResponse();// 评估器var relevancyEvaluator new RelevancyEvaluator(ChatClient.builder(chatModel));// 评估请求EvaluationRequest evaluationRequest new EvaluationRequest(message,(ListContent) response.getMetadata().get(QuestionAnswerAdvisor.RETRIEVED_DOCUMENTS), response);// 评估结果EvaluationResponse evaluationResponse relevancyEvaluator.evaluate(evaluationRequest);return evaluationResponse;}
} 后续Spring AI会根据增强后的请求进行提示词模版的变量填充得到请求最终的提示词并将请求发送给大模型得到大模型的返回结果QuestionAnswerAdvisor也会对返回结果进行增强会把匹配的知识点放入ChatResponse的metadata中。
8.2 MessageChatMemoryAdvisor 是一种Advisor也是用来增强问答请求和响应的而其中另外一个概念就是ChatMemory默认实现为InMemoryChatMemory它可以用来按conversationId进行历史对话记录的存储。
RestController
public class ChatDemoController {Autowiredprivate ChatClient chatClient;private InMemoryChatMemory chatMemory new InMemoryChatMemory();/*** ChatMemory*/GetMapping(/ai/chatMemory)private String chatMemory(String message,String userId){ChatResponse response chatClient.prompt().advisors(new MessageChatMemoryAdvisor(chatMemory,userId,100)).system(sp - sp.param(voice, 律师)).user(message).call().chatResponse();return response.getResult().getOutput().getContent();}
}因此MessageChatMemoryAdvisor的作用就是将原始请求和向量添加到ChatMemory中。
8.3 PromptChatMemoryAdvisor 也是用来记录历史对话记录的和MessageChatMemoryAdvisor的不同点在于MessageChatMemoryAdvisor是把每个历史请求和响应封装为Message增强到请求中而PromptChatMemoryAdvisor是把所有请求和响应也会存到ChatMemory中但是会把所有内容合并一条Message增强到请求中。
8.4 VectorStoreChatMemoryAdvisor 这个就更加强大了它既会进行RAG也会把存储历史对话只不过会把对话记录封装为Document存到向量数据库中。