allow loras to be implicitly evicted and loaded based on max_loaded_loras (#11526)
This commit is contained in:
@@ -58,6 +58,9 @@ class Operation:
|
||||
data: Optional[Any]
|
||||
# If the operation is expected to fail, this is the error message to expect
|
||||
expected_error: Optional[str] = None
|
||||
# Because the logic for implicitly evicting LoRA adapters can be complicated, we explicitly
|
||||
# pass in LoRA adapters that should be implicitly evicted here
|
||||
expected_implicit_evictions: Optional[set[str]] = None
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -142,20 +145,20 @@ BASIC_TESTS = [
|
||||
data=create_batch_data(
|
||||
"Nutanix/Meta-Llama-3.1-8B-Instruct_lora_4_alpha_16"
|
||||
),
|
||||
expected_error="not loaded",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.FORWARD,
|
||||
data=create_batch_data("pbevan11/llama-3.1-8b-ocr-correction"),
|
||||
expected_error="not loaded",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.LOAD,
|
||||
data="Nutanix/Meta-Llama-3.1-8B-Instruct_lora_4_alpha_16",
|
||||
expected_error="already loaded",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.LOAD,
|
||||
data="pbevan11/llama-3.1-8b-ocr-correction",
|
||||
expected_error="already loaded",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.FORWARD,
|
||||
@@ -174,7 +177,6 @@ BASIC_TESTS = [
|
||||
Operation(
|
||||
type=OperationType.FORWARD,
|
||||
data=create_batch_data("philschmid/code-llama-3-1-8b-text-to-sql-lora"),
|
||||
expected_error="not loaded",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.FORWARD,
|
||||
@@ -198,12 +200,10 @@ BASIC_TESTS = [
|
||||
data=create_batch_data(
|
||||
"Nutanix/Meta-Llama-3.1-8B-Instruct_lora_4_alpha_16"
|
||||
),
|
||||
expected_error="not loaded",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.FORWARD,
|
||||
data=create_batch_data("pbevan11/llama-3.1-8b-ocr-correction"),
|
||||
expected_error="not loaded",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.FORWARD,
|
||||
@@ -269,7 +269,6 @@ BASIC_TESTS = [
|
||||
Operation(
|
||||
type=OperationType.FORWARD,
|
||||
data=create_batch_data("philschmid/code-llama-3-1-8b-text-to-sql-lora"),
|
||||
expected_error="not loaded",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.FORWARD,
|
||||
@@ -295,12 +294,10 @@ BASIC_TESTS = [
|
||||
data=create_batch_data(
|
||||
"Nutanix/Meta-Llama-3.1-8B-Instruct_lora_4_alpha_16"
|
||||
),
|
||||
expected_error="not loaded",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.FORWARD,
|
||||
data=create_batch_data("pbevan11/llama-3.1-8b-ocr-correction"),
|
||||
expected_error="not loaded",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.FORWARD,
|
||||
@@ -309,14 +306,17 @@ BASIC_TESTS = [
|
||||
Operation(
|
||||
type=OperationType.LOAD,
|
||||
data="philschmid/code-llama-3-1-8b-text-to-sql-lora",
|
||||
expected_error="already loaded",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.LOAD,
|
||||
data="Nutanix/Meta-Llama-3.1-8B-Instruct_lora_4_alpha_16",
|
||||
expected_error="already loaded",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.LOAD,
|
||||
data="pbevan11/llama-3.1-8b-ocr-correction",
|
||||
expected_error="already loaded",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.FORWARD,
|
||||
@@ -364,7 +364,7 @@ TARGET_MODULE_TESTS = [
|
||||
data=create_batch_data(
|
||||
"Nutanix/Meta-Llama-3.1-8B-Instruct_lora_4_alpha_16"
|
||||
),
|
||||
expected_error="not loaded",
|
||||
expected_error="never been loaded",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.LOAD,
|
||||
@@ -404,7 +404,7 @@ TARGET_MODULE_TESTS = [
|
||||
data=create_batch_data(
|
||||
"algoprog/fact-generation-llama-3.1-8b-instruct-lora"
|
||||
),
|
||||
expected_error="not loaded",
|
||||
expected_error="never been loaded",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.LOAD,
|
||||
@@ -444,7 +444,7 @@ TARGET_MODULE_TESTS = [
|
||||
data=create_batch_data(
|
||||
"Nutanix/Meta-Llama-3.1-8B-Instruct_lora_4_alpha_16"
|
||||
),
|
||||
expected_error="not loaded",
|
||||
expected_error="never been loaded",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.LOAD,
|
||||
@@ -485,12 +485,12 @@ MAX_LORA_RANK_TESTS = [
|
||||
Operation(
|
||||
type=OperationType.FORWARD,
|
||||
data=create_batch_data("philschmid/code-llama-3-1-8b-text-to-sql-lora"),
|
||||
expected_error="not loaded",
|
||||
expected_error="never been loaded",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.FORWARD,
|
||||
data=create_batch_data("pbevan11/llama-3.1-8b-ocr-correction"),
|
||||
expected_error="not loaded",
|
||||
expected_error="never been loaded",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.LOAD,
|
||||
@@ -516,7 +516,7 @@ MAX_LORA_RANK_TESTS = [
|
||||
data=create_batch_data(
|
||||
"philschmid/code-llama-3-1-8b-text-to-sql-lora",
|
||||
),
|
||||
expected_error="not loaded",
|
||||
expected_error="never been loaded",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.FORWARD,
|
||||
@@ -553,7 +553,7 @@ MAX_LORA_RANK_TESTS = [
|
||||
Operation(
|
||||
type=OperationType.FORWARD,
|
||||
data=create_batch_data("philschmid/code-llama-3-1-8b-text-to-sql-lora"),
|
||||
expected_error="not loaded",
|
||||
expected_error="never been loaded",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.LOAD,
|
||||
@@ -580,7 +580,7 @@ MAX_LORA_RANK_TESTS = [
|
||||
]
|
||||
MAX_LOADED_LORAS_TESTS = [
|
||||
TestCase(
|
||||
description="Test max_loaded_loras limit",
|
||||
description="Test max_loaded_loras limit as well as implicit eviction and reloading",
|
||||
base="meta-llama/Llama-3.1-8B-Instruct",
|
||||
max_loras_per_batch=2,
|
||||
max_loaded_loras=2,
|
||||
@@ -598,15 +598,143 @@ MAX_LOADED_LORAS_TESTS = [
|
||||
Operation(
|
||||
type=OperationType.LOAD,
|
||||
data="pbevan11/llama-3.1-8b-ocr-correction",
|
||||
expected_error="Maximum number of loaded LoRA adapters",
|
||||
expected_implicit_evictions={
|
||||
"philschmid/code-llama-3-1-8b-text-to-sql-lora"
|
||||
},
|
||||
),
|
||||
# Implicitly load "philschmid/code-llama-3-1-8b-text-to-sql-lora"
|
||||
Operation(
|
||||
type=OperationType.FORWARD,
|
||||
data=create_batch_data(
|
||||
[
|
||||
"Nutanix/Meta-Llama-3.1-8B-Instruct_lora_4_alpha_16",
|
||||
"philschmid/code-llama-3-1-8b-text-to-sql-lora",
|
||||
]
|
||||
),
|
||||
expected_implicit_evictions={"pbevan11/llama-3.1-8b-ocr-correction"},
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.UNLOAD,
|
||||
data="philschmid/code-llama-3-1-8b-text-to-sql-lora",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.FORWARD,
|
||||
data=create_batch_data(
|
||||
[
|
||||
"Nutanix/Meta-Llama-3.1-8B-Instruct_lora_4_alpha_16",
|
||||
]
|
||||
),
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.LOAD,
|
||||
data="philschmid/code-llama-3-1-8b-text-to-sql-lora",
|
||||
),
|
||||
# Implicitly load "pbevan11/llama-3.1-8b-ocr-correction" and make sure that "Nutanix/Meta-Llama-3.1-8B-Instruct_lora_4_alpha_16"
|
||||
# isn't implicitly unloaded even though it is LRU because it is needed for this forward pass
|
||||
Operation(
|
||||
type=OperationType.FORWARD,
|
||||
data=create_batch_data(
|
||||
[
|
||||
"Nutanix/Meta-Llama-3.1-8B-Instruct_lora_4_alpha_16",
|
||||
"pbevan11/llama-3.1-8b-ocr-correction",
|
||||
]
|
||||
),
|
||||
expected_implicit_evictions={
|
||||
"philschmid/code-llama-3-1-8b-text-to-sql-lora"
|
||||
},
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.UNLOAD,
|
||||
data="Nutanix/Meta-Llama-3.1-8B-Instruct_lora_4_alpha_16",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.LOAD,
|
||||
data="algoprog/fact-generation-llama-3.1-8b-instruct-lora",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.FORWARD,
|
||||
data=create_batch_data(
|
||||
[
|
||||
"Nutanix/Meta-Llama-3.1-8B-Instruct_lora_4_alpha_16",
|
||||
"philschmid/code-llama-3-1-8b-text-to-sql-lora",
|
||||
]
|
||||
),
|
||||
expected_implicit_evictions={
|
||||
"pbevan11/llama-3.1-8b-ocr-correction",
|
||||
"algoprog/fact-generation-llama-3.1-8b-instruct-lora",
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
TestCase(
|
||||
description="Test implicit eviction and reloading with pinned LoRA adapters",
|
||||
base="meta-llama/Llama-3.1-8B-Instruct",
|
||||
max_loras_per_batch=2,
|
||||
max_loaded_loras=2,
|
||||
all_adapters=[
|
||||
"philschmid/code-llama-3-1-8b-text-to-sql-lora",
|
||||
"Nutanix/Meta-Llama-3.1-8B-Instruct_lora_4_alpha_16",
|
||||
"pbevan11/llama-3.1-8b-ocr-correction",
|
||||
],
|
||||
initial_adapters=[
|
||||
{
|
||||
"lora_name": "philschmid/code-llama-3-1-8b-text-to-sql-lora",
|
||||
"lora_path": "philschmid/code-llama-3-1-8b-text-to-sql-lora",
|
||||
"pinned": True,
|
||||
}
|
||||
],
|
||||
op_sequence=[
|
||||
Operation(
|
||||
type=OperationType.LOAD,
|
||||
data="Nutanix/Meta-Llama-3.1-8B-Instruct_lora_4_alpha_16",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.LOAD,
|
||||
data="pbevan11/llama-3.1-8b-ocr-correction",
|
||||
expected_implicit_evictions={
|
||||
"Nutanix/Meta-Llama-3.1-8B-Instruct_lora_4_alpha_16"
|
||||
},
|
||||
),
|
||||
# Implicitly load "Nutanix/Meta-Llama-3.1-8B-Instruct_lora_4_alpha_16"
|
||||
Operation(
|
||||
type=OperationType.FORWARD,
|
||||
data=create_batch_data(
|
||||
[
|
||||
"philschmid/code-llama-3-1-8b-text-to-sql-lora",
|
||||
"Nutanix/Meta-Llama-3.1-8B-Instruct_lora_4_alpha_16",
|
||||
]
|
||||
),
|
||||
expected_implicit_evictions={"pbevan11/llama-3.1-8b-ocr-correction"},
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.LOAD,
|
||||
data={
|
||||
"lora_name": "pbevan11/llama-3.1-8b-ocr-correction",
|
||||
"lora_path": "pbevan11/llama-3.1-8b-ocr-correction",
|
||||
"pinned": True,
|
||||
},
|
||||
expected_error="unpin some adapters",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.UNLOAD,
|
||||
data="philschmid/code-llama-3-1-8b-text-to-sql-lora",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.LOAD,
|
||||
data={
|
||||
"lora_name": "pbevan11/llama-3.1-8b-ocr-correction",
|
||||
"lora_path": "pbevan11/llama-3.1-8b-ocr-correction",
|
||||
"pinned": True,
|
||||
},
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.FORWARD,
|
||||
data=create_batch_data(
|
||||
[
|
||||
"Nutanix/Meta-Llama-3.1-8B-Instruct_lora_4_alpha_16",
|
||||
"pbevan11/llama-3.1-8b-ocr-correction",
|
||||
]
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -640,7 +768,7 @@ EVICTION_TESTS = [
|
||||
"lora_path": "Nutanix/Meta-Llama-3.1-8B-Instruct_lora_4_alpha_16",
|
||||
"pinned": True,
|
||||
},
|
||||
expected_error="starvation",
|
||||
expected_error="unpin some adapters",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.LOAD,
|
||||
@@ -681,7 +809,7 @@ EVICTION_TESTS = [
|
||||
"lora_path": "philschmid/code-llama-3-1-8b-text-to-sql-lora",
|
||||
"pinned": True,
|
||||
},
|
||||
expected_error="starvation",
|
||||
expected_error="unpin some adapters",
|
||||
),
|
||||
Operation(
|
||||
type=OperationType.LOAD,
|
||||
@@ -805,6 +933,7 @@ class LoRAUpdateTestSessionBase:
|
||||
lora_name: str,
|
||||
lora_path: Optional[str] = None,
|
||||
expected_error: Optional[str] = None,
|
||||
expected_implicit_evictions: Optional[set[str]] = None,
|
||||
):
|
||||
"""
|
||||
Load a LoRA adapter by name and path.
|
||||
@@ -823,6 +952,7 @@ class LoRAUpdateTestSessionBase:
|
||||
lora_paths: List[str],
|
||||
max_new_tokens: int = 32,
|
||||
expected_error: Optional[str] = None,
|
||||
expected_implicit_evictions: Optional[set[str]] = None,
|
||||
):
|
||||
"""
|
||||
Perform a batch forward pass with the current set of loaded LoRA adapters.
|
||||
@@ -869,6 +999,7 @@ class LoRAUpdateEngineTestSession(LoRAUpdateTestSessionBase):
|
||||
lora_path: Optional[str] = None,
|
||||
expected_error: Optional[str] = None,
|
||||
pinned: bool = False,
|
||||
expected_implicit_evictions: Optional[set[str]] = None,
|
||||
):
|
||||
"""
|
||||
Load a LoRA adapter by name and path.
|
||||
@@ -893,6 +1024,9 @@ class LoRAUpdateEngineTestSession(LoRAUpdateTestSessionBase):
|
||||
print(f"Received error as expected: {response.error_message}")
|
||||
else:
|
||||
self.expected_adapters.add(lora_name)
|
||||
if expected_implicit_evictions is not None:
|
||||
self.expected_adapters -= expected_implicit_evictions
|
||||
|
||||
self.testcase.assertTrue(
|
||||
response.success,
|
||||
f"Failed to load LoRA adapter {lora_name}: {response.error_message}",
|
||||
@@ -933,6 +1067,7 @@ class LoRAUpdateEngineTestSession(LoRAUpdateTestSessionBase):
|
||||
lora_paths: List[str],
|
||||
max_new_tokens: int = 32,
|
||||
expected_error: Optional[str] = None,
|
||||
expected_implicit_evictions: Optional[set[str]] = None,
|
||||
):
|
||||
"""
|
||||
Perform a batch forward pass with the current set of loaded LoRA adapters.
|
||||
@@ -964,6 +1099,13 @@ class LoRAUpdateEngineTestSession(LoRAUpdateTestSessionBase):
|
||||
output = response.output_strs
|
||||
print(f"output_strs: {output}")
|
||||
|
||||
self.expected_adapters.update(
|
||||
[lora_path for lora_path in lora_paths if lora_path is not None]
|
||||
)
|
||||
|
||||
if expected_implicit_evictions is not None:
|
||||
self.expected_adapters -= expected_implicit_evictions
|
||||
|
||||
return output
|
||||
|
||||
|
||||
@@ -1026,6 +1168,7 @@ class LoRAUpdateServerTestSession(LoRAUpdateTestSessionBase):
|
||||
lora_path: Optional[str] = None,
|
||||
expected_error: Optional[str] = None,
|
||||
pinned: bool = False,
|
||||
expected_implicit_evictions: Optional[set[str]] = None,
|
||||
):
|
||||
"""
|
||||
Load a LoRA adapter by name and path.
|
||||
@@ -1051,6 +1194,9 @@ class LoRAUpdateServerTestSession(LoRAUpdateTestSessionBase):
|
||||
print(f"Received error as expected: {response.text}")
|
||||
else:
|
||||
self.expected_adapters.add(lora_name)
|
||||
if expected_implicit_evictions is not None:
|
||||
self.expected_adapters -= expected_implicit_evictions
|
||||
|
||||
self.testcase.assertTrue(
|
||||
response.ok, f"Failed to load LoRA adapter {lora_name}: {response.text}"
|
||||
)
|
||||
@@ -1072,6 +1218,7 @@ class LoRAUpdateServerTestSession(LoRAUpdateTestSessionBase):
|
||||
DEFAULT_URL_FOR_TEST + "/unload_lora_adapter",
|
||||
json={"lora_name": lora_name},
|
||||
)
|
||||
|
||||
self.testcase.assertTrue(
|
||||
response.ok, f"Failed to unload LoRA adapter {lora_name}: {response.text}"
|
||||
)
|
||||
@@ -1090,6 +1237,7 @@ class LoRAUpdateServerTestSession(LoRAUpdateTestSessionBase):
|
||||
lora_paths: List[str],
|
||||
max_new_tokens: int = 32,
|
||||
expected_error: Optional[str] = None,
|
||||
expected_implicit_evictions: Optional[set[str]] = None,
|
||||
):
|
||||
"""
|
||||
Perform a batch forward pass with the current set of loaded LoRA adapters.
|
||||
@@ -1131,6 +1279,14 @@ class LoRAUpdateServerTestSession(LoRAUpdateTestSessionBase):
|
||||
f"Expected {len(prompts)} outputs, but got {len(output)}",
|
||||
)
|
||||
print(f"output_strs: {output}")
|
||||
|
||||
self.expected_adapters.update(
|
||||
[lora_path for lora_path in lora_paths if lora_path is not None]
|
||||
)
|
||||
|
||||
if expected_implicit_evictions is not None:
|
||||
self.expected_adapters -= expected_implicit_evictions
|
||||
|
||||
return output
|
||||
|
||||
|
||||
@@ -1192,6 +1348,7 @@ class TestLoRADynamicUpdate(CustomTestCase):
|
||||
op_type = op.type
|
||||
data = op.data
|
||||
expected_error = op.expected_error
|
||||
expected_implicit_evictions = op.expected_implicit_evictions
|
||||
print("-" * 100)
|
||||
print(
|
||||
f"Running operation: {op_type} --- data: {data} --- mode: {mode} ---"
|
||||
@@ -1208,6 +1365,7 @@ class TestLoRADynamicUpdate(CustomTestCase):
|
||||
|
||||
result = session.load_lora_adapter(
|
||||
expected_error=expected_error,
|
||||
expected_implicit_evictions=expected_implicit_evictions,
|
||||
**adapter_info,
|
||||
)
|
||||
elif op_type == OperationType.UNLOAD:
|
||||
@@ -1221,6 +1379,7 @@ class TestLoRADynamicUpdate(CustomTestCase):
|
||||
lora_paths=list(adapters),
|
||||
max_new_tokens=max_new_tokens,
|
||||
expected_error=expected_error,
|
||||
expected_implicit_evictions=expected_implicit_evictions,
|
||||
)
|
||||
if not expected_error:
|
||||
forward_outputs.append(result)
|
||||
|
||||
Reference in New Issue
Block a user