hammad-python 0.0.18__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.
Files changed (83) hide show
  1. hammad/__init__.py +7 -137
  2. hammad/_internal.py +1 -0
  3. hammad/cli/_runner.py +8 -8
  4. hammad/cli/plugins.py +55 -26
  5. hammad/cli/styles/utils.py +16 -8
  6. hammad/data/__init__.py +1 -5
  7. hammad/data/collections/__init__.py +2 -3
  8. hammad/data/collections/collection.py +41 -22
  9. hammad/data/collections/indexes/__init__.py +1 -1
  10. hammad/data/collections/indexes/qdrant/__init__.py +1 -1
  11. hammad/data/collections/indexes/qdrant/index.py +106 -118
  12. hammad/data/collections/indexes/qdrant/settings.py +14 -14
  13. hammad/data/collections/indexes/qdrant/utils.py +28 -38
  14. hammad/data/collections/indexes/tantivy/__init__.py +1 -1
  15. hammad/data/collections/indexes/tantivy/index.py +57 -59
  16. hammad/data/collections/indexes/tantivy/settings.py +8 -19
  17. hammad/data/collections/indexes/tantivy/utils.py +28 -52
  18. hammad/data/models/__init__.py +2 -7
  19. hammad/data/sql/__init__.py +1 -1
  20. hammad/data/sql/database.py +71 -73
  21. hammad/data/sql/types.py +37 -51
  22. hammad/formatting/__init__.py +2 -1
  23. hammad/formatting/json/converters.py +2 -2
  24. hammad/genai/__init__.py +96 -36
  25. hammad/genai/agents/__init__.py +47 -1
  26. hammad/genai/agents/agent.py +1022 -0
  27. hammad/genai/agents/run.py +615 -0
  28. hammad/genai/agents/types/__init__.py +29 -22
  29. hammad/genai/agents/types/agent_context.py +13 -0
  30. hammad/genai/agents/types/agent_event.py +128 -0
  31. hammad/genai/agents/types/agent_hooks.py +220 -0
  32. hammad/genai/agents/types/agent_messages.py +31 -0
  33. hammad/genai/agents/types/agent_response.py +90 -0
  34. hammad/genai/agents/types/agent_stream.py +242 -0
  35. hammad/genai/models/__init__.py +1 -0
  36. hammad/genai/models/embeddings/__init__.py +39 -0
  37. hammad/genai/{embedding_models/embedding_model.py → models/embeddings/model.py} +45 -41
  38. hammad/genai/{embedding_models → models/embeddings}/run.py +10 -8
  39. hammad/genai/models/embeddings/types/__init__.py +37 -0
  40. hammad/genai/{embedding_models → models/embeddings/types}/embedding_model_name.py +2 -4
  41. hammad/genai/{embedding_models → models/embeddings/types}/embedding_model_response.py +11 -4
  42. hammad/genai/{embedding_models/embedding_model_request.py → models/embeddings/types/embedding_model_run_params.py} +4 -3
  43. hammad/genai/models/embeddings/types/embedding_model_settings.py +47 -0
  44. hammad/genai/models/language/__init__.py +48 -0
  45. hammad/genai/{language_models/language_model.py → models/language/model.py} +481 -204
  46. hammad/genai/{language_models → models/language}/run.py +80 -57
  47. hammad/genai/models/language/types/__init__.py +40 -0
  48. hammad/genai/models/language/types/language_model_instructor_mode.py +47 -0
  49. hammad/genai/models/language/types/language_model_messages.py +28 -0
  50. hammad/genai/{language_models/_types.py → models/language/types/language_model_name.py} +3 -40
  51. hammad/genai/{language_models → models/language/types}/language_model_request.py +17 -25
  52. hammad/genai/{language_models → models/language/types}/language_model_response.py +61 -68
  53. hammad/genai/{language_models → models/language/types}/language_model_response_chunk.py +8 -5
  54. hammad/genai/models/language/types/language_model_settings.py +89 -0
  55. hammad/genai/{language_models/_streaming.py → models/language/types/language_model_stream.py} +221 -243
  56. hammad/genai/{language_models/_utils → models/language/utils}/__init__.py +8 -11
  57. hammad/genai/models/language/utils/requests.py +421 -0
  58. hammad/genai/{language_models/_utils/_structured_outputs.py → models/language/utils/structured_outputs.py} +31 -20
  59. hammad/genai/models/model_provider.py +4 -0
  60. hammad/genai/{multimodal_models.py → models/multimodal.py} +4 -5
  61. hammad/genai/models/reranking.py +26 -0
  62. hammad/genai/types/__init__.py +1 -0
  63. hammad/genai/types/base.py +215 -0
  64. hammad/genai/{agents/types → types}/history.py +101 -88
  65. hammad/genai/{agents/types/tool.py → types/tools.py} +156 -141
  66. hammad/logging/logger.py +2 -1
  67. hammad/mcp/client/__init__.py +2 -3
  68. hammad/mcp/client/client.py +10 -10
  69. hammad/mcp/servers/__init__.py +2 -1
  70. hammad/service/decorators.py +1 -3
  71. hammad/web/models.py +1 -3
  72. hammad/web/search/client.py +10 -22
  73. {hammad_python-0.0.18.dist-info → hammad_python-0.0.20.dist-info}/METADATA +10 -2
  74. hammad_python-0.0.20.dist-info/RECORD +127 -0
  75. hammad/genai/embedding_models/__init__.py +0 -41
  76. hammad/genai/language_models/__init__.py +0 -35
  77. hammad/genai/language_models/_utils/_completions.py +0 -131
  78. hammad/genai/language_models/_utils/_messages.py +0 -89
  79. hammad/genai/language_models/_utils/_requests.py +0 -202
  80. hammad/genai/rerank_models.py +0 -26
  81. hammad_python-0.0.18.dist-info/RECORD +0 -111
  82. {hammad_python-0.0.18.dist-info → hammad_python-0.0.20.dist-info}/WHEEL +0 -0
  83. {hammad_python-0.0.18.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, Literal, Optional, TYPE_CHECKING
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
- if TYPE_CHECKING:
14
- try:
15
- from litellm import EmbeddingResponse as _LitellmEmbeddingResponse
16
- except ImportError:
17
- _LitellmEmbeddingResponse = Any
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 ...formatting.text import convert_to_text
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(response: "_LitellmEmbeddingResponse") -> EmbeddingModelResponse:
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
- data=embedding_data,
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 = _AIProvider.get_litellm().aembedding
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(f"Error in embedding model request: {e}", response=None) from e
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 .embedding_model_name import EmbeddingModelName
9
- from .embedding_model import EmbeddingModel
10
- from .embedding_model_response import EmbeddingModelResponse
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(BaseModel):
45
- data: List[Embedding]
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.data[0].embedding)
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.data)}\n"
75
+ f">>> Number of Generated Embeddings: {len(self.output)}\n"
69
76
  )
@@ -1,6 +1,7 @@
1
- """hammad.genai.embedding_models.embedding_model_request"""
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
- "EmbeddingModelRequest",
24
+ "EmbeddingModelRunParams",
24
25
  ]
25
26
 
26
27
 
27
- class EmbeddingModelRequest(TypedDict, total=False):
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."""