Spaces:
Configuration error
Configuration error
Download trifecta_bro/tools.py from Brettapps/Trifecta-Lab: direct link, hf CLI and curl.
- Browser
- Download file 4.23 kB
-
https://huggingface.co/spaces/Brettapps/Trifecta-Lab/resolve/main/trifecta_bro/tools.py
- Command line
-
hf download hf://spaces/Brettapps/Trifecta-Lab/trifecta_bro/tools.py
-
curl -L -o tools.py https://huggingface.co/spaces/Brettapps/Trifecta-Lab/resolve/main/trifecta_bro/tools.py
4.23 kB
| """Hermes/Agent reusable tools. | |
| These wrap the deterministic pipeline so an agent can execute natural-language | |
| commands like "Run tomorrow's Australian gallops analysis" or | |
| "Analyse Randwick Race 7" without re-implementing logic. | |
| Each function is a thin, well-documented wrapper returning plain data. Prediction | |
| math stays deterministic (see model/); the agent adds orchestration + explanation. | |
| """ | |
| from __future__ import annotations | |
| import logging | |
| from datetime import datetime, timezone | |
| from pathlib import Path | |
| from typing import Optional | |
| from .config import settings | |
| from .api.formfav_client import FormFavClient | |
| from .api.validator import validate_race_form | |
| from .data.normalizer import normalise_race | |
| from .data.storage import Storage | |
| from .model.analyse_race import analyse_race | |
| from .model.scoring import load_weights | |
| from .jobs.daily_prediction import tomorrow_australia | |
| from .reporting.dashboard import write_outputs | |
| logger = logging.getLogger("trifecta_bro.tools") | |
| def get_tomorrow_meetings(date: str | None = None) -> list[dict]: | |
| """Discover tomorrow's AU gallops meetings via FormFav.""" | |
| date = date or tomorrow_australia() | |
| client = FormFavClient() | |
| raw = client.get_meetings(date) | |
| meetings = [m for m in raw if m.get("country") == settings.country and not m.get("abandoned")] | |
| return [{"track": m.get("track"), "slug": m.get("slug"), "races": m.get("races", [])} | |
| for m in meetings] | |
| def get_race_form(date: str, track_slug: str, race: int) -> dict: | |
| """Fetch normalised race form for one race.""" | |
| client = FormFavClient() | |
| raw = client.get_race_form(date, track_slug, race) | |
| validate_race_form(raw) | |
| return normalise_race(raw).model_dump() | |
| def analyse_race_tool(date: str, track_slug: str, race: int) -> dict: | |
| """Full analysis for a single race (deterministic).""" | |
| client = FormFavClient() | |
| raw = client.get_race_form(date, track_slug, race) | |
| validate_race_form(raw) | |
| race_model = normalise_race(raw) | |
| return analyse_race(race_model, weights=load_weights()) | |
| def rank_runners(date: str, track_slug: str, race: int) -> list[dict]: | |
| a = analyse_race_tool(date, track_slug, race) | |
| return a.get("ranked", []) | |
| def generate_trifecta(date: str, track_slug: str, race: int) -> dict: | |
| a = analyse_race_tool(date, track_slug, race) | |
| return {"trifecta": a.get("trifecta"), "alternatives": a.get("alternatives"), | |
| "confidence": a.get("confidence")} | |
| def save_prediction(date: str, track_slug: str, race: int) -> dict: | |
| a = analyse_race_tool(date, track_slug, race) | |
| with Storage() as s: | |
| s.save_prediction({ | |
| "date": date, "track": a["track"], "track_slug": a["track_slug"], | |
| "race_number": a["race_number"], "model_version": settings.model_version, | |
| "generated_at": datetime.now(timezone.utc).isoformat(), | |
| "top3": a.get("top3"), "trifecta": a.get("trifecta"), | |
| "alternatives": a.get("alternatives"), | |
| "confidence": a["confidence"]["category"], | |
| "confidence_score": a["confidence"]["score"], | |
| "ranked_runners": [{"no": r["number"], "name": r["name"], "score": r["score"]} | |
| for r in a["ranked"]], | |
| "data_completeness": a.get("data_completeness"), | |
| }) | |
| return {"saved": True, "track": a["track"], "race": a["race_number"]} | |
| def run_daily_analysis(date: str | None = None, publish: bool = False) -> dict: | |
| """Run the complete pipeline for a date and return report paths.""" | |
| from ..jobs.daily_prediction import run as _run | |
| return _run(date=date) | |
| def why_ranked_first(date: str, track_slug: str, race: int) -> str: | |
| """Explain in plain language why the top runner ranked first.""" | |
| a = analyse_race_tool(date, track_slug, race) | |
| if a.get("skippable"): | |
| return f"Race skipped: {a.get('reason')}" | |
| top = a["ranked"][0] | |
| subs = top["sub_scores"] | |
| factors = sorted(((k, v) for k, v in subs.items() if v > 0), key=lambda x: x[1], reverse=True) | |
| parts = [f"Runner #{top['number']} {top['name']} ranks first (score {top['score']}) because:" | |
| f" strong {', '.join(k for k, _ in factors[:3])}."] | |
| return " ".join(parts) | |