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.
Files changed (62) hide show
  1. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/PKG-INFO +1 -1
  2. loreguard_cli-0.14.1/loreguard.spec +42 -0
  3. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/pyproject.toml +6 -1
  4. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/scripts/build.py +2 -0
  5. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/cli.py +26 -22
  6. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/config.py +85 -4
  7. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/llama_server.py +9 -1
  8. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/llm.py +4 -4
  9. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/models_registry.py +24 -38
  10. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/uv.lock +9 -1
  11. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/.claude/skills/llama-cpp-troubleshooting/SKILL.md +0 -0
  12. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/.env.example +0 -0
  13. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/.github/workflows/release.yml +0 -0
  14. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/.gitignore +0 -0
  15. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/LICENSE +0 -0
  16. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/README.md +0 -0
  17. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/THIRD_PARTY_NOTICES.md +0 -0
  18. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/loreguard_entry.py +0 -0
  19. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/sdk/API.md +0 -0
  20. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/sdk/csharp/LoreguardSDK.cs +0 -0
  21. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/sdk/gdscript/LoreguardSDK.gd +0 -0
  22. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/sdk/javascript/loreguard-sdk.js +0 -0
  23. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/sdk/python/loreguard_sdk.py +0 -0
  24. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/__init__.py +0 -0
  25. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/__main__.py +0 -0
  26. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/chunk_detector.py +0 -0
  27. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/dialogue_act_classifier.py +0 -0
  28. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/hf_discovery.py +0 -0
  29. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/http_server.py +0 -0
  30. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/intent_classifier.py +0 -0
  31. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/main.py +0 -0
  32. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/nli.py +0 -0
  33. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/npc_chat.py +0 -0
  34. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/runtime.py +0 -0
  35. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/steam.py +0 -0
  36. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/term_ui.py +0 -0
  37. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/__init__.py +0 -0
  38. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/app.py +0 -0
  39. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/modals/__init__.py +0 -0
  40. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/modals/auth_menu.py +0 -0
  41. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/modals/npc_chat.py +0 -0
  42. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/modals/token_input.py +0 -0
  43. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/modals/unified_palette.py +0 -0
  44. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/screens/__init__.py +0 -0
  45. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/screens/auth.py +0 -0
  46. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/screens/main.py +0 -0
  47. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/screens/model_select.py +0 -0
  48. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/screens/nli_setup.py +0 -0
  49. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/screens/running.py +0 -0
  50. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/styles.py +0 -0
  51. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/widgets/__init__.py +0 -0
  52. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/widgets/banner.py +0 -0
  53. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/widgets/footer.py +0 -0
  54. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/widgets/hardware_info.py +0 -0
  55. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/widgets/npc_chat.py +0 -0
  56. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/widgets/server_monitor.py +0 -0
  57. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tui/widgets/status_panel.py +0 -0
  58. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/tunnel.py +0 -0
  59. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/src/wizard.py +0 -0
  60. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/templates/llama31-no-tools.jinja +0 -0
  61. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/tests/test_nli_hhem.py +0 -0
  62. {loreguard_cli-0.14.0 → loreguard_cli-0.14.1}/tests/test_websocket_timeout.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: loreguard-cli
3
- Version: 0.14.0
3
+ Version: 0.14.1
4
4
  Summary: Local inference client for Loreguard NPCs
5
5
  Project-URL: Homepage, https://loreguard.com
6
6
  Project-URL: Documentation, https://github.com/beyond-logic-labs/loreguard-cli#readme
@@ -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.0"
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
- self.worker_id = worker_id or socket.gethostname() or "worker"
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
- # Initialize dialogue act classifier
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
- # Validate token is present (server will validate format)
513
- if not args.token:
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
- Returns None if not set, meaning models should be auto-downloaded from HF.
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
- models_dir = get_models_dir()
191
- if models_dir and subdir:
192
- local_path = models_dir / subdir
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(Path(__file__).parent.parent / "templates" / "llama31-no-tools.jinja"),
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&filename={safe_filename}",
801
- json={}, # llama-server expects JSON body
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&filename={safe_filename}",
893
- json={}, # llama-server expects JSON body
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 models with multi-pass pipeline training
56
- # Based on unsloth/Llama-3.1-8B-Instruct with Unsloth Dynamic (UD) quantization
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-vanilla-ud-q6k",
63
- name="Loreguard Vanilla UD Q6_K",
64
- filename="loreguard-vanilla-UD-Q6_K.gguf",
65
- size_gb=6.6,
66
- size_bytes=7_085_559_072,
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-vanilla-gguf/resolve/main/loreguard-vanilla-UD-Q6_K.gguf",
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-vanilla-ud-q5km",
75
- name="Loreguard Vanilla UD Q5_K_M",
76
- filename="loreguard-vanilla-UD-Q5_K_M.gguf",
77
- size_gb=5.7,
78
- size_bytes=6_145_035_552,
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-vanilla-gguf/resolve/main/loreguard-vanilla-UD-Q5_K_M.gguf",
81
- description="Good quality, smaller size.",
82
- hardware="10GB RAM • 6-8GB VRAM",
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-vanilla-ud-q8",
99
- name="Loreguard Vanilla UD Q8_0",
100
- filename="loreguard-vanilla-UD-Q8_0.gguf",
101
- size_gb=8.5,
102
- size_bytes=9_177_550_624,
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-vanilla-gguf/resolve/main/loreguard-vanilla-UD-Q8_0.gguf",
105
- description="Maximum quality. Requires more VRAM.",
106
- hardware="16GB RAM • 12GB VRAM",
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.12.2"
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"
File without changes
File without changes