# KRONECTOR DataAgent Architecture ## Overview The **DataAgent** (`agents/data_agent.py`) transforms natural-language F1 queries into prediction-ready DataFrames compatible with the ML pipeline. It bridges user intent with model-ready data. ``` User Query → Groq LLM (parse) → Extract Intent → Query Data → DataFrame → predict_dataframe() ``` ## Components ### 1. **Query Intent Extraction** Function: `parse_query_with_groq(query: str) -> QueryIntent` Uses **Groq llama3-70b-8192** to parse natural language and extract: - `season` (int): F1 season year - `round` (int): Race round number - `driver_id` (str | None): 3-letter FastF1 driver code - `driver_name` (str | None): Driver full name - `query_intent` (str | None): What the user is asking **Prompt Strategy:** - Strict JSON-only output (zero temperature) - Uses FastF1 3-letter driver codes (VER, HAM, etc.) - Fails safely with clear error messages **Example:** ```python intent = parse_query_with_groq("What was Max's win probability at Monaco 2023?") # Returns: {"season": 2023, "round": 6, "driver_id": "VER", "driver_name": "Max Verstappen"} ``` ### 2. **Data Filtering & Assembly** Functions: - `_load_feature_data(path)` - Load parquet dataset - `_filter_by_intent(df, intent)` - Filter by season/round/driver - `build_prediction_dataframe(intent, data_path)` - Complete filtering pipeline **Input Schema (from fastf1_pipeline.py):** ``` season, round, driver_id, driver_name, team grid_position, finish_position, circuit_id sector_1_time, sector_2_time, sector_3_time avg_lap_time_practice tire_compound, tire_age_laps, fresh_tire pit_stop_count, team_pit_speed weather_temp_track, weather_rainfall championship_standing ``` ### 3. **Data Pipeline Integration** The returned DataFrame flows directly into: ```python # DataAgent output result = data_agent("Verstappen Monaco 2023") df = result["dataframe"] # Compatible with ML pipeline bundle, encoders = prepare_model_data(df) predictions = predict_dataframe(df, model, encoders) ``` **No intermediate transformations needed** — the agent returns FastF1-schema data that feature_engineering.py handles. ## API Reference ### Main Entry Point ```python def data_agent( query: str, data_path: str | Path = DEFAULT_DATA_PATH, parser: IntentParser | None = None, ) -> DataAgentOutput: """ Parse natural-language query and return prediction-ready rows. Args: query: Natural-language F1 query data_path: Path to fastf1_races.parquet parser: Optional custom parser (for testing/offline use) Returns: DataAgentOutput with: - query (str): Original user query - intent (QueryIntent): Parsed season/round/driver - rows (list[PredictionInputRow]): Matching race rows as dicts - dataframe (pd.DataFrame): Full DataFrame for ML pipeline """ ``` ### CLI Usage ```bash # Parse and display results python -m agents.data_agent "Verstappen Monaco 2023" # Output as JSON python -m agents.data_agent "Hamilton Silverstone 2023" --json # Custom data path python -m agents.data_agent "Norris Austin 2024" --data-path /path/to/races.parquet ``` ## Testing **Run tests:** ```bash python -m pytest tests/test_data_agent.py -v ``` **Test fixtures include:** - Groq API mocking for unit tests - Temporary parquet datasets - Prediction pipeline compatibility checks ## Error Handling | Error | Cause | Resolution | |-------|-------|-----------| | `GROQ_API_KEY is required` | Missing env var | Set `GROQ_API_KEY` in `.env` | | `No rows found for season=X round=Y` | Race doesn't exist in data | Check calendar/data availability | | `No rows matched driver intent` | Driver not in race | Verify driver code and race round | | `JSON parse error` | Groq returned invalid JSON | Retry with lower temperature | ## Design Decisions ### Plain Python (No LangGraph) - Groq API is lightweight and doesn't require orchestration framework - Single synchronous call for query parsing - Future: LangGraph can wrap this for multi-turn conversations ### TypedDict Schema - Ensures type safety across data pipeline - Explicit columns prevent silent failures - Compatible with mypy strict mode ### Groq for Intent Extraction - Fast: 70B model with 8K context window - Accurate: Instruction-tuned for structured output - Cost: $0.19/$0.39 per million tokens (vs Claude) ## Example Workflows ### Single Race Prediction ```python from agents.data_agent import data_agent from ml.predict import load_model_and_encoders, predict_dataframe agent = DataAgent() result = agent.query("Will Verstappen win Monza 2023?") model, encoders = load_model_and_encoders(run_id="abc123") predictions = predict_dataframe(result["dataframe"], model, encoders) print(predictions[["driver_id", "driver_name", "win_probability"]]) ``` ### Batch Queries (future) ```python queries = [ "Verstappen Monaco 2023", "Hamilton Silverstone 2023", "Norris Spa 2023", ] for q in queries: result = data_agent(q) pred = predict_dataframe(result["dataframe"], model, encoders) print(f"{q}: {pred.iloc[0]['win_probability']:.2%}") ``` ### Testing with Mock Parser ```python from agents.data_agent import data_agent, QueryIntent def mock_parser(query: str) -> QueryIntent: return { "season": 2023, "round": 1, "driver_id": "VER", } result = data_agent("test query", parser=mock_parser) # Works without GROQ_API_KEY ``` ## Future Enhancements 1. **LangGraph Integration** — Multi-turn clarification ("Which Hamilton race?") 2. **Result Summarization** — "Max has 87% win probability at Monaco" 3. **Model Explanations** — Attach SHAP values to predictions 4. **Context Awareness** — Current standings, form, tire strategy 5. **Caching** — Avoid re-parsing identical queries ## Files - **Main:** [agents/data_agent.py](agents/data_agent.py) - **Tests:** [tests/test_data_agent.py](tests/test_data_agent.py) - **Upstream (Input Schema):** [data/fastf1_pipeline.py](data/fastf1_pipeline.py) - **Downstream (ML Pipeline):** [ml/feature_engineering.py](ml/feature_engineering.py), [ml/predict.py](ml/predict.py)