Skip to content

Commit 44c7cdf

Browse files
committed
tools: add exact qid retry targeting
1 parent ccb05a8 commit 44c7cdf

14 files changed

Lines changed: 762 additions & 28 deletions

docs/NEXT_SESSION.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,24 @@
2929
- `llama3.1:8b` smoke: `NL_SQL_OLLAMA_GEN_MODEL=llama3.1:8b NL_SQL_OLLAMA_TIMEOUT_SECONDS=45 uv run python scripts/eval_baseline.py --provider ollama --config C --n 5 --seed 0 --report-suffix ollama-llama31-smoke5`**0/5**, all `Request timed out`, P50 latency ~47s. Artifact: `eval/reports/2026-05-22/C_dense_cards-ollama-llama31-smoke5.json`; audit 0 mismatches.
3030
- `qwen2.5-coder:7b-instruct` pull attempted, but blocked by network/TLS (`max retries exceeded`, Cloudflare R2 TLS handshake timeout) after ~6 min and only ~569KB/4.7GB. Local heterogeneous CSC is blocked until the coding model is installed or the machine has a faster local runtime.
3131

32-
**Voting tooling fix (same day):**
32+
**Voting/tooling fix (same day + continuation):**
3333
- `scripts/run_helallao_voting.py` and `scripts/run_openrouter_voting.py` now persist pipeline exceptions as JSON records with `alt_error` and `summary.errored` instead of only printing stderr. Regression coverage: `tests/scripts/test_run_helallao_voting.py` and `tests/scripts/test_run_openrouter_voting.py`. This makes the next qid 1399 or OpenRouter paid-top-up diagnostic run auditable, but it is not a tokenizer workaround by itself.
34+
- Retry/eval CLIs now support exact qid targeting via `--only-qids`: `scripts/eval_baseline.py`, `run_critique_retry.py`, `run_groq_voting.py`, `run_helallao_voting.py`, `run_openrouter_voting.py`, `run_selfcon_retry.py`, `run_sonnet_voting.py`, and `run_wide_schema_retry.py`. Use this before any expensive residue-wide run, e.g. `--only-qids 1399` for tokenizer diagnostics or `--only-qids 207,1404` for P3.F join-path probes. Test coverage: `tests/scripts/test_retry_only_qids_cli.py` plus targeted helallao/openrouter/eval tests.
35+
- P3.F v20 recheck: `207` and `1404` remain FAIL in `v20-kimi-k2-thinking-merged.json`; old partial targets `77` and `990` are no longer clean P3.F work items in v20. Treat `207` carefully: the natural FK-looking path `bond.bond_id = connected.bond_id` is exactly what current predictions choose, while BIRD gold instead uses `connected.atom_id`; a stronger generic FK linker can make this worse. `1404` is the cleaner column-source/GROUP BY target (`event.type` vs `expense.expense_description/type`).
36+
- Gate before commit: `uv run pytest -q` → 309 passed; `uv run ruff check src tests scripts app` clean; `uv run mypy --strict src` clean; `git diff --check` clean. Touched text files verified LF-only.
3437

3538
**Open path past 87.5% (приоритет):**
3639
1. **Paid OpenRouter top-up** ($5+) — unlocks batch eval через heterogeneous `:free`/paid routed models, wiring уже готов.
3740
2. **Local ollama heterogeneous CSC** — blocked until `qwen2.5-coder:7b-instruct` is actually installed; existing local `llama3.1:8b` times out on schema-heavy prompts.
38-
3. **P3.F JOIN-path linker** (`docs/p3f_design.md`) — единственный remaining non-quota engineering path, multi-day.
41+
3. **P3.F JOIN-path linker** (`docs/p3f_design.md`) — единственный remaining non-quota engineering path, multi-day; do not build a generic FK booster without a qid-level acceptance harness for `207/1404`.
3942
4. **GraceKelly maintenance** — re-run `D:/GraceKelly/tools/capture_perplexity_recon.py` + update selectors only if Chrome profile is confirmed free.
4043

44+
**Next tactical plan:**
45+
1. If continuing P3.F, start with a qid-level acceptance harness for `1404` and `207`, not a broad linker.
46+
2. Treat `1404` as the first implementation target; it is a cleaner column-source/GROUP BY failure.
47+
3. Defer `207` until the harness can catch FK-overconfidence regressions, because BIRD gold disagrees with the natural `bond_id` path.
48+
4. Do not run qid `1399` through helallao again until there is a real tokenizer workaround or a diagnostic patch that preserves the exception payload.
49+
4150
**Что НЕ делать:**
4251
- Не повторять plain `kimi-k2-thinking` на v19/v20 residue — v20 уже взял единственный rescue qid 584; остальное same.
4352
- Не повторять plain `grok-4.1-reasoning` на v20 residue — 0 rescues, clean saturation.
@@ -198,6 +207,12 @@ uv run python scripts/run_helallao_voting.py \
198207
--baseline eval/reports/2026-05-18b/v18-gpt52-pro-merged.json \
199208
--out eval/reports/<date>/helallao-gpt52-pro-on-v18-residue.json \
200209
--model gpt-5.2 --sleep-between 4.0
210+
211+
# Точечный diagnostic без полного residue (только после tokenizer workaround):
212+
uv run python scripts/run_helallao_voting.py \
213+
--baseline eval/reports/2026-05-22/v20-kimi-k2-thinking-merged.json \
214+
--out eval/reports/<date>/helallao-qid1399.json \
215+
--model grok-4.1-reasoning --only-qids 1399
201216
```
202217

203218
## Cookies refresh (если helallao падает с auth error)

docs/SESSION_HANDOFF.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111
> - **Post-v20 baseline ablation:** `a62f844` appends compact FK-derived `# Join hints` to the schema block. `uv run python scripts/eval_baseline.py --config C --n 200 --seed 0 --report-suffix fkjoinhints`**56.5% EA** (113/200), vs P2+P3 baseline 56.0% (112/200): 6 wins / 5 regressions, audit 0 mismatches. Target FK/JOIN residue qids 207/584/902/959/1275 stayed FAIL, so this is small baseline hygiene, **not v21/headline**.
1212
> - **Tooling fix from that eval:** `scripts/audit_rescore.py` now treats empty `pred_sql` as no prediction instead of a possible empty-result PASS; `scripts/eval_baseline.py` now skips incompatible prior JSON when rebuilding `index.html`.
1313
> - **Local Ollama probe:** added `NL_SQL_OLLAMA_TIMEOUT_SECONDS` + `max_retries=0` for fail-fast local timeouts. Existing local models are `llama3.1:8b`, `gemma3:4b`, `qwen3:4b`; default `qwen2.5-coder:7b-instruct` is not installed. `llama3.1:8b` config-C smoke5 with 45s timeout → **0/5**, all request timeouts, audit 0 mismatches (`eval/reports/2026-05-22/C_dense_cards-ollama-llama31-smoke5.json`). `ollama pull qwen2.5-coder:7b-instruct` blocked on Cloudflare R2 TLS handshake timeout after ~6 min and ~569KB/4.7GB. Local heterogeneous CSC remains blocked until the coding model is installed or runtime moves to a faster machine.
14-
> - **Voting artifact fix:** `scripts/run_helallao_voting.py` and `scripts/run_openrouter_voting.py` now write pipeline exceptions into voting JSON as records with `alt_error` plus `summary.errored` instead of losing them to stderr-only output. Test coverage: `tests/scripts/test_run_helallao_voting.py` and `tests/scripts/test_run_openrouter_voting.py`. This enables auditable qid 1399 and OpenRouter paid-top-up diagnostics, but it is not the tokenizer workaround.
14+
> - **Voting/tooling artifact fix:** `scripts/run_helallao_voting.py` and `scripts/run_openrouter_voting.py` now write pipeline exceptions into voting JSON as records with `alt_error` plus `summary.errored` instead of losing them to stderr-only output. Test coverage: `tests/scripts/test_run_helallao_voting.py` and `tests/scripts/test_run_openrouter_voting.py`. This enables auditable qid 1399 and OpenRouter paid-top-up diagnostics, but it is not the tokenizer workaround.
15+
> - **Continuation tooling:** exact qid targeting is now available across retry/eval CLIs via `--only-qids`: `scripts/eval_baseline.py`, `run_critique_retry.py`, `run_groq_voting.py`, `run_helallao_voting.py`, `run_openrouter_voting.py`, `run_selfcon_retry.py`, `run_sonnet_voting.py`, and `run_wide_schema_retry.py`. Use it before any expensive residue-wide run, especially qid 1399 tokenizer diagnostics and P3.F join-path probes (207/1404). Coverage: `tests/scripts/test_retry_only_qids_cli.py` plus targeted eval/helallao/openrouter tests.
16+
> - **P3.F v20 recheck:** qids 207 and 1404 still fail in `v20-kimi-k2-thinking-merged.json`; old partial P3.F targets 77 and 990 are no longer clean v20 targets. qid 207 is dangerous for a generic FK-linker because the natural FK-looking path (`connected.bond_id`) is the wrong one under BIRD gold; qid 1404 is the cleaner column-source/GROUP BY target (`event.type`, not expense description/type).
17+
> - **Gate before commit:** `uv run pytest -q` → 309 passed; `uv run ruff check src tests scripts app` clean; `uv run mypy --strict src` clean; `git diff --check` clean. Touched text files verified LF-only. Next tactical plan: build a qid-level `207/1404` acceptance harness before any P3.F implementation; start with `1404`, defer `207` until FK-overconfidence is guarded.
1518
>
1619
> Артефакты v20: `eval/reports/2026-05-22/{helallao-kimi-k2-thinking-on-v19-residue.json, v20-kimi-k2-thinking-merged.json, helallao-grok41-reasoning-on-v20-residue.json, helallao-claude45-thinking-on-v20-residue.json}`. Headline updates: README/UI 87.0→87.5, 174→175, +5.05→+5.55pp over AskData, +39.2→+39.7pp over GPT-4 zero-shot, moderate 83.8→84.8. HF Space redeploy still gated to user.
1720
>

scripts/eval_baseline.py

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
uv run python scripts/eval_baseline.py --config A --n 50 --seed 0
1010
uv run python scripts/eval_baseline.py --config C --n 50 --seed 0
1111
uv run python scripts/eval_baseline.py --n 5 --db bird_california_schools
12+
uv run python scripts/eval_baseline.py --config C --only-qids 1399,1205
1213
"""
1314

1415
from __future__ import annotations
@@ -68,6 +69,14 @@ def main(argv: list[str] | None = None) -> int:
6869
"docs/SESSION_HANDOFF.md for the hybrid recipe)."
6970
),
7071
)
72+
parser.add_argument(
73+
"--only-qids",
74+
default="",
75+
help=(
76+
"comma-separated BIRD question IDs to run exactly, preserving "
77+
"argument order and bypassing --n/--seed sampling"
78+
),
79+
)
7180
parser.add_argument(
7281
"--bird-root",
7382
default=str(DEFAULT_BIRD_ROOT),
@@ -200,20 +209,27 @@ def main(argv: list[str] | None = None) -> int:
200209
)
201210
args = parser.parse_args(argv)
202211

203-
settings = get_settings()
204-
if not settings.mistral_api_key:
205-
print("[error] MISTRAL_API_KEY not set in .env", file=sys.stderr)
206-
return 2
207-
208-
registry = get_default_registry()
209212
examples = load_bird_mini_dev(Path(args.bird_root))
210213
if args.db:
211214
examples = [e for e in examples if e.registry_db_id == args.db]
212215
if not examples:
213216
print(f"[error] no examples for db {args.db!r}", file=sys.stderr)
214217
return 3
215218

216-
sample = dev_split(examples, n=args.n, seed=args.seed)
219+
try:
220+
only_qids = [int(x) for x in args.only_qids.split(",") if x.strip()]
221+
except ValueError:
222+
print("[error] invalid --only-qids: expected comma-separated integers", file=sys.stderr)
223+
return 3
224+
if only_qids:
225+
examples_by_qid = {e.question_id: e for e in examples}
226+
sample = [examples_by_qid[qid] for qid in only_qids if qid in examples_by_qid]
227+
missing_qids = [qid for qid in only_qids if qid not in examples_by_qid]
228+
if missing_qids:
229+
print(f"[error] qids not found after filters: {missing_qids}", file=sys.stderr)
230+
return 3
231+
else:
232+
sample = dev_split(examples, n=args.n, seed=args.seed)
217233
if args.difficulty:
218234
# Apply AFTER dev_split so the same shuffle-prefix examples appear
219235
# as in unfiltered runs — needed for hybrid merging (e.g., F on
@@ -227,6 +243,8 @@ def main(argv: list[str] | None = None) -> int:
227243
)
228244
return 3
229245
print(f"[info] loaded {len(examples)} examples → sampled {len(sample)} (seed={args.seed})")
246+
247+
registry = get_default_registry()
230248
missing = sorted({e.registry_db_id for e in sample} - set(registry.ids()))
231249
if missing:
232250
print(
@@ -236,6 +254,11 @@ def main(argv: list[str] | None = None) -> int:
236254
)
237255
return 4
238256

257+
settings = get_settings()
258+
if not settings.mistral_api_key:
259+
print("[error] MISTRAL_API_KEY not set in .env", file=sys.stderr)
260+
return 2
261+
239262
raw_sql_provider = build_provider(args.provider, settings=settings)
240263
print(f"[info] provider: {args.provider} (model={raw_sql_provider.model})")
241264
sql_provider: LLMProvider

scripts/run_critique_retry.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
--baseline eval/reports/2026-05-13/hybrid+multi-vote-v3.json \
1515
--bird-root data/bird_mini_dev/MINIDEV \
1616
--out eval/reports/2026-05-13/critique-retry.json
17+
uv run python scripts/run_critique_retry.py \
18+
--baseline eval/reports/2026-05-22/v20-kimi-k2-thinking-merged.json \
19+
--out eval/reports/2026-05-22/critique-qid1399.json --only-qids 1399
1720
"""
1821

1922
from __future__ import annotations
@@ -42,6 +45,11 @@ def main() -> int:
4245
p.add_argument("--bird-root", type=Path, default=Path("data/bird_mini_dev/MINIDEV"))
4346
p.add_argument("--out", type=Path, required=True)
4447
p.add_argument("--max-cases", type=int, default=200)
48+
p.add_argument(
49+
"--only-qids",
50+
default="",
51+
help="comma-separated baseline failure qids to retry exactly, preserving argument order",
52+
)
4553
p.add_argument(
4654
"--fewshot-top-k",
4755
type=int,
@@ -90,12 +98,24 @@ def main() -> int:
9098
)
9199
args = p.parse_args()
92100

93-
settings = get_settings()
94101
baseline = json.loads(args.baseline.read_text(encoding="utf-8"))
95102
fails = [r for r in baseline["records"] if not r.get("match")]
103+
try:
104+
only_qids = [int(x) for x in args.only_qids.split(",") if x.strip()]
105+
except ValueError:
106+
print("[error] invalid --only-qids: expected comma-separated integers", file=sys.stderr)
107+
return 3
108+
if only_qids:
109+
fails_by_qid = {int(r["question_id"]): r for r in fails}
110+
missing_qids = [qid for qid in only_qids if qid not in fails_by_qid]
111+
if missing_qids:
112+
print(f"[error] qids not found in baseline failures: {missing_qids}", file=sys.stderr)
113+
return 3
114+
fails = [fails_by_qid[qid] for qid in only_qids]
96115
fails = fails[: args.max_cases]
97116
print(f"[info] {len(fails)} failures to retry with grounded_critique", file=sys.stderr)
98117

118+
settings = get_settings()
99119
examples = {e.question_id: e for e in load_bird_mini_dev(args.bird_root)}
100120
registry = get_default_registry()
101121

scripts/run_groq_voting.py

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
--provider-model qwen/qwen3-32b \
1717
--max-cases 20 \
1818
--out eval/reports/2026-05-12/qwen3-voting.json
19+
uv run python scripts/run_groq_voting.py \
20+
--baseline eval/reports/2026-05-22/v20-kimi-k2-thinking-merged.json \
21+
--provider-model openai/gpt-oss-120b \
22+
--out eval/reports/2026-05-22/groq-qid1399.json --only-qids 1399
1923
"""
2024

2125
from __future__ import annotations
@@ -95,26 +99,46 @@ def main() -> int:
9599
default="",
96100
help="comma-separated qids to skip (already covered by prior runs)",
97101
)
102+
p.add_argument(
103+
"--only-qids",
104+
default="",
105+
help="comma-separated baseline failure qids to retry exactly, preserving argument order",
106+
)
98107
p.add_argument("--bird-root", default="data/bird_mini_dev/MINIDEV")
99108
p.add_argument("--out", type=Path, required=True)
100109
args = p.parse_args()
101110

102-
settings = get_settings()
103-
examples = {e.question_id: e for e in load_bird_mini_dev(Path(args.bird_root))}
104111
baseline = json.loads(args.baseline.read_text(encoding="utf-8"))["records"]
105112

106113
# Pick failing cases of the requested bucket (optionally filter difficulty).
107114
bucket_fn = _BUCKETS[args.bucket]
108115
skip = {int(x) for x in args.skip_qids.split(",") if x.strip()}
109-
candidates = [r for r in baseline if bucket_fn(r) and r["question_id"] not in skip]
110-
if args.difficulty:
111-
candidates = [r for r in candidates if r["difficulty"] == args.difficulty]
116+
try:
117+
only_qids = [int(x) for x in args.only_qids.split(",") if x.strip()]
118+
except ValueError:
119+
print("[error] invalid --only-qids: expected comma-separated integers", file=sys.stderr)
120+
return 3
121+
if only_qids:
122+
failures_by_qid = {int(r["question_id"]): r for r in baseline if not r.get("match")}
123+
missing_qids = [qid for qid in only_qids if qid not in failures_by_qid]
124+
if missing_qids:
125+
print(f"[error] qids not found in baseline failures: {missing_qids}", file=sys.stderr)
126+
return 3
127+
candidates = [failures_by_qid[qid] for qid in only_qids if qid not in skip]
128+
else:
129+
candidates = [r for r in baseline if bucket_fn(r) and r["question_id"] not in skip]
130+
if args.difficulty:
131+
candidates = [r for r in candidates if r["difficulty"] == args.difficulty]
112132
candidates = candidates[: args.max_cases]
113133
print(
114134
f"[info] picked {len(candidates)} {args.bucket} cases (skipped {len(skip)} qids)",
115135
file=sys.stderr,
116136
)
137+
if not candidates:
138+
return 0
117139

140+
settings = get_settings()
141+
examples = {e.question_id: e for e in load_bird_mini_dev(Path(args.bird_root))}
118142
# Pipeline with the Groq alt model. We override the codestral-cached
119143
# provider with a fresh Groq client at the chosen model id.
120144
raw_groq = OpenAI(api_key=settings.groq_api_key, base_url=settings.groq_base_url)

scripts/run_helallao_voting.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
--baseline eval/reports/.../v11.json \\
1212
--out eval/reports/.../helallao-grok-voting.json \\
1313
--model grok-4.1
14+
uv run python scripts/run_helallao_voting.py \\
15+
--baseline eval/reports/.../v20.json \\
16+
--out eval/reports/.../helallao-qid1399.json \\
17+
--model grok-4.1-reasoning --only-qids 1399
1418
"""
1519

1620
from __future__ import annotations
@@ -42,6 +46,11 @@ def main() -> int:
4246
p.add_argument("--out", type=Path, required=True)
4347
p.add_argument("--max-cases", type=int, default=200)
4448
p.add_argument("--skip-qids", default="")
49+
p.add_argument(
50+
"--only-qids",
51+
default="",
52+
help="comma-separated baseline failure qids to retry exactly, preserving argument order",
53+
)
4554
p.add_argument("--model", default="grok-4.1")
4655
p.add_argument(
4756
"--cookies",
@@ -57,13 +66,27 @@ def main() -> int:
5766
)
5867
args = p.parse_args()
5968

60-
settings = get_settings()
6169
baseline = json.loads(args.baseline.read_text(encoding="utf-8"))
6270
fails = [r for r in baseline["records"] if not r.get("match")]
71+
try:
72+
only_qids = [int(x) for x in args.only_qids.split(",") if x.strip()]
73+
except ValueError:
74+
print("[error] invalid --only-qids: expected comma-separated integers", file=sys.stderr)
75+
return 3
76+
if only_qids:
77+
fails_by_qid = {int(r["question_id"]): r for r in fails}
78+
missing_qids = [qid for qid in only_qids if qid not in fails_by_qid]
79+
if missing_qids:
80+
print(f"[error] qids not found in baseline failures: {missing_qids}", file=sys.stderr)
81+
return 3
82+
fails = [fails_by_qid[qid] for qid in only_qids]
6383
skip = {int(x) for x in args.skip_qids.split(",") if x.strip()}
6484
fails = [r for r in fails if r["question_id"] not in skip][: args.max_cases]
6585
print(f"[info] {len(fails)} failures to retry with helallao+{args.model}", file=sys.stderr)
86+
if not fails:
87+
return 0
6688

89+
settings = get_settings()
6790
examples = {e.question_id: e for e in load_bird_mini_dev(args.bird_root)}
6891
registry = get_default_registry()
6992
sql_provider = HelallaoPerplexityProvider(

0 commit comments

Comments
 (0)