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 → 实时渲染打字机效果
相关推荐
不听话坏3 小时前
Ignition篇(下 一) 动态执行前的事情
开发语言·前端·javascript
likeyi073 小时前
require 和 import的区别
开发语言·前端
To_OC3 小时前
手搓 LangChain 工具调用:原来 Agent 的核心逻辑,就是个 while 循环
人工智能·langchain·llm
pany4 小时前
做 AI 友好的开源 Vue3 模板 🌈
前端·vue.js·ai编程
小二·4 小时前
React 19 + Next.js 15 现代前端开发实战:App Router / Server Components / 流式渲染
前端·javascript·react.js
谙忆10245 小时前
前端图片直传对象存储:OSS/S3 预签名 URL、STS 临时凭证与回调校验
前端
CHNE_TAO_EMSM6 小时前
Android studio 打开文件时自动下载源码
前端·javascript·android studio
一孤程7 小时前
Airtest自动化测试第五篇:小程序与Web测试——跨平台自动化全覆盖
前端·自动化测试·小程序·自动化·测试·airtest
IT_陈寒7 小时前
SpringBoot自动配置不是你以为的那样的智能
前端·人工智能·后端
yume_sibai8 小时前
大屏数据可视化 - 边框红绿呼吸灯实现详解
前端·信息可视化·typescript