Skip to content
This repository was archived by the owner on Oct 11, 2024. It is now read-only.
2 changes: 1 addition & 1 deletion examples/offline_inference.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
sampling_params = SamplingParams(temperature=0.8, top_p=0.95)

# Create an LLM.
llm = LLM(model="facebook/opt-125m")
llm = LLM(model="meta-llama/Llama-2-7b-chat-hf")
# Generate texts from the prompts. The output is a list of RequestOutput objects
# that contain the prompt, generated text, and other information.
outputs = llm.generate(prompts, sampling_params)
Expand Down
112 changes: 99 additions & 13 deletions vllm/model_executor/layers/linear.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ def apply_weights(self,
bias: Optional[torch.Tensor] = None) -> torch.Tensor:
"""Apply the weights to the input tensor."""
raise NotImplementedError

def maybe_update_loaded_weight_name(self, name: str) -> str:
"""Update the name of a loaded weight to enable generic handling of
cases where serialized state_dict does not match vllm model definition.
"""
return name


class UnquantizedLinearMethod(LinearMethodBase):
Expand All @@ -59,7 +65,7 @@ def __init__(self, separate_bias_add: bool = False):
def create_weights(self, input_size_per_partition: int,
output_size_per_partition: int, input_size: int,
output_size: int,
params_dtype: torch.dtype) -> Dict[str, Any]:
params_dtype: torch.dtype, logical_widths: Optional[List[int]]) -> Dict[str, Any]:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

lift this to be inside LinearMethodBase ?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I got rid of this on the next pr

weight = Parameter(torch.empty(output_size_per_partition,
input_size_per_partition,
dtype=params_dtype),
Expand Down Expand Up @@ -150,6 +156,9 @@ class ColumnParallelLinear(torch.nn.Module):
skip adding bias but instead return it.
params_dtype: Data type for the parameters.
linear_method: (Maybe quantized) linear method.
logical_widths: Optional list of widths for logical weight matrices.
E.g. for QKVParallelLinear, this parameter defines
the width
"""

def __init__(
Expand All @@ -161,6 +170,7 @@ def __init__(
skip_bias_add: bool = False,
params_dtype: Optional[torch.dtype] = None,
linear_method: Optional[LinearMethodBase] = None,
logical_widths: Optional[List[int]] = None,
):
super().__init__()

Expand All @@ -179,8 +189,15 @@ def __init__(
linear_method = UnquantizedLinearMethod()
self.linear_method = linear_method
self.linear_weights = self.linear_method.create_weights(
self.input_size, self.output_size_per_partition, self.input_size,
self.output_size, self.params_dtype)
input_size_per_partition=self.input_size,
output_size_per_partition=self.output_size_per_partition,
input_size=self.input_size,
output_size=self.output_size,
params_dtype=self.params_dtype,
logical_widths=logical_widths,
# TODO: remove this, should be coming through the quant config.
per_token_quant=False,
)
for name, weight in self.linear_weights.items():
if isinstance(weight, torch.Tensor):
self.register_parameter(name, weight)
Expand Down Expand Up @@ -257,15 +274,34 @@ def __init__(
self.output_sizes = output_sizes
tp_size = get_tensor_model_parallel_world_size()
assert all(output_size % tp_size == 0 for output_size in output_sizes)
super().__init__(input_size, sum(output_sizes), bias, gather_output,
skip_bias_add, params_dtype, linear_method)
super().__init__(
input_size=input_size,
output_size=sum(output_sizes),
bias=bias,
gather_output=gather_output,
skip_bias_add=skip_bias_add,
params_dtype=params_dtype,
linear_method=linear_method,
logical_widths=output_sizes)

def weight_loader(self,
param: Parameter,
loaded_weight: torch.Tensor,
loaded_shard_id: Optional[int] = None):
param_data = param.data
output_dim = getattr(param, "output_dim", None)
param_shard_splitter = getattr(param, "shard_splitter", None)
if output_dim is not None and param_shard_splitter is not None:
raise NotImplementedError(
"We do not currently support output_dim != None and "
"shard_splitter != None for a parameter. Please open an issue."
)
if loaded_shard_id is None and param_shard_splitter is not None:
raise NotImplementedError(
"We do not currently support loaded_shard_id == None and "
"shard_splitter != None for a parameter. Please open an issue."
)

if loaded_shard_id is None:
# Loaded weight is already packed.
if output_dim is None:
Expand Down Expand Up @@ -318,13 +354,18 @@ def weight_loader(self,
start_idx = tp_rank * shard_size
loaded_weight = loaded_weight.narrow(output_dim, start_idx,
shard_size)
# If a param_shard_splitter is defined by the LinearMethod, use it.
elif param_shard_splitter is not None:
param_data, loaded_weight = param_shard_splitter(
param_data, loaded_weight, loaded_shard_id)
else:
ignore_warning = getattr(param, "ignore_warning", False)
if not ignore_warning:
logger.warning(
"Loading a weight without `output_dim` attribute in "
"MergedColumnParallelLinear, assume the weight is "
"the same for all partitions.")

assert param_data.shape == loaded_weight.shape
param_data.copy_(loaded_weight)

Expand Down Expand Up @@ -383,15 +424,38 @@ def __init__(
input_size = self.hidden_size
output_size = (self.num_heads +
2 * self.num_kv_heads) * tp_size * self.head_size
super().__init__(input_size, output_size, bias, False, skip_bias_add,
params_dtype, linear_method)
super().__init__(
input_size=input_size,
output_size=output_size,
bias=bias,
gather_output=False,
skip_bias_add=skip_bias_add,
params_dtype=params_dtype,
linear_method=linear_method,
logical_widths = [
self.num_heads * self.head_size, # q_proj
self.total_num_kv_heads * self.head_size, # k_proj
self.total_num_kv_heads * self.head_size, # v_proj
])

def weight_loader(self,
param: Parameter,
loaded_weight: torch.Tensor,
loaded_shard_id: Optional[str] = None):
param_data = param.data
output_dim = getattr(param, "output_dim", None)
param_shard_splitter = getattr(param, "shard_splitter", None)

if output_dim is not None and param_shard_splitter is not None:
raise NotImplementedError(
"We do not currently support output_dim != None and "
"shard_splitter != None for a parameter. Please open an issue."
)
if loaded_shard_id is None and param_shard_splitter is not None:
raise NotImplementedError(
"We do not currently support loaded_shard_id == None and "
"shard_splitter != None for a parameter. Please open an issue."
)

if loaded_shard_id is None:
# Loaded weight is already packed.
Expand Down Expand Up @@ -427,6 +491,8 @@ def weight_loader(self,

tp_rank = get_tensor_model_parallel_rank()
assert loaded_shard_id in ["q", "k", "v"]

# If output dim is defined, use the default loading process.
if output_dim is not None:
if loaded_shard_id == "q":
shard_offset = 0
Expand All @@ -450,23 +516,31 @@ def weight_loader(self,
shard_size, shard_offset = adjust_marlin_shard(
param, shard_size, shard_offset)

param_data = param_data.narrow(output_dim, shard_offset,
shard_size)
param_data = param_data.narrow(
output_dim, shard_offset, shard_size)
if loaded_shard_id == "q":
shard_id = tp_rank
else:
shard_id = tp_rank // self.num_kv_head_replicas
start_idx = shard_id * shard_size
loaded_weight = loaded_weight.narrow(output_dim, start_idx,
shard_size)
shard_size)
# If a param_shard_splitter is defined by the LinearMethod, use it.
elif param_shard_splitter is not None:
param_data, loaded_weight = param_shard_splitter(
param_data, loaded_weight, loaded_shard_id)
else:
ignore_warning = getattr(param, "ignore_warning", False)
if not ignore_warning:
logger.warning(
"Loading a weight without `output_dim` attribute in "
"QKVParallelLinear, assume the weight is the same "
"for all partitions.")
assert param_data.shape == loaded_weight.shape

assert (
param_data.shape == loaded_weight.shape or
(len(param_data.shape) == 0 and len(loaded_weight.shape) == 0)
)
param_data.copy_(loaded_weight)


Expand Down Expand Up @@ -525,8 +599,15 @@ def __init__(
linear_method = UnquantizedLinearMethod()
self.linear_method = linear_method
self.linear_weights = self.linear_method.create_weights(
self.input_size_per_partition, self.output_size, self.input_size,
self.output_size, self.params_dtype)
input_size_per_partition=self.input_size_per_partition,
output_size_per_partition=self.output_size,
input_size=self.input_size,
output_size=self.output_size,
params_dtype=self.params_dtype,
logical_widths=[self.output_size],
# TODO: remove this, should be coming through the quant config.
per_token_quant=True,
)
for name, weight in self.linear_weights.items():
if isinstance(weight, torch.Tensor):
self.register_parameter(name, weight)
Expand Down Expand Up @@ -555,6 +636,11 @@ def weight_loader(self, param: Parameter, loaded_weight: torch.Tensor):
start_idx = tp_rank * shard_size
loaded_weight = loaded_weight.narrow(input_dim, start_idx,
shard_size)

# TODO: canon
if len(loaded_weight.shape) == 0:
loaded_weight = loaded_weight.reshape(1)

assert param_data.shape == loaded_weight.shape
param_data.copy_(loaded_weight)

Expand Down
Loading