[LoRA] Use deterministic lora_id for --lora-paths so multi-node ranks agree (#24555)

Co-authored-by: gh1595 <278903827+gh1595@users.noreply.github.com>
This commit is contained in:
Yanbin Jiang
2026-05-06 22:20:15 -07:00
committed by GitHub
co-authored by gh1595
parent d363315de9
commit f0368a6666
2 changed files with 28 additions and 4 deletions
+11 -1
View File
@@ -17,7 +17,7 @@ import asyncio
from collections import OrderedDict from collections import OrderedDict
from dataclasses import dataclass, field, fields from dataclasses import dataclass, field, fields
from typing import Dict, List, Optional, Union from typing import Dict, List, Optional, Union
from uuid import uuid4 from uuid import NAMESPACE_URL, uuid4, uuid5
from sglang.srt.utils import ConcurrentCounter from sglang.srt.utils import ConcurrentCounter
from sglang.srt.utils.aio_rwlock import RWLock from sglang.srt.utils.aio_rwlock import RWLock
@@ -42,6 +42,16 @@ class LoRARef:
if self.lora_id is None: if self.lora_id is None:
raise ValueError("lora_id cannot be None") raise ValueError("lora_id cannot be None")
@staticmethod
def deterministic_id(lora_name: str, lora_path: str) -> str:
"""Stable ``lora_id`` for ``--lora-paths`` adapters.
Each node in a multi-node launch parses ``--lora-paths`` independently;
``uuid4`` would mint a different id per node for the same adapter,
breaking cross-node lookups when the master broadcasts a request id.
"""
return uuid5(NAMESPACE_URL, f"{lora_name}\0{lora_path}").hex
def __str__(self) -> str: def __str__(self) -> str:
parts = [ parts = [
f"{f.name}={value}" f"{f.name}={value}"
+17 -3
View File
@@ -7011,17 +7011,26 @@ class ServerArgs:
if "=" in lora_path: if "=" in lora_path:
name, path = lora_path.split("=", 1) name, path = lora_path.split("=", 1)
lora_ref = LoRARef( lora_ref = LoRARef(
lora_name=name, lora_path=path, pinned=False lora_id=LoRARef.deterministic_id(name, path),
lora_name=name,
lora_path=path,
pinned=False,
) )
else: else:
lora_ref = LoRARef( lora_ref = LoRARef(
lora_name=lora_path, lora_path=lora_path, pinned=False lora_id=LoRARef.deterministic_id(lora_path, lora_path),
lora_name=lora_path,
lora_path=lora_path,
pinned=False,
) )
elif isinstance(lora_path, dict): elif isinstance(lora_path, dict):
assert ( assert (
"lora_name" in lora_path and "lora_path" in lora_path "lora_name" in lora_path and "lora_path" in lora_path
), f"When providing LoRA paths as a list of dict, each dict should contain 'lora_name' and 'lora_path' keys. Got: {lora_path}" ), f"When providing LoRA paths as a list of dict, each dict should contain 'lora_name' and 'lora_path' keys. Got: {lora_path}"
lora_ref = LoRARef( lora_ref = LoRARef(
lora_id=LoRARef.deterministic_id(
lora_path["lora_name"], lora_path["lora_path"]
),
lora_name=lora_path["lora_name"], lora_name=lora_path["lora_name"],
lora_path=lora_path["lora_path"], lora_path=lora_path["lora_path"],
pinned=lora_path.get("pinned", False), pinned=lora_path.get("pinned", False),
@@ -7034,7 +7043,12 @@ class ServerArgs:
self.lora_paths.append(lora_ref) self.lora_paths.append(lora_ref)
elif isinstance(self.lora_paths, dict): elif isinstance(self.lora_paths, dict):
self.lora_paths = [ self.lora_paths = [
LoRARef(lora_name=k, lora_path=v, pinned=False) LoRARef(
lora_id=LoRARef.deterministic_id(k, v),
lora_name=k,
lora_path=v,
pinned=False,
)
for k, v in self.lora_paths.items() for k, v in self.lora_paths.items()
] ]
elif self.lora_paths is None: elif self.lora_paths is None: