Add index-free MiniCPM scout, local QLoRA training, and measured evaluation
Tests / core (push) Canceled after 0s
Tests / core (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,265 @@
|
||||
# MiniCPM5 index-free search experiment
|
||||
|
||||
Recorded September 16, 2026, on an RTX 3050 Laptop GPU with 4 GB VRAM,
|
||||
an Intel Core i7-12650H, and approximately 30 GiB usable system RAM.
|
||||
|
||||
## Conclusion
|
||||
|
||||
The index-free search harness, MCP server, and local QLoRA pipeline work, but
|
||||
this experiment has not produced a useful replacement for a coding model's own
|
||||
search. Lower validation action loss and source-verified responses did not
|
||||
translate into reliable implementation localization. The existing indexed
|
||||
MiniLM integration remains the active MCP configuration.
|
||||
|
||||
Both adapters were trained on this laptop without a hosted teacher or solver.
|
||||
Their weights remain local; this repository publishes the implementation,
|
||||
training metadata, artifact hashes, and measured development results. No paired
|
||||
Astra experiment was run, so downstream usefulness with Astra is unproven.
|
||||
|
||||
| Variant | Target hits | Correct files | Median / p95 search time |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| Original model, Ollama Q4_K_M | 0 / 30 | 2 / 30 | 4.83 / 15.41 s |
|
||||
| Original model, Transformers NF4 | 0 / 30 | 4 / 30 | 16.39 / 54.43 s |
|
||||
| QLoRA adapter v1, Transformers NF4 | 0 / 30 | 8 / 30 | 19.40 / 39.98 s |
|
||||
| QLoRA adapter v2, Transformers NF4 | 0 / 30 | 3 / 30 | 32.88 / 44.77 s |
|
||||
| Fixed separate-term keyword control | 2 / 30 | 15 / 30 | 0.23 / 0.30 s |
|
||||
|
||||
The keyword control is a deliberately simple automatic baseline, not a
|
||||
measurement of Astra using grep. The model variants are not competitive with
|
||||
even this control on target retrieval or latency in this development suite.
|
||||
|
||||
## Question and setup
|
||||
|
||||
Can a local 1B model select `grep` and bounded `read` actions, then return useful
|
||||
source ranges without building an index? This experiment implements that loop
|
||||
and a small supervised adapter-training pipeline. It does not measure coding
|
||||
task success with a larger solver or compare against Astra's own search.
|
||||
|
||||
The base model is OpenBMB MiniCPM5-1B, an Apache-2.0 Llama architecture checkpoint
|
||||
with 1,080,632,832 parameters. The protocol uses native XML function calls and
|
||||
no-think framing. The harness provides a current file listing, allows six rounds,
|
||||
at most three actions per round, 512 generated tokens per round, and up to 6,000
|
||||
returned source characters. It enforces a 90-second search budget; a backend's
|
||||
current generation or filesystem operation may slightly exceed the deadline.
|
||||
|
||||
The frozen development suite has 30 English single-function localization tasks:
|
||||
10 each from Requests, Flask, and Click. Source commits, file hashes, and target
|
||||
body ranges are pinned in [`evals/live-search-v1.json`](../../evals/live-search-v1.json).
|
||||
Targets exclude leading docstrings. A hit needs at least three target body lines
|
||||
(or the whole body when shorter), and line precision penalizes broad guesses.
|
||||
Labels are not passed to the search model.
|
||||
|
||||
## First frozen baseline: Ollama Q4_K_M
|
||||
|
||||
| Measurement | Result |
|
||||
| --- | ---: |
|
||||
| Target implementations found | **0 / 30** |
|
||||
| Correct file returned | 2 / 30 |
|
||||
| Verified completed responses | 13 / 30 |
|
||||
| Exhausted search budget | 17 / 30 |
|
||||
| Median / p95 end-to-end latency | 4.83 / 15.41 s |
|
||||
| Total invalid actions / tool errors | 37 / 22 |
|
||||
| Mean rounds / tool calls | 5.37 / 4.70 |
|
||||
| Sampled peak total GPU memory | 1,213 MiB |
|
||||
|
||||
All completed responses had valid source provenance but missed the target body.
|
||||
This illustrates why successful tool execution is not a retrieval-quality metric.
|
||||
The unmodified Q4 model is not useful enough to replace the existing indexed
|
||||
retriever on this suite. A typical failure was selecting a matching comment or
|
||||
trying to finish without reading the requested range.
|
||||
|
||||
Latency excludes model warm-up. GPU memory is device-wide usage sampled once per
|
||||
second, not an exact allocator peak. This is a small sequential laptop workload,
|
||||
not a concurrency or production-serving benchmark.
|
||||
|
||||
## Reference backend baseline
|
||||
|
||||
The corrected Transformers NF4 baseline also found **0/30 targets**, with 4/30
|
||||
correct files, 13 verified completed responses, and 17 exhausted searches.
|
||||
Median latency was **16.39 s**, p95 **54.43 s**, and sampled device memory peaked
|
||||
at **2,198 MiB**. It produced 53 invalid actions and 16 tool errors. These are
|
||||
the baseline settings used for the adapter comparison; Q4 versus NF4 alone would
|
||||
confound adapter quality with the inference backend and quantization format.
|
||||
|
||||
## Keyword control
|
||||
|
||||
A separate non-neural control uses the same executor with up to 12 literal term
|
||||
searches and three 25-line reads. Windows are ranked by the sum of
|
||||
`1 / log2(2 + returned matches)` for their distinct query terms. This bounded
|
||||
match count is a heuristic, not corpus document frequency. The algorithm sees
|
||||
query text and current files only, never target labels.
|
||||
|
||||
The control was added during development after observing the model's failures.
|
||||
An initial single-OR-query version found 0/30 targets: frequent words exhausted
|
||||
the result cap before useful matches. Searching terms separately found **2/30**.
|
||||
Both runs are retained locally. This is a weak automatic keyword baseline; it
|
||||
does not represent an experienced developer or Astra using adaptive grep.
|
||||
|
||||
An idle-laptop repeat of the separate-term control preserved all per-task scores:
|
||||
**0.229 s median / 0.296 s p95**, with 11.57 tool calls per query on average.
|
||||
No GPU or model is required. Its macro line precision was only 0.77%, so even
|
||||
the two target hits do not imply an economical set of source snippets.
|
||||
|
||||
## Local adapter training
|
||||
|
||||
The selected adapter was trained with QLoRA on the original pinned checkpoint,
|
||||
using NF4 double quantization and BF16 computation. This is supervised action
|
||||
training, not a new architecture, full pretraining, or online RL.
|
||||
|
||||
| Setting or measurement | Value |
|
||||
| --- | ---: |
|
||||
| Train / validation trajectories | 256 / 32 |
|
||||
| Train / validation action examples | 826 / 104 |
|
||||
| Epochs / optimizer steps | 1 / 104 |
|
||||
| LoRA rank / alpha / dropout | 16 / 32 / 0.05 |
|
||||
| Trainable parameters | 11,206,656 |
|
||||
| Batch size / gradient accumulation | 1 / 8 |
|
||||
| Learning rate | 0.0001 |
|
||||
| Sequence limit / overlength examples dropped | 2,048 / 0 |
|
||||
| Initial / best validation action loss | 0.33653 / 0.08246 |
|
||||
| Selected checkpoint step | 100 |
|
||||
| Training time, including validation and saves | 1,206 s (20m 6s) |
|
||||
| Peak PyTorch allocated CUDA memory | 2,779 MiB |
|
||||
| Adapter safetensors size | 44,871,152 bytes |
|
||||
|
||||
The timer starts after loading, tokenization, and optimizer setup. Allocator
|
||||
memory is different from the device-wide sampler used for search runs. The
|
||||
recorded run used the laptop's existing CUDA stack; no hosted teacher was called.
|
||||
|
||||
Data comes from the [audited CodeSearchNet subset](../../docs/DATASET.md), retaining
|
||||
source and distractor provenance. Complete candidate pools are repository-disjoint
|
||||
between training and validation; Requests, Flask, and Click are excluded by name.
|
||||
Three-file synthetic repositories preserve source filenames and vary line offsets.
|
||||
An oracle executes query-term searches, source reads, and final range selections.
|
||||
Only assistant action tokens receive loss. Such examples teach protocol and
|
||||
short search sequences, not realistic repository exploration.
|
||||
|
||||
Selection used validation action loss, not the 30-task localization scores.
|
||||
The selected weights are local at `runs/minicpm5-policy-v1/best`; weights are not
|
||||
published with the repository. The adapter's base-reference metadata was
|
||||
normalized to the official model ID and revision after training, without changing
|
||||
the numerical weights. Future training runs save those portable fields directly.
|
||||
The exact training source snapshot remains beside the local run.
|
||||
|
||||
### Adapter v1 search result and data revision
|
||||
|
||||
The first adapter still found **0/30 targets**, despite improving file hits to
|
||||
8/30 and verified completions to 25/30. Invalid actions fell from 53 to 13; tool
|
||||
errors fell from 16 to 14. Median latency was 19.40 s and p95 39.98 s with the
|
||||
unmerged PEFT adapter. Better protocol execution did not produce useful target
|
||||
body retrieval. These development timings are not isolated kernel benchmarks.
|
||||
|
||||
Inspection exposed a weakness in the first oracle recipe: it required exact
|
||||
unread function boundaries after a short grep observation. That observation
|
||||
cannot reveal the function's end. The learned policy often copied the same match
|
||||
line into both read boundaries. The revised recipe instead teaches a fixed
|
||||
observable window around a match, followed by selection from the actual read.
|
||||
Two functions per file and randomized target position reduce the shortcut of
|
||||
always selecting the only function or the end of the file. One unobservable
|
||||
training candidate was rejected; validation rejected none.
|
||||
|
||||
This revision was motivated by development traces, so subsequent localization
|
||||
results remain development results, not a fresh untouched evaluation.
|
||||
|
||||
### Adapter v2 training
|
||||
|
||||
The corrected recipe retained 256 training and 32 validation trajectories
|
||||
(826 / 104 action examples). The limit increased to 2,560 tokens; all examples
|
||||
fit without truncation or dropping. The same base, LoRA configuration, learning
|
||||
rate, seed, and one-epoch schedule were used. The run took **1,297 s (21m 37s)**,
|
||||
with **2,842 MiB** peak PyTorch allocated CUDA memory. Validation action loss
|
||||
fell from **0.48502 to 0.06406**, selecting step **104**.
|
||||
|
||||
These loss values refer to the revised examples and cannot be compared directly
|
||||
with v1's validation loss. The selected adapter is local at
|
||||
`runs/minicpm5-policy-v2/best`. See `training-v2-experiment.json`,
|
||||
`training-v2-result.json`, and `adapter-v2-manifest.json` for the exact settings
|
||||
and artifact hashes. Both adapters use unmerged PEFT inference in the reference
|
||||
backend; the reported search latency is not an optimized merged-GGUF deployment.
|
||||
|
||||
The v2 evaluation process was interrupted after 28 task results had been saved.
|
||||
The remaining two tasks were resumed after verifying the frozen code, suite,
|
||||
repository, and adapter hashes, with a new warm-up. The earlier results were
|
||||
retained. GPU samples for the first segment were not persisted, so this report
|
||||
does not claim a full-run GPU peak for v2 inference.
|
||||
|
||||
### Adapter v2 search result
|
||||
|
||||
The revised adapter again found **0/30 targets** and returned the correct file
|
||||
on 3/30 tasks. Only 7 responses completed; 23 exhausted the search budget. Median
|
||||
latency was **32.88 s**, p95 **44.77 s**, with 51 invalid actions and 22 tool errors.
|
||||
The lower validation action loss did not generalize to this search workload.
|
||||
Observed failures included poor search terms, matches in documentation instead
|
||||
of implementation, invalid source ranges, and failure to recover from tool errors.
|
||||
|
||||
A diagnostic over all successful intermediate reads found target-body coverage
|
||||
on 1/30 tasks for Q4, 0/30 for NF4 and adapter v1, and 1/30 for adapter v2. These
|
||||
are not final-return scores and can consume more context than the returned
|
||||
snippet budget. They show that the problem starts before final selection: most
|
||||
searches never read the target implementation. See [`read-coverage.json`](read-coverage.json).
|
||||
|
||||
## Artifact integrity and diagnostics
|
||||
|
||||
- Base revision: `87179e5c1f455ef22e6223592d2d61351b525bfc`.
|
||||
- Original safetensors file: 2,161,290,912 bytes; SHA-256
|
||||
`7ab8fd86563125929be78aeec8cb3969c7ed2ead3be1ab9d3ec0a9fa69c8660d`.
|
||||
- Official Q4_K_M GGUF revision: `3d55fac80935ae6456986ad2384b5cbcc4d6c948`.
|
||||
- GGUF file: 688,065,920 bytes; SHA-256
|
||||
`81b64d05a23b17b34c475f42b3e72fbde62d4b92cc34541f7a8031d0752deafa`.
|
||||
- Suite SHA-256: `d06effdf41ee2e38bf8f44629949d9b4491067986fc5a73aef22cf80c5a5bf96`.
|
||||
|
||||
Both model-file hashes were verified locally against the publisher's artifacts.
|
||||
The pinned tokenizer and Ollama agreed on the token count of an actual 611-token
|
||||
prompt. A separate JSON-decoding development query, excluded from the 30-task
|
||||
suite, also failed within six rounds with BF16 reference inference (51.18 s).
|
||||
A one-query thinking-mode diagnostic failed too (18.50 s); it is not a benchmark
|
||||
of thinking mode. These checks do not establish that every prompt or runtime
|
||||
configuration would perform equally poorly.
|
||||
|
||||
An early Transformers diagnostic mistakenly removed special XML delimiter tokens
|
||||
during decoding. It was invalidated, corrected, and covered by a regression test.
|
||||
The published Q4 result used Ollama and was unaffected. Only corrected Transformers
|
||||
runs should be used for model comparisons.
|
||||
|
||||
## MCP integration check
|
||||
|
||||
A real stdio client initialized `serve-live` with adapter v2, discovered
|
||||
`scout_live_search`, and made two calls to the same resident server. Both returned
|
||||
valid structured responses without MCP transport errors and with
|
||||
`index_required: false`. Search took 31.89 s and 30.79 s. Both exhausted their
|
||||
six-round budgets on the excluded JSON-decoding development query and returned
|
||||
no source ranges. This validates resident inference and the MCP transport, not
|
||||
successful retrieval. The compact record is [`mcp-smoke.json`](mcp-smoke.json).
|
||||
|
||||
## Reproducibility and limits
|
||||
|
||||
Implementation validation passed: **73 tests**, Ruff lint and format checks,
|
||||
lockfile validation, and source/wheel builds. Tests cover bounded filesystem
|
||||
actions, source verification, protocol decoding, loss masking, and an MCP stdio
|
||||
round trip. These checks validate implementation behavior, not model search quality.
|
||||
|
||||
See [setup and commands](../../docs/LIVE_SEARCH.md). Public JSON artifacts contain
|
||||
configuration, aggregate results, and per-task scores without full source snippets
|
||||
or model-generated reasoning. Full traces, source snapshots, weights, and prepared
|
||||
training data remain in ignored local directories.
|
||||
|
||||
This is a development suite on mature public Python repositories, which may appear
|
||||
in the base model's pretraining. It is not an untouched final holdout. Thirty tasks
|
||||
do not establish performance across repositories, languages, or coding-agent
|
||||
workloads. A gain on this suite would need confirmation on new tasks and a paired
|
||||
solver-with/without-scout experiment before deployment.
|
||||
|
||||
## Recommended next experiment
|
||||
|
||||
Keep this version experimental. First move range arithmetic into the harness:
|
||||
let a policy choose an observed match or span handle, and let the executor expand
|
||||
and validate the corresponding source window. Then train on executed search
|
||||
trajectories in realistic repositories, including unsuccessful searches,
|
||||
reformulations, and distractors. The current short oracle demonstrations mainly
|
||||
teach how to issue actions.
|
||||
|
||||
Freeze a new repository-disjoint evaluation before tuning further. Measure target
|
||||
coverage, returned context size, and latency against lexical and indexed controls.
|
||||
Only then test a larger solver with and without the scout on the same coding
|
||||
tasks. More adapter epochs, dynamic experts, or online reward updates are not
|
||||
supported as the next priority by these results.
|
||||
Reference in New Issue
Block a user