lionagi 0.14.8__py3-none-any.whl → 0.14.10__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.
- lionagi/_errors.py +120 -11
- lionagi/_types.py +0 -6
- lionagi/config.py +3 -1
- lionagi/fields/reason.py +1 -1
- lionagi/libs/concurrency/throttle.py +79 -0
- lionagi/libs/parse.py +2 -1
- lionagi/libs/unstructured/__init__.py +0 -0
- lionagi/libs/unstructured/pdf_to_image.py +45 -0
- lionagi/libs/unstructured/read_image_to_base64.py +33 -0
- lionagi/libs/validate/to_num.py +378 -0
- lionagi/libs/validate/xml_parser.py +203 -0
- lionagi/models/operable_model.py +8 -3
- lionagi/operations/flow.py +0 -1
- lionagi/protocols/generic/event.py +2 -0
- lionagi/protocols/generic/log.py +26 -10
- lionagi/protocols/operatives/step.py +1 -1
- lionagi/protocols/types.py +9 -1
- lionagi/service/__init__.py +22 -1
- lionagi/service/connections/api_calling.py +57 -2
- lionagi/service/connections/endpoint_config.py +1 -1
- lionagi/service/connections/header_factory.py +4 -2
- lionagi/service/connections/match_endpoint.py +10 -10
- lionagi/service/connections/providers/anthropic_.py +5 -2
- lionagi/service/connections/providers/claude_code_.py +13 -17
- lionagi/service/connections/providers/claude_code_cli.py +51 -16
- lionagi/service/connections/providers/exa_.py +5 -3
- lionagi/service/connections/providers/oai_.py +116 -81
- lionagi/service/connections/providers/ollama_.py +38 -18
- lionagi/service/connections/providers/perplexity_.py +36 -14
- lionagi/service/connections/providers/types.py +30 -0
- lionagi/service/hooks/__init__.py +25 -0
- lionagi/service/hooks/_types.py +52 -0
- lionagi/service/hooks/_utils.py +85 -0
- lionagi/service/hooks/hook_event.py +67 -0
- lionagi/service/hooks/hook_registry.py +221 -0
- lionagi/service/imodel.py +120 -34
- lionagi/service/third_party/claude_code.py +715 -0
- lionagi/service/third_party/openai_model_names.py +198 -0
- lionagi/service/third_party/pplx_models.py +16 -8
- lionagi/service/types.py +21 -0
- lionagi/session/branch.py +1 -4
- lionagi/tools/base.py +1 -3
- lionagi/tools/file/reader.py +1 -1
- lionagi/tools/memory/tools.py +2 -2
- lionagi/utils.py +12 -775
- lionagi/version.py +1 -1
- {lionagi-0.14.8.dist-info → lionagi-0.14.10.dist-info}/METADATA +6 -2
- {lionagi-0.14.8.dist-info → lionagi-0.14.10.dist-info}/RECORD +50 -40
- lionagi/service/connections/providers/_claude_code/__init__.py +0 -3
- lionagi/service/connections/providers/_claude_code/models.py +0 -244
- lionagi/service/connections/providers/_claude_code/stream_cli.py +0 -359
- lionagi/service/third_party/openai_models.py +0 -18241
- {lionagi-0.14.8.dist-info → lionagi-0.14.10.dist-info}/WHEEL +0 -0
- {lionagi-0.14.8.dist-info → lionagi-0.14.10.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,221 @@
|
|
1
|
+
# Copyright (c) 2025, HaiyangLi <quantocean.li at gmail dot com>
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
3
|
+
|
4
|
+
from __future__ import annotations
|
5
|
+
|
6
|
+
from typing import Any, TypeVar
|
7
|
+
|
8
|
+
from lionagi.libs.concurrency import get_cancelled_exc_class
|
9
|
+
from lionagi.protocols.types import Event, EventStatus
|
10
|
+
from lionagi.utils import UNDEFINED
|
11
|
+
|
12
|
+
from ._types import HookDict, HookEventTypes, StreamHandlers
|
13
|
+
from ._utils import validate_hooks, validate_stream_handlers
|
14
|
+
|
15
|
+
E = TypeVar("E", bound=Event)
|
16
|
+
|
17
|
+
|
18
|
+
class HookRegistry:
|
19
|
+
def __init__(
|
20
|
+
self,
|
21
|
+
hooks: HookDict = None,
|
22
|
+
stream_handlers: StreamHandlers = None,
|
23
|
+
):
|
24
|
+
_hooks = {}
|
25
|
+
_stream_handlers = {}
|
26
|
+
|
27
|
+
if hooks is not None:
|
28
|
+
validate_hooks(hooks)
|
29
|
+
_hooks.update(hooks)
|
30
|
+
|
31
|
+
if stream_handlers is not None:
|
32
|
+
validate_stream_handlers(stream_handlers)
|
33
|
+
_stream_handlers.update(stream_handlers)
|
34
|
+
|
35
|
+
self._hooks = _hooks
|
36
|
+
self._stream_handlers = _stream_handlers
|
37
|
+
|
38
|
+
async def _call(
|
39
|
+
self,
|
40
|
+
ht_: HookEventTypes,
|
41
|
+
ct_: str | type,
|
42
|
+
ch_: Any,
|
43
|
+
ev_: E | type[E],
|
44
|
+
/,
|
45
|
+
**kw,
|
46
|
+
) -> tuple[Any | Exception, bool]:
|
47
|
+
if ht_ is None and ct_ is None:
|
48
|
+
raise RuntimeError(
|
49
|
+
"Either hook_type or chunk_type must be provided"
|
50
|
+
)
|
51
|
+
if ht_ and (h := self._hooks.get(ht_)):
|
52
|
+
validate_hooks({ht_: h})
|
53
|
+
return await h(ev_, **kw)
|
54
|
+
elif not ct_:
|
55
|
+
raise RuntimeError(
|
56
|
+
"Hook type is required when chunk_type is not provided"
|
57
|
+
)
|
58
|
+
else:
|
59
|
+
validate_stream_handlers(
|
60
|
+
{ct_: (h := self._stream_handlers.get(ct_))}
|
61
|
+
)
|
62
|
+
return await h(ev_, ct_, ch_, **kw)
|
63
|
+
|
64
|
+
async def _call_stream_handler(
|
65
|
+
self,
|
66
|
+
ct_: str | type,
|
67
|
+
ch_: Any,
|
68
|
+
ev_,
|
69
|
+
/,
|
70
|
+
**kw,
|
71
|
+
):
|
72
|
+
handler = self._stream_handlers.get(ct_)
|
73
|
+
validate_stream_handlers({ct_: handler})
|
74
|
+
return await handler(ev_, ct_, ch_, **kw)
|
75
|
+
|
76
|
+
async def pre_event_create(
|
77
|
+
self, event_type: type[E], /, exit: bool = False, **kw
|
78
|
+
) -> tuple[E | Exception | None, bool, EventStatus]:
|
79
|
+
"""Hook to be called before an event is created.
|
80
|
+
|
81
|
+
Typically used to modify or validate the event creation parameters.
|
82
|
+
|
83
|
+
The hook function takes an event type and any additional keyword arguments.
|
84
|
+
It can:
|
85
|
+
- return an instance of the event type
|
86
|
+
- return None if no event should be created during handling, event will be
|
87
|
+
created in corresponding default manner
|
88
|
+
- raise an exception if this event should be cancelled
|
89
|
+
(status: cancelled, reason: f"pre-event-create hook aborted this event: {e}")
|
90
|
+
"""
|
91
|
+
try:
|
92
|
+
res = await self._call(
|
93
|
+
HookEventTypes.PreEventCreate,
|
94
|
+
None,
|
95
|
+
None,
|
96
|
+
event_type,
|
97
|
+
**kw,
|
98
|
+
)
|
99
|
+
return (res, False, EventStatus.COMPLETED)
|
100
|
+
except get_cancelled_exc_class() as e:
|
101
|
+
return ((UNDEFINED, e), True, EventStatus.CANCELLED)
|
102
|
+
except Exception as e:
|
103
|
+
return (e, exit, EventStatus.CANCELLED)
|
104
|
+
|
105
|
+
async def pre_invokation(
|
106
|
+
self, event: E, /, exit: bool = False, **kw
|
107
|
+
) -> tuple[Any, bool, EventStatus]:
|
108
|
+
"""Hook to be called when an event is dequeued and right before it is invoked.
|
109
|
+
|
110
|
+
Typically used to check permissions.
|
111
|
+
|
112
|
+
The hook function takes the content of the event as a dictionary.
|
113
|
+
It can either raise an exception to abort the event invokation or pass to continue (status: cancelled).
|
114
|
+
It cannot modify the event itself, and won't be able to access the event instance.
|
115
|
+
"""
|
116
|
+
try:
|
117
|
+
res = await self._call(
|
118
|
+
HookEventTypes.PreInvokation,
|
119
|
+
None,
|
120
|
+
None,
|
121
|
+
event,
|
122
|
+
**kw,
|
123
|
+
)
|
124
|
+
return (res, False, EventStatus.COMPLETED)
|
125
|
+
except get_cancelled_exc_class() as e:
|
126
|
+
return ((UNDEFINED, e), True, EventStatus.CANCELLED)
|
127
|
+
except Exception as e:
|
128
|
+
return (e, exit, EventStatus.CANCELLED)
|
129
|
+
|
130
|
+
async def post_invokation(
|
131
|
+
self, event: E, /, exit: bool = False, **kw
|
132
|
+
) -> tuple[None | Exception, bool, EventStatus, EventStatus]:
|
133
|
+
"""Hook to be called right after event finished its execution.
|
134
|
+
It can either raise an exception to abort the event invokation or pass to continue (status: aborted).
|
135
|
+
It cannot modify the event itself, and won't be able to access the event instance.
|
136
|
+
"""
|
137
|
+
try:
|
138
|
+
res = await self._call(
|
139
|
+
HookEventTypes.PostInvokation,
|
140
|
+
None,
|
141
|
+
None,
|
142
|
+
event,
|
143
|
+
**kw,
|
144
|
+
)
|
145
|
+
return (res, False, EventStatus.COMPLETED)
|
146
|
+
except get_cancelled_exc_class() as e:
|
147
|
+
return ((UNDEFINED, e), True, EventStatus.CANCELLED)
|
148
|
+
except Exception as e:
|
149
|
+
return (e, exit, EventStatus.ABORTED)
|
150
|
+
|
151
|
+
async def handle_streaming_chunk(
|
152
|
+
self, chunk_type: str | type, chunk: Any, /, exit: bool = False, **kw
|
153
|
+
) -> tuple[Any, bool, EventStatus | None]:
|
154
|
+
"""Hook to be called to consume streaming chunks.
|
155
|
+
|
156
|
+
Typically used for logging or stream event abortion.
|
157
|
+
|
158
|
+
The handler function signature should be: `async def handler(chunk: Any) -> None`
|
159
|
+
It can either raise an exception to mark the event invokation as "failed" or pass to continue (status: aborted).
|
160
|
+
"""
|
161
|
+
try:
|
162
|
+
res = await self._call_stream_handler(
|
163
|
+
chunk_type,
|
164
|
+
chunk,
|
165
|
+
None,
|
166
|
+
**kw,
|
167
|
+
)
|
168
|
+
return (res, False, None)
|
169
|
+
except get_cancelled_exc_class() as e:
|
170
|
+
return ((UNDEFINED, e), True, EventStatus.CANCELLED)
|
171
|
+
except Exception as e:
|
172
|
+
return (e, exit, EventStatus.ABORTED)
|
173
|
+
|
174
|
+
async def call(
|
175
|
+
self,
|
176
|
+
event_like: Event | type[Event],
|
177
|
+
/,
|
178
|
+
*,
|
179
|
+
hook_type: HookEventTypes = None,
|
180
|
+
chunk_type=None,
|
181
|
+
chunk=None,
|
182
|
+
exit=False,
|
183
|
+
**kw,
|
184
|
+
):
|
185
|
+
"""Call a hook or stream handler.
|
186
|
+
|
187
|
+
If method is provided, it will call the corresponding hook.
|
188
|
+
If chunk_type is provided, it will call the corresponding stream handler.
|
189
|
+
If both are provided, method will be used.
|
190
|
+
"""
|
191
|
+
if hook_type is None and chunk_type is None:
|
192
|
+
raise ValueError("Either method or chunk_type must be provided")
|
193
|
+
if hook_type:
|
194
|
+
meta = {}
|
195
|
+
meta["event_type"] = event_like.class_name(full=True)
|
196
|
+
match hook_type:
|
197
|
+
case HookEventTypes.PreEventCreate:
|
198
|
+
return await self.pre_event_create(event_like, **kw), meta
|
199
|
+
case HookEventTypes.PreInvokation:
|
200
|
+
meta["event_id"] = str(event_like.id)
|
201
|
+
meta["event_created_at"] = event_like.created_at
|
202
|
+
return await self.pre_invokation(event_like, **kw), meta
|
203
|
+
case HookEventTypes.PostInvokation:
|
204
|
+
meta["event_id"] = str(event_like.id)
|
205
|
+
meta["event_created_at"] = event_like.created_at
|
206
|
+
return await self.post_invokation(**kw), meta
|
207
|
+
return await self.handle_streaming_chunk(chunk_type, chunk, exit, **kw)
|
208
|
+
|
209
|
+
def _can_handle(
|
210
|
+
self,
|
211
|
+
/,
|
212
|
+
*,
|
213
|
+
ht_: HookEventTypes = None,
|
214
|
+
ct_=None,
|
215
|
+
) -> bool:
|
216
|
+
"""Check if the registry can handle the given event or chunk type."""
|
217
|
+
if ht_:
|
218
|
+
return ht_ in self._hooks
|
219
|
+
if ct_:
|
220
|
+
return ct_ in self._stream_handlers
|
221
|
+
return False
|
lionagi/service/imodel.py
CHANGED
@@ -7,12 +7,15 @@ from collections.abc import AsyncGenerator, Callable
|
|
7
7
|
|
8
8
|
from pydantic import BaseModel
|
9
9
|
|
10
|
-
from lionagi.protocols.generic.
|
11
|
-
from lionagi.
|
10
|
+
from lionagi.protocols.generic.log import Log
|
11
|
+
from lionagi.protocols.types import ID, Event, EventStatus, IDType
|
12
|
+
from lionagi.service.hooks.hook_event import HookEventTypes
|
13
|
+
from lionagi.utils import is_coro_func, time
|
12
14
|
|
13
15
|
from .connections.api_calling import APICalling
|
14
16
|
from .connections.endpoint import Endpoint
|
15
17
|
from .connections.match_endpoint import match_endpoint
|
18
|
+
from .hooks import HookEvent, HookRegistry, global_hook_logger
|
16
19
|
from .rate_limited_processor import RateLimitedAPIExecutor
|
17
20
|
|
18
21
|
|
@@ -47,6 +50,10 @@ class iModel:
|
|
47
50
|
concurrency_limit: int | None = None,
|
48
51
|
streaming_process_func: Callable = None,
|
49
52
|
provider_metadata: dict | None = None,
|
53
|
+
hook_registry: HookRegistry | dict | None = None,
|
54
|
+
exit_hook: bool = False,
|
55
|
+
id: IDType | str = None,
|
56
|
+
created_at: float | None = None,
|
50
57
|
**kwargs,
|
51
58
|
) -> None:
|
52
59
|
"""Initializes the iModel instance.
|
@@ -86,6 +93,22 @@ class iModel:
|
|
86
93
|
Additional keyword arguments, such as `model`, or any other
|
87
94
|
provider-specific fields.
|
88
95
|
"""
|
96
|
+
|
97
|
+
# 1. put in ID and timestamp -----------------------------------------
|
98
|
+
self.id = None
|
99
|
+
self.created_at = None
|
100
|
+
if id is not None:
|
101
|
+
self.id = ID.get_id(id)
|
102
|
+
else:
|
103
|
+
self.id = IDType.create()
|
104
|
+
if created_at is not None:
|
105
|
+
if not isinstance(created_at, float):
|
106
|
+
raise ValueError("created_at must be a float timestamp.")
|
107
|
+
self.created_at = created_at
|
108
|
+
else:
|
109
|
+
self.created_at = time()
|
110
|
+
|
111
|
+
# 2. Configure Endpoint ---------------------------------------------
|
89
112
|
model = kwargs.get("model", None)
|
90
113
|
if model:
|
91
114
|
if not provider:
|
@@ -96,7 +119,6 @@ class iModel:
|
|
96
119
|
else:
|
97
120
|
raise ValueError("Provider must be provided")
|
98
121
|
|
99
|
-
# Pass api_key to endpoint if provided
|
100
122
|
if api_key is not None:
|
101
123
|
kwargs["api_key"] = api_key
|
102
124
|
if isinstance(endpoint, Endpoint):
|
@@ -112,6 +134,7 @@ class iModel:
|
|
112
134
|
if base_url:
|
113
135
|
self.endpoint.config.base_url = base_url
|
114
136
|
|
137
|
+
# 3. Configure executor ---------------------------------------------
|
115
138
|
self.executor = RateLimitedAPIExecutor(
|
116
139
|
queue_capacity=queue_capacity,
|
117
140
|
capacity_refresh_time=capacity_refresh_time,
|
@@ -120,11 +143,91 @@ class iModel:
|
|
120
143
|
limit_tokens=limit_tokens,
|
121
144
|
concurrency_limit=concurrency_limit,
|
122
145
|
)
|
123
|
-
# Use provided streaming_process_func or default to None
|
124
|
-
self.streaming_process_func = streaming_process_func
|
125
146
|
|
126
|
-
#
|
147
|
+
# 4. other configurations --------------------------------------------
|
148
|
+
self.streaming_process_func = streaming_process_func
|
127
149
|
self.provider_metadata = provider_metadata or {}
|
150
|
+
self.hook_registry = hook_registry or HookRegistry()
|
151
|
+
if isinstance(self.hook_registry, dict):
|
152
|
+
self.hook_registry = HookRegistry(**self.hook_registry)
|
153
|
+
self.exit_hook: bool = exit_hook
|
154
|
+
|
155
|
+
async def create_event(
|
156
|
+
self,
|
157
|
+
create_event_type: type[Event] = APICalling,
|
158
|
+
create_event_exit_hook: bool = None,
|
159
|
+
create_event_hook_timeout: float = 10.0,
|
160
|
+
create_event_hook_params: dict = None,
|
161
|
+
pre_invoke_event_exit_hook: bool = None,
|
162
|
+
pre_invoke_event_hook_timeout: float = 30.0,
|
163
|
+
pre_invoke_event_hook_params: dict = None,
|
164
|
+
post_invoke_event_exit_hook: bool = None,
|
165
|
+
post_invoke_event_hook_timeout: float = 30.0,
|
166
|
+
post_invoke_event_hook_params: dict = None,
|
167
|
+
**kwargs,
|
168
|
+
) -> tuple[HookEvent | None, APICalling]:
|
169
|
+
h_ev = None
|
170
|
+
if self.hook_registry._can_handle(ht_=HookEventTypes.PreEventCreate):
|
171
|
+
h_ev = HookEvent(
|
172
|
+
hook_type=HookEventTypes.PreEventCreate,
|
173
|
+
registry=self.hook_registry,
|
174
|
+
event_like=create_event_type,
|
175
|
+
params=create_event_hook_params or {},
|
176
|
+
exit=(
|
177
|
+
self.exit_hook
|
178
|
+
if create_event_exit_hook is None
|
179
|
+
else create_event_exit_hook
|
180
|
+
),
|
181
|
+
timeout=create_event_hook_timeout,
|
182
|
+
)
|
183
|
+
await h_ev.invoke()
|
184
|
+
if h_ev._should_exit:
|
185
|
+
raise h_ev._exit_cause or RuntimeError(
|
186
|
+
"PreEventCreate hook requested exit without a cause"
|
187
|
+
)
|
188
|
+
|
189
|
+
if create_event_type is APICalling:
|
190
|
+
api_call = self.create_api_calling(**kwargs)
|
191
|
+
if h_ev:
|
192
|
+
h_ev.assosiated_event_info["event_id"] = str(api_call.id)
|
193
|
+
h_ev.assosiated_event_info["event_created_at"] = (
|
194
|
+
api_call.created_at
|
195
|
+
)
|
196
|
+
await global_hook_logger.alog(Log(content=h_ev.to_dict()))
|
197
|
+
|
198
|
+
if self.hook_registry._can_handle(
|
199
|
+
ht_=HookEventTypes.PreInvokation
|
200
|
+
):
|
201
|
+
api_call.create_pre_invoke_hook(
|
202
|
+
hook_registry=self.hook_registry,
|
203
|
+
exit_hook=(
|
204
|
+
self.exit_hook
|
205
|
+
if pre_invoke_event_exit_hook is None
|
206
|
+
else pre_invoke_event_exit_hook
|
207
|
+
),
|
208
|
+
hook_timeout=pre_invoke_event_hook_timeout,
|
209
|
+
hook_params=pre_invoke_event_hook_params or {},
|
210
|
+
)
|
211
|
+
|
212
|
+
if self.hook_registry._can_handle(
|
213
|
+
ht_=HookEventTypes.PostInvokation
|
214
|
+
):
|
215
|
+
api_call.create_post_invoke_hook(
|
216
|
+
hook_registry=self.hook_registry,
|
217
|
+
exit_hook=(
|
218
|
+
self.exit_hook
|
219
|
+
if post_invoke_event_exit_hook is None
|
220
|
+
else post_invoke_event_exit_hook
|
221
|
+
),
|
222
|
+
hook_timeout=post_invoke_event_hook_timeout,
|
223
|
+
hook_params=post_invoke_event_hook_params or {},
|
224
|
+
)
|
225
|
+
|
226
|
+
return api_call
|
227
|
+
|
228
|
+
raise ValueError(
|
229
|
+
f"Unsupported event type: {create_event_type}. Only APICalling is supported."
|
230
|
+
)
|
128
231
|
|
129
232
|
def create_api_calling(
|
130
233
|
self, include_token_usage_to_model: bool = False, **kwargs
|
@@ -178,12 +281,7 @@ class iModel:
|
|
178
281
|
return await self.streaming_process_func(chunk)
|
179
282
|
return self.streaming_process_func(chunk)
|
180
283
|
|
181
|
-
async def stream(
|
182
|
-
self,
|
183
|
-
api_call=None,
|
184
|
-
include_token_usage_to_model: bool = False,
|
185
|
-
**kwargs,
|
186
|
-
) -> AsyncGenerator:
|
284
|
+
async def stream(self, api_call=None, **kw) -> AsyncGenerator:
|
187
285
|
"""Performs a streaming API call with the given arguments.
|
188
286
|
|
189
287
|
Args:
|
@@ -196,11 +294,8 @@ class iModel:
|
|
196
294
|
goes wrong.
|
197
295
|
"""
|
198
296
|
if api_call is None:
|
199
|
-
|
200
|
-
api_call = self.
|
201
|
-
include_token_usage_to_model=include_token_usage_to_model,
|
202
|
-
**kwargs,
|
203
|
-
)
|
297
|
+
kw["stream"] = True
|
298
|
+
api_call = await self.create_event(**kw)
|
204
299
|
await self.executor.append(api_call)
|
205
300
|
|
206
301
|
if (
|
@@ -231,9 +326,7 @@ class iModel:
|
|
231
326
|
finally:
|
232
327
|
yield self.executor.pile.pop(api_call.id)
|
233
328
|
|
234
|
-
async def invoke(
|
235
|
-
self, api_call: APICalling = None, **kwargs
|
236
|
-
) -> APICalling | None:
|
329
|
+
async def invoke(self, api_call: APICalling = None, **kw) -> APICalling:
|
237
330
|
"""Invokes a rate-limited API call with the given arguments.
|
238
331
|
|
239
332
|
Args:
|
@@ -251,8 +344,9 @@ class iModel:
|
|
251
344
|
"""
|
252
345
|
try:
|
253
346
|
if api_call is None:
|
254
|
-
|
255
|
-
api_call = self.
|
347
|
+
kw.pop("stream", None)
|
348
|
+
api_call = await self.create_event(**kw)
|
349
|
+
|
256
350
|
if (
|
257
351
|
self.executor.processor is None
|
258
352
|
or self.executor.processor.is_stopped()
|
@@ -291,18 +385,6 @@ class iModel:
|
|
291
385
|
except Exception as e:
|
292
386
|
raise ValueError(f"Failed to invoke API call: {e}")
|
293
387
|
|
294
|
-
@property
|
295
|
-
def allowed_roles(self) -> set[str]:
|
296
|
-
"""list[str]: Roles that are permissible for this endpoint.
|
297
|
-
|
298
|
-
Returns:
|
299
|
-
If the endpoint has an `allowed_roles` attribute, returns that;
|
300
|
-
otherwise, defaults to `{"system", "user", "assistant"}`.
|
301
|
-
"""
|
302
|
-
if hasattr(self.endpoint, "allowed_roles"):
|
303
|
-
return self.endpoint.allowed_roles
|
304
|
-
return {"system", "user", "assistant"}
|
305
|
-
|
306
388
|
@property
|
307
389
|
def model_name(self) -> str:
|
308
390
|
"""str: The name of the model used by the endpoint.
|
@@ -323,6 +405,8 @@ class iModel:
|
|
323
405
|
|
324
406
|
def to_dict(self):
|
325
407
|
return {
|
408
|
+
"id": str(self.id) if self.id else None,
|
409
|
+
"created_at": self.created_at,
|
326
410
|
"endpoint": self.endpoint.to_dict(),
|
327
411
|
"processor_config": self.executor.config,
|
328
412
|
"provider_metadata": self.provider_metadata,
|
@@ -343,5 +427,7 @@ class iModel:
|
|
343
427
|
return cls(
|
344
428
|
endpoint=e1,
|
345
429
|
provider_metadata=data.get("provider_metadata"),
|
430
|
+
id=data.get("id"),
|
431
|
+
created_at=data.get("created_at"),
|
346
432
|
**data.get("processor_config", {}),
|
347
433
|
)
|