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