lionagi 0.0.201__py3-none-any.whl → 0.0.204__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
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
+