lionagi 0.0.201__py3-none-any.whl → 0.0.204__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.
Files changed (53) hide show
  1. lionagi/_services/anthropic.py +79 -1
  2. lionagi/_services/base_service.py +1 -1
  3. lionagi/_services/services.py +61 -25
  4. lionagi/_services/transformers.py +46 -0
  5. lionagi/agents/__init__.py +0 -0
  6. lionagi/configs/oai_configs.py +1 -1
  7. lionagi/configs/openrouter_configs.py +1 -1
  8. lionagi/core/__init__.py +3 -7
  9. lionagi/core/branch/__init__.py +0 -0
  10. lionagi/core/branch/branch.py +589 -0
  11. lionagi/core/branch/branch_manager.py +139 -0
  12. lionagi/core/branch/cluster.py +1 -0
  13. lionagi/core/branch/conversation.py +484 -0
  14. lionagi/core/core_util.py +59 -0
  15. lionagi/core/flow/__init__.py +0 -0
  16. lionagi/core/flow/flow.py +19 -0
  17. lionagi/core/instruction_set/__init__.py +0 -0
  18. lionagi/core/instruction_set/instruction_set.py +343 -0
  19. lionagi/core/messages/__init__.py +0 -0
  20. lionagi/core/messages/messages.py +176 -0
  21. lionagi/core/sessions/__init__.py +0 -0
  22. lionagi/core/sessions/session.py +428 -0
  23. lionagi/models/__init__.py +0 -0
  24. lionagi/models/base_model.py +0 -0
  25. lionagi/models/imodel.py +53 -0
  26. lionagi/schema/data_logger.py +75 -155
  27. lionagi/tests/test_utils/test_call_util.py +658 -657
  28. lionagi/tools/tool_manager.py +121 -188
  29. lionagi/utils/__init__.py +5 -10
  30. lionagi/utils/call_util.py +667 -585
  31. lionagi/utils/io_util.py +3 -0
  32. lionagi/utils/nested_util.py +17 -211
  33. lionagi/utils/pd_util.py +57 -0
  34. lionagi/utils/sys_util.py +220 -184
  35. lionagi/utils/url_util.py +55 -0
  36. lionagi/version.py +1 -1
  37. {lionagi-0.0.201.dist-info → lionagi-0.0.204.dist-info}/METADATA +12 -8
  38. {lionagi-0.0.201.dist-info → lionagi-0.0.204.dist-info}/RECORD +47 -32
  39. lionagi/core/branch.py +0 -193
  40. lionagi/core/conversation.py +0 -341
  41. lionagi/core/flow.py +0 -8
  42. lionagi/core/instruction_set.py +0 -150
  43. lionagi/core/messages.py +0 -243
  44. lionagi/core/sessions.py +0 -474
  45. /lionagi/{tools → agents}/planner.py +0 -0
  46. /lionagi/{tools → agents}/prompter.py +0 -0
  47. /lionagi/{tools → agents}/scorer.py +0 -0
  48. /lionagi/{tools → agents}/summarizer.py +0 -0
  49. /lionagi/{tools → agents}/validator.py +0 -0
  50. /lionagi/core/{flow_util.py → flow/flow_util.py} +0 -0
  51. {lionagi-0.0.201.dist-info → lionagi-0.0.204.dist-info}/LICENSE +0 -0
  52. {lionagi-0.0.201.dist-info → lionagi-0.0.204.dist-info}/WHEEL +0 -0
  53. {lionagi-0.0.201.dist-info → lionagi-0.0.204.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,428 @@
1
+ import pandas as pd
2
+ from typing import Any, List, Union, Dict, Optional, Callable, Tuple
3
+ from dotenv import load_dotenv
4
+
5
+ from lionagi.schema import Tool
6
+ from lionagi._services.oai import OpenAIService
7
+ from ..messages.messages import System, Instruction
8
+ from ..branch.branch import Branch
9
+ from ..branch.branch_manager import BranchManager
10
+
11
+
12
+ load_dotenv()
13
+ OAIService = OpenAIService()
14
+
15
+ class Session:
16
+ """
17
+ Represents a session with conversation branches, tool management, and logging.
18
+
19
+ This class encapsulates the management of different conversation branches, each with its own
20
+ messages, instruction sets, and tools. It also handles logging and interactions with an external service.
21
+
22
+ Attributes:
23
+ branches (Dict[str, Branch]): A dictionary of conversation branches.
24
+ default_branch (Branch): The default branch for the session.
25
+ default_branch_name (str): The name of the default branch.
26
+ llmconfig (Dict[str, Any]): Configuration settings for the language model.
27
+ logger_ (DataLogger): Logger for session data.
28
+ service (OpenAIService): Service used for handling chat completions and other operations.
29
+ """
30
+ def __init__(
31
+ self,
32
+ system: Optional[Union[str, System]] = None,
33
+ sender: Optional[str] = None,
34
+ dir: Optional[str] = None,
35
+ llmconfig: Optional[Dict[str, Any]] = None,
36
+ service: OpenAIService = OAIService,
37
+ branches: Optional[Dict[str, Branch]] = None,
38
+ default_branch: Optional[Branch] = None,
39
+ default_branch_name: str = 'main',
40
+ ):
41
+ """
42
+ Initialize a Session object.
43
+
44
+ Args:
45
+ system (Union[str, System]): Initial system message or System object for the default branch.
46
+ dir (str, optional): Directory path for storing logs.
47
+ llmconfig (Dict[str, Any], optional): Configuration settings for the language model.
48
+ service (OpenAIService, optional): Service used for handling chat completions and other operations.
49
+ branches (Dict[str, Branch], optional): Pre-existing branches to initialize in the session.
50
+ default_branch (Branch, optional): Default branch for the session.
51
+ default_branch_name (str, optional): Name of the default branch, defaults to 'main'.
52
+ """
53
+
54
+ self.branches = branches if isinstance(branches, dict) else {}
55
+ self.default_branch = default_branch if default_branch else Branch(name=default_branch_name, service=service, llmconfig=llmconfig)
56
+ self.default_branch_name = default_branch_name
57
+ if system:
58
+ self.default_branch.add_message(system=system, sender=sender)
59
+ if self.branches:
60
+ if self.default_branch_name not in self.branches.keys():
61
+ raise ValueError('default branch name is not in imported branches')
62
+ if self.default_branch is not self.branches[self.default_branch_name]:
63
+ raise ValueError(f'default branch does not match Branch object under {self.default_branch_name}')
64
+ if not self.branches:
65
+ self.branches[self.default_branch_name] = self.default_branch
66
+ if dir:
67
+ self.default_branch.dir = dir
68
+
69
+ self.branch_manager = BranchManager(self.branches)
70
+
71
+ def new_branch(
72
+ self,
73
+ branch_name: str,
74
+ dir: Optional[str] = None,
75
+ messages: Optional[pd.DataFrame] = None,
76
+ tools: Optional[Union[Tool, List[Tool]]] = None,
77
+ system: Optional[Union[str, System]] = None,
78
+ sender: Optional[str] = None,
79
+ service: Optional[OpenAIService] = None,
80
+ llmconfig: Optional[Dict] = None,
81
+ ) -> None:
82
+ """
83
+ Create a new branch in the session.
84
+
85
+ Args:
86
+ branch_name (str): Name of the new branch.
87
+ dir (str, optional): Directory path for storing logs.
88
+ messages (Optional[pd.DataFrame]): A DataFrame containing conversation messages.
89
+ system (Union[str, System], optional): Initial system message or System object for the new branch.
90
+ tools (Optional[Union[Tool, List[Tool]]], optional): Tools to register with the new branch.
91
+ sender (Optional[str], optional): Sender of the initial system message.
92
+ service (OpenAIService, optional): Service used for the new branch if different from the session's service.
93
+ llmconfig (Dict[str, Any], optional): Configuration settings for the language model.
94
+
95
+ Raises:
96
+ ValueError: If the branch name already exists in the session.
97
+ """
98
+ if branch_name in self.branches.keys():
99
+ raise ValueError(f'Invalid new branch name {branch_name}. Already existed.')
100
+ new_ = Branch(name=branch_name, dir=dir, messages=messages, service=service, llmconfig=llmconfig)
101
+ if system:
102
+ new_.add_message(system=system, sender=sender)
103
+ if tools:
104
+ new_.register_tools(tools=tools)
105
+ self.branches[branch_name] = new_
106
+
107
+ self.branch_manager.sources[branch_name] = new_
108
+ self.branch_manager.requests[branch_name] = {}
109
+
110
+ def get_branch(
111
+ self,
112
+ branch: Optional[Union[Branch, str]] = None,
113
+ get_name: bool = False
114
+ ) -> Union[Branch, Tuple[Branch, str]]:
115
+ """
116
+ Retrieve a branch from the session.
117
+
118
+ Args:
119
+ branch (Optional[Union[Branch, str]], optional): The branch or its name to retrieve.
120
+ Defaults to the default branch if not specified.
121
+ get_name (bool, optional): If True, returns the name of the branch along with the branch object.
122
+
123
+ Returns:
124
+ Union[Branch, Tuple[Branch, str]]: The branch object or a tuple of the branch object and its name.
125
+
126
+ Raises:
127
+ ValueError: If the branch does not exist in the session.
128
+ """
129
+ if isinstance(branch, str):
130
+ if branch not in self.branches.keys():
131
+ raise ValueError(f'Invalid branch name {branch}. Not exist.')
132
+ else:
133
+ if get_name:
134
+ return self.branches[branch], branch
135
+ return self.branches[branch]
136
+
137
+ elif isinstance(branch, Branch) and branch in self.branches.values():
138
+ if get_name:
139
+ return branch, [key for key, value in self.branches.items() if value == branch][0]
140
+ return branch
141
+
142
+ elif branch is None:
143
+ if get_name:
144
+ return self.default_branch, self.default_branch_name
145
+ return self.default_branch
146
+
147
+ else:
148
+ raise ValueError(f'Invalid branch input {branch}.')
149
+
150
+ def change_default(self, branch: Union[str, Branch]) -> None:
151
+ """
152
+ Change the default branch of the session.
153
+
154
+ Args:
155
+ branch (Union[str, Branch]): The branch or its name to set as the new default.
156
+ """
157
+ branch_, name_ = self.get_branch(branch, get_name=True)
158
+ self.default_branch = branch_
159
+ self.default_branch_name = name_
160
+
161
+ def delete_branch(self, branch: Union[Branch, str], verbose: bool = True) -> bool:
162
+ """
163
+ Delete a branch from the session.
164
+
165
+ Args:
166
+ branch (Union[Branch, str]): The branch object or its name to be deleted.
167
+ verbose (bool, optional): If True, prints a confirmation message.
168
+
169
+ Returns:
170
+ bool: True if the branch is successfully deleted, False otherwise.
171
+
172
+ Raises:
173
+ ValueError: If trying to delete the current default branch.
174
+ """
175
+ _, branch_name = self.get_branch(branch, get_name=True)
176
+
177
+ if branch_name == self.default_branch_name:
178
+ raise ValueError(
179
+ f'{branch_name} is the current default branch, please switch to another branch before delete it.'
180
+ )
181
+ else:
182
+ self.branches.pop(branch_name)
183
+ # self.branch_manager.sources.pop(branch_name)
184
+ self.branch_manager.requests.pop(branch_name)
185
+ if verbose:
186
+ print(f'Branch {branch_name} is deleted.')
187
+ return True
188
+
189
+ def merge_branch(
190
+ self,
191
+ from_: Union[str, Branch],
192
+ to_: Union[str, Branch],
193
+ update: bool = True,
194
+ del_: bool = False
195
+ ) -> None:
196
+ """
197
+ Merge one branch into another within the session.
198
+
199
+ Args:
200
+ from_ (Union[str, Branch]): The branch or its name to merge from.
201
+ to_ (Union[str, Branch]): The branch or its name to merge into.
202
+ update (bool, optional): If True, updates the target branch's system message to be same as `from_`.
203
+ del_ (bool, optional): If True, deletes the 'from' branch after merging.
204
+
205
+ Raises:
206
+ ValueError: If the branch does not exist in the session.
207
+ """
208
+ from_ = self.get_branch(branch=from_)
209
+ to_, to_name = self.get_branch(branch=to_, get_name=True)
210
+ to_.merge_branch(from_, update=update)
211
+
212
+ if del_:
213
+ if from_ == self.default_branch:
214
+ self.default_branch_name = to_name
215
+ self.default_branch = to_
216
+ self.delete_branch(from_, verbose=False)
217
+
218
+ async def chat(
219
+ self,
220
+ instruction: Union[Instruction, str],
221
+ to_: Optional[Union[Branch, str]] = None,
222
+ system: Optional[Union[System, str, Dict]] = None,
223
+ context: Optional[Any] = None,
224
+ out: bool = True,
225
+ sender: Optional[str] = None,
226
+ invoke: bool = True,
227
+ tools: Union[bool, Tool, List[Tool], str, List[str]] = False,
228
+ fallback: Optional[Callable] = None,
229
+ fallback_kwargs: Dict = {},
230
+ **kwargs
231
+ ) -> None:
232
+ """
233
+ Initiate a chat with the specified branch using an instruction.
234
+
235
+ Args:
236
+ instruction (Union[Instruction, str]): The instruction or message to send.
237
+ to_ (Optional[Union[Branch, str]], optional): The target branch or its name. Default is the main branch.
238
+ system (Optional[Union[System, str, Dict]], optional): System message or data to use.
239
+ context (Optional[Any], optional): Additional context for the chat.
240
+ out (bool, optional): If True, sends the output message.
241
+ sender (Optional[str], optional): The sender's name.
242
+ invoke (bool, optional): If True, invokes tool processing.
243
+ tools (Union[bool, Tool, List[Tool], str, List[str]], optional): Tools to be used or not used.
244
+ fallback (Optional[Callable], optional): Fallback function to call in case of an exception.
245
+ fallback_kwargs (Dict, optional): Keyword arguments for the fallback function.
246
+ **kwargs: Additional keyword arguments.
247
+
248
+ Raises:
249
+ Exception: If an exception occurs in the chat process and no fallback is provided.
250
+ """
251
+ branch_ = self.get_branch(to_)
252
+ if fallback:
253
+ try:
254
+ return await branch_.chat(
255
+ instruction=instruction, system=system, context=context,
256
+ out=out, sender=sender, invoke=invoke, tools=tools, **kwargs
257
+ )
258
+ except:
259
+ return fallback(**fallback_kwargs)
260
+
261
+ return await branch_.chat(
262
+ instruction=instruction, system=system, context=context,
263
+ out=out, sender=sender, invoke=invoke, tools=tools, **kwargs)
264
+
265
+
266
+ async def auto_followup(
267
+ self,
268
+ instruction: Union[Instruction, str],
269
+ to_: Optional[Union[Branch, str]] = None,
270
+ num: int = 3,
271
+ tools: Union[bool, Tool, List[Tool], str, List[str], List[Dict]] = False,
272
+ fallback: Optional[Callable] = None,
273
+ fallback_kwargs: Dict = {},
274
+ **kwargs
275
+ ) -> None:
276
+ """
277
+ Automatically follow up on a chat conversation within a branch with multiple messages.
278
+
279
+ Args:
280
+ instruction (Union[Instruction, str]): The initial instruction or message to send.
281
+ to_ (Optional[Union[Branch, str]], optional): The target branch or its name. Default is the main branch.
282
+ num (int, optional): The number of follow-up messages to send.
283
+ tools (Union[bool, Tool, List[Tool], str, List[str], List[Dict]], optional): Tools to be used or not used.
284
+ fallback (Optional[Callable], optional): Fallback function to call in case of an exception.
285
+ fallback_kwargs (Dict, optional): Keyword arguments for the fallback function.
286
+ **kwargs: Additional keyword arguments.
287
+
288
+ Raises:
289
+ Exception: If an exception occurs in the auto-followup process and no fallback is provided.
290
+ """
291
+
292
+ branch_ = self.get_branch(to_)
293
+ if fallback:
294
+ try:
295
+ return await branch_.auto_followup(
296
+ instruction=instruction, num=num, tools=tools,**kwargs
297
+ )
298
+ except:
299
+ return fallback(**fallback_kwargs)
300
+
301
+ return await branch_.auto_followup(
302
+ instruction=instruction, num=num, tools=tools,**kwargs
303
+ )
304
+
305
+ def change_first_system_message(self, system: Union[System, str]) -> None:
306
+ """
307
+ Change the system message of the current default branch.
308
+
309
+ Args:
310
+ system (Union[System, str]): The new system message or a System object.
311
+ """
312
+ self.default_branch.change_first_system_message(system)
313
+
314
+ def collect(self, from_: Union[str, Branch, List[str], List[Branch]] = None):
315
+ """
316
+ Collect requests from specified branches or all branches if none specified.
317
+
318
+ Args:
319
+ from_ (Union[str, Branch, List[str], List[Branch]], optional): The source branch(es) from which to collect requests.
320
+ If None, data is collected from all branches. Can be a single branch or a list of branches.
321
+ """
322
+ if from_ is None:
323
+ for branch in self.branches.keys():
324
+ self.branch_manager.collect(branch)
325
+ else:
326
+ if not isinstance(from_, list):
327
+ from_ = [from_]
328
+ for branch in from_:
329
+ if isinstance(branch, Branch):
330
+ branch = branch.name
331
+ if isinstance(branch, str):
332
+ self.branch_manager.collect(branch)
333
+
334
+ def send(self, to_: Union[str, Branch, List[str], List[Branch]] = None):
335
+ """
336
+ Collect requests from specified branches or all branches if none specified.
337
+
338
+ Args:
339
+ to_ (Union[str, Branch, List[str], List[Branch]], optional): The target branch(es) to which to send requests.
340
+ If None, requests are sent to all branches. Can be a single branch or a list of branches.
341
+ """
342
+ if to_ is None:
343
+ for branch in self.branches.keys():
344
+ self.branch_manager.send(branch)
345
+ else:
346
+ if not isinstance(to_, list):
347
+ to_ = [to_]
348
+ for branch in to_:
349
+ if isinstance(branch, Branch):
350
+ branch = branch.name
351
+ if isinstance(branch, str):
352
+ self.branch_manager.send(branch)
353
+
354
+ def collect_send_all(self, receive_all=False):
355
+ """
356
+ Collect and send requests across all branches, with an option to invoke receive_all on each branch.
357
+
358
+ Args:
359
+ receive_all (bool, optional): If True, triggers the receive_all method on each branch after sending requests.
360
+ """
361
+ self.collect()
362
+ self.send()
363
+ if receive_all:
364
+ for branch in self.branches.values():
365
+ branch.receive_all()
366
+
367
+ def register_tools(self, tools: Union[Tool, List[Tool]]) -> None:
368
+ """
369
+ Registers one or more tools to the current active branch.
370
+
371
+ Args:
372
+ tools (Union[Tool, List[Tool]]): The tool or list of tools to register.
373
+ """
374
+ self.default_branch.register_tools(tools)
375
+
376
+ def delete_tool(self, name: str) -> bool:
377
+ """
378
+ Deletes a tool from the current active branch.
379
+
380
+ Args:
381
+ name (str): The name of the tool to delete.
382
+
383
+ Returns:
384
+ bool: True if the tool is deleted, False otherwise.
385
+ """
386
+ return self.default_branch.delete_tool(name)
387
+
388
+ @property
389
+ def describe(self) -> Dict[str, Any]:
390
+ """
391
+ Generates a report of the current active branch.
392
+
393
+ Returns:
394
+ Dict[str, Any]: The report of the current active branch.
395
+ """
396
+ return self.default_branch.describe
397
+
398
+ @property
399
+ def messages(self) -> pd.DataFrame:
400
+ """
401
+ Get the DataFrame containing conversation messages.
402
+
403
+ Returns:
404
+ pd.DataFrame: A DataFrame containing conversation messages.
405
+ """
406
+ return self.default_branch.messages
407
+
408
+ # def add_instruction_set(self, name: str, instruction_set: InstructionSet) -> None:
409
+ # """
410
+ # Adds an instruction set to the current active branch.
411
+ #
412
+ # Args:
413
+ # name (str): The name of the instruction set.
414
+ # instruction_set (InstructionSet): The instruction set to add.
415
+ # """
416
+ # self.default_branch.add_instruction_set(name, instruction_set)
417
+ #
418
+ # def remove_instruction_set(self, name: str) -> bool:
419
+ # """
420
+ # Removes an instruction set from the current active branch.
421
+ #
422
+ # Args:
423
+ # name (str): The name of the instruction set to remove.
424
+ #
425
+ # Returns:
426
+ # bool: True if the instruction set is removed, False otherwise.
427
+ # """
428
+ # return self.default_branch.remove_instruction_set(name)
File without changes
File without changes
@@ -0,0 +1,53 @@
1
+ # from ..configs import oai_schema
2
+
3
+ # class BaseIntelligentModel:
4
+
5
+ # def __init__(
6
+ # self,
7
+ # service=None,
8
+ # default_config=oai_schema['chat']['config'],
9
+ # **kwargs
10
+ # ) -> None:
11
+ # # kwargs are the individual parameters that the model can take
12
+ # # different for different models
13
+ # self.service=service,
14
+ # self.config = {**default_config, **kwargs},
15
+
16
+ # async def __call__(
17
+ # self,
18
+ # payload,
19
+ # service=None,
20
+ # endpoint_='chat/completions',
21
+ # method='post'
22
+ # ):
23
+ # service = service or self.service
24
+ # return await service.serve(
25
+ # payload=payload, endpoint_=endpoint_, method=method
26
+ # )
27
+
28
+ # def set_service(self, service):
29
+ # self.service = service
30
+
31
+ # def set_config(self, config):
32
+ # self.config=config
33
+
34
+ # def change_model(self, model):
35
+ # self.config['model'] = model
36
+
37
+ # def change_temperature(self, temperature):
38
+ # self.config['temperature'] = temperature
39
+
40
+ # def revert_to_default_config(self):
41
+ # self.config = oai_schema['chat']['config']
42
+
43
+ # def modify_config(self, **kwargs):
44
+ # self.config = {**self.config, **kwargs}
45
+
46
+
47
+ # class IModel(BaseIntelligentModel):
48
+
49
+ # def __init__(
50
+ # self, service=None, default_model_kwargs=None, **kwargs
51
+ # ) -> None:
52
+ # super().__init__(service, default_model_kwargs, **kwargs)
53
+