"""把 A/B 采样结果(export/ai-ab-test/round_v1_app2a_area/*.json)直接写入 ai_cache。 用途:E4 小程序 E2E 验证时,不重复消耗百炼预算即可填充 app2a 缓存。 用法: # 默认:每业态取 round1 结果,共 8 个组合写入 cache PYTHONIOENCODING=utf-8 .venv/Scripts/python.exe scripts/ab_to_cache.py # 只写某个业态: PYTHONIOENCODING=utf-8 .venv/Scripts/python.exe scripts/ab_to_cache.py --area vip """ from __future__ import annotations import argparse import json import os import sys from pathlib import Path sys.path.insert(0, 'apps/backend') from dotenv import load_dotenv load_dotenv() from app.ai.cache_service import AICacheService from app.ai.schemas import CacheTypeEnum SITE_ID = 2790685415443269 TIME_DIMENSION = 'this_month' AB_DIR = Path('export/ai-ab-test/round_v1_app2a_area') AREAS = ('hall', 'hallA', 'hallB', 'hallC', 'vip', 'snooker', 'mahjong', 'ktv') def main(): ap = argparse.ArgumentParser() ap.add_argument('--area', type=str, default=None, help='只写单个业态,不指定则全部') ap.add_argument('--round', type=int, default=1, help='使用第几轮结果(默认 round 1)') args = ap.parse_args() target_areas = [args.area] if args.area else list(AREAS) cache_svc = AICacheService() ok = 0 skipped = 0 for area in target_areas: path = AB_DIR / f'{area}_round{args.round}.json' if not path.exists(): print(f'[SKIP] {area}: 文件不存在({path}),可能 A/B 尚未跑到此业态') skipped += 1 continue with open(path, 'r', encoding='utf-8') as f: result = json.load(f) parsed = result.get('parsed') if not isinstance(parsed, dict) and not isinstance(parsed, list): print(f'[SKIP] {area}: parsed 字段异常') skipped += 1 continue # 标准化:result_json 应为 {insights: [...]} 或直接 [...] if isinstance(parsed, list): result_json = {'insights': parsed} else: result_json = parsed target_id = f'{TIME_DIMENSION}__{area}' cache_svc.write_cache( cache_type=CacheTypeEnum.APP2A_FINANCE_AREA.value, site_id=SITE_ID, target_id=target_id, result_json=result_json, triggered_by='ab_replay', score=None, ) ok += 1 print(f'[OK] 写入 app2a_finance_area · {target_id} · {len(result_json.get("insights", []))} 条') print() print(f'=== 完成:{ok} 个写入 · {skipped} 个跳过 ===') if __name__ == '__main__': main()