mirror of
https://github.com/Nezumi-2711/astrbot_plugin_qq_group_daily_analysis.git
synced 2026-09-22 13:38:43 +00:00
[v1.2.0] (话题分析处理) 增加了对 LLM 话题分析部分的提示词提示规范,并且提供正则处理来提高服务可用性
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
# QQ群日常分析插件
|
# QQ群日常分析插件
|
||||||
|
|
||||||
|
|
||||||
[](https://github.com/SXP-Simon/astrbot-qq-group-daily-analysis)
|
[](https://github.com/SXP-Simon/astrbot-qq-group-daily-analysis)
|
||||||
[](https://github.com/AstrBotDevs/AstrBot)
|
[](https://github.com/AstrBotDevs/AstrBot)
|
||||||
[](LICENSE)
|
[](LICENSE)
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ class GroupStatistics:
|
|||||||
"astrbot_qq_group_daily_analysis",
|
"astrbot_qq_group_daily_analysis",
|
||||||
"SXP-Simon",
|
"SXP-Simon",
|
||||||
"QQ群日常分析插件 - 生成精美的群聊日常分析报告",
|
"QQ群日常分析插件 - 生成精美的群聊日常分析报告",
|
||||||
"1.1.0",
|
"1.2.0",
|
||||||
"https://github.com/SXP-Simon/astrbot-qq-group-daily-analysis"
|
"https://github.com/SXP-Simon/astrbot-qq-group-daily-analysis"
|
||||||
)
|
)
|
||||||
class QQGroupDailyAnalysis(Star):
|
class QQGroupDailyAnalysis(Star):
|
||||||
@@ -802,9 +802,22 @@ class QQGroupDailyAnalysis(Star):
|
|||||||
# step = len(text_messages) // 100
|
# step = len(text_messages) // 100
|
||||||
# text_messages = text_messages[::step]
|
# text_messages = text_messages[::step]
|
||||||
|
|
||||||
# 构建LLM提示词
|
# 构建LLM提示词,清理消息内容
|
||||||
|
def clean_message_content(content):
|
||||||
|
"""清理消息内容,移除可能影响JSON解析的字符"""
|
||||||
|
import re
|
||||||
|
# 替换中文引号
|
||||||
|
content = content.replace('"', '"').replace('"', '"')
|
||||||
|
content = content.replace(''', "'").replace(''', "'")
|
||||||
|
# 移除或替换其他特殊字符
|
||||||
|
content = content.replace('\n', ' ').replace('\r', ' ')
|
||||||
|
content = content.replace('\t', ' ')
|
||||||
|
# 移除可能的控制字符
|
||||||
|
content = re.sub(r'[\x00-\x1f\x7f-\x9f]', '', content)
|
||||||
|
return content.strip()
|
||||||
|
|
||||||
messages_text = "\n".join([
|
messages_text = "\n".join([
|
||||||
f"[{msg['time']}] {msg['sender']}: {msg['content']}"
|
f"[{msg['time']}] {msg['sender']}: {clean_message_content(msg['content'])}"
|
||||||
for msg in text_messages
|
for msg in text_messages
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -825,14 +838,29 @@ class QQGroupDailyAnalysis(Star):
|
|||||||
群聊记录:
|
群聊记录:
|
||||||
{messages_text}
|
{messages_text}
|
||||||
|
|
||||||
请以JSON格式返回,格式如下:
|
重要:必须返回标准JSON格式,严格遵守以下规则:
|
||||||
|
1. 只使用英文双引号 " 不要使用中文引号 " "
|
||||||
|
2. 字符串内容中的引号必须转义为 \"
|
||||||
|
3. 多个对象之间用逗号分隔
|
||||||
|
4. 数组元素之间用逗号分隔
|
||||||
|
5. 不要在JSON外添加任何文字说明
|
||||||
|
6. 描述内容避免使用特殊符号,用普通文字表达
|
||||||
|
|
||||||
|
请严格按照以下JSON格式返回,确保可以被标准JSON解析器解析:
|
||||||
[
|
[
|
||||||
{{
|
{{
|
||||||
"topic": "话题名称",
|
"topic": "话题名称",
|
||||||
"contributors": ["参与者1", "参与者2"],
|
"contributors": ["用户1", "用户2"],
|
||||||
"detail": "详细描述话题内容、讨论要点和结论,并且符合约束的准则。"
|
"detail": "话题描述内容"
|
||||||
|
}},
|
||||||
|
{{
|
||||||
|
"topic": "另一个话题",
|
||||||
|
"contributors": ["用户3", "用户4"],
|
||||||
|
"detail": "另一个话题的描述"
|
||||||
}}
|
}}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
注意:返回的内容必须是纯JSON,不要包含markdown代码块标记或其他格式
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# 调用LLM
|
# 调用LLM
|
||||||
@@ -843,8 +871,8 @@ class QQGroupDailyAnalysis(Star):
|
|||||||
|
|
||||||
response = await provider.text_chat(
|
response = await provider.text_chat(
|
||||||
prompt=prompt,
|
prompt=prompt,
|
||||||
max_tokens=3000,
|
max_tokens=6000, # 增加token限制以避免响应被截断
|
||||||
temperature=0.3
|
temperature=0.6
|
||||||
)
|
)
|
||||||
|
|
||||||
# 解析响应
|
# 解析响应
|
||||||
@@ -856,12 +884,129 @@ class QQGroupDailyAnalysis(Star):
|
|||||||
# 尝试解析JSON
|
# 尝试解析JSON
|
||||||
try:
|
try:
|
||||||
import re
|
import re
|
||||||
json_match = re.search(r'\[.*\]', result_text, re.DOTALL)
|
# 提取JSON部分
|
||||||
|
json_match = re.search(r'\[.*?\]', result_text, re.DOTALL)
|
||||||
if json_match:
|
if json_match:
|
||||||
topics_data = json.loads(json_match.group())
|
json_text = json_match.group()
|
||||||
return [SummaryTopic(**topic) for topic in topics_data[:5]]
|
logger.debug(f"话题分析JSON原文: {json_text[:500]}...")
|
||||||
except:
|
|
||||||
pass
|
# 强化JSON清理和修复
|
||||||
|
def fix_json(text):
|
||||||
|
# 移除markdown代码块标记
|
||||||
|
text = re.sub(r'```json\s*', '', text)
|
||||||
|
text = re.sub(r'```\s*$', '', text)
|
||||||
|
|
||||||
|
# 基础清理
|
||||||
|
text = text.replace('\n', ' ').replace('\r', ' ')
|
||||||
|
text = re.sub(r'\s+', ' ', text)
|
||||||
|
|
||||||
|
# 替换中文引号为英文引号
|
||||||
|
text = text.replace('"', '"').replace('"', '"')
|
||||||
|
text = text.replace(''', "'").replace(''', "'")
|
||||||
|
|
||||||
|
# 处理字符串内容中的特殊字符
|
||||||
|
# 转义字符串内的双引号
|
||||||
|
def escape_quotes_in_strings(match):
|
||||||
|
content = match.group(1)
|
||||||
|
# 转义内部的双引号
|
||||||
|
content = content.replace('"', '\\"')
|
||||||
|
return f'"{content}"'
|
||||||
|
|
||||||
|
# 先处理字段值中的引号
|
||||||
|
text = re.sub(r'"([^"]*(?:"[^"]*)*)"', escape_quotes_in_strings, text)
|
||||||
|
|
||||||
|
# 修复截断的JSON
|
||||||
|
if not text.endswith(']'):
|
||||||
|
last_complete = text.rfind('}')
|
||||||
|
if last_complete > 0:
|
||||||
|
text = text[:last_complete + 1] + ']'
|
||||||
|
|
||||||
|
# 修复常见的JSON格式问题
|
||||||
|
# 1. 修复缺失的逗号
|
||||||
|
text = re.sub(r'}\s*{', '}, {', text)
|
||||||
|
|
||||||
|
# 2. 确保字段名有引号
|
||||||
|
text = re.sub(r'([{,]\s*)([a-zA-Z_][a-zA-Z0-9_]*)\s*:', r'\1"\2":', text)
|
||||||
|
|
||||||
|
# 3. 移除多余的逗号
|
||||||
|
text = re.sub(r',\s*}', '}', text)
|
||||||
|
text = re.sub(r',\s*]', ']', text)
|
||||||
|
|
||||||
|
return text
|
||||||
|
|
||||||
|
json_text = fix_json(json_text)
|
||||||
|
logger.debug(f"修复后的JSON: {json_text[:300]}...")
|
||||||
|
|
||||||
|
topics_data = json.loads(json_text)
|
||||||
|
topics = [SummaryTopic(**topic) for topic in topics_data[:5]]
|
||||||
|
logger.info(f"话题分析成功,解析到 {len(topics)} 个话题")
|
||||||
|
return topics
|
||||||
|
else:
|
||||||
|
logger.warning(f"话题分析响应中未找到JSON格式,响应内容: {result_text[:200]}...")
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
logger.error(f"话题分析JSON解析失败: {e}")
|
||||||
|
logger.debug(f"修复后的JSON: {json_text if 'json_text' in locals() else 'N/A'}")
|
||||||
|
logger.debug(f"原始响应: {result_text}")
|
||||||
|
|
||||||
|
# 如果JSON解析失败,尝试用正则表达式提取话题信息
|
||||||
|
try:
|
||||||
|
logger.info("JSON解析失败,尝试正则表达式提取话题...")
|
||||||
|
topics = []
|
||||||
|
|
||||||
|
# 更强的正则表达式提取话题信息,处理转义字符
|
||||||
|
# 匹配每个完整的话题对象
|
||||||
|
topic_pattern = r'\{\s*"topic":\s*"([^"]+)"\s*,\s*"contributors":\s*\[([^\]]+)\]\s*,\s*"detail":\s*"([^"]*(?:\\.[^"]*)*)"\s*\}'
|
||||||
|
matches = re.findall(topic_pattern, result_text, re.DOTALL)
|
||||||
|
|
||||||
|
if not matches:
|
||||||
|
# 尝试更宽松的匹配
|
||||||
|
topic_pattern = r'"topic":\s*"([^"]+)"[^}]*"contributors":\s*\[([^\]]+)\][^}]*"detail":\s*"([^"]*(?:\\.[^"]*)*)"'
|
||||||
|
matches = re.findall(topic_pattern, result_text, re.DOTALL)
|
||||||
|
|
||||||
|
for match in matches[:5]: # 最多5个话题
|
||||||
|
topic_name = match[0].strip()
|
||||||
|
contributors_str = match[1].strip()
|
||||||
|
detail = match[2].strip()
|
||||||
|
|
||||||
|
# 清理detail中的转义字符
|
||||||
|
detail = detail.replace('\\"', '"').replace('\\n', ' ').replace('\\t', ' ')
|
||||||
|
|
||||||
|
# 解析参与者列表
|
||||||
|
contributors = []
|
||||||
|
for contrib in re.findall(r'"([^"]+)"', contributors_str):
|
||||||
|
contributors.append(contrib.strip())
|
||||||
|
|
||||||
|
if not contributors:
|
||||||
|
contributors = ["群友"]
|
||||||
|
|
||||||
|
topics.append(SummaryTopic(
|
||||||
|
topic=topic_name,
|
||||||
|
contributors=contributors[:5], # 最多5个参与者
|
||||||
|
detail=detail # 限制长度
|
||||||
|
))
|
||||||
|
|
||||||
|
if topics:
|
||||||
|
logger.info(f"正则表达式提取成功,获得 {len(topics)} 个话题")
|
||||||
|
return topics
|
||||||
|
else:
|
||||||
|
# 最后的降级方案
|
||||||
|
logger.info("正则表达式提取失败,使用默认话题...")
|
||||||
|
return [SummaryTopic(
|
||||||
|
topic="群聊讨论",
|
||||||
|
contributors=["群友"],
|
||||||
|
detail="今日群聊内容丰富,涵盖多个话题"
|
||||||
|
)]
|
||||||
|
except Exception as regex_e:
|
||||||
|
logger.error(f"正则表达式提取失败: {regex_e}")
|
||||||
|
# 最终降级方案
|
||||||
|
return [SummaryTopic(
|
||||||
|
topic="群聊讨论",
|
||||||
|
contributors=["群友"],
|
||||||
|
detail="今日群聊内容丰富,涵盖多个话题"
|
||||||
|
)]
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"话题分析处理失败: {e}")
|
||||||
|
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -13,6 +13,6 @@ help: | # 插件的帮助信息
|
|||||||
命令:
|
命令:
|
||||||
/群分析 [天数] - 分析群聊活动
|
/群分析 [天数] - 分析群聊活动
|
||||||
/分析设置 [操作] - 管理设置(enable/disable/status/test)
|
/分析设置 [操作] - 管理设置(enable/disable/status/test)
|
||||||
version: v1.1.0 # 插件版本号。格式:v1.1.1 或者 v1.1
|
version: v1.2.0 # 插件版本号。格式:v1.1.1 或者 v1.1
|
||||||
author: SXP-Simon # 作者
|
author: SXP-Simon # 作者
|
||||||
repo: https://github.com/SXP-Simon/astrbot-qq-group-daily-analysis # 插件的仓库地址
|
repo: https://github.com/SXP-Simon/astrbot-qq-group-daily-analysis # 插件的仓库地址
|
||||||
Reference in New Issue
Block a user