kronector / docs /AGENT_ARCHITECTURE.md
Prathamesh Bhamare
Initial commit: KRONECTOR MLOps & Multi-Agent AI system
2532605
|
Raw
History Blame Contribute Delete
6.18 kB
# 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)