Files
PolyWeather/src/analysis/ai_analyzer.py
T

105 lines
4.4 KiB
Python
Raw Normal View History

import os
import time
import requests
from loguru import logger
# 主力模型 + 备用模型(当主力 500 时自动降级)
MODELS = [
"llama-3.3-70b-versatile",
"llama-3.1-8b-instant",
]
def get_ai_analysis(weather_insights: str, city_name: str, temp_symbol: str) -> str:
"""
通过 Groq API (LLaMA 3.3 70B) 对天气态势进行极速交易分析
内置自动重试 + 模型降级机制
"""
api_key = os.getenv("GROQ_API_KEY")
if not api_key:
logger.warning("GROQ_API_KEY 未配置,跳过 AI 分析")
return ""
url = "https://api.groq.com/openai/v1/chat/completions"
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
prompt = f"""
你是一个专业的天气衍生品(如 Polymarket)交易员。你的任务是分析当前天气特征,判断今日实测最高温是否能达到或超过预报中的【最高值】。
请综合以下提供的【{city_name}】气象特征进行深度推理。
【气象特征与事实】
{weather_insights}
【分析优先级】(按此顺序逐项检查,前置项可推翻后置项的结论)
P1 **实况节奏**(最高优先级):
- 近2-4条METAR的温度走势:连涨/持平/回落?
- 触发阈值:连续2报创新高 → 升温未止;连续2报未创新高且已过峰值窗 → 偏死盘。
- 低辐射时段(<100W/m²)仍在升温 → 暖平流驱动,预报往往低估。
P2 **阻碍因子**
- 触发阈值:湿度>80% 且 云量BKN/OVC持续2报 → 判定压温有效。
- 降水已出现(非trace) → 强压温。
- 若阻碍条件未满足,不可凭"多云"单因子就判断"升温受限"。
P3 **数学概率**
- 参考我提供的结算概率分布,但不可用概率去压过 P1 实况节奏。
- 概率是辅助判据,实测趋势是主判据。
P4 **预报背景**(最低优先级):
- DEB融合值和预报可用于判断上沿空间和回落节奏,但当实测已超预报时,不可作为"难以升温"的主论据。
- 结算边界:温度处于 X.5 进位线附近时需特别预警。
【输出要求】
1. **禁止废话**,整体控制在 300 字以内。
2. 严格按照以下 HTML 格式输出:
🤖 <b>Groq AI 决策</b>
- 🎲 盘口: [必须明确指出最热时段(如:预计最热在 14:00-16:00)以及具体的博弈温度(如:锁定在 27°C 或 28°C)。若符合死盘条件,请直接给出死盘结论并说明理由。]
- 💡 逻辑: [用 3-5 句话深度分析实测与预报的博弈。分析当前动力条件对冲击下一个 WU 整数的支持程度。需包含具体数值。]
2026-02-27 01:17:15 +08:00
- 🎯 置信度: [1-10]/10
"""
for model in MODELS:
for attempt in range(2): # 每个模型最多重试 2 次
try:
payload = {
"model": model,
"messages": [
{"role": "system", "content": "你是不讲废话、只看数据的专业气象分析师。"},
{"role": "user", "content": prompt}
],
"temperature": 0.5,
"max_tokens": 250
}
response = requests.post(url, json=payload, headers=headers, timeout=15)
response.raise_for_status()
result = response.json()
content = result['choices'][0]['message']['content'].strip()
if model != MODELS[0]:
logger.info(f"Groq 降级到备用模型 {model} 成功")
return content
except requests.exceptions.HTTPError as e:
status = e.response.status_code if e.response is not None else 0
if status in (500, 502, 503) and attempt == 0:
logger.warning(f"Groq {model} 返回 {status}{1.5}s 后重试...")
time.sleep(1.5)
continue
else:
logger.warning(f"Groq {model} 失败 (HTTP {status}),尝试下一个模型...")
break # 换下一个模型
except Exception as e:
logger.warning(f"Groq {model} 异常: {e},尝试下一个模型...")
break
logger.error("所有 Groq 模型均不可用")
return "\n⚠️ Groq AI 暂时不可用,请稍后再试"