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

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

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


http://www.kler.cn/a/555015.html

相关文章:

  • ip is not allowed to connect to this Mysql server
  • Go 之 Windows下 Beego 项目的搭建
  • TikTok账户安全指南:如何取消两步验证?
  • GO大模型应用开发框架-
  • 掌握 ElasticSearch 四种match查询的原理与应用
  • 无人机遥感技术:从植被监测到生理参数反演的进阶之路
  • uniapp 安卓端 使用axios 和 renderjs 上传 FormData 参数
  • 【个人总结】9. 通讯协议、物联网、DSP及FatFS文件系统 工作三年的嵌入式常见知识点梳理及开发技术要点(欢迎指正、补充)
  • 【C++】优先级队列宝藏岛
  • 关于databean.toString()为空的问题
  • 【新人系列】Golang 入门(一):基础介绍
  • 分布式数据库:架构演进、核心挑战与行业落地实践
  • SpringCloud面试题----服务注册和发现是什么意思?Spring Cloud如何实现
  • 推荐一款AI大模型托管平台-OpenWebUI
  • Debezium 与 Apache Kafka 的集成方式
  • EasyPoi系列之通用导入接口设计
  • 如何用ClassFinal加密JAR保护知识产权!
  • Spring中事务的传播行为方式
  • 如何看nginx.conf文件?
  • vue3学习1