Spaces:
Running
Running
File size: 7,276 Bytes
d3d0e0e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 | # Baseline ReAct Agent Architecture Summary
## Execution Flow
### 1. CLI Entry Points
**Located in:** `src/data_agent_baseline/cli.py`
Two main commands:
- `dabench run-task <task_id>` - Execute single task
- `dabench run-benchmark` - Execute multiple tasks (with parallelization)
### 2. Runner Layer
**Located in:** `src/data_agent_baseline/run/runner.py`
**Key functions:**
- `run_single_task()` - Orchestrates single task execution
- `run_benchmark()` - Orchestrates benchmark execution with optional parallelization
- `_run_single_task_with_timeout()` - Subprocess-based timeout handling
- `_write_task_outputs()` - Generates artifacts
**Execution flow:**
1. Load task from DABenchPublicDataset
2. Initialize ReActAgent with model adapter and tool registry
3. Run agent (with optional timeout in subprocess)
4. Write outputs to disk
### 3. Agent Layer
**Located in:** `src/data_agent_baseline/agents/react.py`
**ReActAgent class:**
- Implements classic ReAct loop (Thought → Action → Observation)
- Maximum steps configurable (default 16)
- Uses ModelAdapter for LLM calls
- Uses ToolRegistry for tool execution
**Core method:** `run(task: PublicTask) -> AgentRunResult`
**Loop structure:**
```
for step in range(max_steps):
1. Build message history (system + task + previous steps)
2. Call LLM to get next step
3. Parse JSON response (thought, action, action_input)
4. Execute tool via ToolRegistry
5. Record observation
6. Check if terminal (answer submitted)
7. Break if answer submitted
```
### 4. Runtime State Management
**Located in:** `src/data_agent_baseline/agents/runtime.py`
**Data structures:**
- `StepRecord` - Single step (thought, action, action_input, observation, ok)
- `AgentRuntimeState` - Mutable state during execution
- `AgentRunResult` - Final immutable result
### 5. Artifact Generation
**Outputs per task:**
```
<run_output_dir>/<task_id>/
├── trace.json # Full execution trace
└── prediction.csv # Final answer (if submitted)
```
## Baseline Trace Structure
### Baseline trace.json Format
```json
{
"task_id": "task_22",
"answer": {
"columns": ["col1", "col2"],
"rows": [["val1", "val2"], ...]
},
"steps": [
{
"step_index": 1,
"thought": "I need to...",
"action": "read_csv",
"action_input": {"path": "...", "max_rows": 10},
"raw_response": "```json\n{...}\n```",
"observation": {
"ok": true,
"tool": "read_csv",
"content": {...}
},
"ok": true
}
],
"failure_reason": null,
"succeeded": true,
"e2e_elapsed_seconds": 8.528
}
```
**Key characteristics:**
- **Simple structure:** No phases, no per-step timing
- **No metadata:** Missing difficulty, question text, context info
- **Minimal metrics:** Only e2e_elapsed_seconds, no token counts
- **No recovery tracking:** No retry/replan information
- **No confidence scores:** No self-assessment
### Current Evaluation Harness Expectations
**Located in:** `src/data_agent_baseline/langgraph_agent/eval_v2.py`
The newer LangGraph agent produces traces with extensive metadata:
```json
{
"task_id": "task_22",
"difficulty": "easy",
"trace_id": "/path/to/trace",
"answer": {...},
"steps": [
{
"step_index": 1,
"thought": "...",
"action": "read_csv",
"action_input": {...},
"raw_response": "...",
"observation": {...},
"ok": true,
"phase": "explore", // ← Baseline missing
"duration_seconds": 0.01, // ← Baseline missing
"token_usage": { // ← Baseline missing
"prompt_tokens": 100,
"completion_tokens": 50,
"total_tokens": 150
}
}
],
"comprehensive_metrics": { // ← Baseline missing
"execution_success": 1,
"execution_time": 8.5,
"tool_calls": 5,
"tool_failures": 0,
"llm_calls": 5,
"total_tokens": 27000,
"stage_metrics": {...},
"action_counts": {...},
"per_action_metrics": {...},
"confidence_score": 0.9,
...
},
"failure_reason": null,
"succeeded": true,
"e2e_elapsed_seconds": 8.528
}
```
## Gap Analysis
### Missing in Baseline Traces
| Feature | Baseline | Evaluation Harness | Impact |
|---------|----------|-------------------|--------|
| **Phase tracking** | ❌ | ✅ (explore, planner, execute, critic) | Cannot compute phase-specific metrics |
| **Per-step timing** | ❌ | ✅ duration_seconds | Cannot compute per-phase time |
| **Token usage** | ❌ | ✅ Per-step and total | Cannot compute cost metrics |
| **Comprehensive metrics** | ❌ | ✅ Full metadata object | Must compute from steps |
| **Stage metrics** | ❌ | ✅ Per-stage breakdown | Cannot compute stage efficiency |
| **Action counts** | ❌ | ✅ Tool usage frequency | Must derive from steps |
| **Confidence scores** | ❌ | ✅ Self-assessment | Cannot evaluate calibration |
| **Recovery tracking** | ❌ | ✅ Replan/retry counts | Cannot measure autonomy |
| **Task metadata** | Partial | ✅ difficulty, question | Need to fetch from task.json |
| **Trace ID** | ❌ | ✅ Full path | Must construct |
### Available in Baseline Traces
✅ **Core execution data:**
- task_id
- answer (columns, rows)
- steps (thought, action, action_input, observation, ok)
- succeeded flag
- failure_reason (if any)
- e2e_elapsed_seconds
✅ **Derivable metrics:**
- Tool call counts (from steps)
- Tool failure counts (from step.ok)
- Tool diversity (from unique actions)
- Trajectory length (from len(steps))
- Tool efficiency (failures / total calls)
- Action counts (frequency analysis)
## Evaluation Strategy
### Phase 1: Adapter-Based Approach
**Do NOT modify baseline execution code.**
Instead:
1. Create adapter layer to normalize baseline traces
2. Infer missing metadata where possible
3. Compute metrics from available data
4. Mark unavailable metrics as NULL
5. Generate comparable evaluation reports
### Adapter Responsibilities
```python
class BaselineTraceAdapter:
def load_trace(trace_path: Path) -> dict
def enrich_with_task_metadata(trace: dict, task_root: Path) -> dict
def compute_derivable_metrics(trace: dict) -> dict
def normalize_to_canonical_schema(trace: dict) -> CanonicalTrace
def export_for_evaluation(trace: CanonicalTrace) -> dict
```
### Metrics Coverage
**Phase 1 Metrics (Baseline-Compatible):**
✅ **Accuracy metrics:**
- Overall accuracy (from gold comparison)
- Per-difficulty accuracy
- Answer precision/recall/F1
✅ **Efficiency metrics:**
- Average steps per task
- Average runtime
- Tool calls per task
✅ **Reliability metrics:**
- Success rate
- Tool error rate
- Timeout rate (if configured)
✅ **Tool usage metrics:**
- Tool diversity
- Tool efficiency
- Most common tools
❌ **Not available for baseline:**
- Token costs (no token tracking)
- Phase-specific timing (no phase labels)
- Confidence calibration (no confidence scores)
- Recovery metrics (no replan tracking)
- Stage efficiency (no stage breakdown)
### Future Compatibility
Design ensures:
- Baseline and LangGraph traces can coexist
- Same evaluation pipeline for both
- Clear indication of unavailable metrics
- Easy addition of new agent types
- Scientific comparison across systems
|