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
lionagi/core/sessions.py DELETED
@@ -1,474 +0,0 @@
1
- import json
2
- from typing import Any, Union, List, Dict, Union, Optional
3
- from dotenv import load_dotenv
4
-
5
- from ..configs.oai_configs import oai_schema
6
- from ..utils.nested_util import get_flattened_keys
7
- from ..utils.call_util import lcall, alcall
8
- from ..schema import DataLogger, Tool
9
- from .._services.oai import OpenAIService
10
- from .messages import System, Instruction, Response
11
- from .instruction_set import InstructionSet
12
- from .branch import Branch
13
-
14
-
15
- load_dotenv()
16
- OAIService = OpenAIService()
17
-
18
- class Session:
19
- """Manages a session with an AI service, handling branching, merging, and messaging.
20
-
21
- Attributes:
22
- llmconfig (Dict[str, Any]): Configuration for the language model.
23
- system, (Union[Dict, Any]): system message
24
- logger_ (DataLogger): Logger for the session data.
25
- service (OpenAIService): The AI service to interact with.
26
- branches (Dict[str, Branch]): Branches for different conversation threads.
27
- current_branch_name (str): The name of the active branch.
28
- current_branch (Branch): The active branch.
29
- latest_response (Response): The latest response received from the AI service.
30
- """
31
-
32
-
33
- def __init__(
34
- self,
35
- system: str,
36
- dir: str = None,
37
- llmconfig: Dict[str, Any] = oai_schema["chat/completions"]["config"],
38
- service: OpenAIService = OAIService,
39
- ):
40
- """Initializes the session with system information, logging directory, and configuration.
41
-
42
- Args:
43
- system: System information to initialize the session with.
44
- dir: Directory to store session logs.
45
- llmconfig: Configuration for the language model.
46
- service: The AI service to interact with.
47
- """
48
- self.llmconfig = llmconfig
49
- self.logger_ = DataLogger(dir=dir)
50
- self.service = service
51
- self.branches = {"main": Branch(System(system))}
52
- self.current_branch_name = 'main'
53
- self.current_branch = self.branches[self.current_branch_name]
54
- self.latest_response = None
55
-
56
- def new_branch(self, name: str, from_: str) -> None:
57
- """Creates a new branch based on an existing one.
58
-
59
- Args:
60
- name: The name of the new branch.
61
- from_: The name of the branch to clone from.
62
-
63
- Raises:
64
- ValueError: If the new branch name already exists or the source branch does not exist.
65
- """
66
- if name in self.branches.keys():
67
- raise ValueError(f'Invalid new branch name {name}. Already existed.')
68
- if from_ not in self.branches.keys():
69
- raise ValueError(f'Invalid source branch name {from_}. Not exist.')
70
-
71
- self.branches[name] = self.branches[from_].clone()
72
-
73
- def switch_branch(self, name: str) -> None:
74
- """Switches the current active branch to the specified branch.
75
-
76
- Args:
77
- name: The name of the branch to switch to.
78
-
79
- Raises:
80
- ValueError: If the specified branch does not exist.
81
- """
82
- if name not in self.branches.keys():
83
- raise ValueError(f'Invalid source branch name {name}. Not exist.')
84
- self.current_branch_name = name
85
- self.current_branch = self.branches[name]
86
-
87
- def merge_branch(
88
- self, from_: str, to_: str, update: bool = True, if_delete: bool = False
89
- ) -> None:
90
- """Merges one branch into another.
91
-
92
- Args:
93
- from_: The name of the branch to merge from.
94
- to_: The name of the branch to merge into.
95
- update: Whether to update the target branch with the source branch's data.
96
- if_delete: Whether to delete the source branch after merging.
97
-
98
- Raises:
99
- ValueError: If either the source or target branch name does not exist.
100
- """
101
- if from_ not in self.branches.keys():
102
- raise ValueError(f'Invalid source branch name {from_}. Not exist.')
103
- if to_ not in self.branches.keys():
104
- raise ValueError(f'Invalid target branch name {from_}. Not exist.')
105
-
106
- self.branches[to_].merge(self.branches[from_], update)
107
- if if_delete:
108
- if from_ == self.current_branch_name:
109
- self.current_branch_name = to_
110
- self.current_branch = self.branches[to_]
111
- self.branches.pop(from_)
112
-
113
- def delete_branch(self, name: str, verbose=True) -> bool:
114
- """Deletes the specified branch.
115
-
116
- Args:
117
- name: The name of the branch to delete.
118
-
119
- Returns:
120
- bool: True if the branch is deleted, False otherwise.
121
-
122
- Raises:
123
- ValueError: If the specified branch is currently active.
124
- """
125
- if name == self.current_branch_name:
126
- raise ValueError(f'{name} is the current active branch, please switch to another branch before delete it.')
127
- if name not in self.branches.keys():
128
- return False
129
- else:
130
- self.branches.pop(name)
131
- if verbose:
132
- print(f'Branch {name} is deleted.')
133
- return True
134
-
135
- async def call_chatcompletion(self, branch: Union[str, Branch], **kwargs):
136
- """Calls the AI service to get a completion for the current conversation.
137
-
138
- Args:
139
- branch: Branch to run.
140
- **kwargs: Additional keyword arguments to pass to the AI service.
141
-
142
- Raises:
143
- NotImplementedError: If the AI service does not return a valid response.
144
- """
145
-
146
- messages = branch.to_chatcompletion_message()
147
- payload, completion = await self.service.serve_chat(messages=messages, **kwargs)
148
- if "choices" in completion:
149
- self.logger_({"input": payload, "output": completion})
150
- self.latest_response = Response(response=completion['choices'][0])
151
- branch.add_message(self.latest_response)
152
- self.service.status_tracker.num_tasks_succeeded += 1
153
- else:
154
- self.service.status_tracker.num_tasks_failed += 1
155
-
156
- async def _output(self, branch: Union[str, Branch], invoke=True, out=True):
157
- """Processes the latest response and optionally invokes tools and returns output.
158
-
159
- Args:
160
- invoke: Whether to invoke tools based on the latest response.
161
- out: Whether to return the output.
162
-
163
- Returns:
164
- Any: The output of the latest response or tool invocation, if requested.
165
- """
166
- content_ = self.latest_response.content
167
- if invoke:
168
- try:
169
- tool_uses = content_
170
- func_calls = lcall(tool_uses["action_list"], branch.tool_manager.get_function_call)
171
- outs = await alcall(func_calls, branch.tool_manager.invoke)
172
- for out, f in zip(outs, func_calls):
173
- response = Response(response={"function": f[0], "arguments": f[1], "output": out})
174
- branch.add_message(response)
175
- except:
176
- pass
177
- if out:
178
- if len(content_.items()) == 1 and len(get_flattened_keys(content_)) == 1:
179
- key = get_flattened_keys(content_)[0]
180
- return content_[key]
181
-
182
- return self.latest_response.content
183
-
184
- def _tool_parser(self, tools: Union[Dict, Tool, List[Tool], str, List[str], List[Dict]],
185
- branch: Union[str, Branch], **kwargs) -> Dict:
186
- """Parses tools and returns keyword arguments for tool usage.
187
-
188
- Args:
189
- tools: A single tool, a list of tools, or a tool name.
190
- **kwargs: Additional keyword arguments.
191
-
192
- Returns:
193
- Dict: Keyword arguments including tool schemas.
194
-
195
- Raises:
196
- ValueError: If the tool is not registered.
197
- """
198
- # 1. single schema: dict
199
- # 2. tool: Tool
200
- # 3. name: str
201
- # 4. list: 3 types of lists
202
- def tool_check(tool):
203
- if isinstance(tool, dict):
204
- return tool
205
- elif isinstance(tool, Tool):
206
- return tool.schema_
207
- elif isinstance(tool, str):
208
- if branch.tool_manager.name_existed(tool):
209
- tool = branch.tool_manager.registry[tool]
210
- return tool.schema_
211
- else:
212
- raise ValueError(f'Function {tool} is not registered.')
213
-
214
- if isinstance(tools, bool):
215
- tool_kwarg = {"tools": branch.tool_manager.to_tool_schema_list()}
216
- kwargs = {**tool_kwarg, **kwargs}
217
-
218
- else:
219
- if not isinstance(tools, list):
220
- tools = [tools]
221
- tool_kwarg = {"tools": lcall(tools, tool_check)}
222
- kwargs = {**tool_kwarg, **kwargs}
223
-
224
- return kwargs
225
-
226
- def _is_invoked(self, branch: Union[str, Branch]):
227
- """Checks if the latest message in the current branch has invoked a tool.
228
-
229
- Returns:
230
- bool: True if a tool has been invoked, False otherwise.
231
- """
232
- content = branch.messages.iloc[-1]['content']
233
- try:
234
- if json.loads(content)['action_response'].keys() >= {'function', 'arguments', 'output'}:
235
- return True
236
- except:
237
- return False
238
-
239
- async def initiate(
240
- self,
241
- instruction: Union[Instruction, str],
242
- system: Optional[str] = None,
243
- context: Optional[Any] = None,
244
- name: Optional[str] = None,
245
- invoke: bool = True,
246
- out: bool = True,
247
- tools: Union[bool, Tool, List[Tool], str, List[str]] = False,
248
- branch: Union[str, Branch] = None,
249
- **kwargs,
250
- ) -> Any:
251
- """Initiates a new conversation or instruction in the current branch.
252
-
253
- Args:
254
- instruction: The instruction to initiate or its content.
255
- system: Optional system information to update.
256
- context: Optional context for the instruction.
257
- name: Optional name of the entity sending the instruction.
258
- invoke: Whether to invoke tools based on the response.
259
- out: Whether to return the output.
260
- tools: Tools to be used or a flag indicating whether to use all tools.
261
- branch: Branch to run.
262
- **kwargs: Additional keyword arguments for the AI service.
263
-
264
- Returns:
265
- Any: The output of the initiation process, if requested.
266
-
267
- Raises:
268
- ValueError: If the tools argument is not in the expected format.
269
- """
270
- if not branch:
271
- branch = self.current_branch
272
- if isinstance(branch, str):
273
- if branch in self.branches.keys():
274
- branch = self.branches[branch]
275
- else:
276
- ValueError(f'branch{branch} does not exist')
277
- if system:
278
- branch.change_system_message(System(system))
279
- if isinstance(instruction, Instruction):
280
- branch.add_message(instruction)
281
- else:
282
- instruct = Instruction(instruction, context, name)
283
- branch.add_message(instruct)
284
- if branch.tool_manager.registry != {}:
285
- if tools:
286
- kwargs = self._tool_parser(tools=tools, branch=branch, **kwargs)
287
- config = {**self.llmconfig, **kwargs}
288
- await self.call_chatcompletion(branch=branch, **config)
289
-
290
- return await self._output(branch, invoke, out)
291
-
292
- async def followup(
293
- self,
294
- instruction: Union[Instruction, str],
295
- system: Optional[str] = None,
296
- context: Optional[Any] = None,
297
- out: bool = True,
298
- name: Optional[str] = None,
299
- invoke: bool = True,
300
- tools: Union[bool, Tool, List[Tool], str, List[str]] = False,
301
- branch: Union[str, Branch] = None,
302
- **kwargs,
303
- ) -> Any:
304
- """Adds a follow-up instruction to the current branch.
305
-
306
- Args:
307
- instruction: The instruction to follow up with or its content.
308
- system: Optional system information to update.
309
- context: Optional context for the instruction.
310
- out: Whether to return the output.
311
- name: Optional name of the entity sending the instruction.
312
- invoke: Whether to invoke tools based on the response.
313
- tools: Tools to be used or a flag indicating whether to use all tools.
314
- branch: Branch to run.
315
- **kwargs: Additional keyword arguments for the AI service.
316
-
317
- Returns:
318
- Any: The output of the follow-up process, if requested.
319
-
320
- Raises:
321
- ValueError: If the tools argument is not in the expected format.
322
- """
323
- if not branch:
324
- branch = self.current_branch
325
- if isinstance(branch, str):
326
- if branch in self.branches.keys():
327
- branch = self.branches[branch]
328
- else:
329
- ValueError(f'branch{branch} does not exist')
330
- if system:
331
- branch.change_system_message(System(system))
332
- if isinstance(instruction, Instruction):
333
- branch.add_message(instruction)
334
- else:
335
- instruct = Instruction(instruction, context, name)
336
- branch.add_message(instruct)
337
-
338
- if 'tool_parsed' in kwargs:
339
- kwargs.pop('tool_parsed')
340
- tool_kwarg = {'tools': tools}
341
- kwargs = {**tool_kwarg, **kwargs}
342
- else:
343
- if branch.tool_manager.registry != {}:
344
- if tools:
345
- kwargs = self._tool_parser(tools=tools, branch=branch, **kwargs)
346
- config = {**self.llmconfig, **kwargs}
347
- await self.call_chatcompletion(branch=branch, **config)
348
-
349
- return await self._output(branch, invoke, out)
350
-
351
- async def auto_followup(
352
- self,
353
- instruction: Union[Instruction, str],
354
- num: int = 3,
355
- tools: Union[bool, Tool, List[Tool], str, List[str], List[Dict]] = False,
356
- branch: Union[str, Branch] = None,
357
- **kwargs,
358
- ) -> None:
359
- if not branch:
360
- branch = self.current_branch
361
- if isinstance(branch, str):
362
- if branch in self.branches.keys():
363
- branch = self.branches[branch]
364
- else:
365
- ValueError(f'branch{branch} does not exist')
366
- if branch.tool_manager.registry != {}:
367
- if tools:
368
- kwargs = self._tool_parser(tools=tools, branch=branch, **kwargs)
369
-
370
- cont_ = True
371
- while num > 0 and cont_ is True:
372
- if tools:
373
- await self.followup(instruction, tool_choice="auto", tool_parsed=True, branch=branch, **kwargs)
374
- else:
375
- await self.followup(instruction, tool_parsed=True, branch=branch, **kwargs)
376
- num -= 1
377
- cont_ = True if self._is_invoked(branch) else False
378
- if num == 0:
379
- await self.followup(instruction, tool_parsed=True, branch=branch, **kwargs)
380
-
381
- async def instruction_set_auto_followup(
382
- self,
383
- instruction_set: InstructionSet,
384
- num: Union[int, List[int]] = 3,
385
- branch: Union[str, Branch] = None,
386
- **kwargs,
387
- ) -> None:
388
- """Automatically follows up an entire set of instructions.
389
-
390
- Args:
391
- instruction_set: The set of instructions to follow up.
392
- num: The number of follow-ups to attempt for each instruction or a list of numbers for each instruction.
393
- branch: Branch to run.
394
- **kwargs: Additional keyword arguments for the AI service.
395
-
396
- Raises:
397
- ValueError: If the number of follow-ups does not match the number of instructions.
398
- """
399
- if not branch:
400
- branch = self.current_branch
401
- if isinstance(branch, str):
402
- if branch in self.branches.keys():
403
- branch = self.branches[branch]
404
- else:
405
- ValueError(f'branch{branch} does not exist')
406
- if isinstance(num, List):
407
- if len(num) != instruction_set.instruct_len:
408
- raise ValueError('Unmatched auto_followup num size and instructions set size')
409
-
410
- current_instruct_node = instruction_set.get_instruction_by_id(instruction_set.first_instruct)
411
- for i in range(instruction_set.instruct_len):
412
- num_ = num if isinstance(num, int) else num[i]
413
- tools = instruction_set.get_tools(current_instruct_node)
414
- if tools:
415
- await self.auto_followup(current_instruct_node, num=num_, tools=tools, branch=branch, **kwargs)
416
- else:
417
- await self.followup(current_instruct_node, branch=branch, **kwargs)
418
- current_instruct_node = instruction_set.get_next_instruction(current_instruct_node)
419
-
420
- #### Branch Methods: effective to current active branch
421
- def change_system_message(self, system: System) -> None:
422
- """Changes the system message of the current active branch.
423
-
424
- Args:
425
- system: The new system message.
426
- """
427
- self.current_branch.change_system_message(system)
428
-
429
- def add_instruction_set(self, name: str, instruction_set: InstructionSet) -> None:
430
- """Adds an instruction set to the current active branch.
431
-
432
- Args:
433
- name: The name of the instruction set.
434
- instruction_set: The instruction set to add.
435
- """
436
- self.current_branch.add_instruction_set(name, instruction_set)
437
-
438
- def remove_instruction_set(self, name: str) -> bool:
439
- """Removes an instruction set from the current active branch.
440
-
441
- Args:
442
- name: The name of the instruction set to remove.
443
-
444
- Returns:
445
- bool: True if the instruction set is removed, False otherwise.
446
- """
447
- return self.current_branch.remove_instruction_set(name)
448
-
449
- def register_tools(self, tools: Union[Tool, List[Tool]]) -> None:
450
- """Registers one or more tools to the current active branch.
451
-
452
- Args:
453
- tools: The tool or list of tools to register.
454
- """
455
- self.current_branch.register_tools(tools)
456
-
457
- def delete_tool(self, name: str) -> bool:
458
- """Deletes a tool from the current active branch.
459
-
460
- Args:
461
- name: The name of the tool to delete.
462
-
463
- Returns:
464
- bool: True if the tool is deleted, False otherwise.
465
- """
466
- return self.current_branch.delete_tool(name)
467
-
468
- def report(self) -> Dict[str, Any]:
469
- """Generates a report of the current active branch.
470
-
471
- Returns:
472
- Dict[str, Any]: The report of the current active branch.
473
- """
474
- return self.current_branch.report()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes