dify+vue+java接入大模型流式输出

接口风格应该都是openAI

一、后端

后端使用常规的spring boot,需要检查安装包,需要使用到webFlux+SseEmitter

XML 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

controller层

java 复制代码
@PostMapping(path = "/test", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter queryPage(@RequestBody TestParam param){
    return testService.test(param);
}

service层

java 复制代码
import cn.hutool.json.JSONObject;
import cn.kunming.kgoa.service.aihelper.api.model.param.TestParam;
import cn.kunming.kgoa.service.common.api.utils.SecurityUtil;
import io.netty.channel.ChannelOption;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import reactor.core.publisher.Flux;
import reactor.netty.http.client.HttpClient;




public SseEmitter test(TestParam param){
    SseEmitter emitter = new SseEmitter(300_000L);

    HttpClient httpClient = HttpClient.create().tcpConfiguration(tcpClient -> tcpClient.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000));
    WebClient client = WebClient.builder().clientConnector(new ReactorClientHttpConnector(httpClient))
            .baseUrl("http://192.168.70.226/v1")
            .build();
    ParameterizedTypeReference<ServerSentEvent<String>> type = new ParameterizedTypeReference<ServerSentEvent<String>>() {
    };
    JSONObject body = new JSONObject();
    body.set("inputs", new JSONObject());
    body.set("query", param.getContent());
    body.set("user", SecurityUtil.getUserId().toString());
    body.set("response_mode", "streaming");
    body.set("conversation_id", param.getConversationId());

    log.info("Dify chat body: {}", body);
    Flux<ServerSentEvent<String>> eventStream = client.post()
            .uri("/chat-messages")
            .header("Authorization", "Bearer " + "app-dgEzITfxrVqxrgSyRnS7p3I1")
            .header("Content-Type", "application/json")
            .bodyValue(body.toString())
            .retrieve()
            .bodyToFlux(type);

    eventStream.subscribe((content) -> {
        String data = content.data();
        log.info("收到数据:"+data);
    }, emitter::completeWithError, emitter::complete);
    return emitter;
}

二、前端

前端需要使用fetch-event-source框架,因为需要使用post进行参数传递,默认的SSE是不支持post方法的。

bash 复制代码
npm install @microsoft/fetch-event-source

实现代码

javascript 复制代码
import { fetchEventSource } from "@microsoft/fetch-event-source";

const ctrl = new AbortController();
let content = ref("你好");
let send = function (content) {
  var url =
    "http://localhost:8001/kgoa-service-aihelper/aihelper/test/test";
  fetchEventSource(url, {
    method: "POST",
    headers: {
      Accept: "*/*",
      Connection: "keep-alive",
      "Content-Type": "application/json",
      Authorization: "pc_3aaac4d1343a3526cc86dd1d0f4eda35",
    },
    body: JSON.stringify({
      content: content,
    }),
    signal: ctrl.signal,
    async onopen(response) {
      console.log("Connection to server opened.");
    },
    onmessage(msg) {
      let data = JSON.parse(msg.data);
      console.log(data);
    },
    onclose() {
      // if the server closes the connection unexpectedly, retry:
      
    },
    onerror(event) {
      console.log(event);
      if (event.target.readyState === EventSource.CLOSED) {
        console.error("EventSource connection closed by the server.");
      } else if (event.target.readyState === 0) {
        console.log("对方回答结束...关闭...");
      }
    },
  });
};
相关推荐
Boilermaker199210 分钟前
【Java EE】Mybatis-Plus
java·开发语言·java-ee
千鼎数字孪生-可视化12 分钟前
Web技术栈重塑HMI开发:HTML5+WebGL的轻量化实践路径
前端·html5·webgl
凌辰揽月13 分钟前
7月10号总结 (1)
前端·css·css3
xdscode32 分钟前
SpringBoot ThreadLocal 全局动态变量设置
java·spring boot·threadlocal
lifallen35 分钟前
Paimon 原子提交实现
java·大数据·数据结构·数据库·后端·算法
天天扭码36 分钟前
很全面的前端面试——CSS篇(上)
前端·css·面试
EndingCoder38 分钟前
搜索算法在前端的实践
前端·算法·性能优化·状态模式·搜索算法
丶小鱼丶42 分钟前
链表算法之【合并两个有序链表】
java·算法·链表
sunbyte43 分钟前
50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | DoubleVerticalSlider(双垂直滑块)
前端·javascript·css·vue.js·vue
Favor_Yang1 小时前
SQL Server通过存储过程实现HTML页面生成
前端·信息可视化·sqlserver·存储过程