Skip to content

Commit

Permalink
docs: enhance class and method documentation
Browse files Browse the repository at this point in the history
- fix formatting issues from last commit
- add docstrings for important classes
  • Loading branch information
leafspark committed Aug 5, 2024
1 parent c9167a7 commit e69237b
Show file tree
Hide file tree
Showing 7 changed files with 316 additions and 126 deletions.
4 changes: 2 additions & 2 deletions docs/AutoGGUF.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
class AutoGGUF(QMainWindow):
"""
AutoGGUF is a PyQt6-based graphical user interface for managing and quantizing large language models.
This class provides functionality for:
- Loading and displaying models (including sharded models)
- Quantizing models with various options
- Downloading llama.cpp releases
- Generating importance matrices
- Converting and exporting LoRA models
- Managing quantization tasks
The GUI allows users to interact with these features in an intuitive way, providing
options for model selection, quantization parameters, and task management.
"""
Expand Down
87 changes: 87 additions & 0 deletions docs/KVOverrideEntry.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
class KVOverrideEntry(QWidget):
"""
KVOverrideEntry is a PyQt6-based widget for creating and managing key-value override entries.
This class provides functionality for:
- Inputting keys and values with type specification
- Dynamic value substitution using predefined placeholders
- Validating inputs based on selected data types
- Generating formatted override strings
The widget includes input fields for keys and values, a type selector,
and a delete button. It supports various system-related and custom placeholders
for dynamic value generation.
Attributes:
deleted (pyqtSignal): Signal emitted when the entry is deleted.
key_input (QLineEdit): Input field for the key.
type_combo (QComboBox): Dropdown for selecting the value type.
value_input (QLineEdit): Input field for the value.
Supported dynamic placeholders:
{system.time.milliseconds}: Current time in milliseconds
{system.time.seconds}: Current time in seconds
{system.date.iso}: Current date in ISO format
{system.datetime.iso}: Current date and time in ISO format
{system.username}: Current system username
{system.hostname}: Current system hostname
{system.platform}: Current operating system platform
{system.python.version}: Python version
{system.date}: Current date in YYYY-MM-DD format
{model.name}: Model name (if provided)
{quant.type}: Quantization type (if provided)
{output.path}: Output path (if provided)
"""

def __init__(self, parent=None):
"""
Initialize the KVOverrideEntry widget.
This method sets up the widget layout, creates and configures input fields,
sets up validators, and connects signals to their respective slots.
Args:
parent (QWidget, optional): The parent widget. Defaults to None.
"""

def delete_clicked(self):
"""
Handle the delete button click event.
Emits the 'deleted' signal to notify the parent widget that this entry
should be removed.
"""

def get_override_string(self, model_name=None, quant_type=None, output_path=None):
"""
Generate a formatted override string with dynamic value substitution.
This method processes the input fields and replaces any placeholders
in the value with their corresponding dynamic values.
Args:
model_name (str, optional): Model name for substitution.
quant_type (str, optional): Quantization type for substitution.
output_path (str, optional): Output path for substitution.
Returns:
str: Formatted override string in the format "key=type:value".
"""

def get_raw_override_string(self):
"""
Generate a raw override string without dynamic substitution.
Returns:
str: Raw override string with placeholders intact, in the format "key=type:value".
"""

def update_validator(self, type_):
"""
Update the validator for the value input field based on the selected type.
This method ensures that the value input adheres to the chosen data type.
Args:
type_ (str): The selected data type ('int', 'float', or 'str').
"""
64 changes: 64 additions & 0 deletions docs/QuantizationThread.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
class QuantizationThread(QThread):
"""
QuantizationThread is a PyQt6-based thread for managing model quantization processes.
This class provides functionality for:
- Running quantization commands as subprocesses
- Parsing and emitting model information during quantization
- Logging quantization output to a file
- Communicating process status, output, and errors to the main thread
The thread manages the execution of quantization commands, monitors their output,
and parses relevant model information. It uses Qt signals to communicate various
events and data back to the main application thread.
Attributes:
output_signal (pyqtSignal): Signal emitting subprocess output lines.
status_signal (pyqtSignal): Signal for updating quantization status.
finished_signal (pyqtSignal): Signal emitted when quantization is complete.
error_signal (pyqtSignal): Signal for reporting errors during quantization.
model_info_signal (pyqtSignal): Signal for sending parsed model information.
Methods:
run(): Executes the quantization process and manages its lifecycle.
parse_model_info(line: str): Parses output lines for model information.
terminate(): Safely terminates the running subprocess.
"""

def __init__(self, command, cwd, log_file):
"""
Initialize the QuantizationThread.
Args:
command (list): The command to execute for quantization.
cwd (str): The working directory for the subprocess.
log_file (str): Path to the file where output will be logged.
"""

def run(self):
"""
Execute the quantization process.
This method runs the subprocess, captures its output, logs it,
parses model information, and emits signals for status updates.
It handles process completion and any exceptions that occur.
"""

def parse_model_info(self, line):
"""
Parse a line of subprocess output for model information.
This method extracts various pieces of model information from
the output lines and stores them in the model_info dictionary.
Args:
line (str): A line of output from the quantization process.
"""

def terminate(self):
"""
Terminate the running subprocess.
This method safely terminates the quantization process if it's
still running, using SIGTERM first and SIGKILL if necessary.
"""
32 changes: 32 additions & 0 deletions docs/convert_lora_to_ggml.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""
Convert PEFT LoRA adapters to GGML format.
This script converts Hugging Face PEFT LoRA adapter files to the GGML format
used by llama.cpp and related projects. It reads the adapter configuration
from 'adapter_config.json' and the model weights from 'adapter_model.bin'
or 'adapter_model.safetensors', then writes the converted model to
'ggml-adapter-model.bin' in the same directory.
Usage:
python lora_to_gguf.py <path> [arch]
Arguments:
path: Directory containing the PEFT LoRA files
arch: Model architecture (default: llama)
The script supports various model architectures and handles both PyTorch
and safetensors formats for input weights. It performs necessary tensor
transformations and writes the output in the GGML binary format.
Requirements:
- Python 3.6+
- numpy
- torch
- safetensors (optional, for safetensors input)
The script also requires the GGUF Python module, which should be in the
'gguf-py/gguf' subdirectory relative to this script's location.
Note: This script is designed for use with llama.cpp and related projects.
Ensure compatibility with your target application when using the output.
"""
40 changes: 40 additions & 0 deletions docs/convert_lora_to_gguf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""
LoRA to GGUF Converter
This script converts a Hugging Face PEFT LoRA adapter to a GGML-compatible file format.
Key features:
- Supports various output formats (f32, f16, bf16, q8_0, auto)
- Handles big-endian and little-endian architectures
- Provides options for lazy evaluation and verbose output
- Combines base model information with LoRA adapters
Classes:
PartialLoraTensor: Dataclass for storing partial LoRA tensor information.
LoraTorchTensor: Custom tensor class for LoRA operations and transformations.
LoraModel: Extends the base model class to incorporate LoRA-specific functionality.
Functions:
get_base_tensor_name: Extracts the base tensor name from a LoRA tensor name.
pyinstaller_include: Placeholder for PyInstaller import handling.
parse_args: Parses command-line arguments for the script.
Usage:
python lora_to_gguf.py --base <base_model_path> <lora_adapter_path> [options]
Arguments:
--base: Path to the directory containing the base model file (required)
lora_path: Path to the directory containing the LoRA adapter file (required)
--outfile: Path to write the output file (optional)
--outtype: Output format (f32, f16, bf16, q8_0, auto; default: f16)
--bigendian: Flag to indicate big-endian machine execution
--no-lazy: Disable lazy evaluation (uses more RAM)
--verbose: Increase output verbosity
--dry-run: Perform a dry run without writing files
The script processes LoRA adapters, combines them with base model information,
and generates a GGML-compatible file for use in various applications.
Note: This script requires specific dependencies like torch, gguf, and safetensors.
Ensure all required libraries are installed before running the script.
"""
29 changes: 21 additions & 8 deletions src/AutoGGUF.py
Original file line number Diff line number Diff line change
Expand Up @@ -1240,7 +1240,7 @@ def load_models(self):
single_models = []

# Regex pattern to match sharded model filenames
shard_pattern = re.compile(r'(.*)-(\d+)-of-(\d+)\.gguf$')
shard_pattern = re.compile(r"(.*)-(\d+)-of-(\d+)\.gguf$")

for file in os.listdir(models_dir):
if file.endswith(".gguf"):
Expand Down Expand Up @@ -1367,7 +1367,7 @@ def quantize_model(self):
quant_type = self.quant_type.currentText()

input_path = os.path.join(self.models_input.text(), model_file)

# Start building the output name
output_name_parts = [
os.path.splitext(model_name)[0],
Expand All @@ -1376,7 +1376,10 @@ def quantize_model(self):
]

# Check for output tensor options
if self.use_output_tensor_type.isChecked() or self.leave_output_tensor.isChecked():
if (
self.use_output_tensor_type.isChecked()
or self.leave_output_tensor.isChecked()
):
output_tensor_part = "o"
if self.use_output_tensor_type.isChecked():
output_tensor_part += "." + self.output_tensor_type.currentText()
Expand Down Expand Up @@ -1421,9 +1424,13 @@ def quantize_model(self):
if self.exclude_weights.text():
command.extend(["--exclude-weights", self.exclude_weights.text()])
if self.use_output_tensor_type.isChecked():
command.extend(["--output-tensor-type", self.output_tensor_type.currentText()])
command.extend(
["--output-tensor-type", self.output_tensor_type.currentText()]
)
if self.use_token_embedding_type.isChecked():
command.extend(["--token-embedding-type", self.token_embedding_type.currentText()])
command.extend(
["--token-embedding-type", self.token_embedding_type.currentText()]
)
if self.keep_split.isChecked():
command.append("--keep-split")
if self.kv_override_entries:
Expand All @@ -1446,7 +1453,9 @@ def quantize_model(self):
ensure_directory(logs_path)

timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
log_file = os.path.join(logs_path, f"{model_name}_{timestamp}_{quant_type}.log")
log_file = os.path.join(
logs_path, f"{model_name}_{timestamp}_{quant_type}.log"
)

# Log quant command
command_str = " ".join(command)
Expand All @@ -1455,14 +1464,18 @@ def quantize_model(self):
thread = QuantizationThread(command, backend_path, log_file)
self.quant_threads.append(thread)

task_item = TaskListItem(QUANTIZING_MODEL_TO.format(model_name, quant_type), log_file)
task_item = TaskListItem(
QUANTIZING_MODEL_TO.format(model_name, quant_type), log_file
)
list_item = QListWidgetItem(self.task_list)
list_item.setSizeHint(task_item.sizeHint())
self.task_list.addItem(list_item)
self.task_list.setItemWidget(list_item, task_item)

# Connect the output signal to the new progress parsing function
thread.output_signal.connect(lambda line: self.parse_progress(line, task_item))
thread.output_signal.connect(
lambda line: self.parse_progress(line, task_item)
)
thread.status_signal.connect(task_item.update_status)
thread.finished_signal.connect(lambda: self.task_finished(thread))
thread.error_signal.connect(lambda err: self.handle_error(err, task_item))
Expand Down
Loading

0 comments on commit e69237b

Please sign in to comment.