增加大模型
This commit is contained in:
@@ -9,7 +9,7 @@ import httpx
|
||||
|
||||
from .chart_image import render_daily_chart_png_async
|
||||
from .config import settings
|
||||
from .db import get_llm_interpretation, save_llm_interpretation
|
||||
from .db import save_llm_interpretation
|
||||
from .stats import compute_three_day_stats
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -29,6 +29,33 @@ def get_interpret_state() -> dict:
|
||||
return dict(_interpret_state)
|
||||
|
||||
|
||||
def init_interpret_batch() -> dict:
|
||||
"""同步初始化批次(API 立即返回 batch_id,避免前端刷新拉错旧批次)。"""
|
||||
if _interpret_lock.locked() or _interpret_state.get("running"):
|
||||
return {"ok": False, "message": "解读任务进行中", **get_interpret_state()}
|
||||
|
||||
stats = compute_three_day_stats()
|
||||
if not stats.get("ok"):
|
||||
return {"ok": False, "message": stats.get("message", "统计数据未就绪")}
|
||||
|
||||
sym_list = stats.get("symbols") or [x["symbol"] for x in stats.get("items", [])]
|
||||
if not sym_list:
|
||||
return {"ok": False, "message": "三日交集为空"}
|
||||
|
||||
bid = datetime.now().strftime("%Y-%m-%d-%H%M")
|
||||
_interpret_state.update(
|
||||
{
|
||||
"running": True,
|
||||
"current_symbol": "",
|
||||
"done": 0,
|
||||
"total": len(sym_list),
|
||||
"batch_id": bid,
|
||||
"last_error": "",
|
||||
}
|
||||
)
|
||||
return {"ok": True, "batch_id": bid, "total": len(sym_list), **get_interpret_state()}
|
||||
|
||||
|
||||
def _api_url() -> str:
|
||||
base = settings.llm_base_url.rstrip("/")
|
||||
if base.endswith("/v1"):
|
||||
@@ -110,21 +137,21 @@ async def run_interpretation_batch(
|
||||
*,
|
||||
batch_id: str | None = None,
|
||||
) -> dict:
|
||||
global _interpret_state
|
||||
|
||||
if _interpret_lock.locked():
|
||||
return {"ok": False, "message": "解读任务进行中"}
|
||||
|
||||
stats = compute_three_day_stats()
|
||||
if not stats.get("ok"):
|
||||
_interpret_state["running"] = False
|
||||
return {"ok": False, "message": stats.get("message", "统计数据未就绪")}
|
||||
|
||||
sym_list = symbols or stats.get("symbols") or [x["symbol"] for x in stats.get("items", [])]
|
||||
if not sym_list:
|
||||
_interpret_state["running"] = False
|
||||
return {"ok": False, "message": "三日交集为空"}
|
||||
|
||||
stats_map = {x["symbol"]: x for x in stats.get("items", [])}
|
||||
bid = batch_id or datetime.now().strftime("%Y-%m-%d-%H%M")
|
||||
bid = batch_id or _interpret_state.get("batch_id") or datetime.now().strftime("%Y-%m-%d-%H%M")
|
||||
interval = settings.llm_symbol_interval_sec
|
||||
|
||||
async with _interpret_lock:
|
||||
@@ -132,10 +159,9 @@ async def run_interpretation_batch(
|
||||
{
|
||||
"running": True,
|
||||
"current_symbol": "",
|
||||
"done": 0,
|
||||
"done": _interpret_state.get("done", 0),
|
||||
"total": len(sym_list),
|
||||
"batch_id": bid,
|
||||
"last_error": "",
|
||||
}
|
||||
)
|
||||
for i, sym in enumerate(sym_list):
|
||||
@@ -164,11 +190,17 @@ async def run_interpretation_batch(
|
||||
|
||||
def schedule_interpret_background(symbols: list[str] | None = None) -> None:
|
||||
"""后台启动解读,不阻塞请求。"""
|
||||
info = init_interpret_batch()
|
||||
if not info.get("ok"):
|
||||
logger.info("Startup LLM skip: %s", info.get("message"))
|
||||
return
|
||||
bid = info.get("batch_id")
|
||||
|
||||
async def _run():
|
||||
try:
|
||||
await run_interpretation_batch(symbols)
|
||||
await run_interpretation_batch(symbols, batch_id=bid)
|
||||
except Exception as e:
|
||||
logger.error("Background LLM batch failed: %s", e)
|
||||
_interpret_state["running"] = False
|
||||
|
||||
asyncio.create_task(_run())
|
||||
|
||||
+27
-8
@@ -14,7 +14,7 @@ from .exceptions import BinanceRateLimitedError
|
||||
from .period_api import get_period_top30
|
||||
from .periods import get_daybefore_period, get_today_period, get_yesterday_period
|
||||
from .chart_image import render_daily_chart_png_async
|
||||
from .llm_service import get_interpret_state, run_interpretation_batch
|
||||
from .llm_service import get_interpret_state, init_interpret_batch, run_interpretation_batch
|
||||
from .scheduler import job_finalize_yesterday, job_push_wecom, job_refresh_today, start_scheduler, startup_tasks, stop_scheduler
|
||||
from .stats import compute_three_day_stats
|
||||
from .aggregator import aggregate_period
|
||||
@@ -207,19 +207,38 @@ async def api_llm_status():
|
||||
|
||||
|
||||
@app.get("/api/llm/interpretations")
|
||||
async def api_llm_interpretations(batch_id: str | None = None, limit: int = 50):
|
||||
return {"items": get_llm_interpretations(batch_id, limit)}
|
||||
async def api_llm_interpretations(batch_id: str | None = None, limit: int = 100):
|
||||
"""返回解读列表;进行中时优先当前批次(即使尚无记录)。"""
|
||||
st = get_interpret_state()
|
||||
bid = batch_id or (st.get("batch_id") if st.get("running") else None)
|
||||
items = get_llm_interpretations(bid, limit) if bid else get_llm_interpretations(None, limit)
|
||||
if not bid and items:
|
||||
bid = items[0].get("batch_id", "")
|
||||
return {
|
||||
"items": items,
|
||||
"batch_id": bid or st.get("batch_id", ""),
|
||||
"running": st.get("running", False),
|
||||
"done": st.get("done", 0),
|
||||
"total": st.get("total", 0),
|
||||
"current_symbol": st.get("current_symbol", ""),
|
||||
}
|
||||
|
||||
|
||||
@app.post("/api/llm/interpret/run")
|
||||
async def api_llm_interpret_run(background_tasks: BackgroundTasks):
|
||||
if not settings.llm_api_key.strip():
|
||||
raise HTTPException(400, "LLM_API_KEY 未配置")
|
||||
state = get_interpret_state()
|
||||
if state.get("running"):
|
||||
return {"ok": False, "message": "解读任务进行中", **state}
|
||||
background_tasks.add_task(run_interpretation_batch)
|
||||
return {"ok": True, "message": "已启动三日交集解读队列", **get_interpret_state()}
|
||||
info = init_interpret_batch()
|
||||
if not info.get("ok"):
|
||||
return info
|
||||
bid = info.get("batch_id")
|
||||
background_tasks.add_task(run_interpretation_batch, batch_id=bid)
|
||||
return {
|
||||
"ok": True,
|
||||
"message": "已启动三日交集解读队列",
|
||||
"batch_id": bid,
|
||||
**get_interpret_state(),
|
||||
}
|
||||
|
||||
|
||||
@app.post("/api/chart/{symbol}/daily/refresh")
|
||||
|
||||
Reference in New Issue
Block a user