Fix calendar filter, module triggers, API cleanup, consolidate get_current_admin, fix LLM schema
This commit is contained in:
+39
-14
@@ -1,4 +1,8 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
平台适配文章撰写
|
||||
根据大纲和平台配置(字数/格式/配图要求),为知乎/公众号/小红书各平台生成适配内容
|
||||
"""
|
||||
import json, datetime, logging, sys, re
|
||||
from pathlib import Path
|
||||
from typing import Dict, List
|
||||
@@ -92,15 +96,17 @@ class Writer:
|
||||
if line.startswith("# "):
|
||||
if current:
|
||||
sections.append(current)
|
||||
current = {"level": 1, "title": line[2:].strip(), "content": ""}
|
||||
current = {"level": 1, "title": line[2:].strip(), "content": "", "section_type": "normal"}
|
||||
elif line.startswith("## "):
|
||||
if current:
|
||||
sections.append(current)
|
||||
current = {"level": 2, "title": line[3:].strip(), "content": ""}
|
||||
title = line[3:].strip()
|
||||
stype = "noise" if title in ("文章大纲", "大纲", "文章结构", "结构") else "normal"
|
||||
current = {"level": 2, "title": title, "content": "", "section_type": stype}
|
||||
elif line.startswith("### "):
|
||||
if current:
|
||||
sections.append(current)
|
||||
current = {"level": 3, "title": line[4:].strip(), "content": ""}
|
||||
current = {"level": 3, "title": line[4:].strip(), "content": "", "section_type": "normal"}
|
||||
else:
|
||||
if current and line.strip():
|
||||
current['content'] = current.get('content', '') + line + "\n"
|
||||
@@ -112,7 +118,13 @@ class Writer:
|
||||
def _clean_markdown(text: str) -> str:
|
||||
lines = text.split('\n')
|
||||
cleaned = []
|
||||
in_code_fence = False
|
||||
for line in lines:
|
||||
if line.strip().startswith('```'):
|
||||
in_code_fence = not in_code_fence
|
||||
continue
|
||||
if in_code_fence:
|
||||
continue
|
||||
line = re.sub(r'^#{1,6}\s+', '', line)
|
||||
line = re.sub(r'^[\-\*\+]\s+', '', line)
|
||||
line = re.sub(r'^\d+[\.\)]\s+', '', line)
|
||||
@@ -133,12 +145,19 @@ class Writer:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _is_bullet_only(self, text: str) -> bool:
|
||||
"""检查内容是否主要是要点列表(大纲格式),需要 LLM 展开"""
|
||||
lines = [l.strip() for l in text.split('\n') if l.strip()]
|
||||
if not lines:
|
||||
return False
|
||||
bullet_count = sum(1 for l in lines if l.startswith(('- ', '* ', '**', '+ ')))
|
||||
return bullet_count / len(lines) > 0.4
|
||||
|
||||
def _expand_section(self, section: Dict) -> str:
|
||||
content = section.get('content', '').strip()
|
||||
if len(content) > 200:
|
||||
return content
|
||||
if HAVE_LLM and len(content) < 150:
|
||||
logger.info(f"使用 LLM 扩写章节: {section['title']}")
|
||||
# 大纲要点格式(>40% 行以 -/*/** 开头)应始终由 LLM 展开为连贯段落
|
||||
if HAVE_LLM and self._is_bullet_only(content):
|
||||
logger.info(f"使用 LLM 扩写章节(要点→段落): {section['title']}")
|
||||
prompt = f"""你是一个资深作者,正在写一篇关于「{self.topic['title']}」的文章。请写「{section['title']}」这一节。
|
||||
|
||||
今天日期:{datetime.datetime.now().strftime('%Y年%m月%d日')}。
|
||||
@@ -147,7 +166,7 @@ class Writer:
|
||||
{content}
|
||||
|
||||
【输出要求】
|
||||
输出3-5段纯粹、流畅的段落文字,共400-800字。
|
||||
输出3-6段纯粹、流畅的段落文字,每节内容根据平台需求控制在200-800字之间。
|
||||
|
||||
格式:
|
||||
- 禁止任何标题/列表/格式标记(#、-、*、1.、**等)
|
||||
@@ -187,7 +206,8 @@ class Writer:
|
||||
text += '。'
|
||||
sentences.append(text)
|
||||
if sentences:
|
||||
return ' '.join(sentences)
|
||||
result = ' '.join(sentences)
|
||||
return self._clean_markdown(result)
|
||||
return ''
|
||||
|
||||
def generate_full_markdown(self) -> str:
|
||||
@@ -200,6 +220,12 @@ class Writer:
|
||||
if expanded:
|
||||
parts.append(expanded + "\n")
|
||||
continue
|
||||
# 跳过大纲结构噪音节点
|
||||
title_stripped = sec['title'].strip()
|
||||
if title_stripped in ('文章大纲', '大纲', '文章结构', '结构'):
|
||||
continue
|
||||
if sec.get('section_type') == 'noise':
|
||||
continue
|
||||
heading = f"{'#' * sec['level']} {sec['title']}"
|
||||
parts.append(heading)
|
||||
if sec.get('content'):
|
||||
@@ -246,11 +272,6 @@ class Writer:
|
||||
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
|
||||
@@ -429,6 +450,10 @@ class Writer:
|
||||
|
||||
html = html.replace("<!-- CONTENT -->", html_content)
|
||||
|
||||
# 防御:清理可能在 LLM 输出中混入的 markdown 代码围栏和文件头
|
||||
html = re.sub(r'^```+\w*\s*\n?', '', html)
|
||||
html = html.strip()
|
||||
|
||||
tags_html = self._get_platform_tags(platform)
|
||||
if tags_html:
|
||||
html = html.replace("<!-- TAGS -->", tags_html)
|
||||
|
||||
Reference in New Issue
Block a user