neuralnode 2.1.10__tar.gz → 2.1.12__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 (116) hide show
  1. {neuralnode-2.1.10 → neuralnode-2.1.12}/PKG-INFO +1 -1
  2. {neuralnode-2.1.10 → neuralnode-2.1.12}/pyproject.toml +1 -1
  3. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/__init__.py +1 -1
  4. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/providers/horus.py +109 -33
  5. neuralnode-2.1.12/temp_header.gguf +0 -0
  6. {neuralnode-2.1.10 → neuralnode-2.1.12}/.env.example +0 -0
  7. {neuralnode-2.1.10 → neuralnode-2.1.12}/.github/workflows/tests.yml +0 -0
  8. {neuralnode-2.1.10 → neuralnode-2.1.12}/Dockerfile +0 -0
  9. {neuralnode-2.1.10 → neuralnode-2.1.12}/LICENSE +0 -0
  10. {neuralnode-2.1.10 → neuralnode-2.1.12}/README.md +0 -0
  11. {neuralnode-2.1.10 → neuralnode-2.1.12}/docker-compose.yml +0 -0
  12. {neuralnode-2.1.10 → neuralnode-2.1.12}/docs/documentation.md +0 -0
  13. {neuralnode-2.1.10 → neuralnode-2.1.12}/docs/ecosystem_plan.md +0 -0
  14. {neuralnode-2.1.10 → neuralnode-2.1.12}/docs/replica_voice_ids.csv +0 -0
  15. {neuralnode-2.1.10 → neuralnode-2.1.12}/docs/replica_voice_ids.md +0 -0
  16. {neuralnode-2.1.10 → neuralnode-2.1.12}/docs/telegram_guide.md +0 -0
  17. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/agent_with_tools.py +0 -0
  18. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/basic_chat.py +0 -0
  19. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/01_basic_usage.py +0 -0
  20. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/02_horus_lens.py +0 -0
  21. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/03_one_liner.py +0 -0
  22. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/04_custom_cache.py +0 -0
  23. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/05_4bit_quantization.py +0 -0
  24. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/06_8bit_quantization.py +0 -0
  25. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/07_multi_gpu.py +0 -0
  26. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/08_flash_attention.py +0 -0
  27. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/09_data_types.py +0 -0
  28. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/10_generation_params.py +0 -0
  29. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/11_streaming.py +0 -0
  30. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/12_chat_templates.py +0 -0
  31. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/13_offline_mode.py +0 -0
  32. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/14_force_download.py +0 -0
  33. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/15_model_info.py +0 -0
  34. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/16_cpu_offloading.py +0 -0
  35. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/17_cpu_only.py +0 -0
  36. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/18_production_setup.py +0 -0
  37. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/19_gguf_4bit.py +0 -0
  38. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/20_gguf_5bit.py +0 -0
  39. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/21_gguf_6bit.py +0 -0
  40. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/22_gguf_8bit.py +0 -0
  41. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/23_gguf_16bit.py +0 -0
  42. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/24_list_models.py +0 -0
  43. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/25_interactive_chat.py +0 -0
  44. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_codes_camples/README.md +0 -0
  45. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_download_guide.py +0 -0
  46. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_examples.py +0 -0
  47. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_tq_ready_gguf.py +0 -0
  48. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/horus_transformers_features.py +0 -0
  49. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/local_models.py +0 -0
  50. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/neuralnode_v21_complete_demo.py +0 -0
  51. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/shade_model_with_tools.py +0 -0
  52. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/telegram_bot_demo.py +0 -0
  53. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/thinking_mode_example.py +0 -0
  54. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/tts_demo.py +0 -0
  55. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/turboquant_example.py +0 -0
  56. {neuralnode-2.1.10 → neuralnode-2.1.12}/examples/v3_features.py +0 -0
  57. {neuralnode-2.1.10 → neuralnode-2.1.12}/horus_chat_voice.py +0 -0
  58. {neuralnode-2.1.10 → neuralnode-2.1.12}/neuralnode_horus_replica_telegram.ipynb +0 -0
  59. {neuralnode-2.1.10 → neuralnode-2.1.12}/publish.bat +0 -0
  60. {neuralnode-2.1.10 → neuralnode-2.1.12}/publish.sh +0 -0
  61. {neuralnode-2.1.10 → neuralnode-2.1.12}/requirements_shade.txt +0 -0
  62. {neuralnode-2.1.10 → neuralnode-2.1.12}/scripts/setup.py +0 -0
  63. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/debug_import.py +0 -0
  64. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/agents/__init__.py +0 -0
  65. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/chains/__init__.py +0 -0
  66. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/config/__init__.py +0 -0
  67. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/core/__init__.py +0 -0
  68. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/core/openai_blocker.py +0 -0
  69. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/diagnostics/__init__.py +0 -0
  70. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/integrations/discord.py +0 -0
  71. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/integrations/slack.py +0 -0
  72. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/integrations/telegram.py +0 -0
  73. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/integrations/whatsapp.py +0 -0
  74. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/memory/__init__.py +0 -0
  75. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/memory/advanced.py +0 -0
  76. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/prompts/__init__.py +0 -0
  77. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/providers/__init__.py +0 -0
  78. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/providers/base.py +0 -0
  79. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/providers/chat/__init__.py +0 -0
  80. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/providers/chat/ai21.py +0 -0
  81. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/providers/chat/anthropic.py +0 -0
  82. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/providers/chat/cohere.py +0 -0
  83. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/providers/chat/deepseek.py +0 -0
  84. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/providers/chat/fireworks.py +0 -0
  85. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/providers/chat/google.py +0 -0
  86. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/providers/chat/groq.py +0 -0
  87. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/providers/chat/mistral.py +0 -0
  88. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/providers/chat/perplexity.py +0 -0
  89. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/providers/chat/together.py +0 -0
  90. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/providers/chat_models.py +0 -0
  91. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/providers/embeddings.py +0 -0
  92. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/providers/local/__init__.py +0 -0
  93. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/providers/local_providers.py +0 -0
  94. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/providers/text_generation.py +0 -0
  95. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/providers/universal_local.py +0 -0
  96. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/rag/__init__.py +0 -0
  97. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/rag/loaders.py +0 -0
  98. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/reasoning/__init__.py +0 -0
  99. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/replica.py +0 -0
  100. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/speech/__init__.py +0 -0
  101. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/thinking.py +0 -0
  102. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/tools/__init__.py +0 -0
  103. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/tools/advanced.py +0 -0
  104. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/tools/multisearch.py +0 -0
  105. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/tools/system/__init__.py +0 -0
  106. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/tools/system/operations.py +0 -0
  107. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/tools/web/__init__.py +0 -0
  108. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/tts/__init__.py +0 -0
  109. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/turboquant.py +0 -0
  110. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/utils/__init__.py +0 -0
  111. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/utils/dependencies.py +0 -0
  112. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/utils/logger.py +0 -0
  113. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/utils/metrics.py +0 -0
  114. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/vectorstores/__init__.py +0 -0
  115. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/neuralnode/vision/__init__.py +0 -0
  116. {neuralnode-2.1.10 → neuralnode-2.1.12}/src/nn/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: neuralnode
3
- Version: 2.1.10
3
+ Version: 2.1.12
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.10"
7
+ version = "2.1.12"
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"
@@ -42,7 +42,7 @@ Quick Start::
42
42
  text = sr.listen()
43
43
  """
44
44
 
45
- __version__ = "2.1.10"
45
+ __version__ = "2.1.12"
46
46
  __author__ = "NeuralNode Contributors"
47
47
 
48
48
  # ── Core types ────────────────────────────────────────────────────────────────
@@ -477,13 +477,23 @@ class HorusProvider(BaseLLMProvider):
477
477
  with redirect_stdout(devnull), redirect_stderr(devnull):
478
478
  yield
479
479
  finally:
480
- if old_stdout_fd is not None:
481
- os.dup2(old_stdout_fd, 1)
482
- os.close(old_stdout_fd)
483
- if old_stderr_fd is not None:
484
- os.dup2(old_stderr_fd, 2)
485
- os.close(old_stderr_fd)
486
- devnull.close()
480
+ # Always restore fds and close devnull, even if yield raised.
481
+ try:
482
+ if old_stdout_fd is not None:
483
+ os.dup2(old_stdout_fd, 1)
484
+ os.close(old_stdout_fd)
485
+ except OSError:
486
+ pass
487
+ try:
488
+ if old_stderr_fd is not None:
489
+ os.dup2(old_stderr_fd, 2)
490
+ os.close(old_stderr_fd)
491
+ except OSError:
492
+ pass
493
+ try:
494
+ devnull.close()
495
+ except OSError:
496
+ pass
487
497
 
488
498
  def _resolve_device(self) -> str:
489
499
  if torch is not None and torch.cuda.is_available():
@@ -532,10 +542,12 @@ class HorusProvider(BaseLLMProvider):
532
542
  return False
533
543
  if not cls._is_gguf_model_id(model_id):
534
544
  return False
535
- # Check the registry first
545
+ # Check the registry first (both 'task' and 'type' fields)
536
546
  info = cls.HORUS_MODELS.get(model_id, {})
537
547
  if str(info.get("task", "")).lower() == "text-to-image":
538
548
  return True
549
+ if str(info.get("type", "")).lower() == "gguf" and "lens" in model_id.lower():
550
+ return True
539
551
  # Heuristic: "lens" in the model path means text-to-image
540
552
  return "lens" in model_id.lower()
541
553
 
@@ -661,6 +673,16 @@ class HorusProvider(BaseLLMProvider):
661
673
  self.tokenizer = horus_tokenizer
662
674
  self.transformer = horus_transformer
663
675
  self.vae = horus_vae
676
+
677
+ # Initialize VAE scale factor and image processor
678
+ vae_scale = 8
679
+ if hasattr(self, "vae") and self.vae is not None:
680
+ if hasattr(self.vae, "config") and getattr(self.vae.config, "block_out_channels", None) is not None:
681
+ vae_scale = 2 ** (len(self.vae.config.block_out_channels) - 1)
682
+ self.vae_scale_factor = vae_scale
683
+
684
+ from diffusers.image_processor import VaeImageProcessor
685
+ self.image_processor = VaeImageProcessor(vae_scale_factor=self.vae_scale_factor * 2)
664
686
 
665
687
  self.model = PatchedZImagePipeline.from_pretrained(
666
688
  repo_id,
@@ -721,13 +743,28 @@ class HorusProvider(BaseLLMProvider):
721
743
  "Install with: pip install gguf"
722
744
  )
723
745
 
724
- # Force diffusers to recognize the newly installed gguf package
746
+ # Force diffusers to recognize the newly installed gguf package.
747
+ # Guard against versions like 'N/A' (local/editable builds) that break
748
+ # packaging.version.parse and cause an InvalidVersion crash inside
749
+ # diffusers.quantizers.gguf.gguf_quantizer.validate_environment().
725
750
  try:
726
751
  import sys
752
+ import importlib.metadata
753
+ from packaging.version import Version
754
+ try:
755
+ raw_version = importlib.metadata.version("gguf")
756
+ # Validate the version string before injecting it.
757
+ Version(raw_version)
758
+ version = raw_version
759
+ except Exception:
760
+ # Fall back to a known-good sentinel that satisfies diffusers >= 0.10.0 check
761
+ version = "0.19.0"
727
762
  if "diffusers.utils.import_utils" in sys.modules:
728
763
  sys.modules["diffusers.utils.import_utils"]._gguf_available = True
764
+ sys.modules["diffusers.utils.import_utils"]._gguf_version = version
729
765
  import diffusers.utils.import_utils as diffusers_import_utils
730
766
  diffusers_import_utils._gguf_available = True
767
+ diffusers_import_utils._gguf_version = version
731
768
  except Exception:
732
769
  pass
733
770
 
@@ -791,13 +828,35 @@ class HorusProvider(BaseLLMProvider):
791
828
  **transformer_kwargs
792
829
  )
793
830
  except Exception as exc:
831
+ # Try without quantization_config first (handles shape mismatch
832
+ # caused by mismatched ZImageTransformer2DModel config when
833
+ # the GGUF was built with a different architecture variant).
834
+ plain_kwargs = {"torch_dtype": compute_dtype}
794
835
  try:
795
836
  transformer = ZImageTransformer2DModel.from_single_file(
796
837
  model_path,
797
- torch_dtype=compute_dtype
838
+ **plain_kwargs
798
839
  )
799
840
  except Exception:
800
- raise RuntimeError(f"Failed to load GGUF transformer from '{model_path}': {exc}")
841
+ # Last resort: allow size mismatch so at least something loads
842
+ try:
843
+ transformer = ZImageTransformer2DModel.from_single_file(
844
+ model_path,
845
+ ignore_mismatched_sizes=True,
846
+ low_cpu_mem_usage=False,
847
+ **plain_kwargs
848
+ )
849
+ logger.warning(
850
+ "Loaded GGUF transformer with ignored size mismatches. "
851
+ "Image quality may be degraded. Consider using the full (non-GGUF) "
852
+ "Horus-Lens-1.0 model for best results."
853
+ )
854
+ except Exception:
855
+ raise RuntimeError(
856
+ f"Failed to load GGUF transformer from '{model_path}': {exc}\n"
857
+ "Hint: The GGUF file may be incompatible with the installed diffusers "
858
+ "version. Try: pip install --upgrade diffusers"
859
+ )
801
860
 
802
861
  base_repo_id = "tokenaii/Horus-Lens-1.0"
803
862
  pipeline_kwargs: Dict[str, Any] = {
@@ -843,6 +902,16 @@ class HorusProvider(BaseLLMProvider):
843
902
  self.tokenizer = horus_tokenizer
844
903
  self.transformer = horus_transformer
845
904
  self.vae = horus_vae
905
+
906
+ # Initialize VAE scale factor and image processor
907
+ vae_scale = 8
908
+ if hasattr(self, "vae") and self.vae is not None:
909
+ if hasattr(self.vae, "config") and getattr(self.vae.config, "block_out_channels", None) is not None:
910
+ vae_scale = 2 ** (len(self.vae.config.block_out_channels) - 1)
911
+ self.vae_scale_factor = vae_scale
912
+
913
+ from diffusers.image_processor import VaeImageProcessor
914
+ self.image_processor = VaeImageProcessor(vae_scale_factor=self.vae_scale_factor * 2)
846
915
 
847
916
  with self._quiet_native_output():
848
917
  self.model = PatchedZImagePipeline.from_pretrained(
@@ -891,23 +960,25 @@ class HorusProvider(BaseLLMProvider):
891
960
  prev_disable_progress = os.environ.get("HF_HUB_DISABLE_PROGRESS_BARS")
892
961
  if self.suppress_native_output:
893
962
  os.environ["HF_HUB_DISABLE_PROGRESS_BARS"] = "1"
894
- with warnings.catch_warnings():
895
- warnings.filterwarnings(
896
- "ignore",
897
- message=r".*You are sending unauthenticated requests to the HF Hub.*",
898
- )
899
- model_path = hf_hub_download(
900
- repo_id=repo_id,
901
- filename=filename,
902
- cache_dir=self.cache_dir,
903
- local_files_only=self.local_files_only,
904
- token=self.token,
905
- )
906
- if self.suppress_native_output:
907
- if prev_disable_progress is None:
908
- os.environ.pop("HF_HUB_DISABLE_PROGRESS_BARS", None)
909
- else:
910
- os.environ["HF_HUB_DISABLE_PROGRESS_BARS"] = prev_disable_progress
963
+ try:
964
+ with warnings.catch_warnings():
965
+ warnings.filterwarnings(
966
+ "ignore",
967
+ message=r".*You are sending unauthenticated requests to the HF Hub.*",
968
+ )
969
+ model_path = hf_hub_download(
970
+ repo_id=repo_id,
971
+ filename=filename,
972
+ cache_dir=self.cache_dir,
973
+ local_files_only=self.local_files_only,
974
+ token=self.token,
975
+ )
976
+ finally:
977
+ if self.suppress_native_output:
978
+ if prev_disable_progress is None:
979
+ os.environ.pop("HF_HUB_DISABLE_PROGRESS_BARS", None)
980
+ else:
981
+ os.environ["HF_HUB_DISABLE_PROGRESS_BARS"] = prev_disable_progress
911
982
 
912
983
  llama_kwargs: Dict[str, Any] = {
913
984
  "model_path": model_path,
@@ -1518,17 +1589,23 @@ class HorusProvider(BaseLLMProvider):
1518
1589
  # Add tool descriptions to system prompt if tools are provided
1519
1590
  if tools:
1520
1591
  tool_desc = self._format_tool_descriptions(tools)
1592
+ tool_section = (
1593
+ "\n\nAvailable tools:\n"
1594
+ + tool_desc
1595
+ + "\n\nTo call a tool, respond with valid JSON: "
1596
+ '{"tool": "<name>", "arguments": {"<param>": "<value>"}}'
1597
+ )
1521
1598
  # Find system message or add one
1522
1599
  has_system = False
1523
1600
  for m in normalized:
1524
1601
  if m["role"] == "system":
1525
- m["content"] = m["content"] + "\n\n" + TOOL_CALLING_PROMPT.format(tool_descriptions=tool_desc)
1602
+ m["content"] = m["content"] + tool_section
1526
1603
  has_system = True
1527
1604
  break
1528
1605
  if not has_system:
1529
1606
  normalized.insert(0, {
1530
1607
  "role": "system",
1531
- "content": UNIFIED_SYSTEM_PROMPT + "\n\n" + TOOL_CALLING_PROMPT.format(tool_descriptions=tool_desc)
1608
+ "content": UNIFIED_SYSTEM_PROMPT + tool_section
1532
1609
  })
1533
1610
 
1534
1611
  prompt = self._render_prompt(normalized)
@@ -1571,7 +1648,7 @@ class HorusProvider(BaseLLMProvider):
1571
1648
  )
1572
1649
 
1573
1650
  async def achat(self, messages: List[Dict[str, Any]], **kwargs) -> Union[LLMResponse, Iterator[StreamingChunk]]:
1574
- loop = asyncio.get_event_loop()
1651
+ loop = asyncio.get_running_loop()
1575
1652
  return await loop.run_in_executor(None, lambda: self.chat(messages, **kwargs))
1576
1653
 
1577
1654
  def complete(self, prompt: str, model: Optional[str] = None, **kwargs) -> LLMResponse:
@@ -1699,8 +1776,7 @@ class HorusProvider(BaseLLMProvider):
1699
1776
 
1700
1777
  async def aembed(self, texts: Union[str, List[str]], model: Optional[str] = None, **kwargs) -> Union[List[float], List[List[float]]]:
1701
1778
  """Async version of embed - runs in executor."""
1702
- import asyncio
1703
- loop = asyncio.get_event_loop()
1779
+ loop = asyncio.get_running_loop()
1704
1780
  return await loop.run_in_executor(None, lambda: self.embed(texts, model=model, **kwargs))
1705
1781
 
1706
1782
  def get_model_info(self) -> Dict[str, Any]:
Binary file
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes