前端界面内的流式传输
目前前端卡最大的问题是依赖于由正则替换得来的消息楼层 iframe 代码块;而流式传输过程中,每次收到新的流式文本,正则替换都会重新应用,这就导致消息楼层 iframe 只能一直是代码块,而直到文本输出完成才能渲染。 以下汇总了能想到的流式传输前端卡思路。
思路1: 自制前端界面负责流式传输文本处理(推荐)
方法1: 不再依靠酒馆发送键,在消息楼层 iframe 中自行设计发送功能(简单)
一个简单的示例是用消息楼层 iframe 制作手机微信界面,在界面中专门有一个发送键,点击后对话的角色将会直接回复消息
也就是说,
- 玩家只在顶楼的消息楼层 iframe 内进行游玩,不再生成新的楼层;
- 对于玩家的输入,我们通过酒馆助手的
generate
、generateRaw
命令自行要求 ai 回复; - 为了让消息记录下来,我们用
setChatMessage
将它保存到消息文件中(或自制存档机制?)。
方法2: 不再依靠酒馆显示,用全局脚本 iframe 获取流式传输文本并生成界面(可能更自由)
既然酒馆的流式传输在显示上有问题,我们不再依赖于酒馆的显示,不再是用正则替换一个消息楼层 iframe 出来用于渲染。
作为替代,我们使用 脚本库 来监听流式传输文本:Discord帖子
- 监听
tavern_events.MESSAGE_SEND -> message_id
,我们可以知道玩家要求酒馆调用 ai 生成; - 监听
tavern_events.STREAM_TOKEN_RECEIVED - > text
,我们可以获取流式传输文本; - 监听
tavern_events.MESSAGE_RECEIVED -> message_id
,我们可以知道酒馆结束了回复。
由此,我们完全可以收集到流式传输文本,将它发送到一个你自制的前端界面中。
而为了让那个前端界面显示出来,你可以使用 JQuery。 JQuery 可以访问界面 html 元素,以修改消息楼层的显示文本为例(仅修改本次显示,不会修改实际的消息文件):
typescript
$(`div.mes[mesid = "${message_id}"]`,window.parent.document).find(`div.mes_text`).append(`<p>新的文本</p>`);
思路2: 让流式传输出来的文本可读
另一种思路是直接舍弃酒馆助手常见的“正则替换正文,从而让正文变成会被渲染的代码块”。
作为替代,直接让全局脚本在消息接收完毕时处理变量然后修改消息,在修改消息时直接连同要渲染的代码块一起发送过去。 这样,玩家可以先看文本,等输出完后再看到前端美化结果:
- 全局脚本监听
tavern_events.MESSAGE_RECEIVED -> message_id
,获取新消息楼层中的 ai 输出; - 全局脚本处理消息中的计算;
- 全局脚本通过
getTavernRegexes
或getLorebookEntries
等,来得到存储在正则、世界书条目或其他地方的消息楼层 iframe(要渲染的<body>
代码块); - 全局脚本将之前的计算结果填入到获取到的消息楼层 iframe 中;
- 全局脚本用
setChatMessage
将消息楼层修改为该消息楼层 iframe。