Step2 提速: - 每席位推理深度覆盖(seat_mode): 业务链条逐席位可配 flash/thinking/pro/ultra, 覆盖链条级 seatMode;前台三处 dispatch + 后台 job 透传, run_seat 用 _SEAT_MODE_PARAMS 解析 - recommend 后端批内并行: engine._run_recommend 由串行 for 改 asyncio.gather(对齐前端) - 研讨前并行取数两段式(gather_first, 业务链条 opt-in): 研讨前全席位并行只取数, 产出作为共享资料注入研讨轮(_seat_message gathered + 前台 runGatherPhase); 新增 gather_first 列(migration 20260620_02 + idempotent SQL) - 削减重复广播: suppressPreBroadcast 扩到 recommend(round>=2)/chain(i>0)/chain收口, 保留首轮背景打底,省 N 次读写大 thread 方案总结报告效果: - summary 加"意图对齐+缺口核对+防幻觉护栏": SOUL + 后端 build_summary_prompt + 前端 buildSummaryPrompt 三处对齐; 推断标注(综合推断)、缺真实信息标注待补充交给用户、绝不凭空编 Tests: test_roundtable_seat_modes / test_roundtable_gather_phase / test_roundtable_summary_prompt Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
119 lines
4.7 KiB
Python
119 lines
4.7 KiB
Python
"""每席位「推理深度覆盖」(seat_modes)在进程内网关 run_seat 的解析测试。
|
||
|
||
语义(与前端 useStep2Orchestration「覆盖优先、否则跟随链条级 selectedMode」逐席位对齐):
|
||
- 席位命中 seat_modes → 用该档(_SEAT_MODE_PARAMS)派生的 thinking/reasoning/subagent **覆盖**
|
||
作业级 seat_*(不论作业级是什么);
|
||
- 席位未命中 → 跟随作业级 seat_thinking_enabled / seat_reasoning_effort / seat_subagent_enabled;
|
||
- 作业级仍为 None → 落 policy("seat") 默认。
|
||
|
||
只验证传给 _run_agent_turn 的三个运行参数,故把 _run_agent_turn / policy / 文本解析全部打桩,
|
||
不触发真实 LLM / 沙箱。
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
from types import SimpleNamespace
|
||
|
||
import pytest
|
||
|
||
|
||
@pytest.fixture
|
||
def _gw(monkeypatch):
|
||
"""构造一个被打桩的 InProcessRoundtableGateway,返回 (build, captured)。
|
||
|
||
build(seat_modes=..., seat_thinking_enabled=..., seat_reasoning_effort=..., seat_subagent_enabled=...)
|
||
返回 gateway 实例;captured 记录最近一次 _run_agent_turn 收到的 thinking/reasoning/subagent。
|
||
"""
|
||
import app.gateway.roundtable_inprocess_gateway as gw
|
||
|
||
captured: dict[str, object] = {}
|
||
|
||
async def _fake_run_agent_turn(*args, **kwargs):
|
||
captured["thinking_enabled"] = kwargs.get("thinking_enabled")
|
||
captured["reasoning_effort"] = kwargs.get("reasoning_effort")
|
||
captured["subagent_enabled"] = kwargs.get("subagent_enabled")
|
||
return []
|
||
|
||
# policy("seat") 默认:thinking=True / reasoning="medium"(= 现有席位默认 pro 行为)。
|
||
monkeypatch.setattr(
|
||
gw,
|
||
"roundtable_run_policy",
|
||
lambda role: SimpleNamespace(excluded_tools=[], skill_stop_names=[], thinking_enabled=True, reasoning_effort="medium"),
|
||
)
|
||
monkeypatch.setattr(gw, "_run_agent_turn", _fake_run_agent_turn)
|
||
# 技能强化与本测试无关 → 原样返回任务,避免触发 load_agent_config / skill storage。
|
||
monkeypatch.setattr(gw, "append_seat_skill_directive", lambda agent_id, task, **k: task)
|
||
monkeypatch.setattr(gw, "_latest_ai_text", lambda messages: "")
|
||
monkeypatch.setattr(gw, "_tool_calls_since_last_human", lambda messages: [])
|
||
|
||
def _build(**kwargs):
|
||
return gw.InProcessRoundtableGateway(SimpleNamespace(state=SimpleNamespace()), user_id="u1", agents=[], **kwargs)
|
||
|
||
return _build, captured
|
||
|
||
|
||
async def _run(gateway):
|
||
await gateway.run_seat(thread_ids={"seat-1": "tid-1"}, agent_id="seat-1", task="任务", model="m")
|
||
|
||
|
||
@pytest.mark.asyncio
|
||
async def test_seat_mode_override_wins_over_job_level(_gw):
|
||
"""席位配了 flash → 覆盖作业级 pro(thinking off / minimal / 无子代理)。"""
|
||
build, captured = _gw
|
||
gateway = build(
|
||
seat_modes={"seat-1": "flash"},
|
||
seat_thinking_enabled=True,
|
||
seat_reasoning_effort="high",
|
||
seat_subagent_enabled=True,
|
||
)
|
||
await _run(gateway)
|
||
assert captured["thinking_enabled"] is False
|
||
assert captured["reasoning_effort"] == "minimal"
|
||
assert captured["subagent_enabled"] is False
|
||
|
||
|
||
@pytest.mark.asyncio
|
||
async def test_ultra_override_enables_subagent(_gw):
|
||
build, captured = _gw
|
||
gateway = build(seat_modes={"seat-1": "ultra"})
|
||
await _run(gateway)
|
||
assert captured["thinking_enabled"] is True
|
||
assert captured["reasoning_effort"] == "high"
|
||
assert captured["subagent_enabled"] is True
|
||
|
||
|
||
@pytest.mark.asyncio
|
||
async def test_no_override_follows_job_level(_gw):
|
||
"""席位未命中 seat_modes → 跟随作业级 seat_*。"""
|
||
build, captured = _gw
|
||
gateway = build(
|
||
seat_modes={"other": "flash"},
|
||
seat_thinking_enabled=True,
|
||
seat_reasoning_effort="low",
|
||
seat_subagent_enabled=False,
|
||
)
|
||
await _run(gateway)
|
||
assert captured["thinking_enabled"] is True
|
||
assert captured["reasoning_effort"] == "low"
|
||
assert captured["subagent_enabled"] is False
|
||
|
||
|
||
@pytest.mark.asyncio
|
||
async def test_no_override_no_job_level_falls_back_to_policy(_gw):
|
||
"""既无席位覆盖、作业级也为 None → 落 policy 默认(thinking=True / medium)。"""
|
||
build, captured = _gw
|
||
gateway = build(seat_modes={})
|
||
await _run(gateway)
|
||
assert captured["thinking_enabled"] is True
|
||
assert captured["reasoning_effort"] == "medium"
|
||
assert captured["subagent_enabled"] is False
|
||
|
||
|
||
@pytest.mark.asyncio
|
||
async def test_unknown_mode_value_ignored_falls_through(_gw):
|
||
"""非法档位值(前端不会下发,防御)→ 安全忽略,回退作业级/policy。"""
|
||
build, captured = _gw
|
||
gateway = build(seat_modes={"seat-1": "bogus"}, seat_reasoning_effort="low", seat_thinking_enabled=True)
|
||
await _run(gateway)
|
||
assert captured["thinking_enabled"] is True
|
||
assert captured["reasoning_effort"] == "low"
|