diff --git a/.opencode/commands/dr-frame.md b/.opencode/commands/dr-frame.md index 55aac1e..9848547 100644 --- a/.opencode/commands/dr-frame.md +++ b/.opencode/commands/dr-frame.md @@ -18,6 +18,7 @@ subtask: false - `target_words_zh` 和 `target_words_en` 必须都存在 - `core_questions` 必须非空 - `report_title` 必须非空(v0.5 新增检查) +- `model_profile` 必须存在(v0.12 新增检查,确保全流程模型策略一致) 任一检查不通过 → 回报用户"访谈不完整",停止。 @@ -52,7 +53,7 @@ prompt: | Required skills: search-strategy, source-quality Tasks: - 1. 3 rounds of search: Tavily + Brave + Exa + 1. 3 rounds of search through `scripts/search.py`: scholar/patents/news/general as appropriate; Tavily/Brave/Exa MCP only as gap-fill 2. Both English and Chinese keywords 3. Return 10-20 Tier 1-2 sources (score ≥6), exclude Tier 4 and blacklist 4. 1-2 sentence outline per source @@ -60,9 +61,10 @@ prompt: | Output format (Markdown): ## Keyword Group : - ### Keywords Used - - English: ... - - Chinese: ... +### Keywords Used +- English: ... +- Chinese: ... +- Routes used: scholar / patents / news / general ### Initial Sources (≥10, Tier 1-2) 1. [src_xxx] | <author/institution> | <year> | <Tier> | <score> - <core finding one sentence> diff --git a/.opencode/commands/dr-init.md b/.opencode/commands/dr-init.md index 18c8623..99ccf1c 100644 --- a/.opencode/commands/dr-init.md +++ b/.opencode/commands/dr-init.md @@ -1,5 +1,5 @@ --- -description: 初始化一个新的 Deep Research 主题。创建 projects/<slug>/ 目录与 manifest.json,启动 Phase 1 访谈(8 步),访谈末尾自动提议 3 个报告标题让用户选。用法:/dr-init <研究主题> +description: 初始化一个新的 Deep Research 主题。创建 projects/<slug>/ 目录与 manifest.json,启动 Phase 1 访谈(9 步,含模型策略选择),访谈末尾自动提议 3 个报告标题让用户选。用法:/dr-init <研究主题> agent: dr-plan subtask: false --- @@ -26,7 +26,7 @@ subtask: false mkdir -p projects/<slug>/{phase1,phase2/drafts,phase2/evidence,phase3/revisions,phase4/figures} ``` -### Step 3: 启动访谈(8 步) +### Step 3: 启动访谈(9 步) **不要急着生成 framework**,向用户清晰编号地提出以下 8 个关键问题: @@ -55,6 +55,13 @@ mkdir -p projects/<slug>/{phase1,phase2/drafts,phase2/evidence,phase3/revisions, - `deep` — 深度(50,000-80,000 中文字,12-15 章;行业专著级) - 说明:字数只是参考,以把问题讲清楚为第一优先。 +9. **模型策略选择(新增,必须在 init 阶段确定)**: + - `simple`:低成本探索 + - `medium`:默认推荐(平衡质量/成本) + - `premium`:高质量正式交付 + - `cn_heavy`:中文/中国市场侧重 + - `codex_native`:Codex 原生模式 + **等待用户回答**。用户可能一次性回答也可能分多轮。 ### Step 4: 提议报告正式标题(关键新增步骤) @@ -105,6 +112,9 @@ mkdir -p projects/<slug>/{phase1,phase2/drafts,phase2/evidence,phase3/revisions, "comparison_targets": [], "exclusions": [], "word_budget_mode": "<auto/concise/detailed/deep>", + "model_profile": "<simple/medium/premium/cn_heavy/codex_native>", + "model_profile_selected_at": "<今天 YYYY-MM-DD>", + "model_profile_source": "dr-init interview", "target_words_zh": <按类型和模式计算,见 length-budget skill §1-2>, "target_words_en": <target_words_zh / 1.4>, "min_words_zh": <target_words_zh × 0.8>, @@ -123,6 +133,16 @@ mkdir -p projects/<slug>/{phase1,phase2/drafts,phase2/evidence,phase3/revisions, 把整个访谈对话写入 `projects/<slug>/phase1/interview.md`(用户原话 + 你的提问 + 提议的候选标题 + 用户选择)。 +### Step 6.5: 立刻应用模型策略(必须执行) + +在项目初始化完成后,立即把 `model_profile` 应用到 agent 文件(OpenCode + Codex 模板): + +```bash +uv run python scripts/dr.py apply-models --profile <model_profile> --target both +``` + +这样可以确保从 Phase 1(plan)到 Phase 4(polisher/reporter)全流程使用同一套预设策略,而不是中途切换。 + ### Step 7: 回报 ``` diff --git a/README.md b/README.md index d5bbcde..0b9a8e0 100644 --- a/README.md +++ b/README.md @@ -213,6 +213,8 @@ codex exec "$(uv run python scripts/dr.py prompt dr-run <slug-or-topic>)" 模型预设配置文件: - `configs/models.yaml`(统一预设,支持 `simple / medium / premium / cn_heavy / codex_native`) +推荐时机:在 `/dr-init` 访谈阶段就确定 `model_profile`,并立即执行 `apply-models`,保证 plan→pm→analyst→verifier→editor→polisher 的全流程策略一致。 + 命令行查看解析后的模型映射: ```bash diff --git a/scripts/dr.py b/scripts/dr.py index 95f674d..e83cffe 100644 --- a/scripts/dr.py +++ b/scripts/dr.py @@ -163,9 +163,11 @@ def cmd_glossary(args: argparse.Namespace) -> int: def cmd_finalize(args: argparse.Namespace) -> int: project_root = resolve_project(args.project) + manifest = load_manifest(project_root) + effective_profile = args.model_profile or manifest.get("model_profile") try: resolved = resolve_model_profile( - profile=args.model_profile, + profile=effective_profile, overrides=parse_model_overrides(args.model_override), ) except ModelConfigError as exc: