| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- """当下供需 gap 脚本主驱每日任务入口。"""
- from __future__ import annotations
- from datetime import date, datetime
- from typing import Any
- from app.gap_script_demand.config import load_gap_script_demand_config
- from app.gap_script_demand.judging import judge_remake_suitable_demands
- from app.gap_script_demand.odps_demand_pool import fetch_demand_names
- from app.gap_script_demand.odps_writer import build_odps_row, sync_gap_script_demands_to_odps
- from app.gap_script_demand.repository import GapScriptDemandRepository
- from app.gap_script_demand.types import GapScriptDemandConfig
- from app.hot_content.config import load_flow_config
- from app.hot_content.timezone import SHANGHAI_TZ
- def _today_shanghai() -> date:
- return datetime.now(SHANGHAI_TZ).date()
- def print_gap_script_demand_summary(summary: dict[str, Any]) -> None:
- """将脚本主驱流程结果打印到控制台。"""
- print("=" * 60)
- print("当下供需gap-脚本主驱 任务结果")
- print("=" * 60)
- print(f"查询日期: {summary.get('query_date')}")
- print(f"ODPS 分区: {summary.get('partition_dt')}")
- print(f"源 strategy: {summary.get('demand_pool_strategy')}")
- print(f"输出 strategy: {summary.get('output_strategy')}")
- print(f"LLM 模型: {summary.get('llm_model')}")
- print(f"批次大小: {summary.get('judge_batch_size')}")
- if summary.get("skip_reason") in {
- "no_demand_names",
- "partition_data_exists",
- "no_matched_demands",
- }:
- print(f"跳过原因: {summary.get('skip_reason')}")
- if summary.get("skip_reason") == "no_matched_demands":
- print(f"ODPS 需求总数: {summary.get('demand_name_total', 0)}")
- print("匹配可改造数: 0")
- print("=" * 60)
- return
- print(f"\nODPS 需求总数: {summary.get('demand_name_total', 0)}")
- print(f"匹配可改造数: {summary.get('matched_count', 0)}")
- matched_names = summary.get("matched_demand_names") or []
- if matched_names:
- print("\n保留的品类+解构词:")
- for name in matched_names:
- print(f" * {name}")
- mysql_save = summary.get("mysql_save") or {}
- if mysql_save.get("skipped"):
- print(
- f"\nMySQL/ODPS 跳过: reason={mysql_save.get('skip_reason')} "
- f"partition_dt={mysql_save.get('partition_dt')}"
- )
- elif mysql_save:
- print(
- f"\nMySQL 写入: table={mysql_save.get('table')} "
- f"saved={mysql_save.get('saved_count', 0)} "
- f"strategy={mysql_save.get('strategy')}"
- )
- odps_sync = summary.get("odps_sync") or {}
- if odps_sync:
- print(
- f"ODPS 写入: table={odps_sync.get('target_table')} "
- f"partition_dt={odps_sync.get('partition_dt')} "
- f"written={odps_sync.get('written_count', 0)}"
- )
- print("=" * 60)
- def _persist_matched_demands(
- *,
- demand_names: list[str],
- strategy: str,
- partition_dt: str,
- target_table: str,
- sync_odps: bool = True,
- ) -> tuple[dict[str, Any], dict[str, Any]]:
- flow_config = load_flow_config()
- repository = GapScriptDemandRepository(flow_config.mysql)
- try:
- mysql_save = repository.persist_matched_demands(
- demand_names=demand_names,
- strategy=strategy,
- partition_dt=partition_dt,
- )
- if mysql_save.get("skipped") or not mysql_save.get("rows"):
- return mysql_save, {}
- if not sync_odps:
- return mysql_save, {}
- odps_rows = [
- build_odps_row(
- strategy=row["strategy"],
- demand_id=row["demand_id"],
- demand_name=row["demand_name"],
- )
- for row in mysql_save["rows"]
- ]
- odps_sync = sync_gap_script_demands_to_odps(
- rows=odps_rows,
- partition_dt=partition_dt,
- target_table=target_table,
- )
- return mysql_save, odps_sync
- finally:
- repository.close()
- def run_gap_script_demand_daily_job(
- config: GapScriptDemandConfig,
- *,
- query_date: date | None = None,
- sync_odps: bool = True,
- ) -> dict[str, Any]:
- """执行脚本主驱流程:拉取当天供需 gap → LLM 筛选可改造项 → 写 MySQL/ODPS。"""
- target_date = query_date or _today_shanghai()
- partition_dt = target_date.strftime("%Y%m%d")
- summary: dict[str, Any] = {
- "query_date": target_date.isoformat(),
- "partition_dt": partition_dt,
- "demand_pool_strategy": config.demand_pool_strategy,
- "output_strategy": config.output_strategy,
- "demand_pool_source_table": config.demand_pool_source_table,
- "llm_model": config.llm_model,
- "judge_batch_size": config.judge_batch_size,
- "demand_name_total": 0,
- "matched_count": 0,
- "matched_demand_names": [],
- "mysql_save": {},
- "odps_sync": {},
- }
- flow_config = load_flow_config()
- repository = GapScriptDemandRepository(flow_config.mysql)
- try:
- if repository.has_partition_data(
- strategy=config.output_strategy,
- partition_dt=partition_dt,
- ):
- summary["skip_reason"] = "partition_data_exists"
- summary["mysql_save"] = {
- "table": "gap_script_demand_pool_di",
- "strategy": config.output_strategy,
- "partition_dt": partition_dt,
- "skipped": True,
- "skip_reason": "partition_data_exists",
- }
- return summary
- finally:
- repository.close()
- demand_names = fetch_demand_names(
- partition_dt=partition_dt,
- strategy=config.demand_pool_strategy,
- source_table=config.demand_pool_source_table,
- )
- summary["demand_name_total"] = len(demand_names)
- if not demand_names:
- summary["skip_reason"] = "no_demand_names"
- return summary
- print(
- f"gap script demand: start judging "
- f"demand_names={len(demand_names)} batch_size={config.judge_batch_size} "
- f"model={config.llm_model}",
- flush=True,
- )
- matched_demand_names = judge_remake_suitable_demands(
- demand_names=demand_names,
- config=config,
- )
- summary["matched_count"] = len(matched_demand_names)
- summary["matched_demand_names"] = matched_demand_names
- if not matched_demand_names:
- summary["skip_reason"] = "no_matched_demands"
- return summary
- print("gap script demand: persisting matched demands", flush=True)
- mysql_save, odps_sync = _persist_matched_demands(
- demand_names=matched_demand_names,
- strategy=config.output_strategy,
- partition_dt=partition_dt,
- target_table=config.demand_pool_source_table,
- sync_odps=sync_odps,
- )
- summary["mysql_save"] = mysql_save
- summary["odps_sync"] = odps_sync
- if mysql_save.get("skipped"):
- summary["skip_reason"] = mysql_save.get("skip_reason")
- return summary
- def test_gap_script_demand_for_date(
- query_date: date,
- *,
- sync_odps: bool = True,
- ) -> dict[str, Any]:
- """测试指定日期的脚本主驱流程。"""
- config = load_gap_script_demand_config()
- return run_gap_script_demand_daily_job(
- config,
- query_date=query_date,
- sync_odps=sync_odps,
- )
|