loreguard-cli 0.14.0__tar.gz → 0.14.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/PKG-INFO +1 -1
- loreguard_cli-0.14.1/loreguard.spec +42 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/pyproject.toml +6 -1
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/scripts/build.py +2 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/cli.py +26 -22
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/config.py +85 -4
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/llama_server.py +9 -1
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/llm.py +4 -4
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/models_registry.py +24 -38
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/uv.lock +9 -1
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/.claude/skills/llama-cpp-troubleshooting/SKILL.md +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/.env.example +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/.github/workflows/release.yml +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/.gitignore +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/LICENSE +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/README.md +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/THIRD_PARTY_NOTICES.md +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/loreguard_entry.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/sdk/API.md +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/sdk/csharp/LoreguardSDK.cs +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/sdk/gdscript/LoreguardSDK.gd +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/sdk/javascript/loreguard-sdk.js +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/sdk/python/loreguard_sdk.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/__init__.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/__main__.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/chunk_detector.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/dialogue_act_classifier.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/hf_discovery.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/http_server.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/intent_classifier.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/main.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/nli.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/npc_chat.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/runtime.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/steam.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/term_ui.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/__init__.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/app.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/modals/__init__.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/modals/auth_menu.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/modals/npc_chat.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/modals/token_input.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/modals/unified_palette.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/screens/__init__.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/screens/auth.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/screens/main.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/screens/model_select.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/screens/nli_setup.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/screens/running.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/styles.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/widgets/__init__.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/widgets/banner.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/widgets/footer.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/widgets/hardware_info.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/widgets/npc_chat.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/widgets/server_monitor.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/widgets/status_panel.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tunnel.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/wizard.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/templates/llama31-no-tools.jinja +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/tests/test_nli_hhem.py +0 -0
- {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/tests/test_websocket_timeout.py +0 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# -*- mode: python ; coding: utf-8 -*-
|
|
2
|
+
from PyInstaller.utils.hooks import collect_submodules
|
|
3
|
+
|
|
4
|
+
hiddenimports = ['src', 'src.config', 'src.llm', 'src.llama_server', 'src.tunnel', 'src.term_ui', 'src.models_registry', 'src.cli', 'src.npc_chat', 'httpx', 'websockets', 'aiofiles', 'pydantic']
|
|
5
|
+
hiddenimports += collect_submodules('src')
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
a = Analysis(
|
|
9
|
+
['loreguard_entry.py'],
|
|
10
|
+
pathex=['.'],
|
|
11
|
+
binaries=[],
|
|
12
|
+
datas=[('templates', 'templates')],
|
|
13
|
+
hiddenimports=hiddenimports,
|
|
14
|
+
hookspath=[],
|
|
15
|
+
hooksconfig={},
|
|
16
|
+
runtime_hooks=[],
|
|
17
|
+
excludes=[],
|
|
18
|
+
noarchive=False,
|
|
19
|
+
optimize=0,
|
|
20
|
+
)
|
|
21
|
+
pyz = PYZ(a.pure)
|
|
22
|
+
|
|
23
|
+
exe = EXE(
|
|
24
|
+
pyz,
|
|
25
|
+
a.scripts,
|
|
26
|
+
a.binaries,
|
|
27
|
+
a.datas,
|
|
28
|
+
[],
|
|
29
|
+
name='loreguard',
|
|
30
|
+
debug=False,
|
|
31
|
+
bootloader_ignore_signals=False,
|
|
32
|
+
strip=False,
|
|
33
|
+
upx=True,
|
|
34
|
+
upx_exclude=[],
|
|
35
|
+
runtime_tmpdir=None,
|
|
36
|
+
console=True,
|
|
37
|
+
disable_windowed_traceback=False,
|
|
38
|
+
argv_emulation=False,
|
|
39
|
+
target_arch=None,
|
|
40
|
+
codesign_identity=None,
|
|
41
|
+
entitlements_file=None,
|
|
42
|
+
)
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "loreguard-cli"
|
|
7
|
-
version = "0.14.
|
|
7
|
+
version = "0.14.1"
|
|
8
8
|
description = "Local inference client for Loreguard NPCs"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -62,3 +62,8 @@ packages = ["src"]
|
|
|
62
62
|
[tool.ruff]
|
|
63
63
|
line-length = 100
|
|
64
64
|
target-version = "py310"
|
|
65
|
+
|
|
66
|
+
[dependency-groups]
|
|
67
|
+
dev = [
|
|
68
|
+
"pyinstaller>=6.17.0",
|
|
69
|
+
]
|
|
@@ -36,6 +36,8 @@ def main():
|
|
|
36
36
|
"--clean",
|
|
37
37
|
# Add src to path so imports work
|
|
38
38
|
"--paths", ".",
|
|
39
|
+
# Include templates directory (jinja chat templates for llama-server)
|
|
40
|
+
"--add-data", "templates:templates",
|
|
39
41
|
# Collect all src submodules
|
|
40
42
|
"--collect-submodules", "src",
|
|
41
43
|
# Add hidden imports that PyInstaller might miss
|
|
@@ -52,8 +52,11 @@ class LoreguardCLI:
|
|
|
52
52
|
self.model_id = model_id
|
|
53
53
|
self.port = port
|
|
54
54
|
self.backend_url = backend_url
|
|
55
|
-
# Worker ID: use provided value, or default to hostname
|
|
56
|
-
|
|
55
|
+
# Worker ID: use provided value, or default to sanitized hostname.
|
|
56
|
+
# Validator requires ^[a-zA-Z0-9_-]{1,64}$ — replace dots with hyphens.
|
|
57
|
+
raw_id = worker_id or socket.gethostname() or "worker"
|
|
58
|
+
import re
|
|
59
|
+
self.worker_id = re.sub(r'[^a-zA-Z0-9_-]', '-', raw_id)[:64]
|
|
57
60
|
|
|
58
61
|
self._llama = None
|
|
59
62
|
self._tunnel = None
|
|
@@ -275,25 +278,8 @@ class LoreguardCLI:
|
|
|
275
278
|
except Exception as e:
|
|
276
279
|
log.warning(f"Intent classifier error: {e}")
|
|
277
280
|
|
|
278
|
-
#
|
|
281
|
+
# Dialogue act classifier disabled
|
|
279
282
|
dialogue_act_classifier = None
|
|
280
|
-
try:
|
|
281
|
-
from .dialogue_act_classifier import (
|
|
282
|
-
DialogueActClassifier,
|
|
283
|
-
is_dialogue_act_model_available,
|
|
284
|
-
)
|
|
285
|
-
if is_dialogue_act_model_available():
|
|
286
|
-
log.info("Loading dialogue act classifier...")
|
|
287
|
-
dialogue_act_classifier = DialogueActClassifier()
|
|
288
|
-
if dialogue_act_classifier.load_model():
|
|
289
|
-
log.info(f"Dialogue act classifier ready (device: {dialogue_act_classifier.device})")
|
|
290
|
-
else:
|
|
291
|
-
log.warning("Dialogue act classifier failed to load")
|
|
292
|
-
dialogue_act_classifier = None
|
|
293
|
-
else:
|
|
294
|
-
log.info("Dialogue act model not available, skipping")
|
|
295
|
-
except Exception as e:
|
|
296
|
-
log.warning(f"Dialogue act classifier error: {e}")
|
|
297
283
|
|
|
298
284
|
# Initialize chunk detector (ADR-0023) - shares model with intent classifier
|
|
299
285
|
chunk_detector = None
|
|
@@ -469,6 +455,11 @@ Available model IDs:
|
|
|
469
455
|
action="store_true",
|
|
470
456
|
help="Enable debug logging and show pipeline pass updates (in wizard mode)",
|
|
471
457
|
)
|
|
458
|
+
parser.add_argument(
|
|
459
|
+
"--bundle-dir",
|
|
460
|
+
default=os.getenv("LOREGUARD_BUNDLE_DIR", ""),
|
|
461
|
+
help="Loreguard bundle directory. Auto-discovers models from manifest.txt.",
|
|
462
|
+
)
|
|
472
463
|
parser.add_argument(
|
|
473
464
|
"--dev",
|
|
474
465
|
action="store_true",
|
|
@@ -485,6 +476,10 @@ Available model IDs:
|
|
|
485
476
|
if args.verbose:
|
|
486
477
|
logging.getLogger().setLevel(logging.DEBUG)
|
|
487
478
|
|
|
479
|
+
# Propagate --bundle-dir to env so config.py picks it up via get_bundle_dir()
|
|
480
|
+
if args.bundle_dir:
|
|
481
|
+
os.environ["LOREGUARD_BUNDLE_DIR"] = args.bundle_dir
|
|
482
|
+
|
|
488
483
|
# Chat mode - test NPC chat directly via API (no model needed)
|
|
489
484
|
if args.chat:
|
|
490
485
|
if not args.token:
|
|
@@ -509,8 +504,17 @@ Available model IDs:
|
|
|
509
504
|
args.token = "dev_mock_token"
|
|
510
505
|
log.info("Running in DEV MODE - no backend connection")
|
|
511
506
|
else:
|
|
512
|
-
#
|
|
513
|
-
|
|
507
|
+
# Local bundle backends (ws:// to localhost/127.0.0.1) run with RequireAuth=false,
|
|
508
|
+
# so any non-empty token is accepted. Only require a real token for cloud backends.
|
|
509
|
+
backend = args.backend
|
|
510
|
+
is_local_backend = (
|
|
511
|
+
backend.startswith("ws://") and
|
|
512
|
+
any(backend.startswith(f"ws://{h}") for h in ("localhost", "127.0.0.1", "[::1]"))
|
|
513
|
+
)
|
|
514
|
+
if not args.token and is_local_backend:
|
|
515
|
+
# Local bundle backends run with RequireAuth=false — any non-empty token works.
|
|
516
|
+
args.token = "local"
|
|
517
|
+
elif not args.token:
|
|
514
518
|
log.error("Token required. Use --token or set LOREGUARD_TOKEN (or use --dev)")
|
|
515
519
|
sys.exit(1)
|
|
516
520
|
|
|
@@ -161,25 +161,83 @@ def load_config() -> dict:
|
|
|
161
161
|
# Pre-shipped llama-server binary path (enterprise bundles).
|
|
162
162
|
# When set, skips auto-download and uses this binary directly.
|
|
163
163
|
"LLAMA_SERVER_PATH": os.getenv("LOREGUARD_LLAMA_SERVER_PATH", ""),
|
|
164
|
+
|
|
165
|
+
# Bundle directory (set by game launchers that ship a loreguard bundle).
|
|
166
|
+
# When set, the client auto-discovers models from manifest.txt inside the bundle.
|
|
167
|
+
# This is the single env var a game needs to set — no per-model configuration required.
|
|
168
|
+
"BUNDLE_DIR": os.getenv("LOREGUARD_BUNDLE_DIR", ""),
|
|
164
169
|
}
|
|
165
170
|
|
|
166
171
|
|
|
172
|
+
def get_bundle_dir() -> Optional[Path]:
|
|
173
|
+
"""Get the loreguard bundle directory, if configured via LOREGUARD_BUNDLE_DIR.
|
|
174
|
+
|
|
175
|
+
Game launchers set this to the bundle root so the client can auto-discover
|
|
176
|
+
models from manifest.txt without any per-model configuration.
|
|
177
|
+
"""
|
|
178
|
+
bundle_dir = get_config_value("BUNDLE_DIR")
|
|
179
|
+
if bundle_dir:
|
|
180
|
+
path = Path(bundle_dir)
|
|
181
|
+
if path.exists() and path.is_dir():
|
|
182
|
+
return path
|
|
183
|
+
return None
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def get_bundle_manifest() -> dict:
|
|
187
|
+
"""Parse the bundle's manifest.txt into a logical-name → dir-name mapping.
|
|
188
|
+
|
|
189
|
+
Returns an empty dict if no bundle dir is configured or manifest is missing.
|
|
190
|
+
|
|
191
|
+
Manifest format:
|
|
192
|
+
nli=vectara--hallucination_evaluation_model
|
|
193
|
+
embedding=BAAI--bge-small-en-v1.5
|
|
194
|
+
reranker=cross-encoder--ms-marco-MiniLM-L-6-v2
|
|
195
|
+
"""
|
|
196
|
+
bundle_dir = get_bundle_dir()
|
|
197
|
+
if not bundle_dir:
|
|
198
|
+
return {}
|
|
199
|
+
manifest_path = bundle_dir / "models" / "manifest.txt"
|
|
200
|
+
if not manifest_path.exists():
|
|
201
|
+
return {}
|
|
202
|
+
result = {}
|
|
203
|
+
for line in manifest_path.read_text().splitlines():
|
|
204
|
+
line = line.strip()
|
|
205
|
+
if not line or line.startswith("#"):
|
|
206
|
+
continue
|
|
207
|
+
if "=" in line:
|
|
208
|
+
key, _, value = line.partition("=")
|
|
209
|
+
result[key.strip()] = value.strip()
|
|
210
|
+
return result
|
|
211
|
+
|
|
212
|
+
|
|
167
213
|
def get_models_dir() -> Optional[Path]:
|
|
168
214
|
"""Get the pre-shipped models directory, if configured (ADR-0027).
|
|
169
215
|
|
|
170
|
-
|
|
216
|
+
Checks LOREGUARD_MODELS_DIR first, then falls back to the bundle's models dir.
|
|
217
|
+
Returns None if neither is set, meaning models should be auto-downloaded from HF.
|
|
171
218
|
"""
|
|
172
219
|
models_dir = get_config_value("MODELS_DIR")
|
|
173
220
|
if models_dir:
|
|
174
221
|
path = Path(models_dir)
|
|
175
222
|
if path.exists() and path.is_dir():
|
|
176
223
|
return path
|
|
224
|
+
bundle_dir = get_bundle_dir()
|
|
225
|
+
if bundle_dir:
|
|
226
|
+
path = bundle_dir / "models"
|
|
227
|
+
if path.exists() and path.is_dir():
|
|
228
|
+
return path
|
|
177
229
|
return None
|
|
178
230
|
|
|
179
231
|
|
|
180
232
|
def resolve_model_path(model_name: str, subdir: str = "") -> str:
|
|
181
233
|
"""Resolve a model path, preferring pre-shipped models over HF downloads.
|
|
182
234
|
|
|
235
|
+
Resolution order:
|
|
236
|
+
1. LOREGUARD_MODELS_DIR/<subdir> (explicit override)
|
|
237
|
+
2. Bundle models dir using manifest.txt (HF name → manifest key → local dir)
|
|
238
|
+
3. Bundle models dir using HF name → org--model convention (fallback)
|
|
239
|
+
4. Original HF model name (download from HuggingFace)
|
|
240
|
+
|
|
183
241
|
Args:
|
|
184
242
|
model_name: HuggingFace model name (e.g., 'vectara/hallucination_evaluation_model')
|
|
185
243
|
subdir: Subdirectory within MODELS_DIR to check (e.g., 'hhem', 'deberta')
|
|
@@ -187,11 +245,34 @@ def resolve_model_path(model_name: str, subdir: str = "") -> str:
|
|
|
187
245
|
Returns:
|
|
188
246
|
Local path if pre-shipped model found, otherwise the original HF model name.
|
|
189
247
|
"""
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
248
|
+
# 1. Explicit LOREGUARD_MODELS_DIR/<subdir>
|
|
249
|
+
explicit_dir = get_config_value("MODELS_DIR")
|
|
250
|
+
if explicit_dir and subdir:
|
|
251
|
+
local_path = Path(explicit_dir) / subdir
|
|
193
252
|
if local_path.exists() and any(local_path.iterdir()):
|
|
194
253
|
return str(local_path)
|
|
254
|
+
|
|
255
|
+
# 2 & 3. Bundle directory resolution
|
|
256
|
+
bundle_dir = get_bundle_dir()
|
|
257
|
+
if bundle_dir:
|
|
258
|
+
bundle_models = bundle_dir / "models"
|
|
259
|
+
|
|
260
|
+
# Try manifest.txt: find the dir name for this HF model name
|
|
261
|
+
manifest = get_bundle_manifest()
|
|
262
|
+
# The manifest uses org--model naming (/ replaced by --)
|
|
263
|
+
hf_as_dir = model_name.replace("/", "--")
|
|
264
|
+
for _key, dir_name in manifest.items():
|
|
265
|
+
if dir_name == hf_as_dir:
|
|
266
|
+
local_path = bundle_models / dir_name
|
|
267
|
+
if local_path.exists() and any(local_path.iterdir()):
|
|
268
|
+
return str(local_path)
|
|
269
|
+
break
|
|
270
|
+
|
|
271
|
+
# Fallback: check bundle models dir using org--model convention directly
|
|
272
|
+
local_path = bundle_models / hf_as_dir
|
|
273
|
+
if local_path.exists() and any(local_path.iterdir()):
|
|
274
|
+
return str(local_path)
|
|
275
|
+
|
|
195
276
|
return model_name
|
|
196
277
|
|
|
197
278
|
|
|
@@ -22,6 +22,14 @@ from typing import AsyncGenerator, Callable, Optional
|
|
|
22
22
|
|
|
23
23
|
import httpx
|
|
24
24
|
|
|
25
|
+
|
|
26
|
+
def _get_templates_dir() -> Path:
|
|
27
|
+
"""Return the templates directory, handling PyInstaller onefile bundles."""
|
|
28
|
+
if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"):
|
|
29
|
+
return Path(sys._MEIPASS) / "templates"
|
|
30
|
+
return Path(__file__).parent.parent / "templates"
|
|
31
|
+
|
|
32
|
+
|
|
25
33
|
LLAMA_VERSION = "b7789" # Must match loreguard-engine bundle version
|
|
26
34
|
|
|
27
35
|
# Download URLs for each platform
|
|
@@ -402,7 +410,7 @@ class LlamaServerProcess:
|
|
|
402
410
|
# Llama 3.1's built-in template forces tool-calling format even without tools,
|
|
403
411
|
# so we use a stripped-down template that only handles chat messages.
|
|
404
412
|
"--jinja",
|
|
405
|
-
"--chat-template-file", str(
|
|
413
|
+
"--chat-template-file", str(_get_templates_dir() / "llama31-no-tools.jinja"),
|
|
406
414
|
]
|
|
407
415
|
|
|
408
416
|
# Add LoRA adapter if specified
|
|
@@ -797,8 +797,8 @@ class LLMProxy:
|
|
|
797
797
|
safe_filename = self._validate_cache_filename(filename)
|
|
798
798
|
|
|
799
799
|
response = await self.client.post(
|
|
800
|
-
f"{self.endpoint}/slots/{slot_id}?action=save
|
|
801
|
-
json={},
|
|
800
|
+
f"{self.endpoint}/slots/{slot_id}?action=save",
|
|
801
|
+
json={"filename": safe_filename},
|
|
802
802
|
timeout=30.0,
|
|
803
803
|
)
|
|
804
804
|
if response.status_code == 200:
|
|
@@ -889,8 +889,8 @@ class LLMProxy:
|
|
|
889
889
|
safe_filename = self._validate_cache_filename(filename)
|
|
890
890
|
|
|
891
891
|
response = await self.client.post(
|
|
892
|
-
f"{self.endpoint}/slots/{slot_id}?action=restore
|
|
893
|
-
json={},
|
|
892
|
+
f"{self.endpoint}/slots/{slot_id}?action=restore",
|
|
893
|
+
json={"filename": safe_filename},
|
|
894
894
|
timeout=30.0,
|
|
895
895
|
)
|
|
896
896
|
if response.status_code == 200:
|
|
@@ -52,58 +52,44 @@ class AdapterInfo:
|
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
# Supported models for NPC inference
|
|
55
|
-
# Fine-tuned Loreguard
|
|
56
|
-
#
|
|
57
|
-
# UD = per-layer optimized quantization for better accuracy at same VRAM
|
|
55
|
+
# Fine-tuned Loreguard NPC model based on Llama 3.1 8B Instruct
|
|
56
|
+
# https://huggingface.co/beyond-logic-labs/loreguard-npc-llama3.1-8b-gguf
|
|
58
57
|
# Ordered by recommendation (best first)
|
|
59
58
|
SUPPORTED_MODELS: list[ModelInfo] = [
|
|
60
|
-
# GGUF models with Unsloth Dynamic quantization (cross-platform, uses llama-server)
|
|
61
59
|
ModelInfo(
|
|
62
|
-
id="loreguard-
|
|
63
|
-
name="Loreguard
|
|
64
|
-
filename="loreguard-
|
|
65
|
-
size_gb=6.
|
|
66
|
-
size_bytes=
|
|
60
|
+
id="loreguard-npc-q6k",
|
|
61
|
+
name="Loreguard NPC Llama 3.1 8B Q6_K",
|
|
62
|
+
filename="loreguard-npc-llama3.1-8b-Q6_K.gguf",
|
|
63
|
+
size_gb=6.1,
|
|
64
|
+
size_bytes=6_596_010_976,
|
|
67
65
|
context_length=8192,
|
|
68
|
-
url=f"https://huggingface.co/{HF_ORG}/loreguard-
|
|
66
|
+
url=f"https://huggingface.co/{HF_ORG}/loreguard-npc-llama3.1-8b-gguf/resolve/main/loreguard-npc-llama3.1-8b-Q6_K.gguf",
|
|
69
67
|
description="Recommended. Best quality/size balance.",
|
|
70
68
|
hardware="12GB RAM • 8GB VRAM",
|
|
71
69
|
recommended=True,
|
|
72
70
|
),
|
|
73
71
|
ModelInfo(
|
|
74
|
-
id="loreguard-
|
|
75
|
-
name="Loreguard
|
|
76
|
-
filename="loreguard-
|
|
77
|
-
size_gb=
|
|
78
|
-
size_bytes=
|
|
72
|
+
id="loreguard-npc-q8",
|
|
73
|
+
name="Loreguard NPC Llama 3.1 8B Q8_0",
|
|
74
|
+
filename="loreguard-npc-llama3.1-8b-Q8_0.gguf",
|
|
75
|
+
size_gb=7.9,
|
|
76
|
+
size_bytes=8_540_775_392,
|
|
79
77
|
context_length=8192,
|
|
80
|
-
url=f"https://huggingface.co/{HF_ORG}/loreguard-
|
|
81
|
-
description="
|
|
82
|
-
hardware="
|
|
83
|
-
recommended=False,
|
|
84
|
-
),
|
|
85
|
-
ModelInfo(
|
|
86
|
-
id="loreguard-vanilla-ud-q4km",
|
|
87
|
-
name="Loreguard Vanilla UD Q4_K_M",
|
|
88
|
-
filename="loreguard-vanilla-UD-Q4_K_M.gguf",
|
|
89
|
-
size_gb=4.9,
|
|
90
|
-
size_bytes=5_282_912_544,
|
|
91
|
-
context_length=8192,
|
|
92
|
-
url=f"https://huggingface.co/{HF_ORG}/loreguard-vanilla-gguf/resolve/main/loreguard-vanilla-UD-Q4_K_M.gguf",
|
|
93
|
-
description="Best for 6GB VRAM. Smallest size.",
|
|
94
|
-
hardware="8GB RAM • 6GB VRAM",
|
|
78
|
+
url=f"https://huggingface.co/{HF_ORG}/loreguard-npc-llama3.1-8b-gguf/resolve/main/loreguard-npc-llama3.1-8b-Q8_0.gguf",
|
|
79
|
+
description="Maximum quality. Requires more VRAM.",
|
|
80
|
+
hardware="16GB RAM • 12GB VRAM",
|
|
95
81
|
recommended=False,
|
|
96
82
|
),
|
|
97
83
|
ModelInfo(
|
|
98
|
-
id="loreguard-
|
|
99
|
-
name="Loreguard
|
|
100
|
-
filename="loreguard-
|
|
101
|
-
size_gb=
|
|
102
|
-
size_bytes=
|
|
84
|
+
id="loreguard-npc-f16",
|
|
85
|
+
name="Loreguard NPC Llama 3.1 8B F16",
|
|
86
|
+
filename="loreguard-npc-llama3.1-8b-f16.gguf",
|
|
87
|
+
size_gb=14.9,
|
|
88
|
+
size_bytes=16_068_895_712,
|
|
103
89
|
context_length=8192,
|
|
104
|
-
url=f"https://huggingface.co/{HF_ORG}/loreguard-
|
|
105
|
-
description="
|
|
106
|
-
hardware="
|
|
90
|
+
url=f"https://huggingface.co/{HF_ORG}/loreguard-npc-llama3.1-8b-gguf/resolve/main/loreguard-npc-llama3.1-8b-f16.gguf",
|
|
91
|
+
description="Full precision. Research/fine-tuning use.",
|
|
92
|
+
hardware="32GB RAM • 20GB VRAM",
|
|
107
93
|
recommended=False,
|
|
108
94
|
),
|
|
109
95
|
]
|
|
@@ -600,7 +600,7 @@ wheels = [
|
|
|
600
600
|
|
|
601
601
|
[[package]]
|
|
602
602
|
name = "loreguard-cli"
|
|
603
|
-
version = "0.
|
|
603
|
+
version = "0.14.0"
|
|
604
604
|
source = { editable = "." }
|
|
605
605
|
dependencies = [
|
|
606
606
|
{ name = "aiofiles" },
|
|
@@ -628,6 +628,11 @@ dev = [
|
|
|
628
628
|
{ name = "ruff" },
|
|
629
629
|
]
|
|
630
630
|
|
|
631
|
+
[package.dev-dependencies]
|
|
632
|
+
dev = [
|
|
633
|
+
{ name = "pyinstaller" },
|
|
634
|
+
]
|
|
635
|
+
|
|
631
636
|
[package.metadata]
|
|
632
637
|
requires-dist = [
|
|
633
638
|
{ name = "aiofiles", specifier = ">=24.1.0" },
|
|
@@ -650,6 +655,9 @@ requires-dist = [
|
|
|
650
655
|
]
|
|
651
656
|
provides-extras = ["dev", "build"]
|
|
652
657
|
|
|
658
|
+
[package.metadata.requires-dev]
|
|
659
|
+
dev = [{ name = "pyinstaller", specifier = ">=6.17.0" }]
|
|
660
|
+
|
|
653
661
|
[[package]]
|
|
654
662
|
name = "macholib"
|
|
655
663
|
version = "1.16.4"
|
{loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/.claude/skills/llama-cpp-troubleshooting/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|