跳转至

P7.U-autotune-multi-target · pysidecar 自动调音多目标曲线 + 偏差/平滑/聚类(ADR-AIOS-11 §4.1 fork 6)

目标 worker:ClaudeB(主仓 04_development/ · pysidecar 子目录 · ClaudeB 写权) [涉及部门]:Python sidecar (pysidecar) · 通用 numpy/scipy/FastAPI 预计:1.0d · 优先级:P1 · 状态:⚪ ready(2026-05-29 13:46 派发 · ADR-AIOS-11 accepted)


🔍 触发与解锁链

触发 hash 状态 影响
ADR-AIOS-11 accepted 2026-05-29 13:46 ✅ 用户拍板 6 fork U-thread 启动 · 后端两线优先 · 本任务最短(1.0d)· 建议 ClaudeB 先做
ADR-11 §1.3.2 GEQ-LSQ 锁定 accepted ✅ 永久 /auto_tune/geq_optimize 已实装 · 本任务扩 target_curve 参数
ADR-11 §1.3.3 内置 3 条目标曲线 accepted ✅ 永久 平直 / Harman 2017 / B&K 1974 资源化
ADR-07 §1.3.4 三层分工 accepted ✅ 永久 数学全交 P7 · 本任务承担 deviation/simulate/smoothing/averaging 全部数学
P5.U-autotune-batch-pipeline dispatched 同期 🟢 同 ClaudeB 串行 本任务先 zombie · 解锁 P5 fork 5 联调真跑

→ pysidecar 独立子进程 · 端口 8001 · 已暴露 19 端点 · 本任务新增 2 端点 + 扩 1 端点 + 内嵌 3 条目标曲线 + 2 个数学算子


完整 prompt(直接复制粘贴 worker 终端)

[U-thread]   P7.U-autotune-multi-target
[部门]       Python sidecar(pysidecar) · ADR-AIOS-11 §4.1 fork 6 多目标曲线 + 偏差/平滑/聚类数学层 · skill: (无 · 通用 Python numpy/scipy/FastAPI)
[Worker CWD] d:/work/25_claude/workspace/AlgoDepartment/04_development/
[Occupies]   P7.K-endpoints(write · 新增 /auto_tune/deviation + /auto_tune/simulate_apply · 扩 /auto_tune/geq_optimize)+ P7.K-models(write · 新增 AnalyzeRequest/Response models)+ P7.K-targets(write · 新增 pysidecar/auto_tune/targets/ 资源目录 + 3 条曲线 JSON)
[优先级]     P1 · 1.0d · 跨栈独立 · ClaudeB 先做(短工作量优先 · 解锁 P5 fork 5)· 与 P5.U-autotune-batch-pipeline 同 ClaudeB 串行
[ADR]        d:/work/25_claude/workspace/AlgoDepartment/06_docs/site-build/docs/08-implementation/40-aios/ADR/ADR-AIOS-11-xitune-autotune.md (§1.3.1 + §1.3.2 + §1.3.3 + §2.1.2 + §2.1.3 + §4.1 fork 6)
[参考文档]
  - 上述 ADR 主文(accepted v1.1)· 重点读 §1.3.1 Harman 4-Phase 流程 + §1.3.2 GEQ-LSQ MVP 锁定 + §1.3.3 内置 3 条目标曲线 + §4.1 fork 6 实施清单
  - 上游 ADR:d:/work/25_claude/workspace/AlgoDepartment/06_docs/site-build/docs/08-implementation/40-aios/ADR/ADR-AIOS-07-p3-p4-overlap.md(§1.3.4 三层分工铁律 · P7 = 数学层)
  - 同部门标本(强制 read · 4 维度对齐):d:/work/25_claude/workspace/AlgoDepartment/06_docs/site-build/docs/08-implementation/40-aios/prompts/done/P5.U-meter-source-tap--4adda88.md(虽然部门是后端 · 但同 ClaudeB · 同三层分工 · 格式严守 11 字段 frontmatter + 顶部表格 + 中文方括号代码块 + 末尾解锁链/风险/历史)
  - 同期派 P5 fork(读以同步 schema):d:/work/25_claude/workspace/AlgoDepartment/06_docs/site-build/docs/08-implementation/40-aios/prompts/active/P5.U-autotune-batch-pipeline.md(P5 调本任务新端点的 schema 期望 · 你的 response model 必须能映射到 P5 的 DeviationResult / GeqOptimizeResult / PredictedResponse)
  - pysidecar/main.py(已实装 19 端点 · 你新增 2 端点 + 扩 1 端点)· 关键既有端点:
    · POST /auto_tune/realtime_frame(已实装 · FFT + 群延迟 + 相位 · 不动)
    · POST /auto_tune/calculate(已实装 · 直接差值法 · 不动 · 前端 c039075 在用)
    · POST /auto_tune/geq_optimize(已实装 · 最小二乘 · **本任务扩 target_curve 参数**)
  - pysidecar/models.py(Pydantic models · 你新增 AnalyzeRequest/Response 类型)
  - pysidecar/auto_tune/(若已存在则在此扩展 · 否则按需新建子目录 + __init__.py)
  - 不要参考 frontend/backend 代码(本任务 100% Python · 跨语言不复用)

【背景】
ADR-AIOS-11 已 accepted(2026-05-29 13:46 用户原话 "accept ADR-AIOS-11 · 顺便 start fork 5+6")· 本任务承担 P5 fork 5 编排所需的全部数学算子 + 资源 · ClaudeB 先做(1.0d 短)→ 后做 P5 fork 5(1.5d)· 总 2.5d 串行。
**架构契约 ADR-07 §1.3.4 三层分工铁律(本任务核心地位)**:
  - **P7(本任务)= 数学分析层** · numpy/scipy 全栈 · 偏差曲线 / 共振峰识别 / 模拟应用 / 1/3 oct 平滑 / 多点平均 / GEQ 求解
  - P5(同期派 fork 5 · ClaudeB 后做)= I/O 编排 · 调本任务端点 · 不做数学
  - 前端(待派 fork 1-4)= UI · 通过 P5 调本任务 · 不做数学
**业务流程**(本任务负责的数学环节):
  - 偏差曲线计算:`deviation_curve_db = current_response_db - target_curve_db`(逐频段)
  - 共振峰识别:scipy.signal.find_peaks(deviation 上 +6dB / -6dB 阈值)+ Q 估算 + 增益估算
  - 1/3 oct 平滑:对数频段 1/3 倍频程平均(31 中心频点 ISO 标准)
  - 多点平均:多个测量点 magnitude_db 几何平均(对数域)
  - 模拟应用:GEQ filters 参数下发到模拟 IIR cascade · 计算"应用后预测响应"

【内置 3 条目标曲线 schema】(§1.3.3 锁定)
JSON 文件:pysidecar/auto_tune/targets/{flat,harman_2017,bk_1974}.json
schema:
{
  "id": "flat | harman_2017 | bk_1974",
  "name": "Flat | Harman 2017 | B&K 1974",
  "description": "...",
  "freq_hz": [20, 25, 31.5, 40, 50, ..., 16000, 20000],   // ISO 1/3 oct 31 频点
  "magnitude_db": [...]                                     // 对应 31 个增益值(平直全 0 · Harman 2017 低频 +6 / 高频 -1dB/oct · B&K 1974 偏明亮)
}
- flat:全 31 频点 0dB
- harman_2017:见 Olive et al. 2017 论文 · 20Hz +6dB · 200Hz +3dB · 1kHz 0dB · 10kHz -2dB · 20kHz -8dB(线性插值 31 频点)
- bk_1974:经典 HiFi · 高频偏明亮 · 5-10kHz +1~+2dB · 其他平直
- 工程师导入自定义曲线**留远景 §11.6 不做**(本任务仅 3 条内置)

【新增 2 端点 + 扩 1 端点 schema】

### POST /auto_tune/deviation(新增)
请求:
{
  "freq_hz": [...],          // 测量频点
  "magnitude_db": [...],     // 测量幅度
  "phase_deg": [...],        // 测量相位
  "target_id": "flat | harman_2017 | bk_1974",
  "smoothing": "none | one_third_oct"   // 默认 one_third_oct
}
响应:
{
  "deviation_curve_db": [...],     // current - target(对齐目标曲线频点)
  "resonance_peaks": [{"freq_hz": float, "q": float, "gain_db": float, "type": "peak | dip"}],
  "rms_error_db": float,           // 整体 RMS 偏差(关键指标 · P5 iterate 收敛判定用)
  "suggestions": [{"freq_hz": float, "gain_db": float, "q": float, "reason": str}]   // 建议调整清单(Phase 2 UI 用)
}

### POST /auto_tune/simulate_apply(新增)
请求:
{
  "current_response": {"freq_hz": [...], "magnitude_db": [...], "phase_deg": [...]},
  "filters": [{"type": "peak | low_shelf | high_shelf", "freq_hz": float, "q": float, "gain_db": float}]
}
响应:
{
  "predicted_response": {"freq_hz": [...], "magnitude_db": [...], "phase_deg": [...]}
}
- 实施:对每个 filter 计算 IIR biquad 系数(scipy.signal.iirpeak / iirnotch · 或手写 RBJ cookbook)→ scipy.signal.freqz 计算频响 → 与 current_response 频域相乘(对数域相加)→ 返回 predicted

### POST /auto_tune/geq_optimize(扩 target_curve 参数)
当前已实装(c039075 锚点)· 本任务**扩展 target_curve 接受 string id**(原可能仅接受数组)· 兼容旧调用(若旧接口收数组继续保留)· 新接口接受:
{
  ...既有字段...,
  "target_id": "flat | harman_2017 | bk_1974",   // 新增 · 与 target_curve 数组二选一
  "constraints": {                               // 新增 · 可选
    "phase_continuity": bool,                    // 默认 false
    "group_delay_min": bool,                     // 默认 false
    "gain_bounds_db": [-12, 12]                  // 默认 [-12, 12]
  }
}
- 内部加载 targets/{target_id}.json 替代数组 · 其他逻辑不动

【新增 2 数学算子】

### one_third_oct_smoothing(magnitude_db: array, freq_hz: array) -> array
- ISO 1/3 oct 31 中心频点(20Hz~20kHz)
- 对每个中心频点 fc · 取 [fc/2^(1/6), fc*2^(1/6)] 区间内的所有原始 magnitude_db 做几何平均(对数域算术平均)
- 返回 31 长度 smoothed_db 数组

### multi_point_averaging(measurements: List[{freq_hz, magnitude_db, phase_deg}]) -> {freq_hz, magnitude_db, phase_deg}
- 输入:N 个测量点的 freq/magnitude/phase
- 输出:幅度对数域几何平均 · 相位向量平均(complex exp 后取均值再 angle)
- 频点已对齐(测量点应在相同 freq_hz 网格)· 不在本算子做插值

【执行步骤】
1. 自查 + 同步:
   git status                                           # 工作区干净
   git branch --show-current                            # = xistudio
   git pull origin xistudio --no-rebase                 # 拿最新 main + 看是否有冲突
   ls pysidecar/                                        # 看现有结构
   cat pysidecar/main.py | head -50                     # 确认 FastAPI 入口 + 既有路由
   cat pysidecar/models.py | head -30                   # 确认 Pydantic models 风格

2. 新增 pysidecar/auto_tune/targets/(目录新建):
   - flat.json(31 频点全 0dB)
   - harman_2017.json(Olive 论文曲线插值 31 频点)
   - bk_1974.json(经典 HiFi · 高频 +1~+2dB)
   - __init__.py(可选 · 若需要 import 加)

3. 新增 pysidecar/auto_tune/target_loader.py(资源加载):
   - def load_target(target_id: str) -> dict:加载 targets/{target_id}.json · 校验 schema · 返回 dict
   - def list_targets() -> List[dict]:返回 3 条曲线 metadata({id, name, description})· Phase 1 UI 选择器用
   - 缓存(LRU)+ 文件不存在抛 ValueError

4. 新增 pysidecar/auto_tune/smoothing.py(数学算子):
   - def one_third_oct_smoothing(magnitude_db: np.ndarray, freq_hz: np.ndarray) -> np.ndarray
   - ISO 1/3 oct 31 中心频点 · 对每个 fc 取区间几何平均 · 见上述 schema 段定义
   - 单测覆盖:输入 100 频点平直 → 输出 31 频点全相同 · 输入有局部峰 → 输出局部 +N dB

5. 新增 pysidecar/auto_tune/averaging.py(数学算子):
   - def multi_point_averaging(measurements: List[dict]) -> dict
   - 幅度对数域算术平均(等价几何平均)· 相位 complex exp 平均后 angle
   - 单测覆盖:N=3 同源测量 → 输出 = 输入(任一)· N=3 不同测量 → 输出在中位附近

6. 新增 pysidecar/auto_tune/deviation.py(核心数学):
   - def compute_deviation(meas: dict, target: dict, smoothing: str = "one_third_oct") -> dict
   - 逻辑:
     · 若 smoothing="one_third_oct"·先用 smoothing.one_third_oct_smoothing
     · deviation_curve_db = meas_smoothed - target_db(对齐 31 频点)
     · resonance_peaks = scipy.signal.find_peaks(deviation, height=6dB) + scipy.signal.find_peaks(-deviation, height=6dB)
     · 估算 Q(用峰宽 -3dB 点)+ gain_db(峰值)· type="peak" if positive else "dip"
     · rms_error_db = np.sqrt(np.mean(deviation**2))
     · suggestions:取 top-5 峰 · {freq, gain=-deviation_at_peak, q, reason}
   - 单测覆盖:平直输入 vs 平直目标 → deviation 全 0 · rms_error_db=0 · peaks 空 · 输入有 +6dB @ 1kHz → suggestions 含 1kHz -6dB 项

7. 新增 pysidecar/auto_tune/simulate.py(核心数学):
   - def simulate_apply(current_response: dict, filters: List[dict]) -> dict
   - 对每个 filter 用 RBJ biquad cookbook 计算系数(peak/low_shelf/high_shelf)· 或用 scipy.signal.iirpeak/iirnotch
   - scipy.signal.freqz 计算频响 H(jw)
   - predicted_magnitude_db = current_magnitude_db + 20*log10(|H|)(对数域相加)
   - predicted_phase_deg = current_phase_deg + np.angle(H, deg=True)
   - 返回 predicted_response dict
   - 单测覆盖:current 全 0dB · filter peak +6dB Q=1.0 @1kHz → predicted 在 1kHz 处 ≈ +6dB 其他基本不变

8. 新增 pysidecar/models_autotune.py(或扩 models.py):
   - Pydantic class DeviationRequest / DeviationResponse
   - Pydantic class SimulateApplyRequest / SimulateApplyResponse
   - Pydantic class TargetCurveInfo(用于 list_targets 返回)

9. 修改 pysidecar/main.py(新增 2 端点 + 扩 1 端点):
   - @app.post("/auto_tune/deviation") · 调 deviation.compute_deviation · 返回 DeviationResponse
   - @app.post("/auto_tune/simulate_apply") · 调 simulate.simulate_apply · 返回 SimulateApplyResponse
   - 既有 @app.post("/auto_tune/geq_optimize"):扩 target_id 参数 · 内部 target_loader.load_target(req.target_id) · 兼容既有 target_curve 数组(if-else)
   - @app.get("/auto_tune/targets")(新增 · 可选 · Phase 1 UI 拉曲线列表):调 target_loader.list_targets

10. 单测 + 验收:
    cd pysidecar
    # 新增 tests/auto_tune/test_smoothing.py(>= 3 case)
    # 新增 tests/auto_tune/test_averaging.py(>= 3 case)
    # 新增 tests/auto_tune/test_deviation.py(>= 4 case · 平直/带峰/收敛/边界)
    # 新增 tests/auto_tune/test_simulate.py(>= 3 case · peak/shelf 各 1)
    # 新增 tests/auto_tune/test_endpoints.py(>= 3 case · TestClient 调 3 端点)
    # 至少 16 个新 case 总计
    pytest                                               # 全绿 · 既有不破坏
    pytest tests/auto_tune/ -v                           # 详细看新增覆盖

11. 端到端验证(若 pysidecar 可启动):
    uvicorn main:app --port 8001 &
    curl -X POST http://localhost:8001/auto_tune/deviation -H "Content-Type: application/json" -d '{"freq_hz":[20,...],"magnitude_db":[...],"phase_deg":[...],"target_id":"flat","smoothing":"one_third_oct"}'
    curl -X GET http://localhost:8001/auto_tune/targets    # 返回 3 条曲线 metadata

12. Commit + push:
    cd ..   # 回到 04_development/
    git add pysidecar/auto_tune/ \
            pysidecar/models_autotune.py \
            pysidecar/main.py \
            pysidecar/tests/auto_tune/
    git commit -m "..."(见下)
    git push origin xistudio

【验收】
- 11-13 文件落地(targets/×3 JSON + target_loader/smoothing/averaging/deviation/simulate ×5 py + models_autotune.py + main.py 修改 + tests/auto_tune/×5 + 可选 __init__.py)
- pytest 全绿 · 新增 >= 16 用例
- 3 端点可达:POST /auto_tune/deviation · POST /auto_tune/simulate_apply · GET /auto_tune/targets · /auto_tune/geq_optimize 扩展兼容 + 新参数生效
- 内置 3 条目标曲线 JSON 格式正确(31 频点 ISO 标准)· `cat targets/flat.json | python -m json.tool` 无错
- 三元组 commit hash 7 位完整
- 端到端验证(可选):curl POST /auto_tune/deviation 返回字段齐全 · GET /auto_tune/targets 返回 3 条

【commit】
commit subject:`feat(P7): add /auto_tune/{deviation,simulate_apply,targets} + 3 built-in target curves (Flat/Harman 2017/B&K 1974) [ADR-AIOS-11 §4.1 fork 6]`

trailer(必须精确):
[step=1/1] [pid=P7] [uid=U-autotune-multi-target] [occupies=P7.K-endpoints+P7.K-models+P7.K-targets]
[files=pysidecar/auto_tune/targets/**, pysidecar/auto_tune/target_loader.py, pysidecar/auto_tune/smoothing.py, pysidecar/auto_tune/averaging.py, pysidecar/auto_tune/deviation.py, pysidecar/auto_tune/simulate.py, pysidecar/models_autotune.py, pysidecar/main.py, pysidecar/tests/auto_tune/**]
[ipc=auto_tune/deviation, auto_tune/simulate_apply, auto_tune/targets, auto_tune/geq_optimize(extended)]

回告格式:① 新增端点列表 ② 3 条目标曲线 freq/db 关键值 ③ 单测新增 case 数 ④ pytest 全绿截图(可选) ⑤ 同步 push 后 P5 fork 5 可立即拉取联调。

【禁止】
- ❌ 不许修改既有 19 端点的现有逻辑(/auto_tune/realtime_frame / /auto_tune/calculate / 18 个 /analyze/* 全部不动)· 仅扩 /auto_tune/geq_optimize target_id 参数(向后兼容 · 不删既有数组接口)
- ❌ 不许修改 contracts/protocol-v1.md(已 frozen)· 本任务走 dev-api 桥接 · 走 P5 fork 5 转发
- ❌ 不许改 frontend / backend_csharp / dsp_algo 代码(本任务 100% pysidecar 内)
- ❌ 不许引入新依赖(numpy + scipy + FastAPI + pydantic 已存量 · 不许 import 其他)· 若必须新增需先 ask
- ❌ 不许把数学逻辑写到 main.py 路由层(必须在 auto_tune/*.py 模块内 · main.py 仅做路由 + 调用)
- ❌ 不许在 P7 上做硬件 I/O(WASAPI / 麦克风 / 文件读写超出 targets/ 范围)· 数学纯函数为主
- ❌ 不许跳验收 · pytest 红必须修到全绿 · 不许 skip 测试
- ❌ 不许省略三元组 trailer
- ❌ 不许自改本 prompt 文件

解锁链(本任务 zombie 后)

  • ✅ P5.U-autotune-batch-pipeline 解锁联调真跑(Step 7 e2e 可调本任务新端点)
  • ✅ P3.U-autotune-phase1-measure 解锁(目标曲线选择器拉 GET /auto_tune/targets · 不再 mock)
  • ✅ P3.U-autotune-phase2-analyze 间接解锁(P5 fork 5 中转 deviation 端点)
  • ✅ P3.U-autotune-phase3-optimize 间接解锁(P5 fork 5 中转 geq_optimize + simulate_apply)
  • ✅ ADR-AIOS-11 §4.1 fork 6 收尾 · P7 数学层全栈就绪 · 解锁 P3 全 4 Phase 真跑

风险评估

风险 缓解
Harman 2017 曲线插值错误(非线性段间不平滑) 用 scipy.interpolate.interp1d(kind='cubic')插值 · 单测验证 1kHz 处 = 0dB · 200Hz +3dB · 20kHz -8dB
RBJ biquad 实现错误 / scipy.signal.iirpeak 与 cookbook 不符 优先用 scipy.signal.iirpeak/iirfilter(成熟实现)· 不手写 cookbook · 单测对照 freq_hz=fc 处 gain ≈ filter.gain_db
⅓ oct 平滑边界处理(20Hz 以下 / 20kHz 以上) 用 numpy.interp 外推 · 边界外用最近值 · 单测覆盖边界
多点平均相位环绕(±π 跳变) 用 complex exp 而非直接相加 angle · 单测验证相位跳变场景
pytest 既有用例破坏 git pull 后先跑全量 pytest 看基线 · 新代码隔离在 auto_tune/ 子目录

历史

时间 事件 hash
2026-05-29 13:46 首次派发(ADR-AIOS-11 accepted 同时 · 用户原话 "accept ADR-AIOS-11 · 顺便 start fork 5+6" · ClaudeB 优先做本任务 1.0d 短工作量) -