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
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