当前位置: 首页 > news >正文

Java集成openai,ollama,千帆,通义千问实现文本聊天

Java集成openai,ollama,千帆,通义千问实现文本聊天

本文所使用的环境如下

Win10 + JDK17 + SpringBoot3.2.4

集成Open AI

pom文件

<?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>

yaml文件

spring:# 代码中的配置会覆盖yaml中相关AI参数配置ai:openai:# Api-Key, 没有的可以去淘宝搜索购买, 替换成你自己的keyapi-key: sk-xxxxxxxxxchat: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-largemodel: gpt-3.5-turbo# 温度temperature: 0.4# 直连地址/代理地址# 切换成你自己的地址base-url: https://xxxx.com

AiMessage

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;
}

Controller

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 聊天模型*/@Resourceprivate 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, 那么这里你得看看, 如果已经使用过了, 那么跳过过这里, 去直接看代码集成

Ollama的下载, 安装以及使用

去Ollama官网下载, 并按照, 需要说明的是Ollama并非是一个大模型, 而是一个大模型的管理, 类似于Docker一样的角色, 而大模型类似于镜像的角色

进入PowerShell命令行中输入以下命令

ollama -v

如果显示了版本, 那么就说明安装成功

在这里插入图片描述

Ollama模型存储位置修改

此时不着急下载模型, Ollama默认会将模型存储如下位置

  • Linux/var/lib/ollama/models
  • WindowsC:\ProgramData\Ollama\models

Windos(我用的是这个)由于ollama是默认存储在C盘, 所以修改一下模型存储位置, 修改步骤如下:

  1. 在环境变量中新增OLLAMA_MODELS变量名, 注意了这个变量名一定不能变, 变量值指向你要存放的文件夹, 如下
    在这里插入图片描述

  2. 重启电脑(不重启电脑不生效!), 然后本地下载的模型就自动迁移的到你配置的目录了!

Ollama基本命令
  • 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退出模型对话
在这里插入图片描述

代码集成Ollama本地模型

pom文件
<?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>
yaml文件
spring:# 代码中的配置会覆盖yaml中相关AI参数配置ai:ollama:chat:options:# 注意了, ollama中要有这个模型model: qwen:0.5btemperature: 0.4# 直连地址/代理地址# 这里填的是我本地的ollama的启动地址,base-url: http://localhost:11434
Controller
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 {@Resourceprivate 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("执行完了");});}
}

通义千问对接

SDK

pom文件
<?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>
yaml文件
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
Controller
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); // 返回值信息}
}

HTTP

api文档

pom文件
<?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>
yaml文件
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
Request
QwenRequest
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;@Datapublic static class Input implements Serializable {private List<Message> messages;}@Datapublic 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;}
}
QwenStreamRequest
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;}
}
Response
QwenBaseResponse
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;@Datapublic 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;}
}
QwenResponse
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;/*** 响应输出结果*/@Datapublic static class Output implements Serializable {/*** 结束原因* 有三种情况:*   1. 正在生成时为null*   2. 生成结束时如果由于停止token导致则为stop*   3. 生成结束时如果因为生成长度过长导致则为length。当result_format设置为text时返回该字段*/@JsonProperty("finish_reason")private String finishReason;/*** 响应结果文本*/private String text;}
}
QwenStreamResponse
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;/*** 响应输出结果*/@Datapublic static class Output implements Serializable {/*** 响应结果*/@JsonProperty("choices")private Choices[] choices;}/*** 响应结果*/@Datapublic 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为模型输出的内容*/@Datapublic static class Message implements Serializable {/*** 角色*/private String role;/*** 内容*/private String content;}
}
Controller
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 messageQwenRequest.Message systemMessage = new QwenRequest.Message();systemMessage.setRole(Role.SYSTEM.getValue());systemMessage.setContent("你是一个Java高级工程师");// user messageQwenRequest.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);// 转换成jsonObjectMapper objectMapper = new ObjectMapper();String reqJsonStr = objectMapper.writeValueAsString(qwenRequest);// 请求的strlog.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 messageQwenRequest.Message systemMessage = new QwenRequest.Message();systemMessage.setRole(Role.SYSTEM.getValue());systemMessage.setContent("你是一个Java高级工程师");// user messageQwenRequest.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);// 转换成jsonObjectMapper objectMapper = new ObjectMapper();String reqJsonStr = objectMapper.writeValueAsString(qwenStreamRequest);// 请求的strlog.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;}
}

百度千帆大模型对接

SDK

pom
<?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>
yaml
spring:ai:# 千帆qianfan:access-key: xxxxxsecret-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
Controller
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); // 温度}
}

参考资料

Spring接入阿里云通义千问Demo

java对接阿里云通义千问API多轮对话承接上下文

SpringBoot + 通义千问 + 自定义React组件, 支持EventStream数据解析!

通义千问最新api java调用

Spring AI 接入OpenAI大模型实现同步和流式对话

Spring Boot 整合 Spring AI 实现项目接入ChatGPT

Ollama全面指南:安装、使用与高级定制

Ollama 常用命令_ollama 命令

【ollama】linux、window系统更改模型存放位置, 全网首发2024!_ollama 设置模型位置

更改ollama模型存储路径

ollama如何把gemma模型部署到D盘

五个优秀的免费 Ollama WebUI 客户端推荐

[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 )

open-webui

零基础入门AI:一键本地运行各种开源大语言模型 - Ollama

RAG 实践-Ollama+AnythingLLM 搭建本地知识库

超级详细Spring AI运用Ollama大模型

Kimi API 还没用起来?请看这篇无门槛快速入门指南

Moonshot AI - 开放平台

ERNIE-4.0-Turbo-8K - 千帆大模型平台 | 百度智能云文档

bce-qianfan-sdk/java at main · baidubce/bce-qianfan-sdk

使用Python调用百度千帆免费大模型接口

java ISO 8601 日期格式进行转换

相关文章:

  • 开发者工具攻略:前端测试的极简指南
  • 刚办理的手机号被停用,你可能遇到这些问题了!
  • 多态的优点
  • R语言进行字符的替换和删减gsub,substr函数
  • vue3中若v-model绑定的响应字段出现三级,该如何实现rules验证规则
  • 视图库对接系列(GA-T 1400)九、视图库对接系列(本级)机动车数据推送
  • 前端技术(二)——javasctipt 介绍
  • 【RAG检索增强生成】MaxKB:构建企业级知识库问答系统(Ollama+Qwen2)
  • 论文阅读YOLO-World: Real-Time Open-Vocabulary Object Detection
  • 快速排序c++java代码实现
  • 全网最简单的Java设计模式【三】工厂方法模式详解
  • 实现点击按钮导出页面pdf
  • Android super.img结构及解包和重新组包
  • Android Gradle开发与应用Gradle详细使用
  • STM32第十四课:低功耗模式和RTC实时时钟
  • JavaScript DOM 10 - 滚动
  • Material Design
  • Vue.js-Day01
  • 技术发展面试
  • 讲清楚之javascript作用域
  • 前端
  • 使用Maven插件构建SpringBoot项目,生成Docker镜像push到DockerHub上
  • 移动互联网+智能运营体系搭建=你家有金矿啊!
  • 与 ConTeXt MkIV 官方文档的接驳
  • 通过调用文摘列表API获取文摘
  • ​如何使用ArcGIS Pro制作渐变河流效果
  • # Swust 12th acm 邀请赛# [ K ] 三角形判定 [题解]
  • #Linux(帮助手册)
  • #NOIP 2014#Day.2 T3 解方程
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • %3cscript放入php,跟bWAPP学WEB安全(PHP代码)--XSS跨站脚本攻击
  • (C语言)strcpy与strcpy详解,与模拟实现
  • (pytorch进阶之路)CLIP模型 实现图像多模态检索任务
  • (二) Windows 下 Sublime Text 3 安装离线插件 Anaconda
  • (二)Pytorch快速搭建神经网络模型实现气温预测回归(代码+详细注解)
  • (附源码)springboot金融新闻信息服务系统 毕业设计651450
  • (附源码)计算机毕业设计SSM疫情居家隔离服务系统
  • (牛客腾讯思维编程题)编码编码分组打印下标(java 版本+ C版本)
  • (算法)N皇后问题
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (转)创业的注意事项
  • (转)德国人的记事本
  • ****** 二十三 ******、软设笔记【数据库】-数据操作-常用关系操作、关系运算
  • ./configure、make、make install 命令
  • .NET Core、DNX、DNU、DNVM、MVC6学习资料
  • .net 程序发生了一个不可捕获的异常
  • .NET 分布式技术比较
  • .NetCore 如何动态路由
  • [ 云计算 | Azure 实践 ] 在 Azure 门户中创建 VM 虚拟机并进行验证
  • [④ADRV902x]: Digital Filter Configuration(发射端)
  • [Android]RecyclerView添加HeaderView出现宽度问题
  • [BUG]vscode插件live server无法自动打开浏览器
  • [FZSZOJ 1223] 上海红茶馆
  • [hdu 3065] 病毒侵袭持续中 [AC自动机] [病毒特征码匹配]
  • [HNOI2008]玩具装箱toy