SpringBoot调用通义千问

2024-08-27 22:28

本文主要是介绍SpringBoot调用通义千问,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

提示:今日花了2个小时搞定了一个简易版的AI对话功能

文章目录

目录

文章目录

SpringBoot代码

引入库

controller

返回对象类

工具类

前端代码

 ​编辑

 效果展示

 后端返回



SpringBoot代码

当然我只做了一个简易版的AI对话,你可以在我的基础之上进行改动

引入库

<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><!-- https://mvnrepository.com/artifact/com.alibaba/dashscope-sdk-java --><dependency><groupId>com.alibaba</groupId><artifactId>dashscope-sdk-java</artifactId><version>2.13.0</version></dependency>

controller

package com.xinggui.demo.controller;import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.xinggui.demo.domain.Response;
import com.xinggui.demo.util.ApiTestUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@Slf4j
@CrossOrigin(origins = "http://127.0.0.1:5500") // 假设前端在3000端口运行
public class test {@PostMapping("/test")public Response test(String problem){if(problem.length() == 0){return new Response("-1","请输入问题",null);}String result = null;try {result = ApiTestUtil.getProblem(problem);} catch (NoApiKeyException e) {log.error("apiKey错误");} catch (InputRequiredException e) {log.error("输入为空");}return new Response("0","success",result);}
}

返回对象类

package com.xinggui.demo.domain;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor
public class Response {private String code;private String msg;private Object data;}

工具类

package com.xinggui.demo.util;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.common.Message;
import com.alibaba.dashscope.common.ResultCallback;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.utils.Constants;
import com.alibaba.dashscope.utils.JsonUtils;
import io.reactivex.Flowable;import java.util.Arrays;
import java.util.concurrent.Semaphore;public class ApiTestUtil {public static String getProblem(String problem) throws NoApiKeyException, InputRequiredException {Constants.apiKey = "请填写你自己的API-key";// 实例化生成器对象Generation gen = new Generation();// 构建用户消息,角色为USER,内容为中国首都的介绍Message userMsg =Message.builder().role(Role.USER.getValue()).content(problem).build();// 构建生成参数,包括模型名称、消息列表、结果格式等GenerationParam param = GenerationParam.builder().model("qwen-max") // 选择使用的模型.messages(Arrays.asList(userMsg)) // 用户的询问消息.resultFormat(GenerationParam.ResultFormat.MESSAGE) // 结果以消息格式返回.topP(0.8).enableSearch(true) // 设置搜索启用及topP参数.incrementalOutput(true) // 以增量方式获取流式输出.build();// 调用生成器的流式调用方法,返回结果为一个Flowable流Flowable<GenerationResult> result = gen.streamCall(param);// 使用StringBuilder来拼接完整的回复内容StringBuilder fullContent = new StringBuilder();// 阻塞方式处理每一个流式输出的消息,并打印出来result.blockingForEach(message -> {// 将当前消息的内容追加到完整内容中fullContent.append(message.getOutput().getChoices().get(0).getMessage().getContent());// 打印当前的消息内容(JSON格式)System.out.println(JsonUtils.toJson(message));});// 打印最终的完整内容System.out.println("Full content: \n" + fullContent.toString());return fullContent.toString();}
}

前端代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>AI Chat Interface</title><!-- 引入 Vue 3 的 CDN --><script src="https://unpkg.com/vue@3/dist/vue.global.js"></script><style>/* 样式 */body {font-family: Avenir, Helvetica, Arial, sans-serif;background-color: #f4f4f9;margin: 0;padding: 0;display: flex;justify-content: center;align-items: center;height: 100vh;}.chat-container {display: flex;flex-direction: column;height: 80vh;width: 80vw;max-width: 600px;border: 1px solid #ccc;border-radius: 10px;overflow: hidden;background-color: #fff;}.chat-window {flex: 1;padding: 10px;overflow-y: auto;background-color: #f4f4f9;position: relative;}.chat-message {display: flex;margin-bottom: 10px;align-items: flex-start;}.message-left {flex-direction: row;}.message-right {flex-direction: row-reverse;}.avatar {width: 40px;height: 40px;border-radius: 50%;background-color: #007bff;display: flex;justify-content: center;align-items: center;color: white;font-weight: bold;margin: 0 10px;}.message-bubble {max-width: 70%;padding: 10px;border-radius: 20px;background-color: #007bff;color: white;word-wrap: break-word;}.message-left .message-bubble {background-color: #e4e6eb;color: black;}.chat-input {display: flex;padding: 10px;border-top: 1px solid #ccc;background-color: #fff;}.chat-input input {flex: 1;padding: 10px;border: 1px solid #ccc;border-radius: 20px;outline: none;}.chat-input button {margin-left: 10px;padding: 10px 20px;border: none;background-color: #007bff;color: white;border-radius: 20px;cursor: pointer;outline: none;}.chat-input button:hover {background-color: #0056b3;}/* From Uiverse.io by SchawnnahJ */ .loader {position: relative;width: 2.5em;height: 2.5em;transform: rotate(165deg);}.loader:before, .loader:after {content: "";position: absolute;top: 50%;left: 50%;display: block;width: 0.5em;height: 0.5em;border-radius: 0.25em;transform: translate(-50%, -50%);}.loader:before {animation: before8 2s infinite;}.loader:after {animation: after6 2s infinite;}@keyframes before8 {0% {width: 0.5em;box-shadow: 1em -0.5em rgba(225, 20, 98, 0.75), -1em 0.5em rgba(111, 202, 220, 0.75);}35% {width: 2.5em;box-shadow: 0 -0.5em rgba(225, 20, 98, 0.75), 0 0.5em rgba(111, 202, 220, 0.75);}70% {width: 0.5em;box-shadow: -1em -0.5em rgba(225, 20, 98, 0.75), 1em 0.5em rgba(111, 202, 220, 0.75);}100% {box-shadow: 1em -0.5em rgba(225, 20, 98, 0.75), -1em 0.5em rgba(111, 202, 220, 0.75);}}@keyframes after6 {0% {height: 0.5em;box-shadow: 0.5em 1em rgba(61, 184, 143, 0.75), -0.5em -1em rgba(233, 169, 32, 0.75);}35% {height: 2.5em;box-shadow: 0.5em 0 rgba(61, 184, 143, 0.75), -0.5em 0 rgba(233, 169, 32, 0.75);}70% {height: 0.5em;box-shadow: 0.5em -1em rgba(61, 184, 143, 0.75), -0.5em 1em rgba(233, 169, 32, 0.75);}100% {box-shadow: 0.5em 1em rgba(61, 184, 143, 0.75), -0.5em -1em rgba(233, 169, 32, 0.75);}}.loading {position: relative;bottom: -20px;display: flex;align-items: center;justify-content: center;}</style>
</head>
<body><div id="app"><div class="chat-container"><div class="chat-window"><div v-for="(message, index) in messages" :key="index" class="chat-message" :class="{'message-left': message.isUser, 'message-right': !message.isUser}"><div class="avatar">{{ message.isUser ? '自己' : 'AI' }}</div><div class="message-bubble">{{ message.text }}</div></div><div class="loading"  v-if="loading"><div style="display: flex;align-items: center;justify-content: center;"><div class="loader"></div><div style="margin-left: 10px;font-weight: bold; color: #e64c87;">加载中</div></div></div></div><div class="chat-input"><input v-model="userInput" @keydown.enter="sendMessage" placeholder="Type your question..." /><button @click="sendMessage">Send</button></div></div></div><script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script><script>const { createApp } = Vue;createApp({data() {return {userInput: '',messages: [{ text: '你有什么需要问的问题吗?', isUser: false }],loading:false};},methods: {sendMessage() {if (this.userInput.trim()) {// 添加用户的消息this.messages.push({ text: this.userInput, isUser: true });// 模拟AI回复(你可以在这里调用AI的接口)this.simulateAIResponse(this.userInput);// 清空输入框this.userInput = '';}},async simulateAIResponse(userText) {this.loading = true;const res =await axios.post("http://localhost:8888/test", {"problem": this.userInput},{ headers: { "Content-Type": "multipart/form-data" } })this.messages.push({text: `AI回答内容: ${res.data.data}`,isUser: false,});this.loading = false;},},}).mount('#app');</script>
</body>
</html>

这里我使用VScode中的liveServer插件,启动项目

后端对http://127.0.0.1:5500做了跨域配置

 

 

 效果展示

 这里还添加了一个Loading效果

 

 后端返回

 今日时间2024年8月27日,希望可以帮助到你

这篇关于SpringBoot调用通义千问的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

SpringBoot使用Apache Tika检测敏感信息

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

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

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

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

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

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

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

java脚本使用不同版本jdk的说明介绍

《java脚本使用不同版本jdk的说明介绍》本文介绍了在Java中执行JavaScript脚本的几种方式,包括使用ScriptEngine、Nashorn和GraalVM,ScriptEngine适用... 目录Java脚本使用不同版本jdk的说明1.使用ScriptEngine执行javascript2.

Spring MVC如何设置响应

《SpringMVC如何设置响应》本文介绍了如何在Spring框架中设置响应,并通过不同的注解返回静态页面、HTML片段和JSON数据,此外,还讲解了如何设置响应的状态码和Header... 目录1. 返回静态页面1.1 Spring 默认扫描路径1.2 @RestController2. 返回 html2

Spring常见错误之Web嵌套对象校验失效解决办法

《Spring常见错误之Web嵌套对象校验失效解决办法》:本文主要介绍Spring常见错误之Web嵌套对象校验失效解决的相关资料,通过在Phone对象上添加@Valid注解,问题得以解决,需要的朋... 目录问题复现案例解析问题修正总结  问题复现当开发一个学籍管理系统时,我们会提供了一个 API 接口去

Java操作ElasticSearch的实例详解

《Java操作ElasticSearch的实例详解》Elasticsearch是一个分布式的搜索和分析引擎,广泛用于全文搜索、日志分析等场景,本文将介绍如何在Java应用中使用Elastics... 目录简介环境准备1. 安装 Elasticsearch2. 添加依赖连接 Elasticsearch1. 创

Spring核心思想之浅谈IoC容器与依赖倒置(DI)

《Spring核心思想之浅谈IoC容器与依赖倒置(DI)》文章介绍了Spring的IoC和DI机制,以及MyBatis的动态代理,通过注解和反射,Spring能够自动管理对象的创建和依赖注入,而MyB... 目录一、控制反转 IoC二、依赖倒置 DI1. 详细概念2. Spring 中 DI 的实现原理三、

SpringBoot 整合 Grizzly的过程

《SpringBoot整合Grizzly的过程》Grizzly是一个高性能的、异步的、非阻塞的HTTP服务器框架,它可以与SpringBoot一起提供比传统的Tomcat或Jet... 目录为什么选择 Grizzly?Spring Boot + Grizzly 整合的优势添加依赖自定义 Grizzly 作为