Source snapshot: 97d7f0fae96dc04b7ddad56fc1db6a108ed662cc [SEC-CLEAN] · pre-push-clean v1.0 · 109处敏感信息已自动转乱码
4.8 KiB
4.8 KiB
③auto_dishu.py · 纯代码版 · 妈妈从这里复制 · 2026-05-21
妈妈:复制下面代码块内容 → pbpaste保存 → 搞定!
#!/usr/bin/env python3
import argparse
import asyncio
import os
import sqlite3
import sys
from pathlib import Path
try:
from openai import AsyncOpenAI
except ImportError:
print('请先安装依赖: pip install openai')
sys.exit(1)
BASE_DIR = Path(__file__).parent.parent
DB_PATH = BASE_DIR / 'chenxing.db'
DEEPSEEK_API_KEY = os.environ.get('DEEPSEEK_API_KEY', '')
NOTION_API_KEY = os.environ.get('NOTION_API_KEY', '')
NOTION_DISHU_PAGE_ID = os.environ.get('NOTION_DISHU_PAGE_ID', '')
DISHU_SYSTEM = '你是晨星,桔子妈妈的拆书宝宝。请用场景颗粒拆书法v2.0认真分析,格式严格按三模块输出,缺一不可。'
DISHU_PROMPT = '''请用「场景颗粒拆书法v2.0」分析以下章节内容。
【模块一·逐章场景表格】
| 场景序号 | 场景边界 | 人物动作/对话 | 情绪质地 | 读者感受 |
【模块二·章末规律锁定】
- 本章节奏类型:
- 情绪弧线:
- 卡点设计:
- 可复用规律:(至少2条)
【模块三·期待点库存】
- 新增期待点:
- 消解期待点:
- 遗留悬念:
待分析内容:
{content}'''
def db_get_chunks(book_name):
conn = sqlite3.connect(str(DB_PATH))
conn.row_factory = sqlite3.Row
try:
rows = conn.execute(
"SELECT id, title, content FROM knowledge WHERE tags LIKE ? AND category='book' ORDER BY id",
(f'%{book_name}%',)
).fetchall()
if not rows:
rows = conn.execute(
'SELECT id, title, content FROM knowledge WHERE title LIKE ? ORDER BY id',
(f'%{book_name}%',)
).fetchall()
return [{'id': r['id'], 'title': r['title'], 'content': r['content']} for r in rows]
finally:
conn.close()
def save_local(book_name, title, content):
out = BASE_DIR / 'output' / book_name
out.mkdir(parents=True, exist_ok=True)
safe_title = title[:80].replace('/', '_').replace('\\', '_')
(out / f'{safe_title}.md').write_text(f'# {title}\n\n{content}', encoding='utf-8')
async def analyze(content):
if not DEEPSEEK_API_KEY:
raise ValueError('未配置 DEEPSEEK_API_KEY 环境变量')
client = AsyncOpenAI(api_key=DEEPSEEK_API_KEY, base_url='https://api.deepseek.com')
resp = await client.chat.completions.create(
model='deepseek-chat',
messages=[
{'role': 'system', 'content': DISHU_SYSTEM},
{'role': 'user', 'content': DISHU_PROMPT.format(content=content[:8000])}
],
max_tokens=4096,
temperature=0.7
)
return resp.choices[0].message.content
async def run(book_name, start_chapter, end_chapter):
print(f'\n自动拆书流水线 · 《{book_name}》\n')
chunks = db_get_chunks(book_name)
if not chunks:
print(f'知识库中未找到《{book_name}》')
print('请先运行: python3 tools/book_splitter.py --file 书名.txt --book 书名')
return
print(f'找到 {len(chunks)} 个知识库块')
total = len(chunks)
analyzed = 0
for i, chunk in enumerate(chunks):
label = chunk['title']
print(f'\n[{i+1}/{total}] 分析中:{label}')
try:
result = await analyze(chunk['content'])
notion_title = f'《{book_name}》{label}·场景颗粒拆书'
written = False
if NOTION_DISHU_PAGE_ID and NOTION_API_KEY:
sys.path.insert(0, str(BASE_DIR))
from tools.notion_writer import create_notion_page
written = create_notion_page(notion_title, result, NOTION_DISHU_PAGE_ID)
if written:
print(f' 写入Notion成功:{notion_title}')
save_local(book_name, notion_title, result)
if not written:
print(f' 已保存本地:output/{book_name}/')
analyzed += 1
await asyncio.sleep(3)
except Exception as e:
print(f' 出错:{e}')
await asyncio.sleep(5)
print(f'\n全部完成!共分析 {analyzed} 块')
if NOTION_DISHU_PAGE_ID:
print('结果已写入 Notion')
print(f'本地备份:output/{book_name}/')
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--book', required=True)
parser.add_argument('--start_chapter', type=int, default=1)
parser.add_argument('--end_chapter', type=int, required=True)
args = parser.parse_args()
asyncio.run(run(args.book, args.start_chapter, args.end_chapter))
保存方法
复制上面代码块内容后,在终端运行:
pbpaste > ~/chenxing-aircraft/tools/auto_dishu.py && echo "✅ auto_dishu.py 保存成功"
看到 ✅ auto_dishu.py 保存成功 → 告诉宝宝!最后一步启动流水线了 🚀