Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ llamacpp-ai-index-maven-plugin/ (repo root; reactor parent)
│ ├── Main.java BitcoinAddressFinder cli/Main.java pattern
│ └── configuration/ CConfiguration + CCommand (BAF public-field style)
├── srcmorph-maven-plugin/ Maven plugin net.ladenthin:srcmorph-maven-plugin, goalPrefix srcmorph
│ └── src/main/java/net/ladenthin/maven/srcmorph/mojo/ (5 mojos; renamed package/properties)
│ └── src/main/java/net/ladenthin/maven/srcmorph/mojo/ (4 goal mojos + the abstract AbstractAiIndexMojo base; renamed package/properties)
├── examples/ config_*.json/.yaml + run_*.sh/.bat + logbackConfiguration.xml
├── docs/ RELEASE.md + the ai-index model-benchmark writeups
└── .github/workflows/ CI adapted to the 3-module reactor
Expand Down Expand Up @@ -127,7 +127,7 @@ above), `layeredArchitecture` (`engine` on top → `indexer` → `provider`/`doc
(`AiGenerationKindLincheckTest`), and the model-backed real tests gated on
`src/test/resources/SmolLM2-135M-Instruct-Q3_K_M.gguf`. **PIT mutation testing**: `mutationThreshold`
100 over an explicit `targetClasses` list in `srcmorph/pom.xml` — currently 47 classes across
config/document/indexer/prompt/provider/support, all killed at 100%. `srcmorph-cli` and the plugin
config/document/engine/indexer/prompt/provider/support, all killed at 100%. `srcmorph-cli` and the plugin
module do not have a PIT gate yet (see `TODO.md`). The `gpu-cuda`/`gpu-vulkan` profiles (swap the
`net.ladenthin:llama` classifier via the `llama.classifier` property) live here; the `jcstress` and
`vmlens` profiles/tests currently still live in the **plugin** module (they were not moved in the
Expand Down Expand Up @@ -195,6 +195,15 @@ themselves.
- **Skip flags stay mojo-side** (`skip`, `skipFile`, `skipPackage`, `skipProject`) — a Maven lifecycle
concern, not part of `SrcMorphConfiguration`; an engine built from a configuration always executes
when asked. See `MojoPhaseSkipTest`.
- **Two property namespaces — do NOT confuse them (this has tripped audits).** The **published mojo
`@Parameter`s** are the `srcmorph.*` set (`srcmorph.skip`, `srcmorph.force`, `srcmorph.planOnly`,
`srcmorph.generationProvider`, `srcmorph.llama.*`, …). The `ai.*` names in the plugin `pom.xml` +
README (`ai.model`, `ai.gpuLayers`, `ai.mainGpu`, `ai.devices`, `ai.index.output.directory`) are
**repo-local Maven build properties** wired into this module's own gpt-oss self-test/benchmark
executions (`<gpuLayers>${ai.gpuLayers}</gpuLayers>`, `<aiDefinitionKey>${ai.model}</aiDefinitionKey>`)
and overridable with `-Dai.*` — they are **not** mojo parameters, and downstream consumers set the
same knobs as `<configuration>`/model-definition elements. So `-Dai.gpuLayers=12` etc. are **correct**
as documented; do not "fix" them to `srcmorph.*`.
- **Architecture rules** (`PluginArchitectureTest`): Maven-annotation confinement to `mojo`, every mojo
extends `AbstractMojo`, plus this module's slice of the shared conventions.
- **jcstress** (`jcstress/AiGenerationKindRace.java`) and **vmlens**
Expand Down
4 changes: 2 additions & 2 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ recorded in git history and `crossrepostatus.md`, not here.
this explicitly with a comment at the spot a PIT plugin block would go). For the CLI: the pure
helpers worth mutation-gating are the config copy/round-trip (`Main#copyWithPlanOnlyForced`) and
command dispatch; `Main`'s I/O-heavy entry points (`main`, `loadConfiguration`) are better served by
integration tests than unit-mutation gating. For the plugin: the 5 mojo classes are Maven-lifecycle
integration tests than unit-mutation gating. For the plugin: the 4 goal mojos (+ the abstract AbstractAiIndexMojo base) are Maven-lifecycle
orchestration (typically integration-tested via Maven invoker/executor, not unit-mutation-tested) —
confirm that reasoning still holds before assuming it's a permanent exemption rather than a gap.

- **Expand `srcmorph`'s own PIT mutation scope (optional).** `srcmorph/pom.xml` wires
`<mutationThreshold>100</mutationThreshold>` over an explicit `<targetClasses>` list (config /
document / prompt / provider / support value+logic classes, plus `indexer.AiInputWindowCalculator`
document / engine / prompt / provider / support value+logic classes, plus `indexer.AiInputWindowCalculator`
and `support.AiProgressBar`), all killed at 100%. Still out (optional, need careful fixtures):
`document.AiMdDocumentCodec` / `AiMdHeaderCodec`, `prompt.AiPromptPreparationSupport`, and the newer
`indexer.AiIndexPlan` / `config.AiConditionGroup`. The orchestration layers (`indexer.*` walk,
Expand Down
2 changes: 1 addition & 1 deletion srcmorph-cli/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ SPDX-License-Identifier: Apache-2.0
<version>0.8.15</version>
</plugin>
<!--
No pitest-maven pluginManagement entry: unlike srcmorph (which gates ~40
No pitest-maven pluginManagement entry: unlike srcmorph (which gates 47
framework-free classes at 100% mutation coverage), this module is not yet PIT-gated.
TODO (tracked for a later step): add a pitest-maven execution here once the CLI's
pure helpers (config copy/round-trip, command dispatch) have dedicated unit tests
Expand Down
37 changes: 23 additions & 14 deletions srcmorph-maven-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,13 @@ Based on an 8-model × 2-prompt benchmark run against this codebase — full res
pros/cons, a source-faithfulness deep-dive, and reproduction steps in
[docs/ai-index-benchmark](../docs/ai-index-benchmark/COMPARISON.md):

> **On the `-Dai.*` flags below** (`ai.model`, `ai.gpuLayers`, `ai.mainGpu`, `ai.devices`, …): these are
> **this repo's own Maven build properties** (defined in `srcmorph-maven-plugin/pom.xml` and wired into
> the gpt-oss profile executions), overridable per run with `-D` when you build *this* repo. They are
> **not** plugin `@Parameter`s — a downstream build of the published plugin instead sets the same knobs as
> `<configuration>`/model-definition elements (`<gpuLayers>`, `<mainGpu>`, `<devices>`, `<aiDefinitionKey>`).
> The published mojo parameters are the separate `srcmorph.*` set.

- **`gpt-oss-20B-mxfp4` — the production default** (switch with `-Dai.model=<key>`). The native MXFP4
quant at a 96K window; it inherits the benchmark's accuracy lead (gpt-oss-20b was most *accurate* per
file, won 5/6 in the per-file matrix — measured on the `c96k`/UD-Q4_K_XL quant, but E5 shows quant
Expand Down Expand Up @@ -555,33 +562,35 @@ GPU `jllama.dll` from it — no library path to manage:
```

```
mvn srcmorph:generate -Dai.gpuLayers=20 # + the GPU runtime on PATH (see below)
mvn srcmorph:generate -Dsrcmorph.generationProvider=llamacpp-jni # + the GPU runtime on PATH (see below)
```

**Alternative — runtime library override (no POM change).** Point `net.ladenthin.llama.lib.path` at a
folder holding the GPU `jllama.dll` (extracted once from the classifier jar); it is tried before the
bundled native:

```
mvn srcmorph:generate -Dnet.ladenthin.llama.lib.path=C:\path\to\gpu-native -Dai.gpuLayers=20
mvn srcmorph:generate -Dnet.ladenthin.llama.lib.path=C:\path\to\gpu-native -Dsrcmorph.generationProvider=llamacpp-jni
```

In both cases:

- **CUDA** needs a matching CUDA 13 toolkit + driver, and the toolkit's `bin\x64` (with `cudart64_13.dll`,
`cublas64_13.dll`) on `PATH` — the classifier jar bundles only `jllama.dll`, not the CUDA runtime.
- **`ai.gpuLayers`** (on the gpt-oss presets): `-1` (default) does **not** pin a layer count, so
llama.cpp **auto-fits** as many layers as fit the card's free VRAM — the robust "runs on any card"
setting (it never over-commits, so no OOM on a 6 GB card, and uses more layers on a bigger one). Pin a
positive number only to force a specific **partial** split (a fixed count disables auto-fit), or `0` to
force CPU. Measured on an 8 GB RTX 3070, auto-fit gpt-oss-20b ≈ 29 decode t/s (vs ≈ 8 on CPU); a card
with ≥ 16 GB fits all layers and is far faster.
- **Picking a GPU on a multi-GPU host** (`ai.mainGpu` / `ai.devices` on the gpt-oss presets): a **CUDA**
build only enumerates NVIDIA devices, so a single-NVIDIA host needs nothing. A **Vulkan** build
enumerates *every* GPU (an integrated GPU is often device `0`), so the default may pick the slower one —
set `-Dai.mainGpu=1` to select the discrete GPU, or `-Dai.devices=Vulkan1` for explicit device names
(these map to the binding's `--main-gpu` / `--device`). On any model definition the same knobs are the
`<mainGpu>` / `<devices>` elements.
- **GPU layer offload** — set `<gpuLayers>` inside your `<aiDefinition>` (see "Per-model
`<aiDefinition>` parameters" above): `-1` (default) does **not** pin a layer count, so llama.cpp
**auto-fits** as many layers as fit the card's free VRAM — the robust "runs on any card" setting (it
never over-commits, so no OOM on a 6 GB card, and uses more layers on a bigger one). Pin a positive
number only to force a specific **partial** split (a fixed count disables auto-fit), or `0` to force
CPU. Measured on an 8 GB RTX 3070, auto-fit gpt-oss-20b ≈ 29 decode t/s (vs ≈ 8 on CPU); a card with
≥ 16 GB fits all layers and is far faster. *(In this repo's own gpt-oss presets the same knob is wired
to the `-Dai.gpuLayers` build property — see the note under "Recommended Models" above.)*
- **Picking a GPU on a multi-GPU host** — set `<mainGpu>` / `<devices>` inside your `<aiDefinition>`: a
**CUDA** build only enumerates NVIDIA devices, so a single-NVIDIA host needs nothing. A **Vulkan**
build enumerates *every* GPU (an integrated GPU is often device `0`), so the default may pick the
slower one — set `<mainGpu>1</mainGpu>` to select the discrete GPU, or `<devices>Vulkan1</devices>`
for explicit device names (these map to the binding's `--main-gpu` / `--device`). *(In this repo's own
gpt-oss presets these are wired to the `-Dai.mainGpu` / `-Dai.devices` build properties.)*

**Profiles (this repo's own reactor build only — test/benchmark).** `-P gpu-cuda` / `-P gpu-vulkan`
swap the `net.ladenthin:llama` classifier (via the `llama.classifier` property) for `srcmorph`'s own
Expand Down
13 changes: 13 additions & 0 deletions srcmorph-maven-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,19 @@ SPDX-License-Identifier: Apache-2.0
provider package touches it); this module no longer declares it directly. The
gpu-cuda / gpu-vulkan profiles that used to set its classifier here now live on
srcmorph/pom.xml, since the classifier choice is resolved at srcmorph's own build. -->
<!-- ====================================================================================
`ai.*` properties (ai.model / ai.gpuLayers / ai.mainGpu / ai.devices / ai.cachePrompt /
ai.index.output.directory, plus the commented-out exp.* experiment knobs) are THIS
repo's own Maven BUILD properties for the self-test / benchmark executions — NOT plugin
@Parameters. They are wired into the local gpt-oss profile executions below (e.g.
<gpuLayers>${ai.gpuLayers}</gpuLayers>, <aiDefinitionKey>${ai.model}</aiDefinitionKey>)
and are overridable per run with -Dai.<name>=<value>. Downstream consumers of the
PUBLISHED plugin do NOT inherit these; they set the same knobs as
<configuration>/model-definition elements (<gpuLayers>, <mainGpu>, <devices>,
<aiDefinitionKey>). The published mojo parameters are the separate `srcmorph.*` set
(see AbstractAiIndexMojo). Do NOT "fix" the docs' `-Dai.*` examples to `srcmorph.*` —
the two namespaces are intentionally different (repo build knobs vs. published params).
==================================================================================== -->
<!-- Default AI model definition (key) used by the gpt-oss profile's generate/aggregate executions.
gpt-oss-20B-mxfp4 is the native MXFP4 format: same ~12 GB size and decode speed as the Q4/Q5/Q8
variants (the MoE experts are MXFP4 regardless), but no double-quantization of the experts ->
Expand Down
Loading