lexsi-ds-agent / docs /dab_failure_analysis.md
bp-lexsi's picture
Add new tools and dab runs
4131399
|
Raw
History Blame Contribute Delete
9.89 kB

A newer version of the Gradio SDK is available: 6.22.0

Upgrade

DataAgentBench failure analysis β€” runs of 2026-06-05

Trajectory analysis of full --all sweeps, scored with DAB's own per-task validate.py. Captured with --log-dir (full per-turn prompts, raw LLM responses, tool args, and untruncated results); diagnoses below cite those traces.

Run config

python -m benchmark.dab.runner --all --llm lexsi --log-dir artifacts/dab_runs/new_tool
  • 5 of 17 datasets runnable (sqlite/duckdb); 12 skipped (postgres/mongo).
  • Score: 10/17 tasks passed β€” consolidate_tables (fix B) recovered stockmarket/query4 + query5 over the pre-tool baseline of 8/17 (both confirmed using the tool; see Β§B).

Measurement note. Single-run pass@1 carries per-task sampling noise β€” any system-prompt change re-rolls multi-step trajectories, so a few tasks can flip run-to-run. Use --iterations 3 (majority vote) to pin a stable number before trusting a future delta.

Results

βœ… = pass, ❌ = fail, 🎯 = recovered by consolidate_tables.

Dataset Query Result Validator reason / note
DEPS_DEV_V1 query1 ❌ Missing name @dmrvos/infrajs>0.0.6>typescript (§C/§D)
DEPS_DEV_V1 query2 ❌ Missing project mui-org/material-ui (§D)
GITHUB_REPOS query1 ❌ No value rounds to 0.33 β€” wrong join (Β§A note)
GITHUB_REPOS query2 βœ… Fuzzy matched swiftandroid/swift
GITHUB_REPOS query3 βœ… Found 1077
GITHUB_REPOS query4 βœ… All repo names matched
music_brainz_20k query1 βœ… Ground truth found
music_brainz_20k query2 βœ… Ground truth found
music_brainz_20k query3 ❌ Wrong song (Zo gaat het leven…) (Β§D)
stockindex query1 βœ… 399001.SZ primary
stockindex query2 ❌ IXIC not in first 200 chars (§C)
stockindex query3 βœ… All name-country pairs matched
stockmarket query1 βœ… 18.44 β‰ˆ 18.44
stockmarket query2 ❌ Missing number 31 β€” consolidated, but count SQL still wrong (Β§B)
stockmarket query3 ❌ Apex Global Brands Inc β€” consolidated, but avg-volume SQL still wrong (Β§B)
stockmarket query4 πŸŽ―βœ… MFA Financial, Inc found β€” recovered via consolidate_tables
stockmarket query5 πŸŽ―βœ… Synthesis Energy Systems, Inc found β€” recovered via consolidate_tables

Total: 10/17 β€” 8 baseline passers + 2 🎯 recoveries via consolidate_tables.


Failure taxonomy

A. Harness bug β€” history truncates tool-call args, agent thinks its SQL is broken (1 task, systemic)

GITHUB_REPOS/query1. The agent wrote a complete 960-char query and run_sql executed it fine (returned 1 row Γ— 3 cols). But the loop echoes each tool call into the observation history truncated to 400 chars (loop.py:236):

f"TOOL CALL: {tool_name}({json.dumps(args_obj, default=str)[:400]})\n"

The 400-char cut lands mid-JOIN, and the appended ) makes the echo read as a query that ends …JOIN artifacts_database_contents c ON c) β€” i.e. truncated mid-join. The agent re-read this, concluded the tooling was broken, re-ran the same query 10 times, and gave up:

"every run_sql execution shown is truncated mid-join (JOIN artifacts_database_contents c ON c)), which causes the query to effectively fail" β€” agent's final answer

So a runnable task was lost to a display artifact, not a real error. (The SQL logic was also likely wrong β€” proportion β‰  0.33 β€” but the agent never got far enough to find out.)

Fix (done). loop.py now echoes args via _echo_args(): full up to an 8000-char cap, and when it must truncate it appends an explicit … [+N chars truncated for display only; the full args above were executed] marker β€” so a display cut can never read as a broken statement. The 960-char query that triggered this is now echoed in full.

B. Scale β€” per-shard table explosion vs the 12-step budget (4 tasks) β€” FIXED via consolidate_tables

The problem. stockmarket materializes 2753 stocktrade_database_<ticker> tables (one per symbol, identical schema Date,Open,High,Low,Close, Adj Close,Volume, ~410 rows each) plus one stockinfo table. The shard key (ticker) lives in the table name, not a column. A question like "across all NYSE stocks…" is a GROUP BY ticker that can only be expressed as a 2753-way UNION ALL β€” unwriteable in a 12-step budget. All four tasks hit step 13 and surrendered:

"the query requires scanning/UNIONing thousands of stocktrade_database_<ticker> tables, and I ran out of allowed tool calls" β€” query3, baseline

The fix (done): a generic consolidate_tables tool (consolidate_tables.py). It folds a sharded family into one table in a single call β€” the giant UNION ALL BY NAME is generated in our code, never against the agent's step budget:

{"tool": "consolidate_tables",
 "args": {"pattern": "stocktrade_database_*", "into": "stocktrade", "key_column": "ticker"}}

It auto-derives the key from the pattern's literal prefix (β†’ bare tickers), schema-guards (unions only same-schema shards, reports the rest), and defaults to a cheap VIEW. Generic by design: per-ticker, per-day, per-region β€” any BYO datalake with sharded tables. Planner rule 14 tells the agent to reach for it when inspect_data shows many same-prefix tables.

Measured: 2753 tables β†’ one 6.47M-row view in 1.2s; the previously-timed-out cross-ticker query runs in ~1s. On the new_tool/ sweep the agent called it in all 4 stockmarket tasks and recovered query4 + query5 (the name-lookup tasks). query2 (count off by the "31") and query3 (avg-volume per company) still fail: the tool removes the structural blocker, but the agent must still write correct analytical SQL on top β€” which it nailed for q4/q5 and missed for q2/q3 (the latter compounded by Β§E coded values).

C. Output format / "primary answer" expectations (2 tasks)

  • stockindex/query2 β€” the answer was correct (IXIC: 44 up / 31 down) but the validator requires the target index in the first 200 chars as the primary answer; the agent buried it after a prose preamble and a markdown table, and added a second index (GSPTSE). Penalized on presentation, not correctness.
  • DEPS_DEV_V1/query1 β€” the agent's query did surface the composite-key rows (@dmrvos/infrajs>0.0.5>typescript) but (a) chose version 0.0.5, not the ground-truth 0.0.6 ("latest release" logic wrong β€” see Β§D), and (b) hedged/refused because the values "look like dependency paths rather than just the package name".

Fix: a benchmark-mode answer directive β€” lead with the bare answer/identifier in the exact requested format, then optional detail.

D. Wrong query semantics β†’ confidently wrong values (2 tasks)

  • DEPS_DEV_V1/query2 β€” returned react-component/picker, tailwindcss/typography, …; ground truth is mui-org/material-ui. The "marked as release" filter
    • fork-count join produced a different top-5.
  • music_brainz_20k/query3 β€” answered "Groovey" by Rich Matteson, $4,128.59 in a single run_sql; ground truth is "Zo gaat het leven aan je voor". Revenue was almost certainly aggregated by the wrong entity (track title vs. recording, or not summed across stores). The agent was overconfident β€” 4 steps, one query, no cross-check.

Fix: these need the DAB db_description field-semantics to be weighted more (e.g. how "latest release" / "revenue" are defined), and a self-check step before finalizing on aggregation questions.

E. Coded-value / data-semantics gaps (compounds B)

stockmarket/query5, query3 β€” the agent filtered on Listing Exchange='Q' AND Market Category='QCM', got 0 rows, and concluded the data didn't match. Listing Exchange/Market Category/ Financial Status are coded columns whose codes differ from the agent's assumptions. It spent steps probing codes instead of answering, which (with Β§B) guaranteed a timeout.


Priorities

Fix Status Impact
A. _echo_args() no longer cuts SQL mid-string βœ… done Removes false "truncated SQL" failures; helps any long-SQL task
B. consolidate_tables folds sharded families into one table βœ… done +2 (stockmarket q4, q5); generic for any sharded datalake
D/E. Lean on db_description semantics + a pre-final self-check open DEPS/query2, music_brainz/query3, stockmarket q2/q3 SQL logic
C. Benchmark answer-format directive (lead with bare answer) open stockindex/query2 (+ partial DEPS/query1)

Net effect of A + B: 10/17. A is a correctness floor (no more false failures); B is the +2 (stockmarket q4, q5). The remaining levers are D/E (analytical-SQL / coded-value semantics β€” the dominant failure mode now that the structural blockers are gone) and C (output format).

Measure with --iterations. Single-run pass@1 is noisy β€” a prompt change re-rolls every multi-step task. Run --iterations 3 (majority vote) before trusting a future delta.

Reproduce / inspect

# Noise-adjusted measurement run (majority vote per task):
python -m benchmark.dab.runner --all --llm lexsi --iterations 3 \
    --log-dir artifacts/dab_runs/measure_v1

# Inspect one trajectory end-to-end (prompts, raw responses, SQL, payloads):
python -c "import json; d=json.load(open('artifacts/dab_runs/new_tool/stockmarket_query4_iter0.json')); \
print(d['reason']); [print(s['n'], s['tool'], (s['args'] or {}).get('sql','')[:80]) for s in d['run']['steps']]"

# Confirm the new tool fired on the stockmarket tasks:
grep -l consolidate_tables artifacts/dab_runs/new_tool/stockmarket_*.json