hammad-python 0.0.29__py3-none-any.whl → 0.0.31__py3-none-any.whl
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.
- ham/__init__.py +10 -0
- {hammad_python-0.0.29.dist-info → hammad_python-0.0.31.dist-info}/METADATA +6 -32
- hammad_python-0.0.31.dist-info/RECORD +6 -0
- hammad/__init__.py +0 -84
- hammad/_internal.py +0 -256
- hammad/_main.py +0 -226
- hammad/cache/__init__.py +0 -40
- hammad/cache/base_cache.py +0 -181
- hammad/cache/cache.py +0 -169
- hammad/cache/decorators.py +0 -261
- hammad/cache/file_cache.py +0 -80
- hammad/cache/ttl_cache.py +0 -74
- hammad/cli/__init__.py +0 -33
- hammad/cli/animations.py +0 -573
- hammad/cli/plugins.py +0 -867
- hammad/cli/styles/__init__.py +0 -55
- hammad/cli/styles/settings.py +0 -139
- hammad/cli/styles/types.py +0 -358
- hammad/cli/styles/utils.py +0 -634
- hammad/data/__init__.py +0 -90
- hammad/data/collections/__init__.py +0 -49
- hammad/data/collections/collection.py +0 -326
- hammad/data/collections/indexes/__init__.py +0 -37
- hammad/data/collections/indexes/qdrant/__init__.py +0 -1
- hammad/data/collections/indexes/qdrant/index.py +0 -723
- hammad/data/collections/indexes/qdrant/settings.py +0 -94
- hammad/data/collections/indexes/qdrant/utils.py +0 -210
- hammad/data/collections/indexes/tantivy/__init__.py +0 -1
- hammad/data/collections/indexes/tantivy/index.py +0 -426
- hammad/data/collections/indexes/tantivy/settings.py +0 -40
- hammad/data/collections/indexes/tantivy/utils.py +0 -176
- hammad/data/configurations/__init__.py +0 -35
- hammad/data/configurations/configuration.py +0 -564
- hammad/data/models/__init__.py +0 -50
- hammad/data/models/extensions/__init__.py +0 -4
- hammad/data/models/extensions/pydantic/__init__.py +0 -42
- hammad/data/models/extensions/pydantic/converters.py +0 -759
- hammad/data/models/fields.py +0 -546
- hammad/data/models/model.py +0 -1078
- hammad/data/models/utils.py +0 -280
- hammad/data/sql/__init__.py +0 -24
- hammad/data/sql/database.py +0 -576
- hammad/data/sql/types.py +0 -127
- hammad/data/types/__init__.py +0 -75
- hammad/data/types/file.py +0 -431
- hammad/data/types/multimodal/__init__.py +0 -36
- hammad/data/types/multimodal/audio.py +0 -200
- hammad/data/types/multimodal/image.py +0 -182
- hammad/data/types/text.py +0 -1308
- hammad/formatting/__init__.py +0 -33
- hammad/formatting/json/__init__.py +0 -27
- hammad/formatting/json/converters.py +0 -158
- hammad/formatting/text/__init__.py +0 -63
- hammad/formatting/text/converters.py +0 -723
- hammad/formatting/text/markdown.py +0 -131
- hammad/formatting/yaml/__init__.py +0 -26
- hammad/formatting/yaml/converters.py +0 -5
- hammad/genai/__init__.py +0 -217
- hammad/genai/a2a/__init__.py +0 -32
- hammad/genai/a2a/workers.py +0 -552
- hammad/genai/agents/__init__.py +0 -59
- hammad/genai/agents/agent.py +0 -1973
- hammad/genai/agents/run.py +0 -1024
- hammad/genai/agents/types/__init__.py +0 -42
- hammad/genai/agents/types/agent_context.py +0 -13
- hammad/genai/agents/types/agent_event.py +0 -128
- hammad/genai/agents/types/agent_hooks.py +0 -220
- hammad/genai/agents/types/agent_messages.py +0 -31
- hammad/genai/agents/types/agent_response.py +0 -125
- hammad/genai/agents/types/agent_stream.py +0 -327
- hammad/genai/graphs/__init__.py +0 -125
- hammad/genai/graphs/_utils.py +0 -190
- hammad/genai/graphs/base.py +0 -1828
- hammad/genai/graphs/plugins.py +0 -316
- hammad/genai/graphs/types.py +0 -638
- hammad/genai/models/__init__.py +0 -1
- hammad/genai/models/embeddings/__init__.py +0 -43
- hammad/genai/models/embeddings/model.py +0 -226
- hammad/genai/models/embeddings/run.py +0 -163
- hammad/genai/models/embeddings/types/__init__.py +0 -37
- hammad/genai/models/embeddings/types/embedding_model_name.py +0 -75
- hammad/genai/models/embeddings/types/embedding_model_response.py +0 -76
- hammad/genai/models/embeddings/types/embedding_model_run_params.py +0 -66
- hammad/genai/models/embeddings/types/embedding_model_settings.py +0 -47
- hammad/genai/models/language/__init__.py +0 -57
- hammad/genai/models/language/model.py +0 -1098
- hammad/genai/models/language/run.py +0 -878
- hammad/genai/models/language/types/__init__.py +0 -40
- hammad/genai/models/language/types/language_model_instructor_mode.py +0 -47
- hammad/genai/models/language/types/language_model_messages.py +0 -28
- hammad/genai/models/language/types/language_model_name.py +0 -239
- hammad/genai/models/language/types/language_model_request.py +0 -127
- hammad/genai/models/language/types/language_model_response.py +0 -217
- hammad/genai/models/language/types/language_model_response_chunk.py +0 -56
- hammad/genai/models/language/types/language_model_settings.py +0 -89
- hammad/genai/models/language/types/language_model_stream.py +0 -600
- hammad/genai/models/language/utils/__init__.py +0 -28
- hammad/genai/models/language/utils/requests.py +0 -421
- hammad/genai/models/language/utils/structured_outputs.py +0 -135
- hammad/genai/models/model_provider.py +0 -4
- hammad/genai/models/multimodal.py +0 -47
- hammad/genai/models/reranking.py +0 -26
- hammad/genai/types/__init__.py +0 -1
- hammad/genai/types/base.py +0 -215
- hammad/genai/types/history.py +0 -290
- hammad/genai/types/tools.py +0 -507
- hammad/logging/__init__.py +0 -35
- hammad/logging/decorators.py +0 -834
- hammad/logging/logger.py +0 -1018
- hammad/mcp/__init__.py +0 -53
- hammad/mcp/client/__init__.py +0 -35
- hammad/mcp/client/client.py +0 -624
- hammad/mcp/client/client_service.py +0 -400
- hammad/mcp/client/settings.py +0 -178
- hammad/mcp/servers/__init__.py +0 -26
- hammad/mcp/servers/launcher.py +0 -1161
- hammad/runtime/__init__.py +0 -32
- hammad/runtime/decorators.py +0 -142
- hammad/runtime/run.py +0 -299
- hammad/service/__init__.py +0 -49
- hammad/service/create.py +0 -527
- hammad/service/decorators.py +0 -283
- hammad/types.py +0 -288
- hammad/typing/__init__.py +0 -435
- hammad/web/__init__.py +0 -43
- hammad/web/http/__init__.py +0 -1
- hammad/web/http/client.py +0 -944
- hammad/web/models.py +0 -275
- hammad/web/openapi/__init__.py +0 -1
- hammad/web/openapi/client.py +0 -740
- hammad/web/search/__init__.py +0 -1
- hammad/web/search/client.py +0 -1023
- hammad/web/utils.py +0 -472
- hammad_python-0.0.29.dist-info/RECORD +0 -135
- {hammad → ham}/py.typed +0 -0
- {hammad_python-0.0.29.dist-info → hammad_python-0.0.31.dist-info}/WHEEL +0 -0
- {hammad_python-0.0.29.dist-info → hammad_python-0.0.31.dist-info}/licenses/LICENSE +0 -0
@@ -1,94 +0,0 @@
|
|
1
|
-
"""hammad.data.collections.indexes.qdrant.settings"""
|
2
|
-
|
3
|
-
from dataclasses import dataclass
|
4
|
-
from typing import (
|
5
|
-
Any,
|
6
|
-
Dict,
|
7
|
-
Optional,
|
8
|
-
Literal,
|
9
|
-
)
|
10
|
-
|
11
|
-
__all__ = (
|
12
|
-
"QdrantCollectionIndexSettings",
|
13
|
-
"QdrantCollectionIndexQuerySettings",
|
14
|
-
"DistanceMetric",
|
15
|
-
)
|
16
|
-
|
17
|
-
|
18
|
-
DistanceMetric = Literal[
|
19
|
-
"cosine",
|
20
|
-
"dot",
|
21
|
-
"euclidean",
|
22
|
-
"manhattan",
|
23
|
-
]
|
24
|
-
|
25
|
-
|
26
|
-
@dataclass
|
27
|
-
class QdrantCollectionIndexSettings:
|
28
|
-
"""Object representation of user configurable settings
|
29
|
-
that can be used to configure a `QdrantCollectionIndex`."""
|
30
|
-
|
31
|
-
vector_size: int = 768
|
32
|
-
"""The size/dimension of the vectors to store."""
|
33
|
-
|
34
|
-
distance_metric: DistanceMetric = "dot"
|
35
|
-
"""Distance metric for similarity search."""
|
36
|
-
|
37
|
-
path: Optional[str] = None
|
38
|
-
"""Path for local Qdrant storage (None = in-memory)."""
|
39
|
-
|
40
|
-
host: Optional[str] = None
|
41
|
-
"""Qdrant server host (if using remote server)."""
|
42
|
-
|
43
|
-
port: int = 6333
|
44
|
-
"""Qdrant server port."""
|
45
|
-
|
46
|
-
grpc_port: int = 6334
|
47
|
-
"""Qdrant gRPC port."""
|
48
|
-
|
49
|
-
prefer_grpc: bool = False
|
50
|
-
"""Whether to prefer gRPC over HTTP."""
|
51
|
-
|
52
|
-
api_key: Optional[str] = None
|
53
|
-
"""API key for Qdrant authentication."""
|
54
|
-
|
55
|
-
timeout: Optional[float] = None
|
56
|
-
"""Request timeout for Qdrant operations."""
|
57
|
-
|
58
|
-
def get_qdrant_config(self) -> Dict[str, Any]:
|
59
|
-
"""Returns a configuration dictionary used
|
60
|
-
to configure the qdrant client internally."""
|
61
|
-
config = {}
|
62
|
-
|
63
|
-
if self.path is not None:
|
64
|
-
config["path"] = self.path
|
65
|
-
elif self.host is not None:
|
66
|
-
config["host"] = self.host
|
67
|
-
config["port"] = self.port
|
68
|
-
config["grpc_port"] = self.grpc_port
|
69
|
-
config["prefer_grpc"] = self.prefer_grpc
|
70
|
-
if self.api_key:
|
71
|
-
config["api_key"] = self.api_key
|
72
|
-
if self.timeout:
|
73
|
-
config["timeout"] = self.timeout
|
74
|
-
else:
|
75
|
-
# In-memory database
|
76
|
-
config["location"] = ":memory:"
|
77
|
-
|
78
|
-
return config
|
79
|
-
|
80
|
-
|
81
|
-
@dataclass
|
82
|
-
class QdrantCollectionIndexQuerySettings:
|
83
|
-
"""Object representation of user configurable settings
|
84
|
-
that can be used to configure the query engine for a
|
85
|
-
`QdrantCollectionIndex`."""
|
86
|
-
|
87
|
-
limit: int = 10
|
88
|
-
"""The maximum number of results to return."""
|
89
|
-
|
90
|
-
score_threshold: Optional[float] = None
|
91
|
-
"""Minimum similarity score threshold for results."""
|
92
|
-
|
93
|
-
exact: bool = False
|
94
|
-
"""Whether to use exact search (slower but more accurate)."""
|
@@ -1,210 +0,0 @@
|
|
1
|
-
"""hammad.data.collections.indexes.qdrant.utils"""
|
2
|
-
|
3
|
-
from dataclasses import dataclass
|
4
|
-
from typing import Any, Dict, List, Optional, Union, final
|
5
|
-
import uuid
|
6
|
-
|
7
|
-
from .....cache import cached
|
8
|
-
from .settings import (
|
9
|
-
QdrantCollectionIndexSettings,
|
10
|
-
QdrantCollectionIndexQuerySettings,
|
11
|
-
DistanceMetric,
|
12
|
-
)
|
13
|
-
|
14
|
-
# Lazy imports to avoid errors when qdrant is not installed
|
15
|
-
try:
|
16
|
-
import numpy as np
|
17
|
-
|
18
|
-
NUMPY_AVAILABLE = True
|
19
|
-
except ImportError:
|
20
|
-
NUMPY_AVAILABLE = False
|
21
|
-
|
22
|
-
__all__ = (
|
23
|
-
"QdrantCollectionIndexError",
|
24
|
-
"QdrantClientWrapper",
|
25
|
-
"create_qdrant_client",
|
26
|
-
"prepare_vector",
|
27
|
-
"convert_distance_metric",
|
28
|
-
"serialize",
|
29
|
-
)
|
30
|
-
|
31
|
-
|
32
|
-
class QdrantCollectionIndexError(Exception):
|
33
|
-
"""Exception raised when an error occurs in the `QdrantCollectionIndex`."""
|
34
|
-
|
35
|
-
|
36
|
-
@dataclass
|
37
|
-
class QdrantClientWrapper:
|
38
|
-
"""Wrapper over the qdrant client and collection setup."""
|
39
|
-
|
40
|
-
client: Any
|
41
|
-
"""The qdrant client object."""
|
42
|
-
|
43
|
-
collection_name: str
|
44
|
-
"""The name of the qdrant collection."""
|
45
|
-
|
46
|
-
|
47
|
-
@cached
|
48
|
-
def convert_distance_metric(metric: DistanceMetric) -> Any:
|
49
|
-
"""Convert string distance metric to qdrant Distance enum."""
|
50
|
-
try:
|
51
|
-
from qdrant_client.models import Distance
|
52
|
-
|
53
|
-
mapping = {
|
54
|
-
"cosine": Distance.COSINE,
|
55
|
-
"dot": Distance.DOT,
|
56
|
-
"euclidean": Distance.EUCLID,
|
57
|
-
"manhattan": Distance.MANHATTAN,
|
58
|
-
}
|
59
|
-
|
60
|
-
return mapping.get(metric, Distance.DOT)
|
61
|
-
except ImportError:
|
62
|
-
raise QdrantCollectionIndexError(
|
63
|
-
"qdrant-client is required for QdrantCollectionIndex. "
|
64
|
-
"Install with: pip install qdrant-client"
|
65
|
-
)
|
66
|
-
|
67
|
-
|
68
|
-
@cached
|
69
|
-
def create_qdrant_client(settings: QdrantCollectionIndexSettings) -> Any:
|
70
|
-
"""Create a qdrant client from settings."""
|
71
|
-
try:
|
72
|
-
from qdrant_client import QdrantClient
|
73
|
-
except ImportError:
|
74
|
-
raise QdrantCollectionIndexError(
|
75
|
-
"qdrant-client is required for QdrantCollectionIndex. "
|
76
|
-
"Install with: pip install qdrant-client"
|
77
|
-
)
|
78
|
-
|
79
|
-
config = settings.get_qdrant_config()
|
80
|
-
|
81
|
-
if "path" in config:
|
82
|
-
# Local persistent storage
|
83
|
-
return QdrantClient(path=config["path"])
|
84
|
-
elif "host" in config:
|
85
|
-
# Remote server
|
86
|
-
client_kwargs = {
|
87
|
-
"host": config["host"],
|
88
|
-
"port": config.get("port", 6333),
|
89
|
-
"grpc_port": config.get("grpc_port", 6334),
|
90
|
-
"prefer_grpc": config.get("prefer_grpc", False),
|
91
|
-
}
|
92
|
-
|
93
|
-
if config.get("api_key"):
|
94
|
-
client_kwargs["api_key"] = config["api_key"]
|
95
|
-
if config.get("timeout"):
|
96
|
-
client_kwargs["timeout"] = config["timeout"]
|
97
|
-
|
98
|
-
return QdrantClient(**client_kwargs)
|
99
|
-
else:
|
100
|
-
# In-memory database
|
101
|
-
return QdrantClient(":memory:")
|
102
|
-
|
103
|
-
|
104
|
-
def prepare_vector(
|
105
|
-
vector: Union[List[float], Any],
|
106
|
-
expected_size: int,
|
107
|
-
) -> List[float]:
|
108
|
-
"""Prepare and validate a vector for qdrant storage."""
|
109
|
-
if NUMPY_AVAILABLE and hasattr(vector, "tolist"):
|
110
|
-
# Handle numpy arrays
|
111
|
-
vector = vector.tolist()
|
112
|
-
elif not isinstance(vector, list):
|
113
|
-
raise QdrantCollectionIndexError(
|
114
|
-
f"Vector must be a list or numpy array, got {type(vector)}"
|
115
|
-
)
|
116
|
-
|
117
|
-
if len(vector) != expected_size:
|
118
|
-
raise QdrantCollectionIndexError(
|
119
|
-
f"Vector size {len(vector)} doesn't match expected size {expected_size}"
|
120
|
-
)
|
121
|
-
|
122
|
-
# Ensure all elements are floats
|
123
|
-
try:
|
124
|
-
return [float(x) for x in vector]
|
125
|
-
except (TypeError, ValueError) as e:
|
126
|
-
raise QdrantCollectionIndexError(f"Vector contains non-numeric values: {e}")
|
127
|
-
|
128
|
-
|
129
|
-
def build_qdrant_filter(filters: Optional[Dict[str, Any]]) -> Optional[Any]:
|
130
|
-
"""Build qdrant filter from filters dict."""
|
131
|
-
if not filters:
|
132
|
-
return None
|
133
|
-
|
134
|
-
try:
|
135
|
-
from qdrant_client.models import Filter, FieldCondition, MatchValue
|
136
|
-
|
137
|
-
conditions = []
|
138
|
-
for key, value in filters.items():
|
139
|
-
conditions.append(FieldCondition(key=key, match=MatchValue(value=value)))
|
140
|
-
|
141
|
-
if len(conditions) == 1:
|
142
|
-
return Filter(must=[conditions[0]])
|
143
|
-
else:
|
144
|
-
return Filter(must=conditions)
|
145
|
-
|
146
|
-
except ImportError:
|
147
|
-
raise QdrantCollectionIndexError(
|
148
|
-
"qdrant-client is required for QdrantCollectionIndex. "
|
149
|
-
"Install with: pip install qdrant-client"
|
150
|
-
)
|
151
|
-
|
152
|
-
|
153
|
-
def create_collection_if_not_exists(
|
154
|
-
client: Any,
|
155
|
-
collection_name: str,
|
156
|
-
settings: QdrantCollectionIndexSettings,
|
157
|
-
) -> None:
|
158
|
-
"""Create qdrant collection if it doesn't exist."""
|
159
|
-
try:
|
160
|
-
from qdrant_client.models import VectorParams
|
161
|
-
|
162
|
-
# Check if collection exists
|
163
|
-
try:
|
164
|
-
collections = client.get_collections()
|
165
|
-
collection_names = [col.name for col in collections.collections]
|
166
|
-
|
167
|
-
if collection_name not in collection_names:
|
168
|
-
# Create collection
|
169
|
-
distance_metric = convert_distance_metric(settings.distance_metric)
|
170
|
-
|
171
|
-
client.create_collection(
|
172
|
-
collection_name=collection_name,
|
173
|
-
vectors_config=VectorParams(
|
174
|
-
size=settings.vector_size, distance=distance_metric
|
175
|
-
),
|
176
|
-
)
|
177
|
-
except Exception:
|
178
|
-
# Collection might already exist or other issue
|
179
|
-
pass
|
180
|
-
|
181
|
-
except ImportError:
|
182
|
-
raise QdrantCollectionIndexError(
|
183
|
-
"qdrant-client is required for QdrantCollectionIndex. "
|
184
|
-
"Install with: pip install qdrant-client"
|
185
|
-
)
|
186
|
-
|
187
|
-
|
188
|
-
@cached
|
189
|
-
def serialize(obj: Any) -> Any:
|
190
|
-
"""Serialize an object to JSON-compatible format."""
|
191
|
-
try:
|
192
|
-
from msgspec import json
|
193
|
-
|
194
|
-
return json.decode(json.encode(obj))
|
195
|
-
except Exception:
|
196
|
-
# Fallback to manual serialization if msgspec fails
|
197
|
-
from dataclasses import is_dataclass, asdict
|
198
|
-
|
199
|
-
if isinstance(obj, (str, int, float, bool, type(None))):
|
200
|
-
return obj
|
201
|
-
elif isinstance(obj, (list, tuple)):
|
202
|
-
return [serialize(item) for item in obj]
|
203
|
-
elif isinstance(obj, dict):
|
204
|
-
return {k: serialize(v) for k, v in obj.items()}
|
205
|
-
elif is_dataclass(obj):
|
206
|
-
return serialize(asdict(obj))
|
207
|
-
elif hasattr(obj, "__dict__"):
|
208
|
-
return serialize(obj.__dict__)
|
209
|
-
else:
|
210
|
-
return str(obj)
|
@@ -1 +0,0 @@
|
|
1
|
-
"""hammad.data.collections.indexes.tantivy"""
|