hammad-python 0.0.19__py3-none-any.whl → 0.0.20__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.
- hammad/__init__.py +7 -137
- hammad/_internal.py +1 -0
- hammad/cli/_runner.py +8 -8
- hammad/cli/plugins.py +55 -26
- hammad/cli/styles/utils.py +16 -8
- hammad/data/__init__.py +1 -5
- hammad/data/collections/__init__.py +2 -3
- hammad/data/collections/collection.py +41 -22
- hammad/data/collections/indexes/__init__.py +1 -1
- hammad/data/collections/indexes/qdrant/__init__.py +1 -1
- hammad/data/collections/indexes/qdrant/index.py +106 -118
- hammad/data/collections/indexes/qdrant/settings.py +14 -14
- hammad/data/collections/indexes/qdrant/utils.py +28 -38
- hammad/data/collections/indexes/tantivy/__init__.py +1 -1
- hammad/data/collections/indexes/tantivy/index.py +57 -59
- hammad/data/collections/indexes/tantivy/settings.py +8 -19
- hammad/data/collections/indexes/tantivy/utils.py +28 -52
- hammad/data/models/__init__.py +2 -7
- hammad/data/sql/__init__.py +1 -1
- hammad/data/sql/database.py +71 -73
- hammad/data/sql/types.py +37 -51
- hammad/formatting/__init__.py +2 -1
- hammad/formatting/json/converters.py +2 -2
- hammad/genai/__init__.py +96 -36
- hammad/genai/agents/__init__.py +47 -1
- hammad/genai/agents/agent.py +1022 -0
- hammad/genai/agents/run.py +615 -0
- hammad/genai/agents/types/__init__.py +29 -22
- hammad/genai/agents/types/agent_context.py +13 -0
- hammad/genai/agents/types/agent_event.py +128 -0
- hammad/genai/agents/types/agent_hooks.py +220 -0
- hammad/genai/agents/types/agent_messages.py +31 -0
- hammad/genai/agents/types/agent_response.py +90 -0
- hammad/genai/agents/types/agent_stream.py +242 -0
- hammad/genai/models/__init__.py +1 -0
- hammad/genai/models/embeddings/__init__.py +39 -0
- hammad/genai/{embedding_models/embedding_model.py → models/embeddings/model.py} +45 -41
- hammad/genai/{embedding_models → models/embeddings}/run.py +10 -8
- hammad/genai/models/embeddings/types/__init__.py +37 -0
- hammad/genai/{embedding_models → models/embeddings/types}/embedding_model_name.py +2 -4
- hammad/genai/{embedding_models → models/embeddings/types}/embedding_model_response.py +11 -4
- hammad/genai/{embedding_models/embedding_model_request.py → models/embeddings/types/embedding_model_run_params.py} +4 -3
- hammad/genai/models/embeddings/types/embedding_model_settings.py +47 -0
- hammad/genai/models/language/__init__.py +48 -0
- hammad/genai/{language_models/language_model.py → models/language/model.py} +481 -204
- hammad/genai/{language_models → models/language}/run.py +80 -57
- hammad/genai/models/language/types/__init__.py +40 -0
- hammad/genai/models/language/types/language_model_instructor_mode.py +47 -0
- hammad/genai/models/language/types/language_model_messages.py +28 -0
- hammad/genai/{language_models/_types.py → models/language/types/language_model_name.py} +3 -40
- hammad/genai/{language_models → models/language/types}/language_model_request.py +17 -25
- hammad/genai/{language_models → models/language/types}/language_model_response.py +61 -68
- hammad/genai/{language_models → models/language/types}/language_model_response_chunk.py +8 -5
- hammad/genai/models/language/types/language_model_settings.py +89 -0
- hammad/genai/{language_models/_streaming.py → models/language/types/language_model_stream.py} +221 -243
- hammad/genai/{language_models/_utils → models/language/utils}/__init__.py +8 -11
- hammad/genai/models/language/utils/requests.py +421 -0
- hammad/genai/{language_models/_utils/_structured_outputs.py → models/language/utils/structured_outputs.py} +31 -20
- hammad/genai/models/model_provider.py +4 -0
- hammad/genai/{multimodal_models.py → models/multimodal.py} +4 -5
- hammad/genai/models/reranking.py +26 -0
- hammad/genai/types/__init__.py +1 -0
- hammad/genai/types/base.py +215 -0
- hammad/genai/{agents/types → types}/history.py +101 -88
- hammad/genai/{agents/types/tool.py → types/tools.py} +156 -141
- hammad/logging/logger.py +1 -1
- hammad/mcp/client/__init__.py +2 -3
- hammad/mcp/client/client.py +10 -10
- hammad/mcp/servers/__init__.py +2 -1
- hammad/service/decorators.py +1 -3
- hammad/web/models.py +1 -3
- hammad/web/search/client.py +10 -22
- {hammad_python-0.0.19.dist-info → hammad_python-0.0.20.dist-info}/METADATA +10 -2
- hammad_python-0.0.20.dist-info/RECORD +127 -0
- hammad/genai/embedding_models/__init__.py +0 -41
- hammad/genai/language_models/__init__.py +0 -35
- hammad/genai/language_models/_utils/_completions.py +0 -131
- hammad/genai/language_models/_utils/_messages.py +0 -89
- hammad/genai/language_models/_utils/_requests.py +0 -202
- hammad/genai/rerank_models.py +0 -26
- hammad_python-0.0.19.dist-info/RECORD +0 -111
- {hammad_python-0.0.19.dist-info → hammad_python-0.0.20.dist-info}/WHEEL +0 -0
- {hammad_python-0.0.19.dist-info → hammad_python-0.0.20.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,242 @@
|
|
1
|
+
"""hammad.genai.agents.types.agent_stream"""
|
2
|
+
|
3
|
+
from typing import (
|
4
|
+
Generic,
|
5
|
+
TypeVar,
|
6
|
+
Iterator,
|
7
|
+
AsyncIterator,
|
8
|
+
List,
|
9
|
+
Any,
|
10
|
+
Dict,
|
11
|
+
Optional,
|
12
|
+
TYPE_CHECKING,
|
13
|
+
Type,
|
14
|
+
Union,
|
15
|
+
Literal,
|
16
|
+
)
|
17
|
+
from contextlib import contextmanager, asynccontextmanager
|
18
|
+
|
19
|
+
from ...types.base import BaseGenAIModelStream
|
20
|
+
from ...types.tools import (
|
21
|
+
Tool,
|
22
|
+
execute_tools_from_language_model_response,
|
23
|
+
)
|
24
|
+
from ...models.language.model import LanguageModel
|
25
|
+
from ...models.language.types import (
|
26
|
+
LanguageModelMessages,
|
27
|
+
LanguageModelResponse,
|
28
|
+
LanguageModelResponseChunk,
|
29
|
+
LanguageModelStream,
|
30
|
+
LanguageModelSettings,
|
31
|
+
)
|
32
|
+
from ...models.language.utils.requests import (
|
33
|
+
parse_messages_input as parse_messages,
|
34
|
+
consolidate_system_messages,
|
35
|
+
)
|
36
|
+
|
37
|
+
from .agent_response import (
|
38
|
+
AgentResponse,
|
39
|
+
_create_agent_response_from_language_model_response,
|
40
|
+
)
|
41
|
+
|
42
|
+
if TYPE_CHECKING:
|
43
|
+
from ..agent import Agent
|
44
|
+
|
45
|
+
T = TypeVar("T")
|
46
|
+
|
47
|
+
|
48
|
+
class AgentResponseChunk(LanguageModelResponseChunk[T], Generic[T]):
|
49
|
+
"""A chunk from an agent response stream representing a single step."""
|
50
|
+
|
51
|
+
def __init__(
|
52
|
+
self,
|
53
|
+
step_number: int,
|
54
|
+
response: LanguageModelResponse[str],
|
55
|
+
output: T | None = None,
|
56
|
+
content: str | None = None,
|
57
|
+
model: str | None = None,
|
58
|
+
is_final: bool = False,
|
59
|
+
**kwargs: Any,
|
60
|
+
):
|
61
|
+
"""Initialize a AgentResponseChunk.
|
62
|
+
|
63
|
+
Args:
|
64
|
+
step_number: The step number of this chunk
|
65
|
+
response: The language model response for this step
|
66
|
+
output: The output value
|
67
|
+
content: The content string
|
68
|
+
model: The model name
|
69
|
+
is_final: Whether this is the final chunk
|
70
|
+
**kwargs: Additional keyword arguments
|
71
|
+
"""
|
72
|
+
super().__init__(
|
73
|
+
output=output if output is not None else response.output,
|
74
|
+
content=content if content is not None else response.content,
|
75
|
+
model=model if model is not None else response.model,
|
76
|
+
is_final=is_final,
|
77
|
+
**kwargs,
|
78
|
+
)
|
79
|
+
self.step_number = step_number
|
80
|
+
self.response = response
|
81
|
+
|
82
|
+
def __bool__(self) -> bool:
|
83
|
+
"""Check if this chunk has meaningful content."""
|
84
|
+
return bool(self.response)
|
85
|
+
|
86
|
+
def __str__(self) -> str:
|
87
|
+
"""String representation of the chunk."""
|
88
|
+
return f"AgentResponseChunk(step={self.step_number}, final={self.is_final})"
|
89
|
+
|
90
|
+
|
91
|
+
class AgentStream(BaseGenAIModelStream[AgentResponseChunk[T]], Generic[T]):
|
92
|
+
"""Stream of agent responses that can be used in sync and async contexts."""
|
93
|
+
|
94
|
+
def __init__(
|
95
|
+
self,
|
96
|
+
agent: "Agent[T]",
|
97
|
+
messages: LanguageModelMessages,
|
98
|
+
model: Optional[Union[LanguageModel, str]] = None,
|
99
|
+
max_steps: Optional[int] = None,
|
100
|
+
context: Optional[Any] = None,
|
101
|
+
output_type: Optional[Type[T]] = None,
|
102
|
+
stream: bool = False,
|
103
|
+
**kwargs: Any,
|
104
|
+
):
|
105
|
+
self.agent = agent
|
106
|
+
self.messages = messages
|
107
|
+
self.context = context
|
108
|
+
self.output_type = output_type
|
109
|
+
self.stream = stream
|
110
|
+
self.kwargs = kwargs
|
111
|
+
self.current_step = 0
|
112
|
+
self.steps: List[LanguageModelResponse[str]] = []
|
113
|
+
self.current_messages = parse_messages(messages)
|
114
|
+
self.is_done = False
|
115
|
+
self._final_response: Optional[LanguageModelResponse[str]] = None
|
116
|
+
|
117
|
+
# Model setup
|
118
|
+
if model is None:
|
119
|
+
self.model = agent.model
|
120
|
+
elif isinstance(model, str):
|
121
|
+
self.model = LanguageModel(model=model)
|
122
|
+
else:
|
123
|
+
self.model = model
|
124
|
+
|
125
|
+
# Max steps setup
|
126
|
+
self.max_steps = max_steps or agent.settings.max_steps
|
127
|
+
|
128
|
+
# Context handling
|
129
|
+
self.current_context = context
|
130
|
+
|
131
|
+
# Model kwargs setup
|
132
|
+
self.model_kwargs = kwargs.copy()
|
133
|
+
if output_type:
|
134
|
+
self.model_kwargs["type"] = output_type
|
135
|
+
if agent.instructor_mode:
|
136
|
+
self.model_kwargs["instructor_mode"] = agent.instructor_mode
|
137
|
+
if stream:
|
138
|
+
self.model_kwargs["stream"] = stream
|
139
|
+
|
140
|
+
def _format_messages(self, messages: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
|
141
|
+
if self.agent.instructions:
|
142
|
+
system_message = {"role": "system", "content": self.agent.instructions}
|
143
|
+
messages = [system_message] + messages
|
144
|
+
return consolidate_system_messages(messages)
|
145
|
+
|
146
|
+
def _process_response(
|
147
|
+
self, response: LanguageModelResponse
|
148
|
+
) -> AgentResponseChunk[T]:
|
149
|
+
self.current_messages.append(response.to_message())
|
150
|
+
|
151
|
+
if response.has_tool_calls:
|
152
|
+
tool_responses = execute_tools_from_language_model_response(
|
153
|
+
tools=self.agent.tools, response=response
|
154
|
+
)
|
155
|
+
for tool_resp in tool_responses:
|
156
|
+
self.current_messages.append(tool_resp.to_dict())
|
157
|
+
|
158
|
+
self.steps.append(response)
|
159
|
+
return AgentResponseChunk(
|
160
|
+
step_number=self.current_step, response=response, is_final=False
|
161
|
+
)
|
162
|
+
else:
|
163
|
+
self.is_done = True
|
164
|
+
self._final_response = response
|
165
|
+
return AgentResponseChunk(
|
166
|
+
step_number=self.current_step, response=response, is_final=True
|
167
|
+
)
|
168
|
+
|
169
|
+
def __iter__(self) -> Iterator[AgentResponseChunk[T]]:
|
170
|
+
# The context manager handling should be managed by the agent's run method
|
171
|
+
while not self.is_done and self.current_step < self.max_steps:
|
172
|
+
self.current_step += 1
|
173
|
+
|
174
|
+
formatted_messages = self.current_messages
|
175
|
+
if self.current_step == 1:
|
176
|
+
formatted_messages = self._format_messages(self.current_messages)
|
177
|
+
|
178
|
+
response = self.model.run(
|
179
|
+
messages=formatted_messages,
|
180
|
+
tools=[tool.model_dump() for tool in self.agent.tools]
|
181
|
+
if self.agent.tools
|
182
|
+
else None,
|
183
|
+
**self.model_kwargs,
|
184
|
+
)
|
185
|
+
|
186
|
+
chunk = self._process_response(response)
|
187
|
+
yield chunk
|
188
|
+
if chunk.is_final:
|
189
|
+
break
|
190
|
+
|
191
|
+
def __aiter__(self) -> AsyncIterator[AgentResponseChunk[T]]:
|
192
|
+
return self
|
193
|
+
|
194
|
+
async def __anext__(self) -> AgentResponseChunk[T]:
|
195
|
+
if self.is_done or self.current_step >= self.max_steps:
|
196
|
+
raise StopAsyncIteration
|
197
|
+
|
198
|
+
# The context manager handling should be managed by the agent's run method
|
199
|
+
self.current_step += 1
|
200
|
+
|
201
|
+
formatted_messages = self.current_messages
|
202
|
+
if self.current_step == 1:
|
203
|
+
formatted_messages = self._format_messages(self.current_messages)
|
204
|
+
|
205
|
+
response = await self.model.async_run(
|
206
|
+
messages=formatted_messages,
|
207
|
+
tools=[tool.model_dump() for tool in self.agent.tools]
|
208
|
+
if self.agent.tools
|
209
|
+
else None,
|
210
|
+
**self.model_kwargs,
|
211
|
+
)
|
212
|
+
|
213
|
+
chunk = self._process_response(response)
|
214
|
+
if chunk.is_final:
|
215
|
+
self.is_done = True
|
216
|
+
return chunk
|
217
|
+
|
218
|
+
def _build_response(self) -> AgentResponse[T]:
|
219
|
+
if self._final_response:
|
220
|
+
final_response = self._final_response
|
221
|
+
elif self.steps:
|
222
|
+
final_response = self.steps[-1]
|
223
|
+
else:
|
224
|
+
raise RuntimeError("No response generated by the agent.")
|
225
|
+
|
226
|
+
return _create_agent_response_from_language_model_response(
|
227
|
+
response=final_response,
|
228
|
+
steps=self.steps,
|
229
|
+
context=self.current_context,
|
230
|
+
)
|
231
|
+
|
232
|
+
def collect(self) -> AgentResponse[T]:
|
233
|
+
"""Collect all steps and return final response."""
|
234
|
+
for _ in self:
|
235
|
+
pass
|
236
|
+
return self._build_response()
|
237
|
+
|
238
|
+
async def async_collect(self) -> AgentResponse[T]:
|
239
|
+
"""Collect all steps and return final response."""
|
240
|
+
async for _ in self:
|
241
|
+
pass
|
242
|
+
return self._build_response()
|
@@ -0,0 +1 @@
|
|
1
|
+
"""hammad.genai.models"""
|
@@ -0,0 +1,39 @@
|
|
1
|
+
"""hammad.genai.models.embeddings"""
|
2
|
+
|
3
|
+
from typing import TYPE_CHECKING
|
4
|
+
from ...._internal import create_getattr_importer
|
5
|
+
|
6
|
+
|
7
|
+
if TYPE_CHECKING:
|
8
|
+
from .model import EmbeddingModel
|
9
|
+
from .run import (
|
10
|
+
run_embedding_model,
|
11
|
+
async_run_embedding_model,
|
12
|
+
)
|
13
|
+
from .types import (
|
14
|
+
Embedding,
|
15
|
+
EmbeddingModelResponse,
|
16
|
+
EmbeddingModelSettings,
|
17
|
+
)
|
18
|
+
|
19
|
+
|
20
|
+
__all__ = [
|
21
|
+
"EmbeddingModel",
|
22
|
+
# hammad.genai.models.embeddings.run
|
23
|
+
"run_embedding_model",
|
24
|
+
"async_run_embedding_model",
|
25
|
+
# hammad.genai.models.embeddings.types.embedding
|
26
|
+
"Embedding",
|
27
|
+
# hammad.genai.models.embeddings.types.embedding_model_response
|
28
|
+
"EmbeddingModelResponse",
|
29
|
+
# hammad.genai.models.embeddings.types.embedding_model_settings
|
30
|
+
"EmbeddingModelSettings",
|
31
|
+
]
|
32
|
+
|
33
|
+
|
34
|
+
__getattr__ = create_getattr_importer(__all__)
|
35
|
+
|
36
|
+
|
37
|
+
def __dir__() -> list[str]:
|
38
|
+
"""Return the list of attributes to be shown in the REPL."""
|
39
|
+
return __all__
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
import asyncio
|
4
4
|
from dataclasses import dataclass
|
5
|
-
from typing import Any, List,
|
5
|
+
from typing import Any, List, Optional
|
6
6
|
import sys
|
7
7
|
|
8
8
|
if sys.version_info >= (3, 12):
|
@@ -10,21 +10,17 @@ if sys.version_info >= (3, 12):
|
|
10
10
|
else:
|
11
11
|
from typing_extensions import TypedDict
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
from ..language_models.language_model import _AIProvider
|
20
|
-
from .embedding_model_request import EmbeddingModelRequest
|
21
|
-
from .embedding_model_name import EmbeddingModelName
|
22
|
-
from .embedding_model_response import (
|
13
|
+
from ..model_provider import litellm
|
14
|
+
|
15
|
+
from .types import (
|
16
|
+
EmbeddingModelName,
|
17
|
+
EmbeddingModelRunParams,
|
18
|
+
EmbeddingModelSettings,
|
23
19
|
Embedding,
|
24
20
|
EmbeddingUsage,
|
25
21
|
EmbeddingModelResponse,
|
26
22
|
)
|
27
|
-
from
|
23
|
+
from ....formatting.text import convert_to_text
|
28
24
|
|
29
25
|
|
30
26
|
__all__ = (
|
@@ -43,7 +39,9 @@ class EmbeddingModelError(Exception):
|
|
43
39
|
super().__init__(self.message)
|
44
40
|
|
45
41
|
|
46
|
-
def _parse_litellm_response_to_embedding_model_response(
|
42
|
+
def _parse_litellm_response_to_embedding_model_response(
|
43
|
+
response: "litellm.EmbeddingResponse",
|
44
|
+
) -> EmbeddingModelResponse:
|
47
45
|
"""Parse the response from `litellm` to an `EmbeddingModelResponse` object."""
|
48
46
|
try:
|
49
47
|
embedding_data: List[Embedding] = []
|
@@ -57,10 +55,11 @@ def _parse_litellm_response_to_embedding_model_response(response: "_LitellmEmbed
|
|
57
55
|
total_tokens=response.usage.total_tokens,
|
58
56
|
)
|
59
57
|
return EmbeddingModelResponse(
|
60
|
-
|
58
|
+
output=embedding_data,
|
61
59
|
model=response.model,
|
62
60
|
object="list",
|
63
61
|
usage=usage,
|
62
|
+
type="embedding_model",
|
64
63
|
)
|
65
64
|
except Exception as e:
|
66
65
|
raise EmbeddingModelError(
|
@@ -73,19 +72,30 @@ def _parse_litellm_response_to_embedding_model_response(response: "_LitellmEmbed
|
|
73
72
|
class EmbeddingModel:
|
74
73
|
"""Embeddings provider client that utilizes the `litellm` module
|
75
74
|
when generating embeddings."""
|
76
|
-
|
77
|
-
model: EmbeddingModelName = "openai/text-embedding-3-small"
|
78
|
-
|
75
|
+
|
76
|
+
model: EmbeddingModelName | str = "openai/text-embedding-3-small"
|
77
|
+
|
78
|
+
base_url: Optional[str] = None
|
79
|
+
"""Optional base URL for a custom embedding provider."""
|
80
|
+
|
81
|
+
api_key: Optional[str] = None
|
82
|
+
"""Optional API key for a custom embedding provider."""
|
83
|
+
|
84
|
+
api_type: Optional[str] = None
|
85
|
+
"""Optional API type for a custom embedding provider."""
|
86
|
+
|
87
|
+
api_version: Optional[str] = None
|
88
|
+
"""Optional API version for a custom embedding provider."""
|
89
|
+
|
90
|
+
settings: EmbeddingModelSettings = EmbeddingModelSettings()
|
91
|
+
"""Optional settings for the embedding model."""
|
92
|
+
|
79
93
|
async def async_run(
|
80
94
|
self,
|
81
95
|
input: List[Any] | Any,
|
82
96
|
dimensions: Optional[int] = None,
|
83
97
|
encoding_format: Optional[str] = None,
|
84
98
|
timeout=600,
|
85
|
-
api_base: Optional[str] = None,
|
86
|
-
api_version: Optional[str] = None,
|
87
|
-
api_key: Optional[str] = None,
|
88
|
-
api_type: Optional[str] = None,
|
89
99
|
caching: bool = False,
|
90
100
|
user: Optional[str] = None,
|
91
101
|
format: bool = False,
|
@@ -122,24 +132,26 @@ class EmbeddingModel:
|
|
122
132
|
i,
|
123
133
|
)
|
124
134
|
|
125
|
-
async_embedding_fn =
|
135
|
+
async_embedding_fn = litellm.aembedding
|
126
136
|
|
127
137
|
try:
|
128
138
|
response = await async_embedding_fn(
|
129
139
|
model=self.model,
|
130
140
|
input=input,
|
131
|
-
dimensions=dimensions,
|
132
|
-
encoding_format=encoding_format,
|
133
|
-
timeout=timeout,
|
134
|
-
api_base=api_base,
|
135
|
-
api_version=api_version,
|
136
|
-
api_key=api_key,
|
137
|
-
api_type=api_type,
|
138
|
-
caching=caching,
|
139
|
-
user=user,
|
141
|
+
dimensions=dimensions or self.settings.dimensions,
|
142
|
+
encoding_format=encoding_format or self.settings.encoding_format,
|
143
|
+
timeout=timeout or self.settings.timeout,
|
144
|
+
api_base=self.base_url or self.settings.api_base,
|
145
|
+
api_version=self.api_version or self.settings.api_version,
|
146
|
+
api_key=self.api_key or self.settings.api_key,
|
147
|
+
api_type=self.api_type or self.settings.api_type,
|
148
|
+
caching=caching or self.settings.caching,
|
149
|
+
user=user or self.settings.user,
|
140
150
|
)
|
141
151
|
except Exception as e:
|
142
|
-
raise EmbeddingModelError(
|
152
|
+
raise EmbeddingModelError(
|
153
|
+
f"Error in embedding model request: {e}", response=None
|
154
|
+
) from e
|
143
155
|
|
144
156
|
return _parse_litellm_response_to_embedding_model_response(response)
|
145
157
|
|
@@ -149,10 +161,6 @@ class EmbeddingModel:
|
|
149
161
|
dimensions: Optional[int] = None,
|
150
162
|
encoding_format: Optional[str] = None,
|
151
163
|
timeout=600,
|
152
|
-
api_base: Optional[str] = None,
|
153
|
-
api_version: Optional[str] = None,
|
154
|
-
api_key: Optional[str] = None,
|
155
|
-
api_type: Optional[str] = None,
|
156
164
|
caching: bool = False,
|
157
165
|
user: Optional[str] = None,
|
158
166
|
format: bool = False,
|
@@ -182,12 +190,8 @@ class EmbeddingModel:
|
|
182
190
|
dimensions=dimensions,
|
183
191
|
encoding_format=encoding_format,
|
184
192
|
timeout=timeout,
|
185
|
-
api_base=api_base,
|
186
|
-
api_version=api_version,
|
187
|
-
api_key=api_key,
|
188
|
-
api_type=api_type,
|
189
193
|
caching=caching,
|
190
194
|
user=user,
|
191
195
|
format=format,
|
192
196
|
)
|
193
|
-
)
|
197
|
+
)
|
@@ -5,9 +5,11 @@ Standalone functions for running embedding models with full parameter typing.
|
|
5
5
|
|
6
6
|
from typing import Any, List, Optional, overload, Union
|
7
7
|
|
8
|
-
from .
|
9
|
-
|
10
|
-
|
8
|
+
from .types import (
|
9
|
+
EmbeddingModelName,
|
10
|
+
EmbeddingModelResponse,
|
11
|
+
)
|
12
|
+
from .model import EmbeddingModel
|
11
13
|
|
12
14
|
__all__ = [
|
13
15
|
"run_embedding_model",
|
@@ -54,7 +56,7 @@ def run_embedding_model(
|
|
54
56
|
format: bool = False,
|
55
57
|
) -> EmbeddingModelResponse:
|
56
58
|
"""Run an embedding model with the given input.
|
57
|
-
|
59
|
+
|
58
60
|
Args:
|
59
61
|
input: The input text/content to generate embeddings for
|
60
62
|
model: The embedding model to use
|
@@ -68,7 +70,7 @@ def run_embedding_model(
|
|
68
70
|
caching: Whether to cache the request
|
69
71
|
user: The user to use for the request
|
70
72
|
format: Whether to format each non-string input as a markdown string
|
71
|
-
|
73
|
+
|
72
74
|
Returns:
|
73
75
|
EmbeddingModelResponse: The embedding response
|
74
76
|
"""
|
@@ -127,7 +129,7 @@ async def async_run_embedding_model(
|
|
127
129
|
format: bool = False,
|
128
130
|
) -> EmbeddingModelResponse:
|
129
131
|
"""Asynchronously run an embedding model with the given input.
|
130
|
-
|
132
|
+
|
131
133
|
Args:
|
132
134
|
input: The input text/content to generate embeddings for
|
133
135
|
model: The embedding model to use
|
@@ -141,7 +143,7 @@ async def async_run_embedding_model(
|
|
141
143
|
caching: Whether to cache the request
|
142
144
|
user: The user to use for the request
|
143
145
|
format: Whether to format each non-string input as a markdown string
|
144
|
-
|
146
|
+
|
145
147
|
Returns:
|
146
148
|
EmbeddingModelResponse: The embedding response
|
147
149
|
"""
|
@@ -158,4 +160,4 @@ async def async_run_embedding_model(
|
|
158
160
|
caching=caching,
|
159
161
|
user=user,
|
160
162
|
format=format,
|
161
|
-
)
|
163
|
+
)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
"""hammad.genai.models.embeddings.types"""
|
2
|
+
|
3
|
+
from typing import TYPE_CHECKING
|
4
|
+
from ....._internal import create_getattr_importer
|
5
|
+
|
6
|
+
|
7
|
+
if TYPE_CHECKING:
|
8
|
+
from .embedding_model_name import EmbeddingModelName
|
9
|
+
from .embedding_model_run_params import EmbeddingModelRunParams
|
10
|
+
from .embedding_model_response import (
|
11
|
+
Embedding,
|
12
|
+
EmbeddingUsage,
|
13
|
+
EmbeddingModelResponse,
|
14
|
+
)
|
15
|
+
from .embedding_model_settings import EmbeddingModelSettings
|
16
|
+
|
17
|
+
|
18
|
+
__all__ = [
|
19
|
+
# hammad.genai.models.embeddings.types.embedding_model_name
|
20
|
+
"EmbeddingModelName",
|
21
|
+
# hammad.genai.models.embeddings.types.embedding_model_run_params
|
22
|
+
"EmbeddingModelRunParams",
|
23
|
+
# hammad.genai.models.embeddings.types.embedding_model_response
|
24
|
+
"Embedding",
|
25
|
+
"EmbeddingUsage",
|
26
|
+
"EmbeddingModelResponse",
|
27
|
+
# hammad.genai.models.embeddings.types.embedding_model_settings
|
28
|
+
"EmbeddingModelSettings",
|
29
|
+
]
|
30
|
+
|
31
|
+
|
32
|
+
__getattr__ = create_getattr_importer(__all__)
|
33
|
+
|
34
|
+
|
35
|
+
def __dir__() -> list[str]:
|
36
|
+
"""Return the list of attributes to be shown in the REPL."""
|
37
|
+
return __all__
|
@@ -3,9 +3,7 @@
|
|
3
3
|
from typing import Literal
|
4
4
|
|
5
5
|
|
6
|
-
__all__ = (
|
7
|
-
"EmbeddingModelName",
|
8
|
-
)
|
6
|
+
__all__ = ("EmbeddingModelName",)
|
9
7
|
|
10
8
|
|
11
9
|
EmbeddingModelName = Literal[
|
@@ -74,4 +72,4 @@ EmbeddingModelName = Literal[
|
|
74
72
|
"ollama/all-minilm",
|
75
73
|
"ollama/nomic-embed-text",
|
76
74
|
]
|
77
|
-
"""Common embedding models supported by `litellm`."""
|
75
|
+
"""Common embedding models supported by `litellm`."""
|
@@ -4,6 +4,8 @@ from typing import List, Literal
|
|
4
4
|
|
5
5
|
from pydantic import BaseModel
|
6
6
|
|
7
|
+
from ....types.base import BaseGenAIModelResponse
|
8
|
+
|
7
9
|
__all__ = (
|
8
10
|
"Embedding",
|
9
11
|
"EmbeddingUsage",
|
@@ -41,8 +43,8 @@ class EmbeddingUsage(BaseModel):
|
|
41
43
|
"""The total number of tokens used by the request."""
|
42
44
|
|
43
45
|
|
44
|
-
class EmbeddingModelResponse(
|
45
|
-
|
46
|
+
class EmbeddingModelResponse(BaseGenAIModelResponse[List[Embedding]]):
|
47
|
+
output: List[Embedding]
|
46
48
|
"""The list of embeddings generated by the model."""
|
47
49
|
|
48
50
|
model: str
|
@@ -54,10 +56,15 @@ class EmbeddingModelResponse(BaseModel):
|
|
54
56
|
usage: EmbeddingUsage
|
55
57
|
"""The usage information for the request."""
|
56
58
|
|
59
|
+
@property
|
60
|
+
def data(self) -> List[Embedding]:
|
61
|
+
"""The list of embeddings generated by the model."""
|
62
|
+
return self.output
|
63
|
+
|
57
64
|
@property
|
58
65
|
def dimensions(self) -> int:
|
59
66
|
"""The dimensions of the embedding."""
|
60
|
-
return len(self.
|
67
|
+
return len(self.output[0].embedding)
|
61
68
|
|
62
69
|
def __str__(self) -> str:
|
63
70
|
return (
|
@@ -65,5 +72,5 @@ class EmbeddingModelResponse(BaseModel):
|
|
65
72
|
f">>> Model: {self.model}\n"
|
66
73
|
f">>> Dimensions: {self.dimensions}\n"
|
67
74
|
f">>> Usage: {self.usage}\n"
|
68
|
-
f">>> Number of Generated Embeddings: {len(self.
|
75
|
+
f">>> Number of Generated Embeddings: {len(self.output)}\n"
|
69
76
|
)
|
@@ -1,6 +1,7 @@
|
|
1
|
-
"""hammad.genai.embedding_models.
|
1
|
+
"""hammad.genai.embedding_models.embedding_model_run_params"""
|
2
2
|
|
3
3
|
import sys
|
4
|
+
|
4
5
|
if sys.version_info >= (3, 12):
|
5
6
|
from typing import TypedDict, Required, NotRequired
|
6
7
|
else:
|
@@ -20,11 +21,11 @@ from typing import (
|
|
20
21
|
from .embedding_model_name import EmbeddingModelName
|
21
22
|
|
22
23
|
__all__ = [
|
23
|
-
"
|
24
|
+
"EmbeddingModelRunParams",
|
24
25
|
]
|
25
26
|
|
26
27
|
|
27
|
-
class
|
28
|
+
class EmbeddingModelRunParams(TypedDict, total=False):
|
28
29
|
"""A request to an embedding model."""
|
29
30
|
|
30
31
|
input: List[Any] | Any
|
@@ -0,0 +1,47 @@
|
|
1
|
+
"""hammad.genai.models.embeddings.types.embedding_model_settings"""
|
2
|
+
|
3
|
+
from pydantic import BaseModel
|
4
|
+
from typing import Any, List, Optional
|
5
|
+
|
6
|
+
from .embedding_model_name import EmbeddingModelName
|
7
|
+
from ....types.base import BaseGenAIModelSettings
|
8
|
+
|
9
|
+
|
10
|
+
__all__ = [
|
11
|
+
"EmbeddingModelSettings",
|
12
|
+
]
|
13
|
+
|
14
|
+
|
15
|
+
class EmbeddingModelSettings(BaseGenAIModelSettings):
|
16
|
+
"""A request to an embedding model."""
|
17
|
+
|
18
|
+
format: bool = False
|
19
|
+
"""Whether to format each non-string input as a markdown string."""
|
20
|
+
|
21
|
+
# LiteLLM Settings
|
22
|
+
dimensions: Optional[int] = None
|
23
|
+
"""The dimensions of the embedding."""
|
24
|
+
|
25
|
+
encoding_format: Optional[str] = None
|
26
|
+
"""The encoding format of the embedding."""
|
27
|
+
|
28
|
+
timeout: Optional[int] = None
|
29
|
+
"""The timeout for the embedding request."""
|
30
|
+
|
31
|
+
api_base: Optional[str] = None
|
32
|
+
"""The API base for the embedding request."""
|
33
|
+
|
34
|
+
api_version: Optional[str] = None
|
35
|
+
"""The API version for the embedding request."""
|
36
|
+
|
37
|
+
api_key: Optional[str] = None
|
38
|
+
"""The API key for the embedding request."""
|
39
|
+
|
40
|
+
api_type: Optional[str] = None
|
41
|
+
"""The API type for the embedding request."""
|
42
|
+
|
43
|
+
caching: bool = False
|
44
|
+
"""Whether to cache the embedding request."""
|
45
|
+
|
46
|
+
user: Optional[str] = None
|
47
|
+
"""The user for the embedding request."""
|