diff --git a/scripts/writer.py b/scripts/writer.py index d5f85b6..d733eae 100644 --- a/scripts/writer.py +++ b/scripts/writer.py @@ -173,127 +173,49 @@ class Writer: def _adapt_for_platform(self, markdown: str, platform: str) -> str: cfg = PLATFORM_CONFIG[platform] - - platform_prompts = { - "zhihu": f"""你是一个知乎高赞答主。把以下文章改写成能获得高赞+高收藏+被推荐到知乎日报级别的回答。 - -## 知乎爆款特征 -- 开头即结论:前3行说清核心观点,不铺垫 -- 每个观点有数据/案例/逻辑推导支撑 -- 结构清晰:扫读能抓重点,精读有深度 -- 互动钩子:适当留白或提问引发讨论 -- SEO:首段包含用户搜索时的核心关键词 - -## 改写要求 -- 用第三人称或「我们」视角,不要用「我」 -- 不要编个人经历——知乎读者在意的是分析质量 -- 每个主要观点配1个数据或案例支撑,**必须使用2025-2026年最新数据**,禁用超过2年的过时数据 -- 段落之间空行分隔,逻辑递进 -- 避免「总的来说」「综上所述」「值得注意的是」 -- 结尾可用引导性提问 -- 字数:{cfg['max_chars']}字以内 -- 直接输出改写后的正文,不要输出任何思考过程、解释或额外说明 - -## 原文 -{markdown[:3000]} - -## 输出 -直接输出改写后的完整内容(仅正文),每段后空一行。""", - - "wechat": f"""你是一个10万+爆款公众号作者。把以下文章改写成读者愿意转发到朋友圈的推文。 - -## 公众号爆款特征 -- 开头3秒定生死:第一句制造共鸣或好奇心 -- 短段落+节奏感:每段2-3行,手机阅读友好 -- 金句频出:每200字左右有一个可截图发朋友圈的句子 -- 社交货币:读者转发=表达自己的观点 -- SEO:标题和开头包含微信搜索关键词 - -## 改写要求 -- 用「你」视角,**通篇不允许出现「我」字** -- 把原文中所有「我」改成「你」或「很多人」或「有人」 -- 结构可完全不同——抓住1-2个痛点打透,不用全面分析 -- 可删减原文,保留最有力的观点和最打动人的案例,**必须使用2025-2026年最新数据** -- 适当加粗核心观点(不要整段加粗) -- 避免「综上所述」「值得注意的是」「换言之」 -- 字数:{cfg['max_chars']}字以内 -- 直接输出改写后的正文,不要输出任何思考过程、解释或额外说明 - -## 原文 -{markdown[:3000]} - -## 输出 -直接输出改写后的完整内容(仅正文),每段后空一行。""", - - "xiaohongshu": f"""你是一个小红书爆款笔记写手。把以下文章改写成收藏过万的笔记。 - -## 小红书爆款特征 -- 极短!用户3秒扫不完就会划走 -- 直接给结论/清单/步骤,不给分析过程 -- 标题采用「数字+结果」模式 -- 正文用emoji做视觉分割,人人阅读 -- SEO:标题和正文包含用户搜索关键词 - -## 改写要求 -- **全文 {cfg['max_chars']} 字以内**,多一个都不要 -- 用「你」或「姐妹」视角,不要用「我」 -- 开头一句抓住注意力(反常识观点或「你知道吗…」) -- 正文每段1-2句,可完全打乱原文结构 -- emoji每段最多1个(✨💡✅🔸选1-2个用),不堆砌 -- 结尾加3-5个#话题标签:1-2个流量大标签+1-2个精准标签 -- 深度分析全部砍掉,只留最 actionable 的内容,**使用2025-2026年最新数据** -- 直接输出笔记正文+标签,不要输出任何思考过程或额外说明 - -## 原文 -{markdown[:3000]} - -## 输出 -直接输出改写后的完整内容(仅正文)。""", - } - - if HAVE_LLM: - prompt = platform_prompts.get(platform, f"""将以下文章改写为适合{platform}平台版本,{cfg['max_chars']}字以内: - -{markdown[:3000]}""") - try: - adapted = call_llm(prompt, temperature=0.7, max_tokens=2000) - if adapted and len(adapted.strip()) > 50: - adapted = adapted.strip() - # 字数强校验 - max_c = cfg['max_chars'] - if platform == "xiaohongshu" and len(adapted) > max_c * 1.2: - adapted = adapted[:max_c] - last_break = max(adapted.rfind('。'), adapted.rfind('\n'), adapted.rfind('!'), adapted.rfind('?')) - if last_break > max_c // 2: - adapted = adapted[:last_break + 1] - # 微信/知乎清除残留的"我" - if platform in ("wechat", "zhihu"): - adapted = adapted.replace('我', '你') - logger.info(f"LLM 平台适配完成: {platform} ({len(adapted)}字, \"我\"x{adapted.count('我')})") - return adapted - except Exception as e: - logger.warning(f"LLM {platform} 适配失败: {e}") - except Exception as e: - logger.warning(f"LLM {platform} 适配失败: {e}") + max_c = cfg['max_chars'] + lines = markdown.split('\n') if platform == "xiaohongshu": - lines = markdown.split('\n') result = [] char_count = 0 for line in lines: - if char_count >= cfg['max_chars']: + if char_count >= max_c: break if line.startswith('## '): line = f"## ✨ {line[3:]}" elif line.startswith('### '): line = f"### 💡 {line[4:]}" - result.append(line) char_count += len(line) adapted = '\n'.join(result) if adapted.count('#') == 0: adapted = f"# {self.topic['title']}\n\n{adapted}" return adapted + + if platform == "wechat": + result = [] + for line in lines: + line = line.replace('我', '你') + if line.startswith('### '): + result.append(f"\n**{line[4:]}**\n") + elif line.startswith('## '): + result.append(f"\n**{line[3:]}**\n") + elif line.strip() and len(line) > 80: + sentences = [s.strip() for s in line.replace('。', '。\n').split('\n') if s.strip()] + for s in sentences: + if s: + result.append(s) + else: + result.append(line) + adapted = '\n'.join(result) + if len(adapted) > max_c: + adapted = adapted[:max_c] + last = max(adapted.rfind('。'), adapted.rfind('\n'), adapted.rfind('!')) + if last > max_c // 2: + adapted = adapted[:last + 1] + return adapted + return markdown def _get_platform_tags(self, platform: str) -> str: