# -*- coding: utf-8 -*- """ AI 触发工具 — DWS 任务完成后通知后端 AI 模块。 通过 POST /api/internal/ai/trigger 发送事件, 后端异步执行 AI 调用链(App2 预生成、消费事件链等)。 失败时仅记录日志,不中断 ETL 流程。 """ from __future__ import annotations import logging import os from typing import Any import requests logger = logging.getLogger(__name__) # 超时设置(秒):连接 5s,读取 10s _TIMEOUT = (5, 10) def trigger_ai_event( event_type: str, site_id: int, member_id: int | None = None, payload: dict[str, Any] | None = None, connector_type: str = "feiqiu", ) -> bool: """向后端 AI 模块发送触发事件。 Args: event_type: 事件类型(dws_completed / consumption / note_created / task_assigned) site_id: 门店 ID member_id: 会员 ID(可选) payload: 附加数据(可选) connector_type: 连接器类型,默认 feiqiu Returns: True 表示发送成功,False 表示失败(已记录日志) """ backend_url = os.environ.get("BACKEND_API_URL", "").rstrip("/") token = os.environ.get("INTERNAL_API_TOKEN", "") if not backend_url: logger.warning("AI 触发跳过:BACKEND_API_URL 未配置") return False if not token: logger.warning("AI 触发跳过:INTERNAL_API_TOKEN 未配置") return False url = f"{backend_url}/api/internal/ai/trigger" headers = { "Authorization": f"Internal-Token {token}", "Content-Type": "application/json", } body = { "event_type": event_type, "connector_type": connector_type, "site_id": site_id, "member_id": member_id, "payload": payload or {}, } try: resp = requests.post(url, json=body, headers=headers, timeout=_TIMEOUT) if resp.status_code == 200: data = resp.json() logger.info( "AI 触发成功:event=%s site=%s job_id=%s", event_type, site_id, data.get("trigger_job_id"), ) return True else: logger.warning( "AI 触发失败:event=%s site=%s status=%s body=%s", event_type, site_id, resp.status_code, resp.text[:200], ) return False except requests.RequestException as exc: logger.warning( "AI 触发异常:event=%s site=%s error=%s", event_type, site_id, exc, ) return False