💬 Commit message: Update 2026-02-15 05:34:38, 4 files, 75 lines

📁 Files changed: 4
📝 Lines changed: 75

  • .coverage
  • gguf.sh
  • cli.py
  • generate_routes.py
This commit is contained in:
Adam Ladachowski
2026-02-15 05:34:38 +01:00
parent 8b3e19d237
commit 8beb92d83a
4 changed files with 65 additions and 10 deletions
BIN
View File
Binary file not shown.
Executable
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/env bash
# Convert all safetensors to q8_0 GGUF format (skip if already exists)
set -euo pipefail
for sf in *.safetensors; do
[[ -f "$sf" ]] || continue
base="${sf%.safetensors}"
gguf="${base}-q8_0.gguf"
if [[ -f "$gguf" ]]; then
echo "Skip: $gguf exists"
continue
fi
echo "Converting: $sf -> $gguf"
sd -M convert -m "$sf" -o "$gguf" --type q8_0
done
+36 -6
View File
@@ -48,6 +48,18 @@ from tensors.safetensor import compute_sha256, get_base_name, read_safetensor_me
# Key masking threshold # Key masking threshold
MIN_KEY_LENGTH_FOR_MASKING = 8 MIN_KEY_LENGTH_FOR_MASKING = 8
# Size threshold for GB display
_MB_PER_GB = 1024
def _format_size_mb(size_mb: float | None) -> str:
"""Format size in MB to human-readable string."""
if not size_mb:
return ""
if size_mb >= _MB_PER_GB:
return f"{size_mb / _MB_PER_GB:.1f} GB"
return f"{size_mb:.0f} MB"
def _version_callback(value: bool) -> None: def _version_callback(value: bool) -> None:
if value: if value:
@@ -1016,16 +1028,25 @@ def models_list(
return return
table = Table(title="Available Models", show_header=True, header_style="bold magenta") table = Table(title="Available Models", show_header=True, header_style="bold magenta")
table.add_column("Status", style="dim", width=3) table.add_column("ID", style="dim", width=8)
table.add_column("Name", style="cyan") table.add_column("Name", style="cyan")
table.add_column("Path", style="dim") table.add_column("File", style="white")
table.add_column("Size", style="green", justify="right")
for model in models: for model in models:
path = model.get("path", "") path = model.get("path", "")
name = model.get("name", Path(path).stem if path else "") name = model.get("name", Path(path).stem if path else "")
is_active = active in {path, name} is_active = active in {path, name}
status = "[green]✓[/green]" if is_active else ""
table.add_row(status, name, path) civitai_id = model.get("civitai_model_id")
id_str = str(civitai_id) if civitai_id else ""
display_name = model.get("display_name", name)
if is_active:
display_name = f"[green]✓[/green] {display_name}"
filename = model.get("filename", Path(path).name if path else "")
size_str = _format_size_mb(model.get("size_mb"))
table.add_row(id_str, display_name, filename, size_str)
console.print(table) console.print(table)
@@ -1091,13 +1112,22 @@ def models_loras(
return return
table = Table(title="Available LoRAs", show_header=True, header_style="bold magenta") table = Table(title="Available LoRAs", show_header=True, header_style="bold magenta")
table.add_column("ID", style="dim", width=8)
table.add_column("Name", style="cyan") table.add_column("Name", style="cyan")
table.add_column("Path", style="dim") table.add_column("File", style="white")
table.add_column("Size", style="green", justify="right")
for lora in loras: for lora in loras:
path = lora.get("path", "") path = lora.get("path", "")
name = lora.get("name", Path(path).stem if path else "") name = lora.get("name", Path(path).stem if path else "")
table.add_row(name, path)
civitai_id = lora.get("civitai_model_id")
id_str = str(civitai_id) if civitai_id else ""
display_name = lora.get("display_name", name)
filename = lora.get("filename", Path(path).name if path else "")
size_str = _format_size_mb(lora.get("size_mb"))
table.add_row(id_str, display_name, filename, size_str)
console.print(table) console.print(table)
+10 -4
View File
@@ -5,6 +5,7 @@ from __future__ import annotations
import base64 import base64
import logging import logging
import time import time
from pathlib import Path
from typing import Any from typing import Any
import httpx import httpx
@@ -55,8 +56,16 @@ class GenerateRequest(PydanticBaseModel):
def _build_sd_request(req: GenerateRequest) -> dict[str, Any]: def _build_sd_request(req: GenerateRequest) -> dict[str, Any]:
"""Build request body for sd-server.""" """Build request body for sd-server."""
prompt = req.prompt
# sd-server expects LoRA in prompt as <lora:name:weight> syntax
if req.lora:
lora_name = Path(req.lora.path).stem
lora_tag = f"<lora:{lora_name}:{req.lora.multiplier}>"
prompt = f"{prompt} {lora_tag}"
body: dict[str, Any] = { body: dict[str, Any] = {
"prompt": req.prompt, "prompt": prompt,
"negative_prompt": req.negative_prompt, "negative_prompt": req.negative_prompt,
"width": req.width, "width": req.width,
"height": req.height, "height": req.height,
@@ -69,9 +78,6 @@ def _build_sd_request(req: GenerateRequest) -> dict[str, Any]:
body["sampler_name"] = req.sampler_name body["sampler_name"] = req.sampler_name
if req.scheduler: if req.scheduler:
body["scheduler"] = req.scheduler body["scheduler"] = req.scheduler
# sd-server expects LoRA as JSON array, not in prompt
if req.lora:
body["lora"] = [{"path": req.lora.path, "multiplier": req.lora.multiplier}]
return body return body