Skip to content

test: add integration tests for LoRA module - #752

Merged
ooples merged 5 commits into
masterfrom
test/lora-integration-tests
Jan 26, 2026
Merged

ooples merged 5 commits into
masterfrom
test/lora-integration-tests

Conversation

@ooples

@ooples ooples commented Jan 23, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Add comprehensive integration tests for LoRA module covering:
    • LoRALayer initialization, forward/backward pass, parameter handling
    • StandardLoRAAdapter wrapping, freezing, training workflow
    • Multiple adapter variants (Standard, DoRA, VeRA, DVoRA, LoKr, LoHa, LoRAFA, PiSSA, MoRA)
    • Parameter efficiency calculations
  • Remove stale CLBlast project reference from test project
  • Fix multiple bugs discovered by integration tests:
    • DoRAAdapter: transpose MergeWeights result to match expected dimensions
    • LoRAAdapterBase: fix matrix indexing in MergeToDenseOrFullyConnected
    • LoRAXSAdapter: handle null _trainableR in ParameterCount property
    • StandardLoRAAdapter: fix matrix indexing in MergeToOriginalLayer
    • VeRAAdapter: handle null scaling vectors in ParameterCount and override UpdateParametersFromLayers

Test plan

  • All 119 LoRA tests pass on both net10.0 and net471
  • Build succeeds with no errors
  • All adapter variants (Standard, DoRA, VeRA, DVoRA, LoKr, LoHa, LoRAFA, PiSSA, MoRA) tested

Closes #641

🤖 Generated with Claude Code

- Add 32 integration tests for LoRA module
- Test LoRALayer initialization, forward/backward pass, parameter handling
- Test StandardLoRAAdapter wrapping, freezing, training workflow
- Test multiple adapter variants (Standard, LoKr, LoHa, LoRAFA, PiSSA, MoRA)
- Test parameter efficiency calculations
- Remove stale CLBlast project reference from test project

Note: Some adapters (DoRA, VeRA, LoRAXS, DVoRA) have bugs and are excluded
until source implementation issues are fixed.

Closes #641

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jan 23, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
aidotnet-playground-api Ready Ready Preview, Comment Jan 25, 2026 10:34pm

@coderabbitai

coderabbitai Bot commented Jan 23, 2026 •

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Added a comprehensive integration test suite for LoRA adapters covering many adapter variants, parameter-efficiency checks, edge cases, and end-to-end training scaffolds.
  • Bug Fixes

    • Corrected LoRA weight-dimension and merge logic for stable fine-tuning behavior.
    • Fixed initialization-order handling so adapter parameters initialize and synchronize reliably.
  • Chores

    • Removed an unused project dependency from the test project.

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

Removed a native project reference from the test project and added extensive LoRA integration tests; several LoRA adapters were corrected to align LoRA weight/index layouts and made initialization-safe.

Changes

Cohort / File(s) Summary
Project reference change
tests/AiDotNet.Tests/AiDotNetTests.csproj
Removed ProjectReference to ..\..\src\AiDotNet.Native.CLBlast\AiDotNet.Native.CLBlast.csproj.
LoRA integration tests
tests/AiDotNet.Tests/IntegrationTests/LoRA/LoRAIntegrationTests.cs
Added comprehensive integration test suite (~618 lines) covering many LoRA adapters, forward/backward passes, parameter counts, edge cases, and a training scaffold.
DoRA adapter weight orientation
src/LoRA/Adapters/DoRAAdapter.cs
Merge/forward now reads LoRA MergeWeights() as [inputSize, outputSize], transposes to [outputSize, inputSize] before applying to base weights.
LoRA adapter base merge indexing
src/LoRA/Adapters/LoRAAdapterBase.cs
Fixed mapping from flat base parameter index to LoRA matrix indices to use inputIdx/outputIdx matching loraWeights layout [input, output].
Standard LoRA merge indexing
src/LoRA/Adapters/StandardLoRAAdapter.cs
MergeToOriginalLayer now indexes loraWeights[inputIdx, outputIdx] when combining into base parameters.
LoRAXS parameter safety
src/LoRA/Adapters/LoRAXSAdapter.cs
ParameterCount and UpdateParametersFromLayers now guard against _trainableR being null during base construction; returns safe defaults until initialized.
VeRA initialization & sync
src/LoRA/Adapters/VeRAAdapter.cs
Added null-safe ParameterCount handling and a protected UpdateParametersFromLayers() override that no-ops if scaling vectors are null; otherwise packs scaling vectors into the parameter vector.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hopped through indices, flipped a bit,
I nudged a link and wrote a testy skit.
I transposed weights with careful cheer,
Now LoRA trains without a fear.
Tiny rabbit clap—code's in gear!

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.91% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding comprehensive integration tests for the LoRA module, which is the primary objective of this PR.
Description check ✅ Passed The description clearly covers the main changes: integration tests for LoRA, removal of stale CLBlast reference, and bug fixes discovered during testing, all related to the changeset.
Linked Issues check ✅ Passed The PR addresses issue #641's requirement for LoRA integration tests by providing comprehensive test coverage [#641], fixing bugs in adapters (DoRA, LoRAAdapterBase, LoRAXSAdapter, StandardLoRA, VeRA), and achieving broad variant coverage.
Out of Scope Changes check ✅ Passed All changes are in scope: integration tests for LoRA module, bug fixes in LoRA adapters discovered by testing, and removal of stale project reference are all directly related to issue #641 objectives.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch test/lora-integration-tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot added the feature Feature work item label Jan 23, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@tests/AiDotNet.Tests/IntegrationTests/LoRA/LoRAIntegrationTests.cs`:
- Around line 443-482: The test LoRA_TrainingWorkflow_ReducesLoss currently
regenerates random input and target each epoch which prevents meaningful loss
reduction; fix it by creating a fixed training example or small fixed dataset
outside the epoch loop (call CreateTensor once or build an array of
inputs/targets before the for-loop) and reuse those same tensors each epoch for
adapter.Forward/Backward/UpdateParameters; optionally seed the RNG or create
deterministic tensors so the test is stable and then assert that finalLoss <
initialLoss (or at least decreased) in addition to the NaN/Infinity checks.
🧹 Nitpick comments (2)
tests/AiDotNet.Tests/IntegrationTests/LoRA/LoRAIntegrationTests.cs (2)

385-401: Consider adding forward pass tests for LoKr and LoHa adapters.

These adapters only have initialization tests, while QLoRA and AdaLoRA have both initialization and forward pass tests. For consistency and better coverage, consider adding forward pass tests similar to QLoRAAdapter_Forward_ProducesValidOutput.


548-573: Remove unused variable.

The input variable at line 552 is never used. The loop correctly creates testInput based on each adapter's actual input shape (line 567).

♻️ Suggested fix
     public void AllAdapters_ForwardPass_ProducesValidOutput()
     {
         var baseLayer = new DenseLayer<double>(InputSize, OutputSize);
-        var input = CreateTensor(1, InputSize);
 
         // Note: DoRA, VeRA, LoRAXS have bugs; MoRA requires square layers; DVoRA requires initialization

Comment thread tests/AiDotNet.Tests/IntegrationTests/LoRA/LoRAIntegrationTests.cs
- DoRAAdapter: transpose MergeWeights result to match expected dimensions
- LoRAAdapterBase: fix matrix indexing in MergeToDenseOrFullyConnected
- LoRAXSAdapter: handle null _trainableR in ParameterCount property
- StandardLoRAAdapter: fix matrix indexing in MergeToOriginalLayer
- VeRAAdapter: handle null scaling vectors in ParameterCount and override
  UpdateParametersFromLayers to use only scaling vectors

Also adds DVoRA to the AllAdapters forward pass test.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move input and target tensor creation outside the training loop
for meaningful loss reduction verification.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/LoRA/Adapters/DoRAAdapter.cs`:
- Around line 374-378: Merge path still uses the untransposed delta: when
MergeWeights() returns loraWeightDeltaRaw ([inputSize, outputSize]) you
transpose it to loraWeightDelta ([outputSize, inputSize]) in Forward but
MergeToOriginalLayer() is still adding loraWeightDeltaRaw directly; update
MergeToOriginalLayer() (and the similar code around the 720-730 region) to use
the transposed matrix (or swap indices when indexing) so the delta is applied as
[outputSize, inputSize] to the base weight matrix, referencing MergeWeights(),
loraWeightDeltaRaw, loraWeightDelta, and MergeToOriginalLayer() to locate the
changes.

In `@src/LoRA/Adapters/LoRAXSAdapter.cs`:
- Around line 250-257: ParameterCount currently returns Rank * Rank when
_trainableR is null which allows the base constructor to call
UpdateParametersFromLayers() and pack _loraLayer parameters (size
_loraLayer.ParameterCount) into a too-small buffer; change behavior to prevent
packing until _trainableR is initialized by making ParameterCount return
_loraLayer.ParameterCount (or otherwise the larger safe size) when _trainableR
is null, or add a guard in UpdateParametersFromLayers() to early-return if
_trainableR is null; update references in ParameterCount, the class constructor,
and UpdateParametersFromLayers() so the base ctor cannot overrun the Parameters
buffer.
♻️ Duplicate comments (1)
tests/AiDotNet.Tests/IntegrationTests/LoRA/LoRAIntegrationTests.cs (1)

451-490: Loss-reduction test still lacks an assertion.

The test name implies a decrease, but only NaN/Infinity checks are performed. Consider asserting finalLoss <= initialLoss (with a small tolerance) or renaming the test to reflect intent.

♻️ Suggested assertion
         Assert.False(double.IsNaN(finalLoss), "Final loss should not be NaN");
         Assert.False(double.IsInfinity(finalLoss), "Final loss should not be Infinity");
+        Assert.True(finalLoss <= initialLoss + 1e-8,
+            $"Expected loss to decrease (initial {initialLoss}, final {finalLoss}).");

Comment thread src/LoRA/Adapters/DoRAAdapter.cs
Comment thread src/LoRA/Adapters/LoRAXSAdapter.cs
- Add assertion for loss reduction in LoRA_TrainingWorkflow_ReducesLoss test
- Remove unused input variable in AllAdapters_ForwardPass_ProducesValidOutput

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- DoRAAdapter: Transpose loraWeights in MergeToOriginalLayer to match
  base weight dimensions [outputSize, inputSize]
- LoRAXSAdapter: Override UpdateParametersFromLayers to prevent buffer
  overrun during base constructor call before _trainableR is initialized

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
0.0% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@ooples
ooples merged commit 5493051 into master Jan 26, 2026
41 of 42 checks passed
@ooples
ooples deleted the test/lora-integration-tests branch January 26, 2026 00:57
@coderabbitai coderabbitai Bot mentioned this pull request Jan 27, 2026
3 tasks done

This branch was successfully deployed

1 active deployment
Preview — 00217f30 Deployed Jan 25, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Feature work item

Projects

None yet

Development

Successfully merging this pull request may close these issues.

test: Add integration tests for LoRA module [P2]

2 participants