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

相关文章

Spring Boot集成/输出/日志级别控制/持久化开发实践

《SpringBoot集成/输出/日志级别控制/持久化开发实践》SpringBoot默认集成Logback,支持灵活日志级别配置(INFO/DEBUG等),输出包含时间戳、级别、类名等信息,并可通过... 目录一、日志概述1.1、Spring Boot日志简介1.2、日志框架与默认配置1.3、日志的核心作用

破茧 JDBC:MyBatis 在 Spring Boot 中的轻量实践指南

《破茧JDBC:MyBatis在SpringBoot中的轻量实践指南》MyBatis是持久层框架,简化JDBC开发,通过接口+XML/注解实现数据访问,动态代理生成实现类,支持增删改查及参数... 目录一、什么是 MyBATis二、 MyBatis 入门2.1、创建项目2.2、配置数据库连接字符串2.3、入

Springboot项目启动失败提示找不到dao类的解决

《Springboot项目启动失败提示找不到dao类的解决》SpringBoot启动失败,因ProductServiceImpl未正确注入ProductDao,原因:Dao未注册为Bean,解决:在启... 目录错误描述原因解决方法总结***************************APPLICA编

深度解析Spring Security 中的 SecurityFilterChain核心功能

《深度解析SpringSecurity中的SecurityFilterChain核心功能》SecurityFilterChain通过组件化配置、类型安全路径匹配、多链协同三大特性,重构了Spri... 目录Spring Security 中的SecurityFilterChain深度解析一、Security

SpringBoot多环境配置数据读取方式

《SpringBoot多环境配置数据读取方式》SpringBoot通过环境隔离机制,支持properties/yaml/yml多格式配置,结合@Value、Environment和@Configura... 目录一、多环境配置的核心思路二、3种配置文件格式详解2.1 properties格式(传统格式)1.

Apache Ignite 与 Spring Boot 集成详细指南

《ApacheIgnite与SpringBoot集成详细指南》ApacheIgnite官方指南详解如何通过SpringBootStarter扩展实现自动配置,支持厚/轻客户端模式,简化Ign... 目录 一、背景:为什么需要这个集成? 二、两种集成方式(对应两种客户端模型) 三、方式一:自动配置 Thick

Spring WebClient从入门到精通

《SpringWebClient从入门到精通》本文详解SpringWebClient非阻塞响应式特性及优势,涵盖核心API、实战应用与性能优化,对比RestTemplate,为微服务通信提供高效解决... 目录一、WebClient 概述1.1 为什么选择 WebClient?1.2 WebClient 与

Java.lang.InterruptedException被中止异常的原因及解决方案

《Java.lang.InterruptedException被中止异常的原因及解决方案》Java.lang.InterruptedException是线程被中断时抛出的异常,用于协作停止执行,常见于... 目录报错问题报错原因解决方法Java.lang.InterruptedException 是 Jav

深入浅出SpringBoot WebSocket构建实时应用全面指南

《深入浅出SpringBootWebSocket构建实时应用全面指南》WebSocket是一种在单个TCP连接上进行全双工通信的协议,这篇文章主要为大家详细介绍了SpringBoot如何集成WebS... 目录前言为什么需要 WebSocketWebSocket 是什么Spring Boot 如何简化 We

java中pdf模版填充表单踩坑实战记录(itextPdf、openPdf、pdfbox)

《java中pdf模版填充表单踩坑实战记录(itextPdf、openPdf、pdfbox)》:本文主要介绍java中pdf模版填充表单踩坑的相关资料,OpenPDF、iText、PDFBox是三... 目录准备Pdf模版方法1:itextpdf7填充表单(1)加入依赖(2)代码(3)遇到的问题方法2:pd