Skip to content

Agenda 摄入 + 多 agenda 隔离:方向 YAML 收件、范围圈定、token 预算封顶#41

Merged
Protocol-zero-0 merged 2 commits into
masterfrom
feat/agenda-intake-and-isolation
Jun 11, 2026
Merged

Agenda 摄入 + 多 agenda 隔离:方向 YAML 收件、范围圈定、token 预算封顶#41
Protocol-zero-0 merged 2 commits into
masterfrom
feat/agenda-intake-and-isolation

Conversation

@Protocol-zero-0

@Protocol-zero-0 Protocol-zero-0 commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

这是什么

把"用户提一个研究方向 → 系统圈定范围跑发现 → 多个方向互不干扰、各有 token 上限"这条链路补齐,分三块:

1. 方向 YAML 摄入(规则映射,无 LLM)

  • agents/direction_intake.py:用户侧 schema(direction / keywords / constraints / goal / contact)确定性映射到 ResearchAgenda
    • direction → description + 自动 slug name;keywords → focus;contact → submitter
    • constraints.compute 做关键词 best-effort 映射到 prefer.resource_class("单卡 / cpu / 笔记本"等 → 保守档),原文完整保留在 raw_config
    • goal(idea_only | experiment_plan | signal | verified_evidence)→ required_output.goal
    • 同时产出一份模板化中文回执(echo),告诉提交者系统理解成了什么
  • scripts/agenda_inbox_watcher.py:扫 research_agendas/inbox/*.yaml--once 或默认 60s 轮询),成功 → 直接走 agenda_loader 落库 + 写 <file>.echo.json + 移入 processed/;失败 → 移入 failed/ + <file>.error.txt。选择直连 DB 而不是 POST 本机 API,web 服务没起也能收件。deploy/agenda-inbox-watcher.example 附 systemd timer 和 cron 两种挂法。

2. Agenda 范围圈定(向后兼容)

  • _fetch_insight_pool(agenda=...):候选池按 agenda 圈定 = 本 agenda 打标的 insight + 关键词(focus + prefer.keywords)命中的未标记 insight;其他 agenda 的产出一律排除。不传 agenda 时与现状完全一致。
  • get_tier1_signals / get_tier2_signals 接收 taxonomy 子图 node_ids(由 agenda 关键词 LIKE 圈出),entity overlap / pattern match / plateau / limitation cluster 等信号查询只看子图。
  • run_tier1_discovery / run_tier2_discovery / run_full_discovery 接收可选 agenda,产出的 deep_insights 打上 agenda_id(新列,可空,旧数据 NULL)。

3. 多 agenda 隔离 + token 封顶

  • research_agendas 加列 submitter / token_budget(NULL → 取 AGENDA_TOKEN_BUDGET_DEFAULT,默认 0 = 不封顶、只记账)/ token_spent / status(新增 paused_budget);新表 agenda_token_ledger(agenda_id / operation / tokens / cost_usd / created_at)。
  • agents/agenda_budget.pyagenda_scope(agenda_id, operation) 上下文内的 call_llm 调用 先查预算再发请求——超限抛 AgendaBudgetExceededError,一个 token 都不花、不留半截写库;成功后记一条 ledger + 原子累加 token_spent;越线即置 paused_budget。提高预算或 POST /api/research_agenda/<id>/resume 后可继续。
  • 新端点:GET /<id>/insightsGET /<id>/selections(只回本 agenda 的产出)、POST /<id>/resumeGET /api/token_usage(按 agenda + 总量汇总 ledger,本地对账的唯一来源)。

行为变化(需要 reviewer 注意)

  • 单活跃排他取消:原 set_active_agenda 会把其他 agenda 的 is_active 清零,现在多 agenda 可同时 active。排查了全部调用点:save_agenda / update_agenda 不再隐式排他;get_active_agenda()/current 端点和 /select 不传 agenda_id 时的 fallback、demo 脚本)保留,语义改为"最新的活跃 agenda",单 agenda 部署行为不变。tests/test_agenda_contract.py 中断言排他的用例相应改为断言多活跃。
  • /select 新增可选 scoped: true,候选池按 agenda 圈定;默认仍是全池打分(与现状一致)。

迁移

  • 新列同时写进 schema_agenda.sql(SQLite)和 schema_agenda_postgres.sql(PG)供新库使用;旧库走 db/database.py 里既有的 _ensure_columns 模式(_ensure_agenda_isolation_schema),两条后端路径都在 init_db() 中调用。已用 master 版老 schema 建库再跑新 init_db() 验证无痛升级(旧行自动得到 token_spent=0 / status='active')。

测试

  • 基线(master):15 failed, 464 passed(既有失败集中在 manuscript/lint/venue 等无关区域)
  • 改后:15 failed, 497 passed,失败清单与基线逐条一致,新增 33 个用例全绿:
    • tests/test_direction_intake.py:完整样例映射、slug 确定性、goal 缺省、compute 映射规则、9 类坏输入、收件流转(processed/echo、failed/error、忽略非 yaml)
    • tests/test_agenda_scope.py:medical imaging vs cryptography 两个 agenda,候选池互不含对方关键词域的记录、打标产出不跨 agenda、scoped 选择各落在本域、不传 agenda 全池不变
    • tests/test_agenda_budget.py:ledger 记账、超限暂停、暂停后调用在请求前被拦(fake provider 调用计数验证)、resume / 提高预算恢复、0 预算关闭上限、resume 与 /api/token_usage 端点
  • 端到端冒烟:临时库 + inbox 跑 --once,echo 回执与落库字段核对通过。

已知取舍

  • signal harvest(harvest_all)本身仍是全库 SQL 聚合:信号表是共享聚合表、无 agenda 列,圈定放在信号消费侧(get_tier1/2_signals);harvest_signals(agenda=...) 接收上下文仅做日志标注。
  • 预算 check→record 不是分布式锁,并发下可能超出约一次调用的 token 量,作为软上限的可接受误差(模块 docstring 已注明)。
  • agenda 关键词在 taxonomy 中圈不到任何节点时,信号扫描回退全局(避免饿死稀疏方向),产出仍打 agenda_id、预算仍生效,并打印提示。
  • contradiction_clusters.node_ids 是 JSON 文本列,未做子图过滤(LIKE 匹配 JSON 不可靠),保持全量。

已知边界

  • 预算记账与封顶目前只覆盖发现阶段(signal harvest、Tier 1/2 discovery、selection):记账钩子挂在 call_llm / _call_provider 上,agenda_scope 只在发现路径进入;agenda_orchestrator 派发后的 auto_research 执行路径暂不计入,执行期的 LLM 消耗不会出现在 ledger 里。后续扩展见 Extend agenda token accounting to the auto_research execution path #42
  • 默认不启用封顶,只统计AGENDA_TOKEN_BUDGET_DEFAULT 为 0;token_budget 为 0/NULL/负数时 check_budget 直接放行、永不置 paused_budget,但 record_usage 照常写 agenda_token_ledger 并累加 token_spent。显式设置正数 token_budget 才启用封顶。

方向摄入(用户侧 YAML → ResearchAgenda,规则映射、无 LLM):
- agents/direction_intake.py:direction/keywords/constraints/goal/contact
  确定性映射到 agenda 合约,constraints.compute 关键词映射到保守资源档,
  原文存 raw_config;同时产出中文回执(echo)供提交者确认
- scripts/agenda_inbox_watcher.py:扫描 research_agendas/inbox/ 下 .yaml,
  成功落库 + 写 .echo.json 移入 processed/,失败移入 failed/ + .error.txt;
  支持 --once 与 60s 轮询;deploy/ 附 systemd timer / cron 示例

范围圈定(agenda 范围内扫描,不传 agenda 时行为不变):
- _fetch_insight_pool 支持按 agenda 圈定:本 agenda 产出 + 关键词命中的
  未标记 insight;其他 agenda 的产出一律排除
- get_tier1_signals / get_tier2_signals 接收 taxonomy 子图 node_ids,
  按 agenda 关键词 LIKE 圈定信号查询;Tier1/Tier2 入口接收可选 agenda
- 新产出 deep_insights 打 agenda_id(新列,旧数据为 NULL)

多 agenda 隔离 + token 封顶:
- research_agendas 加 submitter / token_budget / token_spent / status 列,
  新建 agenda_token_ledger 表;SQLite 与 Postgres 两条 schema 路径同步,
  旧库经 _ensure_columns 无痛升级
- 单活跃排他改为允许多 agenda 并行 active(set_active_agenda 不再清除
  其他 agenda;get_active_agenda 保留为取最新活跃的便捷入口)
- agents/agenda_budget.py:agenda_scope 上下文内的 LLM 调用先查预算
  (超限抛错、不发请求、不留半截写库)、成功后记账;超限置
  paused_budget,提高预算或 POST /<id>/resume 后可继续
- 新 API:GET /<id>/insights、GET /<id>/selections(按 agenda 隔离)、
  POST /<id>/resume、GET /api/token_usage(本地 token 对账汇总)

测试:intake 解析(含坏输入)、收件流转、两个领域 agenda 候选互不串题、
预算超限暂停/恢复;全量 pytest 与 master 基线一致(仅既有失败项)。
…get to accounting-only

- Escape %/_/\ in user-supplied scope keywords before they are bound into
  SQL LIKE patterns (agenda_selector pool query, signal_harvester taxonomy
  circle and tier2 keyword filter), with an explicit ESCAPE '\' clause valid
  on both SQLite and PostgreSQL. Shared helper db.sql_dialect.escape_like.
- agenda_inbox_watcher: quarantine files over 256KB into failed/ with an
  .error.txt before reading their content.
- AGENDA_TOKEN_BUDGET_DEFAULT 2M -> 0: budgets of 0/NULL/negative pass
  check_budget and never set paused_budget, while record_usage keeps writing
  agenda_token_ledger and token_spent. Docs updated accordingly.
- Tests: wildcard keywords no longer widen the candidate pool, oversized
  inbox files are rejected unread, zero budget still accounts usage.
@Protocol-zero-0 Protocol-zero-0 merged commit 7bdff2f into master Jun 11, 2026
2 checks passed
@Protocol-zero-0 Protocol-zero-0 deleted the feat/agenda-intake-and-isolation branch June 11, 2026 20:12
Protocol-zero-0 added a commit that referenced this pull request Jun 12, 2026
#41 只圈了信号消费侧,Tier1/Tier2 的生成 prompt 完全不知道 agenda 存在,
taxonomy 匹配不上还会回退全库扫描,实测一个粗差检测方向的 agenda 产出的
5 条 Tier2 idea 全部跑题(RAG/代码生成等)。

- 两个 agent 的全部生成环节(结构检测、形式化、问题提炼、方法设计、实验
  设计)在带 agenda 时把方向原话 + focus/prefer 关键词作为硬约束段注入
  prompt;不带 agenda 时 prompt 逐字节不变
- 新增 agents/agenda_relevance.py:生成后的规则关键词闸,命中任一范围词
  即保留(阈值 AGENDA_SCOPE_MIN_TERM_HITS 可配,默认 1,0 关闭),出域
  insight 不入库,计入 dropped_out_of_scope 并记日志
- discover_paradigm_insights / discover_paper_ideas 返回值改为
  {insights, dropped_out_of_scope},调度器解包并写入 tier*_done 事件
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant