hammad-python 0.0.11__tar.gz → 0.0.13__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.
- {hammad_python-0.0.11 → hammad_python-0.0.13}/.gitignore +1 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/PKG-INFO +4 -1
- hammad_python-0.0.13/hammad/__init__.py +180 -0
- hammad_python-0.0.13/hammad/_core/__init__.py +1 -0
- hammad_python-0.0.13/hammad/_core/_utils/__init__.py +4 -0
- hammad_python-0.0.13/hammad/_core/_utils/_import_utils.py +182 -0
- hammad_python-0.0.13/hammad/ai/__init__.py +59 -0
- hammad_python-0.0.13/hammad/ai/_utils.py +142 -0
- hammad_python-0.0.13/hammad/ai/completions/__init__.py +44 -0
- hammad_python-0.0.13/hammad/ai/completions/client.py +729 -0
- hammad_python-0.0.13/hammad/ai/completions/create.py +686 -0
- hammad_python-0.0.13/hammad/ai/completions/types.py +711 -0
- hammad_python-0.0.13/hammad/ai/completions/utils.py +374 -0
- hammad_python-0.0.13/hammad/ai/embeddings/__init__.py +35 -0
- hammad_python-0.0.13/hammad/ai/embeddings/client/__init__.py +1 -0
- hammad_python-0.0.13/hammad/ai/embeddings/client/base_embeddings_client.py +26 -0
- hammad_python-0.0.13/hammad/ai/embeddings/client/fastembed_text_embeddings_client.py +200 -0
- hammad_python-0.0.13/hammad/ai/embeddings/client/litellm_embeddings_client.py +288 -0
- hammad_python-0.0.13/hammad/ai/embeddings/create.py +159 -0
- hammad_python-0.0.13/hammad/ai/embeddings/types.py +69 -0
- hammad_python-0.0.13/hammad/base/__init__.py +35 -0
- {hammad_python-0.0.11/hammad/based → hammad_python-0.0.13/hammad/base}/fields.py +23 -23
- {hammad_python-0.0.11/hammad/based → hammad_python-0.0.13/hammad/base}/model.py +124 -14
- hammad_python-0.0.13/hammad/base/utils.py +280 -0
- hammad_python-0.0.13/hammad/cache/__init__.py +48 -0
- hammad_python-0.0.13/hammad/cache/base_cache.py +181 -0
- hammad_python-0.0.13/hammad/cache/cache.py +169 -0
- hammad_python-0.0.13/hammad/cache/decorators.py +261 -0
- hammad_python-0.0.13/hammad/cache/file_cache.py +80 -0
- hammad_python-0.0.13/hammad/cache/ttl_cache.py +74 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/cli/__init__.py +10 -2
- {hammad_python-0.0.11/hammad/cli/styles → hammad_python-0.0.13/hammad/cli}/animations.py +79 -23
- hammad_python-0.0.11/hammad/cli/plugins/__init__.py → hammad_python-0.0.13/hammad/cli/plugins.py +85 -90
- hammad_python-0.0.13/hammad/cli/styles/__init__.py +55 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/cli/styles/settings.py +4 -0
- hammad_python-0.0.13/hammad/configuration/__init__.py +35 -0
- {hammad_python-0.0.11/hammad/data/types/files → hammad_python-0.0.13/hammad/configuration}/configuration.py +96 -7
- hammad_python-0.0.13/hammad/data/__init__.py +39 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/data/collections/__init__.py +4 -2
- hammad_python-0.0.13/hammad/data/collections/collection.py +452 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/data/collections/vector_collection.py +118 -12
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/data/databases/__init__.py +2 -2
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/data/databases/database.py +383 -32
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/json/__init__.py +2 -2
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/logging/__init__.py +13 -5
- hammad_python-0.0.13/hammad/logging/decorators.py +834 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/logging/logger.py +442 -22
- hammad_python-0.0.13/hammad/multimodal/__init__.py +24 -0
- {hammad_python-0.0.11/hammad/data/types/files → hammad_python-0.0.13/hammad/multimodal}/audio.py +21 -6
- {hammad_python-0.0.11/hammad/data/types/files → hammad_python-0.0.13/hammad/multimodal}/image.py +5 -5
- hammad_python-0.0.13/hammad/multithreading/__init__.py +304 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/pydantic/__init__.py +2 -2
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/pydantic/converters.py +1 -1
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/pydantic/models/__init__.py +2 -2
- hammad_python-0.0.13/hammad/text/__init__.py +82 -0
- hammad_python-0.0.13/hammad/text/converters.py +723 -0
- hammad_python-0.0.11/hammad/text/utils/markdown/formatting.py → hammad_python-0.0.13/hammad/text/markdown.py +25 -23
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/text/text.py +12 -14
- hammad_python-0.0.13/hammad/types/__init__.py +11 -0
- {hammad_python-0.0.11/hammad/data/types/files → hammad_python-0.0.13/hammad/types}/file.py +18 -18
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/typing/__init__.py +138 -84
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/web/__init__.py +3 -2
- hammad_python-0.0.13/hammad/web/models.py +245 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/web/search/client.py +75 -23
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/web/utils.py +14 -5
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/yaml/__init__.py +2 -2
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/yaml/converters.py +1 -1
- hammad_python-0.0.13/mkdocs.yml +74 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/pyproject.toml +26 -1
- hammad_python-0.0.13/tests/ai/completions/test_ai_completions_create.py +241 -0
- hammad_python-0.0.13/tests/ai/completions/test_ai_completions_types.py +585 -0
- hammad_python-0.0.11/tests/based/test_core_based_fields.py → hammad_python-0.0.13/tests/base/test_base_fields.py +21 -18
- hammad_python-0.0.11/tests/based/test_core_based_model.py → hammad_python-0.0.13/tests/base/test_base_model.py +5 -1
- {hammad_python-0.0.11 → hammad_python-0.0.13}/tests/cache/test_cache_cache.py +13 -8
- {hammad_python-0.0.11 → hammad_python-0.0.13}/tests/cli/test_cli_plugins_animate.py +59 -2
- hammad_python-0.0.13/tests/configuration/test_configuration.py +0 -0
- hammad_python-0.0.13/tests/data/test_data_collections_vector_collection.py +495 -0
- hammad_python-0.0.13/tests/data/test_data_databases_database.py +725 -0
- hammad_python-0.0.13/tests/logging/test_logging_decorators.py +534 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/tests/text/test_text_utils_converters.py +2 -2
- {hammad_python-0.0.11 → hammad_python-0.0.13}/tests/text/test_text_utils_markdown_converters.py +47 -59
- {hammad_python-0.0.11 → hammad_python-0.0.13}/uv.lock +2259 -1307
- hammad_python-0.0.11/hammad/__init__.py +0 -67
- hammad_python-0.0.11/hammad/based/__init__.py +0 -52
- hammad_python-0.0.11/hammad/based/utils.py +0 -455
- hammad_python-0.0.11/hammad/cache/__init__.py +0 -30
- hammad_python-0.0.11/hammad/cache/_cache.py +0 -746
- hammad_python-0.0.11/hammad/cli/styles/__init__.py +0 -5
- hammad_python-0.0.11/hammad/data/__init__.py +0 -51
- hammad_python-0.0.11/hammad/data/collections/collection.py +0 -227
- hammad_python-0.0.11/hammad/data/types/__init__.py +0 -33
- hammad_python-0.0.11/hammad/data/types/files/__init__.py +0 -1
- hammad_python-0.0.11/hammad/data/types/files/document.py +0 -195
- hammad_python-0.0.11/hammad/logging/decorators.py +0 -432
- hammad_python-0.0.11/hammad/text/__init__.py +0 -37
- hammad_python-0.0.11/hammad/text/utils/__init__.py +0 -1
- hammad_python-0.0.11/hammad/text/utils/converters.py +0 -229
- hammad_python-0.0.11/hammad/text/utils/markdown/__init__.py +0 -1
- hammad_python-0.0.11/hammad/text/utils/markdown/converters.py +0 -506
- hammad_python-0.0.11/tests/data/test_data_collections_vector_collection.py +0 -256
- hammad_python-0.0.11/tests/data/test_data_databases_database.py +0 -306
- hammad_python-0.0.11/tests/logging/test_logging_decorators.py +0 -230
- {hammad_python-0.0.11 → hammad_python-0.0.13}/.python-version +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/LICENSE +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/README.md +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/cli/styles/types.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/cli/styles/utils.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/data/collections/base_collection.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/data/collections/searchable_collection.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/json/converters.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/py.typed +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/pydantic/models/arbitrary_model.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/pydantic/models/cacheable_model.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/pydantic/models/fast_model.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/pydantic/models/function_model.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/pydantic/models/subscriptable_model.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/web/http/__init__.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/web/http/client.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/web/openapi/__init__.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/web/openapi/client.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/hammad/web/search/__init__.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/tests/cli/test_cli_plugins_input.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/tests/cli/test_cli_plugins_print.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/tests/cli/test_cli_styles_utils.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/tests/data/test_data_collections_searchable_collection.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/tests/json/test_json_converters.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/tests/logging/test_logging_logger.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/tests/pydantic/test_pydantic_converters.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/tests/pydantic/test_pydantic_models.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/tests/text/test_text_text.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/tests/typing/test_typing_utils.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/tests/web/test_web_toolkits_http_toolkit.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/tests/web/test_web_toolkits_openapi_toolkit.py +0 -0
- {hammad_python-0.0.11 → hammad_python-0.0.13}/tests/web/test_web_utils.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: hammad-python
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.13
|
4
4
|
Summary: hammad - *Nightly* hyper-fast opinionated resources and modules built for quick development.
|
5
5
|
Author-email: Hammad Saeed <hammadaidev@gmail.com>
|
6
6
|
License-File: LICENSE
|
@@ -15,6 +15,7 @@ Requires-Dist: python-dotenv>=1.1.0
|
|
15
15
|
Requires-Dist: pyyaml>=6.0.2
|
16
16
|
Requires-Dist: rich>=13.9.4
|
17
17
|
Requires-Dist: selectolax>=0.3.30
|
18
|
+
Requires-Dist: sqlalchemy>=2.0.41
|
18
19
|
Requires-Dist: tantivy>=0.24.0
|
19
20
|
Requires-Dist: tenacity>=9.0.0
|
20
21
|
Requires-Dist: typing-inspect>=0.9.0
|
@@ -24,6 +25,8 @@ Requires-Dist: instructor>=1.9.0; extra == 'ai'
|
|
24
25
|
Requires-Dist: litellm>=1.72.4; extra == 'ai'
|
25
26
|
Requires-Dist: openai-agents>=0.0.19; extra == 'ai'
|
26
27
|
Requires-Dist: qdrant-client>=1.14.3; extra == 'ai'
|
28
|
+
Provides-Extra: fastembed
|
29
|
+
Requires-Dist: fastembed; extra == 'fastembed'
|
27
30
|
Provides-Extra: serve
|
28
31
|
Requires-Dist: fastapi>=0.115.8; extra == 'serve'
|
29
32
|
Requires-Dist: python-multipart>=0.0.19; extra == 'serve'
|
@@ -0,0 +1,180 @@
|
|
1
|
+
"""hammad-python
|
2
|
+
|
3
|
+
```markdown
|
4
|
+
## Happliy Accelerated Micro Modules (for) Application Development
|
5
|
+
```
|
6
|
+
"""
|
7
|
+
|
8
|
+
from typing import TYPE_CHECKING
|
9
|
+
from ._core._utils._import_utils import _auto_create_getattr_loader
|
10
|
+
|
11
|
+
|
12
|
+
if TYPE_CHECKING:
|
13
|
+
# hammad.ai
|
14
|
+
# NOTE:
|
15
|
+
# TO USE MODULES FROM THE `hammad.ai` EXTENSION,
|
16
|
+
# REQUIRES INSTALLATION OF THE `hammad-python[ai]` PACKAGE.
|
17
|
+
from .ai import (
|
18
|
+
create_completion,
|
19
|
+
async_create_completion,
|
20
|
+
create_embeddings,
|
21
|
+
async_create_embeddings,
|
22
|
+
)
|
23
|
+
|
24
|
+
# hammad.base
|
25
|
+
from .base import Model, field, create_model, is_field, is_model, validator
|
26
|
+
|
27
|
+
# hammad.cache
|
28
|
+
from .cache import Cache, cached, auto_cached, create_cache
|
29
|
+
|
30
|
+
# hammad.cli
|
31
|
+
from .cli import print, animate, input
|
32
|
+
|
33
|
+
# hammad.configuration
|
34
|
+
from .configuration import (
|
35
|
+
Configuration,
|
36
|
+
read_configuration_from_os_vars,
|
37
|
+
read_configuration_from_dotenv,
|
38
|
+
read_configuration_from_file,
|
39
|
+
read_configuration_from_url,
|
40
|
+
read_configuration_from_os_prefix,
|
41
|
+
)
|
42
|
+
|
43
|
+
# hammad.data
|
44
|
+
from .data import Collection, Database, create_collection, create_database
|
45
|
+
|
46
|
+
# hammad.json
|
47
|
+
from .json import encode_json, decode_json, convert_to_json_schema
|
48
|
+
|
49
|
+
# hammad.logging
|
50
|
+
from .logging import (
|
51
|
+
Logger,
|
52
|
+
create_logger,
|
53
|
+
trace,
|
54
|
+
trace_cls,
|
55
|
+
trace_function,
|
56
|
+
trace_http,
|
57
|
+
install_trace_http,
|
58
|
+
)
|
59
|
+
|
60
|
+
# hammad.multithreading
|
61
|
+
from .multithreading import (
|
62
|
+
run_parallel,
|
63
|
+
run_sequentially,
|
64
|
+
run_with_retry,
|
65
|
+
retry,
|
66
|
+
)
|
67
|
+
|
68
|
+
# hammad.pydantic
|
69
|
+
from .pydantic import (
|
70
|
+
convert_to_pydantic_field,
|
71
|
+
convert_to_pydantic_model,
|
72
|
+
)
|
73
|
+
|
74
|
+
# hammad.text
|
75
|
+
from .text import (
|
76
|
+
Text,
|
77
|
+
OutputText,
|
78
|
+
SimpleText,
|
79
|
+
convert_to_text,
|
80
|
+
convert_type_to_text,
|
81
|
+
convert_docstring_to_text,
|
82
|
+
)
|
83
|
+
|
84
|
+
# hammad.web
|
85
|
+
from .web import (
|
86
|
+
create_http_client,
|
87
|
+
create_openapi_client,
|
88
|
+
create_search_client,
|
89
|
+
search_news,
|
90
|
+
search_web,
|
91
|
+
run_web_request,
|
92
|
+
read_web_page,
|
93
|
+
read_web_pages,
|
94
|
+
extract_page_links,
|
95
|
+
)
|
96
|
+
|
97
|
+
# hammad.yaml
|
98
|
+
from .yaml import encode_yaml, decode_yaml, read_yaml_file
|
99
|
+
|
100
|
+
|
101
|
+
__all__ = (
|
102
|
+
# hammad.ai
|
103
|
+
"create_completion",
|
104
|
+
"async_create_completion",
|
105
|
+
"create_embeddings",
|
106
|
+
"async_create_embeddings",
|
107
|
+
# hammad.base
|
108
|
+
"Model",
|
109
|
+
"field",
|
110
|
+
"create_model",
|
111
|
+
# hammad.cache
|
112
|
+
"Cache",
|
113
|
+
"cached",
|
114
|
+
"auto_cached",
|
115
|
+
"create_cache",
|
116
|
+
# hammad.cli
|
117
|
+
"print",
|
118
|
+
"animate",
|
119
|
+
"input",
|
120
|
+
# hammad.configuration
|
121
|
+
"Configuration",
|
122
|
+
"read_configuration_from_os_vars",
|
123
|
+
"read_configuration_from_dotenv",
|
124
|
+
"read_configuration_from_file",
|
125
|
+
"read_configuration_from_url",
|
126
|
+
"read_configuration_from_os_prefix",
|
127
|
+
# hammad.data
|
128
|
+
"Collection",
|
129
|
+
"Database",
|
130
|
+
"create_collection",
|
131
|
+
"create_database",
|
132
|
+
# hammad.json
|
133
|
+
"encode_json",
|
134
|
+
"decode_json",
|
135
|
+
"convert_to_json_schema",
|
136
|
+
# hammad.logging
|
137
|
+
"Logger",
|
138
|
+
"create_logger",
|
139
|
+
"trace",
|
140
|
+
"trace_cls",
|
141
|
+
"trace_function",
|
142
|
+
"trace_http",
|
143
|
+
"install_trace_http",
|
144
|
+
# hammad.multithreading
|
145
|
+
"run_parallel",
|
146
|
+
"run_sequentially",
|
147
|
+
"run_with_retry",
|
148
|
+
"retry",
|
149
|
+
# hammad.pydantic
|
150
|
+
"convert_to_pydantic_field",
|
151
|
+
"convert_to_pydantic_model",
|
152
|
+
# hammad.text
|
153
|
+
"Text",
|
154
|
+
"OutputText",
|
155
|
+
"SimpleText",
|
156
|
+
"convert_to_text",
|
157
|
+
"convert_type_to_text",
|
158
|
+
"convert_docstring_to_text",
|
159
|
+
# hammad.web
|
160
|
+
"create_http_client",
|
161
|
+
"create_openapi_client",
|
162
|
+
"create_search_client",
|
163
|
+
"search_news",
|
164
|
+
"search_web",
|
165
|
+
"run_web_request",
|
166
|
+
"read_web_page",
|
167
|
+
"read_web_pages",
|
168
|
+
"extract_page_links",
|
169
|
+
# hammad.yaml
|
170
|
+
"encode_yaml",
|
171
|
+
"decode_yaml",
|
172
|
+
"read_yaml_file",
|
173
|
+
)
|
174
|
+
|
175
|
+
|
176
|
+
__getattr__ = _auto_create_getattr_loader(__all__)
|
177
|
+
|
178
|
+
|
179
|
+
def __dir__() -> list[str]:
|
180
|
+
return list(__all__)
|
@@ -0,0 +1 @@
|
|
1
|
+
"""hammad._core"""
|
@@ -0,0 +1,182 @@
|
|
1
|
+
"""hammad._core._utils._import_utils"""
|
2
|
+
|
3
|
+
from typing import Any, Callable
|
4
|
+
import inspect
|
5
|
+
import ast
|
6
|
+
import hashlib
|
7
|
+
|
8
|
+
__all__ = ("_auto_create_getattr_loader",)
|
9
|
+
|
10
|
+
|
11
|
+
class _ModuleCache:
|
12
|
+
"""Minimal cache implementation for internal use only."""
|
13
|
+
|
14
|
+
def __init__(self, maxsize: int = 128):
|
15
|
+
self.maxsize = maxsize
|
16
|
+
self._cache: dict[str, Any] = {}
|
17
|
+
|
18
|
+
def _make_key(self, data: str) -> str:
|
19
|
+
"""Create a simple hash key from string data."""
|
20
|
+
return hashlib.sha256(data.encode("utf-8")).hexdigest()[:16]
|
21
|
+
|
22
|
+
def get(self, key: str, default: Any = None) -> Any:
|
23
|
+
"""Get value from cache."""
|
24
|
+
return self._cache.get(key, default)
|
25
|
+
|
26
|
+
def set(self, key: str, value: Any) -> None:
|
27
|
+
"""Set value in cache with basic LRU eviction."""
|
28
|
+
if len(self._cache) >= self.maxsize and key not in self._cache:
|
29
|
+
# Simple eviction: remove oldest (first) item
|
30
|
+
oldest_key = next(iter(self._cache))
|
31
|
+
del self._cache[oldest_key]
|
32
|
+
self._cache[key] = value
|
33
|
+
|
34
|
+
def cached_call(self, func: Callable[[str], Any]) -> Callable[[str], Any]:
|
35
|
+
"""Decorator to cache function calls."""
|
36
|
+
|
37
|
+
def wrapper(arg: str) -> Any:
|
38
|
+
key = self._make_key(arg)
|
39
|
+
result = self.get(key)
|
40
|
+
if result is None:
|
41
|
+
result = func(arg)
|
42
|
+
self.set(key, result)
|
43
|
+
return result
|
44
|
+
|
45
|
+
return wrapper
|
46
|
+
|
47
|
+
|
48
|
+
# Global cache instance for parse function
|
49
|
+
_parse_cache = _ModuleCache(maxsize=64)
|
50
|
+
|
51
|
+
|
52
|
+
def _create_getattr_loader(
|
53
|
+
imports_dict: dict[str, tuple[str, str]], package: str
|
54
|
+
) -> Callable[[str], Any]:
|
55
|
+
"""Create a lazy loader function for __getattr__.
|
56
|
+
|
57
|
+
Args:
|
58
|
+
imports_dict: Dictionary mapping attribute names to (module_path, original_name) tuples
|
59
|
+
package: The package name for import_module
|
60
|
+
|
61
|
+
Returns:
|
62
|
+
A __getattr__ function that lazily imports modules
|
63
|
+
"""
|
64
|
+
from importlib import import_module
|
65
|
+
|
66
|
+
_cache = {}
|
67
|
+
|
68
|
+
def __getattr__(name: str) -> Any:
|
69
|
+
if name in _cache:
|
70
|
+
return _cache[name]
|
71
|
+
|
72
|
+
if name in imports_dict:
|
73
|
+
module_path, original_name = imports_dict[name]
|
74
|
+
module = import_module(module_path, package)
|
75
|
+
result = getattr(module, original_name)
|
76
|
+
_cache[name] = result
|
77
|
+
return result
|
78
|
+
raise AttributeError(f"module '{package}' has no attribute '{name}'")
|
79
|
+
|
80
|
+
return __getattr__
|
81
|
+
|
82
|
+
|
83
|
+
_type_checking_cache = {}
|
84
|
+
|
85
|
+
|
86
|
+
def _auto_create_getattr_loader(all_exports: tuple[str, ...]) -> Callable[[str], Any]:
|
87
|
+
"""Automatically create a lazy loader by inspecting the calling module.
|
88
|
+
|
89
|
+
This function inspects the calling module's source code to extract
|
90
|
+
TYPE_CHECKING imports and automatically builds the import map.
|
91
|
+
|
92
|
+
Args:
|
93
|
+
all_exports: The __all__ tuple from the calling module
|
94
|
+
|
95
|
+
Returns:
|
96
|
+
A __getattr__ function that lazily imports modules
|
97
|
+
"""
|
98
|
+
# Get the calling module's frame
|
99
|
+
frame = inspect.currentframe()
|
100
|
+
if frame is None or frame.f_back is None:
|
101
|
+
raise RuntimeError("Cannot determine calling module")
|
102
|
+
|
103
|
+
calling_frame = frame.f_back
|
104
|
+
module_name = calling_frame.f_globals.get("__name__", "")
|
105
|
+
package = calling_frame.f_globals.get("__package__", "")
|
106
|
+
filename = calling_frame.f_globals.get("__file__", "")
|
107
|
+
|
108
|
+
# Check cache first
|
109
|
+
cache_key = (filename, tuple(all_exports))
|
110
|
+
if cache_key in _type_checking_cache:
|
111
|
+
return _type_checking_cache[cache_key]
|
112
|
+
|
113
|
+
# Read the source file
|
114
|
+
try:
|
115
|
+
with open(filename, "r") as f:
|
116
|
+
source_code = f.read()
|
117
|
+
except (IOError, OSError):
|
118
|
+
# Fallback: try to get source from the module
|
119
|
+
import sys
|
120
|
+
|
121
|
+
module = sys.modules.get(module_name)
|
122
|
+
if module:
|
123
|
+
source_code = inspect.getsource(module)
|
124
|
+
else:
|
125
|
+
raise RuntimeError(f"Cannot read source for module {module_name}")
|
126
|
+
|
127
|
+
# Parse the source to extract TYPE_CHECKING imports
|
128
|
+
imports_map = _parse_type_checking_imports(source_code)
|
129
|
+
|
130
|
+
# Filter to only include exports that are in __all__
|
131
|
+
filtered_map = {
|
132
|
+
name: path for name, path in imports_map.items() if name in all_exports
|
133
|
+
}
|
134
|
+
|
135
|
+
loader = _create_getattr_loader(filtered_map, package)
|
136
|
+
_type_checking_cache[cache_key] = loader
|
137
|
+
return loader
|
138
|
+
|
139
|
+
|
140
|
+
def _parse_type_checking_imports(source_code: str) -> dict[str, tuple[str, str]]:
|
141
|
+
"""Parse TYPE_CHECKING imports from source code to build import map.
|
142
|
+
|
143
|
+
Args:
|
144
|
+
source_code: The source code containing TYPE_CHECKING imports
|
145
|
+
|
146
|
+
Returns:
|
147
|
+
Dictionary mapping local names to (module_path, original_name) tuples
|
148
|
+
"""
|
149
|
+
|
150
|
+
@_parse_cache.cached_call
|
151
|
+
def _exec(source_code: str) -> dict[str, tuple[str, str]]:
|
152
|
+
tree = ast.parse(source_code)
|
153
|
+
imports = {}
|
154
|
+
|
155
|
+
for node in ast.walk(tree):
|
156
|
+
if isinstance(node, ast.If):
|
157
|
+
# Check if this is a TYPE_CHECKING block
|
158
|
+
is_type_checking = False
|
159
|
+
|
160
|
+
if isinstance(node.test, ast.Name) and node.test.id == "TYPE_CHECKING":
|
161
|
+
is_type_checking = True
|
162
|
+
elif isinstance(node.test, ast.Attribute):
|
163
|
+
if (
|
164
|
+
isinstance(node.test.value, ast.Name)
|
165
|
+
and node.test.value.id == "typing"
|
166
|
+
and node.test.attr == "TYPE_CHECKING"
|
167
|
+
):
|
168
|
+
is_type_checking = True
|
169
|
+
|
170
|
+
if is_type_checking:
|
171
|
+
# Process imports in this block
|
172
|
+
for stmt in node.body:
|
173
|
+
if isinstance(stmt, ast.ImportFrom) and stmt.module:
|
174
|
+
module_path = f".{stmt.module}"
|
175
|
+
for alias in stmt.names:
|
176
|
+
original_name = alias.name
|
177
|
+
local_name = alias.asname or original_name
|
178
|
+
imports[local_name] = (module_path, original_name)
|
179
|
+
|
180
|
+
return imports
|
181
|
+
|
182
|
+
return _exec(source_code)
|
@@ -0,0 +1,59 @@
|
|
1
|
+
"""hammad.ai"""
|
2
|
+
|
3
|
+
from typing import TYPE_CHECKING
|
4
|
+
from .._core._utils._import_utils import _auto_create_getattr_loader
|
5
|
+
|
6
|
+
if TYPE_CHECKING:
|
7
|
+
from .completions import (
|
8
|
+
CompletionsClient,
|
9
|
+
Completion,
|
10
|
+
CompletionChunk,
|
11
|
+
CompletionsInputParam,
|
12
|
+
CompletionsModelName,
|
13
|
+
CompletionsOutputType,
|
14
|
+
CompletionStream,
|
15
|
+
AsyncCompletionStream,
|
16
|
+
async_create_completion,
|
17
|
+
create_completion,
|
18
|
+
)
|
19
|
+
from .embeddings import (
|
20
|
+
Embedding,
|
21
|
+
EmbeddingResponse,
|
22
|
+
EmbeddingUsage,
|
23
|
+
BaseEmbeddingsClient,
|
24
|
+
FastEmbedTextEmbeddingsClient,
|
25
|
+
LiteLlmEmbeddingsClient,
|
26
|
+
create_embeddings,
|
27
|
+
async_create_embeddings,
|
28
|
+
)
|
29
|
+
|
30
|
+
|
31
|
+
__all__ = (
|
32
|
+
# hammad.ai.completions
|
33
|
+
"CompletionsClient",
|
34
|
+
"Completion",
|
35
|
+
"CompletionChunk",
|
36
|
+
"CompletionsInputParam",
|
37
|
+
"CompletionsModelName",
|
38
|
+
"CompletionsOutputType",
|
39
|
+
"CompletionStream",
|
40
|
+
"AsyncCompletionStream",
|
41
|
+
"async_create_completion",
|
42
|
+
"create_completion",
|
43
|
+
# hammad.ai.embeddings
|
44
|
+
"Embedding",
|
45
|
+
"EmbeddingResponse",
|
46
|
+
"EmbeddingUsage",
|
47
|
+
"BaseEmbeddingsClient",
|
48
|
+
"FastEmbedTextEmbeddingsClient",
|
49
|
+
"LiteLlmEmbeddingsClient",
|
50
|
+
"create_embeddings",
|
51
|
+
"async_create_embeddings",
|
52
|
+
)
|
53
|
+
|
54
|
+
|
55
|
+
__getattr__ = _auto_create_getattr_loader(__all__)
|
56
|
+
|
57
|
+
|
58
|
+
def __dir__() -> list[str]:
|
59
|
+
return list(__all__)
|
@@ -0,0 +1,142 @@
|
|
1
|
+
"""hammad.ai._utils
|
2
|
+
|
3
|
+
Shared internal utilities for the `hammad.ai` extension."""
|
4
|
+
|
5
|
+
from typing import Any, Optional, Sequence
|
6
|
+
|
7
|
+
__all__ = (
|
8
|
+
"get_instructor",
|
9
|
+
"get_litellm",
|
10
|
+
"get_fastembed",
|
11
|
+
"get_fastembed_text_embedding_model",
|
12
|
+
)
|
13
|
+
|
14
|
+
|
15
|
+
# ------------------------------------------------------------
|
16
|
+
# INSTRUCTOR
|
17
|
+
# ------------------------------------------------------------
|
18
|
+
|
19
|
+
|
20
|
+
INSTRUCTOR_MODULE = None
|
21
|
+
"""Library level singleton for the `instructor` module."""
|
22
|
+
|
23
|
+
|
24
|
+
def get_instructor():
|
25
|
+
"""Get the instructor module."""
|
26
|
+
global INSTRUCTOR_MODULE
|
27
|
+
|
28
|
+
if INSTRUCTOR_MODULE is None:
|
29
|
+
try:
|
30
|
+
import instructor
|
31
|
+
|
32
|
+
INSTRUCTOR_MODULE = instructor
|
33
|
+
except ImportError:
|
34
|
+
raise ImportError(
|
35
|
+
"instructor is not installed. Please install it with `pip install hammad-python[ai]`"
|
36
|
+
)
|
37
|
+
|
38
|
+
return INSTRUCTOR_MODULE
|
39
|
+
|
40
|
+
|
41
|
+
# ------------------------------------------------------------
|
42
|
+
# LITELLM
|
43
|
+
# ------------------------------------------------------------
|
44
|
+
|
45
|
+
|
46
|
+
LITELLM_MODULE = None
|
47
|
+
"""Library level singleton for the `litellm` module."""
|
48
|
+
|
49
|
+
|
50
|
+
def get_litellm():
|
51
|
+
"""Get the litellm module."""
|
52
|
+
global LITELLM_MODULE
|
53
|
+
if LITELLM_MODULE is None:
|
54
|
+
try:
|
55
|
+
import litellm
|
56
|
+
|
57
|
+
litellm.drop_params = True
|
58
|
+
litellm.modify_params = True
|
59
|
+
LITELLM_MODULE = litellm
|
60
|
+
except ImportError:
|
61
|
+
raise ImportError(
|
62
|
+
"litellm is not installed. Please install it with `pip install hammad-python[ai]`"
|
63
|
+
)
|
64
|
+
|
65
|
+
return LITELLM_MODULE
|
66
|
+
|
67
|
+
|
68
|
+
# ------------------------------------------------------------
|
69
|
+
# FASTEMBED
|
70
|
+
# ------------------------------------------------------------
|
71
|
+
|
72
|
+
|
73
|
+
FASTEMBED_MODULE = None
|
74
|
+
"""Library level singleton for the `fastembed` module."""
|
75
|
+
|
76
|
+
|
77
|
+
def get_fastembed():
|
78
|
+
"""Get the fastembed module."""
|
79
|
+
global FASTEMBED_MODULE
|
80
|
+
if FASTEMBED_MODULE is None:
|
81
|
+
try:
|
82
|
+
import fastembed
|
83
|
+
|
84
|
+
FASTEMBED_MODULE = fastembed
|
85
|
+
except ImportError:
|
86
|
+
raise ImportError(
|
87
|
+
"fastembed is not installed. Please install it with `pip install hammad-python[ai]`"
|
88
|
+
)
|
89
|
+
|
90
|
+
return FASTEMBED_MODULE
|
91
|
+
|
92
|
+
|
93
|
+
FASTEMBED_LOADED_TEXT_EMBEDDING_MODELS: dict = {}
|
94
|
+
|
95
|
+
|
96
|
+
def get_fastembed_text_embedding_model(
|
97
|
+
model: str,
|
98
|
+
cache_dir: Optional[str] = None,
|
99
|
+
threads: Optional[int] = None,
|
100
|
+
providers: Optional[Sequence[Any]] = None,
|
101
|
+
cuda: bool = False,
|
102
|
+
device_ids: Optional[list[int]] = None,
|
103
|
+
lazy_load: bool = False,
|
104
|
+
):
|
105
|
+
"""Initializes a fastembed model instance for a given
|
106
|
+
model name using a global library level singleton.
|
107
|
+
|
108
|
+
NOTE: Custom models are not supported yet.
|
109
|
+
|
110
|
+
Args:
|
111
|
+
model (str) : The model name to load.
|
112
|
+
cache_dir (Optional[str]) : The directory to cache the model in.
|
113
|
+
threads (Optional[int]) : The number of threads to use for the model.
|
114
|
+
providers (Optional[Sequence[Any]]) : The ONNX providers to use for the model.
|
115
|
+
cuda (bool) : Whether to use CUDA for the model.
|
116
|
+
device_ids (Optional[list[int]]) : The device IDs to use for the model.
|
117
|
+
lazy_load (bool) : Whether to lazy load the model.
|
118
|
+
|
119
|
+
Returns:
|
120
|
+
fastembed.TextEmbedding : The loaded fastembed model instance.
|
121
|
+
"""
|
122
|
+
global FASTEMBED_LOADED_TEXT_EMBEDDING_MODELS
|
123
|
+
|
124
|
+
if model not in FASTEMBED_LOADED_TEXT_EMBEDDING_MODELS:
|
125
|
+
fastembed_module = get_fastembed()
|
126
|
+
|
127
|
+
try:
|
128
|
+
embedding_model = fastembed_module.TextEmbedding(
|
129
|
+
model_name=model,
|
130
|
+
cache_dir=cache_dir,
|
131
|
+
threads=threads,
|
132
|
+
providers=providers,
|
133
|
+
cuda=cuda,
|
134
|
+
device_ids=device_ids,
|
135
|
+
lazy_load=lazy_load,
|
136
|
+
)
|
137
|
+
except Exception as e:
|
138
|
+
raise e
|
139
|
+
|
140
|
+
FASTEMBED_LOADED_TEXT_EMBEDDING_MODELS[model] = embedding_model
|
141
|
+
|
142
|
+
return FASTEMBED_LOADED_TEXT_EMBEDDING_MODELS[model]
|
@@ -0,0 +1,44 @@
|
|
1
|
+
"""hammad.ai.completions
|
2
|
+
|
3
|
+
Contains types and model like objects for working with language model
|
4
|
+
completions."""
|
5
|
+
|
6
|
+
from typing import TYPE_CHECKING
|
7
|
+
from ..._core._utils._import_utils import _auto_create_getattr_loader
|
8
|
+
|
9
|
+
if TYPE_CHECKING:
|
10
|
+
from .client import CompletionsClient
|
11
|
+
from .types import (
|
12
|
+
Completion,
|
13
|
+
CompletionChunk,
|
14
|
+
CompletionStream,
|
15
|
+
AsyncCompletionStream,
|
16
|
+
CompletionsInputParam,
|
17
|
+
CompletionsModelName,
|
18
|
+
CompletionsOutputType,
|
19
|
+
)
|
20
|
+
from .create import create_completion, async_create_completion
|
21
|
+
|
22
|
+
|
23
|
+
__all__ = (
|
24
|
+
# hammad.ai.completions.client
|
25
|
+
"CompletionsClient",
|
26
|
+
# hammad.ai.completions.types
|
27
|
+
"Completion",
|
28
|
+
"CompletionChunk",
|
29
|
+
"CompletionStream",
|
30
|
+
"AsyncCompletionStream",
|
31
|
+
"CompletionsInputParam",
|
32
|
+
"CompletionsModelName",
|
33
|
+
"CompletionsOutputType",
|
34
|
+
# hammad.ai.completions.create
|
35
|
+
"create_completion",
|
36
|
+
"async_create_completion",
|
37
|
+
)
|
38
|
+
|
39
|
+
|
40
|
+
__getattr__ = _auto_create_getattr_loader(__all__)
|
41
|
+
|
42
|
+
|
43
|
+
def __dir__() -> list[str]:
|
44
|
+
return list(__all__)
|