Files
PolyWeather/src/analysis/ai_analyzer.py
T
2026-02-27 14:02:35 +08:00

93 lines
4.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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}
【分析重点】
1. **动力来源**:对比太阳辐射(W/m²)与最高温出现时间。如果低辐射时段气温冲高,说明是强暖平流,预报往往低估这种惯性。
2. **阻碍因子**:由于高湿度(>80%)、降水或全阴天气导致的升温失速。
3. **结算推演**:根据我提供给你的【博弈区间】以及【当前所处时段(是否过了最热期)】推断并告诉我最终结算温度落在哪个区间的希望更大。
4. **结算边界**:如果当前温度处于 X.5 这种进位/舍位边缘,需特别预警。
5. **概率估算**:综合集合预报区间、多模型分歧度、当前实测趋势,对最可能的 2-4 个 WU 结算整数温度给出概率估算(必须加起来 = 100%)。
【输出要求】
1. **禁止废话**,整体控制在 150 字以内。
2. 严格按照以下 HTML 格式输出:
🤖 <b>Groq AI 决策</b>
- 🎲 盘口: [必须明确指出最热时段(如:预计最热在 14:00-16:00)以及当前的博弈区间(如:锁定在 27°C 或 28°C 之间博弈)。若已明确降温,请直接给出死盘结论(如:已过最热点且降温,锁定在 X 度结算,悬念终止)。]
- 💡 逻辑: [不要重复模版例子!请使用一句话提炼机场实测(如风速风向、云量、气温变化趋势)及热力动力因子。]
- 📊 概率: [列出最可能的 2-4 个结算温度及概率。格式示例:3°C(15%) | 4°C(55%) | 5°C(25%) | 6°C(5%)]
- 🎯 置信度: [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 暂时不可用,请稍后再试"