feat: news categorized by topic (5 categories, 5 each), with subtitles

This commit is contained in:
Beast
2026-06-14 13:43:12 +08:00
parent ba98a79459
commit d36103f3e8

View File

@ -1,4 +1,4 @@
"""Use DeepSeek to summarize top news into 500-word Chinese briefs.""" """Use DeepSeek to summarize top news into categorized Chinese briefs (5 per category)."""
import json, os, requests import json, os, requests
from datetime import datetime, timezone, timedelta from datetime import datetime, timezone, timedelta
@ -20,38 +20,50 @@ def load_raw_news():
def summarize(items): def summarize(items):
"""Send raw news to DeepSeek and get summarized articles."""
# Build a condensed input for the AI (titles + summaries)
news_text = "" news_text = ""
for i, item in enumerate(items[:20], 1): for i, item in enumerate(items[:30], 1):
title = item.get("title", "") title = item.get("title", "")
summary = item.get("summary", "")[:150].replace("<", "").replace(">", "") summary = item.get("summary", "")[:150].replace("<", "").replace(">", "")
news_text += f"{i}. [{item['source']}] {title}\n {summary}\n\n" source = item.get("source", "")
news_text += f"{i}. [{source}] {title}\n {summary}\n\n"
prompt = f"""你是一个新闻整理助手。以下是来自BBC世界新闻、BBC中文、Hacker News的最新资讯。 prompt = f"""你是一个新闻整理助手。以下是来自BBC世界新闻、BBC中文、新浪新闻、涌报、Hacker News的最新资讯。
请从以上内容中精选出最重要的10条新闻每条用中文写成一段300-500字的精炼摘要。 请从以上内容中精选出最重要的新闻按以下分类组织每个分类最多5条
要求:
1. 选择真正重要、有信息量的新闻(优先世界大事、科技突破、财经动向)
2. 每条摘要独立、完整,包含核心事实和背景
3. 语言简洁有力,适合快速阅读
4. 按重要性排序
5. 每条附上来源标签
输出格式为JSON数组 分类要求
[ - 国际要闻:全球政治、外交、军事
- 科技前沿AI、软件、硬件、互联网
- 财经动向:市场、经济、商业
- 中国热点:中国相关新闻
- 社会生活:健康、环境、文化、民生
每条新闻格式:
## 小标题10字以内概括核心
正文200-300字中文精炼摘要包含核心事实和背景
输出格式为JSON
{{ {{
"rank": 1, "categories": [
"title": "精炼标题20字以内", {{
"source": "BBC World", "name": "国际要闻",
"summary": "300-500字中文摘要..." "items": [
{{"rank": 1, "subtitle": "小标题", "title": "原标题", "source": "BBC World", "summary": "正文..."}},
...
]
}}, }},
... ...
] ]
}}
只输出JSON不要其他内容。 注意:
- 每个分类最多5条
- 小标题要精炼抓人
- 摘要要有信息量,不要空话
- 只输出JSON不要其他内容
今日要闻原始数据 原始新闻
{news_text}""" {news_text}"""
resp = requests.post( resp = requests.post(
@ -60,35 +72,39 @@ def summarize(items):
json={ json={
"model": MODEL, "model": MODEL,
"messages": [{"role": "user", "content": prompt}], "messages": [{"role": "user", "content": prompt}],
"temperature": 0.5, "temperature": 0.4,
"max_tokens": 6000, "max_tokens": 8000,
}, },
timeout=120, timeout=180,
) )
if resp.status_code != 200: if resp.status_code != 200:
print(f"API error: {resp.status_code} {resp.text[:200]}") print(f"API error: {resp.status_code} {resp.text[:200]}")
return None return None
result = resp.json() content = resp.json()["choices"][0]["message"]["content"]
content = result["choices"][0]["message"]["content"]
# Parse JSON from response
content = content.strip() content = content.strip()
if content.startswith("```"): if content.startswith("```"):
content = content.split("\n", 1)[1] lines = content.split("\n")
content = content.rsplit("\n", 1)[0] content = "\n".join(lines[1:-1]) if lines[-1].strip() == "```" else "\n".join(lines[1:])
if content.endswith("```"):
content = content[:-3]
content = content.strip()
try: try:
articles = json.loads(content) result = json.loads(content)
except: except:
print(f"JSON parse failed, content: {content[:300]}") # Try to fix common JSON issues
content = content.strip()
# Remove trailing commas before closing brackets
import re
content = re.sub(r',\s*}', '}', content)
content = re.sub(r',\s*]', ']', content)
try:
result = json.loads(content)
except:
print(f"JSON parse failed, len={len(content)}")
print(f"First 800 chars: {content[:800]}")
return None return None
return articles return result
if __name__ == "__main__": if __name__ == "__main__":
@ -98,21 +114,23 @@ if __name__ == "__main__":
print("No news data") print("No news data")
exit(0) exit(0)
print(f"Loaded {len(items)} raw news items. Summarizing...") print(f"Loaded {len(items)} raw news items. AI summarizing by category...")
articles = summarize(items) data = summarize(items)
if not articles: if not data:
print("Summarization failed") print("Summarization failed")
exit(1) exit(1)
result = { result = {
"updated_at": now, "updated_at": now,
"total": len(articles), "categories": data.get("categories", []),
"articles": articles,
} }
total = sum(len(c["items"]) for c in result["categories"])
os.makedirs(os.path.dirname(OUTPUT), exist_ok=True) os.makedirs(os.path.dirname(OUTPUT), exist_ok=True)
with open(OUTPUT, "w", encoding="utf-8") as f: with open(OUTPUT, "w", encoding="utf-8") as f:
json.dump(result, f, ensure_ascii=False, indent=2) json.dump(result, f, ensure_ascii=False, indent=2)
print(f"Written {len(articles)} summarized articles to {OUTPUT}") print(f"Written {total} articles across {len(result['categories'])} categories")
for c in result["categories"]:
print(f" {c['name']}: {len(c['items'])} items")