hammad-python 0.0.25__py3-none-any.whl → 0.0.27__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 CHANGED
@@ -36,6 +36,7 @@ if TYPE_CHECKING:
36
36
 
37
37
  from ._main import (
38
38
  to,
39
+ run,
39
40
  fn,
40
41
  new,
41
42
  read,
@@ -68,6 +69,7 @@ __all__ = (
68
69
  "web_search",
69
70
  "web_request",
70
71
  "to",
72
+ "run",
71
73
  "fn",
72
74
  "new",
73
75
  "read",
@@ -222,7 +222,16 @@ def create_collection(
222
222
  distance_metric: "DistanceMetric" = "dot",
223
223
  settings: Optional["QdrantCollectionIndexSettings"] = None,
224
224
  query_settings: Optional["QdrantCollectionIndexQuerySettings"] = None,
225
- embedding_function: Optional[Callable[[Any], List[float]]] = None,
225
+ embedding_model: Optional[
226
+ "EmbeddingModelName"
227
+ ] = "openai/text-embedding-3-small",
228
+ embedding_dimensions: Optional[int] = None,
229
+ embedding_api_key: Optional[str] = None,
230
+ embedding_base_url: Optional[str] = None,
231
+ # Rerank-specific parameters
232
+ rerank_model: Optional[str] = None,
233
+ rerank_api_key: Optional[str] = None,
234
+ rerank_base_url: Optional[str] = None,
226
235
  ) -> "QdrantCollectionIndex": ...
227
236
 
228
237
 
@@ -247,7 +256,16 @@ def create_collection(
247
256
  ] = None,
248
257
  # Vector/Qdrant-specific parameters
249
258
  distance_metric: "DistanceMetric" = "dot",
250
- embedding_function: Optional[Callable[[Any], List[float]]] = None,
259
+ embedding_model: Optional[
260
+ "EmbeddingModelName"
261
+ ] = "openai/text-embedding-3-small",
262
+ embedding_dimensions: Optional[int] = None,
263
+ embedding_api_key: Optional[str] = None,
264
+ embedding_base_url: Optional[str] = None,
265
+ # Rerank-specific parameters
266
+ rerank_model: Optional[str] = None,
267
+ rerank_api_key: Optional[str] = None,
268
+ rerank_base_url: Optional[str] = None,
251
269
  ) -> Union["TantivyCollectionIndex", "QdrantCollectionIndex"]:
252
270
  """
253
271
  Create a data collection of the specified type. Collections are a unified
@@ -275,6 +293,11 @@ def create_collection(
275
293
  embedding_api_key: API key for the embedding service
276
294
  embedding_base_url: Base URL for the embedding service
277
295
 
296
+ # Rerank parameters (for vector collections):
297
+ rerank_model: The rerank model to use (e.g., 'cohere/rerank-english-v3.0')
298
+ rerank_api_key: API key for the rerank service
299
+ rerank_base_url: Base URL for the rerank service
300
+
278
301
  Returns:
279
302
  A TantivyCollectionIndex or QdrantCollectionIndex instance
280
303
  """
@@ -289,5 +312,11 @@ def create_collection(
289
312
  settings=settings,
290
313
  query_settings=query_settings,
291
314
  distance_metric=distance_metric,
292
- embedding_function=embedding_function,
315
+ embedding_model=embedding_model,
316
+ embedding_dimensions=embedding_dimensions,
317
+ embedding_api_key=embedding_api_key,
318
+ embedding_base_url=embedding_base_url,
319
+ rerank_model=rerank_model,
320
+ rerank_api_key=rerank_api_key,
321
+ rerank_base_url=rerank_base_url,
293
322
  )
@@ -0,0 +1,190 @@
1
+
2
+ from typing import TYPE_CHECKING
3
+
4
+ if TYPE_CHECKING:
5
+ from .base import BaseGraph
6
+
7
+
8
+ def visualize_base_graph(graph: "BaseGraph", filename: str) -> None:
9
+ """Generate a visualization of the graph with clean, readable flow."""
10
+ if not graph._action_nodes or not graph._start_action_name:
11
+ raise ValueError("No actions defined in graph")
12
+
13
+ # Build our own mermaid code for better control over layout
14
+ mermaid_lines = ["graph TD"] # Top-Down layout
15
+
16
+ # Track which nodes we've already added
17
+ added_nodes = set()
18
+
19
+ # Style definitions
20
+ mermaid_lines.append(" %% Styles")
21
+ mermaid_lines.append(" classDef startNode fill:#4CAF50,stroke:#333,stroke-width:2px,color:#fff")
22
+ mermaid_lines.append(" classDef endNode fill:#f44336,stroke:#333,stroke-width:2px,color:#fff")
23
+ mermaid_lines.append(" classDef defaultNode fill:#2196F3,stroke:#333,stroke-width:2px,color:#fff")
24
+ mermaid_lines.append("")
25
+
26
+ # Helper to get clean node ID
27
+ def get_node_id(action_name: str) -> str:
28
+ return action_name.replace(" ", "_").replace("-", "_")
29
+
30
+ # Helper to add a node if not already added
31
+ def add_node(action_name: str, is_start: bool = False, is_end: bool = False) -> None:
32
+ if action_name not in added_nodes:
33
+ node_id = get_node_id(action_name)
34
+ # Use the action name as the display label
35
+ display_name = action_name
36
+
37
+ if is_start:
38
+ mermaid_lines.append(f" {node_id}[{display_name}]:::startNode")
39
+ elif is_end:
40
+ mermaid_lines.append(f" {node_id}[{display_name}]:::endNode")
41
+ else:
42
+ mermaid_lines.append(f" {node_id}[{display_name}]:::defaultNode")
43
+ added_nodes.add(action_name)
44
+
45
+ # Add all nodes and connections
46
+ mermaid_lines.append(" %% Nodes and connections")
47
+
48
+ # Start with the start node
49
+ add_node(graph._start_action_name, is_start=True)
50
+
51
+ # Process all actions to find connections
52
+ for action_name in graph._action_nodes:
53
+ action_func = getattr(graph, action_name, None)
54
+ if action_func and hasattr(action_func, '_action_settings'):
55
+ settings = action_func._action_settings
56
+
57
+ # Add the node
58
+ add_node(action_name, is_end=settings.terminates)
59
+
60
+ # Add connections based on 'next' settings
61
+ if settings.next:
62
+ source_id = get_node_id(action_name)
63
+
64
+ if isinstance(settings.next, str):
65
+ # Simple string case
66
+ target_id = get_node_id(settings.next)
67
+ add_node(settings.next)
68
+ mermaid_lines.append(f" {source_id} --> {target_id}")
69
+
70
+ elif isinstance(settings.next, list):
71
+ # List case - branches to multiple nodes
72
+ for next_action in settings.next:
73
+ if isinstance(next_action, str):
74
+ target_id = get_node_id(next_action)
75
+ add_node(next_action)
76
+ mermaid_lines.append(f" {source_id} --> {target_id}")
77
+
78
+ elif hasattr(settings.next, '__class__') and settings.next.__class__.__name__ == 'SelectionStrategy':
79
+ # SelectionStrategy case
80
+ if settings.next.actions:
81
+ # Show all possible paths with a decision diamond
82
+ decision_id = f"{source_id}_decision"
83
+ mermaid_lines.append(f" {source_id} --> {decision_id}{{LLM Selection}}")
84
+
85
+ for next_action in settings.next.actions:
86
+ target_id = get_node_id(next_action)
87
+ add_node(next_action)
88
+ mermaid_lines.append(f" {decision_id} --> {target_id}")
89
+ else:
90
+ # If no specific actions, it can go to any node
91
+ # For visualization, show connections to all non-start nodes
92
+ decision_id = f"{source_id}_decision"
93
+ mermaid_lines.append(f" {source_id} --> {decision_id}{{LLM Selection}}")
94
+
95
+ for other_action in graph._action_nodes:
96
+ if other_action != action_name and other_action != graph._start_action_name:
97
+ target_id = get_node_id(other_action)
98
+ add_node(other_action)
99
+ mermaid_lines.append(f" {decision_id} -.-> {target_id}")
100
+
101
+ # If start node has no explicit next, but there are other nodes, show possible connections
102
+ start_func = getattr(graph, graph._start_action_name, None)
103
+ if start_func and hasattr(start_func, '_action_settings'):
104
+ if not start_func._action_settings.next and len(graph._action_nodes) > 1:
105
+ source_id = get_node_id(graph._start_action_name)
106
+ # Find end nodes (terminates=True) to connect to
107
+ for action_name in graph._action_nodes:
108
+ if action_name != graph._start_action_name:
109
+ action_func = getattr(graph, action_name, None)
110
+ if action_func and hasattr(action_func, '_action_settings'):
111
+ if action_func._action_settings.terminates:
112
+ target_id = get_node_id(action_name)
113
+ add_node(action_name, is_end=True)
114
+ mermaid_lines.append(f" {source_id} --> {target_id}")
115
+
116
+ # Join all lines
117
+ mermaid_code = "\n".join(mermaid_lines)
118
+
119
+ # Render the mermaid diagram and save it
120
+ try:
121
+ import subprocess
122
+ import tempfile
123
+ import os
124
+ import shutil
125
+
126
+ # Check if mmdc (mermaid CLI) is available
127
+ if shutil.which('mmdc') is None:
128
+ raise FileNotFoundError("mermaid-cli (mmdc) not found. Install with: npm install -g @mermaid-js/mermaid-cli")
129
+
130
+ # Create a temporary mermaid file
131
+ with tempfile.NamedTemporaryFile(mode='w', suffix='.mmd', delete=False) as temp_file:
132
+ temp_file.write(mermaid_code)
133
+ temp_mmd_path = temp_file.name
134
+
135
+ try:
136
+ # Determine output format from filename extension
137
+ output_format = 'png' # default
138
+ if filename.lower().endswith('.svg'):
139
+ output_format = 'svg'
140
+ elif filename.lower().endswith('.pdf'):
141
+ output_format = 'pdf'
142
+
143
+ # Use mermaid CLI to render the diagram
144
+ cmd = ['mmdc', '-i', temp_mmd_path, '-o', filename]
145
+
146
+ # Add format flag only if not PNG (PNG is default)
147
+ if output_format != 'png':
148
+ cmd.extend(['-f', output_format])
149
+
150
+ # Add theme and background color
151
+ cmd.extend(['-t', 'default', '-b', 'transparent'])
152
+
153
+ result = subprocess.run(cmd, capture_output=True, text=True, check=True)
154
+
155
+ if result.returncode == 0:
156
+ print(f"Graph visualization saved to: {filename}")
157
+ else:
158
+ raise subprocess.CalledProcessError(result.returncode, result.args, result.stderr)
159
+
160
+ finally:
161
+ # Clean up temporary file
162
+ if os.path.exists(temp_mmd_path):
163
+ os.unlink(temp_mmd_path)
164
+
165
+ except FileNotFoundError as e:
166
+ # Provide helpful error message for missing mermaid CLI
167
+ print(f"Warning: {e}")
168
+ # Save as .mmd file instead
169
+ mmd_filename = filename.rsplit('.', 1)[0] + '.mmd'
170
+ with open(mmd_filename, "w") as f:
171
+ f.write(mermaid_code)
172
+ print(f"Mermaid code saved to: {mmd_filename}")
173
+ print("To render as PNG, install mermaid-cli: npm install -g @mermaid-js/mermaid-cli")
174
+
175
+ except subprocess.CalledProcessError as e:
176
+ # Handle mermaid CLI errors
177
+ print(f"Error rendering mermaid diagram: {e.stderr if e.stderr else str(e)}")
178
+ # Save as .mmd file as fallback
179
+ mmd_filename = filename.rsplit('.', 1)[0] + '.mmd'
180
+ with open(mmd_filename, "w") as f:
181
+ f.write(mermaid_code)
182
+ print(f"Mermaid code saved to: {mmd_filename} (rendering failed)")
183
+
184
+ except Exception as e:
185
+ # General fallback: save the mermaid code
186
+ print(f"Unexpected error: {e}")
187
+ mmd_filename = filename.rsplit('.', 1)[0] + '.mmd'
188
+ with open(mmd_filename, "w") as f:
189
+ f.write(mermaid_code)
190
+ print(f"Mermaid code saved to: {mmd_filename}")
@@ -1,4 +1,4 @@
1
- """hammad.genai.graphs.base - Graph implementation using pydantic-graph with Agent/LanguageModel integration"""
1
+ """hammad.genai.graphs.base"""
2
2
 
3
3
  from typing import (
4
4
  Any,
@@ -44,6 +44,7 @@ from .types import (
44
44
  ActionSettings,
45
45
  GraphHistoryEntry,
46
46
  )
47
+ from ._utils import visualize_base_graph
47
48
 
48
49
  if TYPE_CHECKING:
49
50
  try:
@@ -825,6 +826,29 @@ class ActionDecorator:
825
826
 
826
827
  def decorator(f: Callable) -> Callable:
827
828
  action_name = name or f.__name__
829
+
830
+ # Check if action name is reserved
831
+ reserved_names = {
832
+ 'run', 'async_run', 'iter', 'async_iter',
833
+ 'visualize', 'builder', 'as_a2a',
834
+ '_initialize', '_collect_state_class', '_collect_actions',
835
+ '_create_pydantic_graph', '_get_start_action_signature'
836
+ }
837
+ if action_name in reserved_names:
838
+ raise ValueError(
839
+ f"Action name '{action_name}' is reserved and cannot be used. "
840
+ f"Reserved names include: {', '.join(sorted(reserved_names))}. "
841
+ "Please choose a different name for your action."
842
+ )
843
+
844
+ # Check that the action has at least one parameter besides 'self'
845
+ sig = inspect.signature(f)
846
+ params = [p for p in sig.parameters if p != 'self']
847
+ if not params:
848
+ raise ValueError(
849
+ f"Action '{action_name}' must have at least one parameter besides 'self'. "
850
+ "Actions need input parameters to process."
851
+ )
828
852
 
829
853
  # Create a dynamic ActionNode class for this specific action with unique name
830
854
  class DynamicActionNode(ActionNode[StateT]):
@@ -921,7 +945,7 @@ class BaseGraph(Generic[StateT, T]):
921
945
  self,
922
946
  state: Optional[StateT] = None,
923
947
  *,
924
- model: Optional[LanguageModelName | str] = None,
948
+ model: Optional[LanguageModelName | str] = "openai/gpt-4.1-nano",
925
949
  temperature: Optional[float] = None,
926
950
  max_tokens: Optional[int] = None,
927
951
  tools: Optional[List[Callable]] = None,
@@ -1160,6 +1184,10 @@ class BaseGraph(Generic[StateT, T]):
1160
1184
  # Merge global settings with provided kwargs
1161
1185
  merged_settings = self._global_settings.copy()
1162
1186
  merged_settings.update(language_model_kwargs)
1187
+
1188
+ # Include the global model if it's set and not overridden
1189
+ if self._global_model and "model" not in merged_settings:
1190
+ merged_settings["model"] = self._global_model
1163
1191
 
1164
1192
  # Pass verbose/debug flags (prefer explicit params over global settings)
1165
1193
  start_node._verbose = (
@@ -1329,6 +1357,10 @@ class BaseGraph(Generic[StateT, T]):
1329
1357
  # Merge global settings with provided kwargs
1330
1358
  merged_settings = self._global_settings.copy()
1331
1359
  merged_settings.update(language_model_kwargs)
1360
+
1361
+ # Include the global model if it's set and not overridden
1362
+ if self._global_model and "model" not in merged_settings:
1363
+ merged_settings["model"] = self._global_model
1332
1364
 
1333
1365
  # Pass verbose/debug flags (prefer explicit params over global settings)
1334
1366
  start_node._verbose = (
@@ -1466,6 +1498,10 @@ class BaseGraph(Generic[StateT, T]):
1466
1498
  # Merge global settings with provided kwargs
1467
1499
  merged_settings = self._global_settings.copy()
1468
1500
  merged_settings.update(language_model_kwargs)
1501
+
1502
+ # Include the global model if it's set and not overridden
1503
+ if self._global_model and "model" not in merged_settings:
1504
+ merged_settings["model"] = self._global_model
1469
1505
 
1470
1506
  # Pass verbose/debug flags (prefer explicit params over global settings)
1471
1507
  start_node._verbose = (
@@ -1634,6 +1670,10 @@ class BaseGraph(Generic[StateT, T]):
1634
1670
  # Merge global settings with provided kwargs
1635
1671
  merged_settings = self._global_settings.copy()
1636
1672
  merged_settings.update(language_model_kwargs)
1673
+
1674
+ # Include the global model if it's set and not overridden
1675
+ if self._global_model and "model" not in merged_settings:
1676
+ merged_settings["model"] = self._global_model
1637
1677
 
1638
1678
  # Pass verbose/debug flags (prefer explicit params over global settings)
1639
1679
  start_node._verbose = (
@@ -1678,18 +1718,6 @@ class BaseGraph(Generic[StateT, T]):
1678
1718
  **language_model_kwargs,
1679
1719
  )
1680
1720
 
1681
- def visualize(self, filename: str) -> None:
1682
- """Generate a visualization of the graph using pydantic-graph's mermaid support."""
1683
- if self._pydantic_graph and self._start_action_name:
1684
- start_node_class = self._action_nodes.get(self._start_action_name)
1685
- if start_node_class:
1686
- # Use pydantic-graph's built-in mermaid generation
1687
- mermaid_code = self._pydantic_graph.mermaid_code(
1688
- start_node=start_node_class
1689
- )
1690
- with open(filename, "w") as f:
1691
- f.write(mermaid_code)
1692
-
1693
1721
  @classmethod
1694
1722
  def builder(cls) -> GraphBuilder[StateT, T]:
1695
1723
  """Create a builder for this graph."""
@@ -1784,3 +1812,17 @@ class BaseGraph(Generic[StateT, T]):
1784
1812
  lifespan_timeout=lifespan_timeout,
1785
1813
  **uvicorn_kwargs,
1786
1814
  )
1815
+
1816
+ def visualize(self, filename: str) -> None:
1817
+ """Visualize the graph as mermaid.
1818
+
1819
+ Args:
1820
+ filename: The filename to save the visualization to.
1821
+
1822
+ Ex: 'graph.png' / 'graph.mmd'
1823
+
1824
+ Returns:
1825
+ None
1826
+
1827
+ """
1828
+ visualize_base_graph(self, filename)
@@ -13,6 +13,7 @@ from typing import (
13
13
  )
14
14
 
15
15
  from .....cache import cached
16
+ from .....typing import get_type_description
16
17
 
17
18
  from ...model_provider import litellm
18
19
  from ....types.base import BaseGenAIModelResponse
@@ -210,6 +211,7 @@ class LanguageModelResponse(BaseGenAIModelResponse[T]):
210
211
  output += f"\n{self.completion}"
211
212
 
212
213
  output += f"\n\n>>> Model: {self.model}"
214
+ output += f"\n>>> Type: {get_type_description(type(self.output))}"
213
215
  output += f"\n>>> Tool Calls: {len(self.tool_calls) if self.tool_calls else 0}"
214
216
 
215
217
  return output
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hammad-python
3
- Version: 0.0.25
3
+ Version: 0.0.27
4
4
  Author-email: Hammad Saeed <hammadaidev@gmail.com>
5
5
  License: MIT License
6
6
 
@@ -1,4 +1,4 @@
1
- hammad/__init__.py,sha256=KeGEXWQEjoDi4hNzPQXhydXZV2knovoiBcwDX0Y5cpw,1681
1
+ hammad/__init__.py,sha256=PtKUoTlLLfTA8cuhfvvaG1PCz6B4gkyl4d0OgZA0rNY,1705
2
2
  hammad/_internal.py,sha256=qQGXjzQyyCxzH5kMjCHwVdAojp-2OOVAO2T2QDxOBn8,8957
3
3
  hammad/_main.py,sha256=2y18WxvGqRtA0C4aaYK9-LhFXwhFvY6832kNmUyebRA,6902
4
4
  hammad/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -18,7 +18,7 @@ hammad/cli/styles/types.py,sha256=vNIeQY_23m10K8qVT7Iy-PMwosGL-La-UAZKszHJjEE,79
18
18
  hammad/cli/styles/utils.py,sha256=zzi0JdH1X7O8XWRlMVfJP2jB-OWt7zkpm_LeCHoSKVY,28287
19
19
  hammad/data/__init__.py,sha256=rga828Od--N3QeGlnOSweADD1WsRLjSTqkaZVk1VhW0,2232
20
20
  hammad/data/collections/__init__.py,sha256=xEORHnjoV75Fa6LFDMyFw90oDaJ0e9VmISLFV3mOsIQ,1110
21
- hammad/data/collections/collection.py,sha256=fi7jyT2GmXiGLNajjegBJMbefzggL0PIMHf-81ov7Bo,10833
21
+ hammad/data/collections/collection.py,sha256=SvmZY0B5_VDMQGX72TxLs9BMeDs8kASmROQca_F3534,11989
22
22
  hammad/data/collections/indexes/__init__.py,sha256=RmXKWKq2sbtA1swz5vamKKWut-eKfc-Q2tUnij-E-IU,960
23
23
  hammad/data/collections/indexes/qdrant/__init__.py,sha256=KU89TIJkYmJPnVxWKHfXntkIYwhn86ejXtWG30hCyHg,49
24
24
  hammad/data/collections/indexes/qdrant/index.py,sha256=UzhW64i5Yq5AXyGZjkW4dljgQxwKUbjF6vhzendbjko,25634
@@ -68,7 +68,8 @@ hammad/genai/agents/types/agent_messages.py,sha256=csjEq42bElaTZYZW2dE6nlFZc142-
68
68
  hammad/genai/agents/types/agent_response.py,sha256=tQ3oNBZC_9dD7t-7tRuKA2h1a-XE5gGryVF9XcmZ5GA,3863
69
69
  hammad/genai/agents/types/agent_stream.py,sha256=VIfqZp55wq6jQh_OtPzZjiL_K4cEoVCkeEZS3s_MIXI,11069
70
70
  hammad/genai/graphs/__init__.py,sha256=bK59ilXuR46DgSjat7kOOr_KujIpJSfbCSgriceRhjw,3112
71
- hammad/genai/graphs/base.py,sha256=0Q4VgWmRbe6UTNVCCow7Dc9czR9YkFVyXoR7h6AQQZk,68024
71
+ hammad/genai/graphs/_utils.py,sha256=kLPD9iAWhI7zRDTNLnYGRrD2f2IPre-0GYLMQcq1xzU,8854
72
+ hammad/genai/graphs/base.py,sha256=02kLcQRFJxGw-rPlfFBDWW9C9_CAlPYHdlTwu7rg7nA,69633
72
73
  hammad/genai/graphs/plugins.py,sha256=AK_JSo2eLCD9cdrxZ5OxxZtLVrUDcQ8f_FWBxOQPzyw,10007
73
74
  hammad/genai/graphs/types.py,sha256=kpQvWpE7cKjK9TzNFa_I-z7LfxWdlCuIA-lfRTk_nFU,20701
74
75
  hammad/genai/models/__init__.py,sha256=e4TbEsiKIoXENOEsdIdQcWWt0RnFdTEqCz0nICHQHtM,26
@@ -91,7 +92,7 @@ hammad/genai/models/language/types/language_model_instructor_mode.py,sha256=7ywB
91
92
  hammad/genai/models/language/types/language_model_messages.py,sha256=e-HZ_YKXq17gwmMlpOmYUYUpBFm7Mu3aRawtjSslWXs,504
92
93
  hammad/genai/models/language/types/language_model_name.py,sha256=2V70cZ47L9yIcug6LCcMHcvEJaee7gRN6DUPhLUBlsE,8056
93
94
  hammad/genai/models/language/types/language_model_request.py,sha256=ZtzhCx8o6zkEBS3uTFXFLf_poDD7MnIp1y7MbKckOmI,3911
94
- hammad/genai/models/language/types/language_model_response.py,sha256=uUmcaSBBb0-CrWOx1axZ-INHmgyac5ktiAbR-HyW-fk,7520
95
+ hammad/genai/models/language/types/language_model_response.py,sha256=CE-PWxmAB9RDzHqGjEUvYaVnbDnKYz4eEMW4Fz65F4s,7640
95
96
  hammad/genai/models/language/types/language_model_response_chunk.py,sha256=wIzGZw732KsI-a1-uASjATA6qvBuq-7rupWoFjsAgQo,1796
96
97
  hammad/genai/models/language/types/language_model_settings.py,sha256=C0EvLXZoOLgPZ4bX7mVFs_CWP-jam27qkseJRGsBAfQ,2794
97
98
  hammad/genai/models/language/types/language_model_stream.py,sha256=XgJ83JSbtTdf7jeLQMrDhMfI7zp0pRrdY7JWYbZV_h0,22043
@@ -128,7 +129,7 @@ hammad/web/openapi/__init__.py,sha256=JhJQ6_laBmB2djIYFc0vgGha2GsdUe4FP1LDdZCQ5J
128
129
  hammad/web/openapi/client.py,sha256=1pXz7KAO_0pN4kQZoWKWskXDYGiJ535TsPO1GGCiC0E,26816
129
130
  hammad/web/search/__init__.py,sha256=e9A6znPIiZCz-4secyHbUs0uUGf5yAqW6wGacgx961U,24
130
131
  hammad/web/search/client.py,sha256=LIx2MsHhn6cRTuq5i1mWowRTdIhPobY4GQV3S3bk9lk,36694
131
- hammad_python-0.0.25.dist-info/METADATA,sha256=cTOPOxOkgGaLI8kKAuRY1Expm0DVYLbpEDN8GCxcPbw,6785
132
- hammad_python-0.0.25.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
133
- hammad_python-0.0.25.dist-info/licenses/LICENSE,sha256=h74yFUWjbBaodcWG5wNmm30npjl8obVcxD-1nQfUp2I,1069
134
- hammad_python-0.0.25.dist-info/RECORD,,
132
+ hammad_python-0.0.27.dist-info/METADATA,sha256=WfL-hAEfVrPhAwRn3cBaEdm0EfaVIv3RYfz54OkLv08,6785
133
+ hammad_python-0.0.27.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
134
+ hammad_python-0.0.27.dist-info/licenses/LICENSE,sha256=h74yFUWjbBaodcWG5wNmm30npjl8obVcxD-1nQfUp2I,1069
135
+ hammad_python-0.0.27.dist-info/RECORD,,