StreamElement 流式回答
流式呈现整段 AI 回答的元素
安装
pnpm add @talex-touch/tuffex
import { TxStreamElement } from '@talex-touch/tuffex/stream-element'
import '@talex-touch/tuffex/stream-element/style.css'
import '@talex-touch/tuffex/base.css' // 全局引入一次
用法
AI 回答
[n] 按 sources 解析为引用 chip;操作、来源与追问放在 footer 插槽,done 后出现。
示例加载中...
委托渲染的 Markdown
表格、公式等委托片段逐行显影,与原生片段共用一个时钟;reserve 让回放时下方内容不动。
示例加载中...
插槽与状态
parts 直接接收结构化片段;part-<name> 插槽渲染同名的自定义片段。
示例加载中...
最佳实践
- 传目前为止的完整回答,不要只传增量。
- 源头真正结束前保持
streaming为真:结尾写到一半的**bold、`code会先被补全,标记符号不会闪现。 - 属于完整回答的内容(操作、来源、追问)放进
footer插槽并以done为条件;回答末尾没有外边距,footer 自己设间距。 - 复制、分享用你持有的完整回答,不用屏幕上显示的部分。
- 单段文字用
TxStreamText;不需要逐词显影时用TxStreamMarkdown。
API 参考
属性
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
content | string | '' | 目前收到的全部 Markdown。 |
parts | StreamPart[] | — | content 的结构化替代,二者都给时以它为准。 |
streaming | boolean | false | 源头仍在输出。 |
sources | AiSourceItem[] | — | 按模型引用顺序给出;[n] 解析为 sources[n - 1] 的引用 chip。 |
wordMs | number | 24 | 每 wordMs 放出一个词。 |
maxLagMs | number | 600 | 任何词都在到达后这段时间内显示。 |
drainMs | number | 320 | streaming 变为 false 后,在这段时间内放完剩余部分。 |
pauseMs | number | 400 | 超过这段时间没有新词即报告 paused。 |
reveal | 'aurora' | 'hue' | 'blur' | 'languid' | 'none' | 'aurora' | 词的进场方式,预设同 TxStreamText;代码保持语法颜色。 |
caret | boolean | true | 流式进行时在写入位置显示光标。 |
reserve | boolean | false | 完整内容回放时占住最终版面,replay() 时也占住回答当前的高度;streaming 时忽略。 |
renderers | Record<string, Component> | — | 按名称渲染自定义片段的组件;part-<name> 插槽优先。 |
markdownProps | Partial<StreamMarkdownProps> | — | 透传给渲染委托片段的 TxStreamMarkdown。 |
locale | string | 'zh' | Intl.Segmenter 分词所用的语言。 |
事件
| 名称 | 参数 | 说明 |
|---|---|---|
state-change | (state: StreamState) | 流式状态变化时触发。 |
done | — | 每次播放触发一次:末词已显示且源头已结束。 |
cite | (source: AiSourceItem) | 引用 chip 被打开时触发;chip 自身不跳转。 |
插槽
| 名称 | 作用域 | 说明 |
|---|---|---|
caret | { state } | 替换光标,位于文字与代码的写入位置。 |
citation | { source, label, index } | 替换引用 chip。 |
inline | { name, props } | 渲染文字中的自定义行内片段。 |
code | { part, code, streaming } | 替换代码块;code 为已显影的部分。 |
part-<name> | { part, state } | 渲染 { type: 'custom', name } 片段。 |
footer | { state, done } | 回答下方;末词已显示且源头已结束时 done 为真。 |
暴露方法
| 名称 | 类型 | 说明 |
|---|---|---|
state | StreamState | 当前流式状态。 |
replay | () => void | 从第一个词起重播整段回答。 |
skip | () => void | 立即显示全部内容,不播放进场。 |
类型
type StreamPart =
| { type: 'heading', depth: 1 | 2 | 3 | 4 | 5 | 6, inlines: StreamInline[] }
| { type: 'paragraph', inlines: StreamInline[], tight?: boolean }
| { type: 'list', ordered: boolean, start?: number, items: { checked?: boolean, parts: StreamPart[] }[] }
| { type: 'quote', parts: StreamPart[] }
| { type: 'rule' }
| { type: 'code', lang?: string, code: string, filename?: string }
| { type: 'markdown', raw: string }
| { type: 'custom', name: string, props?: Record<string, unknown> }
CSS 变量
| 变量 | 默认值 | 说明 |
|---|---|---|
--tx-stream-reveal-1 / -2 / -3 | 蓝 / 紫 / 粉,随主题变化 | 色带的三个颜色节点,与 TxStreamText 共用。 |
--tx-stream-reveal-duration | 取决于预设 | 由组件按 reveal 写入根节点,无需设置。 |
概述
- 节奏、状态、增量显影与降级行为同 StreamText;所有片段按文档顺序排在同一个时钟上。
- 原生渲染并逐词显影:标题、段落、强调、删除线、行内代码、安全链接、列表(嵌套、任务)、引用、分割线与围栏代码(
TxCodeStream)。 - 表格、公式、mermaid、原始 HTML 与图片整体委托给
TxStreamMarkdown(含其净化与远程图片策略),逐行显影;相邻的委托块合为一个片段。 - 光标只在写入位置:回答中任何时候只有一个,回答结束时收起。
[n]只在纯文字中变成引用 chip(带来源名称的链接),代码与链接文字中不会;没有对应来源时保持为文字。
技术实现
- 建立在
TxStreamText、TxCodeStream与TxStreamMarkdown之上:parse.ts把 Markdown 解析为片段,plan.ts把片段排上时钟。 - 源码:
packages/tuffex/packages/components/src/stream-element/。
查看源码
packages/tuffex/packages/components/src/stream-element/index.ts
使用场景
- 对话回复或助手面板中的回答,带来源、代码与追问。
- 混合正文、列表、表格与公式的生成报告。
- 在卡片或演示里配合
reserve回放存档的回答。
相关组件
- StreamText:流式呈现一段文字,本组件建立在它之上。
- CodeStream:渲染代码片段。
- StreamMarkdown:渲染委托片段。
- Sources、MessageActions 与 SuggestionChips:在
footer插槽里收尾一段回答。