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;
  }
}
相关推荐
bobz9655 分钟前
分析 docker.service 和 docker.socket 这两个服务各自的作用
后端
野犬寒鸦16 分钟前
力扣hot100:旋转图像(48)(详细图解以及核心思路剖析)
java·数据结构·后端·算法·leetcode
ZHOU_WUYI38 分钟前
FastVLM-0.5B 模型解析
人工智能·llm
phiilo42 分钟前
golang 设置进程退出时kill所有子进程
后端
花花无缺42 分钟前
python自动化-pytest-用例发现规则和要求
后端·python
程序员小假1 小时前
我们来说一说 Cglib 与 JDK 动态代理
后端
Wilber的技术分享1 小时前
【大模型实战笔记 1】Prompt-Tuning方法
人工智能·笔记·机器学习·大模型·llm·prompt
摆烂工程师3 小时前
教你如何认证 Gemini 教育优惠的二次验证,薅个 1年的 Gemini Pro 会员
后端·程序员·gemini
绝无仅有3 小时前
未来教育行业的 Go 服务开发解决方案与实践
后端·面试·github
程序员爱钓鱼3 小时前
Go语言实战案例- 命令行参数解析器
后端·google·go