lionagi 0.5.3__py3-none-any.whl → 0.5.5__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- lionagi/core/action/action_manager.py +2 -0
- lionagi/core/communication/assistant_response.py +10 -0
- lionagi/core/communication/message.py +1 -1
- lionagi/core/communication/message_manager.py +13 -0
- lionagi/core/communication/utils.py +4 -2
- lionagi/core/session/branch_mixins.py +76 -39
- lionagi/core/session/session.py +3 -3
- lionagi/integrations/anthropic_/AnthropicModel.py +4 -9
- lionagi/integrations/anthropic_/AnthropicService.py +10 -0
- lionagi/integrations/anthropic_/anthropic_max_output_token_data.yaml +5 -0
- lionagi/integrations/anthropic_/anthropic_price_data.yaml +26 -6
- lionagi/integrations/anthropic_/version.py +1 -1
- lionagi/integrations/groq_/GroqService.py +5 -0
- lionagi/integrations/groq_/version.py +1 -1
- lionagi/integrations/litellm_/imodel.py +5 -0
- lionagi/integrations/openai_/OpenAIModel.py +0 -4
- lionagi/integrations/openai_/OpenAIService.py +9 -0
- lionagi/integrations/openai_/version.py +1 -1
- lionagi/integrations/perplexity_/PerplexityService.py +5 -0
- lionagi/integrations/perplexity_/version.py +1 -1
- lionagi/libs/func/async_calls/alcall.py +7 -0
- lionagi/operations/brainstorm/brainstorm.py +318 -93
- lionagi/operations/plan/plan.py +280 -67
- lionagi/service/imodel.py +5 -0
- lionagi/version.py +1 -1
- {lionagi-0.5.3.dist-info → lionagi-0.5.5.dist-info}/METADATA +1 -1
- {lionagi-0.5.3.dist-info → lionagi-0.5.5.dist-info}/RECORD +29 -29
- {lionagi-0.5.3.dist-info → lionagi-0.5.5.dist-info}/WHEEL +0 -0
- {lionagi-0.5.3.dist-info → lionagi-0.5.5.dist-info}/licenses/LICENSE +0 -0
@@ -253,6 +253,8 @@ class ActionManager:
|
|
253
253
|
ValueError: If a specified tool is not registered.
|
254
254
|
TypeError: If an unsupported tool type is provided.
|
255
255
|
"""
|
256
|
+
if isinstance(tools, list | tuple) and len(tools) == 1:
|
257
|
+
tools = tools[0]
|
256
258
|
if isinstance(tools, bool):
|
257
259
|
if tools:
|
258
260
|
tool_kwarg = {"tools": self.schema_list}
|
@@ -146,6 +146,16 @@ class AssistantResponse(RoledMessage):
|
|
146
146
|
"""
|
147
147
|
return copy(self.content["assistant_response"])
|
148
148
|
|
149
|
+
@response.setter
|
150
|
+
def response(self, value: str) -> None:
|
151
|
+
"""
|
152
|
+
Set the assistant response content.
|
153
|
+
|
154
|
+
Args:
|
155
|
+
value: The new response content
|
156
|
+
"""
|
157
|
+
self.content["assistant_response"] = value
|
158
|
+
|
149
159
|
@property
|
150
160
|
def model_response(self) -> dict | list[dict]:
|
151
161
|
"""
|
@@ -498,6 +498,19 @@ class MessageManager:
|
|
498
498
|
]
|
499
499
|
)
|
500
500
|
|
501
|
+
def remove_last_instruction_tool_schemas(self) -> None:
|
502
|
+
id_ = self.last_instruction.ln_id
|
503
|
+
self.messages[id_].tool_schemas = None
|
504
|
+
|
505
|
+
def concat_recent_action_responses_to_instruction(
|
506
|
+
self, instruction: Instruction
|
507
|
+
) -> None:
|
508
|
+
for i in reversed(self.messages.progress):
|
509
|
+
if isinstance(self.messages[i], ActionResponse):
|
510
|
+
instruction.context.append(self.messages[i].content.to_dict())
|
511
|
+
else:
|
512
|
+
break
|
513
|
+
|
501
514
|
def to_chat_msgs(self, progress=None) -> list[dict]:
|
502
515
|
"""
|
503
516
|
Convert messages to chat format.
|
@@ -92,9 +92,11 @@ def format_text_item(item: Any) -> str:
|
|
92
92
|
for j in item:
|
93
93
|
if isinstance(j, dict):
|
94
94
|
for k, v in j.items():
|
95
|
-
|
95
|
+
if v is not None:
|
96
|
+
msg += f"- {k}: {v} \n\n"
|
96
97
|
else:
|
97
|
-
|
98
|
+
if j is not None:
|
99
|
+
msg += f"{j}\n"
|
98
100
|
return msg
|
99
101
|
|
100
102
|
|
@@ -33,6 +33,7 @@ from ..communication.types import (
|
|
33
33
|
ActionResponse,
|
34
34
|
AssistantResponse,
|
35
35
|
Instruction,
|
36
|
+
RoledMessage,
|
36
37
|
)
|
37
38
|
|
38
39
|
|
@@ -149,6 +150,8 @@ class BranchOperationMixin(ABC):
|
|
149
150
|
if auto_retry_parse is True:
|
150
151
|
operative.auto_retry_parse = True
|
151
152
|
|
153
|
+
if actions:
|
154
|
+
tools = tools or True
|
152
155
|
if invoke_actions and tools:
|
153
156
|
tool_schemas = self.get_tool_schema(tools)
|
154
157
|
|
@@ -275,7 +278,7 @@ class BranchOperationMixin(ABC):
|
|
275
278
|
**kwargs,
|
276
279
|
) -> tuple[Instruction, AssistantResponse]:
|
277
280
|
|
278
|
-
ins = self.msgs.create_instruction(
|
281
|
+
ins: Instruction = self.msgs.create_instruction(
|
279
282
|
instruction=instruction,
|
280
283
|
guidance=guidance,
|
281
284
|
context=context,
|
@@ -289,7 +292,57 @@ class BranchOperationMixin(ABC):
|
|
289
292
|
)
|
290
293
|
|
291
294
|
progress = progress or self.msgs.progress
|
292
|
-
messages
|
295
|
+
messages: list[RoledMessage] = [
|
296
|
+
self.msgs.messages[i] for i in progress
|
297
|
+
]
|
298
|
+
|
299
|
+
use_ins = None
|
300
|
+
if imodel.sequential_exchange:
|
301
|
+
_to_use = []
|
302
|
+
_action_responses: set[ActionResponse] = set()
|
303
|
+
|
304
|
+
for i in messages:
|
305
|
+
if isinstance(i, ActionResponse):
|
306
|
+
_action_responses.add(i)
|
307
|
+
if isinstance(i, AssistantResponse):
|
308
|
+
_to_use.append(i.model_copy())
|
309
|
+
if isinstance(i, Instruction):
|
310
|
+
if _action_responses:
|
311
|
+
j = i.model_copy()
|
312
|
+
d_ = [k.content.to_dict() for k in _action_responses]
|
313
|
+
for z in d_:
|
314
|
+
if z not in j.context:
|
315
|
+
j.context.append(z)
|
316
|
+
|
317
|
+
_to_use.append(j)
|
318
|
+
_action_responses = set()
|
319
|
+
else:
|
320
|
+
_to_use.append(i)
|
321
|
+
|
322
|
+
messages = _to_use
|
323
|
+
if _action_responses:
|
324
|
+
j = ins.model_copy()
|
325
|
+
d_ = [k.content.to_dict() for k in _action_responses]
|
326
|
+
for z in d_:
|
327
|
+
if z not in j.context:
|
328
|
+
j.context.append(z)
|
329
|
+
use_ins = j
|
330
|
+
|
331
|
+
if messages and len(messages) > 1:
|
332
|
+
_msgs = [messages[0]]
|
333
|
+
|
334
|
+
for i in messages[1:]:
|
335
|
+
if isinstance(i, AssistantResponse):
|
336
|
+
if isinstance(_msgs[-1], AssistantResponse):
|
337
|
+
_msgs[-1].response = (
|
338
|
+
f"{_msgs[-1].response}\n\n{i.response}"
|
339
|
+
)
|
340
|
+
else:
|
341
|
+
_msgs.append(i)
|
342
|
+
else:
|
343
|
+
if isinstance(_msgs[-1], AssistantResponse):
|
344
|
+
_msgs.append(i)
|
345
|
+
messages = _msgs
|
293
346
|
|
294
347
|
if self.msgs.system and "system" not in imodel.allowed_roles:
|
295
348
|
messages = [msg for msg in messages if msg.role != "system"]
|
@@ -312,9 +365,10 @@ class BranchOperationMixin(ABC):
|
|
312
365
|
first_instruction.guidance or ""
|
313
366
|
)
|
314
367
|
messages[0] = first_instruction
|
368
|
+
messages.append(use_ins or ins)
|
315
369
|
|
316
370
|
else:
|
317
|
-
messages.append(ins)
|
371
|
+
messages.append(use_ins or ins)
|
318
372
|
|
319
373
|
kwargs["messages"] = [i.chat_msg for i in messages]
|
320
374
|
imodel = imodel or self.imodel
|
@@ -331,6 +385,7 @@ class BranchOperationMixin(ABC):
|
|
331
385
|
sender=self,
|
332
386
|
recipient=self.user,
|
333
387
|
)
|
388
|
+
|
334
389
|
return ins, res
|
335
390
|
|
336
391
|
async def communicate(
|
@@ -346,7 +401,6 @@ class BranchOperationMixin(ABC):
|
|
346
401
|
imodel: iModel = None,
|
347
402
|
images: list = None,
|
348
403
|
image_detail: Literal["low", "high", "auto"] = None,
|
349
|
-
tools: str | FUNCTOOL | list[FUNCTOOL | str] | bool = None,
|
350
404
|
num_parse_retries: int = 0,
|
351
405
|
retry_imodel: iModel = None,
|
352
406
|
retry_kwargs: dict = {},
|
@@ -355,7 +409,6 @@ class BranchOperationMixin(ABC):
|
|
355
409
|
] = "return_value",
|
356
410
|
skip_validation: bool = False,
|
357
411
|
clear_messages: bool = False,
|
358
|
-
invoke_action: bool = True,
|
359
412
|
response_format: (
|
360
413
|
type[BaseModel] | BaseModel
|
361
414
|
) = None, # alias of request_model
|
@@ -380,10 +433,6 @@ class BranchOperationMixin(ABC):
|
|
380
433
|
)
|
381
434
|
num_parse_retries = 5
|
382
435
|
|
383
|
-
tool_schemas = None
|
384
|
-
if invoke_action and tools:
|
385
|
-
tool_schemas = self.get_tool_schema(tools)
|
386
|
-
|
387
436
|
ins, res = await self._invoke_imodel(
|
388
437
|
instruction=instruction,
|
389
438
|
guidance=guidance,
|
@@ -395,36 +444,14 @@ class BranchOperationMixin(ABC):
|
|
395
444
|
imodel=imodel,
|
396
445
|
images=images,
|
397
446
|
image_detail=image_detail,
|
398
|
-
tool_schemas=tool_schemas,
|
399
447
|
**kwargs,
|
400
448
|
)
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
action_request_models = None
|
405
|
-
action_response_models = None
|
449
|
+
self.msgs.add_message(instruction=ins)
|
450
|
+
self.msgs.add_message(assistant_response=res)
|
406
451
|
|
407
452
|
if skip_validation:
|
408
453
|
return res.response
|
409
454
|
|
410
|
-
if invoke_action and tools:
|
411
|
-
action_request_models = ActionRequestModel.create(res.response)
|
412
|
-
|
413
|
-
if action_request_models and invoke_action:
|
414
|
-
action_response_models = await alcall(
|
415
|
-
action_request_models,
|
416
|
-
self.invoke_action,
|
417
|
-
suppress_errors=True,
|
418
|
-
)
|
419
|
-
|
420
|
-
if action_request_models and not action_response_models:
|
421
|
-
for i in action_request_models:
|
422
|
-
await self.msgs.a_add_message(
|
423
|
-
action_request_model=i,
|
424
|
-
sender=self,
|
425
|
-
recipient=None,
|
426
|
-
)
|
427
|
-
|
428
455
|
_d = None
|
429
456
|
if request_fields is not None or request_model is not None:
|
430
457
|
parse_success = None
|
@@ -475,9 +502,12 @@ class BranchOperationMixin(ABC):
|
|
475
502
|
if _d and isinstance(_d, dict):
|
476
503
|
parse_success = True
|
477
504
|
if res not in self.msgs.messages:
|
478
|
-
|
479
|
-
|
480
|
-
)
|
505
|
+
if isinstance(
|
506
|
+
self.msgs.messages[-1], AssistantResponse
|
507
|
+
):
|
508
|
+
self.msgs.messages[-1].response = res.response
|
509
|
+
else:
|
510
|
+
self.msgs.add_message(assistant_response=res)
|
481
511
|
return _d
|
482
512
|
|
483
513
|
elif request_model:
|
@@ -495,9 +525,16 @@ class BranchOperationMixin(ABC):
|
|
495
525
|
_d = request_model.model_validate(_d)
|
496
526
|
parse_success = True
|
497
527
|
if res not in self.msgs.messages:
|
498
|
-
|
499
|
-
|
500
|
-
)
|
528
|
+
if isinstance(
|
529
|
+
self.msgs.messages[-1], AssistantResponse
|
530
|
+
):
|
531
|
+
self.msgs.messages[-1].response = (
|
532
|
+
res.response
|
533
|
+
)
|
534
|
+
else:
|
535
|
+
self.msgs.add_message(
|
536
|
+
assistant_response=res
|
537
|
+
)
|
501
538
|
return _d
|
502
539
|
except Exception as e:
|
503
540
|
logging.warning(
|
lionagi/core/session/session.py
CHANGED
@@ -128,9 +128,9 @@ class Session(Component):
|
|
128
128
|
branch: The branch to set as default or its identifier.
|
129
129
|
"""
|
130
130
|
branch = self.branches[branch]
|
131
|
-
if
|
132
|
-
|
133
|
-
|
131
|
+
if not isinstance(branch, Branch):
|
132
|
+
raise ValueError("Input value for branch is not a valid branch.")
|
133
|
+
self.default_branch = branch
|
134
134
|
|
135
135
|
def to_df(self, branches: ID.RefSeq = None) -> pd.DataFrame:
|
136
136
|
out = self.concat_messages(branches=branches)
|
@@ -4,6 +4,7 @@
|
|
4
4
|
|
5
5
|
from pathlib import Path
|
6
6
|
|
7
|
+
import yaml
|
7
8
|
from dotenv import load_dotenv
|
8
9
|
from pydantic import (
|
9
10
|
BaseModel,
|
@@ -33,12 +34,6 @@ price_config_file_name = path / "anthropic_price_data.yaml"
|
|
33
34
|
max_output_token_file_name = path / "anthropic_max_output_token_data.yaml"
|
34
35
|
|
35
36
|
|
36
|
-
class _ModuleImportClass:
|
37
|
-
from lionagi.libs.package.imports import check_import
|
38
|
-
|
39
|
-
yaml = check_import("yaml", pip_name="pyyaml")
|
40
|
-
|
41
|
-
|
42
37
|
class AnthropicModel(BaseModel):
|
43
38
|
model: str = Field(description="ID of the model to use.")
|
44
39
|
|
@@ -239,7 +234,7 @@ class AnthropicModel(BaseModel):
|
|
239
234
|
)
|
240
235
|
if estimated_output_len == 0:
|
241
236
|
with open(max_output_token_file_name) as file:
|
242
|
-
output_token_config =
|
237
|
+
output_token_config = yaml.safe_load(file)
|
243
238
|
estimated_output_len = output_token_config.get(self.model, 0)
|
244
239
|
self.estimated_output_len = estimated_output_len
|
245
240
|
|
@@ -261,13 +256,13 @@ class AnthropicModel(BaseModel):
|
|
261
256
|
num_of_input_tokens = self.text_token_calculator.calculate(input_text)
|
262
257
|
|
263
258
|
with open(price_config_file_name) as file:
|
264
|
-
price_config =
|
259
|
+
price_config = yaml.safe_load(file)
|
265
260
|
|
266
261
|
model_price_info_dict = price_config["model"][self.model]
|
267
262
|
estimated_price = (
|
268
263
|
model_price_info_dict["input_tokens"] * num_of_input_tokens
|
269
264
|
+ model_price_info_dict["output_tokens"]
|
270
265
|
* estimated_num_of_output_tokens
|
271
|
-
)
|
266
|
+
) / 1_000_000
|
272
267
|
|
273
268
|
return estimated_price
|
@@ -51,6 +51,11 @@ class AnthropicService(Service):
|
|
51
51
|
# Map model versions to their base models for shared rate limiting
|
52
52
|
shared_models = {
|
53
53
|
"claude-3-opus-20240229": "claude-3-opus",
|
54
|
+
"claude-3-sonnet-20241022": "claude-3-sonnet",
|
55
|
+
"claude-3-haiku-20241022": "claude-3-haiku",
|
56
|
+
"claude-3-opus-latest": "claude-3-opus",
|
57
|
+
"claude-3-sonnet-latest": "claude-3-sonnet",
|
58
|
+
"claude-3-haiku-latest": "claude-3-haiku",
|
54
59
|
"claude-3-sonnet-20240229": "claude-3-sonnet",
|
55
60
|
"claude-3-haiku-20240307": "claude-3-haiku",
|
56
61
|
}
|
@@ -115,3 +120,8 @@ class AnthropicService(Service):
|
|
115
120
|
@property
|
116
121
|
def allowed_roles(self):
|
117
122
|
return ["user", "assistant"]
|
123
|
+
|
124
|
+
@property
|
125
|
+
def sequential_exchange(self):
|
126
|
+
"""whether the service requires user/assistant exchange"""
|
127
|
+
return True
|
@@ -2,6 +2,11 @@
|
|
2
2
|
#
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
4
4
|
|
5
|
+
claude-3-5-sonnet-20241022: 8192 # Latest model
|
6
|
+
claude-3-5-haiku-20241022: 8192 # Latest model
|
5
7
|
claude-3-opus-20240229: 4096
|
6
8
|
claude-3-sonnet-20240229: 4096
|
7
9
|
claude-3-haiku-20240307: 4096
|
10
|
+
claude-2.1: 4096
|
11
|
+
claude-2.0: 4096
|
12
|
+
claude-instant-1.2: 4096
|
@@ -3,12 +3,32 @@
|
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
4
4
|
|
5
5
|
model:
|
6
|
+
# Latest Models (3.5 series)
|
7
|
+
claude-3-5-sonnet-20241022:
|
8
|
+
input_tokens: 3.0
|
9
|
+
output_tokens: 15.0
|
10
|
+
claude-3-5-haiku-20241022:
|
11
|
+
input_tokens: 0.80
|
12
|
+
output_tokens: 4.0
|
13
|
+
|
14
|
+
# Claude 3 Models
|
6
15
|
claude-3-opus-20240229:
|
7
|
-
input_tokens: 0
|
8
|
-
output_tokens: 0
|
16
|
+
input_tokens: 15.0
|
17
|
+
output_tokens: 75.0
|
9
18
|
claude-3-sonnet-20240229:
|
10
|
-
input_tokens: 0
|
11
|
-
output_tokens: 0
|
19
|
+
input_tokens: 3.0
|
20
|
+
output_tokens: 15.0
|
12
21
|
claude-3-haiku-20240307:
|
13
|
-
input_tokens: 0.
|
14
|
-
output_tokens:
|
22
|
+
input_tokens: 0.25
|
23
|
+
output_tokens: 1.25
|
24
|
+
|
25
|
+
# Legacy Models
|
26
|
+
claude-2.1:
|
27
|
+
input_tokens: 8.0
|
28
|
+
output_tokens: 24.0
|
29
|
+
claude-2.0:
|
30
|
+
input_tokens: 8.0
|
31
|
+
output_tokens: 24.0
|
32
|
+
claude-instant-1.2:
|
33
|
+
input_tokens: 0.8
|
34
|
+
output_tokens: 2.4
|
@@ -424,3 +424,12 @@ class OpenAIService(Service):
|
|
424
424
|
method="POST",
|
425
425
|
content_type="application/json",
|
426
426
|
)
|
427
|
+
|
428
|
+
@property
|
429
|
+
def allowed_roles(self):
|
430
|
+
return ["user", "assistant", "system"]
|
431
|
+
|
432
|
+
@property
|
433
|
+
def sequential_exchange(self):
|
434
|
+
"""whether the service requires user/assistant exchange"""
|
435
|
+
return False
|
@@ -1 +1 @@
|
|
1
|
-
__version__ = "1.0.
|
1
|
+
__version__ = "1.0.3"
|
@@ -1 +1 @@
|
|
1
|
-
__version__ = "1.0.
|
1
|
+
__version__ = "1.0.1"
|
@@ -148,6 +148,13 @@ async def alcall(
|
|
148
148
|
ucall(func, i, **kwargs), retry_timeout
|
149
149
|
)
|
150
150
|
return index, result
|
151
|
+
|
152
|
+
except InterruptedError:
|
153
|
+
return index, None
|
154
|
+
|
155
|
+
except asyncio.CancelledError:
|
156
|
+
return index, None
|
157
|
+
|
151
158
|
except TimeoutError as e:
|
152
159
|
raise TimeoutError(
|
153
160
|
f"{error_msg or ''} Timeout {retry_timeout} seconds "
|