""" AI 宗师点拨系统 - 通过 Hugging Face Inference API 调用 Qwen3.5-9B 模型 综合五术数据生成深度国学解读 """ import logging import requests from typing import Optional, Dict, Any from huggingface_hub import InferenceClient import time logger = logging.getLogger(__name__) class AIAdvisor: """AI 宗师大师 - 综合五术数据生成解读""" def __init__(self, hf_token: str, model_id: str, timeout: int = 8): """ 初始化 AI 顾问 Args: hf_token: Hugging Face API Token model_id: 模型 ID (Jackrong/Qwen3.5-9B-GLM5.1-Distill-v1) timeout: API 调用超时(秒) """ self.hf_token = hf_token self.model_id = model_id self.timeout = timeout if self.hf_token: self.client = InferenceClient(api_key=self.hf_token) else: self.client = None logger.warning("HF_TOKEN not configured. AI Advisor is disabled.") def _build_master_prompt(self, lunar_data: Dict[str, Any], bazi: Dict[str, Any], qimen: Dict[str, Any], liuren: Dict[str, Any], meihua: Dict[str, Any], planner: Dict[str, Any]) -> str: """ 构建宗师级 Prompt,将五术数据整合成单一问询 Args: lunar_data: 历法信息(日期、真太阳时等) bazi: 八字分析结果 qimen: 奇门盘象 liuren: 六壬四课三传 meihua: 梅花卦象 planner: 皇极经世时辰规划 Returns: Prompt 字符串 """ # 提取关键信息 bazi_pillars = bazi.get('pillars', ['?', '?', '?', '?']) bazi_pattern = bazi.get('pattern', '?') bazi_analysis = bazi.get('analysis', '')[:100] # 截断到 100 字以减少 token 消耗 qimen_ju = qimen.get('ju_num', '?') qimen_patterns = ', '.join(qimen.get('global_patterns', [])) liuren_verdict = ', '.join(liuren.get('bifa_verdicts', [])[:3]) # 取前 3 个 meihua_hex = meihua.get('hexagram', '?') meihua_desc = meihua.get('description', '')[:80] planner_main = planner.get('schedule', [{}])[0] if planner.get('schedule') else {} planner_luck = planner_main.get('luck', '?') prompt = f"""你是国学大师,精通五术玄学。现在根据以下用户的五术测算数据,生成一段深邃而合理的宗师点拨。 【用户信息】 - 真太阳时: {lunar_data.get('tst', '?')} - 农历: {lunar_data.get('lunar_date', '?')} 【五术测算汇总】 1️⃣ 八字分析 四柱: {' '.join(bazi_pillars)} 格局: {bazi_pattern} 简析: {bazi_analysis} 2️⃣ 奇门遁甲 局数: {qimen_ju}阴遁/阳遁 格局: {qimen_patterns} 3️⃣ 六壬毕法 占断: {liuren_verdict} 4️⃣ 梅花易数 卦象: {meihua_hex} 含义: {meihua_desc} 5️⃣ 皇极经世 今日主卦吉凶: {planner_luck} 【任务】 请以宗师的身份,用 2-3 句古文/半文言风格的语句,综合上述五术数据,给出这位提问者的当日大运走向和核心建议。 要求: - 语气简洁有力,带有一点"仙气"但不过度渲染 - 必须同时涉及至少 3 个术数的数据 - 如有吉象则鼓励进取,凶象则建议谨慎守成 - 避免绝对化表述,留下理性的解释空间 【宗师点拨】 """ return prompt def get_master_insight(self, divination_results: Dict[str, Any]) -> Optional[str]: """调用 Hugging Face Inference API 获取宗师解读""" if not self.hf_token: logger.debug("AI Advisor is disabled (no HF_TOKEN)") return None try: prompt = self._build_master_prompt( divination_results.get('lunar_data', {}), divination_results.get('bazi', {}), divination_results.get('qimen', {}), divination_results.get('liuren', {}), divination_results.get('meihua', {}), divination_results.get('planner', {}) ) logger.debug(f"Calling Hugging Face API with model {self.model_id}") start_time = time.time() if not self.client: return "【宗师未苏醒】客户端初始化失败,请检查配置。" # 使用官方 InferenceClient 自带的智能路由功能 (支持 Together/HF Pro 等多种后端引擎) messages = [{"role": "user", "content": prompt}] response = self.client.chat_completion( messages=messages, model=self.model_id, max_tokens=300, stream=False, temperature=0.7, top_p=0.95 ) elapsed = time.time() - start_time insight = response.choices[0].message.content.strip() logger.info(f"AI Advisor response received in {elapsed:.2f}s: {insight[:100]}") return insight if insight else "【宗师沉默】模型返回了空信息。" except Exception as e: # 捕获 HF Hub 相关错误及普通错误 err_msg = str(e) logger.error(f"HF API call failed: {type(e).__name__} - {err_msg}") if "401" in err_msg or "Unauthorized" in err_msg: return f"【宗师传音受阻】云端认证失败 (HTTP 401)。请确保 HF_TOKEN 具有 Inference 权限并且未过期。" elif "503" in err_msg or "loading" in err_msg.lower(): return f"【宗师正在入定】模型节点正在冷启动唤醒中,大约需要半分钟,请稍后重新起课。" elif "404" in err_msg or "not found" in err_msg.lower(): return f"【时空道标丢失】找不到该模型 ({self.model_id}) 或其不支持此种对话模式,请尝试更换模型ID。" elif "timeout" in err_msg.lower(): return f"【宗师传音超时】跨越时空通讯未能按时接通,请稍后重试。" else: return f"【宗师连接中断】({type(e).__name__}) 请稍后重试。"