diff --git a/deploy/profile-scripts/functional_health_check.py b/deploy/profile-scripts/functional_health_check.py index d9456e22..16471360 100644 --- a/deploy/profile-scripts/functional_health_check.py +++ b/deploy/profile-scripts/functional_health_check.py @@ -40,7 +40,7 @@ REGISTRY = [ "repair": {"action": "rerun_script", "script": "market_watch.py"}}, {"module": "mtf_cache", "function": "多周期均线缓存刷新(mtf_cache)", "check": {"type": "db_freshness", "table": "mtf_cache", "col": "updated_at", - "max_age_min": 75, "when": "trading"}, + "max_age_min": 240, "when": "trading"}, # 2026-08-24 75→240: 调度为50 7,11,14三趟/天,间隔3.5h,75min必误报 "repair": {"action": "rerun_script", "script": "refresh_mtf_cache.py"}}, {"module": "macro_context", "function": "宏观上下文刷新(macro_context_log)", "check": {"type": "db_freshness", "table": "macro_context_log", "col": "created_at", @@ -57,8 +57,8 @@ REGISTRY = [ {"module": "reassess_daily", "function": "每日12维重评完成度(持仓当日覆盖+分析存在率)", "check": {"type": "reassess_daily", "when": "daily"}, "repair": {"action": "rerun_script", "script": "batch_reassess.py --type holding --today"}}, - {"module": "gateway_llm", "function": "LLM调用链可用(gateway agent.log)", - "check": {"type": "agent_log", "max_age_min": 30, "when": "always"}, + {"module": "gateway_llm", "function": "LLM调用链可用(ocg-router探测)", + "check": {"type": "ocg_router", "when": "always"}, # 2026-08-24 agent.log检查过时(红线11后LLM走ocg-router直连,无gateway流量≠故障) "repair": {"action": "llm_diagnose"}}, {"module": "sense_ocr", "function": "识图服务(SenseNova OCR配置+API可达)", "check": {"type": "ocr_health", "when": "always"}, @@ -119,6 +119,22 @@ def check_agent_log(chk, now): return "fail", f"检查失败: {e}" +def check_ocg_router(chk, now): + """LLM链路真实可用性:ocg-router /v1/models 探测(2026-08-24 替代过时 agent.log 检查)""" + try: + import urllib.request, json as _j + req = urllib.request.Request("http://127.0.0.1:19878/v1/models", + headers={"Authorization": "Bearer ocg-router-local"}) + with urllib.request.urlopen(req, timeout=8) as r: + d = _j.loads(r.read().decode()) + n = len(d.get("data", [])) + if n > 0: + return "ok", f"ocg-router在线 {n}模型" + return "fail", "ocg-router模型列表空" + except Exception as e: + return "fail", f"ocg-router不可达: {str(e)[:80]}" + + def check_bot_activity(chk, now): try: # 第一判据:服务当前是否 active(权威"现在在不在跑") @@ -273,6 +289,8 @@ def main(): status, reason = check_file_freshness(chk, now) elif t == "agent_log": status, reason = check_agent_log(chk, now) + elif t == "ocg_router": + status, reason = check_ocg_router(chk, now) elif t == "bot_activity": status, reason = check_bot_activity(chk, now) elif t == "ocr_health": diff --git a/deploy/profile-scripts/self_repair.py b/deploy/profile-scripts/self_repair.py index 60cc7495..d8f05975 100644 --- a/deploy/profile-scripts/self_repair.py +++ b/deploy/profile-scripts/self_repair.py @@ -177,6 +177,9 @@ def llm_diagnose(failure): - 数据库: /home/hmo/MoFin/data/mofin.db - 当前时间: {datetime.now().strftime('%Y-%m-%d %H:%M')}(注意是否交易时段,非交易时段部分管道停跑属正常) +【注册表推荐修复动作】{json.dumps(hint, ensure_ascii=False) if hint else '无'} +(判断为真实异常时,rerun_script 的 script 名必须严格用推荐动作里的,禁止自编) + {WHITELIST_ACTIONS} 请只输出一个 JSON 动作(不要其他文字)。如果是非交易时段的正常空闲,选 none。""" @@ -197,6 +200,10 @@ def llm_diagnose(failure): action = json.loads(m.group(0)) if action.get('action') in ('rerun_script', 'restart_service', 'sync_links', 'switch_llm_key', 'none'): + # 2026-08-24 script名校正:LLM常把模块名当脚本名编(如mtf_cache→非法), + # 注册表 hint 有标准脚本名时强制使用(空转修复循环根治) + if action.get('action') == 'rerun_script' and hint.get('script'): + action['script'] = hint['script'] return action, text[:200] except Exception as e: print(f' LLM 诊断不可用: {str(e)[:80]}')