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

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日,希望可以帮助到你

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Scratch编程新纪元:网络请求与数据解析的探索之旅
  • 13-springcloud gateway集成nacos实现负载均衡
  • 【0-1背包】力扣416. 分割等和子集
  • 大模型本地化部署2-Docker部署MaxKB
  • Unity(2022.3.41LTS) - 网格,纹理,材质
  • Clickhouse集群化(三)集群化部署
  • 云计算day32
  • Windows系统安装MySQL
  • 2024 Ollama 一站式解决在Windows系统安装、使用、定制服务与实战案例
  • 线性代数:如何由AB=E 推出 BA=AB?
  • 【有来开源组织】开发规范手册
  • 【开端】 进行页面升级或维护时不影响用户体验NGINX配置
  • 影像设备国产替代究竟有多重要?这家企业提前布局8K时代
  • object.defineProperty用法
  • 开放式耳机的优缺点有什么?本文为你讲解推荐一下!
  • @jsonView过滤属性
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • iBatis和MyBatis在使用ResultMap对应关系时的区别
  • JavaScript/HTML5图表开发工具JavaScript Charts v3.19.6发布【附下载】
  • Java知识点总结(JDBC-连接步骤及CRUD)
  • JS学习笔记——闭包
  • vue--为什么data属性必须是一个函数
  • 基于web的全景—— Pannellum小试
  • 前端js -- this指向总结。
  • 使用权重正则化较少模型过拟合
  • 我的业余项目总结
  • 移动端解决方案学习记录
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • linux 淘宝开源监控工具tsar
  • Play Store发现SimBad恶意软件,1.5亿Android用户成受害者 ...
  • 东超科技获得千万级Pre-A轮融资,投资方为中科创星 ...
  • 国内唯一,阿里云入选全球区块链云服务报告,领先AWS、Google ...
  • ​​​【收录 Hello 算法】10.4 哈希优化策略
  • ​如何在iOS手机上查看应用日志
  • ​总结MySQL 的一些知识点:MySQL 选择数据库​
  • # Spring Cloud Alibaba Nacos_配置中心与服务发现(四)
  • #systemverilog# 之 event region 和 timeslot 仿真调度(十)高层次视角看仿真调度事件的发生
  • (2)关于RabbitMq 的 Topic Exchange 主题交换机
  • (delphi11最新学习资料) Object Pascal 学习笔记---第5章第5节(delphi中的指针)
  • (ros//EnvironmentVariables)ros环境变量
  • (zhuan) 一些RL的文献(及笔记)
  • (备忘)Java Map 遍历
  • (附源码)springboot金融新闻信息服务系统 毕业设计651450
  • (接上一篇)前端弄一个变量实现点击次数在前端页面实时更新
  • (蓝桥杯每日一题)love
  • (十) 初识 Docker file
  • (算法)N皇后问题
  • (已解决)vue+element-ui实现个人中心,仿照原神
  • (转)Linux NTP配置详解 (Network Time Protocol)
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
  • .net 怎么循环得到数组里的值_关于js数组
  • .net6Api后台+uniapp导出Excel
  • .NET版Word处理控件Aspose.words功能演示:在ASP.NET MVC中创建MS Word编辑器
  • .Net程序帮助文档制作
  • .php结尾的域名,【php】php正则截取url中域名后的内容