赞
踩
本文所使用的环境如下
Win10 + JDK17 + SpringBoot3.2.4
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.4</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.whiteBrocade</groupId> <artifactId>ai-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>ai-demo</name> <description>ai-demo</description> <url/> <licenses> <license/> </licenses> <developers> <developer/> </developers> <scm> <connection/> <developerConnection/> <tag/> <url/> </scm> <properties> <java.version>17</java.version> <spring-ai.version>1.0.0-M1</spring-ai.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--热部署插件--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--hutool--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.26</version> </dependency> <!-- Open AI--> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai-spring-boot-starter</artifactId> </dependency> <!-- ollama AI--> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-ollama-spring-boot-starter</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-bom</artifactId> <version>${spring-ai.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build> <repositories> <!-- 这里指定了Srping的仓库, 因为现在市面上的Mvaven仓库还没有Spring-ai模块, 例如阿里云, 腾讯云等等都是下载不到的--> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> </project>
spring: # 代码中的配置会覆盖yaml中相关AI参数配置 ai: openai: # Api-Key, 没有的可以去淘宝搜索购买, 替换成你自己的key api-key: sk-xxxxxxxxx chat: options: # 模型, 默认为gpt-3.5-turbo,目前这个代理api支持以下模型: # gpt-3.5-turbo, gpt-3.5-turbo-0301, gpt-3.5-turbo-0613, gpt-3.5-turbo-0125, gpt-3.5-turbo-16k # gpt-3.5-turbo-1706, gpt-3.5-turbo-16k-0613, text-embedding-3-small, text-embedding-3-large model: gpt-3.5-turbo # 温度 temperature: 0.4 # 直连地址/代理地址 # 切换成你自己的地址 base-url: https://xxxx.com
import lombok.Data; import org.springframework.ai.chat.messages.Message; import java.util.Date; /** * @author whiteBrocade * @description: 通用的Message抽象对象 */ @Data public class AiMessage { /** * id */ private Long id; /** * 用户id */ private Long userId; /** * 角色: user/assistant */ private String role; /** * AI类型: ollama, openai */ private String type; /** * 创建时间 */ private Date createTime; /** * message内容 */ private Message message; }
import cn.hutool.core.collection.BoundedPriorityQueue; import cn.hutool.core.date.DateUtil; import cn.hutool.core.text.StrBuilder; import cn.hutool.core.util.RandomUtil; import com.whitebrocade.aidemo2.domain.AiMessage; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.ai.chat.messages.AssistantMessage; import org.springframework.ai.chat.messages.Message; import org.springframework.ai.chat.messages.SystemMessage; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.openai.OpenAiChatModel; import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Flux; import java.util.Date; import java.util.List; @Slf4j @RestController @RequestMapping("/openai") public class OpenaiController { /** * Open AI 聊天模型 */ @Resource private OpenAiChatModel openAiChatModel; /** * 同步方式实现聊天功能 * * @param prompt 提示词 * @return 聊天结果 */ @PostMapping("/chat") public String chat(String prompt) { String ret = openAiChatModel.call(prompt); log.info(ret); return ret; } /** * 同步方式实现聊天功能 * * @param prompt 提示词 * @return 聊天结果 */ @PostMapping("/chat2") public String chat2(String prompt) { ChatResponse chatResponse = openAiChatModel.call(new Prompt(prompt)); String ret = chatResponse.getResult().getOutput().getContent(); log.info(ret); return ret; } /** * OpenAiChatOptions.builder() 传入的一个参数, 可以控制大模型的设置 * 参数可以再代码中配置, 也可以在文件中配置, 如果代码中写了关于gpt的参数, 配置文件中也配置了参数, 那么以代码中为主 * @param prompt 提示词 * @return 聊天结果 */ @PostMapping("/chat3") public Object chat3(String prompt){ ChatResponse chatResponse = openAiChatModel.call(new Prompt(prompt, OpenAiChatOptions.builder() //.withModel("gpt-4-32k") // gpt的版本 , 32K是参数, 参数越高, 回答问题越准确 .withTemperature(0.4F) // 温度值, 温度越高, 回答的准确率越低, 温度越低, 回答的准确率越高 .build())); String ret = chatResponse.getResult().getOutput().getContent(); log.info(ret); return ret; } /*** * 流式方式实现聊天功能 * @param prompt 提示词 * @return 聊天结果流 */ @PostMapping(value = "/stream1", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux<String> stream1(String prompt) { return openAiChatModel.stream(prompt); } /** * 对话上下文轮数 */ private final int limit = 2; /** * 有界队列, 这里限2条信息, 并且删除最先发送的那条消息 */ private final BoundedPriorityQueue<AiMessage> messageQueue = new BoundedPriorityQueue<>(limit * 2, (o1, o2) -> -(DateUtil.compare(o1.getCreateTime(), o2.getCreateTime()))); // 初始化java角色 { // 系统前置消息 Message systemMessage = new SystemMessage("你是一个Java行业的专家, 现在根据我的提问进行相关解答"); AiMessage aiMessage = new AiMessage(); aiMessage.setId(RandomUtil.randomLong()); aiMessage.setUserId(1L); aiMessage.setRole(OpenAiApi.ChatCompletionMessage.Role.SYSTEM.name()); aiMessage.setType("openai"); aiMessage.setCreateTime(new Date()); aiMessage.setMessage(systemMessage); messageQueue.offer(aiMessage); } /** * 流式方式实现聊天功能 * @param prompt 提示词 * @return 聊天结果流 */ @PostMapping(value = "/stream2", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux<String> stream2(String prompt){ // 构造用户回答 UserMessage userMessage = new UserMessage(prompt); AiMessage userAiMessage = new AiMessage(); userAiMessage.setId(RandomUtil.randomLong()); userAiMessage.setUserId(1L); userAiMessage.setRole("user"); userAiMessage.setType("openai"); userAiMessage.setCreateTime(new Date()); userAiMessage.setMessage(userMessage); messageQueue.offer(userAiMessage); List<Message> messageList = messageQueue.stream() .map(AiMessage::getMessage) .toList(); // 模型填参 Flux<ChatResponse> flux = openAiChatModel.stream(new Prompt(messageList, OpenAiChatOptions.builder() //.withModel("gpt-4-32k") //gpt的版本 ,32K是参数,参数越高,回答问题越准确 .withTemperature(0.4F) //温度值,温度越高,回答的准确率越低,温度越低,回答的准确率越高 .build())); // strBuilder用于追加AI的回答 StrBuilder strBuilder = StrBuilder.create(); return flux.map(response -> { String content = response.getResult().getOutput().getContent(); if (content != null) { strBuilder.append(content); return content; } else { // null表示结束, 此时我们返回"", 前端判断返回结果是否为"" return ""; } }).doOnComplete(() -> { AssistantMessage assistantMessage = new AssistantMessage(strBuilder.toString()); AiMessage assistantAiMessage = new AiMessage(); assistantAiMessage.setId(RandomUtil.randomLong()); assistantAiMessage.setUserId(1L); assistantAiMessage.setRole("system"); assistantAiMessage.setType("openai"); assistantAiMessage.setCreateTime(new Date()); assistantAiMessage.setMessage(assistantMessage); messageQueue.offer(assistantAiMessage); log.info("Open AI模型响应结果: {}", strBuilder); log.info("执行完了"); }); } }
如果本地没下载和或者没有使用Ollama, 那么这里你得看看, 如果已经使用过了, 那么跳过过这里, 去直接看代码集成
去Ollama官网下载, 并按照, 需要说明的是Ollama并非是一个大模型, 而是一个大模型的管理, 类似于Docker一样的角色, 而大模型类似于镜像的角色
进入PowerShell命令行中输入以下命令
ollama -v
如果显示了版本, 那么就说明安装成功
此时不着急下载模型, Ollama默认会将模型存储如下位置
/var/lib/ollama/models
C:\ProgramData\Ollama\models
Windos(我用的是这个)由于ollama是默认存储在C盘, 所以修改一下模型存储位置, 修改步骤如下:
在环境变量中新增OLLAMA_MODELS
变量名, 注意了这个变量名一定不能变, 变量值指向你要存放的文件夹, 如下
重启电脑(不重启电脑不生效!), 然后本地下载的模型就自动迁移的到你配置的目录了!
ollama serve
: 启动
ollama list
: 查看所有可用模型
ollama run 模型名称
: 运行选定模型
ollama show 模型名称
: 来获取更详细的模型信息, 包括模型的描述、版本、大小等
ollama download 模型名称
: 下载模型
ollama update 模型名称
: 来更新已下载的模型
ollama rm 模型名称
ollama ps
: 查看正在运行的模型
这里先简单过一眼, 后续使用到会介绍
点击Models
进入模型下载页面
搜索阿里的千问2的模型
选择0.5b的参数的模型
这里的b是指模型的训练的参数量, 1b=1亿参数, 参数越多, AI模型越智能, 对应的硬盘越大, 所需要的GPU和内存要求越高, 所以此处选择0.5的, 不懵逼, 不伤脑
复制此命令到, 命令行中执行, 然后ollama就会下载该模型, 耐心等待即可, 下载完成会运行该模型
直接输入你的问题即可, Ctrl + D退出模型对话
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.4</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.whiteBrocade</groupId> <artifactId>ai-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>ai-demo</name> <description>ai-demo2</description> <url/> <licenses> <license/> </licenses> <developers> <developer/> </developers> <scm> <connection/> <developerConnection/> <tag/> <url/> </scm> <properties> <java.version>17</java.version> <spring-ai.version>1.0.0-M1</spring-ai.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--热部署插件--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--hutool--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.26</version> </dependency> <!-- Open AI--> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai-spring-boot-starter</artifactId> </dependency> <!-- ollama AI--> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-ollama-spring-boot-starter</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-bom</artifactId> <version>${spring-ai.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build> <repositories> <!-- 这里指定了Srping的仓库, 因为现在市面上的Mvaven仓库还没有Spring-ai模块, 例如阿里云, 腾讯云等等都是下载不到的--> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> </project>
spring:
# 代码中的配置会覆盖yaml中相关AI参数配置
ai:
ollama:
chat:
options:
# 注意了, ollama中要有这个模型
model: qwen:0.5b
temperature: 0.4
# 直连地址/代理地址
# 这里填的是我本地的ollama的启动地址,
base-url: http://localhost:11434
import cn.hutool.core.text.StrBuilder; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.ai.chat.messages.AssistantMessage; import org.springframework.ai.chat.messages.Message; import org.springframework.ai.chat.messages.SystemMessage; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.ollama.OllamaChatModel; import org.springframework.ai.ollama.api.OllamaOptions; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Flux; import java.util.ArrayList; import java.util.List; /** * @author whiteBrocade * @description: OllamaController */ @Slf4j @RestController @RequestMapping("/ollama") public class OllamaController { @Resource private OllamaChatModel ollamaChatModel; /** * 一次性聊天, 不会记录上下文 * @param prompt 提示词 * @return */ @PostMapping(value = "/chat1") public Object chat1(String prompt) { String ret = ollamaChatModel.call(prompt); log.info(ret); return ret; } /** * 这里可以将消息存入MySQL */ private final List<Message> messageList = new ArrayList<>(); { // 系统前置消息 Message systemMessage = new SystemMessage("你是一个Java行业的专家, 现在根据我的提问进行相关解答"); messageList.add(systemMessage); } /** * 一次性聊天, 不会记录上下文 * @param prompt 提示词 * @return */ @RequestMapping(value = "/chat2") public Object chat2(String prompt) { Message userMessage = new UserMessage(prompt); messageList.add(userMessage); ChatResponse chatResponse = ollamaChatModel.call(new Prompt(messageList)); String content = chatResponse.getResult().getOutput().getContent(); log.info(content); return content; } /** * 流式方式实现聊天功能 * @param prompt 提示词 * @return 聊天结果流 */ @PostMapping(value = "/stream1", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux<String> stream1(String prompt) { return ollamaChatModel.stream(prompt); } /** * 流式方式实现聊天功能 * @param prompt 提示词 * @return 聊天结果流 */ @PostMapping(value = "/stream2", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux<String> stream2(String prompt) { UserMessage userMessage = new UserMessage(prompt); messageList.add(userMessage); Flux<ChatResponse> flux = ollamaChatModel.stream(new Prompt(messageList, OllamaOptions.create() .withTemperature(0.4F) //温度值,温度越高,回答的准确率越低,温度越低,回答的准确率越高 )); // sb用于追加AI的回答 StrBuilder strBuilder = StrBuilder.create(); return flux.map(response -> { String content = response.getResult().getOutput().getContent(); if (content != null) { strBuilder.append(content); return content; } else { // null表示结束, 此时我们返回"", 前端判断返回结果是否为"" return ""; } }).doOnComplete(() -> { AssistantMessage assistantMessage = new AssistantMessage(strBuilder.toString()); messageList.add(assistantMessage); log.info("ollama AI模型响应结果: {}", strBuilder); log.info("执行完了"); }); } }
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.whiteBrocade</groupId> <artifactId>ai-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>ai-demo</name> <description>ai-demo</description> <properties> <java.version>17</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <spring-boot.version>2.4.2</spring-boot.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--阿里AI的SDK--> <dependency> <groupId>com.alibaba</groupId> <artifactId>dashscope-sdk-java</artifactId> <version>2.15.0</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> </exclusion> </exclusions> </dependency> <!-- Reactor Core --> <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-core</artifactId> <version>3.4.6</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.26</version> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>17</source> <target>17</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring-boot.version}</version> <configuration> <mainClass>com.whitebrocade.aidemo.AiDemoApplication</mainClass> <skip>true</skip> </configuration> <executions> <execution> <id>repackage</id> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
spring: ai: qwen: # 义通千问的api-key, 没有的去阿里云申请 api-key: sk-xxxxxx # 模型 model: qwen-plus # 随机数种 seed: 1234 # 消耗的token数目 # 对于中文文本来说, 千问模型的1个token平均对应1.5-1.8个汉字;对于英文文本来说, 1个token通常对应一个单词或词根 maxTokens: 10 # 温度 temperature: 0.4 # 是否允许联网查询 enableSearch: true # 返回内容是否不需要追加, true不追加, false追加 incrementalOutput: true
import cn.hutool.core.text.StrBuilder; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import com.alibaba.dashscope.aigc.generation.Generation; import com.alibaba.dashscope.aigc.generation.GenerationParam; import com.alibaba.dashscope.aigc.generation.GenerationResult; import com.alibaba.dashscope.aigc.generation.GenerationUsage; import com.alibaba.dashscope.common.Message; import com.alibaba.dashscope.common.Role; import com.alibaba.dashscope.exception.InputRequiredException; import com.alibaba.dashscope.exception.NoApiKeyException; import io.reactivex.Flowable; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.ArrayList; import java.util.Collections; import java.util.List; @Slf4j @RestController @RequestMapping("/qwen") public class QwenController { /** * 随机数种 */ @Value("${spring.ai.qwen.seed}") private Integer seed; /** * AI模型 */ @Value("${spring.ai.qwen.model}") private String model; /** * AI密钥 */ @Value("${spring.ai.qwen.api-key}") private String apiKey; /** * 生成最大的token */ @Value("${spring.ai.qwen.maxTokens}") private Integer maxTokens; /** * 温度 */ @Value("${spring.ai.qwen.temperature}") private Float temperature; /** * 是否联网 */ @Value("${spring.ai.qwen.enableSearch}") private boolean enableSearch; /** * 返回内容是否不需要追加 */ @Value("${spring.ai.qwen.incrementalOutput}") private boolean incrementalOutput; /** * AI生成对象 */ private final Generation generation = new Generation(); // -------------------------- 方法 -------------------------- /** * 单轮对话 * * @param prompt 提示词 * @return 返回结果 */ @PostMapping(value = "/chat") public String chat(String prompt) { try { // 用户与模型的对话历史。list中的每个元素形式为{“role”:角色, “content”: 内容}。 Message userMessage = this.buildMessage(Role.USER, prompt); // 填充参数 GenerationParam param = this.getBaseGenerationParam() .messages(Collections.singletonList(userMessage)) .build(); GenerationResult generationResult = generation.call(param); log.info("千问输出结果:{}", JSONUtil.toJsonStr(generationResult)); return generationResult.getOutput().getChoices().get(0).getMessage().getContent(); } catch (Exception e) { log.error(e.getMessage()); throw new RuntimeException(e); } } /** * message存储, 这里模拟数据查询出来的Message集合 */ private final List<Message> messageList = new ArrayList<>(); { // 初始化系统角色 Message systemMsg = Message.builder() .role(Role.ASSISTANT.getValue()) .content("你是Java高级工程师, 现在根据我的提问进行回答") // 初始化系统角色 .build(); messageList.add(systemMsg); } /** * 流式单论对话 * * @param prompt 提示词 * @return 返回结果 */ @PostMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flowable<String> stream(String prompt) throws NoApiKeyException, InputRequiredException { // 用户与模型的对话历史。list中的每个元素形式为{"role":角色, "content": 内容}。 Message userMessage = this.buildMessage(Role.USER, prompt); messageList.add(userMessage); // 填充参数 GenerationParam param = this.getBaseGenerationParam() .messages(messageList) .build(); Flowable<GenerationResult> flux = generation.streamCall(param); return flux.map(generationResult -> { Message repMessage = generationResult.getOutput().getChoices().get(0).getMessage(); log.info("千问模型响应结果, 角色:{}, 内容: {}", repMessage.getRole(), repMessage.getContent()); String content = repMessage.getContent(); return content; }).doOnComplete(() -> { log.info("结果响应完了"); }).doOnError(e -> { log.error("结果响应发生异常"); throw new RuntimeException(e); }); } /** * 流式单论对话, 当相应内容完成后, 返回"" * * @param prompt 多轮对话提示词 * @return 返回结果 */ @PostMapping(value = "/stream2", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flowable<String> stream2(String prompt) throws NoApiKeyException, InputRequiredException { // 初始化用户信息 Message userMessage = this.buildMessage(Role.USER, prompt); // 支持对话轮数 if (messageList.size() == 7) { messageList.remove(0); } messageList.add(userMessage); // 填充参数 GenerationParam param = this.getBaseGenerationParam() .messages(messageList) .build(); // 流式返回 Flowable<GenerationResult> flux = generation.streamCall(param); // 响应的消息 StrBuilder strBuilder = new StrBuilder(); return flux.map(generationResult -> { // token消耗情况 GenerationUsage usage = generationResult.getUsage(); Integer inputTokens = usage.getInputTokens(); Integer outputTokens = usage.getOutputTokens(); Integer totalTokens = usage.getTotalTokens(); log.info("输入token: {}, 输出token: {}, 总token: {}", inputTokens, outputTokens, totalTokens); Message assistantMessage = generationResult.getOutput().getChoices().get(0).getMessage(); String role = assistantMessage.getRole(); String content = assistantMessage.getContent(); if (StrUtil.isNotEmpty(content)) { strBuilder.append(content); log.info("千问模型响应结果, 角色: {}, 内容: {}", role, content); } return content; }).doOnComplete(() -> { // 添加assistant返回到messages列表,user/assistant消息必须交替出现 if (messageList.size() == 7) { messageList.remove(0); } // 将响应消息添加到集合中 Message assistantMessage = Message.builder() .role(Role.ASSISTANT.getValue()) .content(strBuilder.toString()) .build(); messageList.add(assistantMessage); log.info("结果响应完了"); }).doOnError(e -> { log.error("结果响应发生异常"); throw new RuntimeException(e); }); } /** * 构建Message * @param role 角色 * @param content 内容 * @return 构建好的Message */ private Message buildMessage(Role role, String content) { return Message.builder() .role(role.getValue()) .content(content) .build(); }; /** * 构建公共param * * @return GenerationParam */ private GenerationParam.GenerationParamBuilder<?, ?> getBaseGenerationParam() { // 模型参数 return GenerationParam.builder() .seed(seed) // 随机数种 .model(model) // AI模型 .apiKey(apiKey) // Api Key .maxTokens(maxTokens) // 生成结果消耗的最大token值 .temperature(temperature) // 温度 .enableSearch(enableSearch) .incrementalOutput(incrementalOutput) // 后续输出不追加之前输出的内容 .resultFormat(GenerationParam.ResultFormat.MESSAGE); // 返回值信息 } }
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.whiteBrocade</groupId> <artifactId>ai-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>ai-demo</name> <description>ai-demo</description> <properties> <java.version>17</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <spring-boot.version>2.4.2</spring-boot.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- Reactor Core --> <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-core</artifactId> <version>3.4.6</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.26</version> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>17</source> <target>17</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring-boot.version}</version> <configuration> <mainClass>com.whitebrocade.aidemo.AiDemoApplication</mainClass> <skip>true</skip> </configuration> <executions> <execution> <id>repackage</id> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
spring: ai: qwen: # 义通千问的api-key, 没有的去阿里云申请 api-key: sk-xxxxxxx # 模型 model: qwen-plus # 随机数种 seed: 1234 # 消耗的token数目 maxTokens: 1000 # 温度 temperature: 0.4 # 是否允许联网查询 enableSearch: true # 返回内容是否不需要追加, true不追加, false追加 incrementalOutput: true # http请求地址 url: https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation
import com.alibaba.dashscope.aigc.generation.GenerationParam; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import lombok.Getter; import lombok.Setter; import java.io.Serializable; import java.util.List; /** * 千问请求参数 */ @Data public class QwenRequest implements Serializable { /** * AI模型 */ private String model; /** * message输入 */ private Input input; /** * 其它参数 */ private Parameters parameters; @Data public static class Input implements Serializable { private List<Message> messages; } @Data public static class Message implements Serializable { /** * 角色 */ private String role; /** * 内容 */ private String content; } /** * 参数 */ public static class Parameters implements Serializable { /** * 随机数种 */ @Getter @Setter @JsonProperty("seed") private Integer seed; /** * 限制模型生成token的数量 */ @Getter @Setter @JsonProperty("max_tokens") private Integer maxTokens; /** * 温度 */ @Getter @Setter @JsonProperty("temperature") private Float temperature; /** * 是否互联网搜索 */ @Getter @Setter @JsonProperty("enable_search") private boolean enableSearch; /** * 响应结果格式: text */ @Getter @JsonProperty("result_format") private String resultFormat = GenerationParam.ResultFormat.TEXT; } }
import com.alibaba.dashscope.aigc.generation.GenerationParam; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; import java.io.Serializable; /** * @author whiteBrocade * @description: 流式请求 */ @Data @EqualsAndHashCode(callSuper = true) public class QwenStreamRequest extends QwenRequest implements Serializable { public static class Parameters extends QwenRequest.Parameters implements Serializable { /** * 是否增量输出 */ @Getter @Setter @JsonProperty("incremental_output") private boolean incrementalOutput; /** * 响应结果格式: message */ @Getter @JsonProperty("result_format") private String resultFormat = GenerationParam.ResultFormat.MESSAGE; } }
import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import java.io.Serializable; /** * @author whiteBrocade * @description: 千问普通请求响应结果 */ @Data public class QwenBaseResponse implements Serializable { /** * 本次调用使用的token信息。 */ private Usage usage; /** * 本次请求的系统唯一码 */ @JsonProperty("request_id") private String requestId; @Data public static class Usage implements Serializable { /** * 本次对话消耗的token */ @JsonProperty("total_tokens") private int totalTokens; /** * 响应消耗的token */ @JsonProperty("output_tokens") private int outputTokens; /** * 请求消耗的token */ @JsonProperty("input_tokens") private int inputTokens; } }
package com.whitebrocade.aidemo.response; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; /** * @author whiteBrocade * @description: 千问普通请求响应结果 */ @Data @EqualsAndHashCode(callSuper = true) public class QwenResponse extends QwenBaseResponse implements Serializable { /** * 响应输出结果 */ private QwenResponse.Output output; /** * 响应输出结果 */ @Data public static class Output implements Serializable { /** * 结束原因 * 有三种情况: * 1. 正在生成时为null * 2. 生成结束时如果由于停止token导致则为stop * 3. 生成结束时如果因为生成长度过长导致则为length。当result_format设置为text时返回该字段 */ @JsonProperty("finish_reason") private String finishReason; /** * 响应结果文本 */ private String text; } }
import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; /** * @author whiteBrocade * @description: 流式响应结果 */ @Data @EqualsAndHashCode(callSuper = true) public class QwenStreamResponse extends QwenBaseResponse implements Serializable { /** * 响应输出结果 */ private QwenStreamResponse.Output output; /** * 响应输出结果 */ @Data public static class Output implements Serializable { /** * 响应结果 */ @JsonProperty("choices") private Choices[] choices; } /** * 响应结果 */ @Data public static class Choices implements Serializable { /** * 停止原因 * 1. null: 生成过程中 * 2. stop: stop token导致结束 * 3. length: 生成长度导致结束 */ @JsonProperty("finish_reason") private String finish_reason; /** * 信息 */ private Message message; } /** * message每个元素形式为{"role":角色, "content": 内容}。角色可选值:system、user、assistant。content为模型输出的内容 */ @Data public static class Message implements Serializable { /** * 角色 */ private String role; /** * 内容 */ private String content; } }
package com.whitebrocade.aidemo.web; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.text.StrBuilder; import cn.hutool.core.util.StrUtil; import cn.hutool.http.ContentType; import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpUtil; import com.alibaba.dashscope.common.Role; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.whitebrocade.aidemo.request.QwenRequest; import com.whitebrocade.aidemo.request.QwenStreamRequest; import com.whitebrocade.aidemo.response.QwenResponse; import com.whitebrocade.aidemo.response.QwenStreamResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Flux; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.util.List; /** * @author whiteBrocade * @version 1.0 * @date 2024/7/4 下午1:02 * @description: TODO */ @Slf4j @RestController @RequestMapping("/qwen/http") public class QwenHttpController { /** * 请求地址 */ @Value("${spring.ai.qwen.url}") private String url; /** * 随机数种 */ @Value("${spring.ai.qwen.seed}") private Integer seed; /** * AI模型 */ @Value("${spring.ai.qwen.model}") private String model; /** * AI密钥 */ @Value("${spring.ai.qwen.api-key}") private String apiKey; /** * 生成最大的token */ @Value("${spring.ai.qwen.maxTokens}") private Integer maxTokens; /** * 温度 */ @Value("${spring.ai.qwen.temperature}") private Float temperature; /** * 是否联网 */ @Value("${spring.ai.qwen.enableSearch}") private boolean enableSearch; /** * 返回内容是否不需要追加 */ @Value("${spring.ai.qwen.incrementalOutput}") private boolean incrementalOutput; // --------------------- 方法 --------------------- @PostMapping(value = "/chat") public String chat(String prompt) throws Exception { // 填充message // system message QwenRequest.Message systemMessage = new QwenRequest.Message(); systemMessage.setRole(Role.SYSTEM.getValue()); systemMessage.setContent("你是一个Java高级工程师"); // user message QwenRequest.Message userMessage = new QwenRequest.Message(); userMessage.setRole(Role.USER.getValue()); userMessage.setContent(prompt); List<QwenRequest.Message> messages = List.of(systemMessage, userMessage); QwenRequest qwenRequest = this.getQwenRequest(messages); // 转换成json ObjectMapper objectMapper = new ObjectMapper(); String reqJsonStr = objectMapper.writeValueAsString(qwenRequest); // 请求的str log.info("请求参数: {}", reqJsonStr); HttpRequest httpRequest = this.getHttpRequest() .body(reqJsonStr); // 请求体 String text; // 响应文本 try { String responseJsonStr = httpRequest.execute() // 发送请求 .body(); log.info("响应结果: {}", responseJsonStr); QwenResponse qwenResponse = objectMapper.readValue(responseJsonStr, QwenResponse.class); text = qwenResponse.getOutput().getText(); } catch (Exception e) { log.error("请求异常: {}", e.getMessage()); throw new RuntimeException(); } return text; } /** * 流式对话 * @param prompt 提示词 * @return 响应结果 */ @PostMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux<String> stream(String prompt) throws JsonProcessingException { // 填充message // system message QwenRequest.Message systemMessage = new QwenRequest.Message(); systemMessage.setRole(Role.SYSTEM.getValue()); systemMessage.setContent("你是一个Java高级工程师"); // user message QwenRequest.Message userMessage = new QwenRequest.Message(); userMessage.setRole(Role.USER.getValue()); userMessage.setContent(prompt); List<QwenRequest.Message> messages = List.of(systemMessage, userMessage); QwenStreamRequest qwenStreamRequest = this.getQwenStreamRequest(messages); // 转换成json ObjectMapper objectMapper = new ObjectMapper(); String reqJsonStr = objectMapper.writeValueAsString(qwenStreamRequest); // 请求的str log.info("请求参数: {}", reqJsonStr); HttpRequest streamHttpRequest = this.getStreamHttpRequest() .body(reqJsonStr); // 请求体 // try { // // // text = qwenResponse.getOutput().getText(); // } catch (Exception e) { // log.error("请求异常: {}", e.getMessage()); // throw new RuntimeException(); // } return Flux.create(sink -> { InputStream inputStream = streamHttpRequest.execute(true) // 异步调用 .bodyStream(); BufferedReader in = new BufferedReader(new InputStreamReader(inputStream)); try (inputStream) { StrBuilder strBuilder = StrBuilder.create(); String line; while ((line = in.readLine()) != null) { // 数据前缀 String prefix = "data:"; if (line.startsWith(prefix)) { // 截取数据 String responseJsonStr = StrUtil.subAfter(line.trim(), prefix, false); QwenStreamResponse qwenStreamResponse = objectMapper.readValue(responseJsonStr, QwenStreamResponse.class); // 内容 String content = qwenStreamResponse .getOutput() .getChoices()[0] .getMessage() .getContent(); strBuilder.append(content); // 发送每个响应片段 // 当为""的时候, 那么就就表示响应结束 sink.next(content); } } log.info("响应内容为: {}", strBuilder.toString()); // todo 这里可以讲响应内容保存到数据库中 // 完成流式传输 sink.complete(); } catch (Exception e) { // 发送错误信号 log.error("传输错误", e); sink.error(e); } }); } /** * 获取基本的QwenRequest * @return HttpRequest */ private HttpRequest getHttpRequest() { return HttpUtil.createPost(url) .contentType(ContentType.JSON.getValue()) // Content-Type .auth("Bearer " + apiKey); // Authorization } /** * 流式请求 * @return HttpRequest */ private HttpRequest getStreamHttpRequest() { return this.getHttpRequest() .header("X-DashScope-SSE", "enable"); } /** * 获取基本的QwenRequest * @param messages 消息 * @return QwenRequest */ private QwenRequest getQwenRequest(List<QwenRequest.Message> messages) { QwenRequest qwenRequest = new QwenRequest(); qwenRequest.setModel(model); // 模型 QwenRequest.Input input = new QwenRequest.Input(); input.setMessages(messages); qwenRequest.setInput(input); QwenRequest.Parameters parameters = new QwenRequest.Parameters(); parameters.setSeed(seed); parameters.setMaxTokens(maxTokens); parameters.setTemperature(temperature); parameters.setEnableSearch(enableSearch); qwenRequest.setParameters(parameters); return qwenRequest; } /** * 获取 QwenStreamRequest * @param messages 消息 * @return QwenStreamRequest */ private QwenStreamRequest getQwenStreamRequest(List<QwenRequest.Message> messages) { QwenRequest qwenRequest = this.getQwenRequest(messages); QwenStreamRequest qwenStreamRequest = new QwenStreamRequest(); qwenStreamRequest.setModel(qwenRequest.getModel()); qwenStreamRequest.setInput(qwenRequest.getInput()); QwenRequest.Parameters parameters = qwenRequest.getParameters(); QwenStreamRequest.Parameters tempparameters = new QwenStreamRequest.Parameters(); BeanUtil.copyProperties(parameters, tempparameters); // 设置增量输出 tempparameters.setIncrementalOutput(incrementalOutput); qwenStreamRequest.setParameters(tempparameters); return qwenStreamRequest; } }
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.whiteBrocade</groupId> <artifactId>ai-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>ai-demo</name> <description>ai-demo</description> <properties> <java.version>17</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <spring-boot.version>2.4.2</spring-boot.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--千帆-文心一言--> <dependency> <groupId>com.baidubce</groupId> <artifactId>qianfan</artifactId> <version>0.0.9</version> </dependency> <!-- Reactor Core --> <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-core</artifactId> <version>3.4.6</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.26</version> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>17</source> <target>17</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring-boot.version}</version> <configuration> <mainClass>com.whitebrocade.aidemo.AiDemoApplication</mainClass> <skip>true</skip> </configuration> <executions> <execution> <id>repackage</id> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
spring:
ai:
# 千帆
qianfan:
access-key: xxxxx
secret-key: xxxxxx
# 使用免费的模型, 免费的模型如下ERNIE-Speed-128K, ERNIE-Speed-8K, ERNIE Speed-AppBuilder, ERNIE-Lite-8K, ERNIE-Lite-8K-0922, ERNIE-Tiny-8K, Yi-34B-Chat, Fuyu-8B, Prompt模板
model: ERNIE-Speed-128K
# 输出结果影响因子
topP: 0.7
# 温度
temperature: 0.7
# 输出最大的token值
maxOutputTokens: 50
import com.baidubce.qianfan.Qianfan; import com.baidubce.qianfan.core.StreamIterator; import com.baidubce.qianfan.core.auth.Auth; import com.baidubce.qianfan.core.builder.ChatBuilder; import com.baidubce.qianfan.model.chat.ChatResponse; import com.baidubce.qianfan.model.constant.ChatRole; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Flux; /** * @author whiteBrocade * @version 1.0 * @date 2024/7/3 下午7:02 * @description: TODO */ @Slf4j @RestController @RequestMapping("/qianfan") public class QianFanController { /** * 输出文本的多样性因子, 影响输出文本的多样性, 取值越大, 生成文本的多样性越强 */ @Value("${spring.ai.qianfan.topP}") private Double topP; /** * AI模型 */ @Value("${spring.ai.qianfan.model}") private String model; /** * accessKey */ @Value("${spring.ai.qianfan.access-key}") private String accessKey; /** * secretKey */ @Value("${spring.ai.qianfan.secret-key}") private String secretKey; /** * 温度 */ @Value("${spring.ai.qianfan.temperature}") private Double temperature; /** * 指定模型最大输出token数, 说明: * (1)如果设置此参数, 范围[2, 2048] * (2)如果不设置此参数, 最大输出token数为1024 */ @Value("${spring.ai.qianfan.maxOutputTokens}") private Integer maxOutputTokens; /** * 单论对话 * * @param prompt 提示词 * @return 响应结果 */ @PostMapping(value = "/chat") public String chat(String prompt) { // 创建 ChatResponse response = this.getBaseChatBuilder() .addMessage(ChatRole.USER, prompt) // com.baidubce.qianfan.model.constant.ChatRole 这个类有相关的角色 添加用户消息 (此方法可以调用多次, 以实现多轮对话的消息传递) // .addUserMessage("") // 添加用户信息 // .addAssistantMessage("") // 添加助理信息 .execute(); // 发起请求 String result = response.getResult(); log.info(result); return result; } /** * 多轮对话 * * @param prompt 提示词 * @return 响应结果 */ @PostMapping(value = "/chat2") public String chat2(String prompt) { // 创建 ChatResponse response = this.getBaseChatBuilder() .addUserMessage("你是谁?") // 添加用户信息 .addAssistantMessage("你好, 我是一个人工智能语言模型, 可以协助你完成范围广泛的任务并提供有关各种主题的信息。作为一个计算机程序, 我没有具体的身份和个人特征, 我的目的是通过回答问题、提供信息和执行任务来帮助用户。请问你有任何问题都可以询问我。") // 添加助理信息 .addUserMessage(prompt) // 添加用户信息 .execute(); // 发起请求 String result = response.getResult(); log.info(result); return result; } /** * 流式对话 * @param prompt 提示词 * @return 响应结果 */ @PostMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux<String> stream(String prompt) { return Flux.create(sink -> { try(StreamIterator<ChatResponse> flux = this.getBaseChatBuilder() .addUserMessage(prompt) .executeStream()) { // 当有数据的时候, 将数据返回 while (flux.hasNext()) { ChatResponse chunk = flux.next(); String result = chunk.getResult(); // 发送每个响应片段 // 当为""的时候, 那么就就表示响应结束 sink.next(result); } // 完成流式传输 sink.complete(); } catch (Exception e) { // 发送错误信号 log.error("传输错误", e); sink.error(e); } }); } /** * 获取初始化ChatBuilder * * @return ChatBuilder */ private ChatBuilder getBaseChatBuilder() { Qianfan qianfan = new Qianfan(Auth.TYPE_OAUTH, accessKey, secretKey); return qianfan.chatCompletion() .topP(topP) // 输出文本的多样性因子 .maxOutputTokens(maxOutputTokens) // 指定模型最大输出token数 .model(model) // 使用model指定预置模型 .temperature(temperature); // 温度 } }
SpringBoot + 通义千问 + 自定义React组件, 支持EventStream数据解析!
Spring AI 接入OpenAI大模型实现同步和流式对话
Spring Boot 整合 Spring AI 实现项目接入ChatGPT
【ollama】linux、window系统更改模型存放位置, 全网首发2024!_ollama 设置模型位置
[Ollama深度探索:AI大模型本地部署的全面教程_ollama训练大模型](https://blog.csdn.net/xiaobing259/article/details/139853520#:~:text=二、安装与配置 1 1、系统要求 在开始安装Ollama之前, 确保您的系统满足以下基本要求: 操作系统:macOS、Windows 10及以上版本、Linux(包括但不限于Ubuntu、Fedora) 内存:至少4GB RAM,推荐8GB或以上, 具体取决于所运行模型的大小,… 4 4、启动Ollama服务 Ollama服务可以通过命令行界面(CLI)启动。 使用以下命令启动Ollama服务: ollama serve )
零基础入门AI:一键本地运行各种开源大语言模型 - Ollama
RAG 实践-Ollama+AnythingLLM 搭建本地知识库
ERNIE-4.0-Turbo-8K - 千帆大模型平台 | 百度智能云文档
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。