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.
Files changed (137) hide show
  1. ham/__init__.py +10 -0
  2. {hammad_python-0.0.29.dist-info → hammad_python-0.0.31.dist-info}/METADATA +6 -32
  3. hammad_python-0.0.31.dist-info/RECORD +6 -0
  4. hammad/__init__.py +0 -84
  5. hammad/_internal.py +0 -256
  6. hammad/_main.py +0 -226
  7. hammad/cache/__init__.py +0 -40
  8. hammad/cache/base_cache.py +0 -181
  9. hammad/cache/cache.py +0 -169
  10. hammad/cache/decorators.py +0 -261
  11. hammad/cache/file_cache.py +0 -80
  12. hammad/cache/ttl_cache.py +0 -74
  13. hammad/cli/__init__.py +0 -33
  14. hammad/cli/animations.py +0 -573
  15. hammad/cli/plugins.py +0 -867
  16. hammad/cli/styles/__init__.py +0 -55
  17. hammad/cli/styles/settings.py +0 -139
  18. hammad/cli/styles/types.py +0 -358
  19. hammad/cli/styles/utils.py +0 -634
  20. hammad/data/__init__.py +0 -90
  21. hammad/data/collections/__init__.py +0 -49
  22. hammad/data/collections/collection.py +0 -326
  23. hammad/data/collections/indexes/__init__.py +0 -37
  24. hammad/data/collections/indexes/qdrant/__init__.py +0 -1
  25. hammad/data/collections/indexes/qdrant/index.py +0 -723
  26. hammad/data/collections/indexes/qdrant/settings.py +0 -94
  27. hammad/data/collections/indexes/qdrant/utils.py +0 -210
  28. hammad/data/collections/indexes/tantivy/__init__.py +0 -1
  29. hammad/data/collections/indexes/tantivy/index.py +0 -426
  30. hammad/data/collections/indexes/tantivy/settings.py +0 -40
  31. hammad/data/collections/indexes/tantivy/utils.py +0 -176
  32. hammad/data/configurations/__init__.py +0 -35
  33. hammad/data/configurations/configuration.py +0 -564
  34. hammad/data/models/__init__.py +0 -50
  35. hammad/data/models/extensions/__init__.py +0 -4
  36. hammad/data/models/extensions/pydantic/__init__.py +0 -42
  37. hammad/data/models/extensions/pydantic/converters.py +0 -759
  38. hammad/data/models/fields.py +0 -546
  39. hammad/data/models/model.py +0 -1078
  40. hammad/data/models/utils.py +0 -280
  41. hammad/data/sql/__init__.py +0 -24
  42. hammad/data/sql/database.py +0 -576
  43. hammad/data/sql/types.py +0 -127
  44. hammad/data/types/__init__.py +0 -75
  45. hammad/data/types/file.py +0 -431
  46. hammad/data/types/multimodal/__init__.py +0 -36
  47. hammad/data/types/multimodal/audio.py +0 -200
  48. hammad/data/types/multimodal/image.py +0 -182
  49. hammad/data/types/text.py +0 -1308
  50. hammad/formatting/__init__.py +0 -33
  51. hammad/formatting/json/__init__.py +0 -27
  52. hammad/formatting/json/converters.py +0 -158
  53. hammad/formatting/text/__init__.py +0 -63
  54. hammad/formatting/text/converters.py +0 -723
  55. hammad/formatting/text/markdown.py +0 -131
  56. hammad/formatting/yaml/__init__.py +0 -26
  57. hammad/formatting/yaml/converters.py +0 -5
  58. hammad/genai/__init__.py +0 -217
  59. hammad/genai/a2a/__init__.py +0 -32
  60. hammad/genai/a2a/workers.py +0 -552
  61. hammad/genai/agents/__init__.py +0 -59
  62. hammad/genai/agents/agent.py +0 -1973
  63. hammad/genai/agents/run.py +0 -1024
  64. hammad/genai/agents/types/__init__.py +0 -42
  65. hammad/genai/agents/types/agent_context.py +0 -13
  66. hammad/genai/agents/types/agent_event.py +0 -128
  67. hammad/genai/agents/types/agent_hooks.py +0 -220
  68. hammad/genai/agents/types/agent_messages.py +0 -31
  69. hammad/genai/agents/types/agent_response.py +0 -125
  70. hammad/genai/agents/types/agent_stream.py +0 -327
  71. hammad/genai/graphs/__init__.py +0 -125
  72. hammad/genai/graphs/_utils.py +0 -190
  73. hammad/genai/graphs/base.py +0 -1828
  74. hammad/genai/graphs/plugins.py +0 -316
  75. hammad/genai/graphs/types.py +0 -638
  76. hammad/genai/models/__init__.py +0 -1
  77. hammad/genai/models/embeddings/__init__.py +0 -43
  78. hammad/genai/models/embeddings/model.py +0 -226
  79. hammad/genai/models/embeddings/run.py +0 -163
  80. hammad/genai/models/embeddings/types/__init__.py +0 -37
  81. hammad/genai/models/embeddings/types/embedding_model_name.py +0 -75
  82. hammad/genai/models/embeddings/types/embedding_model_response.py +0 -76
  83. hammad/genai/models/embeddings/types/embedding_model_run_params.py +0 -66
  84. hammad/genai/models/embeddings/types/embedding_model_settings.py +0 -47
  85. hammad/genai/models/language/__init__.py +0 -57
  86. hammad/genai/models/language/model.py +0 -1098
  87. hammad/genai/models/language/run.py +0 -878
  88. hammad/genai/models/language/types/__init__.py +0 -40
  89. hammad/genai/models/language/types/language_model_instructor_mode.py +0 -47
  90. hammad/genai/models/language/types/language_model_messages.py +0 -28
  91. hammad/genai/models/language/types/language_model_name.py +0 -239
  92. hammad/genai/models/language/types/language_model_request.py +0 -127
  93. hammad/genai/models/language/types/language_model_response.py +0 -217
  94. hammad/genai/models/language/types/language_model_response_chunk.py +0 -56
  95. hammad/genai/models/language/types/language_model_settings.py +0 -89
  96. hammad/genai/models/language/types/language_model_stream.py +0 -600
  97. hammad/genai/models/language/utils/__init__.py +0 -28
  98. hammad/genai/models/language/utils/requests.py +0 -421
  99. hammad/genai/models/language/utils/structured_outputs.py +0 -135
  100. hammad/genai/models/model_provider.py +0 -4
  101. hammad/genai/models/multimodal.py +0 -47
  102. hammad/genai/models/reranking.py +0 -26
  103. hammad/genai/types/__init__.py +0 -1
  104. hammad/genai/types/base.py +0 -215
  105. hammad/genai/types/history.py +0 -290
  106. hammad/genai/types/tools.py +0 -507
  107. hammad/logging/__init__.py +0 -35
  108. hammad/logging/decorators.py +0 -834
  109. hammad/logging/logger.py +0 -1018
  110. hammad/mcp/__init__.py +0 -53
  111. hammad/mcp/client/__init__.py +0 -35
  112. hammad/mcp/client/client.py +0 -624
  113. hammad/mcp/client/client_service.py +0 -400
  114. hammad/mcp/client/settings.py +0 -178
  115. hammad/mcp/servers/__init__.py +0 -26
  116. hammad/mcp/servers/launcher.py +0 -1161
  117. hammad/runtime/__init__.py +0 -32
  118. hammad/runtime/decorators.py +0 -142
  119. hammad/runtime/run.py +0 -299
  120. hammad/service/__init__.py +0 -49
  121. hammad/service/create.py +0 -527
  122. hammad/service/decorators.py +0 -283
  123. hammad/types.py +0 -288
  124. hammad/typing/__init__.py +0 -435
  125. hammad/web/__init__.py +0 -43
  126. hammad/web/http/__init__.py +0 -1
  127. hammad/web/http/client.py +0 -944
  128. hammad/web/models.py +0 -275
  129. hammad/web/openapi/__init__.py +0 -1
  130. hammad/web/openapi/client.py +0 -740
  131. hammad/web/search/__init__.py +0 -1
  132. hammad/web/search/client.py +0 -1023
  133. hammad/web/utils.py +0 -472
  134. hammad_python-0.0.29.dist-info/RECORD +0 -135
  135. {hammad → ham}/py.typed +0 -0
  136. {hammad_python-0.0.29.dist-info → hammad_python-0.0.31.dist-info}/WHEEL +0 -0
  137. {hammad_python-0.0.29.dist-info → hammad_python-0.0.31.dist-info}/licenses/LICENSE +0 -0
@@ -1,1098 +0,0 @@
1
- """hammad.genai.language_models.language_model"""
2
-
3
- from typing import (
4
- Any,
5
- Callable,
6
- List,
7
- TypeVar,
8
- Generic,
9
- Union,
10
- Optional,
11
- Type,
12
- overload,
13
- Dict,
14
- TYPE_CHECKING,
15
- )
16
- import functools
17
- import inspect
18
- import asyncio
19
- from typing_extensions import Literal
20
-
21
- if TYPE_CHECKING:
22
- from httpx import Timeout
23
-
24
- from ....logging.logger import _get_internal_logger
25
- from ..model_provider import litellm, instructor
26
-
27
- from ...types.base import BaseGenAIModel
28
- from .types.language_model_instructor_mode import LanguageModelInstructorMode
29
- from .types.language_model_name import LanguageModelName
30
- from .types.language_model_messages import LanguageModelMessages
31
- from .types.language_model_response import LanguageModelResponse
32
- from .types.language_model_settings import LanguageModelSettings
33
- from .types.language_model_stream import LanguageModelStream
34
-
35
- from .utils import (
36
- parse_messages_input,
37
- handle_completion_request_params,
38
- handle_completion_response,
39
- handle_structured_output_request_params,
40
- prepare_response_model,
41
- handle_structured_output_response,
42
- format_tool_calls,
43
- LanguageModelRequestBuilder,
44
- )
45
-
46
- __all__ = [
47
- "LanguageModel",
48
- "LanguageModelError",
49
- "create_language_model",
50
- ]
51
-
52
- T = TypeVar("T")
53
-
54
-
55
- logger = _get_internal_logger(__name__)
56
-
57
-
58
- class LanguageModelError(Exception):
59
- """Error raised when an error occurs during a language model operation."""
60
-
61
- def __init__(self, message: str, *args: Any, **kwargs: Any):
62
- super().__init__(message, *args, **kwargs)
63
- self.message = message
64
- self.args = args
65
- self.kwargs = kwargs
66
-
67
-
68
- class LanguageModel(BaseGenAIModel, Generic[T]):
69
- """
70
- A Generative AI model that can be used to generate text, chat completions,
71
- structured outputs, call tools and more.
72
- """
73
-
74
- model: LanguageModelName | str = "openai/gpt-4o-mini"
75
- """The model to use for requests."""
76
-
77
- type: Type[T] = str
78
- """The type of the output of the language model."""
79
-
80
- instructions: Optional[str] = None
81
- """Instructions for the language model."""
82
-
83
- base_url: Optional[str] = None
84
- api_key: Optional[str] = None
85
- api_version: Optional[str] = None
86
- organization: Optional[str] = None
87
- deployment_id: Optional[str] = None
88
- model_list: Optional[List[Any]] = None
89
- extra_headers: Optional[Dict[str, str]] = None
90
-
91
- settings: LanguageModelSettings = LanguageModelSettings()
92
- """Settings for the language model."""
93
-
94
- instructor_mode: LanguageModelInstructorMode = "tool_call"
95
- """Default instructor mode for structured outputs."""
96
-
97
- def __init__(
98
- self,
99
- model: LanguageModelName = "openai/gpt-4o-mini",
100
- base_url: Optional[str] = None,
101
- api_key: Optional[str] = None,
102
- instructor_mode: LanguageModelInstructorMode = "tool_call",
103
- verbose: bool = False,
104
- debug: bool = False,
105
- **kwargs: Any,
106
- ):
107
- """Initialize the language model.
108
-
109
- Args:
110
- model: The model to use for requests
111
- base_url: Custom base URL for the API
112
- api_key: API key for authentication
113
- instructor_mode: Default instructor mode for structured outputs
114
- verbose: If True, set logger to INFO level for detailed output
115
- debug: If True, set logger to DEBUG level for maximum verbosity
116
- **kwargs: Additional arguments passed to BaseGenAIModel
117
- """
118
- # Initialize BaseGenAIModel via super()
119
- super().__init__(model=model, base_url=base_url, api_key=api_key, **kwargs)
120
-
121
- # Initialize LanguageModel-specific attributes
122
- self._instructor_client = None
123
- self.verbose = verbose
124
- self.debug = debug
125
-
126
- # Set logger level based on verbose/debug flags
127
- if debug:
128
- logger.setLevel("DEBUG")
129
- elif verbose:
130
- logger.setLevel("INFO")
131
-
132
- logger.info(f"Initialized LanguageModel w/ model: {self.model}")
133
- logger.debug(f"LanguageModel settings: {self.settings}")
134
-
135
- def _get_instructor_client(
136
- self, mode: Optional[LanguageModelInstructorMode] = None
137
- ):
138
- """Get or create an instructor client with the specified mode."""
139
- effective_mode = mode or self.instructor_mode
140
-
141
- # Create a new client if mode changed or client doesn't exist
142
- if (
143
- self._instructor_client is None
144
- or getattr(self._instructor_client, "_mode", None) != effective_mode
145
- ):
146
- logger.debug(
147
- f"Creating new instructor client for mode: {effective_mode} from old mode: {getattr(self._instructor_client, '_mode', None)}"
148
- )
149
-
150
- self._instructor_client = instructor.from_litellm(
151
- completion=litellm.completion, mode=instructor.Mode(effective_mode)
152
- )
153
- self._instructor_client._mode = effective_mode
154
-
155
- return self._instructor_client
156
-
157
- def _get_async_instructor_client(
158
- self, mode: Optional[LanguageModelInstructorMode] = None
159
- ):
160
- """Get or create an async instructor client with the specified mode."""
161
- effective_mode = mode or self.instructor_mode
162
-
163
- return instructor.from_litellm(
164
- completion=litellm.acompletion, mode=instructor.Mode(effective_mode)
165
- )
166
-
167
- # Overloaded run methods for different return types
168
-
169
- @overload
170
- def run(
171
- self,
172
- messages: LanguageModelMessages,
173
- instructions: Optional[str] = None,
174
- *,
175
- stream: Literal[False] = False,
176
- model: Optional[LanguageModelName | str] = None,
177
- base_url: Optional[str] = None,
178
- api_key: Optional[str] = None,
179
- mock_response: Optional[str] = None,
180
- **kwargs: Any,
181
- ) -> LanguageModelResponse[str]: ...
182
-
183
- @overload
184
- def run(
185
- self,
186
- messages: LanguageModelMessages,
187
- instructions: Optional[str] = None,
188
- *,
189
- stream: Literal[False] = False,
190
- model: Optional[LanguageModelName | str] = None,
191
- base_url: Optional[str] = None,
192
- api_key: Optional[str] = None,
193
- temperature: Optional[float] = None,
194
- max_tokens: Optional[int] = None,
195
- top_p: Optional[float] = None,
196
- tools: Optional[List[Any]] = None,
197
- tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
198
- timeout: Optional[Union[float, str, "Timeout"]] = None,
199
- presence_penalty: Optional[float] = None,
200
- frequency_penalty: Optional[float] = None,
201
- seed: Optional[int] = None,
202
- user: Optional[str] = None,
203
- mock_response: Optional[str] = None,
204
- **kwargs: Any,
205
- ) -> LanguageModelResponse[str]: ...
206
-
207
- @overload
208
- def run(
209
- self,
210
- messages: LanguageModelMessages,
211
- instructions: Optional[str] = None,
212
- *,
213
- stream: Literal[True],
214
- model: Optional[LanguageModelName | str] = None,
215
- base_url: Optional[str] = None,
216
- api_key: Optional[str] = None,
217
- mock_response: Optional[str] = None,
218
- **kwargs: Any,
219
- ) -> LanguageModelStream[str]: ...
220
-
221
- @overload
222
- def run(
223
- self,
224
- messages: LanguageModelMessages,
225
- instructions: Optional[str] = None,
226
- *,
227
- stream: Literal[True],
228
- model: Optional[LanguageModelName | str] = None,
229
- base_url: Optional[str] = None,
230
- api_key: Optional[str] = None,
231
- temperature: Optional[float] = None,
232
- max_tokens: Optional[int] = None,
233
- top_p: Optional[float] = None,
234
- tools: Optional[List[Any]] = None,
235
- tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
236
- timeout: Optional[Union[float, str, "Timeout"]] = None,
237
- presence_penalty: Optional[float] = None,
238
- frequency_penalty: Optional[float] = None,
239
- seed: Optional[int] = None,
240
- user: Optional[str] = None,
241
- mock_response: Optional[str] = None,
242
- **kwargs: Any,
243
- ) -> LanguageModelStream[str]: ...
244
-
245
- @overload
246
- def run(
247
- self,
248
- messages: LanguageModelMessages,
249
- instructions: Optional[str] = None,
250
- *,
251
- type: Type[T],
252
- stream: Literal[False] = False,
253
- model: Optional[LanguageModelName | str] = None,
254
- base_url: Optional[str] = None,
255
- api_key: Optional[str] = None,
256
- mock_response: Optional[str] = None,
257
- **kwargs: Any,
258
- ) -> LanguageModelResponse[T]: ...
259
-
260
- @overload
261
- def run(
262
- self,
263
- messages: LanguageModelMessages,
264
- instructions: Optional[str] = None,
265
- *,
266
- type: Type[T],
267
- stream: Literal[False] = False,
268
- model: Optional[LanguageModelName | str] = None,
269
- base_url: Optional[str] = None,
270
- api_key: Optional[str] = None,
271
- temperature: Optional[float] = None,
272
- max_tokens: Optional[int] = None,
273
- top_p: Optional[float] = None,
274
- instructor_mode: Optional[LanguageModelInstructorMode] = None,
275
- response_field_name: Optional[str] = None,
276
- response_field_instruction: Optional[str] = None,
277
- response_model_name: Optional[str] = None,
278
- max_retries: Optional[int] = None,
279
- strict: Optional[bool] = None,
280
- validation_context: Optional[Dict[str, Any]] = None,
281
- context: Optional[Dict[str, Any]] = None,
282
- completion_kwargs_hooks: Optional[List[Callable[..., None]]] = None,
283
- completion_response_hooks: Optional[List[Callable[..., None]]] = None,
284
- completion_error_hooks: Optional[List[Callable[..., None]]] = None,
285
- completion_last_attempt_hooks: Optional[List[Callable[..., None]]] = None,
286
- parse_error_hooks: Optional[List[Callable[..., None]]] = None,
287
- timeout: Optional[Union[float, str, "Timeout"]] = None,
288
- presence_penalty: Optional[float] = None,
289
- frequency_penalty: Optional[float] = None,
290
- seed: Optional[int] = None,
291
- user: Optional[str] = None,
292
- mock_response: Optional[str] = None,
293
- **kwargs: Any,
294
- ) -> LanguageModelResponse[T]: ...
295
-
296
- @overload
297
- def run(
298
- self,
299
- messages: LanguageModelMessages,
300
- instructions: Optional[str] = None,
301
- *,
302
- type: Type[T],
303
- stream: Literal[True],
304
- model: Optional[LanguageModelName | str] = None,
305
- base_url: Optional[str] = None,
306
- api_key: Optional[str] = None,
307
- mock_response: Optional[str] = None,
308
- **kwargs: Any,
309
- ) -> LanguageModelStream[T]: ...
310
-
311
- @overload
312
- def run(
313
- self,
314
- messages: LanguageModelMessages,
315
- instructions: Optional[str] = None,
316
- *,
317
- type: Type[T],
318
- stream: Literal[True],
319
- model: Optional[LanguageModelName | str] = None,
320
- base_url: Optional[str] = None,
321
- api_key: Optional[str] = None,
322
- temperature: Optional[float] = None,
323
- max_tokens: Optional[int] = None,
324
- top_p: Optional[float] = None,
325
- instructor_mode: Optional[LanguageModelInstructorMode] = None,
326
- response_field_name: Optional[str] = None,
327
- response_field_instruction: Optional[str] = None,
328
- response_model_name: Optional[str] = None,
329
- max_retries: Optional[int] = None,
330
- strict: Optional[bool] = None,
331
- validation_context: Optional[Dict[str, Any]] = None,
332
- context: Optional[Dict[str, Any]] = None,
333
- completion_kwargs_hooks: Optional[List[Callable[..., None]]] = None,
334
- completion_response_hooks: Optional[List[Callable[..., None]]] = None,
335
- completion_error_hooks: Optional[List[Callable[..., None]]] = None,
336
- completion_last_attempt_hooks: Optional[List[Callable[..., None]]] = None,
337
- parse_error_hooks: Optional[List[Callable[..., None]]] = None,
338
- timeout: Optional[Union[float, str, "Timeout"]] = None,
339
- presence_penalty: Optional[float] = None,
340
- frequency_penalty: Optional[float] = None,
341
- seed: Optional[int] = None,
342
- user: Optional[str] = None,
343
- mock_response: Optional[str] = None,
344
- **kwargs: Any,
345
- ) -> LanguageModelStream[T]: ...
346
-
347
- def run(
348
- self,
349
- messages: LanguageModelMessages,
350
- instructions: Optional[str] = None,
351
- mock_response: Optional[str] = None,
352
- verbose: Optional[bool] = None,
353
- debug: Optional[bool] = None,
354
- **kwargs: Any,
355
- ) -> Union[LanguageModelResponse[Any], LanguageModelStream[Any]]:
356
- """Run a language model request.
357
-
358
- Args:
359
- messages: The input messages/content for the request
360
- instructions: Optional system instructions to prepend
361
- mock_response: Mock response string for testing (saves API costs)
362
- verbose: If True, set logger to INFO level for this request
363
- debug: If True, set logger to DEBUG level for this request
364
- **kwargs: Additional request parameters
365
-
366
- Returns:
367
- LanguageModelResponse or LanguageModelStream depending on parameters
368
- """
369
- # Set logger level for this request if specified
370
- original_level = logger.level
371
- if debug or (debug is None and self.debug):
372
- logger.setLevel("DEBUG")
373
- elif verbose or (verbose is None and self.verbose):
374
- logger.setLevel("INFO")
375
-
376
- logger.info(f"Running LanguageModel request with model: {self.model}")
377
- logger.debug(f"LanguageModel request kwargs: {kwargs}")
378
-
379
- try:
380
- # Extract model, base_url, api_key, and mock_response from kwargs, using instance defaults
381
- model = kwargs.pop("model", None) or self.model
382
- base_url = kwargs.pop("base_url", None) or self.base_url
383
- api_key = kwargs.pop("api_key", None) or self.api_key
384
- mock_response_param = kwargs.pop("mock_response", None) or mock_response
385
-
386
- # Add base_url, api_key, and mock_response to kwargs if they are set
387
- if base_url is not None:
388
- kwargs["base_url"] = base_url
389
- if api_key is not None:
390
- kwargs["api_key"] = api_key
391
- if mock_response_param is not None:
392
- kwargs["mock_response"] = mock_response_param
393
-
394
- # Create the request
395
- request = LanguageModelRequestBuilder(
396
- messages=messages, instructions=instructions, model=model, **kwargs
397
- )
398
-
399
- # Parse messages
400
- parsed_messages = parse_messages_input(
401
- request.messages, request.instructions
402
- )
403
- if request.is_structured_output():
404
- parsed_messages = format_tool_calls(parsed_messages)
405
-
406
- # Handle different request types
407
- if request.is_structured_output():
408
- return self._handle_structured_output_request(request, parsed_messages)
409
- else:
410
- return self._handle_completion_request(request, parsed_messages)
411
-
412
- except Exception as e:
413
- raise LanguageModelError(f"Error in language model request: {e}") from e
414
- finally:
415
- # Restore original logger level
416
- if debug is not None or verbose is not None:
417
- logger.setLevel(original_level)
418
-
419
- # Overloaded async_run methods for different return types
420
-
421
- @overload
422
- async def async_run(
423
- self,
424
- messages: LanguageModelMessages,
425
- instructions: Optional[str] = None,
426
- *,
427
- stream: Literal[False] = False,
428
- model: Optional[LanguageModelName | str] = None,
429
- base_url: Optional[str] = None,
430
- api_key: Optional[str] = None,
431
- mock_response: Optional[str] = None,
432
- **kwargs: Any,
433
- ) -> LanguageModelResponse[str]: ...
434
-
435
- @overload
436
- async def async_run(
437
- self,
438
- messages: LanguageModelMessages,
439
- instructions: Optional[str] = None,
440
- *,
441
- stream: Literal[False] = False,
442
- model: Optional[LanguageModelName | str] = None,
443
- base_url: Optional[str] = None,
444
- api_key: Optional[str] = None,
445
- temperature: Optional[float] = None,
446
- max_tokens: Optional[int] = None,
447
- top_p: Optional[float] = None,
448
- tools: Optional[List[Any]] = None,
449
- tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
450
- timeout: Optional[Union[float, str, "Timeout"]] = None,
451
- presence_penalty: Optional[float] = None,
452
- frequency_penalty: Optional[float] = None,
453
- seed: Optional[int] = None,
454
- user: Optional[str] = None,
455
- mock_response: Optional[str] = None,
456
- **kwargs: Any,
457
- ) -> LanguageModelResponse[str]: ...
458
-
459
- @overload
460
- async def async_run(
461
- self,
462
- messages: LanguageModelMessages,
463
- instructions: Optional[str] = None,
464
- *,
465
- stream: Literal[True],
466
- model: Optional[LanguageModelName | str] = None,
467
- base_url: Optional[str] = None,
468
- api_key: Optional[str] = None,
469
- mock_response: Optional[str] = None,
470
- **kwargs: Any,
471
- ) -> LanguageModelStream[str]: ...
472
-
473
- @overload
474
- async def async_run(
475
- self,
476
- messages: LanguageModelMessages,
477
- instructions: Optional[str] = None,
478
- *,
479
- stream: Literal[True],
480
- model: Optional[LanguageModelName | str] = None,
481
- base_url: Optional[str] = None,
482
- api_key: Optional[str] = None,
483
- temperature: Optional[float] = None,
484
- max_tokens: Optional[int] = None,
485
- top_p: Optional[float] = None,
486
- tools: Optional[List[Any]] = None,
487
- tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
488
- timeout: Optional[Union[float, str, "Timeout"]] = None,
489
- presence_penalty: Optional[float] = None,
490
- frequency_penalty: Optional[float] = None,
491
- seed: Optional[int] = None,
492
- user: Optional[str] = None,
493
- mock_response: Optional[str] = None,
494
- **kwargs: Any,
495
- ) -> LanguageModelStream[str]: ...
496
-
497
- @overload
498
- async def async_run(
499
- self,
500
- messages: LanguageModelMessages,
501
- instructions: Optional[str] = None,
502
- *,
503
- type: Type[T],
504
- stream: Literal[False] = False,
505
- model: Optional[LanguageModelName | str] = None,
506
- base_url: Optional[str] = None,
507
- api_key: Optional[str] = None,
508
- mock_response: Optional[str] = None,
509
- **kwargs: Any,
510
- ) -> LanguageModelResponse[T]: ...
511
-
512
- @overload
513
- async def async_run(
514
- self,
515
- messages: LanguageModelMessages,
516
- instructions: Optional[str] = None,
517
- *,
518
- type: Type[T],
519
- stream: Literal[False] = False,
520
- model: Optional[LanguageModelName | str] = None,
521
- base_url: Optional[str] = None,
522
- api_key: Optional[str] = None,
523
- temperature: Optional[float] = None,
524
- max_tokens: Optional[int] = None,
525
- top_p: Optional[float] = None,
526
- instructor_mode: Optional[LanguageModelInstructorMode] = None,
527
- response_field_name: Optional[str] = None,
528
- response_field_instruction: Optional[str] = None,
529
- response_model_name: Optional[str] = None,
530
- max_retries: Optional[int] = None,
531
- strict: Optional[bool] = None,
532
- validation_context: Optional[Dict[str, Any]] = None,
533
- context: Optional[Dict[str, Any]] = None,
534
- completion_kwargs_hooks: Optional[List[Callable[..., None]]] = None,
535
- completion_response_hooks: Optional[List[Callable[..., None]]] = None,
536
- completion_error_hooks: Optional[List[Callable[..., None]]] = None,
537
- completion_last_attempt_hooks: Optional[List[Callable[..., None]]] = None,
538
- parse_error_hooks: Optional[List[Callable[..., None]]] = None,
539
- timeout: Optional[Union[float, str, "Timeout"]] = None,
540
- presence_penalty: Optional[float] = None,
541
- frequency_penalty: Optional[float] = None,
542
- seed: Optional[int] = None,
543
- user: Optional[str] = None,
544
- mock_response: Optional[str] = None,
545
- **kwargs: Any,
546
- ) -> LanguageModelResponse[T]: ...
547
-
548
- @overload
549
- async def async_run(
550
- self,
551
- messages: LanguageModelMessages,
552
- instructions: Optional[str] = None,
553
- *,
554
- type: Type[T],
555
- stream: Literal[True],
556
- model: Optional[LanguageModelName | str] = None,
557
- base_url: Optional[str] = None,
558
- api_key: Optional[str] = None,
559
- mock_response: Optional[str] = None,
560
- **kwargs: Any,
561
- ) -> LanguageModelStream[T]: ...
562
-
563
- @overload
564
- async def async_run(
565
- self,
566
- messages: LanguageModelMessages,
567
- instructions: Optional[str] = None,
568
- *,
569
- type: Type[T],
570
- stream: Literal[True],
571
- model: Optional[LanguageModelName | str] = None,
572
- base_url: Optional[str] = None,
573
- api_key: Optional[str] = None,
574
- temperature: Optional[float] = None,
575
- max_tokens: Optional[int] = None,
576
- top_p: Optional[float] = None,
577
- instructor_mode: Optional[LanguageModelInstructorMode] = None,
578
- response_field_name: Optional[str] = None,
579
- response_field_instruction: Optional[str] = None,
580
- response_model_name: Optional[str] = None,
581
- max_retries: Optional[int] = None,
582
- strict: Optional[bool] = None,
583
- validation_context: Optional[Dict[str, Any]] = None,
584
- context: Optional[Dict[str, Any]] = None,
585
- completion_kwargs_hooks: Optional[List[Callable[..., None]]] = None,
586
- completion_response_hooks: Optional[List[Callable[..., None]]] = None,
587
- completion_error_hooks: Optional[List[Callable[..., None]]] = None,
588
- completion_last_attempt_hooks: Optional[List[Callable[..., None]]] = None,
589
- parse_error_hooks: Optional[List[Callable[..., None]]] = None,
590
- timeout: Optional[Union[float, str, "Timeout"]] = None,
591
- presence_penalty: Optional[float] = None,
592
- frequency_penalty: Optional[float] = None,
593
- seed: Optional[int] = None,
594
- user: Optional[str] = None,
595
- mock_response: Optional[str] = None,
596
- **kwargs: Any,
597
- ) -> LanguageModelStream[T]: ...
598
-
599
- async def async_run(
600
- self,
601
- messages: LanguageModelMessages,
602
- instructions: Optional[str] = None,
603
- mock_response: Optional[str] = None,
604
- verbose: Optional[bool] = None,
605
- debug: Optional[bool] = None,
606
- **kwargs: Any,
607
- ) -> Union[LanguageModelResponse[Any], LanguageModelStream[Any]]:
608
- """Run an async language model request.
609
-
610
- Args:
611
- messages: The input messages/content for the request
612
- instructions: Optional system instructions to prepend
613
- mock_response: Mock response string for testing (saves API costs)
614
- verbose: If True, set logger to INFO level for this request
615
- debug: If True, set logger to DEBUG level for this request
616
- **kwargs: Additional request parameters
617
-
618
- Returns:
619
- LanguageModelResponse or LanguageModelAsyncStream depending on parameters
620
- """
621
- # Set logger level for this request if specified
622
- original_level = logger.level
623
- if debug or (debug is None and self.debug):
624
- logger.setLevel("DEBUG")
625
- elif verbose or (verbose is None and self.verbose):
626
- logger.setLevel("INFO")
627
-
628
- logger.info(f"Running async LanguageModel request with model: {self.model}")
629
- logger.debug(f"LanguageModel request kwargs: {kwargs}")
630
-
631
- try:
632
- # Extract model, base_url, api_key, and mock_response from kwargs, using instance defaults
633
- model = kwargs.pop("model", None) or self.model
634
- base_url = kwargs.pop("base_url", None) or self.base_url
635
- api_key = kwargs.pop("api_key", None) or self.api_key
636
- mock_response_param = kwargs.pop("mock_response", None) or mock_response
637
-
638
- # Add base_url, api_key, and mock_response to kwargs if they are set
639
- if base_url is not None:
640
- kwargs["base_url"] = base_url
641
- if api_key is not None:
642
- kwargs["api_key"] = api_key
643
- if mock_response_param is not None:
644
- kwargs["mock_response"] = mock_response_param
645
-
646
- # Create the request
647
- request = LanguageModelRequestBuilder(
648
- messages=messages, instructions=instructions, model=model, **kwargs
649
- )
650
-
651
- # Parse messages
652
- parsed_messages = parse_messages_input(
653
- request.messages, request.instructions
654
- )
655
- if request.is_structured_output():
656
- parsed_messages = format_tool_calls(parsed_messages)
657
-
658
- # Handle different request types
659
- if request.is_structured_output():
660
- return await self._handle_async_structured_output_request(
661
- request, parsed_messages
662
- )
663
- else:
664
- return await self._handle_async_completion_request(
665
- request, parsed_messages
666
- )
667
-
668
- except Exception as e:
669
- raise LanguageModelError(
670
- f"Error in async language model request: {e}"
671
- ) from e
672
- finally:
673
- # Restore original logger level
674
- if debug is not None or verbose is not None:
675
- logger.setLevel(original_level)
676
-
677
- def _handle_completion_request(
678
- self, request: LanguageModelRequestBuilder, parsed_messages: List[Any]
679
- ) -> Union[LanguageModelResponse[str], LanguageModelStream[str]]:
680
- """Handle a standard completion request."""
681
- # Get filtered parameters
682
- params = handle_completion_request_params(request.get_completion_settings())
683
- params["messages"] = parsed_messages
684
-
685
- if request.is_streaming():
686
- # Handle streaming - stream parameter is already in params
687
- if "stream_options" not in params and "stream_options" in request.settings:
688
- params["stream_options"] = request.settings["stream_options"]
689
- stream = litellm.completion(**params)
690
- return LanguageModelStream(
691
- model=request.model,
692
- stream=stream,
693
- output_type=str,
694
- )
695
- else:
696
- # Handle non-streaming
697
- response = litellm.completion(**params)
698
- return handle_completion_response(response, request.model)
699
-
700
- async def _handle_async_completion_request(
701
- self, request: LanguageModelRequestBuilder, parsed_messages: List[Any]
702
- ) -> Union[LanguageModelResponse[str], LanguageModelStream[str]]:
703
- """Handle an async standard completion request."""
704
- # Get filtered parameters
705
- params = handle_completion_request_params(request.get_completion_settings())
706
- params["messages"] = parsed_messages
707
-
708
- if request.is_streaming():
709
- # Handle streaming - stream parameter is already in params
710
- if "stream_options" not in params and "stream_options" in request.settings:
711
- params["stream_options"] = request.settings["stream_options"]
712
- stream = await litellm.acompletion(**params)
713
- return LanguageModelStream(
714
- model=request.model,
715
- stream=stream,
716
- output_type=str,
717
- )
718
- else:
719
- # Handle non-streaming
720
- response = await litellm.acompletion(**params)
721
- return handle_completion_response(response, request.model)
722
-
723
- def _handle_structured_output_request(
724
- self, request: LanguageModelRequestBuilder, parsed_messages: List[Any]
725
- ) -> Union[LanguageModelResponse[Any], LanguageModelStream[Any]]:
726
- """Handle a structured output request."""
727
- # Get filtered parameters
728
- params = handle_structured_output_request_params(
729
- request.get_structured_output_settings()
730
- )
731
- params["messages"] = parsed_messages
732
-
733
- # Prepare response model
734
- response_model = prepare_response_model(
735
- request.get_output_type(),
736
- request.get_response_field_name(),
737
- request.get_response_field_instruction(),
738
- request.get_response_model_name(),
739
- )
740
-
741
- # Get instructor client
742
- client = self._get_instructor_client(request.get_instructor_mode())
743
-
744
- if request.is_streaming():
745
- if isinstance(request.get_output_type(), list):
746
- # Handle streaming - stream parameter is already in params
747
- stream = client.chat.completions.create_iterable(
748
- response_model=response_model,
749
- max_retries=request.get_max_retries(),
750
- strict=request.get_strict_mode(),
751
- **params,
752
- )
753
- else:
754
- # Handle streaming - stream parameter is already in params
755
- stream = client.chat.completions.create_partial(
756
- response_model=response_model,
757
- max_retries=request.get_max_retries(),
758
- strict=request.get_strict_mode(),
759
- **params,
760
- )
761
- return LanguageModelStream(
762
- model=request.model,
763
- stream=stream,
764
- output_type=request.get_output_type(),
765
- response_field_name=request.get_response_field_name(),
766
- )
767
- else:
768
- # Handle non-streaming
769
- response, completion = client.chat.completions.create_with_completion(
770
- response_model=response_model,
771
- max_retries=request.get_max_retries(),
772
- strict=request.get_strict_mode(),
773
- **params,
774
- )
775
- return handle_structured_output_response(
776
- response,
777
- completion,
778
- request.model,
779
- request.get_output_type(),
780
- request.get_response_field_name(),
781
- )
782
-
783
- async def _handle_async_structured_output_request(
784
- self, request: LanguageModelRequestBuilder, parsed_messages: List[Any]
785
- ) -> Union[LanguageModelResponse[Any], LanguageModelStream[Any]]:
786
- """Handle an async structured output request."""
787
- # Get filtered parameters
788
- params = handle_structured_output_request_params(
789
- request.get_structured_output_settings()
790
- )
791
- params["messages"] = parsed_messages
792
-
793
- # Prepare response model
794
- response_model = prepare_response_model(
795
- request.get_output_type(),
796
- request.get_response_field_name(),
797
- request.get_response_field_instruction(),
798
- request.get_response_model_name(),
799
- )
800
-
801
- # Get async instructor client
802
- client = self._get_async_instructor_client(request.get_instructor_mode())
803
-
804
- if request.is_streaming():
805
- if isinstance(request.get_output_type(), list):
806
- # Handle streaming - stream parameter is already in params
807
- stream = client.chat.completions.create_iterable(
808
- response_model=response_model,
809
- max_retries=request.get_max_retries(),
810
- strict=request.get_strict_mode(),
811
- **params,
812
- )
813
- else:
814
- # Handle streaming - stream parameter is already in params
815
- stream = client.chat.completions.create_partial(
816
- response_model=response_model,
817
- max_retries=request.get_max_retries(),
818
- strict=request.get_strict_mode(),
819
- **params,
820
- )
821
- return LanguageModelStream(
822
- model=request.model,
823
- stream=stream,
824
- output_type=request.get_output_type(),
825
- response_field_name=request.get_response_field_name(),
826
- )
827
- else:
828
- # Handle non-streaming
829
- response, completion = await client.chat.completions.create_with_completion(
830
- response_model=response_model,
831
- max_retries=request.get_max_retries(),
832
- strict=request.get_strict_mode(),
833
- **params,
834
- )
835
- return handle_structured_output_response(
836
- response,
837
- completion,
838
- request.model,
839
- request.get_output_type(),
840
- request.get_response_field_name(),
841
- )
842
-
843
- def as_tool(
844
- self,
845
- func: Optional[Callable] = None,
846
- *,
847
- name: Optional[str] = None,
848
- description: Optional[str] = None,
849
- instructions: Optional[str] = None,
850
- **kwargs: Any,
851
- ) -> Union[Callable, Any]:
852
- """Convert this language model to a tool that can be used by agents.
853
-
854
- Can be used as a decorator or as a function:
855
-
856
- As a decorator:
857
- @model.as_tool()
858
- def my_function(param1: str, param2: int) -> MyType:
859
- '''Function description'''
860
- pass
861
-
862
- As a function:
863
- tool = model.as_tool(
864
- name="my_tool",
865
- description="Tool description",
866
- instructions="Custom instructions for the LLM"
867
- )
868
-
869
- Args:
870
- func: The function to wrap (when used as decorator)
871
- name: The name of the tool
872
- description: Description of what the tool does
873
- instructions: Custom instructions for the LLM generation
874
- **kwargs: Additional arguments for tool creation
875
-
876
- Returns:
877
- BaseTool or decorated function
878
- """
879
- from ...types.base import BaseTool
880
- from ....formatting.text.converters import convert_docstring_to_text
881
-
882
- def create_tool_wrapper(target_func: Optional[Callable] = None) -> Any:
883
- """Create a tool wrapper for the language model."""
884
-
885
- if target_func is not None:
886
- # Decorator usage - use function signature and docstring
887
- sig = inspect.signature(target_func)
888
- func_name = name or target_func.__name__
889
-
890
- # Get return type from function signature
891
- return_type = (
892
- sig.return_annotation
893
- if sig.return_annotation != inspect.Signature.empty
894
- else str
895
- )
896
-
897
- # Extract docstring as system instructions
898
- system_instructions = instructions or convert_docstring_to_text(
899
- target_func
900
- )
901
-
902
- # Create parameter schema from function signature
903
- parameters_schema = {"type": "object", "properties": {}, "required": []}
904
-
905
- for param_name, param in sig.parameters.items():
906
- param_type = (
907
- param.annotation
908
- if param.annotation != inspect.Parameter.empty
909
- else str
910
- )
911
-
912
- # Convert type to JSON schema type
913
- if param_type == str:
914
- json_type = "string"
915
- elif param_type == int:
916
- json_type = "integer"
917
- elif param_type == float:
918
- json_type = "number"
919
- elif param_type == bool:
920
- json_type = "boolean"
921
- elif param_type == list:
922
- json_type = "array"
923
- elif param_type == dict:
924
- json_type = "object"
925
- else:
926
- json_type = "string" # Default fallback
927
-
928
- parameters_schema["properties"][param_name] = {
929
- "type": json_type,
930
- "description": f"Parameter {param_name} of type {param_type.__name__ if hasattr(param_type, '__name__') else str(param_type)}",
931
- }
932
-
933
- if param.default == inspect.Parameter.empty:
934
- parameters_schema["required"].append(param_name)
935
-
936
- # Create partial function with model settings
937
- partial_func = functools.partial(
938
- self._execute_tool_function,
939
- target_func=target_func,
940
- return_type=return_type,
941
- system_instructions=system_instructions,
942
- )
943
-
944
- # Handle async functions
945
- if asyncio.iscoroutinefunction(target_func):
946
-
947
- async def async_tool_function(**tool_kwargs: Any) -> Any:
948
- return await partial_func(**tool_kwargs)
949
-
950
- return BaseTool(
951
- name=func_name,
952
- description=description
953
- or system_instructions
954
- or f"Tool for {func_name}",
955
- function=async_tool_function,
956
- parameters_json_schema=parameters_schema,
957
- **kwargs,
958
- )
959
- else:
960
-
961
- def sync_tool_function(**tool_kwargs: Any) -> Any:
962
- return partial_func(**tool_kwargs)
963
-
964
- return BaseTool(
965
- name=func_name,
966
- description=description
967
- or system_instructions
968
- or f"Tool for {func_name}",
969
- function=sync_tool_function,
970
- parameters_json_schema=parameters_schema,
971
- **kwargs,
972
- )
973
- else:
974
- # Function usage - create generic tool
975
- tool_name = name or f"language_model_{self.model.replace('/', '_')}"
976
- tool_description = (
977
- description or f"Language model tool using {self.model}"
978
- )
979
-
980
- # Create partial function with model settings
981
- partial_func = functools.partial(
982
- self._execute_generic_tool, system_instructions=instructions
983
- )
984
-
985
- def generic_tool_function(
986
- input: str, type: Optional[Type[T]] = None, **tool_kwargs: Any
987
- ) -> Any:
988
- """Generic tool function that runs the language model."""
989
- return partial_func(input=input, output_type=type, **tool_kwargs)
990
-
991
- # Generic parameter schema
992
- parameters_schema = {
993
- "type": "object",
994
- "properties": {
995
- "input": {
996
- "type": "string",
997
- "description": "The input text for the language model",
998
- },
999
- "type": {
1000
- "type": "string",
1001
- "description": "Optional output type specification",
1002
- },
1003
- },
1004
- "required": ["input"],
1005
- }
1006
-
1007
- return BaseTool(
1008
- name=tool_name,
1009
- description=tool_description,
1010
- function=generic_tool_function,
1011
- parameters_json_schema=parameters_schema,
1012
- **kwargs,
1013
- )
1014
-
1015
- if func is None:
1016
- # Called as @model.as_tool() or model.as_tool()
1017
- return create_tool_wrapper
1018
- else:
1019
- # Called as @model.as_tool (without parentheses)
1020
- return create_tool_wrapper(func)
1021
-
1022
- def _execute_tool_function(
1023
- self,
1024
- target_func: Callable,
1025
- return_type: Type,
1026
- system_instructions: str,
1027
- **kwargs: Any,
1028
- ) -> Any:
1029
- """Execute a function-based tool using the language model."""
1030
- # Format the function call parameters
1031
- param_text = ", ".join([f"{k}={v}" for k, v in kwargs.items()])
1032
- input_text = f"Function: {target_func.__name__}({param_text})"
1033
-
1034
- # Use the language model to generate structured output
1035
- if return_type != str:
1036
- response = self.run(
1037
- messages=[{"role": "user", "content": input_text}],
1038
- instructions=system_instructions,
1039
- type=return_type,
1040
- )
1041
- else:
1042
- response = self.run(
1043
- messages=[{"role": "user", "content": input_text}],
1044
- instructions=system_instructions,
1045
- )
1046
-
1047
- return response.output
1048
-
1049
- def _execute_generic_tool(
1050
- self,
1051
- input: str,
1052
- output_type: Optional[Type] = None,
1053
- system_instructions: Optional[str] = None,
1054
- **kwargs: Any,
1055
- ) -> Any:
1056
- """Execute a generic tool using the language model."""
1057
- if output_type and output_type != str:
1058
- response = self.run(
1059
- messages=[{"role": "user", "content": input}],
1060
- instructions=system_instructions,
1061
- type=output_type,
1062
- **kwargs,
1063
- )
1064
- else:
1065
- response = self.run(
1066
- messages=[{"role": "user", "content": input}],
1067
- instructions=system_instructions,
1068
- **kwargs,
1069
- )
1070
-
1071
- return response.output
1072
-
1073
-
1074
- def create_language_model(
1075
- model: str | LanguageModelName = "openai/gpt-4o-mini",
1076
- base_url: Optional[str] = None,
1077
- api_key: Optional[str] = None,
1078
- api_version: Optional[str] = None,
1079
- organization: Optional[str] = None,
1080
- deployment_id: Optional[str] = None,
1081
- model_list: Optional[List[Any]] = None,
1082
- extra_headers: Optional[Dict[str, str]] = None,
1083
- verbose: bool = False,
1084
- debug: bool = False,
1085
- ) -> LanguageModel:
1086
- """Create a language model instance."""
1087
- return LanguageModel(
1088
- model=model,
1089
- base_url=base_url,
1090
- api_key=api_key,
1091
- api_version=api_version,
1092
- organization=organization,
1093
- deployment_id=deployment_id,
1094
- model_list=model_list,
1095
- extra_headers=extra_headers,
1096
- verbose=verbose,
1097
- debug=debug,
1098
- )