feat: init AI email summarization bot

- Multi-account IMAP email polling with UID tracking
- DeepSeek API integration with JSON Mode structured output
- Telegram notification with formatted MarkdownV2 message
- YAML config with dataclass-based type validation
- Graceful shutdown on SIGINT/SIGTERM
- 60s default polling interval
This commit is contained in:
2026-07-02 19:45:34 +08:00
commit e2826a3e3b
11 changed files with 364 additions and 0 deletions

48
src/ai_client.py Normal file
View File

@@ -0,0 +1,48 @@
import json
from typing import Any
import requests
from src.config import AIConfig
SYSTEM_PROMPT = """你是一个邮件摘要助手。请分析邮件内容并以 JSON 格式返回结构化摘要。
返回格式必须严格遵循以下 JSON schema
{
"subject": "邮件主题",
"sender": "发件人",
"summary": "50字以内的核心摘要",
"priority": "high/medium/low",
"action_required": true/false,
"action_items": ["待办事项1", "待办事项2"],
"key_points": ["关键要点1", "关键要点2"]
}
只返回 JSON不要包含任何其他文字。"""
def summarize_email(ai_cfg: AIConfig, subject: str, sender: str, body: str) -> dict[str, Any]:
content = f"发件人: {sender}\n主题: {subject}\n正文:\n{body[:4000]}"
payload = {
"model": ai_cfg.model,
"messages": [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": content},
],
"response_format": {"type": "json_object"},
}
headers = {
"Authorization": f"Bearer {ai_cfg.api_key}",
"Content-Type": "application/json",
}
resp = requests.post(
f"{ai_cfg.base_url.rstrip('/')}/chat/completions",
headers=headers,
json=payload,
timeout=60,
)
resp.raise_for_status()
result = resp.json()
raw = result["choices"][0]["message"]["content"]
return json.loads(raw)