23ff63baa9
- writer.py: _expand_section() 去除 <100字阈值,始终调用 LLM 平台专属扩写
- prompt_loader.py: 新增 section_expansion_zhihu/wechat/xiaohongshu 三个独立 prompt
- admin.html: 配置管理标签页 + 敏感词/清理规则子标签 + 敏感词表格化管理(编辑/删除)
- config_items.py: PUT /sensitive-words/{id} 支持更新 word/category
- compliance_checker.py: AI 套话从 DB 加载 + 人称规则修正
- initial_data.py: PlatformConfig 字数迁移 + 新种子
- 各前端页面: LLM 配置 rate_limit 字段 + 供应商列表排序
6.0 KiB
6.0 KiB
AGENTS.md
Stack
- Backend: FastAPI 0.104 + SQLAlchemy 2.0 + PostgreSQL 16 (
yzr_nr) - Frontend: Vue 3 (CDN, no build step) + Element Plus — static HTML served by FastAPI
- Auth: JWT (
python-jose+ bcrypt), default adminadmin/admin123 - Scheduler: APScheduler (daily cron: 01:10 trends, 01:30 collect, 02:00 generate, 03:00 optimize, 05:00 sources, 06:00 metrics)
- Task DB:
TaskLog(module_id/status/error_trace/result_data/triggered_by) +TaskConfig(params/enabled/schedule) - LLM: Multi-provider (nvidia primary, opencode-go fallback). API keys in DB (managed via admin UI) or
.env.
Commands
# Start/stop/restart server (systemd service, auto-restart on failure)
systemctl start yzr-platform.service # 启动
systemctl stop yzr-platform.service # 停止
systemctl restart yzr-platform.service # 重启
systemctl status yzr-platform.service # 查看状态
journalctl -u yzr-platform.service -n 50 --no-pager # 查看日志
# Fallback: start without systemd (用于调试)
cd /root/openclaw-workspace/projects/yu-zhi-ran
setsid ./start-platform.sh 8001
# Run full integration test
cd /root/openclaw-workspace/projects/yu-zhi-ran && python3 tests/test_new_features.py
# Run specific scripts (from project root)
python3 scripts/collector.py
python3 scripts/creator.py --topic-id B02
Project layout
yu-zhi-ran/
├── platform/
│ ├── backend/app/main.py # FastAPI entry, mounts frontend at /
│ ├── backend/app/api/*.py # 21 API routers
│ ├── backend/app/core/ # nvidia_client.py, scheduler.py, etc.
│ ├── backend/app/models.py # SQLAlchemy models (593 lines)
│ ├── backend/app/schemas.py # Pydantic schemas (504 lines)
│ ├── backend/app/database.py # PG env config + ALTER TABLE migrations
│ ├── backend/app/initial_data.py
│ └── backend/.env # API keys, DB creds
├── scripts/ # creator.py, writer.py, collector.py, etc.
├── tests/test_new_features.py # 33-test integration suite
└── PROGRESS.md # Single source of truth for project status
Gotchas & conventions
Server
- Shell timeout kills background processes — always use
setsidto start - Env in
platform/backend/.env, loaded viadotenvat each module level
Database
init_db()indatabase.pyruns ALTER TABLE migrations at startup (PostgreSQL)USE_POSTGRES=falsefalls back to SQLite (used in tests)- Models have timezone-aware
DateTime(timezone=True)columns
Content quality architecture (三平台差异化)
核心原则:三平台不再共享同一篇 markdown,各自独立展开。
writer.py对 zhihu/wechat/xiaohongshu 分别调用generate_platform_markdown(platform),各走不同的section_expansion_{platform}prompt- 知乎:数据分析深度(400-800字/节),用「你」称呼读者
- 公众号:个人叙事对话感(300-500字/节),用「我」口吻
- 小红书:精炼干货(100-200字/节),直接给方法,可用 emoji
字数配置:
- 知乎 min 3000 / max 8000
- 公众号 min 2000 / max 4000
- 小红书 min 400 / max 1000
- 存于
platform_configs表,min_words/max_words字段,后台「平台管理」可改
AI 套话检测:
- DB 存储:
content_clean_rules表,rule_type='ai_telltale' - 由
config_items.py中的DEFAULT_CONTENT_CLEAN_RULES种子数据 compliance_checker.py运行时从 DB 加载(_load_ai_telltales()),DB 不可用时回退代码硬编码列表- 后台「配置管理→敏感词/清理规则」可增删改(操作
ContentCleanRule表)
Prompts (prompt_configs table)
- DB 是唯一来源,修改 prompt 直接
UPDATE prompt_configs SET content = '...' WHERE key = '...'; - 代码
scripts/prompt_loader.py中的_PROMPT_DEFAULTS仅作种子数据,第一次写入后就不再生效 - 新增 prompt:在
_PROMPT_DEFAULTS添加定义 → 重启后自动补入 DB(仅当该 key 不存在时) - 修改 prompt:直接改 DB,不要改代码(除非要更新种子供新环境用)
- DB 不可用时回退代码默认值(仅紧急模式)
- 三平台独立 section_expansion 提示词 key:
section_expansion_zhihu/section_expansion_wechat/section_expansion_xiaohongshu - 标题提示词去套路化,使用自然语言(不像 AI 写的 prompt)
Prompt quality checks (compliance_checker.py)
- 软质量问题(AI套话/人称混用/阅读体验)只降分、不挡流程(
passed=true) - 硬合规问题(敏感词/法律/品牌)扣分多且阻塞流程
- AI 套话从 DB
content_clean_rules(rule_type='ai_telltale')加载,后台可动态管理 - 人称检查修正:去掉「大家」误报,仅检查「你们」和「你」混用
LLM
call_llm()incore/nvidia_client.py— reads active provider from DBLLMConfig.is_active, API key from env- DeepSeek reasoning models return
reasoning_content(thinking) +content(answer).call_llmpreferscontent, falls back to tail ofreasoning_content max_tokensmust be generous (≥500 for tags/titles, ≥2000 for article content) — reasoning models consume tokens for thinking- Schema (
LLMConfigResponse) must includeprovider,base_url,api_keyfields or they get silently dropped from API responses
Frontend
- No npm build step — edit
.htmlfiles directly - H5 mobile nav only created when
window.innerWidth <= 768 navigation-component.js+navbar-component.jsinjected as Vue components- For date filters on topics, use backend
?today=true(server-sidedate.today()) — client-sidenew Date()gives UTC which differs from Asia/Shanghai by 8h
Tests
test_new_features.pystarts its own uvicorn on port 18503, runs against SQLite- Run from project root:
python3 tests/test_new_features.py
Project status
- PROGRESS.md is the single truth source for progress — update it after any significant task
archive/dir keeps historical/outdated docs withYYYY-MM-DDdate suffix