lionagi 0.3.6__py3-none-any.whl → 0.3.8__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.
@@ -1,11 +1,11 @@
1
1
  """Component class, base building block in LionAGI."""
2
2
 
3
3
  import contextlib
4
- from abc import ABC
5
- from collections.abc import Sequence
6
4
  from functools import singledispatchmethod
7
- from typing import Any, Type, TypeAlias, TypeVar, Union
5
+ from typing import Any, TypeAlias, TypeVar, Union
8
6
 
7
+ import lionfuncs as ln
8
+ from lionabc import Observable
9
9
  from pandas import DataFrame, Series
10
10
  from pydantic import AliasChoices, BaseModel, Field, ValidationError
11
11
 
@@ -22,7 +22,13 @@ T = TypeVar("T")
22
22
  _init_class = {}
23
23
 
24
24
 
25
- class Element(BaseModel, ABC):
25
+ def change_dict_key(dict_: dict, old_key: str, new_key: str) -> None:
26
+ """Change a key in a dictionary."""
27
+ if old_key in dict_:
28
+ dict_[new_key] = dict_.pop(old_key)
29
+
30
+
31
+ class Element(BaseModel, Observable):
26
32
  """Base class for elements within the LionAGI system.
27
33
 
28
34
  Attributes:
@@ -31,15 +37,14 @@ class Element(BaseModel, ABC):
31
37
  """
32
38
 
33
39
  ln_id: str = Field(
34
- default_factory=SysUtil.create_id,
40
+ default_factory=SysUtil.id,
35
41
  title="ID",
36
- description="A 32-char unique hash identifier.",
37
42
  frozen=True,
38
43
  validation_alias=AliasChoices("node_id", "ID", "id"),
39
44
  )
40
45
 
41
46
  timestamp: str = Field(
42
- default_factory=lambda: SysUtil.get_timestamp(sep=None)[:-6],
47
+ default_factory=lambda: ln.time(type_="iso"),
43
48
  title="Creation Timestamp",
44
49
  description="The UTC timestamp of creation",
45
50
  frozen=True,
@@ -57,7 +62,7 @@ class Element(BaseModel, ABC):
57
62
  return True
58
63
 
59
64
 
60
- class Component(Element, ABC):
65
+ class Component(Element):
61
66
  """
62
67
  Represents a distinguishable, temporal entity in LionAGI.
63
68
 
@@ -195,17 +200,15 @@ class Component(Element, ABC):
195
200
  """Create a Component instance from a LlamaIndex object."""
196
201
  dict_ = obj.to_dict()
197
202
 
198
- SysUtil.change_dict_key(dict_, "text", "content")
203
+ change_dict_key(dict_, "text", "content")
199
204
  metadata = dict_.pop("metadata", {})
200
205
 
201
206
  for field in llama_meta_fields:
202
207
  metadata[field] = dict_.pop(field, None)
203
208
 
204
- SysUtil.change_dict_key(metadata, "class_name", "llama_index_class")
205
- SysUtil.change_dict_key(metadata, "id_", "llama_index_id")
206
- SysUtil.change_dict_key(
207
- metadata, "relationships", "llama_index_relationships"
208
- )
209
+ change_dict_key(metadata, "class_name", "llama_index_class")
210
+ change_dict_key(metadata, "id_", "llama_index_id")
211
+ change_dict_key(metadata, "relationships", "llama_index_relationships")
209
212
 
210
213
  dict_["metadata"] = metadata
211
214
  return cls.from_obj(dict_)
@@ -244,7 +247,7 @@ class Component(Element, ABC):
244
247
  @classmethod
245
248
  def _process_langchain_dict(cls, dict_: dict) -> dict:
246
249
  """Process a dictionary containing Langchain-specific data."""
247
- SysUtil.change_dict_key(dict_, "page_content", "content")
250
+ change_dict_key(dict_, "page_content", "content")
248
251
 
249
252
  metadata = dict_.pop("metadata", {})
250
253
  metadata.update(dict_.pop("kwargs", {}))
@@ -264,9 +267,9 @@ class Component(Element, ABC):
264
267
  if field in dict_:
265
268
  metadata[field] = dict_.pop(field)
266
269
 
267
- SysUtil.change_dict_key(metadata, "lc", "langchain")
268
- SysUtil.change_dict_key(metadata, "type", "lc_type")
269
- SysUtil.change_dict_key(metadata, "id", "lc_id")
270
+ change_dict_key(metadata, "lc", "langchain")
271
+ change_dict_key(metadata, "type", "lc_type")
272
+ change_dict_key(metadata, "id", "lc_id")
270
273
 
271
274
  extra_fields = {
272
275
  k: v for k, v in metadata.items() if k not in lc_meta_fields
@@ -298,9 +301,9 @@ class Component(Element, ABC):
298
301
  dict_["metadata"] = meta_
299
302
 
300
303
  if "ln_id" not in dict_:
301
- dict_["ln_id"] = meta_.pop("ln_id", SysUtil.create_id())
304
+ dict_["ln_id"] = meta_.pop("ln_id", SysUtil.id())
302
305
  if "timestamp" not in dict_:
303
- dict_["timestamp"] = SysUtil.get_timestamp(sep=None)[:-6]
306
+ dict_["timestamp"] = ln.time(type_="iso")
304
307
  if "metadata" not in dict_:
305
308
  dict_["metadata"] = {}
306
309
  if "extra_fields" not in dict_:
@@ -453,13 +456,13 @@ class Component(Element, ABC):
453
456
  ninsert(
454
457
  self.metadata,
455
458
  ["last_updated", name],
456
- SysUtil.get_timestamp(sep=None)[:-6],
459
+ ln.time(type_="iso")[:-6],
457
460
  )
458
461
  elif isinstance(a, tuple) and isinstance(a[0], int):
459
462
  nset(
460
463
  self.metadata,
461
464
  ["last_updated", name],
462
- SysUtil.get_timestamp(sep=None)[:-6],
465
+ ln.time(type_="iso")[:-6],
463
466
  )
464
467
 
465
468
  def _meta_pop(self, indices, default=...):
@@ -614,10 +617,4 @@ LionIDable: TypeAlias = Union[str, Element]
614
617
 
615
618
  def get_lion_id(item: LionIDable) -> str:
616
619
  """Get the Lion ID of an item."""
617
- if isinstance(item, Sequence) and len(item) == 1:
618
- item = item[0]
619
- if isinstance(item, str) and len(item) == 32:
620
- return item
621
- if getattr(item, "ln_id", None) is not None:
622
- return item.ln_id
623
- raise LionTypeError("Item must be a single LionIDable object.")
620
+ return SysUtil.get_id(item)
@@ -227,12 +227,6 @@ class Sendable(BaseModel, ABC):
227
227
  return value
228
228
 
229
229
  a = get_lion_id(value)
230
- if not isinstance(a, str) or len(a) != 32:
231
- raise LionTypeError(
232
- "Invalid sender or recipient value. "
233
- "Expected a valid node id or one of "
234
- "'system' or 'user'."
235
- )
236
230
  return a
237
231
 
238
232
 
@@ -1,7 +1,6 @@
1
1
  import contextlib
2
2
  from collections import deque
3
3
  from collections.abc import Mapping
4
- from typing import Tuple
5
4
 
6
5
  from pydantic import Field
7
6
 
@@ -1,6 +1,7 @@
1
1
  import asyncio
2
2
  import os
3
3
 
4
+ import lionfuncs as ln
4
5
  import numpy as np
5
6
  from dotenv import load_dotenv
6
7
 
@@ -91,8 +92,8 @@ class iModel:
91
92
  service (BaseService, optional): An instance of BaseService.
92
93
  **kwargs: Additional parameters for the model.
93
94
  """
94
- self.ln_id: str = SysUtil.create_id()
95
- self.timestamp: str = SysUtil.get_timestamp(sep=None)[:-6]
95
+ self.ln_id: str = SysUtil.id()
96
+ self.timestamp: str = ln.time(type_="iso")
96
97
  self.endpoint = endpoint
97
98
  self.allowed_parameters = allowed_parameters
98
99
  if isinstance(provider, type):
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  import asyncio
4
4
  from collections.abc import AsyncIterator, Callable, Iterable
5
5
  from functools import wraps
6
- from typing import Any, Generic, Type, TypeVar
6
+ from typing import Any, Generic, TypeVar
7
7
 
8
8
  from pydantic import Field, field_validator
9
9
 
@@ -1,9 +1,8 @@
1
1
  import contextlib
2
2
 
3
+ import lionfuncs as ln
3
4
  from pydantic import Field, field_validator
4
5
 
5
- from lionagi.libs import SysUtil
6
-
7
6
  from .abc import Element, ItemNotFoundError, LionIDable, Ordering, get_lion_id
8
7
  from .util import _validate_order
9
8
 
@@ -90,7 +89,7 @@ class Progression(Element, Ordering):
90
89
  """Remove the next occurrence of an item from the progression."""
91
90
  if item in self:
92
91
  item = self._validate_order(item)
93
- l_ = SysUtil.create_copy(self.order)
92
+ l_ = ln.copy(self.order)
94
93
 
95
94
  with contextlib.suppress(Exception):
96
95
  for i in item:
@@ -143,7 +142,7 @@ class Progression(Element, Ordering):
143
142
  def __radd__(self, other):
144
143
  if not isinstance(other, Progression):
145
144
  _copy = self.copy()
146
- l_ = SysUtil.create_copy(_copy.order)
145
+ l_ = ln.copy(_copy.order)
147
146
  l_.insert(0, get_lion_id(other))
148
147
  _copy.order = l_
149
148
  return _copy
@@ -190,7 +189,7 @@ class Progression(Element, Ordering):
190
189
 
191
190
  def __list__(self):
192
191
  """Return a list representation of the progression."""
193
- return SysUtil.create_copy(self.order)
192
+ return ln.copy(self.order)
194
193
 
195
194
  def __reversed__(self):
196
195
  """Return a reversed progression."""
@@ -1,93 +1,3 @@
1
- from __future__ import annotations
1
+ from lionagi.operations.select import select
2
2
 
3
- from collections.abc import Callable
4
- from enum import Enum
5
-
6
- from lionfuncs import choose_most_similar
7
- from pydantic import BaseModel
8
-
9
- from lionagi.core.director.models import ReasonModel
10
- from lionagi.core.session.branch import Branch
11
-
12
- from .utils import is_enum
13
-
14
- PROMPT = "Please select up to {max_num_selections} items from the following list {choices}. Provide the selection(s), and no comments from you"
15
-
16
-
17
- class SelectionModel(BaseModel):
18
- selected: list[str | Enum]
19
-
20
-
21
- class ReasonSelectionModel(BaseModel):
22
- selected: list[str | Enum]
23
- reason: ReasonModel
24
-
25
-
26
- async def select(
27
- choices: list[str] | type[Enum],
28
- max_num_selections: int = 1,
29
- instruction=None,
30
- context=None,
31
- system=None,
32
- sender=None,
33
- recipient=None,
34
- reason: bool = False,
35
- return_enum: bool = False,
36
- enum_parser: Callable = None, # parse the model string response to appropriate type
37
- branch: Branch = None,
38
- return_pydantic_model=False,
39
- **kwargs, # additional chat arguments
40
- ):
41
- selections = []
42
- if return_enum and not is_enum(choices):
43
- raise ValueError("return_enum can only be True if choices is an Enum")
44
-
45
- if is_enum(choices):
46
- selections = [selection.value for selection in choices]
47
- else:
48
- selections = choices
49
-
50
- prompt = PROMPT.format(
51
- max_num_selections=max_num_selections, choices=selections
52
- )
53
-
54
- if instruction:
55
- prompt = f"{instruction}\n\n{prompt} \n\n "
56
-
57
- branch = branch or Branch()
58
- response: SelectionModel | ReasonSelectionModel | str = await branch.chat(
59
- instruction=prompt,
60
- context=context,
61
- system=system,
62
- sender=sender,
63
- recipient=recipient,
64
- pydantic_model=SelectionModel if not reason else ReasonSelectionModel,
65
- return_pydantic_model=True,
66
- **kwargs,
67
- )
68
-
69
- selected = response
70
- if isinstance(response, SelectionModel | ReasonSelectionModel):
71
- selected = response.selected
72
- selected = [selected] if not isinstance(selected, list) else selected
73
- corrected_selections = [
74
- choose_most_similar(selection, selections) for selection in selected
75
- ]
76
-
77
- if return_enum:
78
- out = []
79
- if not enum_parser:
80
- enum_parser = lambda x: x
81
- for selection in corrected_selections:
82
- selection = enum_parser(selection)
83
- for member in choices.__members__.values():
84
- if member.value == selection:
85
- out.append(member)
86
- corrected_selections = out
87
-
88
- if return_pydantic_model:
89
- if not isinstance(response, SelectionModel | ReasonSelectionModel):
90
- return SelectionModel(selected=corrected_selections)
91
- response.selected = corrected_selections
92
- return response
93
- return corrected_selections
3
+ __all__ = ["select"]
@@ -1,4 +1,4 @@
1
- from lionfuncs import choose_most_similar
1
+ from lionfuncs import string_similarity
2
2
 
3
3
  from lionagi.core.rule.base import Rule
4
4
 
@@ -45,4 +45,4 @@ class ChoiceRule(Rule):
45
45
  Returns:
46
46
  str: The most similar value from the set of predefined choices.
47
47
  """
48
- return choose_most_similar(value, self.keys)
48
+ return string_similarity(value, self.keys, choose_most_similar=True)
@@ -2,9 +2,9 @@ import asyncio
2
2
  import contextlib
3
3
  import re
4
4
  from abc import ABC
5
- from typing import Any, Optional
5
+ from typing import Any
6
6
 
7
- from lionfuncs import extract_json_block, to_dict, validate_mapping
7
+ from lionfuncs import extract_block, to_dict, validate_mapping
8
8
 
9
9
  from lionagi.core.collections.abc import ActionError
10
10
  from lionagi.core.message import ActionRequest, ActionResponse, Instruction
@@ -1156,7 +1156,7 @@ class DirectiveMixin(ABC):
1156
1156
  return to_dict(out_, fuzzy_parse=True)
1157
1157
 
1158
1158
  with contextlib.suppress(Exception):
1159
- return extract_json_block(out_)
1159
+ return extract_block(out_)
1160
1160
 
1161
1161
  with contextlib.suppress(Exception):
1162
1162
  match = re.search(r"```json\n({.*?})\n```", out_, re.DOTALL)
File without changes
File without changes