A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 14, 05:30 UTC
Move `LoRAConfig` from `config/__init__.py` to `config/lora.py` (#24644)
Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
Harry Mellor committed
Sep 11, 2025 at 12:01 UTC
5f5271f1ee2ef281ed8ecc66b126aa34964e797d
25 files changed
+167
-137
tests/core/test_scheduler.py
+2
-1
@@ -10,7 +10,8 @@ import pytest # noqa
10
import torch
11
from torch import Use # noqa
12
13
-from vllm.config import CacheConfig, LoRAConfig, SchedulerConfig
13
+from vllm.config import CacheConfig, SchedulerConfig
14
+from vllm.config.lora import LoRAConfig
15
from vllm.core.interfaces import AllocStatus
16
from vllm.core.scheduler import Scheduler, SchedulingBudget
17
from vllm.lora.request import LoRARequest
tests/lora/test_layers.py
+1
-1
@@ -11,7 +11,7 @@ import pytest
11
import torch
12
import torch.nn.functional as F
13
14
-from vllm.config import LoRAConfig
14
+from vllm.config.lora import LoRAConfig
15
# yapf conflicts with isort for this block
16
# yapf: disable
17
from vllm.lora.layers import (BaseLayerWithLoRA, ColumnParallelLinearWithLoRA,
tests/lora/test_lora_allowed_token_ids.py
+2
-2
@@ -3,8 +3,8 @@
3
4
import pytest
5
6
-from vllm.config import (CacheConfig, DeviceConfig, LoRAConfig, ModelConfig,
7
- VllmConfig)
6
+from vllm.config import CacheConfig, DeviceConfig, ModelConfig, VllmConfig
7
+from vllm.config.lora import LoRAConfig
8
from vllm.lora.request import LoRARequest
9
from vllm.sampling_params import SamplingParams
10
from vllm.transformers_utils.tokenizer_group import init_tokenizer_from_configs
tests/lora/test_lora_manager.py
+1
-1
@@ -8,7 +8,7 @@ import torch
8
from safetensors.torch import load_file
9
from torch import nn
10
11
-from vllm.config import LoRAConfig
11
+from vllm.config.lora import LoRAConfig
12
from vllm.lora.layers import (ColumnParallelLinearWithLoRA,
13
MergedColumnParallelLinearWithLoRA,
14
RowParallelLinearWithLoRA)
tests/lora/test_peft_helper.py
+1
-1
@@ -7,7 +7,7 @@ import shutil
7
8
import pytest
9
10
-from vllm.config import LoRAConfig
10
+from vllm.config.lora import LoRAConfig
11
from vllm.lora.peft_helper import PEFTHelper
12
13
ERROR_CASES = [
tests/lora/test_worker.py
+2
-1
@@ -6,9 +6,10 @@ import random
6
import tempfile
7
from unittest.mock import patch
8
9
-from vllm.config import (CacheConfig, DeviceConfig, LoRAConfig, ModelConfig,
9
+from vllm.config import (CacheConfig, DeviceConfig, ModelConfig,
10
ParallelConfig, SchedulerConfig, VllmConfig)
11
from vllm.config.load import LoadConfig
12
+from vllm.config.lora import LoRAConfig
13
from vllm.lora.models import LoRAMapping
14
from vllm.lora.request import LoRARequest
15
from vllm.v1.worker.gpu_worker import Worker
vllm/config/__init__.py
+1
-110
@@ -36,6 +36,7 @@ from vllm.config.compilation import (CompilationConfig, CompilationLevel,
36
from vllm.config.kv_events import KVEventsConfig
37
from vllm.config.kv_transfer import KVTransferConfig
38
from vllm.config.load import LoadConfig
39
+from vllm.config.lora import LoRAConfig
40
from vllm.config.parallel import (DistributedExecutorBackend, EPLBConfig,
41
ParallelConfig)
42
from vllm.config.scheduler import SchedulerConfig, SchedulerPolicy
@@ -2400,116 +2401,6 @@ class SpeculativeConfig:
2401
return f"SpeculativeConfig({method=}, {model=}, {num_spec_tokens=})"
2402
2403
2403
-LoRADType = Literal["auto", "float16", "bfloat16"]
2404
-
2405
-
2406
-@config
2407
-@dataclass(config=ConfigDict(arbitrary_types_allowed=True))
2408
-class LoRAConfig:
2409
- """Configuration for LoRA."""
2410
-
2411
- max_lora_rank: int = 16
2412
- """Max LoRA rank."""
2413
- max_loras: int = 1
2414
- """Max number of LoRAs in a single batch."""
2415
- fully_sharded_loras: bool = False
2416
- """By default, only half of the LoRA computation is sharded with tensor
2417
- parallelism. Enabling this will use the fully sharded layers. At high
2418
- sequence length, max rank or tensor parallel size, this is likely faster.
2419
- """
2420
- max_cpu_loras: Optional[int] = None
2421
- """Maximum number of LoRAs to store in CPU memory. Must be >= than
2422
- `max_loras`."""
2423
- lora_dtype: Union[torch.dtype, LoRADType] = "auto"
2424
- """Data type for LoRA. If auto, will default to base model dtype."""
2425
- lora_extra_vocab_size: int = 256
2426
- """(Deprecated) Maximum size of extra vocabulary that can be present in a
2427
- LoRA adapter. Will be removed in v0.12.0."""
2428
- lora_vocab_padding_size: ClassVar[int] = current_platform\
2429
- .get_lora_vocab_padding_size()
2430
- default_mm_loras: Optional[dict[str, str]] = None
2431
- """Dictionary mapping specific modalities to LoRA model paths; this field
2432
- is only applicable to multimodal models and should be leveraged when a
2433
- model always expects a LoRA to be active when a given modality is present.
2434
- Note that currently, if a request provides multiple additional
2435
- modalities, each of which have their own LoRA, we do NOT apply
2436
- default_mm_loras because we currently only support one lora adapter
2437
- per prompt. When run in offline mode, the lora IDs for n modalities
2438
- will be automatically assigned to 1-n with the names of the modalities
2439
- in alphabetic order."""
2440
- bias_enabled: bool = False
2441
- """[DEPRECATED] Enable bias for LoRA adapters. This option will be
2442
- removed in v0.12.0."""
2443
-
2444
- def compute_hash(self) -> str:
2445
- """
2446
- WARNING: Whenever a new field is added to this config,
2447
- ensure that it is included in the factors list if
2448
- it affects the computation graph.
2449
-
2450
- Provide a hash that uniquely identifies all the configs
2451
- that affect the structure of the computation
2452
- graph from input ids/embeddings to the final hidden states,
2453
- excluding anything before input ids/embeddings and after
2454
- the final hidden states.
2455
- """
2456
- factors: list[Any] = []
2457
- factors.append(self.max_lora_rank)
2458
- factors.append(self.max_loras)
2459
- factors.append(self.fully_sharded_loras)
2460
- factors.append(self.lora_dtype)
2461
- factors.append(self.lora_extra_vocab_size)
2462
- factors.append(self.lora_vocab_padding_size)
2463
- factors.append(self.bias_enabled)
2464
- hash_str = hashlib.md5(str(factors).encode(),
2465
- usedforsecurity=False).hexdigest()
2466
- return hash_str
2467
-
2468
- def __post_init__(self):
2469
- # Deprecation warning for lora_extra_vocab_size
2470
- logger.warning(
2471
- "`lora_extra_vocab_size` is deprecated and will be removed "
2472
- "in v0.12.0. Additional vocabulary support for "
2473
- "LoRA adapters is being phased out.")
2474
-
2475
- # Deprecation warning for enable_lora_bias
2476
- if self.bias_enabled:
2477
- logger.warning("`enable_lora_bias` is deprecated "
2478
- "and will be removed in v0.12.0.")
2479
-
2480
- # Setting the maximum rank to 512 should be able to satisfy the vast
2481
- # majority of applications.
2482
- possible_max_ranks = (8, 16, 32, 64, 128, 256, 320, 512)
2483
- possible_lora_extra_vocab_size = (256, 512)
2484
- if self.max_lora_rank not in possible_max_ranks:
2485
- raise ValueError(
2486
- f"max_lora_rank ({self.max_lora_rank}) must be one of "
2487
- f"{possible_max_ranks}.")
2488
- if self.lora_extra_vocab_size not in possible_lora_extra_vocab_size:
2489
- raise ValueError(
2490
- f"lora_extra_vocab_size ({self.lora_extra_vocab_size}) "
2491
- f"must be one of {possible_lora_extra_vocab_size}.")
2492
- if self.max_loras < 1:
2493
- raise ValueError(f"max_loras ({self.max_loras}) must be >= 1.")
2494
- if self.max_cpu_loras is None:
2495
- self.max_cpu_loras = self.max_loras
2496
- elif self.max_cpu_loras < self.max_loras:
2497
- raise ValueError(
2498
- f"max_cpu_loras ({self.max_cpu_loras}) must be >= "
2499
- f"max_loras ({self.max_loras})")
2500
-
2501
- def verify_with_cache_config(self, cache_config: CacheConfig):
2502
- if cache_config.cpu_offload_gb > 0 and not envs.VLLM_USE_V1:
2503
- raise ValueError(
2504
- "V0 LoRA does not support CPU offload, please use V1.")
2505
-
2506
- def verify_with_model_config(self, model_config: ModelConfig):
2507
- if self.lora_dtype in (None, "auto"):
2508
- self.lora_dtype = model_config.dtype
2509
- elif isinstance(self.lora_dtype, str):
2510
- self.lora_dtype = getattr(torch, self.lora_dtype)
2511
-
2512
-
2404
@config
2405
@dataclass
2406
class MultiModalConfig:
vllm/config/lora.py
new
+132
@@ -0,0 +1,132 @@
1
+# SPDX-License-Identifier: Apache-2.0
2
+# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
+
4
+import hashlib
5
+from typing import TYPE_CHECKING, Any, ClassVar, Literal, Optional, Union
6
+
7
+import torch
8
+from pydantic import ConfigDict
9
+from pydantic.dataclasses import dataclass
10
+
11
+import vllm.envs as envs
12
+from vllm.config.utils import config
13
+from vllm.logger import init_logger
14
+from vllm.platforms import current_platform
15
+
16
+if TYPE_CHECKING:
17
+ from vllm.config import ModelConfig
18
+ from vllm.config.cache import CacheConfig
19
+else:
20
+ ModelConfig = Any
21
+ CacheConfig = Any
22
+
23
+logger = init_logger(__name__)
24
+
25
+LoRADType = Literal["auto", "float16", "bfloat16"]
26
+
27
+
28
+@config
29
+@dataclass(config=ConfigDict(arbitrary_types_allowed=True))
30
+class LoRAConfig:
31
+ """Configuration for LoRA."""
32
+
33
+ max_lora_rank: int = 16
34
+ """Max LoRA rank."""
35
+ max_loras: int = 1
36
+ """Max number of LoRAs in a single batch."""
37
+ fully_sharded_loras: bool = False
38
+ """By default, only half of the LoRA computation is sharded with tensor
39
+ parallelism. Enabling this will use the fully sharded layers. At high
40
+ sequence length, max rank or tensor parallel size, this is likely faster.
41
+ """
42
+ max_cpu_loras: Optional[int] = None
43
+ """Maximum number of LoRAs to store in CPU memory. Must be >= than
44
+ `max_loras`."""
45
+ lora_dtype: Union[torch.dtype, LoRADType] = "auto"
46
+ """Data type for LoRA. If auto, will default to base model dtype."""
47
+ lora_extra_vocab_size: int = 256
48
+ """(Deprecated) Maximum size of extra vocabulary that can be present in a
49
+ LoRA adapter. Will be removed in v0.12.0."""
50
+ lora_vocab_padding_size: ClassVar[int] = current_platform\
51
+ .get_lora_vocab_padding_size()
52
+ default_mm_loras: Optional[dict[str, str]] = None
53
+ """Dictionary mapping specific modalities to LoRA model paths; this field
54
+ is only applicable to multimodal models and should be leveraged when a
55
+ model always expects a LoRA to be active when a given modality is present.
56
+ Note that currently, if a request provides multiple additional
57
+ modalities, each of which have their own LoRA, we do NOT apply
58
+ default_mm_loras because we currently only support one lora adapter
59
+ per prompt. When run in offline mode, the lora IDs for n modalities
60
+ will be automatically assigned to 1-n with the names of the modalities
61
+ in alphabetic order."""
62
+ bias_enabled: bool = False
63
+ """[DEPRECATED] Enable bias for LoRA adapters. This option will be
64
+ removed in v0.12.0."""
65
+
66
+ def compute_hash(self) -> str:
67
+ """
68
+ WARNING: Whenever a new field is added to this config,
69
+ ensure that it is included in the factors list if
70
+ it affects the computation graph.
71
+
72
+ Provide a hash that uniquely identifies all the configs
73
+ that affect the structure of the computation
74
+ graph from input ids/embeddings to the final hidden states,
75
+ excluding anything before input ids/embeddings and after
76
+ the final hidden states.
77
+ """
78
+ factors: list[Any] = []
79
+ factors.append(self.max_lora_rank)
80
+ factors.append(self.max_loras)
81
+ factors.append(self.fully_sharded_loras)
82
+ factors.append(self.lora_dtype)
83
+ factors.append(self.lora_extra_vocab_size)
84
+ factors.append(self.lora_vocab_padding_size)
85
+ factors.append(self.bias_enabled)
86
+ hash_str = hashlib.md5(str(factors).encode(),
87
+ usedforsecurity=False).hexdigest()
88
+ return hash_str
89
+
90
+ def __post_init__(self):
91
+ # Deprecation warning for lora_extra_vocab_size
92
+ logger.warning(
93
+ "`lora_extra_vocab_size` is deprecated and will be removed "
94
+ "in v0.12.0. Additional vocabulary support for "
95
+ "LoRA adapters is being phased out.")
96
+
97
+ # Deprecation warning for enable_lora_bias
98
+ if self.bias_enabled:
99
+ logger.warning("`enable_lora_bias` is deprecated "
100
+ "and will be removed in v0.12.0.")
101
+
102
+ # Setting the maximum rank to 512 should be able to satisfy the vast
103
+ # majority of applications.
104
+ possible_max_ranks = (8, 16, 32, 64, 128, 256, 320, 512)
105
+ possible_lora_extra_vocab_size = (256, 512)
106
+ if self.max_lora_rank not in possible_max_ranks:
107
+ raise ValueError(
108
+ f"max_lora_rank ({self.max_lora_rank}) must be one of "
109
+ f"{possible_max_ranks}.")
110
+ if self.lora_extra_vocab_size not in possible_lora_extra_vocab_size:
111
+ raise ValueError(
112
+ f"lora_extra_vocab_size ({self.lora_extra_vocab_size}) "
113
+ f"must be one of {possible_lora_extra_vocab_size}.")
114
+ if self.max_loras < 1:
115
+ raise ValueError(f"max_loras ({self.max_loras}) must be >= 1.")
116
+ if self.max_cpu_loras is None:
117
+ self.max_cpu_loras = self.max_loras
118
+ elif self.max_cpu_loras < self.max_loras:
119
+ raise ValueError(
120
+ f"max_cpu_loras ({self.max_cpu_loras}) must be >= "
121
+ f"max_loras ({self.max_loras})")
122
+
123
+ def verify_with_cache_config(self, cache_config: CacheConfig):
124
+ if cache_config.cpu_offload_gb > 0 and not envs.VLLM_USE_V1:
125
+ raise ValueError(
126
+ "V0 LoRA does not support CPU offload, please use V1.")
127
+
128
+ def verify_with_model_config(self, model_config: ModelConfig):
129
+ if self.lora_dtype in (None, "auto"):
130
+ self.lora_dtype = model_config.dtype
131
+ elif isinstance(self.lora_dtype, str):
132
+ self.lora_dtype = getattr(torch, self.lora_dtype)
vllm/core/scheduler.py
+2
-1
@@ -11,7 +11,8 @@ from typing import Callable, Deque, Dict, Iterable, List, Optional
11
from typing import Sequence as GenericSequence
12
from typing import Set, Tuple, Union
13
14
-from vllm.config import CacheConfig, LoRAConfig, SchedulerConfig
14
+from vllm.config import CacheConfig, SchedulerConfig
15
+from vllm.config.lora import LoRAConfig
16
from vllm.core.interfaces import AllocStatus, BlockSpaceManager
17
from vllm.logger import init_logger
18
from vllm.lora.request import LoRARequest
vllm/engine/async_llm_engine.py
+3
-2
@@ -10,8 +10,9 @@ from typing import (Any, AsyncGenerator, Callable, Dict, Iterable, List,
10
from weakref import ReferenceType
11
12
import vllm.envs as envs
13
-from vllm.config import (DecodingConfig, LoRAConfig, ModelConfig,
14
- ParallelConfig, SchedulerConfig, VllmConfig)
13
+from vllm.config import (DecodingConfig, ModelConfig, ParallelConfig,
14
+ SchedulerConfig, VllmConfig)
15
+from vllm.config.lora import LoRAConfig
16
from vllm.core.scheduler import SchedulerOutputs
17
from vllm.engine.arg_utils import AsyncEngineArgs
18
from vllm.engine.async_timeout import asyncio_timeout
vllm/engine/llm_engine.py
+3
-3
@@ -16,9 +16,9 @@ import torch
16
from typing_extensions import TypeVar
17
18
import vllm.envs as envs
19
-from vllm.config import (DecodingConfig, LoRAConfig, ModelConfig,
20
- ObservabilityConfig, ParallelConfig, SchedulerConfig,
21
- VllmConfig)
19
+from vllm.config import (DecodingConfig, ModelConfig, ObservabilityConfig,
20
+ ParallelConfig, SchedulerConfig, VllmConfig)
21
+from vllm.config.lora import LoRAConfig
22
from vllm.core.scheduler import ScheduledSequenceGroup, SchedulerOutputs
23
from vllm.engine.arg_utils import EngineArgs
24
from vllm.engine.metrics_types import StatLoggerBase, Stats
vllm/lora/layers/base.py
+1
-1
@@ -7,7 +7,7 @@ import torch
7
import torch.nn as nn
8
from transformers import PretrainedConfig
9
10
-from vllm.config import LoRAConfig
10
+from vllm.config.lora import LoRAConfig
11
12
if TYPE_CHECKING:
13
from vllm.lora.punica_wrapper import PunicaWrapperBase
vllm/lora/layers/base_linear.py
+1
-1
@@ -6,7 +6,7 @@ from typing import Optional, cast
6
import torch
7
from transformers import PretrainedConfig
8
9
-from vllm.config import LoRAConfig
9
+from vllm.config.lora import LoRAConfig
10
from vllm.distributed.utils import divide
11
# yapf: disable
12
from vllm.model_executor.layers.linear import (ColumnParallelLinear,
vllm/lora/layers/column_parallel_linear.py
+1
-1
@@ -7,7 +7,7 @@ import torch
7
import torch.nn as nn
8
from transformers import PretrainedConfig
9
10
-from vllm.config import LoRAConfig
10
+from vllm.config.lora import LoRAConfig
11
from vllm.distributed import (get_tensor_model_parallel_rank,
12
get_tensor_model_parallel_world_size,
13
tensor_model_parallel_all_gather)
vllm/lora/layers/logits_processor.py
+1
-1
@@ -8,7 +8,7 @@ import torch
8
import torch.nn as nn
9
from transformers import PretrainedConfig
10
11
-from vllm.config import LoRAConfig
11
+from vllm.config.lora import LoRAConfig
12
from vllm.distributed import (get_tensor_model_parallel_rank,
13
get_tensor_model_parallel_world_size)
14
from vllm.model_executor.layers.logits_processor import LogitsProcessor
vllm/lora/layers/replicated_linear.py
+1
-1
@@ -7,7 +7,7 @@ import torch
7
import torch.nn as nn
8
from transformers import PretrainedConfig
9
10
-from vllm.config import LoRAConfig
10
+from vllm.config.lora import LoRAConfig
11
from vllm.model_executor.layers.linear import ReplicatedLinear
12
13
from .base_linear import BaseLinearLayerWithLoRA
vllm/lora/layers/row_parallel_linear.py
+1
-1
@@ -7,7 +7,7 @@ import torch
7
import torch.nn as nn
8
from transformers import PretrainedConfig
9
10
-from vllm.config import LoRAConfig
10
+from vllm.config.lora import LoRAConfig
11
from vllm.distributed import (get_tensor_model_parallel_rank,
12
get_tensor_model_parallel_world_size,
13
split_tensor_along_last_dim,
vllm/lora/layers/vocal_parallel_embedding.py
+1
-1
@@ -8,7 +8,7 @@ import torch.nn as nn
8
import torch.nn.functional as F
9
from transformers import PretrainedConfig
10
11
-from vllm.config import LoRAConfig
11
+from vllm.config.lora import LoRAConfig
12
from vllm.model_executor.layers.vocab_parallel_embedding import (
13
VocabParallelEmbedding)
14
from vllm.platforms import current_platform
vllm/lora/models.py
+1
-1
@@ -16,7 +16,7 @@ from vllm.adapter_commons.models import (AdapterLRUCache, AdapterModel,
16
from vllm.adapter_commons.utils import (add_adapter, deactivate_adapter,
17
get_adapter, list_adapters,
18
remove_adapter, set_adapter_mapping)
19
-from vllm.config import LoRAConfig
19
+from vllm.config.lora import LoRAConfig
20
from vllm.logger import init_logger
21
from vllm.lora.layers import BaseLayerWithLoRA, LoRAMapping
22
from vllm.lora.lora import LoRALayerWeights, PackedLoRALayerWeights
vllm/lora/peft_helper.py
+1
-1
@@ -9,7 +9,7 @@ import os
9
from dataclasses import MISSING, dataclass, field, fields
10
from typing import Literal, Optional, Union
11
12
-from vllm.config import LoRAConfig
12
+from vllm.config.lora import LoRAConfig
13
from vllm.logger import init_logger
14
from vllm.model_executor.model_loader.tensorizer import TensorizerConfig
15
vllm/lora/utils.py
+1
-1
@@ -11,7 +11,7 @@ from huggingface_hub.utils import (EntryNotFoundError, HfHubHTTPError,
11
from torch import nn
12
from transformers import PretrainedConfig
13
14
-from vllm.config import LoRAConfig
14
+from vllm.config.lora import LoRAConfig
15
from vllm.logger import init_logger
16
# being imported for _all_lora_classes below
17
# yapf conflicts with isort for this block
vllm/lora/worker_manager.py
+1
-1
@@ -11,7 +11,7 @@ from vllm.adapter_commons.utils import (add_adapter_worker,
11
list_adapters_worker,
12
set_active_adapters_worker)
13
from vllm.adapter_commons.worker_manager import AbstractWorkerManager
14
-from vllm.config import LoRAConfig
14
+from vllm.config.lora import LoRAConfig
15
from vllm.logger import init_logger
16
from vllm.lora.models import (LoRAModel, LoRAModelManager,
17
LRUCacheLoRAModelManager, create_lora_manager)
vllm/model_executor/models/bart.py
+2
-1
@@ -29,7 +29,8 @@ from transformers import BartConfig
29
from transformers.utils import logging
30
31
from vllm.attention import Attention, AttentionType
32
-from vllm.config import CacheConfig, LoRAConfig, VllmConfig
32
+from vllm.config import CacheConfig, VllmConfig
33
+from vllm.config.lora import LoRAConfig
34
from vllm.distributed import get_tensor_model_parallel_world_size
35
from vllm.model_executor.layers.activation import get_act_fn
36
from vllm.model_executor.layers.linear import (ColumnParallelLinear,
vllm/transformers_utils/tokenizer_group.py
+2
-1
@@ -5,7 +5,8 @@ from typing import Optional
5
6
from typing_extensions import assert_never
7
8
-from vllm.config import LoRAConfig, ModelConfig, SchedulerConfig
8
+from vllm.config import ModelConfig, SchedulerConfig
9
+from vllm.config.lora import LoRAConfig
10
from vllm.lora.request import LoRARequest
11
from vllm.transformers_utils.tokenizer import (AnyTokenizer, encode_tokens,
12
get_lora_tokenizer,
vllm/v1/worker/lora_model_runner_mixin.py
+2
-1
@@ -11,7 +11,8 @@ import numpy as np
11
import torch
12
import torch.nn as nn
13
14
-from vllm.config import LoRAConfig, ModelConfig, SchedulerConfig
14
+from vllm.config import ModelConfig, SchedulerConfig
15
+from vllm.config.lora import LoRAConfig
16
from vllm.logger import init_logger
17
from vllm.lora.layers import LoRAMapping
18
from vllm.lora.request import LoRARequest