latitude-sdk 0.1.0b7__tar.gz → 0.1.0b9__tar.gz
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.
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/PKG-INFO +2 -2
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/pyproject.toml +2 -2
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/src/latitude_sdk/sdk/evaluations.py +4 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/src/latitude_sdk/sdk/latitude.py +1 -5
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/src/latitude_sdk/sdk/logs.py +12 -13
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/src/latitude_sdk/sdk/prompts.py +112 -44
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/src/latitude_sdk/sdk/types.py +35 -3
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/src/latitude_sdk/util/utils.py +1 -0
- latitude_sdk-0.1.0b9/tests/prompts/chat_test.py +559 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/tests/prompts/run_test.py +289 -2
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/tests/utils/fixtures.py +340 -18
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/tests/utils/utils.py +20 -11
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/uv.lock +26 -5
- latitude_sdk-0.1.0b7/tests/prompts/chat_test.py +0 -294
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/.gitignore +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/.python-version +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/README.md +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/scripts/format.py +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/scripts/lint.py +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/scripts/test.py +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/src/latitude_sdk/__init__.py +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/src/latitude_sdk/client/__init__.py +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/src/latitude_sdk/client/client.py +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/src/latitude_sdk/client/payloads.py +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/src/latitude_sdk/client/router.py +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/src/latitude_sdk/env/__init__.py +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/src/latitude_sdk/env/env.py +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/src/latitude_sdk/py.typed +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/src/latitude_sdk/sdk/__init__.py +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/src/latitude_sdk/sdk/errors.py +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/src/latitude_sdk/util/__init__.py +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/tests/__init__.py +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/tests/evaluations/__init__.py +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/tests/evaluations/create_result_test.py +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/tests/evaluations/trigger_test.py +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/tests/logs/__init__.py +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/tests/logs/create_test.py +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/tests/prompts/__init__.py +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/tests/prompts/get_or_create_test.py +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/tests/prompts/get_test.py +0 -0
- {latitude_sdk-0.1.0b7 → latitude_sdk-0.1.0b9}/tests/utils/__init__.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: latitude-sdk
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.0b9
|
4
4
|
Summary: Latitude SDK for Python
|
5
5
|
Project-URL: repository, https://github.com/latitude-dev/latitude-llm/tree/main/packages/sdks/python
|
6
6
|
Project-URL: homepage, https://github.com/latitude-dev/latitude-llm/tree/main/packages/sdks/python#readme
|
@@ -11,7 +11,7 @@ License-Expression: LGPL-3.0
|
|
11
11
|
Requires-Python: <3.13,>=3.9
|
12
12
|
Requires-Dist: httpx-sse>=0.4.0
|
13
13
|
Requires-Dist: httpx>=0.28.1
|
14
|
-
Requires-Dist: latitude-telemetry>=0.1.
|
14
|
+
Requires-Dist: latitude-telemetry>=0.1.0b6
|
15
15
|
Requires-Dist: pydantic>=2.10.3
|
16
16
|
Requires-Dist: typing-extensions>=4.12.2
|
17
17
|
Description-Content-Type: text/markdown
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "latitude-sdk"
|
3
|
-
version = "0.1.0-beta.
|
3
|
+
version = "0.1.0-beta.9"
|
4
4
|
description = "Latitude SDK for Python"
|
5
5
|
authors = [{ name = "Latitude Data SL", email = "hello@latitude.so" }]
|
6
6
|
maintainers = [{ name = "Latitude Data SL", email = "hello@latitude.so" }]
|
@@ -15,7 +15,7 @@ dependencies = [
|
|
15
15
|
"httpx-sse>=0.4.0",
|
16
16
|
"pydantic>=2.10.3",
|
17
17
|
"typing-extensions>=4.12.2",
|
18
|
-
"latitude-telemetry>=0.1.
|
18
|
+
"latitude-telemetry>=0.1.0b6",
|
19
19
|
]
|
20
20
|
|
21
21
|
[dependency-groups]
|
@@ -41,6 +41,8 @@ class Evaluations:
|
|
41
41
|
self._client = client
|
42
42
|
|
43
43
|
async def trigger(self, uuid: str, options: TriggerEvaluationOptions) -> TriggerEvaluationResult:
|
44
|
+
options = TriggerEvaluationOptions(**{**dict(self._options), **dict(options)})
|
45
|
+
|
44
46
|
async with self._client.request(
|
45
47
|
handler=RequestHandler.TriggerEvaluation,
|
46
48
|
params=TriggerEvaluationRequestParams(
|
@@ -55,6 +57,8 @@ class Evaluations:
|
|
55
57
|
async def create_result(
|
56
58
|
self, uuid: str, evaluation_uuid: str, options: CreateEvaluationResultOptions
|
57
59
|
) -> CreateEvaluationResultResult:
|
60
|
+
options = CreateEvaluationResultOptions(**{**dict(self._options), **dict(options)})
|
61
|
+
|
58
62
|
async with self._client.request(
|
59
63
|
handler=RequestHandler.CreateEvaluationResult,
|
60
64
|
params=CreateEvaluationResultRequestParams(
|
@@ -1,6 +1,5 @@
|
|
1
1
|
from typing import Optional
|
2
2
|
|
3
|
-
from latitude_telemetry import InternalOptions as TelemetryInternalOptions
|
4
3
|
from latitude_telemetry import Telemetry, TelemetryOptions
|
5
4
|
|
6
5
|
from latitude_sdk.client import Client, ClientOptions, RouterOptions
|
@@ -40,7 +39,7 @@ DEFAULT_INTERNAL_OPTIONS = InternalOptions(
|
|
40
39
|
|
41
40
|
|
42
41
|
DEFAULT_LATITUDE_OPTIONS = LatitudeOptions(
|
43
|
-
telemetry=None, #
|
42
|
+
telemetry=None, # NOTE: Telemetry is opt-in
|
44
43
|
internal=DEFAULT_INTERNAL_OPTIONS,
|
45
44
|
)
|
46
45
|
|
@@ -79,9 +78,6 @@ class Latitude:
|
|
79
78
|
)
|
80
79
|
|
81
80
|
if self._options.telemetry:
|
82
|
-
self._options.telemetry.internal = TelemetryInternalOptions(
|
83
|
-
**{**dict(self._options.internal), **dict(self._options.telemetry.internal or {})}
|
84
|
-
)
|
85
81
|
self.telemetry = Telemetry(api_key, self._options.telemetry)
|
86
82
|
|
87
83
|
self.prompts = Prompts(self._client, self._options)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import
|
1
|
+
from typing import Any, Dict, Optional, Sequence, Union
|
2
2
|
|
3
3
|
from latitude_sdk.client import Client, CreateLogRequestBody, CreateLogRequestParams, RequestHandler
|
4
4
|
from latitude_sdk.sdk.errors import ApiError, ApiErrorCodes
|
@@ -6,6 +6,7 @@ from latitude_sdk.sdk.types import (
|
|
6
6
|
Log,
|
7
7
|
Message,
|
8
8
|
SdkOptions,
|
9
|
+
_Message,
|
9
10
|
)
|
10
11
|
from latitude_sdk.util import Model
|
11
12
|
|
@@ -31,9 +32,8 @@ class Logs:
|
|
31
32
|
self._options = options
|
32
33
|
self._client = client
|
33
34
|
|
34
|
-
def
|
35
|
-
|
36
|
-
if not project_id:
|
35
|
+
def _ensure_log_options(self, options: LogOptions):
|
36
|
+
if not options.project_id:
|
37
37
|
raise ApiError(
|
38
38
|
status=404,
|
39
39
|
code=ApiErrorCodes.NotFoundError,
|
@@ -41,16 +41,15 @@ class Logs:
|
|
41
41
|
response="Project ID is required",
|
42
42
|
)
|
43
43
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
log_options = self._ensure_options(options)
|
50
|
-
options = CreateLogOptions(**{**dict(options), **dict(log_options)})
|
51
|
-
|
44
|
+
async def create(
|
45
|
+
self, path: str, messages: Sequence[Union[Message, Dict[str, Any]]], options: CreateLogOptions
|
46
|
+
) -> CreateLogResult:
|
47
|
+
options = CreateLogOptions(**{**dict(self._options), **dict(options)})
|
48
|
+
self._ensure_log_options(options)
|
52
49
|
assert options.project_id is not None
|
53
50
|
|
51
|
+
messages = [_Message.validate_python(message) for message in messages]
|
52
|
+
|
54
53
|
async with self._client.request(
|
55
54
|
handler=RequestHandler.CreateLog,
|
56
55
|
params=CreateLogRequestParams(
|
@@ -59,7 +58,7 @@ class Logs:
|
|
59
58
|
),
|
60
59
|
body=CreateLogRequestBody(
|
61
60
|
path=path,
|
62
|
-
messages=
|
61
|
+
messages=messages,
|
63
62
|
response=options.response,
|
64
63
|
),
|
65
64
|
) as response:
|
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
import asyncio
|
2
|
+
from typing import Any, AsyncGenerator, Dict, List, Optional, Sequence, Union
|
2
3
|
|
3
4
|
from latitude_sdk.client import (
|
4
5
|
ChatPromptRequestBody,
|
@@ -21,14 +22,25 @@ from latitude_sdk.sdk.types import (
|
|
21
22
|
ChainEventStepCompleted,
|
22
23
|
FinishedEvent,
|
23
24
|
Message,
|
25
|
+
OnToolCall,
|
26
|
+
OnToolCallDetails,
|
24
27
|
Prompt,
|
25
28
|
SdkOptions,
|
26
29
|
StreamCallbacks,
|
27
30
|
StreamEvents,
|
31
|
+
StreamTypes,
|
32
|
+
ToolMessage,
|
33
|
+
ToolResult,
|
34
|
+
ToolResultContent,
|
35
|
+
_Message,
|
28
36
|
)
|
29
37
|
from latitude_sdk.util import Model
|
30
38
|
|
31
39
|
|
40
|
+
class OnToolCallPaused(Exception):
|
41
|
+
pass
|
42
|
+
|
43
|
+
|
32
44
|
class PromptOptions(Model):
|
33
45
|
project_id: Optional[int] = None
|
34
46
|
version_uuid: Optional[str] = None
|
@@ -53,6 +65,7 @@ class GetOrCreatePromptResult(Prompt, Model):
|
|
53
65
|
class RunPromptOptions(StreamCallbacks, PromptOptions, Model):
|
54
66
|
custom_identifier: Optional[str] = None
|
55
67
|
parameters: Optional[Dict[str, Any]] = None
|
68
|
+
tools: Optional[Dict[str, OnToolCall]] = None
|
56
69
|
stream: Optional[bool] = None
|
57
70
|
|
58
71
|
|
@@ -61,6 +74,7 @@ class RunPromptResult(FinishedEvent, Model):
|
|
61
74
|
|
62
75
|
|
63
76
|
class ChatPromptOptions(StreamCallbacks, Model):
|
77
|
+
tools: Optional[Dict[str, OnToolCall]] = None
|
64
78
|
stream: Optional[bool] = None
|
65
79
|
|
66
80
|
|
@@ -76,9 +90,8 @@ class Prompts:
|
|
76
90
|
self._options = options
|
77
91
|
self._client = client
|
78
92
|
|
79
|
-
def
|
80
|
-
|
81
|
-
if not project_id:
|
93
|
+
def _ensure_prompt_options(self, options: PromptOptions):
|
94
|
+
if not options.project_id:
|
82
95
|
raise ApiError(
|
83
96
|
status=404,
|
84
97
|
code=ApiErrorCodes.NotFoundError,
|
@@ -86,12 +99,8 @@ class Prompts:
|
|
86
99
|
response="Project ID is required",
|
87
100
|
)
|
88
101
|
|
89
|
-
version_uuid = options.version_uuid or self._options.version_uuid
|
90
|
-
|
91
|
-
return PromptOptions(project_id=project_id, version_uuid=version_uuid)
|
92
|
-
|
93
102
|
async def _handle_stream(
|
94
|
-
self, stream: AsyncGenerator[ClientEvent, Any],
|
103
|
+
self, stream: AsyncGenerator[ClientEvent, Any], on_event: Optional[StreamCallbacks.OnEvent]
|
95
104
|
) -> FinishedEvent:
|
96
105
|
uuid = None
|
97
106
|
conversation: List[Message] = []
|
@@ -145,8 +154,8 @@ class Prompts:
|
|
145
154
|
response=stream_event.data,
|
146
155
|
)
|
147
156
|
|
148
|
-
if
|
149
|
-
|
157
|
+
if on_event:
|
158
|
+
on_event(event)
|
150
159
|
|
151
160
|
if not uuid or not response:
|
152
161
|
raise ApiError(
|
@@ -159,10 +168,65 @@ class Prompts:
|
|
159
168
|
# NOTE: FinishedEvent not in on_event
|
160
169
|
return FinishedEvent(uuid=uuid, conversation=conversation, response=response)
|
161
170
|
|
162
|
-
|
163
|
-
|
164
|
-
|
171
|
+
def _pause_tool_execution(self) -> ToolResult:
|
172
|
+
raise OnToolCallPaused()
|
173
|
+
|
174
|
+
async def _handle_tool_calls(
|
175
|
+
self, result: FinishedEvent, options: Union[RunPromptOptions, ChatPromptOptions]
|
176
|
+
) -> Optional[FinishedEvent]:
|
177
|
+
# Seems Python cannot infer the type
|
178
|
+
assert result.response.type == StreamTypes.Text and result.response.tool_calls is not None
|
165
179
|
|
180
|
+
if not options.tools:
|
181
|
+
raise ApiError(
|
182
|
+
status=400,
|
183
|
+
code=ApiErrorCodes.AIRunError,
|
184
|
+
message="Tools not supplied",
|
185
|
+
response="Tools not supplied",
|
186
|
+
)
|
187
|
+
|
188
|
+
for tool_call in result.response.tool_calls:
|
189
|
+
if tool_call.name not in options.tools:
|
190
|
+
raise ApiError(
|
191
|
+
status=400,
|
192
|
+
code=ApiErrorCodes.AIRunError,
|
193
|
+
message=f"Tool {tool_call.name} not supplied",
|
194
|
+
response=f"Tool {tool_call.name} not supplied",
|
195
|
+
)
|
196
|
+
|
197
|
+
details = OnToolCallDetails(
|
198
|
+
conversation_uuid=result.uuid,
|
199
|
+
messages=result.conversation,
|
200
|
+
pause_execution=self._pause_tool_execution,
|
201
|
+
requested_tool_calls=result.response.tool_calls,
|
202
|
+
)
|
203
|
+
|
204
|
+
tool_results = await asyncio.gather(
|
205
|
+
*[options.tools[tool_call.name](tool_call, details) for tool_call in result.response.tool_calls],
|
206
|
+
return_exceptions=False,
|
207
|
+
)
|
208
|
+
|
209
|
+
tool_messages = [
|
210
|
+
ToolMessage(
|
211
|
+
content=[
|
212
|
+
ToolResultContent(
|
213
|
+
id=tool_result.id,
|
214
|
+
name=tool_result.name,
|
215
|
+
result=tool_result.result,
|
216
|
+
is_error=tool_result.is_error,
|
217
|
+
)
|
218
|
+
]
|
219
|
+
)
|
220
|
+
for tool_result in tool_results
|
221
|
+
]
|
222
|
+
|
223
|
+
next_result = await self.chat(result.uuid, tool_messages, ChatPromptOptions(**dict(options)))
|
224
|
+
|
225
|
+
return FinishedEvent(**dict(next_result)) if next_result else None
|
226
|
+
|
227
|
+
async def get(self, path: str, options: GetPromptOptions) -> GetPromptResult:
|
228
|
+
options = GetPromptOptions(**{**dict(self._options), **dict(options)})
|
229
|
+
self._ensure_prompt_options(options)
|
166
230
|
assert options.project_id is not None
|
167
231
|
|
168
232
|
async with self._client.request(
|
@@ -176,9 +240,8 @@ class Prompts:
|
|
176
240
|
return GetPromptResult.model_validate_json(response.content)
|
177
241
|
|
178
242
|
async def get_or_create(self, path: str, options: GetOrCreatePromptOptions) -> GetOrCreatePromptResult:
|
179
|
-
|
180
|
-
|
181
|
-
|
243
|
+
options = GetOrCreatePromptOptions(**{**dict(self._options), **dict(options)})
|
244
|
+
self._ensure_prompt_options(options)
|
182
245
|
assert options.project_id is not None
|
183
246
|
|
184
247
|
async with self._client.request(
|
@@ -196,9 +259,8 @@ class Prompts:
|
|
196
259
|
|
197
260
|
async def run(self, path: str, options: RunPromptOptions) -> Optional[RunPromptResult]:
|
198
261
|
try:
|
199
|
-
|
200
|
-
|
201
|
-
|
262
|
+
options = RunPromptOptions(**{**dict(self._options), **dict(options)})
|
263
|
+
self._ensure_prompt_options(options)
|
202
264
|
assert options.project_id is not None
|
203
265
|
|
204
266
|
async with self._client.request(
|
@@ -215,21 +277,22 @@ class Prompts:
|
|
215
277
|
),
|
216
278
|
) as response:
|
217
279
|
if options.stream:
|
218
|
-
result = await self._handle_stream(
|
219
|
-
response.sse(),
|
220
|
-
callbacks=StreamCallbacks(
|
221
|
-
on_event=options.on_event,
|
222
|
-
on_finished=options.on_finished,
|
223
|
-
on_error=options.on_error,
|
224
|
-
),
|
225
|
-
)
|
280
|
+
result = await self._handle_stream(response.sse(), options.on_event)
|
226
281
|
else:
|
227
282
|
result = RunPromptResult.model_validate_json(response.content)
|
228
283
|
|
229
|
-
|
230
|
-
|
284
|
+
if options.tools and result.response.type == StreamTypes.Text and result.response.tool_calls:
|
285
|
+
try:
|
286
|
+
# NOTE: The last sdk.chat called will already call on_finished
|
287
|
+
final_result = await self._handle_tool_calls(result, options)
|
288
|
+
return RunPromptResult(**dict(final_result)) if final_result else None
|
289
|
+
except OnToolCallPaused:
|
290
|
+
pass
|
291
|
+
|
292
|
+
if options.on_finished:
|
293
|
+
options.on_finished(FinishedEvent(**dict(result)))
|
231
294
|
|
232
|
-
|
295
|
+
return RunPromptResult(**dict(result))
|
233
296
|
|
234
297
|
except Exception as exception:
|
235
298
|
if not isinstance(exception, ApiError):
|
@@ -248,35 +311,40 @@ class Prompts:
|
|
248
311
|
return None
|
249
312
|
|
250
313
|
async def chat(
|
251
|
-
self, uuid: str, messages:
|
314
|
+
self, uuid: str, messages: Sequence[Union[Message, Dict[str, Any]]], options: ChatPromptOptions
|
252
315
|
) -> Optional[ChatPromptResult]:
|
253
316
|
try:
|
317
|
+
options = ChatPromptOptions(**{**dict(self._options), **dict(options)})
|
318
|
+
|
319
|
+
messages = [_Message.validate_python(message) for message in messages]
|
320
|
+
|
254
321
|
async with self._client.request(
|
255
322
|
handler=RequestHandler.ChatPrompt,
|
256
323
|
params=ChatPromptRequestParams(
|
257
324
|
conversation_uuid=uuid,
|
258
325
|
),
|
259
326
|
body=ChatPromptRequestBody(
|
260
|
-
messages=
|
327
|
+
messages=messages,
|
261
328
|
stream=options.stream,
|
262
329
|
),
|
263
330
|
) as response:
|
264
331
|
if options.stream:
|
265
|
-
result = await self._handle_stream(
|
266
|
-
response.sse(),
|
267
|
-
callbacks=StreamCallbacks(
|
268
|
-
on_event=options.on_event,
|
269
|
-
on_finished=options.on_finished,
|
270
|
-
on_error=options.on_error,
|
271
|
-
),
|
272
|
-
)
|
332
|
+
result = await self._handle_stream(response.sse(), options.on_event)
|
273
333
|
else:
|
274
334
|
result = ChatPromptResult.model_validate_json(response.content)
|
275
335
|
|
276
|
-
|
277
|
-
|
336
|
+
if options.tools and result.response.type == StreamTypes.Text and result.response.tool_calls:
|
337
|
+
try:
|
338
|
+
# NOTE: The last sdk.chat called will already call on_finished
|
339
|
+
final_result = await self._handle_tool_calls(result, options)
|
340
|
+
return ChatPromptResult(**dict(final_result)) if final_result else None
|
341
|
+
except OnToolCallPaused:
|
342
|
+
pass
|
343
|
+
|
344
|
+
if options.on_finished:
|
345
|
+
options.on_finished(FinishedEvent(**dict(result)))
|
278
346
|
|
279
|
-
|
347
|
+
return ChatPromptResult(**dict(result))
|
280
348
|
|
281
349
|
except Exception as exception:
|
282
350
|
if not isinstance(exception, ApiError):
|
@@ -1,8 +1,8 @@
|
|
1
1
|
from datetime import datetime
|
2
|
-
from typing import Any, Dict, List, Literal, Optional, Protocol, Union, runtime_checkable
|
2
|
+
from typing import Any, Callable, Dict, List, Literal, Optional, Protocol, Union, runtime_checkable
|
3
3
|
|
4
4
|
from latitude_sdk.sdk.errors import ApiError
|
5
|
-
from latitude_sdk.util import Field, Model, StrEnum
|
5
|
+
from latitude_sdk.util import Adapter, Field, Model, StrEnum
|
6
6
|
|
7
7
|
|
8
8
|
class DbErrorRef(Model):
|
@@ -63,7 +63,7 @@ class ToolResultContent(Model):
|
|
63
63
|
type: Literal[ContentType.ToolResult] = ContentType.ToolResult
|
64
64
|
id: str = Field(alias=str("toolCallId"))
|
65
65
|
name: str = Field(alias=str("toolName"))
|
66
|
-
result:
|
66
|
+
result: Any
|
67
67
|
is_error: Optional[bool] = Field(default=None, alias=str("isError"))
|
68
68
|
|
69
69
|
|
@@ -106,6 +106,7 @@ class ToolMessage(Model):
|
|
106
106
|
|
107
107
|
|
108
108
|
Message = Union[SystemMessage, UserMessage, AssistantMessage, ToolMessage]
|
109
|
+
_Message = Adapter(Message)
|
109
110
|
|
110
111
|
|
111
112
|
class ModelUsage(Model):
|
@@ -114,12 +115,29 @@ class ModelUsage(Model):
|
|
114
115
|
total_tokens: int = Field(alias=str("totalTokens"))
|
115
116
|
|
116
117
|
|
118
|
+
class FinishReason(StrEnum):
|
119
|
+
Stop = "stop"
|
120
|
+
Length = "length"
|
121
|
+
ContentFilter = "content-filter"
|
122
|
+
ToolCalls = "tool-calls"
|
123
|
+
Error = "error"
|
124
|
+
Other = "other"
|
125
|
+
Unknown = "unknown"
|
126
|
+
|
127
|
+
|
117
128
|
class ToolCall(Model):
|
118
129
|
id: str
|
119
130
|
name: str
|
120
131
|
arguments: Dict[str, Any]
|
121
132
|
|
122
133
|
|
134
|
+
class ToolResult(Model):
|
135
|
+
id: str
|
136
|
+
name: str
|
137
|
+
result: Any
|
138
|
+
is_error: Optional[bool] = None
|
139
|
+
|
140
|
+
|
123
141
|
class StreamTypes(StrEnum):
|
124
142
|
Text = "text"
|
125
143
|
Object = "object"
|
@@ -183,6 +201,7 @@ class ChainEventCompleted(Model):
|
|
183
201
|
event: Literal[StreamEvents.Latitude] = StreamEvents.Latitude
|
184
202
|
type: Literal[ChainEvents.Completed] = ChainEvents.Completed
|
185
203
|
uuid: Optional[str] = None
|
204
|
+
finish_reason: FinishReason = Field(alias=str("finishReason"))
|
186
205
|
config: Dict[str, Any]
|
187
206
|
messages: Optional[List[Message]] = None
|
188
207
|
object: Optional[Any] = None
|
@@ -275,9 +294,22 @@ class StreamCallbacks(Model):
|
|
275
294
|
on_error: Optional[OnError] = None
|
276
295
|
|
277
296
|
|
297
|
+
class OnToolCallDetails(Model):
|
298
|
+
conversation_uuid: str
|
299
|
+
messages: List[Message]
|
300
|
+
pause_execution: Callable[[], ToolResult]
|
301
|
+
requested_tool_calls: List[ToolCall]
|
302
|
+
|
303
|
+
|
304
|
+
@runtime_checkable
|
305
|
+
class OnToolCall(Protocol):
|
306
|
+
async def __call__(self, call: ToolCall, details: OnToolCallDetails) -> ToolResult: ...
|
307
|
+
|
308
|
+
|
278
309
|
class SdkOptions(Model):
|
279
310
|
project_id: Optional[int] = None
|
280
311
|
version_uuid: Optional[str] = None
|
312
|
+
tools: Optional[Dict[str, OnToolCall]] = None
|
281
313
|
|
282
314
|
|
283
315
|
class GatewayOptions(Model):
|