SimplerLLM 0.3.4__tar.gz → 0.3.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.
- simplerllm-0.3.6/MANIFEST.in +3 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/PKG-INFO +5 -2
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm/wrappers/anthropic_wrapper.py +2 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm/wrappers/openai_wrapper.py +2 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_addons/json_generation.py +13 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_providers/anthropic_llm.py +16 -2
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_providers/openai_llm.py +26 -10
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/tools/json_helpers.py +180 -17
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM.egg-info/PKG-INFO +5 -2
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM.egg-info/SOURCES.txt +3 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM.egg-info/requires.txt +3 -1
- simplerllm-0.3.6/requirements.txt +30 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/setup.py +6 -1
- simplerllm-0.3.6/tests/test_aspect_ratio_debug.py +114 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_pydantic_json.py +1 -1
- {simplerllm-0.3.4 → simplerllm-0.3.6}/LICENSE +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/README.md +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/image/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/image/generation/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/image/generation/base.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/image/generation/providers/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/image/generation/providers/google_image.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/image/generation/providers/image_response_models.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/image/generation/providers/openai_image.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/image/generation/providers/seedream_image.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/image/generation/providers/stability_image.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/image/generation/wrappers/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/image/generation/wrappers/google_wrapper.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/image/generation/wrappers/openai_wrapper.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/image/generation/wrappers/seedream_wrapper.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/image/generation/wrappers/stability_wrapper.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/embeddings/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/embeddings/base.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/embeddings/models.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/embeddings/providers.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm/base.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm/reliable.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm/wrappers/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm/wrappers/cohere_wrapper.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm/wrappers/deepseek_wrapper.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm/wrappers/gemini_wrapper.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm/wrappers/hf_local_wrapper.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm/wrappers/moonshot_wrapper.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm/wrappers/ollama_wrapper.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm/wrappers/openrouter_wrapper.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm/wrappers/perplexity_wrapper.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_addons/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_addons/cost_utils.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_addons/pattern_extraction.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_brainstorm/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_brainstorm/models.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_brainstorm/recursive_brainstorm.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_feedback/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_feedback/feedback_loop.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_feedback/models.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_judge/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_judge/judge.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_judge/models.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_providers/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_providers/cohere_llm.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_providers/deepseek_llm.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_providers/gemini_llm.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_providers/hf_local_llm.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_providers/llm_response_models.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_providers/moonshot_llm.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_providers/ollama_llm.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_providers/openrouter_llm.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_providers/perplexity_llm.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_providers/voyage_llm.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_router/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_router/models.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/language/llm_router/router.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/prompts/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/prompts/hub/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/prompts/hub/agentic_prompts.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/prompts/hub/prompt_manager.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/prompts/messages_template.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/prompts/prompt_builder.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/tools/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/tools/apify_api.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/tools/email_functions.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/tools/file_functions.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/tools/file_loader.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/tools/generic_loader.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/tools/image_helpers.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/tools/pandas_func.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/tools/pattern_helpers.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/tools/python_func.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/tools/rapid_api.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/tools/serp.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/tools/text_chunker.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/tools/youtube.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/utils/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/utils/custom_verbose.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/vectors/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/vectors/base.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/vectors/exceptions.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/vectors/models.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/vectors/providers/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/vectors/providers/local_provider.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/vectors/providers/qdrant_provider.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/vectors/wrappers/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/vectors/wrappers/local_wrapper.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/vectors/wrappers/qdrant_wrapper.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/voice/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/voice/stt/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/voice/stt/base.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/voice/stt/providers/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/voice/stt/providers/openai_stt.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/voice/stt/providers/stt_response_models.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/voice/stt/wrappers/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/voice/stt/wrappers/openai_wrapper.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/voice/tts/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/voice/tts/base.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/voice/tts/factory.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/voice/tts/models.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/voice/tts/providers/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/voice/tts/providers/elevenlabs_tts.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/voice/tts/providers/lahajati_tts.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM/voice/tts/providers/openai_tts.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM.egg-info/dependency_links.txt +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/SimplerLLM.egg-info/top_level.txt +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/setup.cfg +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/__init__.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_anthropic.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_brainstorm.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_cohere.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_deepseek.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_embeddings.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_gemini.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_google_image.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_hf_local.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_hf_mini.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_judge.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_lahajati_tts.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_llm_addons.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_moonshot.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_ollama.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_openai.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_openai_image.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_openrouter.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_perplexity.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_pydantic_advanced.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_reliable.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_reliable_pydantic.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_seedream_image.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_stability_image.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_tts.py +0 -0
- {simplerllm-0.3.4 → simplerllm-0.3.6}/tests/test_vectors.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: SimplerLLM
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.6
|
|
4
4
|
Summary: An easy-to-use Library for interacting with language models.
|
|
5
5
|
Home-page: https://github.com/hassancs91/SimplerLLM
|
|
6
6
|
Author: Hasan Aboul Hasan
|
|
@@ -18,6 +18,8 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.10
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
23
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
24
|
Requires-Python: >=3.6
|
|
23
25
|
Description-Content-Type: text/markdown
|
|
@@ -43,7 +45,6 @@ Requires-Dist: colorama>=0.4
|
|
|
43
45
|
Requires-Dist: scipy>=1.15
|
|
44
46
|
Requires-Dist: tiktoken>=0.9
|
|
45
47
|
Requires-Dist: qdrant-client==1.14.3
|
|
46
|
-
Requires-Dist: voyageai==0.3.3
|
|
47
48
|
Requires-Dist: pydub>=0.25.1
|
|
48
49
|
Requires-Dist: elevenlabs>=2.22.0
|
|
49
50
|
Requires-Dist: moviepy>=1.0.3
|
|
@@ -52,6 +53,8 @@ Provides-Extra: transformers
|
|
|
52
53
|
Requires-Dist: transformers>=4.36.0; extra == "transformers"
|
|
53
54
|
Requires-Dist: torch>=2.0.0; extra == "transformers"
|
|
54
55
|
Requires-Dist: accelerate>=0.25.0; extra == "transformers"
|
|
56
|
+
Provides-Extra: voyage
|
|
57
|
+
Requires-Dist: voyageai>=0.3.3; extra == "voyage"
|
|
55
58
|
Dynamic: author
|
|
56
59
|
Dynamic: author-email
|
|
57
60
|
Dynamic: classifier
|
|
@@ -89,6 +89,7 @@ class AnthropicLLM(LLM):
|
|
|
89
89
|
max_tokens=max_tokens,
|
|
90
90
|
full_response=full_response,
|
|
91
91
|
api_key=self.api_key,
|
|
92
|
+
json_mode=json_mode,
|
|
92
93
|
)
|
|
93
94
|
if self.verbose:
|
|
94
95
|
verbose_print("Web search response received successfully", "info")
|
|
@@ -241,6 +242,7 @@ class AnthropicLLM(LLM):
|
|
|
241
242
|
max_tokens=max_tokens,
|
|
242
243
|
full_response=full_response,
|
|
243
244
|
api_key=self.api_key,
|
|
245
|
+
json_mode=json_mode,
|
|
244
246
|
)
|
|
245
247
|
if self.verbose:
|
|
246
248
|
verbose_print("Web search response received successfully", "info")
|
|
@@ -245,6 +245,7 @@ class OpenAILLM(LLM):
|
|
|
245
245
|
max_tokens=max_tokens,
|
|
246
246
|
full_response=full_response,
|
|
247
247
|
api_key=self.api_key,
|
|
248
|
+
json_mode=json_mode,
|
|
248
249
|
)
|
|
249
250
|
if self.verbose:
|
|
250
251
|
verbose_print("Web search response received successfully", "info")
|
|
@@ -407,6 +408,7 @@ class OpenAILLM(LLM):
|
|
|
407
408
|
max_tokens=max_tokens,
|
|
408
409
|
full_response=full_response,
|
|
409
410
|
api_key=self.api_key,
|
|
411
|
+
json_mode=json_mode,
|
|
410
412
|
)
|
|
411
413
|
if self.verbose:
|
|
412
414
|
verbose_print("Web search response received successfully", "info")
|
|
@@ -47,6 +47,7 @@ from SimplerLLM.tools.json_helpers import (
|
|
|
47
47
|
validate_json_with_pydantic_model,
|
|
48
48
|
generate_json_example_from_pydantic,
|
|
49
49
|
extract_schema_constraints,
|
|
50
|
+
try_auto_wrap_for_nested_model,
|
|
50
51
|
HAS_ROOT_MODEL,
|
|
51
52
|
RootModel,
|
|
52
53
|
)
|
|
@@ -279,6 +280,9 @@ def generate_pydantic_json_model(
|
|
|
279
280
|
# Handle RootModel list unwrapping (when LLM wraps list in object)
|
|
280
281
|
json_object = _unwrap_rootmodel_list(json_object, model_class)
|
|
281
282
|
|
|
283
|
+
# Handle auto-wrapping for nested models (when LLM returns unwrapped objects)
|
|
284
|
+
json_object = try_auto_wrap_for_nested_model(model_class, json_object)
|
|
285
|
+
|
|
282
286
|
validated, errors = validate_json_with_pydantic_model(
|
|
283
287
|
model_class, json_object
|
|
284
288
|
)
|
|
@@ -411,6 +415,9 @@ def generate_pydantic_json_model_reliable(
|
|
|
411
415
|
# Handle RootModel list unwrapping (when LLM wraps list in object)
|
|
412
416
|
json_object = _unwrap_rootmodel_list(json_object, model_class)
|
|
413
417
|
|
|
418
|
+
# Handle auto-wrapping for nested models (when LLM returns unwrapped objects)
|
|
419
|
+
json_object = try_auto_wrap_for_nested_model(model_class, json_object)
|
|
420
|
+
|
|
414
421
|
validated, errors = validate_json_with_pydantic_model(
|
|
415
422
|
model_class, json_object
|
|
416
423
|
)
|
|
@@ -541,6 +548,9 @@ async def generate_pydantic_json_model_async(
|
|
|
541
548
|
# Handle RootModel list unwrapping (when LLM wraps list in object)
|
|
542
549
|
json_object = _unwrap_rootmodel_list(json_object, model_class)
|
|
543
550
|
|
|
551
|
+
# Handle auto-wrapping for nested models (when LLM returns unwrapped objects)
|
|
552
|
+
json_object = try_auto_wrap_for_nested_model(model_class, json_object)
|
|
553
|
+
|
|
544
554
|
validated, errors = validate_json_with_pydantic_model(
|
|
545
555
|
model_class, json_object
|
|
546
556
|
)
|
|
@@ -674,6 +684,9 @@ async def generate_pydantic_json_model_reliable_async(
|
|
|
674
684
|
# Handle RootModel list unwrapping (when LLM wraps list in object)
|
|
675
685
|
json_object = _unwrap_rootmodel_list(json_object, model_class)
|
|
676
686
|
|
|
687
|
+
# Handle auto-wrapping for nested models (when LLM returns unwrapped objects)
|
|
688
|
+
json_object = try_auto_wrap_for_nested_model(model_class, json_object)
|
|
689
|
+
|
|
677
690
|
validated, errors = validate_json_with_pydantic_model(
|
|
678
691
|
model_class, json_object
|
|
679
692
|
)
|
|
@@ -443,6 +443,7 @@ def generate_response_with_web_search(
|
|
|
443
443
|
max_tokens: int = 300,
|
|
444
444
|
full_response: bool = False,
|
|
445
445
|
api_key: Optional[str] = None,
|
|
446
|
+
json_mode: bool = False,
|
|
446
447
|
) -> Optional[Dict]:
|
|
447
448
|
"""
|
|
448
449
|
Generate a response using Anthropic's Messages API with web search enabled.
|
|
@@ -454,6 +455,7 @@ def generate_response_with_web_search(
|
|
|
454
455
|
max_tokens: Maximum tokens for the response
|
|
455
456
|
full_response: If True, returns LLMFullResponse with web_sources
|
|
456
457
|
api_key: Anthropic API key
|
|
458
|
+
json_mode: If True, enhances system prompt to request JSON output
|
|
457
459
|
|
|
458
460
|
Returns:
|
|
459
461
|
str or LLMFullResponse: Generated text or full response with web sources
|
|
@@ -475,6 +477,11 @@ def generate_response_with_web_search(
|
|
|
475
477
|
|
|
476
478
|
client = Anthropic(api_key=api_key)
|
|
477
479
|
|
|
480
|
+
# Enhance system prompt for JSON mode
|
|
481
|
+
effective_system_prompt = system_prompt
|
|
482
|
+
if json_mode:
|
|
483
|
+
effective_system_prompt = f"{system_prompt}\n\nIMPORTANT: You MUST respond with valid JSON only. No additional text or explanation outside the JSON structure."
|
|
484
|
+
|
|
478
485
|
# Execute with retry logic
|
|
479
486
|
response = None
|
|
480
487
|
last_error = None
|
|
@@ -484,7 +491,7 @@ def generate_response_with_web_search(
|
|
|
484
491
|
response = client.messages.create(
|
|
485
492
|
model=model_name,
|
|
486
493
|
max_tokens=max_tokens,
|
|
487
|
-
system=
|
|
494
|
+
system=effective_system_prompt,
|
|
488
495
|
messages=messages,
|
|
489
496
|
tools=[{
|
|
490
497
|
"type": "web_search_20250305",
|
|
@@ -550,6 +557,7 @@ async def generate_response_with_web_search_async(
|
|
|
550
557
|
max_tokens: int = 300,
|
|
551
558
|
full_response: bool = False,
|
|
552
559
|
api_key: Optional[str] = None,
|
|
560
|
+
json_mode: bool = False,
|
|
553
561
|
) -> Optional[Dict]:
|
|
554
562
|
"""
|
|
555
563
|
Asynchronously generate a response using Anthropic's Messages API with web search enabled.
|
|
@@ -561,6 +569,7 @@ async def generate_response_with_web_search_async(
|
|
|
561
569
|
max_tokens: Maximum tokens for the response
|
|
562
570
|
full_response: If True, returns LLMFullResponse with web_sources
|
|
563
571
|
api_key: Anthropic API key
|
|
572
|
+
json_mode: If True, enhances system prompt to request JSON output
|
|
564
573
|
|
|
565
574
|
Returns:
|
|
566
575
|
str or LLMFullResponse: Generated text or full response with web sources
|
|
@@ -584,6 +593,11 @@ async def generate_response_with_web_search_async(
|
|
|
584
593
|
|
|
585
594
|
client = AsyncAnthropic(api_key=api_key)
|
|
586
595
|
|
|
596
|
+
# Enhance system prompt for JSON mode
|
|
597
|
+
effective_system_prompt = system_prompt
|
|
598
|
+
if json_mode:
|
|
599
|
+
effective_system_prompt = f"{system_prompt}\n\nIMPORTANT: You MUST respond with valid JSON only. No additional text or explanation outside the JSON structure."
|
|
600
|
+
|
|
587
601
|
# Execute with retry logic
|
|
588
602
|
response = None
|
|
589
603
|
last_error = None
|
|
@@ -593,7 +607,7 @@ async def generate_response_with_web_search_async(
|
|
|
593
607
|
response = await client.messages.create(
|
|
594
608
|
model=model_name,
|
|
595
609
|
max_tokens=max_tokens,
|
|
596
|
-
system=
|
|
610
|
+
system=effective_system_prompt,
|
|
597
611
|
messages=messages,
|
|
598
612
|
tools=[{
|
|
599
613
|
"type": "web_search_20250305",
|
|
@@ -713,6 +713,7 @@ def generate_response_with_web_search(
|
|
|
713
713
|
max_tokens=300,
|
|
714
714
|
full_response=False,
|
|
715
715
|
api_key=None,
|
|
716
|
+
json_mode=False,
|
|
716
717
|
):
|
|
717
718
|
"""
|
|
718
719
|
Generate a response using OpenAI's Responses API with web search enabled.
|
|
@@ -723,6 +724,7 @@ def generate_response_with_web_search(
|
|
|
723
724
|
max_tokens: Maximum tokens for the response
|
|
724
725
|
full_response: If True, returns LLMFullResponse with web_sources
|
|
725
726
|
api_key: OpenAI API key
|
|
727
|
+
json_mode: If True, enables JSON output format
|
|
726
728
|
|
|
727
729
|
Returns:
|
|
728
730
|
str or LLMFullResponse: Generated text or full response with web sources
|
|
@@ -732,11 +734,17 @@ def generate_response_with_web_search(
|
|
|
732
734
|
|
|
733
735
|
for attempt in range(MAX_RETRIES):
|
|
734
736
|
try:
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
737
|
+
# Build request parameters
|
|
738
|
+
# Note: JSON mode is NOT supported with web search in OpenAI's Responses API
|
|
739
|
+
# The json_mode parameter is accepted but ignored - JSON extraction happens
|
|
740
|
+
# post-response via extract_json_from_text() in json_generation.py
|
|
741
|
+
request_params = {
|
|
742
|
+
"model": model_name,
|
|
743
|
+
"input": input_text,
|
|
744
|
+
"tools": [{"type": "web_search"}],
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
response = openai_client.responses.create(**request_params)
|
|
740
748
|
|
|
741
749
|
# Extract text and citations from the response
|
|
742
750
|
generated_text = ""
|
|
@@ -784,6 +792,7 @@ async def generate_response_with_web_search_async(
|
|
|
784
792
|
max_tokens=300,
|
|
785
793
|
full_response=False,
|
|
786
794
|
api_key=None,
|
|
795
|
+
json_mode=False,
|
|
787
796
|
):
|
|
788
797
|
"""
|
|
789
798
|
Asynchronously generate a response using OpenAI's Responses API with web search enabled.
|
|
@@ -794,6 +803,7 @@ async def generate_response_with_web_search_async(
|
|
|
794
803
|
max_tokens: Maximum tokens for the response
|
|
795
804
|
full_response: If True, returns LLMFullResponse with web_sources
|
|
796
805
|
api_key: OpenAI API key
|
|
806
|
+
json_mode: If True, enables JSON output format
|
|
797
807
|
|
|
798
808
|
Returns:
|
|
799
809
|
str or LLMFullResponse: Generated text or full response with web sources
|
|
@@ -803,11 +813,17 @@ async def generate_response_with_web_search_async(
|
|
|
803
813
|
|
|
804
814
|
for attempt in range(MAX_RETRIES):
|
|
805
815
|
try:
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
816
|
+
# Build request parameters
|
|
817
|
+
# Note: JSON mode is NOT supported with web search in OpenAI's Responses API
|
|
818
|
+
# The json_mode parameter is accepted but ignored - JSON extraction happens
|
|
819
|
+
# post-response via extract_json_from_text() in json_generation.py
|
|
820
|
+
request_params = {
|
|
821
|
+
"model": model_name,
|
|
822
|
+
"input": input_text,
|
|
823
|
+
"tools": [{"type": "web_search"}],
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
response = await async_openai_client.responses.create(**request_params)
|
|
811
827
|
|
|
812
828
|
# Extract text and citations from the response
|
|
813
829
|
generated_text = ""
|
|
@@ -15,6 +15,38 @@ except ImportError:
|
|
|
15
15
|
RootModel = None
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
def _is_decimal_type(field_type) -> bool:
|
|
19
|
+
"""Check if a type is Decimal, handling various import scenarios."""
|
|
20
|
+
if field_type is Decimal:
|
|
21
|
+
return True
|
|
22
|
+
if field_type == Decimal:
|
|
23
|
+
return True
|
|
24
|
+
# Fallback: check by name for cases where Decimal is imported differently
|
|
25
|
+
type_name = getattr(field_type, '__name__', None)
|
|
26
|
+
if type_name == 'Decimal':
|
|
27
|
+
return True
|
|
28
|
+
return False
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _is_origin_type(origin, target_types: tuple) -> bool:
|
|
32
|
+
"""
|
|
33
|
+
Check if origin matches any of the target types.
|
|
34
|
+
Handles differences between Python versions where get_origin() may return
|
|
35
|
+
different values (e.g., set vs typing.Set).
|
|
36
|
+
"""
|
|
37
|
+
if origin is None:
|
|
38
|
+
return False
|
|
39
|
+
# Direct comparison
|
|
40
|
+
if origin in target_types:
|
|
41
|
+
return True
|
|
42
|
+
# Check by name for cross-version compatibility
|
|
43
|
+
origin_name = getattr(origin, '__name__', str(origin))
|
|
44
|
+
for target in target_types:
|
|
45
|
+
target_name = getattr(target, '__name__', str(target))
|
|
46
|
+
if origin_name == target_name:
|
|
47
|
+
return True
|
|
48
|
+
return False
|
|
49
|
+
|
|
18
50
|
|
|
19
51
|
def convert_pydantic_to_json(model_instance):
|
|
20
52
|
"""
|
|
@@ -126,7 +158,14 @@ def validate_json_with_pydantic_model(model_class, json_data):
|
|
|
126
158
|
try:
|
|
127
159
|
# RootModel takes value directly, not as kwargs
|
|
128
160
|
if is_root_model:
|
|
129
|
-
|
|
161
|
+
# Handle case where LLM wrapped the list in an object
|
|
162
|
+
# e.g., {"items": ["a", "b"]} should become ["a", "b"]
|
|
163
|
+
actual_item = item
|
|
164
|
+
if isinstance(item, dict) and len(item) == 1:
|
|
165
|
+
single_value = list(item.values())[0]
|
|
166
|
+
if isinstance(single_value, list):
|
|
167
|
+
actual_item = single_value
|
|
168
|
+
model_instance = model_class(actual_item)
|
|
130
169
|
else:
|
|
131
170
|
model_instance = model_class(**item)
|
|
132
171
|
validated_data.append(model_instance.model_dump())
|
|
@@ -144,6 +183,102 @@ def validate_json_with_pydantic_model(model_class, json_data):
|
|
|
144
183
|
return validated_data, validation_errors
|
|
145
184
|
|
|
146
185
|
|
|
186
|
+
def try_auto_wrap_for_nested_model(model_class: Type[BaseModel], json_data: list) -> list:
|
|
187
|
+
"""
|
|
188
|
+
Auto-wrap unwrapped JSON objects if the model expects them in a single List field.
|
|
189
|
+
|
|
190
|
+
When an LLM returns separate objects instead of wrapping them in the expected
|
|
191
|
+
container field, this function detects and fixes the structure.
|
|
192
|
+
|
|
193
|
+
Example:
|
|
194
|
+
Input (unwrapped): [{"name": "A", ...}, {"name": "B", ...}]
|
|
195
|
+
Output (wrapped): [{"items": [{"name": "A", ...}, {"name": "B", ...}]}]
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
model_class: The target Pydantic model class
|
|
199
|
+
json_data: List of extracted JSON objects
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
Modified json_data with auto-wrapping applied if applicable
|
|
203
|
+
"""
|
|
204
|
+
if not json_data or len(json_data) == 0:
|
|
205
|
+
return json_data
|
|
206
|
+
|
|
207
|
+
# Skip RootModel (handled separately by _unwrap_rootmodel_list)
|
|
208
|
+
if HAS_ROOT_MODEL and RootModel is not None:
|
|
209
|
+
try:
|
|
210
|
+
if issubclass(model_class, RootModel):
|
|
211
|
+
return json_data
|
|
212
|
+
except TypeError:
|
|
213
|
+
pass
|
|
214
|
+
|
|
215
|
+
# Handle case where LLM returned a JSON array that got wrapped as [[{}, {}]]
|
|
216
|
+
# This happens when extract_json_from_text parses "[{...}, {...}]" and wraps it
|
|
217
|
+
working_data = json_data
|
|
218
|
+
if (len(json_data) == 1 and
|
|
219
|
+
isinstance(json_data[0], list) and
|
|
220
|
+
len(json_data[0]) > 0 and
|
|
221
|
+
all(isinstance(item, dict) for item in json_data[0])):
|
|
222
|
+
# json_data is [[{}, {}]] - use the inner list for processing
|
|
223
|
+
working_data = json_data[0]
|
|
224
|
+
|
|
225
|
+
# First try validation - if at least one item validates, use it
|
|
226
|
+
# This handles the case where extract_json_from_text extracts both
|
|
227
|
+
# the outer wrapper AND inner objects from pretty-printed JSON
|
|
228
|
+
validated, errors = validate_json_with_pydantic_model(model_class, working_data)
|
|
229
|
+
if validated:
|
|
230
|
+
# At least one item validated - return only the validated items
|
|
231
|
+
# Re-extract just the validated data to return
|
|
232
|
+
valid_items = []
|
|
233
|
+
for item in working_data:
|
|
234
|
+
try:
|
|
235
|
+
model_class(**item)
|
|
236
|
+
valid_items.append(item)
|
|
237
|
+
except:
|
|
238
|
+
pass
|
|
239
|
+
if valid_items:
|
|
240
|
+
return valid_items
|
|
241
|
+
|
|
242
|
+
# Find List[SomeModel] fields in the model
|
|
243
|
+
type_hints = get_type_hints(model_class)
|
|
244
|
+
list_fields = []
|
|
245
|
+
|
|
246
|
+
for field_name, field_type in type_hints.items():
|
|
247
|
+
origin = get_origin(field_type)
|
|
248
|
+
if origin is list:
|
|
249
|
+
args = get_args(field_type)
|
|
250
|
+
if args and hasattr(args[0], '__annotations__'):
|
|
251
|
+
# This is a List[SomeModel] field
|
|
252
|
+
list_fields.append((field_name, args[0]))
|
|
253
|
+
|
|
254
|
+
# Only auto-wrap if model has exactly ONE List[Model] field
|
|
255
|
+
if len(list_fields) != 1:
|
|
256
|
+
return json_data
|
|
257
|
+
|
|
258
|
+
field_name, inner_model = list_fields[0]
|
|
259
|
+
inner_fields = set(get_type_hints(inner_model).keys())
|
|
260
|
+
|
|
261
|
+
# Check if ALL extracted objects contain the inner model's required fields
|
|
262
|
+
# Allow extra keys (they'll be ignored during Pydantic validation)
|
|
263
|
+
# This makes auto-wrap more robust with web search where LLM output is less constrained
|
|
264
|
+
all_match = all(
|
|
265
|
+
isinstance(obj, dict) and inner_fields.issubset(set(obj.keys()))
|
|
266
|
+
for obj in working_data
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
if all_match:
|
|
270
|
+
# Wrap the objects in the expected structure
|
|
271
|
+
wrapped = [{field_name: working_data}]
|
|
272
|
+
|
|
273
|
+
# Validate the wrapped structure
|
|
274
|
+
validated, errors = validate_json_with_pydantic_model(model_class, wrapped)
|
|
275
|
+
if not errors:
|
|
276
|
+
return wrapped
|
|
277
|
+
|
|
278
|
+
# Return original if wrapping didn't help
|
|
279
|
+
return working_data
|
|
280
|
+
|
|
281
|
+
|
|
147
282
|
def convert_json_to_pydantic_model(model_class, json_data):
|
|
148
283
|
try:
|
|
149
284
|
# Handle RootModel - it takes the value directly, not as kwargs
|
|
@@ -173,6 +308,10 @@ def get_field_constraints(field_info):
|
|
|
173
308
|
"""
|
|
174
309
|
constraints = {}
|
|
175
310
|
|
|
311
|
+
# Check direct pattern attribute on FieldInfo (Pydantic v2 Field(pattern="..."))
|
|
312
|
+
if hasattr(field_info, 'pattern') and field_info.pattern:
|
|
313
|
+
constraints['pattern'] = field_info.pattern
|
|
314
|
+
|
|
176
315
|
# Check if field_info has constraints attribute (Pydantic v2)
|
|
177
316
|
if hasattr(field_info, 'constraints'):
|
|
178
317
|
for constraint in field_info.constraints:
|
|
@@ -362,7 +501,7 @@ def example_value_for_type(field_type: Type, constraints: dict = None, _recursio
|
|
|
362
501
|
return "12345678-1234-5678-1234-567812345678"
|
|
363
502
|
|
|
364
503
|
# Handle Decimal type
|
|
365
|
-
if field_type
|
|
504
|
+
if _is_decimal_type(field_type):
|
|
366
505
|
if 'ge' in constraints:
|
|
367
506
|
return str(constraints['ge'])
|
|
368
507
|
elif 'gt' in constraints:
|
|
@@ -406,21 +545,44 @@ def example_value_for_type(field_type: Type, constraints: dict = None, _recursio
|
|
|
406
545
|
for field_name, field_info in field_type.model_fields.items():
|
|
407
546
|
field_constraints = get_field_constraints(field_info)
|
|
408
547
|
field_type_hint = get_type_hints(field_type).get(field_name)
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
548
|
+
# Try smart example first (handles field validators like username, password, email)
|
|
549
|
+
smart = get_smart_example_for_field(field_name, field_type_hint, field_constraints)
|
|
550
|
+
if smart is not None:
|
|
551
|
+
example_data[field_name] = smart
|
|
552
|
+
else:
|
|
553
|
+
value = example_value_for_type(
|
|
554
|
+
field_type_hint,
|
|
555
|
+
field_constraints,
|
|
556
|
+
_recursion_depth + 1,
|
|
557
|
+
_seen_types
|
|
558
|
+
)
|
|
559
|
+
# For list-type fields, ensure we return [] instead of None
|
|
560
|
+
# This handles circular references in List[Model] fields
|
|
561
|
+
if value is None and field_type_hint is not None:
|
|
562
|
+
hint_origin = get_origin(field_type_hint)
|
|
563
|
+
if hint_origin is list:
|
|
564
|
+
value = []
|
|
565
|
+
example_data[field_name] = value
|
|
415
566
|
else:
|
|
416
567
|
# Fallback for older Pydantic versions
|
|
417
568
|
for field_name, field_type_hint in get_type_hints(field_type).items():
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
569
|
+
# Try smart example first
|
|
570
|
+
smart = get_smart_example_for_field(field_name, field_type_hint, {})
|
|
571
|
+
if smart is not None:
|
|
572
|
+
example_data[field_name] = smart
|
|
573
|
+
else:
|
|
574
|
+
value = example_value_for_type(
|
|
575
|
+
field_type_hint,
|
|
576
|
+
{},
|
|
577
|
+
_recursion_depth + 1,
|
|
578
|
+
_seen_types
|
|
579
|
+
)
|
|
580
|
+
# For list-type fields, ensure we return [] instead of None
|
|
581
|
+
if value is None and field_type_hint is not None:
|
|
582
|
+
hint_origin = get_origin(field_type_hint)
|
|
583
|
+
if hint_origin is list:
|
|
584
|
+
value = []
|
|
585
|
+
example_data[field_name] = value
|
|
424
586
|
return field_type(**example_data)
|
|
425
587
|
elif field_type == str:
|
|
426
588
|
# Check for pattern constraint first
|
|
@@ -447,8 +609,9 @@ def example_value_for_type(field_type: Type, constraints: dict = None, _recursio
|
|
|
447
609
|
return base_string[:target_length]
|
|
448
610
|
else:
|
|
449
611
|
# Need to pad or repeat to meet minimum length
|
|
612
|
+
# Use underscores instead of spaces to avoid breaking alphanumeric validators
|
|
450
613
|
repeats = (target_length // len(base_string)) + 1
|
|
451
|
-
repeated = (base_string + "
|
|
614
|
+
repeated = (base_string + "_") * repeats
|
|
452
615
|
return repeated[:target_length]
|
|
453
616
|
elif field_type == int:
|
|
454
617
|
# Respect numeric constraints
|
|
@@ -532,7 +695,7 @@ def example_value_for_type(field_type: Type, constraints: dict = None, _recursio
|
|
|
532
695
|
for i in range(1, 3): # Create 2 example key-value pairs
|
|
533
696
|
example_dict[f"example_key_{i}"] = example_value_for_type(value_type, {}, _recursion_depth + 1, _seen_types)
|
|
534
697
|
return example_dict
|
|
535
|
-
elif origin
|
|
698
|
+
elif _is_origin_type(origin, (set, frozenset)): # Handle Set and FrozenSet
|
|
536
699
|
args = get_args(field_type)
|
|
537
700
|
if not args:
|
|
538
701
|
return [] # No type specified, return empty list
|
|
@@ -548,7 +711,7 @@ def example_value_for_type(field_type: Type, constraints: dict = None, _recursio
|
|
|
548
711
|
value = f"{value}_{i}"
|
|
549
712
|
items.append(value)
|
|
550
713
|
return items # Return as list since JSON doesn't support sets
|
|
551
|
-
elif origin
|
|
714
|
+
elif _is_origin_type(origin, (tuple,)): # Handle Tuple types
|
|
552
715
|
args = get_args(field_type)
|
|
553
716
|
if not args:
|
|
554
717
|
return [] # No type args, return empty list
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: SimplerLLM
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.6
|
|
4
4
|
Summary: An easy-to-use Library for interacting with language models.
|
|
5
5
|
Home-page: https://github.com/hassancs91/SimplerLLM
|
|
6
6
|
Author: Hasan Aboul Hasan
|
|
@@ -18,6 +18,8 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.10
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
23
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
24
|
Requires-Python: >=3.6
|
|
23
25
|
Description-Content-Type: text/markdown
|
|
@@ -43,7 +45,6 @@ Requires-Dist: colorama>=0.4
|
|
|
43
45
|
Requires-Dist: scipy>=1.15
|
|
44
46
|
Requires-Dist: tiktoken>=0.9
|
|
45
47
|
Requires-Dist: qdrant-client==1.14.3
|
|
46
|
-
Requires-Dist: voyageai==0.3.3
|
|
47
48
|
Requires-Dist: pydub>=0.25.1
|
|
48
49
|
Requires-Dist: elevenlabs>=2.22.0
|
|
49
50
|
Requires-Dist: moviepy>=1.0.3
|
|
@@ -52,6 +53,8 @@ Provides-Extra: transformers
|
|
|
52
53
|
Requires-Dist: transformers>=4.36.0; extra == "transformers"
|
|
53
54
|
Requires-Dist: torch>=2.0.0; extra == "transformers"
|
|
54
55
|
Requires-Dist: accelerate>=0.25.0; extra == "transformers"
|
|
56
|
+
Provides-Extra: voyage
|
|
57
|
+
Requires-Dist: voyageai>=0.3.3; extra == "voyage"
|
|
55
58
|
Dynamic: author
|
|
56
59
|
Dynamic: author-email
|
|
57
60
|
Dynamic: classifier
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
LICENSE
|
|
2
|
+
MANIFEST.in
|
|
2
3
|
README.md
|
|
4
|
+
requirements.txt
|
|
3
5
|
setup.py
|
|
4
6
|
SimplerLLM/__init__.py
|
|
5
7
|
SimplerLLM.egg-info/PKG-INFO
|
|
@@ -120,6 +122,7 @@ SimplerLLM/voice/tts/providers/lahajati_tts.py
|
|
|
120
122
|
SimplerLLM/voice/tts/providers/openai_tts.py
|
|
121
123
|
tests/__init__.py
|
|
122
124
|
tests/test_anthropic.py
|
|
125
|
+
tests/test_aspect_ratio_debug.py
|
|
123
126
|
tests/test_brainstorm.py
|
|
124
127
|
tests/test_cohere.py
|
|
125
128
|
tests/test_deepseek.py
|
|
@@ -19,7 +19,6 @@ colorama>=0.4
|
|
|
19
19
|
scipy>=1.15
|
|
20
20
|
tiktoken>=0.9
|
|
21
21
|
qdrant-client==1.14.3
|
|
22
|
-
voyageai==0.3.3
|
|
23
22
|
pydub>=0.25.1
|
|
24
23
|
elevenlabs>=2.22.0
|
|
25
24
|
moviepy>=1.0.3
|
|
@@ -29,3 +28,6 @@ yt-dlp>=2023.3.4
|
|
|
29
28
|
transformers>=4.36.0
|
|
30
29
|
torch>=2.0.0
|
|
31
30
|
accelerate>=0.25.0
|
|
31
|
+
|
|
32
|
+
[voyage]
|
|
33
|
+
voyageai>=0.3.3
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
aiohttp>=3.9
|
|
2
|
+
anthropic>=0.40.0
|
|
3
|
+
cohere>=5.0
|
|
4
|
+
duckduckgo_search>=5.3
|
|
5
|
+
elevenlabs>=1.0
|
|
6
|
+
lxml_html_clean>=0.1
|
|
7
|
+
newspaper3k>=0.2
|
|
8
|
+
numpy>=1.26
|
|
9
|
+
openai>=1.59
|
|
10
|
+
google-genai>=1.52.0
|
|
11
|
+
Pillow>=10.0
|
|
12
|
+
pydantic>=2.10
|
|
13
|
+
PyPDF2>=3.0
|
|
14
|
+
python-dotenv>=1.0
|
|
15
|
+
python_docx>=1.1
|
|
16
|
+
requests>=2.31
|
|
17
|
+
youtube_transcript_api>=0.6
|
|
18
|
+
colorama>=0.4
|
|
19
|
+
scipy>=1.15
|
|
20
|
+
tiktoken>=0.9
|
|
21
|
+
qdrant-client==1.14.3
|
|
22
|
+
# voyageai is optional - install via: pip install SimplerLLM[voyage]
|
|
23
|
+
# (Not in default install because upstream voyageai currently requires-python <3.14)
|
|
24
|
+
pydub>=0.25.1
|
|
25
|
+
elevenlabs>=2.22.0
|
|
26
|
+
# sounddevice>=0.4.6 # Optional - for live voice features. Requires PortAudio. Install with: pip install SimplerLLM[voice]
|
|
27
|
+
# pynput>=1.7.6 # Optional - for push-to-talk. Install with: pip install SimplerLLM[voice]
|
|
28
|
+
# pygame>=2.5.0 # Optional - only needed for AudioPlayer file playback. Install with: pip install pygame>=2.5.0
|
|
29
|
+
moviepy>=1.0.3
|
|
30
|
+
yt-dlp>=2023.3.4
|
|
@@ -15,6 +15,9 @@ extras_require = {
|
|
|
15
15
|
"torch>=2.0.0",
|
|
16
16
|
"accelerate>=0.25.0",
|
|
17
17
|
],
|
|
18
|
+
"voyage": [
|
|
19
|
+
"voyageai>=0.3.3",
|
|
20
|
+
],
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
# Read the long description from the README file
|
|
@@ -23,7 +26,7 @@ with open("README.md", encoding="utf-8") as f:
|
|
|
23
26
|
|
|
24
27
|
setup(
|
|
25
28
|
name="SimplerLLM",
|
|
26
|
-
version="0.3.
|
|
29
|
+
version="0.3.6",
|
|
27
30
|
author="Hasan Aboul Hasan",
|
|
28
31
|
author_email="hasan@learnwithhasan.com",
|
|
29
32
|
description="An easy-to-use Library for interacting with language models.",
|
|
@@ -48,6 +51,8 @@ setup(
|
|
|
48
51
|
"Programming Language :: Python :: 3.10",
|
|
49
52
|
"Programming Language :: Python :: 3.11",
|
|
50
53
|
"Programming Language :: Python :: 3.12",
|
|
54
|
+
"Programming Language :: Python :: 3.13",
|
|
55
|
+
"Programming Language :: Python :: 3.14",
|
|
51
56
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
52
57
|
],
|
|
53
58
|
|