Files
inspiration-collector/analyzers/weekly_work_report.py

210 lines
7.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Weekly work report synthesizer - reads daily work logs and generates weekly analysis."""
import logging
import os
import sys
from datetime import datetime, timezone, timedelta
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from tools.config import load_secrets, get_output_dir
from tools.llm import DeepSeekClient
logger = logging.getLogger(__name__)
TZ_BEIJING = timezone(timedelta(hours=8))
PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
WORK_WEEKLY_SYSTEM_PROMPT = """你是一个私人工作日志分析师。你的任务是阅读用户过去一周的每日工作日志,生成一篇有深度的周度工作分析。
## 核心原则
1. **概述先行**:给出本周工作的整体面貌——主要精力投向了哪些领域、总体节奏如何。
2. **按主题组织,不按时间罗列**:不要"周一做了X、周二做了Y"。要提炼跨日的工作主线——哪些项目贯穿了整周?哪些任务是单日完成的?
3. **识别模式和趋势**:本周的工作节奏有什么特点?是否出现了新的工作类型?哪些工作在重复发生?是否有一些事在全周的工作日志中反复出现但没有被解决?
4. **产出导向**:本周有什么可量化的产出?写了什么材料?参加了什么会议?完成了什么节点?
5. **前瞻建议**:基于本周工作日志,下周需要关注什么?有什么待办被遗漏了?
## 输出格式
纯 Markdown不要代码块包裹。
### 1. 本周工作概览
一段话概括本周工作的底色——主要在忙什么、节奏如何、核心成果。
### 2. 工作统计
| 维度 | 数值 |
|:---|:---|
| 有工作记录的天数 | X/7 |
| 工作 Memos 总数 | X 条 |
| 涉及标签 | #工作 #会议 ... |
| 单日最高工作量 | 周X · X条 |
### 3. 深入分析
按主题组织:
- 持续性的工作主线(跨日出现的项目/主题)
- 本周重要节点(会议、截止日期、关键决策)
- 工作节奏评价(是否有某天特别忙?是否有连续高压?)
- 新出现的工作类型或关注点
- 被遗漏或被推迟的事项
### 4. 下周关注
基于本周工作轨迹,列出下周需要重点关注的事项。具体到事项+时间节点。
---
注意:
- 如果某天没有工作日志,在统计中注明,但分析中跳过。
- 分析要有观点——不只是"做了什么",更要回答"这意味着什么""接下来该做什么"
- 篇幅不设上限。"""
def read_week_work_logs(week_start, week_end):
"""Read all daily work logs from week_start to week_end."""
all_texts = []
daily_root = get_output_dir("daily")
current = week_start
while current <= week_end:
date_str = current.strftime("%Y-%m-%d")
work_file = os.path.join(daily_root, date_str, "work", f"工作日志_{date_str}.md")
if os.path.exists(work_file):
with open(work_file, "r", encoding="utf-8") as f:
text = f.read()
all_texts.append((date_str, text))
logger.info(f"{date_str}: {len(text)} chars")
else:
logger.info(f"{date_str}: no work log")
current += timedelta(days=1)
return all_texts
def extract_weekly_work_stats(all_texts):
"""Extract statistics from daily work logs."""
total_memos = 0
all_tags = set()
highest_day = ("", 0)
days_with_data = 0
for date_str, text in all_texts:
if "今日无工作" in text:
continue
days_with_data += 1
# Count memos (each ### header with content)
import re
memo_count = len(re.findall(r'^###\s+\d{2}:\d{2}', text, re.MULTILINE))
total_memos += memo_count
if memo_count > highest_day[1]:
highest_day = (date_str, memo_count)
# Extract tags
tag_matches = re.findall(r'#(\w+)', text)
work_tags = {"工作", "会议", "项目", "出差", "培训", "汇报", "材料", "接待", "调研"}
for tag in tag_matches:
if tag in work_tags:
all_tags.add(tag)
return {
"days_with_data": days_with_data,
"total_memos": total_memos,
"top_day": highest_day,
"tags": sorted(all_tags),
}
def generate_weekly_work_report():
"""Main entry: generate weekly work report."""
now = datetime.now(TZ_BEIJING)
yesterday = now - timedelta(days=1)
week_end = yesterday.replace(hour=23, minute=59, second=59)
week_start = (week_end - timedelta(days=6)).replace(hour=0, minute=0, second=0)
logger.info(f"Week range: {week_start.strftime('%Y-%m-%d')}{week_end.strftime('%Y-%m-%d')}")
# Step 1: Read daily work logs
all_texts = read_week_work_logs(week_start, week_end)
if not all_texts:
logger.warning("No work logs found this week")
return None
# Step 2: Extract stats
stats = extract_weekly_work_stats(all_texts)
# Step 3: Build context
context_parts = []
context_parts.append(f"## 本周工作统计\n")
context_parts.append(f"- 有工作记录的天数:{stats['days_with_data']}/7")
context_parts.append(f"- 工作 Memos 总数:{stats['total_memos']}")
context_parts.append(f"- 涉及标签:{' '.join('#' + t for t in stats['tags'])}")
if stats['top_day'][0]:
context_parts.append(f"- 单日最高:{stats['top_day'][0]} · {stats['top_day'][1]}")
context_parts.append("")
context_parts.append("## 每日工作日志原文\n")
for date_str, text in all_texts:
context_parts.append(f"### {date_str}\n")
context_parts.append(text[:3500]) # Trim each day
context_parts.append("\n---\n")
full_context = "\n".join(context_parts)
# Step 4: Call DeepSeek API
secrets = load_secrets()
client = DeepSeekClient(secrets["deepseek_api_key"])
logger.info(f"Sending to DeepSeek... ({len(full_context)} chars)")
result = client.chat(
system_prompt=WORK_WEEKLY_SYSTEM_PROMPT,
user_message=full_context,
temperature=0.5,
)
# Step 5: Assemble and write
year = week_start.strftime("%Y")
week_num = week_start.isocalendar()[1]
week_start_str = week_start.strftime("%m%d")
week_end_str = week_end.strftime("%m%d")
filename = f"工作周报_W{week_num}_{week_start_str}-{week_end_str}.md"
header = f"""# 工作周报 · {week_start.strftime('%Y.%m.%d')}{week_end.strftime('%Y.%m.%d')}
> 基于 {stats['days_with_data']}/7 天工作日志生成 · 依托 DeepSeek API 分析
"""
final_report = header + result
output_dir = os.path.join(get_output_dir("weekly"), "work")
os.makedirs(output_dir, exist_ok=True)
output_path = os.path.join(output_dir, filename)
with open(output_path, "w", encoding="utf-8") as f:
f.write(final_report)
logger.info(f"Report saved to {output_path}")
return output_path
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
path = generate_weekly_work_report()
if path:
print(f"DONE: {path}")
else:
print("FAILED: No report generated")
sys.exit(1)