62 lines
3.4 KiB
Python
62 lines
3.4 KiB
Python
"""群命令:/总结 昵称,或 /总结群聊。"""
|
||
from wxbot_framework.llm import LLMError
|
||
from wxbot_framework.members import MemberError, SnapshotExpired
|
||
from wxbot_framework.personality import personality_text
|
||
from wxbot_framework.summary import ChatSummarizer, conversation_rows, split_text
|
||
|
||
|
||
class Plugin:
|
||
def on_load(self, ctx):
|
||
self.members = ctx.members
|
||
if not self.members.history_enabled or not self.members.daily_clear:
|
||
raise ValueError("聊天总结需要成员配置 history_enabled 和 daily_clear 都为 true")
|
||
self.summarizer = ChatSummarizer(ctx.llm, chunk_chars=ctx.config.get("chunk_chars", 16000))
|
||
|
||
def on_message(self, message, ctx):
|
||
if message.type != 1 or not message.is_group or message.chat_id not in self.members.groups:
|
||
return
|
||
words = message.text.strip().split(maxsplit=1)
|
||
if not words or words[0] not in ("/总结", "/总结群聊"):
|
||
return
|
||
group = words[0] == "/总结群聊"
|
||
if len(words) != (1 if group else 2):
|
||
ctx.reply(message, "用法:/总结群聊" if group else "用法:/总结 昵称")
|
||
return
|
||
try:
|
||
snapshot = (self.members.today_group_snapshot(message.chat_id) if group else
|
||
self.members.today_snapshot(words[1], message.chat_id))
|
||
except MemberError as error:
|
||
ctx.reply(message, str(error) + ("。" if group else "。请本人先发送 /绑定 昵称。"))
|
||
return
|
||
rows = conversation_rows(snapshot)
|
||
personality = ctx.personality(message)
|
||
guard = lambda: ctx.response_guard(snapshot, personality)
|
||
try:
|
||
if not rows:
|
||
name = "本群" if group else snapshot.member.name
|
||
ctx.reply(message, f"{name}今天还没有可总结的聊天记录。", delivery_guard=guard)
|
||
return
|
||
summarizer = ChatSummarizer(ctx.llm_for(message, personality=personality),
|
||
chunk_chars=self.summarizer.chunk_chars)
|
||
summary = summarizer.summarize(snapshot, rows,
|
||
current=lambda: self.members.snapshot_is_current(snapshot))
|
||
if group:
|
||
participants = len({row["sender_id"] for row in rows})
|
||
title = f"今日群聊总结({snapshot.day},{len(rows)}条,{participants}人)\n"
|
||
else:
|
||
title = f"{snapshot.member.name} 今日聊天({snapshot.day},{len(rows)}条)\n"
|
||
content = personality_text(summary, personality.name) if personality.name == "嘴臭" else title + summary
|
||
for part in split_text(content):
|
||
if not ctx.reply(message, part, delivery_guard=guard):
|
||
raise RuntimeError("原生文本发送未成功")
|
||
ctx.logger.info("聊天总结完成:room=%s scope=%s member=%s records=%d", message.chat_id,
|
||
"group" if group else "member", "本群" if group else snapshot.member.name, len(rows))
|
||
except SnapshotExpired:
|
||
ctx.logger.info("聊天总结已取消:记录或人格状态已变更,room=%s", message.chat_id)
|
||
except LLMError as error:
|
||
ctx.logger.warning("聊天总结失败:%s", error)
|
||
try:
|
||
ctx.reply(message, "暂时无法生成聊天总结,请稍后重试。", delivery_guard=guard)
|
||
except SnapshotExpired:
|
||
pass
|