NestJS + LangChain SSE 流式输出 + 前端实时渲染打字机效果

整体流程

  1. 后端:NestJS 开启 SSE 接口 → 调用 LangChain 流式 LLM → 逐块推送到前端
  2. 前端:监听 SSE 流 → 实时拼接文字 → 实现打字机效果

一、后端实现(NestJS + LangChain + SSE)

1. 安装依赖

bash 复制代码
# Nest 核心
npm install @nestjs/common @nestjs/core @nestjs/platform-express

# LangChain
npm install langchain @langchain/openai

2. 后端 SSE 流式接口(核心代码)

src/ai/ai.controller.ts

typescript 复制代码
import { Controller, Post, Body, Sse } from '@nestjs/common';
import { Observable } from 'rxjs';
import { ChatOpenAI } from '@langchain/openai';
import { HumanMessage } from '@langchain/core/messages';

@Controller('ai')
export class AiController {
  // SSE 流式输出 AI 回答
  @Post('stream')
  @Sse('sse') // 声明这是 SSE 接口
  async streamChat(@Body() body: { message: string }) {
    const { message } = body;

    // 1. 初始化流式 LLM
    const llm = new ChatOpenAI({
      model: 'gpt-3.5-turbo',
      apiKey: '你的 OPENAI_API_KEY',
      configuration: {
      	baseURL: '你的 OPENAI_BASE_URL',
      },
    });

    // 2. from 接收流式迭代器 → map 包装成 SSE 格式
    const stream = await llm.stream([new HumanMessage(message)]);
    return from(stream).pipe(
      map((chunk) => ({
        data: chunk.content,
      }))
    );
  }
}

二、前端实现

  • 使用浏览器原生 EventSourcefetch + ReadableStream 接收 SSE,从而实现实时拼接内容 → 打字机效果
javascript 复制代码
async function chat(message) {
  const res = await fetch('http://localhost:3000/ai/stream', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ message }),
  });

  const reader = res.body.getReader();
  const decoder = new TextDecoder();
  let text = '';

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;

		// 解析 SSE 流
    for (const line of decoder.decode(value).split('\n')) {
      if (!line.startsWith('data:')) continue;
      const data = line.replace('data:', '').trim();
      text += data;
      document.getElementById('result').innerText = text; // 打字机效果
    }
  }
}

三、补充:原生 EventSource

EventSource 只支持 GET,不能 POST。无需 fetch、无需解析流、无需 TextDecoder,因为 EventSource 本身就是 SSE 专用对象,最简洁。

html 复制代码
<script>
const res = document.getElementById('result');
let text = '';
// 创建 SSE 连接
const es = new EventSource('http://localhost:3000/ai/stream?message=你好');
// 接收流式消息
es.onmessage = e => {
  text += e.data;
  res.innerText = text;
};
// 结束
es.onend = () => es.close();;
// 错误
es.onerror = es.close;
</script>

四、总结

  • 后端:NestJS @Sse + LangChain stream() + RxJS Observable 推流
  • 前端:fetch 读取流 → 解析 SSE → 实时渲染打字机效果
相关推荐
1314lay_10071 小时前
axios的Post方法和Delete方法的参数个数和位置不同,导致415错误
前端·javascript·vue.js·elementui
LXXgalaxy1 小时前
HTML头部元信息避坑指南
前端·html
qq_381338501 小时前
现代 CSS 黑科技:Container Queries、:has() 与嵌套语法实战
前端·css·科技
枫叶丹41 小时前
【HarmonyOS 6.0】ArkWeb:Web组件销毁模式深度解析
开发语言·前端·华为·harmonyos
拉拉尼亚1 小时前
WebRTC 完全指南:原理、教程与应用场景
前端·typescript·实时音视频
lkbhua莱克瓦242 小时前
ZogginWeb 电脑端沉浸式记单词整合优化方案(终极版)
前端·zogginweb开发
小则又沐风a2 小时前
深剖string内部结构 手撕string
java·前端·数据库·c++
不恋水的雨2 小时前
html中补齐table表格合并导致每行td数量不一致的情况
前端·html
iReachers2 小时前
HTML打包EXE工具四种弹窗方式图文详解 - 单窗口/新窗口/标签页/浏览器打开
前端·javascript·html·弹窗·html打包exe·html转程序