Spring-GPT智谱清言AI项目(附源码)

一、项目介绍

本项目是Spring AI第三方调用整合智谱请言(官网是:https://open.bigmodel.cn)的案例,回答响应流式输出显示,这里使用的是免费模型,需要其他模型可以去 https://www.bigmodel.cn/pricing 切换。

在这里主要是完整地描述前后端开发和第三方调用的过程,SSE流式请求响应,MD稳定渲染显示等。

二、后端开发

后端使用的是Java,版本是JDK17,spring-boot版本是3.0.2,下面是pom.xml配置文件:

<?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</groupId>
    <artifactId>spring-gpt-service</artifactId>
    <version>0.0.9</version>
    <name>spring-gpt-service</name>
    <description>spring-gpt-service</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>3.0.2</spring-boot.version>
    </properties>

    <!-- 依赖 -->
    <dependencies>
        <!-- web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- oapi -->
        <dependency>
            <groupId>cn.bigmodel.openapi</groupId>
            <artifactId>oapi-java-sdk</artifactId>
            <version>release-V4-2.3.0</version>
        </dependency>
        <!-- okhttp -->
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.9.3</version>
        </dependency>
        <!-- gson -->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.8</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.75</version>
        </dependency>
        <!-- flux -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </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>
            <!--打包jar插件配置-->
            <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>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

 

​​​​​​​由于Get请求参数直接在链接上会受到换行符\n或\r的限制,改用Post请求,使用json封装请求参数,下面是RequestData类:

import lombok.Data;

@Data
public class RequestData {
    private String msg;
}

接口层accumulator.getDelta().getContent()这句代码是返回每次的具体结果

 /**
 * 通过ModelApiResponse.getFlowable()获取流式数据,最后通过blockingGet()获取最终结果
 * System.out.print(accumulator.getDelta().getContent());  // 这句代码是返回的具体结果
 * 因为直接SSE传text,受结束符\n影响,可以使用base64传输
 */ 
@PostMapping(value = "/zp2", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> testSseInvoke(@RequestBody RequestData requestData) {
        String msg = requestData.getMsg();
        List<ChatMessage> messages = new ArrayList<>();
        ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), msg);
        messages.add(chatMessage);
        String requestId = String.format(requestIdTemplate, System.currentTimeMillis());
        ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
                .model(Constants.ModelChatGLM4)
                .stream(Boolean.TRUE)
                .messages(messages)
                .requestId(requestId)
                .build();
        Flux<String> flux = Flux.create(emitter -> {
            ModelApiResponse sseModelApiResp = client.invokeModelApi(chatCompletionRequest);
            if (sseModelApiResp.isSuccess()) {
                AtomicBoolean isFirst = new AtomicBoolean(true);
                mapStreamToAccumulator(sseModelApiResp.getFlowable())
                        .doOnNext(accumulator -> {
//                            if (isFirst.getAndSet(false)) {
//                                String base64Msg = Base64.getEncoder().encodeToString("Response: ".getBytes(StandardCharsets.UTF_8));
//                                emitter.next(base64Msg);
//                            }
                            if (accumulator.getDelta() != null && accumulator.getDelta().getTool_calls() != null) {
                                try {
                                    String jsonString = mapper.writeValueAsString(accumulator.getDelta().getTool_calls());
                                    String tool = "tool_calls: " + jsonString;
                                    String base64Msg = Base64.getEncoder().encodeToString(tool.getBytes(StandardCharsets.UTF_8));
                                    emitter.next(base64Msg);
                                } catch (Exception e) {
                                    String err = "Error converting tool_calls to JSON: " + e.getMessage();
                                    String base64Msg = Base64.getEncoder().encodeToString(err.getBytes(StandardCharsets.UTF_8));
                                    emitter.next(base64Msg);
                                }
                            }
                            if (accumulator.getDelta() != null && accumulator.getDelta().getContent() != null) {
                                String content = accumulator.getDelta().getContent();
                                String base64Msg = Base64.getEncoder().encodeToString(content.getBytes(StandardCharsets.UTF_8));
                                // 具体结果
                                // System.out.print(content);
                                emitter.next(base64Msg);
                            }
                        })
                        .doOnComplete(() -> {
                            emitter.next("\n");
                            emitter.complete();
                        })
                        .subscribe();
            } else {
                emitter.next("Error: " + sseModelApiResp.getError() + "\n");
                emitter.complete();
            }
        });
        return flux;
    }

三、前端实现

前端使用Vue3,具体其他库详见项目的package.json文件

pnpm create vue@latest

其中使用md-editor-v3来做MD文档格式显示

 pnpm add md-editor-v3

下面是在组件中的具体使用:

<script lang="ts" setup>
import { MdPreview } from 'md-editor-v3';
import 'md-editor-v3/lib/preview.css';
</script>

<LayoutContent class="content">
          <!-- 聊天列表 -->
          <ul class="chat-list" ref="messageListRef">
            <li class="chat-item" :class="`chat-item--${msg.role}`" v-for="msg in chatMessages">
              <MdPreview style="padding: 0; background-color: transparent;" type="String" :model-value="msg.content"/>
            </li>
            <li class="chat-item chat-item--system" :class="{ hidden: !isLoading }">
              <MdPreview :model-value="messagePlaceholder"/>
              <Spin/>
            </li>
          </ul>
</LayoutContent>

四、源码仓库

=======================================================================

联系开发者:2013994940@qq.com

Gitee源码地址:https://gitee.com/BuLiangShuai01033/spring-gpt

=======================================================================

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/972256.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

用deepseek学大模型08-卷积神经网络(CNN)

yuanbao.tencent.com 从入门到精通卷积神经网络(CNN),着重介绍的目标函数&#xff0c;损失函数&#xff0c;梯度下降 标量和矩阵形式的数学推导&#xff0c;pytorch真实能跑的代码案例以及模型,数据&#xff0c;预测结果的可视化展示&#xff0c; 模型应用场景和优缺点&#xf…

deepseek-v3在阿里云和腾讯云的使用中的差异

随着deepseek在各大云商上线&#xff0c;试用了下阿里云和腾讯云的deepseek服务&#xff0c;在回答经典数学问题9.9和9.11谁大时&#xff0c;发现还是有差异的。将相关的问题记录如下。 1、问题表现 笔者使用的openai的官方sdk go-openai。 因本文中测验主要使用阿里云和腾讯…

React 与 Vue 对比指南 - 上

React 与 Vue 对比指南 - 上 本文将展示如何在 React 和 Vue 中实现常见功能&#xff0c;从基础渲染到高级状态管理 Hello 分别使用 react 和 vue 写一个 Hello World&#xff01; react export default () > {return <div>Hello World!</div>; }vue <…

STM32 HAL库 UART串口发送数据实验

一、实验目标 通过STM32的UART串口发送字符串数据到PC端串口调试助手&#xff0c;验证通信功能。 二、硬件准备 主控芯片&#xff1a;STM32F103C8T6。 串口模块&#xff1a;USB转TTL模块。 接线说明&#xff1a; STM32的USART1_TX&#xff08;PA9&#xff09; → USB-TTL模…

WPF创建自定义类和控件及打包成dll引用

WPF创建自定义类和控件及打包成dll引用 一、前言二、创建自定义类和控件并生成dll文件2.1创建类库项目2.2创建自定义类和控件2.3生成dll文件 三、在其他项目中引用3.1添加dll文件引用3.2cs文件中引用命名空间3.3XAML文件中引用命名空间 一、前言 出于一些代码复用的需求&#…

平板作为电脑拓展屏

有线串流&#xff08;速度更快&#xff09; spacedesk 打开usb对安卓的连接 用usb线直接连接电脑和平板 无线串流&#xff08;延迟高&#xff0c;不推荐&#xff09; todesk pc和手机端同时下载软件&#xff0c;连接后可以进行远程控制或扩展屏幕 spacedesk 连接到同一个…

深度学习05 ResNet残差网络

目录 传统卷积神经网络存在的问题 如何解决 批量归一化BatchNormalization, BN 残差连接方式 ​残差结构 ResNet网络 ResNet 网络是在 2015年 由微软实验室中的何凯明等几位大神提出&#xff0c;斩获当年ImageNet竞赛中分类任务第一名&#xff0c;目标检测第一名。获得CO…

【ClickHouse】Ubuntu下离线安装ClickHouse数据库并使用DBeaver连接

目录 0. 安装前准备1 安装ClickHouse1.1 下载安装包1.2 离线安装1.3 配置密码1.4 启动ClickHouse服务 2 DBeaver连接配置2.1 下载ClickHouse驱动2.2 DBeaver配置2.2.1 配置主要参数2.2.2 配置驱动 2.3 常见问题处理2.3.1 修改远程登录配置2.3.2 更新驱动配置 0. 安装前准备 有…

缓存三大问题及其解决方案

缓存三大问题及其解决方案 1. 前言 ​ 在现代系统架构中&#xff0c;缓存与数据库的结合使用是一种经典的设计模式。为了确保缓存中的数据与数据库中的数据保持一致&#xff0c;通常会给缓存数据设置一个过期时间。当系统接收到用户请求时&#xff0c;首先会访问缓存。如果缓…

千峰React:脚手架准备+JSX基础

组件化->封装性 React提供函数组件实现组件化 React和传统JS的区别就是JS需要手动管理DOM操作&#xff0c;React: 采用组件化开发&#xff0c;通过虚拟DOM提升性能。 MVC 是一种软件设计模式&#xff0c;全称为 Model-View-Controller&#xff08;模型-视图-控制器&#x…

springmvc(13/158)

太感动了&#xff0c;搞了半天以为是 这个dispatcherservlet报错的问题&#xff0c;结果是我第一次改springmvc-servlet.xml里面的后缀出了问题。 <servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.D…

节目选择器安卓软件编写(针对老年人)

文章目录 需求来源软件界面演示效果源码获取 对爬虫、逆向感兴趣的同学可以查看文章&#xff0c;一对一小班教学&#xff1a;https://blog.csdn.net/weixin_35770067/article/details/142514698 需求来源 由于现在的视频软件过于复杂&#xff0c;某客户想开发一个针对老年人、…

图解循环神经网络(RNN)

目录 1.循环神经网络介绍 2.网络结构 3.结构分类 4.模型工作原理 5.模型工作示例 6.总结 1.循环神经网络介绍 RNN&#xff08;Recurrent Neural Network&#xff0c;循环神经网络&#xff09;是一种专门用于处理序列数据的神经网络结构。与传统的神经网络不同&#xff0c…

深入解析Qt事件循环

在Qt开发中&#xff0c;QApplication::exec()这行代码是每个开发者都熟悉的“魔法咒语”。为什么GUI程序必须调用它才能响应操作&#xff1f;为何耗时操作会导致界面冻结&#xff1f;本文将以事件循环为核心&#xff0c;揭示Qt高效运转的底层逻辑&#xff0c;探讨其设计哲学与最…

超全Deepseek资料包,deepseek下载安装部署提示词及本地部署指南介绍

该资料包涵盖了DeepSeek模型的下载、安装、部署以及本地运行的详细指南&#xff0c;适合希望在本地环境中高效运行DeepSeek模型的用户。资料包不仅包括基础的安装步骤&#xff0c;还提供了68G多套独立部署视频教程教程&#xff0c;针对不同硬件配置的模型选择建议&#xff0c;以…

计算机网络(涵盖OSI,TCP/IP,交换机,路由器,局域网)

一、网络通信基础 &#xff08;一&#xff09;网络通信的概念 网络通信是指终端设备之间通过计算机网络进行的信息传递与交流。它类似于现实生活中的物品传递过程&#xff1a;数据&#xff08;物品&#xff09;被封装成报文&#xff08;包裹&#xff09;&#xff0c;通过网络…

【办公类-90-02】】20250215大班周计划四类活动的写法(分散运动、户外游戏、个别化综合)(基础列表采用读取WORD表格单元格数据,非采用切片组合)

背景需求&#xff1a; 做了中班的四类活动安排表&#xff0c;我顺便给大班做一套 【办公类-90-01】】20250213中班周计划四类活动的写法&#xff08;分散运动、户外游戏、个别化&#xff08;美工室图书吧探索室&#xff09;&#xff09;-CSDN博客文章浏览阅读874次&#xff0…

深度学习笔记之自然语言处理(NLP)

深度学习笔记之自然语言处理(NLP) 在行将开学之时&#xff0c;我将开始我的深度学习笔记的自然语言处理部分&#xff0c;这部分内容是在前面基础上开展学习的&#xff0c;且目前我的学习更加倾向于通识。自然语言处理部分将包含《动手学深度学习》这本书的第十四章&#xff0c…

使用IDEA创建Maven项目、Maven坐标,以及导入Maven项目

一、创建Maven项目 正如使用Vue创建工程化的前端项目&#xff0c;此时&#xff0c;使用Maven创建标准化的后端项目。 以下适用于2021版本的IDEA。 name和artifactid会自动保持一致。 Groupid&#xff1a;一般写公司域名倒写&#xff0c;再加上项目名&#xff08;也可以不…

Oracle视图(基本使用)

视图 视图是通过定制的方式显示一个或者多个表的数据。 视图可以视为“虚拟表”或“存储的查询”。 视图的优点&#xff1a; 提供了另外一种级别的表安全性隐藏了数据的复杂性简化了用户的SQL命令隔离基表结构的改变通过重命名列&#xff0c;从另一个角度提供数据。 视图里…