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;
  }
}
相关推荐
码事漫谈4 小时前
黄仁勋被裁第一天,就收到了橄榄枝
后端
金銀銅鐵5 小时前
带您看懂字节码指令(二):空循环里有什么
java·后端·ai编程
皮皮林5516 小时前
比 Xshell 还好用的 SSH 客户端神器,MobaXterm 太爱了!
后端
我不会起名字3227 小时前
会话缓存失效排查:区分 Redis 失效与节点广播
redis·后端·go·即时通讯·im·故障排查
深入云栈9 小时前
Netty 4.2.x 源码深度解析 (二十三):ByteBuf 核心设计 —— 索引、类型与零拷贝
java·后端·架构
JackJiang9 小时前
IM踩坑:聊天消息ID怎么设计?一个UUID搞不定,我用双ID解决
后端·架构
开心猴爷9 小时前
iOS 上架 App 流程
后端·ios
code_Bo9 小时前
不只命令行:我把跨 Agent 会话同步做成了桌面应用
前端·javascript·后端
用户83562907805110 小时前
使用 Python 控制 Excel 工作表的分页位置
后端·python
用户83562907805110 小时前
Python 如何在 Word 中添加和管理文档变量
后端·python