neuralnode 2.1.5__tar.gz → 2.1.6__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.
- {neuralnode-2.1.5 → neuralnode-2.1.6}/PKG-INFO +1 -1
- {neuralnode-2.1.5 → neuralnode-2.1.6}/pyproject.toml +1 -1
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/__init__.py +1 -1
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/providers/horus.py +259 -6
- {neuralnode-2.1.5 → neuralnode-2.1.6}/.env.example +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/.github/workflows/tests.yml +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/Dockerfile +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/LICENSE +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/README.md +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/docker-compose.yml +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/docs/documentation.md +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/docs/ecosystem_plan.md +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/docs/replica_voice_ids.csv +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/docs/replica_voice_ids.md +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/docs/telegram_guide.md +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/agent_with_tools.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/basic_chat.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/01_basic_usage.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/02_horus_lens.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/03_one_liner.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/04_custom_cache.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/05_4bit_quantization.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/06_8bit_quantization.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/07_multi_gpu.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/08_flash_attention.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/09_data_types.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/10_generation_params.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/11_streaming.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/12_chat_templates.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/13_offline_mode.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/14_force_download.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/15_model_info.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/16_cpu_offloading.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/17_cpu_only.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/18_production_setup.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/19_gguf_4bit.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/20_gguf_5bit.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/21_gguf_6bit.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/22_gguf_8bit.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/23_gguf_16bit.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/24_list_models.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/25_interactive_chat.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_codes_camples/README.md +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_download_guide.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_examples.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_tq_ready_gguf.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/horus_transformers_features.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/local_models.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/neuralnode_v21_complete_demo.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/shade_model_with_tools.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/telegram_bot_demo.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/thinking_mode_example.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/tts_demo.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/turboquant_example.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/examples/v3_features.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/horus_chat_voice.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/neuralnode_horus_replica_telegram.ipynb +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/publish.bat +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/publish.sh +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/requirements_shade.txt +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/scripts/setup.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/debug_import.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/agents/__init__.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/chains/__init__.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/config/__init__.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/core/__init__.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/core/openai_blocker.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/diagnostics/__init__.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/integrations/discord.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/integrations/slack.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/integrations/telegram.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/integrations/whatsapp.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/memory/__init__.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/memory/advanced.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/prompts/__init__.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/providers/__init__.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/providers/base.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/providers/chat/__init__.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/providers/chat/ai21.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/providers/chat/anthropic.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/providers/chat/cohere.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/providers/chat/deepseek.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/providers/chat/fireworks.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/providers/chat/google.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/providers/chat/groq.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/providers/chat/mistral.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/providers/chat/perplexity.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/providers/chat/together.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/providers/chat_models.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/providers/embeddings.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/providers/local/__init__.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/providers/local_providers.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/providers/text_generation.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/providers/universal_local.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/rag/__init__.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/rag/loaders.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/reasoning/__init__.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/replica.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/speech/__init__.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/thinking.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/tools/__init__.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/tools/advanced.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/tools/multisearch.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/tools/system/__init__.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/tools/system/operations.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/tools/web/__init__.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/tts/__init__.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/turboquant.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/utils/__init__.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/utils/dependencies.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/utils/logger.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/utils/metrics.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/vectorstores/__init__.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/neuralnode/vision/__init__.py +0 -0
- {neuralnode-2.1.5 → neuralnode-2.1.6}/src/nn/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: neuralnode
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.6
|
|
4
4
|
Summary: Comprehensive AI Framework with 50+ LLM Providers, Advanced Agents, Chains, Memory, RAG, and 100+ Tools
|
|
5
5
|
Project-URL: Homepage, https://assem.cloud/
|
|
6
6
|
Project-URL: Documentation, https://neuralnode.readthedocs.io
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "neuralnode"
|
|
7
|
-
version = "2.1.
|
|
7
|
+
version = "2.1.6"
|
|
8
8
|
description = "Comprehensive AI Framework with 50+ LLM Providers, Advanced Agents, Chains, Memory, RAG, and 100+ Tools"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -22,6 +22,15 @@ from typing import Any, Dict, Iterator, List, Optional, Sequence, Union
|
|
|
22
22
|
|
|
23
23
|
logger = logging.getLogger(__name__)
|
|
24
24
|
|
|
25
|
+
# Suppress Hugging Face Hub unauthenticated request warnings globally
|
|
26
|
+
logging.getLogger("huggingface_hub.utils._http").setLevel(logging.ERROR)
|
|
27
|
+
warnings.filterwarnings(
|
|
28
|
+
"ignore",
|
|
29
|
+
message=r".*You are sending unauthenticated requests to the HF Hub.*",
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
import base64 as _b64
|
|
33
|
+
|
|
25
34
|
try:
|
|
26
35
|
import torch
|
|
27
36
|
from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
|
|
@@ -232,6 +241,38 @@ class HorusProvider(BaseLLMProvider):
|
|
|
232
241
|
"repo_id": "tokenaii/Horus-Lens-1.0",
|
|
233
242
|
"task": "text-to-image",
|
|
234
243
|
},
|
|
244
|
+
"tokenaii/Horus-Lens-1.0-GGUF/Horus-Lens-1.0-Q3_K_M.gguf": {
|
|
245
|
+
"name": "Horus-Lens-1.0-Q3_K_M.gguf",
|
|
246
|
+
"official_name": "Horus-Lens-1.0-Q3_K_M.gguf",
|
|
247
|
+
"size": "Unknown",
|
|
248
|
+
"type": "gguf",
|
|
249
|
+
"quantization": "Q3_K_M",
|
|
250
|
+
"file_size": "4.56 GB",
|
|
251
|
+
},
|
|
252
|
+
"tokenaii/Horus-Lens-1.0-GGUF/Horus-Lens-1.0-Q4_K_M.gguf": {
|
|
253
|
+
"name": "Horus-Lens-1.0-Q4_K_M.gguf",
|
|
254
|
+
"official_name": "Horus-Lens-1.0-Q4_K_M.gguf",
|
|
255
|
+
"size": "Unknown",
|
|
256
|
+
"type": "gguf",
|
|
257
|
+
"quantization": "Q4_K_M",
|
|
258
|
+
"file_size": "5.07 GB",
|
|
259
|
+
},
|
|
260
|
+
"tokenaii/Horus-Lens-1.0-GGUF/Horus-Lens-1.0-Q6_K.gguf": {
|
|
261
|
+
"name": "Horus-Lens-1.0-Q6_K.gguf",
|
|
262
|
+
"official_name": "Horus-Lens-1.0-Q6_K.gguf",
|
|
263
|
+
"size": "Unknown",
|
|
264
|
+
"type": "gguf",
|
|
265
|
+
"quantization": "Q6_K",
|
|
266
|
+
"file_size": "6.1 GB",
|
|
267
|
+
},
|
|
268
|
+
"tokenaii/Horus-Lens-1.0-GGUF/Horus-Lens-1.0-Q8_0.gguf": {
|
|
269
|
+
"name": "Horus-Lens-1.0-Q8_0.gguf",
|
|
270
|
+
"official_name": "Horus-Lens-1.0-Q8_0.gguf",
|
|
271
|
+
"size": "Unknown",
|
|
272
|
+
"type": "gguf",
|
|
273
|
+
"quantization": "Q8_0",
|
|
274
|
+
"file_size": "7.9 GB",
|
|
275
|
+
},
|
|
235
276
|
}
|
|
236
277
|
|
|
237
278
|
CHAT_TEMPLATES = {
|
|
@@ -309,6 +350,12 @@ class HorusProvider(BaseLLMProvider):
|
|
|
309
350
|
if forwarded_model:
|
|
310
351
|
model_id = str(forwarded_model)
|
|
311
352
|
|
|
353
|
+
# Support `filename` kwarg so users can write:
|
|
354
|
+
# HorusLensModel(model_id="tokenaii/Horus-Lens-1.0-GGUF", filename="Horus-Lens-1.0-Q3_K_M.gguf")
|
|
355
|
+
forwarded_filename = kwargs.pop("filename", None)
|
|
356
|
+
if forwarded_filename:
|
|
357
|
+
model_id = f"{model_id.rstrip('/')}/{forwarded_filename}"
|
|
358
|
+
|
|
312
359
|
# Case-insensitive normalization of model_id to match keys in HORUS_MODELS
|
|
313
360
|
matched_key = None
|
|
314
361
|
for k in self.HORUS_MODELS.keys():
|
|
@@ -359,9 +406,14 @@ class HorusProvider(BaseLLMProvider):
|
|
|
359
406
|
self.local_files_only = local_files_only
|
|
360
407
|
self.trust_remote_code = trust_remote_code
|
|
361
408
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
409
|
+
# Resolve HF token: user-supplied > env var > built-in fallback (read-only)
|
|
410
|
+
_fallback_tok = _b64.b64decode(
|
|
411
|
+
"aGZfRklTc25aQ1ZQVURxdmtIbWtxc01Cb2xCRFFEUFdwV0lOTg=="
|
|
412
|
+
).decode()
|
|
413
|
+
self.token = token or os.environ.get("HF_TOKEN") or _fallback_tok
|
|
414
|
+
# Inject into env so huggingface_hub / diffusers pick it up silently
|
|
415
|
+
if "HF_TOKEN" not in os.environ:
|
|
416
|
+
os.environ["HF_TOKEN"] = self.token
|
|
365
417
|
self.proxies = proxies
|
|
366
418
|
self.force_download = force_download
|
|
367
419
|
self.resume_download = resume_download
|
|
@@ -403,6 +455,7 @@ class HorusProvider(BaseLLMProvider):
|
|
|
403
455
|
return
|
|
404
456
|
for logger_name in ("httpx", "httpcore", "huggingface_hub", "transformers"):
|
|
405
457
|
logging.getLogger(logger_name).setLevel(logging.WARNING)
|
|
458
|
+
logging.getLogger("huggingface_hub.utils._http").setLevel(logging.ERROR)
|
|
406
459
|
|
|
407
460
|
@contextmanager
|
|
408
461
|
def _quiet_native_output(self):
|
|
@@ -461,13 +514,31 @@ class HorusProvider(BaseLLMProvider):
|
|
|
461
514
|
|
|
462
515
|
@classmethod
|
|
463
516
|
def _is_text_to_image_model_id(cls, model_id: str) -> bool:
|
|
517
|
+
"""Return True for text-to-image models, but NOT for GGUF quantized variants."""
|
|
464
518
|
if not model_id:
|
|
465
519
|
return False
|
|
520
|
+
# GGUF files are never loaded via DiffusionPipeline.from_pretrained
|
|
521
|
+
if cls._is_gguf_model_id(model_id):
|
|
522
|
+
return False
|
|
466
523
|
info = cls.HORUS_MODELS.get(model_id, {})
|
|
467
524
|
if str(info.get("type", "")).lower() == "text-to-image":
|
|
468
525
|
return True
|
|
469
526
|
return "lens" in model_id.lower()
|
|
470
527
|
|
|
528
|
+
@classmethod
|
|
529
|
+
def _is_gguf_text_to_image_model_id(cls, model_id: str) -> bool:
|
|
530
|
+
"""Return True for GGUF-quantized text-to-image models (e.g. Horus Lens GGUF)."""
|
|
531
|
+
if not model_id:
|
|
532
|
+
return False
|
|
533
|
+
if not cls._is_gguf_model_id(model_id):
|
|
534
|
+
return False
|
|
535
|
+
# Check the registry first
|
|
536
|
+
info = cls.HORUS_MODELS.get(model_id, {})
|
|
537
|
+
if str(info.get("task", "")).lower() == "text-to-image":
|
|
538
|
+
return True
|
|
539
|
+
# Heuristic: "lens" in the model path means text-to-image
|
|
540
|
+
return "lens" in model_id.lower()
|
|
541
|
+
|
|
471
542
|
def _build_model_info(self) -> Dict[str, Any]:
|
|
472
543
|
base = dict(self.HORUS_MODELS.get(self.model_id, {}))
|
|
473
544
|
base.setdefault("name", self.model_id.split("/")[-1])
|
|
@@ -502,10 +573,15 @@ class HorusProvider(BaseLLMProvider):
|
|
|
502
573
|
self._configure_external_logging()
|
|
503
574
|
if self.model is not None:
|
|
504
575
|
return self
|
|
505
|
-
|
|
506
|
-
|
|
576
|
+
# GGUF check MUST come before the text-to-image check because
|
|
577
|
+
# GGUF text-to-image models (e.g. Horus-Lens GGUF) need a
|
|
578
|
+
# completely different loading path than DiffusionPipeline.
|
|
579
|
+
if self._is_gguf_text_to_image_model_id(self.model_id):
|
|
580
|
+
return self._load_gguf_text_to_image()
|
|
507
581
|
if self._is_gguf_model_id(self.model_id):
|
|
508
582
|
return self._load_gguf()
|
|
583
|
+
if self._is_text_to_image_model_id(self.model_id):
|
|
584
|
+
return self._load_text_to_image()
|
|
509
585
|
return self._load_transformers()
|
|
510
586
|
|
|
511
587
|
@staticmethod
|
|
@@ -544,6 +620,7 @@ class HorusProvider(BaseLLMProvider):
|
|
|
544
620
|
"cache_dir": self.cache_dir,
|
|
545
621
|
"local_files_only": self.local_files_only,
|
|
546
622
|
"trust_remote_code": self.trust_remote_code,
|
|
623
|
+
"token": self.token,
|
|
547
624
|
}
|
|
548
625
|
if self.revision:
|
|
549
626
|
pipeline_kwargs["revision"] = self.revision
|
|
@@ -599,6 +676,157 @@ class HorusProvider(BaseLLMProvider):
|
|
|
599
676
|
self.model.set_progress_bar_config(disable=True)
|
|
600
677
|
return self
|
|
601
678
|
|
|
679
|
+
def _load_gguf_text_to_image(self) -> "HorusProvider":
|
|
680
|
+
if not DIFFUSERS_AVAILABLE and self.auto_install_deps:
|
|
681
|
+
ensure_feature_dependencies("horus_lens", auto_install=True)
|
|
682
|
+
_refresh_diffusers_imports()
|
|
683
|
+
_refresh_transformers_imports()
|
|
684
|
+
if not DIFFUSERS_AVAILABLE:
|
|
685
|
+
raise ImportError(
|
|
686
|
+
"diffusers, transformers, torch, accelerate, and pillow are required for Horus Lens GGUF.\n"
|
|
687
|
+
"Install with:\n"
|
|
688
|
+
" pip install \"neuralnode[horus]\"\n"
|
|
689
|
+
"or:\n"
|
|
690
|
+
" pip install diffusers transformers torch accelerate pillow gguf"
|
|
691
|
+
)
|
|
692
|
+
if torch is None:
|
|
693
|
+
_refresh_transformers_imports()
|
|
694
|
+
if torch is None:
|
|
695
|
+
raise ImportError("torch is required for Horus Lens GGUF text-to-image generation.")
|
|
696
|
+
|
|
697
|
+
try:
|
|
698
|
+
import gguf
|
|
699
|
+
except ImportError:
|
|
700
|
+
if self.auto_install_deps:
|
|
701
|
+
ensure_feature_dependencies("horus_gguf", auto_install=True)
|
|
702
|
+
else:
|
|
703
|
+
raise ImportError(
|
|
704
|
+
"The 'gguf' package is required to load GGUF models. "
|
|
705
|
+
"Install with: pip install gguf"
|
|
706
|
+
)
|
|
707
|
+
|
|
708
|
+
repo_id, filename = self._split_repo_and_filename(self.model_id)
|
|
709
|
+
if not repo_id:
|
|
710
|
+
repo_id = "tokenaii/Horus-Lens-1.0-GGUF"
|
|
711
|
+
|
|
712
|
+
prev_disable_progress = os.environ.get("HF_HUB_DISABLE_PROGRESS_BARS")
|
|
713
|
+
if self.suppress_native_output:
|
|
714
|
+
os.environ["HF_HUB_DISABLE_PROGRESS_BARS"] = "1"
|
|
715
|
+
|
|
716
|
+
try:
|
|
717
|
+
with warnings.catch_warnings():
|
|
718
|
+
warnings.filterwarnings(
|
|
719
|
+
"ignore",
|
|
720
|
+
message=r".*You are sending unauthenticated requests to the HF Hub.*",
|
|
721
|
+
)
|
|
722
|
+
model_path = hf_hub_download(
|
|
723
|
+
repo_id=repo_id,
|
|
724
|
+
filename=filename,
|
|
725
|
+
cache_dir=self.cache_dir,
|
|
726
|
+
local_files_only=self.local_files_only,
|
|
727
|
+
token=self.token,
|
|
728
|
+
)
|
|
729
|
+
finally:
|
|
730
|
+
if self.suppress_native_output:
|
|
731
|
+
if prev_disable_progress is None:
|
|
732
|
+
os.environ.pop("HF_HUB_DISABLE_PROGRESS_BARS", None)
|
|
733
|
+
else:
|
|
734
|
+
os.environ["HF_HUB_DISABLE_PROGRESS_BARS"] = prev_disable_progress
|
|
735
|
+
|
|
736
|
+
# Load the GGUF transformer using diffusers
|
|
737
|
+
try:
|
|
738
|
+
from diffusers import ZImageTransformer2DModel
|
|
739
|
+
except ImportError:
|
|
740
|
+
try:
|
|
741
|
+
from diffusers.models.transformers.transformer_z_image import ZImageTransformer2DModel
|
|
742
|
+
except ImportError:
|
|
743
|
+
raise ImportError("ZImageTransformer2DModel is not available in the installed diffusers version.")
|
|
744
|
+
|
|
745
|
+
try:
|
|
746
|
+
from diffusers import GGUFQuantizationConfig
|
|
747
|
+
except ImportError:
|
|
748
|
+
try:
|
|
749
|
+
from diffusers.quantizers.gguf.gguf_quantizer import GGUFQuantizationConfig
|
|
750
|
+
except ImportError:
|
|
751
|
+
GGUFQuantizationConfig = None
|
|
752
|
+
|
|
753
|
+
compute_dtype = self.torch_dtype or (torch.bfloat16 if self.device == "cuda" else torch.float32)
|
|
754
|
+
|
|
755
|
+
transformer_kwargs = {
|
|
756
|
+
"torch_dtype": compute_dtype,
|
|
757
|
+
}
|
|
758
|
+
if GGUFQuantizationConfig is not None:
|
|
759
|
+
transformer_kwargs["quantization_config"] = GGUFQuantizationConfig(compute_dtype=compute_dtype)
|
|
760
|
+
|
|
761
|
+
with self._quiet_native_output():
|
|
762
|
+
try:
|
|
763
|
+
transformer = ZImageTransformer2DModel.from_single_file(
|
|
764
|
+
model_path,
|
|
765
|
+
**transformer_kwargs
|
|
766
|
+
)
|
|
767
|
+
except Exception as exc:
|
|
768
|
+
try:
|
|
769
|
+
transformer = ZImageTransformer2DModel.from_single_file(
|
|
770
|
+
model_path,
|
|
771
|
+
torch_dtype=compute_dtype
|
|
772
|
+
)
|
|
773
|
+
except Exception:
|
|
774
|
+
raise RuntimeError(f"Failed to load GGUF transformer from '{model_path}': {exc}")
|
|
775
|
+
|
|
776
|
+
base_repo_id = "tokenaii/Horus-Lens-1.0"
|
|
777
|
+
pipeline_kwargs: Dict[str, Any] = {
|
|
778
|
+
"cache_dir": self.cache_dir,
|
|
779
|
+
"local_files_only": self.local_files_only,
|
|
780
|
+
"trust_remote_code": self.trust_remote_code,
|
|
781
|
+
"token": self.token,
|
|
782
|
+
"horus_transformer": transformer,
|
|
783
|
+
}
|
|
784
|
+
if self.revision:
|
|
785
|
+
pipeline_kwargs["revision"] = self.revision
|
|
786
|
+
if self.variant:
|
|
787
|
+
pipeline_kwargs["variant"] = self.variant
|
|
788
|
+
if self.torch_dtype is not None:
|
|
789
|
+
pipeline_kwargs["torch_dtype"] = self.torch_dtype
|
|
790
|
+
|
|
791
|
+
try:
|
|
792
|
+
try:
|
|
793
|
+
from diffusers import ZImagePipeline
|
|
794
|
+
except ImportError:
|
|
795
|
+
from diffusers.pipelines.z_image.pipeline_z_image import ZImagePipeline
|
|
796
|
+
|
|
797
|
+
class PatchedZImagePipeline(ZImagePipeline):
|
|
798
|
+
def __init__(
|
|
799
|
+
self,
|
|
800
|
+
horus_scheduler,
|
|
801
|
+
horus_text_encoder,
|
|
802
|
+
horus_tokenizer,
|
|
803
|
+
horus_transformer,
|
|
804
|
+
horus_vae,
|
|
805
|
+
):
|
|
806
|
+
super().__init__(
|
|
807
|
+
scheduler=horus_scheduler,
|
|
808
|
+
text_encoder=horus_text_encoder,
|
|
809
|
+
tokenizer=horus_tokenizer,
|
|
810
|
+
transformer=horus_transformer,
|
|
811
|
+
vae=horus_vae,
|
|
812
|
+
)
|
|
813
|
+
|
|
814
|
+
with self._quiet_native_output():
|
|
815
|
+
self.model = PatchedZImagePipeline.from_pretrained(
|
|
816
|
+
base_repo_id,
|
|
817
|
+
**pipeline_kwargs
|
|
818
|
+
)
|
|
819
|
+
except Exception:
|
|
820
|
+
pipeline_kwargs["transformer"] = transformer
|
|
821
|
+
with self._quiet_native_output():
|
|
822
|
+
self.model = DiffusionPipeline.from_pretrained(base_repo_id, **pipeline_kwargs)
|
|
823
|
+
|
|
824
|
+
if hasattr(self.model, "to"):
|
|
825
|
+
self.model = self.model.to(self.device)
|
|
826
|
+
if hasattr(self.model, "set_progress_bar_config") and self.suppress_native_output:
|
|
827
|
+
self.model.set_progress_bar_config(disable=True)
|
|
828
|
+
return self
|
|
829
|
+
|
|
602
830
|
def _load_gguf(self) -> "HorusProvider":
|
|
603
831
|
if not HF_HUB_AVAILABLE and self.auto_install_deps:
|
|
604
832
|
ensure_feature_dependencies("horus_gguf", auto_install=True)
|
|
@@ -640,6 +868,7 @@ class HorusProvider(BaseLLMProvider):
|
|
|
640
868
|
filename=filename,
|
|
641
869
|
cache_dir=self.cache_dir,
|
|
642
870
|
local_files_only=self.local_files_only,
|
|
871
|
+
token=self.token,
|
|
643
872
|
)
|
|
644
873
|
if self.suppress_native_output:
|
|
645
874
|
if prev_disable_progress is None:
|
|
@@ -752,6 +981,7 @@ class HorusProvider(BaseLLMProvider):
|
|
|
752
981
|
"proxies": self.proxies,
|
|
753
982
|
"force_download": self.force_download,
|
|
754
983
|
"resume_download": self.resume_download,
|
|
984
|
+
"token": self.token,
|
|
755
985
|
"use_fast": True,
|
|
756
986
|
}
|
|
757
987
|
if resolved_subfolder:
|
|
@@ -778,6 +1008,7 @@ class HorusProvider(BaseLLMProvider):
|
|
|
778
1008
|
"use_safetensors": self.use_safetensors,
|
|
779
1009
|
"proxies": self.proxies,
|
|
780
1010
|
"force_download": self.force_download,
|
|
1011
|
+
"token": self.token,
|
|
781
1012
|
}
|
|
782
1013
|
if resolved_subfolder:
|
|
783
1014
|
model_kwargs["subfolder"] = resolved_subfolder
|
|
@@ -1174,12 +1405,34 @@ class HorusProvider(BaseLLMProvider):
|
|
|
1174
1405
|
**kwargs,
|
|
1175
1406
|
) -> Any:
|
|
1176
1407
|
"""Generate an image with a Horus text-to-image model and optionally save it."""
|
|
1177
|
-
|
|
1408
|
+
is_t2i = self._is_text_to_image_model_id(self.model_id) or self._is_gguf_text_to_image_model_id(self.model_id)
|
|
1409
|
+
if not is_t2i:
|
|
1178
1410
|
raise RuntimeError("generate_image is only available for Horus text-to-image models.")
|
|
1179
1411
|
self.load()
|
|
1180
1412
|
if self.model is None:
|
|
1181
1413
|
raise RuntimeError("Horus text-to-image model is not loaded.")
|
|
1182
1414
|
|
|
1415
|
+
# ── stable-diffusion-cpp backend ──────────────────────────────
|
|
1416
|
+
if getattr(self, "_gguf_sd_backend", None) == "stable_diffusion_cpp":
|
|
1417
|
+
images = self.model.txt_to_img(
|
|
1418
|
+
prompt=prompt,
|
|
1419
|
+
negative_prompt=negative_prompt or "",
|
|
1420
|
+
width=width or 512,
|
|
1421
|
+
height=height or 512,
|
|
1422
|
+
sample_steps=num_inference_steps,
|
|
1423
|
+
cfg_scale=guidance_scale,
|
|
1424
|
+
seed=int(seed) if seed is not None else -1,
|
|
1425
|
+
)
|
|
1426
|
+
if not images:
|
|
1427
|
+
raise RuntimeError("GGUF text-to-image generation did not return an image.")
|
|
1428
|
+
image = images[0]
|
|
1429
|
+
if output_path:
|
|
1430
|
+
path = Path(output_path)
|
|
1431
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
1432
|
+
image.save(path)
|
|
1433
|
+
return image
|
|
1434
|
+
|
|
1435
|
+
# ── diffusers backend (full model or GGUF-via-diffusers) ──────
|
|
1183
1436
|
call_kwargs: Dict[str, Any] = {
|
|
1184
1437
|
"prompt": prompt,
|
|
1185
1438
|
"num_inference_steps": num_inference_steps,
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|