> ## Documentation Index
> Fetch the complete documentation index at: https://docs.runanywhere.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# LoRA Adapters

> Hot-swap fine-tuned LoRA adapters at runtime without reloading models

## Overview

LoRA (Low-Rank Adaptation) lets you apply lightweight fine-tuned adapters to a loaded base model at runtime. Swap adapters instantly without reloading the full model — perfect for switching between domain-specific behaviors like medical QA, creative writing, or code generation.

```mermaid theme={null}
graph LR
    A(Base Model) --> B(Load LoRA)
    B --> C(Adapted Model)
    C --> D(Generate)
    C --> E(Swap LoRA)
    E --> B

    style A fill:#334155,color:#fff,stroke:#334155
    style B fill:#ff6900,color:#fff,stroke:#ff6900
    style C fill:#fb2c36,color:#fff,stroke:#fb2c36
    style D fill:#334155,color:#fff,stroke:#334155
    style E fill:#475569,color:#fff,stroke:#475569
```

## Package Imports

```kotlin theme={null}
import com.runanywhere.sdk.public.RunAnywhere
import com.runanywhere.sdk.public.extensions.LLM.LoRAAdapterConfig
import com.runanywhere.sdk.public.extensions.LLM.LoRAAdapterInfo
import com.runanywhere.sdk.public.extensions.loadLoraAdapter
import com.runanywhere.sdk.public.extensions.removeLoraAdapter
import com.runanywhere.sdk.public.extensions.clearLoraAdapters
import com.runanywhere.sdk.public.extensions.getLoadedLoraAdapters
import com.runanywhere.sdk.public.extensions.checkLoraCompatibility
```

## Basic Usage

```kotlin theme={null}
// 1. Load a base model first
RunAnywhere.loadLLMModel("qwen-0.5b")

// 2. Check compatibility
val compat = RunAnywhere.checkLoraCompatibility("/path/to/adapter.gguf")
if (!compat.isCompatible) {
    println("Incompatible: ${compat.error}")
    return
}

// 3. Apply a LoRA adapter
RunAnywhere.loadLoraAdapter(LoRAAdapterConfig(
    path = "/path/to/adapter.gguf",
    scale = 1.0f
))

// 4. Generate with the adapter applied
val result = RunAnywhere.generate("What are the symptoms of diabetes?")
println(result.text)
```

<Warning>
  A base LLM model **must be loaded** before applying LoRA adapters. Calling `loadLoraAdapter()`
  without a loaded model will throw an `SDKError`.
</Warning>

## Adapter Scale

The `scale` parameter controls how strongly the adapter affects generation:

| Scale   | Effect                                  |
| ------- | --------------------------------------- |
| `0.0`   | No effect (adapter loaded but inactive) |
| `0.5`   | Half strength — subtle influence        |
| `1.0`   | Full strength (default)                 |
| `> 1.0` | Amplified effect (use with caution)     |

```kotlin theme={null}
// Subtle adapter influence
RunAnywhere.loadLoraAdapter(LoRAAdapterConfig(
    path = "/path/to/style-adapter.gguf",
    scale = 0.3f
))
```

## Stacking Multiple Adapters

You can apply multiple LoRA adapters simultaneously:

```kotlin theme={null}
// Apply medical knowledge adapter
RunAnywhere.loadLoraAdapter(LoRAAdapterConfig(
    path = "/path/to/medical-qa.gguf",
    scale = 1.0f
))

// Stack a conversational style adapter on top
RunAnywhere.loadLoraAdapter(LoRAAdapterConfig(
    path = "/path/to/conversational.gguf",
    scale = 0.5f
))

// Both adapters are now active
val adapters = RunAnywhere.getLoadedLoraAdapters()
println("Active adapters: ${adapters.size}") // 2
```

## API Reference

### LoRAAdapterConfig

```kotlin theme={null}
@Serializable
data class LoRAAdapterConfig(
    val path: String,        // Path to LoRA adapter GGUF file (required)
    val scale: Float = 1.0f  // Scale factor (0.0 to 1.0+)
)
```

| Parameter | Type     | Default | Description                                               |
| --------- | -------- | ------- | --------------------------------------------------------- |
| `path`    | `String` | —       | Path to the LoRA adapter `.gguf` file. Must not be blank. |
| `scale`   | `Float`  | `1.0f`  | How strongly the adapter affects output.                  |

### LoRAAdapterInfo

```kotlin theme={null}
@Serializable
data class LoRAAdapterInfo(
    val path: String,     // Path used when loading
    val scale: Float,     // Active scale factor
    val applied: Boolean  // Whether applied to current context
)
```

### LoraCompatibilityResult

```kotlin theme={null}
data class LoraCompatibilityResult(
    val isCompatible: Boolean,
    val error: String? = null
)
```

### loadLoraAdapter

```kotlin theme={null}
suspend fun RunAnywhere.loadLoraAdapter(config: LoRAAdapterConfig)
```

Loads and applies a LoRA adapter to the currently loaded model. Context is recreated internally.

**Throws:** `SDKError` if no model is loaded or loading fails.

### removeLoraAdapter

```kotlin theme={null}
suspend fun RunAnywhere.removeLoraAdapter(path: String)
```

Removes a specific LoRA adapter by the path used when loading.

**Throws:** `SDKError` if adapter not found or removal fails.

### clearLoraAdapters

```kotlin theme={null}
suspend fun RunAnywhere.clearLoraAdapters()
```

Removes all loaded LoRA adapters and restores the base model behavior.

### getLoadedLoraAdapters

```kotlin theme={null}
suspend fun RunAnywhere.getLoadedLoraAdapters(): List<LoRAAdapterInfo>
```

Returns information about all currently loaded adapters.

### checkLoraCompatibility

```kotlin theme={null}
fun RunAnywhere.checkLoraCompatibility(loraPath: String): LoraCompatibilityResult
```

Checks if a LoRA adapter file is compatible with the currently loaded model. Always call this before `loadLoraAdapter()` to avoid runtime errors.

## Adapter Catalog

Register LoRA adapters in a catalog for discovery and management:

```kotlin theme={null}
import com.runanywhere.sdk.public.extensions.LoraAdapterCatalogEntry
import com.runanywhere.sdk.public.extensions.registerLoraAdapter
import com.runanywhere.sdk.public.extensions.loraAdaptersForModel
import com.runanywhere.sdk.public.extensions.allRegisteredLoraAdapters

// Register adapter metadata
RunAnywhere.registerLoraAdapter(LoraAdapterCatalogEntry(
    id = "medical-qa-v1",
    name = "Medical QA Adapter",
    description = "Fine-tuned for medical question answering",
    downloadUrl = "https://huggingface.co/your-org/medical-qa-lora/resolve/main/adapter.gguf",
    filename = "medical-qa.gguf",
    compatibleModelIds = listOf("qwen-0.5b", "qwen-1.5b"),
    fileSize = 25_000_000L,
    defaultScale = 1.0f
))

// Find adapters for a specific model
val adapters = RunAnywhere.loraAdaptersForModel("qwen-0.5b")
adapters.forEach { println("${it.name}: ${it.description}") }

// List all registered adapters
val all = RunAnywhere.allRegisteredLoraAdapters()
```

### LoraAdapterCatalogEntry

| Parameter            | Type           | Description                             |
| -------------------- | -------------- | --------------------------------------- |
| `id`                 | `String`       | Unique identifier                       |
| `name`               | `String`       | Display name                            |
| `description`        | `String`       | What the adapter does                   |
| `downloadUrl`        | `String`       | URL to download the adapter file        |
| `filename`           | `String`       | Local filename                          |
| `compatibleModelIds` | `List<String>` | Base model IDs this adapter works with  |
| `fileSize`           | `Long`         | File size in bytes (default: 0)         |
| `defaultScale`       | `Float`        | Recommended scale factor (default: 1.0) |

## Examples

### Swapping Adapters in a ViewModel

```kotlin theme={null}
class ChatViewModel : ViewModel() {
    private var currentDomain: String? = null

    fun switchDomain(domain: String, adapterPath: String) {
        viewModelScope.launch {
            // Remove previous adapter
            RunAnywhere.clearLoraAdapters()

            // Apply new domain adapter
            RunAnywhere.loadLoraAdapter(LoRAAdapterConfig(
                path = adapterPath,
                scale = 1.0f
            ))

            currentDomain = domain
        }
    }

    fun generate(prompt: String) {
        viewModelScope.launch {
            val result = RunAnywhere.generate(prompt)
            _response.value = result.text
        }
    }
}
```

### Adapter A/B Testing

```kotlin theme={null}
suspend fun compareAdapters(
    prompt: String,
    adapterA: String,
    adapterB: String
): Pair<String, String> {
    // Test adapter A
    RunAnywhere.clearLoraAdapters()
    RunAnywhere.loadLoraAdapter(LoRAAdapterConfig(path = adapterA))
    val resultA = RunAnywhere.generate(prompt)

    // Test adapter B
    RunAnywhere.clearLoraAdapters()
    RunAnywhere.loadLoraAdapter(LoRAAdapterConfig(path = adapterB))
    val resultB = RunAnywhere.generate(prompt)

    return Pair(resultA.text, resultB.text)
}
```

## Error Handling

```kotlin theme={null}
try {
    RunAnywhere.loadLoraAdapter(LoRAAdapterConfig(
        path = "/path/to/adapter.gguf",
        scale = 1.0f
    ))
} catch (e: SDKError) {
    when {
        e.message?.contains("not initialized") == true ->
            println("SDK not initialized")
        e.message?.contains("not loaded") == true ->
            println("Load a base model first")
        else ->
            println("LoRA error: ${e.message}")
    }
}
```

## Performance Tips

<Tip>
  * **Check compatibility first** — always call `checkLoraCompatibility()` before loading to avoid
    errors - **Adapter loading recreates context** — expect \~100-300ms latency when loading/removing
    adapters - **KV cache is cleared** — conversation history is reset when adapters change -
    **Adapters are lightweight** — typically 10-50MB vs. multi-GB base models - **Scale tuning** —
    start with 1.0 and adjust down if the adapter overfits
</Tip>

## Related

<CardGroup cols={2}>
  <Card title="LLM Generation" icon="brain" href="/kotlin/llm/generate">
    Text generation with options
  </Card>

  <Card title="LLM Streaming" icon="bars-staggered" href="/kotlin/llm/stream">
    Streaming text generation
  </Card>

  <Card title="RAG Pipeline" icon="magnifying-glass" href="/kotlin/rag">
    Retrieval-augmented generation
  </Card>

  <Card title="Best Practices" icon="star" href="/kotlin/best-practices">
    Performance optimization
  </Card>
</CardGroup>
