diff --git a/src/ai_client.py b/src/ai_client.py index ceaa693..2bba533 100644 --- a/src/ai_client.py +++ b/src/ai_client.py @@ -33,7 +33,7 @@ SYSTEM_PROMPT = """你是一个邮件摘要助手。请分析邮件内容并以 - category: 邮件类型。推广邮件(营销、促销、广告、 newsletter 推广等)标记为 "promotion";验证码邮件标记为 "notification";普通邮件标记为 "normal" - verification_code: 仅当 category 为 "notification" 且邮件包含验证码时填写,只填纯数字验证码(如「123456」「888888」),不包含平台名。非验证码邮件留空字符串 - app_name: 仅当 category 为 "notification" 且邮件包含验证码时填写,填写发送验证码的应用/平台名称(如「GitHub」「微信」「Kraken」)。非验证码邮件留空字符串 -- links: 从邮件正文中提取用户需要点击的链接。只提取有意义的、用户可能需要操作的链接(如确认链接、登录链接、下载链接、账单链接等),不要提取退订链接、追踪像素、邮件头中的无关链接。每条包含简短描述文字和完整 URL。最多 3 条。没有需要点击的链接时为空数组 +- links: 从邮件正文中提取用户需要点击的链接。只提取有意义的、用户可能需要操作的链接(如确认链接、登录链接、下载链接、账单链接、退订链接等),不要提取、追踪像素、邮件头中的无关链接。每条包含简短描述文字和完整 URL。最多 3 条。没有需要点击的链接时为空数组 - summary 要简洁,把需要知道的信息浓缩成一句话,不需要分条列出 - 当 category 为 "promotion" 时,summary 直接写成一句话:「[发送方名称] 在推广 [推广的产品/服务/活动]」,例如「腾讯云在推广双十一云服务器折扣」。此时 can_reply 为 false,reply_suggestions 为空数组 - can_reply 为 false 表示无需回复或不适合建议回复(此时忽略 reply_suggestions) @@ -47,7 +47,7 @@ SYSTEM_PROMPT = """你是一个邮件摘要助手。请分析邮件内容并以 def summarize_email(ai_cfg: AIConfig, recipient: str, subject: str, sender: str, body: str, account: str = "") -> dict[str, Any]: body_preview = body[:80].replace("\n", " ") logger.info("AI 摘要请求: sender=%s subject=%s body_preview=%s", sender, subject, body_preview) - content = f"收件人: {recipient}\n发件人: {sender}\n主题: {subject}\n账号: {account}\n正文:\n{body[:4000]}" + content = f"收件人: {recipient}\n发件人: {sender}\n主题: {subject}\n账号: {account}\n正文:\n{body}" payload = { "model": ai_cfg.model, @@ -70,7 +70,7 @@ PROMO_DETAIL_PROMPT = """你是一个邮件分析助手。用户想了解更多 @retry() def expand_promo_detail(ai_cfg: AIConfig, sender: str, subject: str, body: str) -> list[str]: logger.info("AI 推广详情请求: sender=%s subject=%s", sender, subject) - content = f"发件人: {sender}\n主题: {subject}\n正文:\n{body[:4000]}" + content = f"发件人: {sender}\n主题: {subject}\n正文:\n{body}" payload = { "model": ai_cfg.model, "messages": [ @@ -104,7 +104,7 @@ def generate_more_replies(ai_cfg: AIConfig, sender: str, subject: str, body: str previous_suggestions: list[dict], user_hint: str = "") -> list[dict]: logger.info("AI 换批请求: sender=%s subject=%s user_hint=%s prev=%d 条", sender, subject, user_hint or "(无)", len(previous_suggestions)) - content = f"发件人: {sender}\n主题: {subject}\n正文:\n{body[:4000]}\n\n已生成过的回复:\n" + content = f"发件人: {sender}\n主题: {subject}\n正文:\n{body}\n\n已生成过的回复:\n" for i, s in enumerate(previous_suggestions, 1): content += f"{i}. {s['text']}\n" if user_hint: @@ -134,7 +134,7 @@ def _call_deepseek(ai_cfg: AIConfig, payload: dict) -> dict: f"{ai_cfg.base_url.rstrip('/')}/chat/completions", headers=headers, json=payload, - timeout=60, + timeout=120, ) elapsed = time.time() - t0 resp.raise_for_status() diff --git a/src/summarizer.py b/src/summarizer.py index 3a436ed..d01901a 100644 --- a/src/summarizer.py +++ b/src/summarizer.py @@ -50,5 +50,6 @@ def tg_send_and_mark(cfg: Config, info: dict): original_recipient=info.get("original_recipient", ""), original_reply_to=info.get("original_reply_to", ""), account_email=info.get("account_email", "")) + # 只有 send_summary 成功返回(未抛异常)才标记已读 mark_as_seen(acct, [info["uid"]]) - logger.info(f" 已发送并标记已读") + logger.info(f" TG 发送成功,已标记已读")