处理评述问题

This commit is contained in:
zlt 2026-08-07 09:13:55 +08:00
parent 90d27d43fd
commit bcf9ff0481
1 changed files with 100 additions and 3 deletions

103
DEVLOG.md
View File

@ -11,12 +11,22 @@
> - **bionic_trader决策系统** 跑在 `192.168.16.188:38000`,挂载卷,
> `git pull``docker compose restart backend-api worker-brain` 即生效;
> **新增 env 必须 `docker compose up -d --force-recreate`**restart 不重读 env。
> 容器时钟是 UTC看时间戳先加八小时。
> - **akg-factor-bridge因子桥**`factorevaluation`,容器名 `akg_factor_bridge`
> API 在 8300常驻 API 改码要 compose restart。容器时钟是 UTC。
> API 在 8300常驻 API 改码要 compose restart。
>
> **时区2026-08-06 查实、2026-08-07 再证一次,这里写的以实测为准)**
> 不能按「哪个系统」一刀切,要按「哪种时间」分:
> - **容器时钟与容器日志正文** —— 北京时间,**不要加八小时**。
> 证据bionic 容器内 `date``15:37 CST`
> - **数据库的时间列**`strategy_audit_log.created_at`、
> `strategy_daily_results.updated_at` 等)—— **UTC要加八小时**
> 证据08-07 北京 09:03 时该库 `SELECT NOW()` = `2026-08-07 01:03:32`
> - **日期列**`audit_date`、`trade_date`)—— 北京日期,不换算。
> - `docker logs -t` 自己加的那个时间戳前缀是 UTC跟正文里 Python logging
> 打的时间不是一个口径,别混着读。
>
> 记录纪律:判收状态只写「真机见过」或「未判收」两种,不写「应该没问题」。
> 时间一律写北京时间,引用桥或决策系统的日志时间时先加八小时并标注已换算。
> 时间一律写北京时间,引用数据库时间列时先加八小时并标注已换算。
---
@ -450,6 +460,93 @@ PMS_UNAVAILABLE 三个值,而 `pms_advisor._today_exit_verdict` 第 102 行明
---
## 2026-08-07 · 股票评述里冒出「【手动重跑AKG_PLAN】」运维口径的话被当成风控质询
**做了什么**
页面上一些股票的评述里出现了「【手动重跑AKG_PLAN】」这种谁也看不懂的字段。第一反应会怀疑
是前一天新建仓那批改动,但**不是**:三个仓库全文检索「手动重跑」只有一个出处,
`bionic_trader/scripts/rerun_pool.py` 第 237238 行。链条如下(全部是源码,不是推测):
1. `rerun_pool.py` 下发 `analyze_strategic_plan.delay(c, reason, None, target_date)`
**第二个位置参数不是留痕字段,是 `reviewer_feedback`** —— 风控官质询通道。
2. `tasks_brain.IntradayClassifier.classify()` 第一道判断是 `if "【盘中" not in text: return None`
「【手动重跑】」不带这个前缀,返回 None。
3. 于是掉进 `elif reviewer_feedback:` 分支,被拼进提示词的
`[📢 CRITICAL CHALLENGE FROM RISK OFFICER]` 段,后面跟着
`You MUST address this in your analysis`
4. 那是一句命令。大脑照办,把这句运维口径的话写进了 `analysis`
5. `generate_chinese_report``save_to_database` → 覆盖进
`strategy_daily_results.analysis_summary`,也就是页面上的评述。
**这条真正的教训不是那个字段,是它顺带证实的悬项二。** `rerun_pool` 落库是
`INSERT ... ON DUPLICATE KEY UPDATE`,把 `signal_type / support_level / pressure_level /
analysis_summary` 一起就地覆盖。查实的落库时刻(库时钟是 UTC下面已换算成北京时间
| trade_date | 行数 | 落库时刻(北京,已换算) | 当时是什么时候 |
|---|---|---|---|
| 20260806 | 16 | 08-06 22:32 → 22:45 | 收盘后,安全 |
| 20260805 | 18 | 08-05 22:30 → **08-06 11:04** | **盘中**,改写的是当时正被读的昨夜结论 |
| 20260804 | 11 | **08-05 13:04** → 08-07 00:50 | **盘中**,补录历史日 |
08-06 早盘 11:04 与 08-05 午盘 13:04 各有一次盘中重跑。而这张表下游有两个人在读:
bionic 的 `pms_advisor`(支撑压力位算 PMS 买卖区间、`signal_type` 走 `BAD_Y_SIGNALS` 闸)、
`pool.py``BAD_SIGNALS`(决定把哪只票请出候选池)。所以「盘中不跑 push-pool」这条纪律
不只针对桥,`rerun_pool` 同样在内 —— 这次是拿实测把它钉死了,不再是推测。
顺带记一条待查的:`SZ000800` 现在有两行相互打架的定性,`trade_date=20260806` 是 `SELL`
08-06 22:38 写入),`trade_date=20260804` 是 `DROPPED`08-07 00:50 写入,晚了两个多小时)。
补录历史日会写出一行「时间上更新、日期上更旧」的结论,取数方按 `trade_date` 排还是按
`updated_at` 排会拿到不同答案。两边取数口径要对一遍,这次没做。
**改法(两处,缺一不可)**
- **根治** —— `rerun_pool.py` 下发时第二个位置参数固定传 `None``--reason` 保留,但改成
只印在脚本自己的输出里给人看。
- **兜底** —— `tasks_brain.py``_is_ops_note()` 前缀护栏,认
`【手动重跑】/【运维】/【回补】`,命中就先打一行日志再把 `reviewer_feedback` 置空。
为什么两处都要:`rerun_pool` 的用法示例第 2 条明写着鼓励人手填
`--reason "调整X因子后重跑"`,只堵住默认值,下次手填照样中招。
护栏落点选在 `analyze_strategic_plan` 打完那行「🧠 Brain 正在介入」日志之后、
`IntradayClassifier.classify` 之前。**先打日志再丢弃**是有意的:「谁在什么时候用什么理由
重跑了这只票」这条线索要留在日志里,它只是不该进大模型的证据。拦在源头一次就够,因为
下游用到 `reviewer_feedback` 的只有 classify 和风控官质询段两处。
**已经被污染的评述救不回来**:就地覆盖,没有历史表。要洗只能改完代码后按同一个池重跑一遍
让它再覆盖一次,而那又是一次全量重算、支撑压力位会再动 —— 只能收盘后做,别在盘中洗。
**动了哪些文件**(都在 bionic_traderPMS 侧一个字没动)
- `scripts/rerun_pool.py` —— 下发传 `None``--reason` 改为本地留痕;文件头补两段说明
(「什么时候不能跑」「为什么 --reason 不再下发给大脑」)。
- `workers/tasks_brain.py` —— 新增 `_OPS_NOTE_PREFIXES``_is_ops_note()`
`analyze_strategic_plan` 里加四行护栏。既有两条路径(盘中事件、常规风控意见)零改动。
- `scripts/selftest_ops_note_guard.py`新增24 项)—— 不 import `tasks_brain`
(它拖着 milvus/llm靠 AST 把 `_is_ops_note` 从源码里抠出来单独执行做真实断言,
再用 AST 校验护栏落点与 `delay` 的第二个实参。做过三次变异验证,确认它真的会失败:
说明文字塞回去、护栏只打日志不置空、前缀写宽一个字,三次都被抓住。
**部署方式**
决策系统那台:`git pull` 后 `docker compose restart worker-brain`。没有新增 env
不需要 `--force-recreate`。**只重启 worker-brain 就够**`backend-api` 没动。
**真机判收**
未判收。判收两步:① 容器里跑一次
`docker exec trader_worker_brain python scripts/selftest_ops_note_guard.py` 见「全部通过」;
② 收盘后拿任意一只票跑一次 `rerun_pool.py --group AKG_PLAN --limit 1 --reason "护栏验证"`
确认 worker 日志里有「🛡️ 运维口径说明已从提示词中剔除」这一行,且该票新落库的
`analysis_summary` 里不含「手动重跑」。
**还欠着什么**
1. 上面两步真机判收。
2. `SZ000800` 那种「补录历史日写出时间更新、日期更旧的行」,取数方按 `trade_date` 还是
`updated_at` 排要对一遍口径(`pms_advisor` 与桥 `pool.py` 两处)。
3. 已污染的三批评述16/18/11 行)要不要收盘后洗一遍,没定。
4. `rerun_pool.py``--dry-run` 的中文说明写的是「干跑」,项目里同类东西叫「试算」,
措辞不统一。这次没改,因为跟本条改动无关,单独提。
---
<!--
下一条节点从这里往下写,格式照抄上面:
## YYYY-MM-DD · 一句话标题