RxJS for LLM 流式架构

结论:复杂状态流中,一边接收一边解析一边分流一边传递上下文做状态管理又要有错误处理,RxJS 能起到一定程度的作用

什么场景会用到 RxJS?

  • 异步流
  • 多协议解析 (vx, markdown, json, bash script)
  • 分发 (解析之后需要执行)
  • 解耦
  • Scheduler 控制流的调度机制

AI 输出解析的本质

  • 从 HTTP Stream 数据流检测并 分发子语义段落
  • 按照语言类型 分支处理
  • 每个处理器有自己的解析和消费逻辑

RxJS 应用场景

  • 事件驱动,异步解耦,多路流合并 / 拆分
  • 每一段子流可以 filter / groupBy / switchMap / mergeMap
  • 自然支持 取消, 中断, 错误恢复

RxJS 工具功能

  • 操作符 - scan 构造状态机, bufferWhen 拆段, groupBy 语言分发
  • 天然流式 - HTTP Chunk 到一部分处理一部分
  • 高度解耦 - 每个语言逻辑放在单独 pipe() 里面
  • 动态分流 - 在 runtime 动态按照内容格式分给不同分支
  • 中间态可观察 - debug log 状态可视化 (意味着测试驱动,问题可溯源,业务领域分隔)
  • 类型安全 - 符合 TS 设计, 团队成员提效

Q1 - RxJS 过时了吧?

即使操作符复杂,类型安全和 lazy execution 也值得使用 RxJS

Q2 - RxJS 并不适合做状态管理了

of course, 但 RxJS 仍然是最适合在当前 use-case 下大放异彩的

在简单情况下当然不如 mobx, zustand 甚至 signals

Q3 - RxJS 团队不可维护

stackoverflow.com/questions/7...

架构设计中参考 Facade 设计,以简洁形式或 observable 形式暴露,隐藏底层复杂管线

RxJS 的难度本质在于 operator 模式产生的高心智成本 → 认识到问题 → 结合现有 use-case 进行针对性降低维护门槛

RxJS 在这个场景的优势

优势 为什么重要
操作符丰富 scan 构造状态机,bufferWhen 拆段,groupBy 按语言分发
天然流式处理 HTTP chunk 到达一部分就可以处理一部分
高度解耦 每种语言处理逻辑放在单独的 pipe()
动态分流 可以在 runtime 动态按内容格式分给不同分支
中间态可观察 debug、log、状态可视化都很方便

1. 将 stream 转为 Observable

ts 复制代码
import { fromEvent, Observable } from 'rxjs';

function createTextStream(response: ReadableStream<Uint8Array>): Observable<string> {
return new Observable(observer => {
  const reader = response.getReader();
  const decoder = new TextDecoder();

  (async () => {
    while (true) {
      const { done, value } = await reader.read();
      if (done) {
        observer.complete();
        break;
      }
      observer.next(decoder.decode(value, { stream: true }));
    }
  })();
});
}

2. 使用 scan 构造语言块解析器(Markdown / HTML / JSON / Git log)

ini 复制代码
stream$.pipe(
  scan((state, chunk) => {
    state.buffer += chunk;

    const blocks = extractLanguageBlocks(state.buffer); // 返回 [{type: 'json', content: '...'}]
    state.buffer = getRemainingBuffer(state.buffer); // 剩下没处理完的内容

    blocks.forEach(block => state.blocks.push(block));

    return state;
  }, { buffer: '', blocks: [] }),
  mergeMap(state => from(state.blocks)), // 把 blocks 变成 stream
)

3. 使用 groupBy + 各自的解析逻辑处理

less 复制代码
.pipe(
  groupBy(block => block.type),
  mergeMap(group$ =>
    group$.pipe(
      map(block => parseAndConsume(block)) // 每种语言自己内部 parser + 消费逻辑
    )
  )
)

4. parseAndConsume(block) 结构建议

typescript 复制代码
function parseAndConsume(block: { type: string, content: string }) {
  switch (block.type) {
    case 'json':
      try {
        const obj = JSON.parse(block.content);
        return handleJson(obj); // 解耦的消费者
      } catch {}
      break;
    case 'markdown':
      return renderMarkdown(block.content);
    case 'html':
      return renderHtml(block.content);
    case 'gitlog':
      return parseGitLog(block.content);
    default:
      return null;
  }
}
相关推荐
小小小小小鹿28 分钟前
Ai入门-搭建一个专属的ai学习助手
llm·ai编程
rzl0231 分钟前
SpringBoot(黑马)
java·spring boot·后端
wenb1n39 分钟前
【安全漏洞】防范未然:如何有效关闭不必要的HTTP请求方法,保护你的Web应用
后端
wenb1n39 分钟前
【安全漏洞】网络守门员:深入理解与应用iptables,守护Linux服务器安全
后端
Pomelo_刘金1 小时前
单测原则与实践
后端
香饽饽~、1 小时前
[第十三篇] Spring Boot监控
java·spring boot·后端
硅基宙宇AIGC1 小时前
亲测鹅厂Codebuddy!抢到多个邀请码后发现了AI编程的天花板?(文末送码)
前端·后端
Leinwin1 小时前
Azure可靠性架构指南:构建云时代的高可用系统
后端·python·flask
八苦1 小时前
ACME协议
后端
陈随易1 小时前
牛回,速归!VSCode开启AI的野兽模式究竟有多强
前端·后端·程序员