清理城市农业类别 + 修复采集器LLM直接选题
清理: - sustainability_cases.json移除GLO-001/CHN-001城市农业案例,替换为循环消费 - initial_cases.json移除case8东京垂直农场/case26城市屋顶农场 - strategy_topics_to_json.py移除B01/B05/D05三个种菜选题 - collector.py移除城市农业→循环消费映射,更新注释 - 删除fix_collector.py/test_image_gen.py/generate_images.py等遗留脚本 - 删除import_topics.py和automation/下旧版生成脚本 修复: - collector.py _generate_topic_with_llm不再依赖搜索结果,无搜索时LLM直接生成 - run()始终调用LLM,不再要求web_search_results非空 - 替换sources.yaml中已失效的RSS源(澎湃/虎嗅/中新网→36氪/少数派)
This commit is contained in:
+22
-35
@@ -59,7 +59,7 @@ class SustainabilityCase:
|
||||
"""可持续性案例"""
|
||||
id: str
|
||||
country: str
|
||||
category: str # 子领域:城市农业、零浪费生活等
|
||||
category: str # 子领域:零浪费生活、循环消费等
|
||||
title: str
|
||||
core_idea: str
|
||||
data_facts: str
|
||||
@@ -254,7 +254,6 @@ class SustainabilityCollector:
|
||||
'低碳出行': '低碳出行',
|
||||
'循环消费': '循环消费',
|
||||
'环保科技': '环保科技产品',
|
||||
'城市农业': '循环消费',
|
||||
}
|
||||
case_data['category'] = category_map.get(field, field[:4] if len(field) > 4 else field)
|
||||
|
||||
@@ -378,57 +377,47 @@ class SustainabilityCollector:
|
||||
logger.warning(f"web_search失败 {source.name}: {e}")
|
||||
return []
|
||||
|
||||
def _generate_topic_with_llm(self, search_results: List[Dict]) -> Optional[SustainabilityTopic]:
|
||||
"""用LLM从搜索结果中生成选题"""
|
||||
def _generate_topic_with_llm(self, search_results: Optional[List[Dict]] = None) -> Optional[SustainabilityTopic]:
|
||||
"""用LLM生成选题(有搜索结果时参考,无结果时直接生成)"""
|
||||
try:
|
||||
from app.core.nvidia_client import call_llm
|
||||
except ImportError:
|
||||
logger.warning("LLM不可用,跳过AI选题生成")
|
||||
return None
|
||||
|
||||
if not search_results:
|
||||
return None
|
||||
|
||||
# 整理搜索结果摘要
|
||||
summaries = []
|
||||
for r in search_results[:6]:
|
||||
summaries.append(f"- {r.get('title','')}: {r.get('content','')[:150]}")
|
||||
search_text = "\n".join(summaries)
|
||||
|
||||
# 获取已有选题做去重参考
|
||||
existing = self._get_existing_titles()
|
||||
existing_hint = ""
|
||||
if existing:
|
||||
existing_hint = f"\n以下选题已存在,请避免重复:\n" + "\n".join(f"- {t[:30]}" for t in existing[-10:])
|
||||
existing_hint = "\n已存在选题(避免重复):" + "、".join(t[:20] for t in existing[-8:])
|
||||
|
||||
# 按日期选不同类别
|
||||
categories = self.config.get("sustainability_categories", ["可持续生活"])
|
||||
day_idx = datetime.datetime.now().timetuple().tm_yday % len(categories)
|
||||
target_category = categories[day_idx]
|
||||
|
||||
prompt = f"""你是一个内容策略师。基于以下搜索结果,生成一个有价值、适合中文互联网传播的选题。
|
||||
search_section = ""
|
||||
if search_results:
|
||||
summaries = [f"- {r.get('title','')}: {r.get('content','')[:120]}" for r in search_results[:4]]
|
||||
search_section = "搜索结果参考:\n" + "\n".join(summaries) + "\n"
|
||||
|
||||
prompt = f"""你是一个内容策略师。生成一个面向中国年轻读者、有价值、适合传播的选题。
|
||||
|
||||
目标类别:{target_category}
|
||||
|
||||
搜索结果:
|
||||
{search_text}
|
||||
{search_section}
|
||||
{existing_hint}
|
||||
|
||||
请生成一个选题,输出JSON格式:
|
||||
{{
|
||||
"title": "标题(20字内,有吸引力,含核心关键词)",
|
||||
生成一个选题,直接输出JSON(不要其他文字):
|
||||
{{{{
|
||||
"title": "标题(20字内,含核心关键词,避免「新趋势」「指南」这类烂尾词)",
|
||||
"core_concept": "核心观点(一句话说清独特价值)",
|
||||
"audience_pain": "受众痛点(真实用户的困惑或需求)",
|
||||
"unique_angle": "独特视角(差异化切入点)",
|
||||
"audience_pain": "受众痛点(真实用户的困惑)",
|
||||
"unique_angle": "差异化切入点",
|
||||
"format": "内容形式(趋势洞察/实操指南/对比分析/案例解读)"
|
||||
}}
|
||||
}}}}
|
||||
|
||||
要求:
|
||||
- 标题要像人会搜索的,带领域关键词
|
||||
- 避免「新趋势」「指南」「攻略」这类同质化结尾
|
||||
- 切入点要具体,不要泛泛而谈
|
||||
- 优先考虑中国读者能实操的内容
|
||||
只输出JSON,不要其他文字。"""
|
||||
- 标题像普通人会搜索的
|
||||
- 切入点具体,不泛泛而谈
|
||||
- 优先考虑中国读者能实操的内容"""
|
||||
|
||||
try:
|
||||
resp = call_llm(prompt, temperature=0.7)
|
||||
@@ -797,10 +786,8 @@ class SustainabilityCollector:
|
||||
logger.info(f"RSS采集 {sum(1 for a in all_articles if a.get('source_name','') not in [s.name for s in self.sources if s.type=='web_search'])} 篇, "
|
||||
f"搜索采集 {len(web_search_results)} 篇")
|
||||
|
||||
# ---------------------- 第二阶段:尝试LLM选题生成 ----------------------
|
||||
llm_topic = None
|
||||
if web_search_results:
|
||||
llm_topic = self._generate_topic_with_llm(web_search_results)
|
||||
# ---------------------- 第二阶段:LLM选题生成 ----------------------
|
||||
llm_topic = self._generate_topic_with_llm(web_search_results if web_search_results else None)
|
||||
|
||||
if llm_topic and not self._is_duplicate_topic(llm_topic.title, existing_titles):
|
||||
llm_topic.created_at = datetime.datetime.now().isoformat()
|
||||
|
||||
Reference in New Issue
Block a user