This commit is contained in:
taylorxie
2026-03-09 23:21:30 +08:00
parent caddfb61f1
commit 11e37a157d

View File

@@ -159,16 +159,19 @@ class AiBotPlugin(AbsExtraConfigPlugin):
msgtype=MessageType.TEXT, body="", format=Format.HTML, formatted_body="" msgtype=MessageType.TEXT, body="", format=Format.HTML, formatted_body=""
) )
response_event_id = await evt.respond(placeholder, in_thread=self.config['reply_in_thread']) response_event_id = await evt.respond(placeholder, in_thread=self.config['reply_in_thread'])
self.log.debug("Streaming: placeholder sent")
accumulated = "" accumulated = ""
last_edit_len = 0 last_edit_len = 0
EDIT_THRESHOLD = 50 # 每积累50个字符更新一次消息 EDIT_THRESHOLD = 100 # 每积累100个字符更新一次消息
pending_edit: asyncio.Task = None # 追踪正在发送的编辑任务
try: try:
async for chunk in platform.create_chat_completion_stream(self, evt): async for chunk in platform.create_chat_completion_stream(self, evt):
accumulated += chunk accumulated += chunk
# 只有在没有正在进行的编辑任务时才发送中间更新
if len(accumulated) - last_edit_len >= EDIT_THRESHOLD: if len(accumulated) - last_edit_len >= EDIT_THRESHOLD:
try: if pending_edit is None or pending_edit.done():
display = accumulated + "" display = accumulated + ""
new_content = TextMessageEventContent( new_content = TextMessageEventContent(
msgtype=MessageType.TEXT, msgtype=MessageType.TEXT,
@@ -177,18 +180,28 @@ class AiBotPlugin(AbsExtraConfigPlugin):
formatted_body=markdown.render(display) formatted_body=markdown.render(display)
) )
new_content.set_edit(response_event_id) new_content.set_edit(response_event_id)
await asyncio.wait_for( # 使用fire-and-forget不等待不取消避免mautrix内部锁死锁
self.client.send_message(evt.room_id, new_content), pending_edit = asyncio.ensure_future(
timeout=5.0 self.client.send_message(evt.room_id, new_content)
) )
last_edit_len = len(accumulated) last_edit_len = len(accumulated)
except Exception as edit_err: self.log.debug(f"Streaming: mid-edit fired, accumulated={len(accumulated)}")
self.log.warning(f"Streaming mid-edit failed (skipping): {edit_err}") else:
self.log.debug(f"Streaming: skipping mid-edit, previous still in flight, accumulated={len(accumulated)}")
except Exception as e: except Exception as e:
self.log.exception(f"Streaming error: {e}") self.log.exception(f"Streaming error: {e}")
if not accumulated: if not accumulated:
accumulated = f"Streaming error: {e}" accumulated = f"Streaming error: {e}"
self.log.debug(f"Streaming: loop done, total={len(accumulated)}")
# 等待最后一个中间编辑完成(不取消,避免锁问题)
if pending_edit and not pending_edit.done():
try:
await asyncio.wait_for(asyncio.shield(pending_edit), timeout=10.0)
except Exception:
pass
# 输出最终完整内容 # 输出最终完整内容
if not accumulated: if not accumulated:
accumulated = "(无响应)" accumulated = "(无响应)"
@@ -199,10 +212,9 @@ class AiBotPlugin(AbsExtraConfigPlugin):
formatted_body=markdown.render(accumulated) formatted_body=markdown.render(accumulated)
) )
final_content.set_edit(response_event_id) final_content.set_edit(response_event_id)
await asyncio.wait_for( self.log.debug("Streaming: sending final edit")
self.client.send_message(evt.room_id, final_content), await self.client.send_message(evt.room_id, final_content)
timeout=15.0 self.log.debug("Streaming: final edit done")
)
def get_ai_platform(self) -> Platform: def get_ai_platform(self) -> Platform:
use_platform = self.config.cur_platform use_platform = self.config.cur_platform