sql_env / specs /F003-VERIFICATION_INPUT.json
hjerpe's picture
Upload folder using huggingface_hub
5dd1bb4 verified
Raw
History Blame Contribute Delete
8.07 kB
{
"$schema": "autocode-verification-input-v1",
"feature_id": "F003",
"spec_path": "specs/F003-IMPLEMENTATION_SPEC.md",
"generated": "2026-03-27T12:00:00Z",
"verification_mode": "mvp",
"overview": {
"summary": "Dense 3-layer reward system for SQLEnv. Layer 1 provides operational signals (exec_ok, new_info, repeat penalty, step_cost). Layer 2 computes progress-to-target for QUERY actions using fixed weighted average of cardinality (0.25), value overlap (0.50), and numeric range proximity (0.25), binned to 5 levels with improvement-only gating. Layer 3 is the existing terminal correctness signal. Total step rewards clamped to [-0.2, +0.5].",
"goal": "Agents get meaningful per-step feedback during exploration so GRPO training converges. Random exploration yields ~0.1 cumulative reward, targeted queries ~0.3, correct answer ~1.3."
},
"interfaces": {
"types": [
{
"name": "EpisodeContext",
"fields": [
{"name": "gold_rows", "type": "list[tuple]", "optional": false, "description": "Gold SQL result rows cached at reset(), used by Layer 2 progress metrics"},
{"name": "query_hashes", "type": "set[str]", "optional": false, "description": "Set of hashes of previously executed SQL strings for repeat detection"},
{"name": "best_progress", "type": "float", "optional": false, "description": "Best binned progress score seen so far (improvement-only gating)"},
{"name": "cumulative_step_reward", "type": "float", "optional": false, "description": "Running total of step rewards for clamping to [-0.2, +0.5]"},
{"name": "cumulative_new_info_reward", "type": "float", "optional": false, "description": "Running total of new_info rewards for capping at 0.10"}
],
"description": "Per-episode server-side state extended with reward-tracking fields"
}
],
"functions": [
{
"name": "compute_step_reward",
"params": [
{"name": "ctx", "type": "EpisodeContext", "description": "Episode context (mutated: updates tracking fields)"},
{"name": "action_type", "type": "str", "description": "One of DESCRIBE, SAMPLE, QUERY"},
{"name": "sql", "type": "str", "description": "SQL string executed (for repeat detection)"},
{"name": "rows", "type": "list[tuple] | None", "description": "Result rows from query, or None if error"},
{"name": "error", "type": "str | None", "description": "Error message if action failed, else None"}
],
"returns": "float",
"description": "Main entry point. Combines Layer 1 + Layer 2 signals, clamps running total to [-0.2, +0.5]."
},
{
"name": "_layer1_operational",
"params": [
{"name": "ctx", "type": "EpisodeContext", "description": "Episode context"},
{"name": "action_type", "type": "str", "description": "Action type string"},
{"name": "sql", "type": "str", "description": "SQL string for repeat detection"},
{"name": "rows", "type": "list[tuple] | None", "description": "Result rows"},
{"name": "error", "type": "str | None", "description": "Error message if failed"}
],
"returns": "float",
"description": "Layer 1 operational signals: exec_ok(+0.02), new_info(+0.01 capped 0.10), repeat(-0.01), step_cost(-0.005)."
},
{
"name": "_layer2_progress",
"params": [
{"name": "ctx", "type": "EpisodeContext", "description": "Episode context with gold_rows"},
{"name": "rows", "type": "list[tuple]", "description": "Query result rows"}
],
"returns": "float",
"description": "Layer 2 progress-to-target for QUERY only. Weighted avg of sub-metrics, binned to 5 levels, improvement-only, scaled by 0.15."
},
{
"name": "_cardinality_score",
"params": [
{"name": "pred_rows", "type": "list[tuple]", "description": "Predicted result rows"},
{"name": "gold_rows", "type": "list[tuple]", "description": "Gold result rows"}
],
"returns": "float",
"description": "Row count similarity: 1 - |len(pred) - len(gold)| / max(len(pred), len(gold), 1). Returns [0.0, 1.0]."
},
{
"name": "_value_overlap_score",
"params": [
{"name": "pred_rows", "type": "list[tuple]", "description": "Predicted result rows"},
{"name": "gold_rows", "type": "list[tuple]", "description": "Gold result rows"}
],
"returns": "float",
"description": "Jaccard overlap of flattened cell values as strings. Returns [0.0, 1.0]."
},
{
"name": "_numeric_range_score",
"params": [
{"name": "pred_rows", "type": "list[tuple]", "description": "Predicted result rows"},
{"name": "gold_rows", "type": "list[tuple]", "description": "Gold result rows"}
],
"returns": "float",
"description": "Log-distance proximity for numeric cells. mean(1/(1+log(1+|pred-gold|))). Returns 1.0 if no numerics in gold. Returns [0.0, 1.0]."
},
{
"name": "_bin_progress",
"params": [
{"name": "raw_score", "type": "float", "description": "Raw progress score in [0.0, 1.0]"}
],
"returns": "float",
"description": "Bin to {0, 0.25, 0.5, 0.75, 1.0}. Thresholds at 0.125, 0.375, 0.625, 0.875."
}
],
"api_endpoints": []
},
"data_flow": {
"primary_flow": [
"step() receives SQLAction with action_type and argument",
"step() dispatches to handler (_handle_query, _handle_describe, _handle_sample)",
"For non-terminal actions, step() calls compute_step_reward(ctx, action_type, sql, rows, error)",
"compute_step_reward calls _layer1_operational for all action types",
"compute_step_reward calls _layer2_progress for QUERY actions only (when rows is not None and gold_rows is not empty)",
"_layer2_progress computes weighted average of _cardinality_score(0.25), _value_overlap_score(0.50), _numeric_range_score(0.25)",
"_layer2_progress bins result via _bin_progress, rewards only improvement over best_progress, scales by 0.15",
"compute_step_reward sums Layer 1 + Layer 2, clamps cumulative to [-0.2, +0.5], returns step reward"
],
"alternative_flows": [
{
"name": "SQL error on QUERY",
"trigger": "Query execution raises sqlite3.Error",
"steps": [
"step() catches error, sets error string",
"compute_step_reward called with error set and rows=None",
"Layer 1 returns step_cost only (-0.005)",
"Layer 2 skipped"
]
},
{
"name": "Empty gold_rows",
"trigger": "Gold SQL returned no rows at reset()",
"steps": [
"gold_rows stored as empty list in EpisodeContext",
"Layer 2 returns 0.0 (skipped)",
"Layer 1 operates normally"
]
},
{
"name": "Repeated query",
"trigger": "SQL hash already in ctx.query_hashes",
"steps": [
"Layer 1 applies repeat penalty (-0.01) in addition to step_cost",
"No exec_ok bonus for repeated query",
"Layer 2 still computes progress (may still show improvement)"
]
}
]
},
"error_handling": {
"error_types": [
{
"name": "SQL execution error",
"when": "Invalid query syntax or runtime SQL error during QUERY action",
"message_template": "Layer 1 returns step_cost only; Layer 2 skipped"
},
{
"name": "Empty gold rows",
"when": "Gold SQL returns no rows at episode reset",
"message_template": "Layer 2 returns 0.0; Layer 1 operates normally"
}
],
"retry_strategy": null
},
"dependencies": {
"external": [],
"internal": [
"models.py (EpisodeContext dataclass)",
"server/sql_environment.py (step() and reset() integration)",
"tests/test_smoke.py (existing tests need assertion updates)"
]
}
}