lionagi 0.0.104__py3-none-any.whl → 0.0.105__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,87 +2,91 @@ from .message import Message
2
2
 
3
3
  class Conversation:
4
4
  """
5
- A class modeling conversations and managing messages within the conversation.
5
+ A class representing a conversation between users and the assistant.
6
6
 
7
- This class facilitates the organization and manipulation of messages in a conversation.
8
- It includes methods for initiating a conversation, adding messages, changing the system message,
9
- appending the last response, and keeping the last N exchanges.
7
+ This class manages the exchange of messages within a conversation, including system settings,
8
+ user instructions, and assistant responses.
10
9
 
11
10
  Attributes:
12
- response_counts: A class-level attribute to track the number of responses.
13
- messages: A list containing messages in the conversation.
14
- msg: An instance of the Message class for creating and processing messages.
15
- responses: A list containing response messages.
11
+ response_counts (int): The count of assistant responses in the conversation.
12
+ messages (list): A list to store messages in the conversation.
13
+ msg (Message): An instance of the Message class for creating messages.
14
+ responses (list): A list to store assistant responses in the conversation.
16
15
 
17
16
  Methods:
18
- initiate_conversation: Start a new conversation with system and user instructions.
19
- add_messages: Add messages to the conversation.
20
- change_system: Change the system message in the conversation.
21
- append_last_response: Append the last response to the conversation.
22
- keep_last_n_exchanges: Keep only the last N exchanges in the conversation.
17
+ initiate_conversation(system, instruction, context=None, name=None):
18
+ Initiate a conversation with a system setting and user instruction.
19
+
20
+ add_messages(system, instruction, context=None, response=None, tool=None, name=None):
21
+ Add messages to the conversation, including system setting, user instruction, and assistant response.
22
+
23
+ change_system(system):
24
+ Change the system setting in the conversation.
25
+
26
+ keep_last_n_exchanges(n: int):
27
+ Keep the last n exchanges in the conversation.
23
28
  """
24
-
25
29
  response_counts = 0
26
30
 
27
31
  def __init__(self, messages=None) -> None:
28
32
  """
29
33
  Initialize a Conversation object.
30
34
 
31
- Args:
32
- messages: A list of messages to initialize the conversation.
35
+ Parameters:
36
+ messages (list): A list of messages to initialize the conversation. Default is None.
37
+
33
38
  """
34
39
  self.messages = messages or []
35
40
  self.msg = Message()
36
41
  self.responses = []
37
42
 
38
- def initiate_conversation(self, system, instruction, context=None):
43
+ def initiate_conversation(self, system, instruction, context=None, name=None):
39
44
  """
40
- Start a new conversation with a system message and an instruction.
45
+ Initiate a conversation with a system setting and user instruction.
41
46
 
42
- Args:
43
- system: The content of the system message.
44
- instruction: The content of the user instruction.
45
- context: Additional context for the user instruction.
47
+ Parameters:
48
+ system (str): The system setting for the conversation.
49
+ instruction (str): The user instruction to initiate the conversation.
50
+ context (dict): Additional context for the conversation. Default is None.
51
+ name (str): The name associated with the user. Default is None.
46
52
  """
47
53
  self.messages, self.responses = [], []
48
54
  self.add_messages(system=system)
49
- self.add_messages(instruction=instruction, context=context)
55
+ self.add_messages(instruction=instruction, context=context, name=name)
50
56
 
51
- def add_messages(self, system=None, instruction=None, context=None, response=None):
57
+ # modify the message adding to accomodate tools
58
+ def add_messages(self, system=None, instruction=None, context=None, response=None, tool=None, name=None):
52
59
  """
53
- Add messages to the conversation.
60
+ Add messages to the conversation, including system setting, user instruction, and assistant response.
54
61
 
55
- Args:
56
- system: The content of the system message.
57
- instruction: The content of the user instruction.
58
- context: Additional context for the user instruction.
59
- response: The content of the assistant's response.
62
+ Parameters:
63
+ system (str): The system setting for the message. Default is None.
64
+ instruction (str): The instruction content for the message. Default is None.
65
+ context (dict): Additional context for the message. Default is None.
66
+ response (dict): The response content for the message. Default is None.
67
+ tool (dict): The tool information for the message. Default is None.
68
+ name (str): The name associated with the message. Default is None.
60
69
  """
61
- msg = self.msg(system=system, instruction=instruction, response=response, context=context)
70
+ msg = self.msg(system=system, instruction=instruction, context=context, response=response, tool=tool, name=name)
62
71
  self.messages.append(msg)
63
72
 
64
73
  def change_system(self, system):
65
74
  """
66
- Change the system message in the conversation.
75
+ Change the system setting in the conversation.
67
76
 
68
- Args:
69
- system: The new content for the system message.
77
+ Parameters:
78
+ system (str): The new system setting for the conversation.
70
79
  """
71
80
  self.messages[0] = self.msg(system=system)
72
81
 
73
- def append_last_response(self):
74
- """
75
- Append the last response to the conversation.
76
- """
77
- self.add_messages(response=self.responses[-1])
78
-
79
82
  def keep_last_n_exchanges(self, n: int):
80
83
  """
81
- Keep only the last N exchanges in the conversation.
84
+ Keep the last n exchanges in the conversation.
82
85
 
83
- Args:
84
- n: The number of exchanges to keep.
86
+ Parameters:
87
+ n (int): The number of exchanges to keep.
85
88
  """
89
+ # keep last n_exchanges, one exchange is marked by one assistant response
86
90
  response_indices = [
87
91
  index for index, message in enumerate(self.messages[1:]) if message["role"] == "assistant"
88
92
  ]
@@ -1,76 +1,139 @@
1
1
  from datetime import datetime
2
2
  import json
3
- from ..utils.sys_util import create_id
3
+ from ..utils.sys_util import create_id, l_call
4
4
  from ..utils.log_util import DataLogger
5
5
 
6
6
 
7
7
  class Message:
8
8
  """
9
- A class modeling messages in conversations.
9
+ A class representing a message in a conversation.
10
10
 
11
- This class is designed to encapsulate messages exchanged between different roles
12
- (user, assistant, or system) in a conversation. It includes functionality to process,
13
- log, and manage messages.
11
+ This class encapsulates messages from users, the assistant, systems, and external tools.
14
12
 
15
13
  Attributes:
16
- role: The role of the message (user, assistant, or system).
17
- content: The content of the message.
18
- sender: The sender of the message.
19
- logger: An instance of DataLogger for logging message information.
14
+ role (str): The role of the message, indicating if it's from the user, assistant, system, or tool.
15
+ content: The content of the message, which can be an instruction, response, system setting, or tool information.
16
+ name (str): The name associated with the message, specifying the source (user, assistant, system, or tool).
17
+ metadata (dict): Additional metadata including id, timestamp, and name.
18
+ _logger (DataLogger): An instance of the DataLogger class for logging message details.
20
19
 
21
20
  Methods:
22
- __call__: Process and log a message based on its role.
21
+ create_message(system, instruction, context, response, tool, name):
22
+ Create a message based on the provided information.
23
+
24
+ to_json() -> dict:
25
+ Convert the message to a JSON format.
26
+
27
+ __call__(system, instruction, context, response, name, tool) -> dict:
28
+ Create and return a message in JSON format.
29
+
30
+ to_csv(dir, filename, verbose, timestamp, dir_exist_ok, file_exist_ok):
31
+ Save the message to a CSV file.
23
32
  """
24
33
  def __init__(self) -> None:
25
34
  """
26
- Initialize a Message object with attributes for role, content, sender, and a DataLogger.
35
+ Initialize a Message object.
27
36
  """
28
37
  self.role = None
29
38
  self.content = None
30
- self.sender = None
31
- self.logger = DataLogger()
32
-
33
- def __call__(self, system=None, instruction=None, response=None, context=None, sender=None):
39
+ self.name = None
40
+ self.metadata = None
41
+ self._logger = DataLogger()
42
+
43
+ def create_message(self, system=None, instruction=None, context=None, response=None, tool=None, name=None):
34
44
  """
35
- Process and log a message based on the specified role (system, instruction, or response).
45
+ Create a message based on the provided information.
36
46
 
37
- Args:
38
- system: The content of the message in the system role.
39
- instruction: The content of the message in the user role.
40
- response: The content of the message in the assistant role.
41
- context: Additional context for the user instruction.
42
- sender: The sender of the message.
47
+ Parameters:
48
+ system (str): The system setting for the message. Default is None.
49
+ instruction (str): The instruction content for the message. Default is None.
50
+ context (dict): Additional context for the message. Default is None.
51
+ response (dict): The response content for the message. Default is None.
52
+ tool (dict): The tool information for the message. Default is None.
53
+ name (str): The name associated with the message. Default is None.
43
54
  """
55
+ if sum(l_call([system, instruction, response, tool], bool)) > 1:
56
+ raise ValueError("Error: Message cannot have more than one role.")
44
57
 
45
- if sum(map(bool, [system, instruction, response])) > 1:
46
- raise ValueError("Message cannot have more than one role.")
47
- else:
58
+ else:
48
59
  if response:
49
60
  self.role = "assistant"
50
- self.sender = sender or "assistant"
51
- self.content = response['content']
61
+ response = response["message"]
62
+ if str(response['content']) == "None":
63
+ try:
64
+ # currently can only support a single function response
65
+ if response['tool_calls'][0]['type'] == 'function':
66
+ self.name = name or ("func_" + response['tool_calls'][0]['function']['name'])
67
+ content = response['tool_calls'][0]['function']['arguments']
68
+ self.content = {"function":self.name, "arguments": content}
69
+ except:
70
+ raise ValueError("Response message must be one of regular response or function calling")
71
+ else:
72
+ self.content = response['content']
73
+ self.name = name or "assistant"
52
74
  elif instruction:
53
75
  self.role = "user"
54
- self.sender = sender or "user"
55
76
  self.content = {"instruction": instruction}
77
+ self.name = name or "user"
56
78
  if context:
57
- self.content.update(context)
79
+ self.content.update({"context": context})
58
80
  elif system:
59
81
  self.role = "system"
60
- self.sender = sender or "system"
61
82
  self.content = system
83
+ self.name = name or "system"
84
+ elif tool:
85
+ self.role = "tool"
86
+ self.content = tool
87
+ self.name = name or "tool"
88
+
89
+ def to_json(self):
90
+ """
91
+ Convert the message to a JSON format.
92
+
93
+ Returns:
94
+ - dict: The message in JSON format.
95
+ """
62
96
  out = {
63
97
  "role": self.role,
64
98
  "content": json.dumps(self.content) if isinstance(self.content, dict) else self.content
65
99
  }
66
-
67
- a = {**{
100
+
101
+ self.metadata = {
68
102
  "id": create_id(),
69
103
  "timestamp": datetime.now().isoformat(),
70
- "sender": self.sender
71
- }, **out}
72
- self.logger(a)
104
+ "name": self.name}
105
+
106
+ self._logger({**self.metadata, **out})
73
107
  return out
108
+
109
+ def __call__(self, system=None, instruction=None, context=None, response=None, name=None, tool=None):
110
+ """
111
+ Create and return a message in JSON format.
112
+
113
+ Parameters:
114
+ system (str): The system setting for the message. Default is None.
115
+ instruction (str): The instruction content for the message. Default is None.
116
+ context (dict): Additional context for the message. Default is None.
117
+ response (dict): The response content for the message. Default is None.
118
+ name (str): The name associated with the message. Default is None.
119
+ tool (dict): The tool information for the message. Default is None.
120
+
121
+ Returns:
122
+ dict: The message in JSON format.
123
+ """
124
+ self.create_message(system, instruction, context, response, tool, name)
125
+ return self.to_json()
74
126
 
75
- def _to_csv(self, dir, filename, verbose=True, timestamp=True, dir_exist_ok=True, file_exist_ok=False):
76
- self.logger.to_csv(dir, filename, verbose, timestamp, dir_exist_ok, file_exist_ok)
127
+ def to_csv(self, dir=None, filename=None, verbose=True, timestamp=True, dir_exist_ok=True, file_exist_ok=False):
128
+ """
129
+ Save the message to a CSV file.
130
+
131
+ Parameters:
132
+ dir (str): The directory path for saving the CSV file. Default is None.
133
+ filename (str): The filename for the CSV file. Default is None.
134
+ verbose (bool): Whether to include verbose information in the CSV. Default is True.
135
+ timestamp (bool): Whether to include timestamps in the CSV. Default is True.
136
+ dir_exist_ok (bool): Whether to allow the directory to exist. Default is True.
137
+ file_exist_ok (bool): Whether to allow the file to exist. Default is False.
138
+ """
139
+ self._logger.to_csv(dir, filename, verbose, timestamp, dir_exist_ok, file_exist_ok)
@@ -3,108 +3,222 @@ import asyncio
3
3
  from typing import Any
4
4
 
5
5
  from .conversation import Conversation
6
- from ..api.oai_config import oai_llmconfig
6
+ from ..utils.sys_util import to_list
7
7
  from ..utils.log_util import DataLogger
8
8
  from ..utils.api_util import StatusTracker
9
+ from ..utils.tool_util import ToolManager
9
10
  from ..api.oai_service import OpenAIService
10
11
 
12
+ from ..api.oai_config import oai_llmconfig
13
+
11
14
 
12
15
  status_tracker = StatusTracker()
13
16
  OAIService = OpenAIService()
14
17
 
15
18
  class Session():
16
19
  """
17
- A class representing a conversation session with chat completion capabilities.
20
+ A class representing a conversation session with a conversational AI system.
18
21
 
19
- This class manages conversations, interacts with chat completion services (currently OpenAI),
20
- and logs the interactions using a DataLogger.
22
+ This class manages the flow of conversation, system settings, and interactions with external tools.
21
23
 
22
24
  Attributes:
23
- conversation: An instance of the Conversation class for managing messages.
24
- system: The system identifier for the conversation session.
25
- llmconfig: Configuration parameters for language models.
26
- logger: An instance of DataLogger for logging conversation interactions.
27
- api_service: An instance of the API service for making asynchronous API calls.
25
+ conversation (Conversation): An instance of the Conversation class to manage messages.
26
+ system (str): The current system setting for the conversation.
27
+ llmconfig (dict): Configuration settings for the language model.
28
+ _logger (DataLogger): An instance of the DataLogger class for logging conversation details.
29
+ api_service: An instance of the API service for making calls to the conversational AI model.
30
+ toolmanager (ToolManager): An instance of the ToolManager class for managing external tools.
28
31
 
29
32
  Methods:
30
- initiate: Initiate a conversation session with the given instruction.
31
- followup: Continue the conversation session with a follow-up instruction.
32
- create_payload_chatcompletion: Create a payload for chat completion API calls.
33
- call_chatcompletion: Make an asynchronous call to the chat completion API.
33
+ set_dir(dir):
34
+ Set the directory for logging.
35
+
36
+ set_system(system):
37
+ Set the system for the conversation.
38
+
39
+ set_llmconfig(llmconfig):
40
+ Set the language model configuration.
41
+
42
+ set_api_service(api_service):
43
+ Set the API service for making model calls.
44
+
45
+ _output(output, invoke=True, out=True) -> Any:
46
+ Process the output, invoke tools if needed, and optionally return the output.
47
+
48
+ register_tools(tools, funcs, update=False, new=False, prefix=None, postfix=None):
49
+ Register tools and their corresponding functions.
50
+
51
+ initiate(instruction, system=None, context=None, out=True, name=None, invoke=True, **kwargs) -> Any:
52
+ Start a new conversation session with the provided instruction.
53
+
54
+ followup(instruction, system=None, context=None, out=True, name=None, invoke=True, **kwargs) -> Any:
55
+ Continue the conversation with the provided instruction.
56
+
57
+ create_payload_chatcompletion(**kwargs) -> dict:
58
+ Create a payload for chat completion based on the conversation state and configuration.
59
+
60
+ call_chatcompletion(sleep=0.1, **kwargs) -> None:
61
+ Make a call to the chat completion API and process the response.
62
+
63
+ messages_to_csv(dir=None, filename="_messages.csv", **kwargs) -> None:
64
+ Save conversation messages to a CSV file.
65
+
66
+ log_to_csv(dir=None, filename="_llmlog.csv", **kwargs) -> None:
67
+ Save conversation logs to a CSV file.
34
68
  """
35
69
 
36
70
  def __init__(self, system, dir=None, llmconfig=oai_llmconfig, api_service=OAIService):
37
71
  """
38
- Initialize a Session object.
72
+ Initialize a Session object with default or provided settings.
39
73
 
40
- Args:
41
- system: The system identifier for the conversation session.
42
- dir: The directory for logging interactions.
43
- llmconfig: Configuration parameters for language models.
44
- api_service: An instance of the API service for making asynchronous API calls.
74
+ Parameters:
75
+ system (str): The initial system setting for the conversation.
76
+ dir (Optional[str]): The directory for logging. Default is None.
77
+ llmconfig (Optional[dict]): Configuration settings for the language model. Default is oai_llmconfig.
78
+ api_service: An instance of the API service for making calls to the conversational AI model.
45
79
  """
46
80
  self.conversation = Conversation()
47
81
  self.system = system
48
82
  self.llmconfig = llmconfig
49
- self.logger = DataLogger(dir=dir)
83
+ self._logger = DataLogger(dir=dir)
84
+ self.api_service = api_service
85
+ self.toolmanager = ToolManager()
86
+
87
+ def set_dir(self, dir):
88
+ """
89
+ Set the directory for logging.
90
+
91
+ Parameters:
92
+ dir (str): The directory path.
93
+ """
94
+ self._logger.dir = dir
95
+
96
+ def set_system(self, system):
97
+ """
98
+ Set the system for the conversation.
99
+
100
+ Parameters:
101
+ system (str): The system setting.
102
+ """
103
+ self.conversation.change_system(system)
104
+
105
+ def set_llmconfig(self, llmconfig):
106
+ """
107
+ Set the language model configuration.
108
+
109
+ Parameters:
110
+ llmconfig (dict): Configuration settings for the language model.
111
+ """
112
+ self.llmconfig = llmconfig
113
+
114
+ def set_api_service(self, api_service):
115
+ """
116
+ Set the API service for making model calls.
117
+
118
+ Parameters:
119
+ api_service: An instance of the API service.
120
+ """
50
121
  self.api_service = api_service
51
122
 
52
- async def initiate(self, instruction, system=None, context=None, out=True, **kwargs) -> Any:
123
+ async def _output(self, output, invoke=True, out=True):
53
124
  """
54
- Initiate a conversation session with the given instruction.
125
+ Process the output, invoke tools if needed, and optionally return the output.
55
126
 
56
- Args:
57
- instruction: The user's instruction to initiate the conversation.
58
- system: The content of the system message.
59
- context: Additional context for the user instruction.
60
- out: Whether to return the output content.
127
+ Parameters:
128
+ output: The output to process.
129
+ invoke (bool): Whether to invoke tools based on the output. Default is True.
130
+ out (bool): Whether to return the output. Default is True.
61
131
 
62
132
  Returns:
63
- Any: The output content if 'out' is True, otherwise None.
133
+ Any: The processed output.
134
+ """
135
+ if invoke:
136
+ try:
137
+ func, args = self.toolmanager._get_function_call(output)
138
+ outs = await self.toolmanager.ainvoke(func, args)
139
+ self.conversation.add_messages(tool=outs)
140
+ except:
141
+ pass
142
+ if out:
143
+ return output
144
+
145
+ def register_tools(self, tools, funcs, update=False, new=False, prefix=None, postfix=None):
146
+ """
147
+ Register tools and their corresponding functions.
148
+
149
+ Parameters:
150
+ tools (list): The list of tool information dictionaries.
151
+ funcs (list): The list of corresponding functions.
152
+ update (bool): Whether to update existing functions.
153
+ new (bool): Whether to create new registries for existing functions.
154
+ prefix (Optional[str]): A prefix to add to the function names.
155
+ postfix (Optional[str]): A postfix to add to the function names.
156
+ """
157
+ funcs = to_list(funcs)
158
+ self.toolmanager.register_tools(tools, funcs, update, new, prefix, postfix)
159
+
160
+ async def initiate(self, instruction, system=None, context=None, out=True, name=None, invoke=True, **kwargs) -> Any:
161
+ """
162
+ Start a new conversation session with the provided instruction.
163
+
164
+ Parameters:
165
+ instruction (str): The instruction to initiate the conversation.
166
+ system (Optional[str]): The system setting for the conversation. Default is None.
167
+ context (Optional[dict]): Additional context for the instruction. Default is None.
168
+ out (bool): Whether to return the output. Default is True.
169
+ name (Optional[str]): The name associated with the instruction. Default is None.
170
+ invoke (bool): Whether to invoke tools based on the output. Default is True.
171
+ kwargs: Additional keyword arguments for configuration.
172
+
173
+ Returns:
174
+ Any: The processed output.
64
175
  """
65
176
  config = {**self.llmconfig, **kwargs}
66
177
  system = system or self.system
67
- self.conversation.initiate_conversation(system=system, instruction=instruction, context=context)
68
-
178
+ self.conversation.initiate_conversation(system=system, instruction=instruction, context=context, name=name)
69
179
  await self.call_chatcompletion(**config)
70
- if out:
71
- return self.conversation.responses[-1]['content']
180
+ output = self.conversation.responses[-1]['content']
181
+
182
+ return await self._output(output, invoke, out)
72
183
 
73
- async def followup(self, instruction, system=None, context=None, out=True, **kwargs) -> Any:
184
+ async def followup(self, instruction, system=None, context=None, out=True, name=None, invoke=True, **kwargs) -> Any:
74
185
  """
75
- Continue the conversation session with a follow-up instruction.
186
+ Continue the conversation with the provided instruction.
76
187
 
77
- Args:
78
- instruction: The user's follow-up instruction.
79
- system: The content of the system message.
80
- context: Additional context for the user instruction.
81
- out: Whether to return the output content.
188
+ Parameters:
189
+ instruction (str): The instruction to continue the conversation.
190
+ system (Optional[str]): The system setting for the conversation. Default is None.
191
+ context (Optional[dict]): Additional context for the instruction. Default is None.
192
+ out (bool): Whether to return the output. Default is True.
193
+ name (Optional[str]): The name associated with the instruction. Default is None.
194
+ invoke (bool): Whether to invoke tools based on the output. Default is True.
195
+ kwargs: Additional keyword arguments for configuration.
82
196
 
83
197
  Returns:
84
- Any: The output content if 'out' is True, otherwise None.
198
+ Any: The processed output.
85
199
  """
86
- self.conversation.append_last_response()
87
200
  if system:
88
201
  self.conversation.change_system(system)
89
- self.conversation.add_messages(instruction=instruction, context=context)
90
-
202
+ self.conversation.add_messages(instruction=instruction, context=context, name=name)
91
203
  config = {**self.llmconfig, **kwargs}
92
204
  await self.call_chatcompletion(**config)
93
- if out:
94
- return self.conversation.responses[-1]['content']
205
+ output = self.conversation.responses[-1]['content']
206
+
207
+ return await self._output(output, invoke, out)
95
208
 
96
209
  def create_payload_chatcompletion(self, **kwargs):
97
210
  """
98
- Create a payload for chat completion API calls.
211
+ Create a payload for chat completion based on the conversation state and configuration.
212
+
213
+ Parameters:
214
+ kwargs: Additional keyword arguments for configuration.
99
215
 
100
- Args:
101
- kwargs: Additional keyword arguments for customization.
216
+ Returns:
217
+ dict: The payload for chat completion.
102
218
  """
103
219
  # currently only openai chat completions are supported
104
220
  messages = self.conversation.messages
105
-
106
221
  config = {**self.llmconfig, **kwargs}
107
-
108
222
  payload = {
109
223
  "messages": messages,
110
224
  "model": config.get('model'),
@@ -117,34 +231,30 @@ class Session():
117
231
  }
118
232
 
119
233
  for key in ["seed", "stop", "stream", "tools", "tool_choice", "user", "max_tokens"]:
120
- if config[key] is True:
234
+ if bool(config[key]) is True and str(config[key]) != "none":
121
235
  payload.update({key: config[key]})
122
-
123
236
  return payload
124
-
125
- async def call_chatcompletion(self, delay=1, **kwargs):
237
+
238
+ async def call_chatcompletion(self, sleep=0.1, **kwargs):
126
239
  """
127
- Make an asynchronous call to the chat completion API.
240
+ Make a call to the chat completion API and process the response.
128
241
 
129
- Args:
130
- delay: The delay (in seconds) between API calls.
131
- kwargs: Additional keyword arguments for customization.
242
+ Parameters:
243
+ sleep (float): The sleep duration after making the API call. Default is 0.1.
244
+ kwargs: Additional keyword arguments for configuration.
132
245
  """
133
- # currently only openai chat completions are supported
134
-
135
246
  endpoint = f"chat/completions"
136
247
  try:
137
248
  async with aiohttp.ClientSession() as session:
249
+ payload = self.create_payload_chatcompletion(**kwargs)
138
250
  completion = await self.api_service.call_api(
139
- session, endpoint,
140
- self.create_payload_chatcompletion(**kwargs))
251
+ session, endpoint, payload)
141
252
  if "choices" in completion:
142
- completion = completion['choices'][0] # currently can only call one completion at a time, n has to be 1
143
- self.logger({"input":self.conversation.messages, "output": completion})
144
- response = {"role": "assistant", "content": completion['message']["content"]}
145
- self.conversation.responses.append(response)
253
+ self._logger({"input":payload, "output": completion})
254
+ self.conversation.add_messages(response=completion['choices'][0])
255
+ self.conversation.responses.append(self.conversation.messages[-1])
146
256
  self.conversation.response_counts += 1
147
- await asyncio.sleep(delay=delay)
257
+ await asyncio.sleep(sleep)
148
258
  status_tracker.num_tasks_succeeded += 1
149
259
  else:
150
260
  status_tracker.num_tasks_failed += 1
@@ -153,13 +263,29 @@ class Session():
153
263
  raise e
154
264
 
155
265
  def messages_to_csv(self, dir=None, filename="_messages.csv", **kwags):
156
- dir = dir or self.logger.dir
266
+ """
267
+ Save conversation messages to a CSV file.
268
+
269
+ Parameters:
270
+ dir (Optional[str]): The directory path for saving the CSV file. Default is None.
271
+ filename (Optional[str]): The filename for the CSV file. Default is "_messages.csv".
272
+ kwargs: Additional keyword arguments for CSV file settings.
273
+ """
274
+ dir = dir or self._logger.dir
157
275
  if dir is None:
158
276
  raise ValueError("No directory specified.")
159
- self.conversation.msg._to_csv(dir=dir, filename=filename, **kwags)
277
+ self.conversation.msg.to_csv(dir=dir, filename=filename, **kwags)
160
278
 
161
279
  def log_to_csv(self, dir=None, filename="_llmlog.csv", **kwags):
162
- dir = dir or self.logger.dir
280
+ """
281
+ Save conversation logs to a CSV file.
282
+
283
+ Parameters:
284
+ dir (Optional[str]): The directory path for saving the CSV file. Default is None.
285
+ filename (Optional[str]): The filename for the CSV file. Default is "_llmlog.csv".
286
+ kwargs: Additional keyword arguments for CSV file settings.
287
+ """
288
+ dir = dir or self._logger.dir
163
289
  if dir is None:
164
290
  raise ValueError("No directory specified.")
165
- self.logger.to_csv(dir=dir, filename=filename, **kwags)
291
+ self._logger.to_csv(dir=dir, filename=filename, **kwags)
File without changes
lionagi/utils/__init__.py CHANGED
@@ -1,9 +1,10 @@
1
1
  from .sys_util import to_flat_dict, append_to_jsonl, to_list, str_to_num, make_copy, to_temp, to_csv, hold_call, ahold_call, l_call, al_call, m_call, am_call, e_call, ae_call, get_timestamp, create_path
2
2
  from .doc_util import dir_to_path, read_text, dir_to_files, chunk_text, file_to_chunks, file_to_chunks, get_bins
3
3
  from .log_util import DataLogger
4
+ from .tool_util import ToolManager
4
5
 
5
6
  __all__ = [
6
7
  "to_list", "str_to_num", "make_copy", "to_temp", "to_csv", "hold_call", "ahold_call", "l_call", "al_call", "m_call", "am_call", "e_call", "ae_call", "get_timestamp", "create_path", "to_flat_dict", "append_to_jsonl",
7
8
  "dir_to_path", "read_text", "dir_to_files", "chunk_text", "file_to_chunks", "file_to_chunks", "get_bins",
8
- "DataLogger"
9
+ "DataLogger", "ToolManager"
9
10
  ]
lionagi/utils/doc_util.py CHANGED
@@ -26,7 +26,7 @@ def dir_to_path(dir: str, ext, recursive: bool = False, flat: bool = True):
26
26
  def _dir_to_path(ext, recursive=recursive):
27
27
  tem = '**/*' if recursive else '*'
28
28
  return list(Path(dir).glob(tem + ext))
29
-
29
+
30
30
  return to_list(l_call(ext, _dir_to_path, flat=True), flat=flat)
31
31
 
32
32
  def read_text(filepath: str, clean: bool = True) -> str:
@@ -48,15 +48,15 @@ def read_text(filepath: str, clean: bool = True) -> str:
48
48
  content = f.read()
49
49
  if clean:
50
50
  # Define characters to replace and their replacements
51
- replacements = {'\\': ' ', '\\\n': ' ', '\\\t': ' ', ' ': ' ', '\'': ' '}
51
+ replacements = {'\\': ' ', '\n': ' ', '\t': ' ', ' ': ' ', '\'': ' '}
52
52
  for old, new in replacements.items():
53
53
  content = content.replace(old, new)
54
54
  return content
55
55
 
56
- def dir_to_files(dir: str, ext: str, recursive: bool = False,
57
- reader: Callable = read_text, clean: bool = True,
56
+ def dir_to_files(dir: str, ext: str, recursive: bool = False,
57
+ reader: Callable = read_text, clean: bool = True,
58
58
  to_csv: bool = False, project: str = 'project',
59
- output_dir: str = 'data/logs/sources/', filename: Optional[str] = None,
59
+ output_dir: str = 'data/logs/sources/', filename: Optional[str] = None,
60
60
  verbose: bool = True, timestamp: bool = True, logger: Optional[DataLogger] = None):
61
61
  """
62
62
  Reads and processes files in a specified directory with the given extension.
@@ -81,9 +81,9 @@ def dir_to_files(dir: str, ext: str, recursive: bool = False,
81
81
  Examples:
82
82
  >>> logs = dir_to_files(dir='my_directory', ext='.txt', to_csv=True)
83
83
  """
84
-
84
+
85
85
  sources = dir_to_path(dir, ext, recursive)
86
-
86
+
87
87
  def split_path(path: Path) -> tuple:
88
88
  folder_name = path.parent.name
89
89
  file_name = path.name
@@ -99,9 +99,9 @@ def dir_to_files(dir: str, ext: str, recursive: bool = False,
99
99
  "file_size": len(str(content)),
100
100
  'content': content
101
101
  } if content else None
102
-
102
+
103
103
  logs = to_list(l_call(sources, to_dict, flat=True), dropna=True)
104
-
104
+
105
105
  if to_csv:
106
106
  filename = filename or f"{project}_sources.csv"
107
107
  logger = DataLogger(dir=output_dir, log=logs) if not logger else logger
@@ -109,7 +109,7 @@ def dir_to_files(dir: str, ext: str, recursive: bool = False,
109
109
 
110
110
  return logs
111
111
 
112
- def chunk_text(input: str, chunk_size: int, overlap: float,
112
+ def chunk_text(input: str, chunk_size: int, overlap: float,
113
113
  threshold: int) -> List[Union[str, None]]:
114
114
  """
115
115
  Splits a string into chunks of a specified size, allowing for optional overlap between chunks.
@@ -127,19 +127,19 @@ def chunk_text(input: str, chunk_size: int, overlap: float,
127
127
  Returns:
128
128
  List[Union[str, None]]: List of text chunks.
129
129
  """
130
-
130
+
131
131
  try:
132
132
  # Ensure text is a string
133
133
  if not isinstance(input, str):
134
134
  input = str(input)
135
-
135
+
136
136
  chunks = []
137
137
  n_chunks = math.ceil(len(input) / chunk_size)
138
138
  overlap_size = int(chunk_size * overlap / 2)
139
-
139
+
140
140
  if n_chunks == 1:
141
141
  return [input]
142
-
142
+
143
143
  elif n_chunks == 2:
144
144
  chunks.append(input[:chunk_size + overlap_size])
145
145
  if len(input) - chunk_size > threshold:
@@ -147,28 +147,28 @@ def chunk_text(input: str, chunk_size: int, overlap: float,
147
147
  else:
148
148
  return [input]
149
149
  return chunks
150
-
150
+
151
151
  elif n_chunks > 2:
152
152
  chunks.append(input[:chunk_size + overlap_size])
153
153
  for i in range(1, n_chunks - 1):
154
154
  start_idx = chunk_size * i - overlap_size
155
155
  end_idx = chunk_size * (i + 1) + overlap_size
156
156
  chunks.append(input[start_idx:end_idx])
157
-
157
+
158
158
  if len(input) - chunk_size * (n_chunks - 1) > threshold:
159
159
  chunks.append(input[chunk_size * (n_chunks - 1) - overlap_size:])
160
160
  else:
161
- chunks[-1] += input[chunk_size * (n_chunks - 1):]
162
-
161
+ chunks[-1] += input[chunk_size * (n_chunks - 1) + overlap_size:]
162
+
163
163
  return chunks
164
-
164
+
165
165
  except Exception as e:
166
166
  raise ValueError(f"An error occurred while chunking the text. {e}")
167
167
 
168
- def _file_to_chunks(input: Dict[str, Any],
169
- field: str = 'content',
170
- chunk_size: int = 1500,
171
- overlap: float = 0.2,
168
+ def _file_to_chunks(input: Dict[str, Any],
169
+ field: str = 'content',
170
+ chunk_size: int = 1500,
171
+ overlap: float = 0.2,
172
172
  threshold: int = 200) -> List[Dict[str, Any]]:
173
173
  """
174
174
  Splits text from a specified dictionary field into chunks and returns a list of dictionaries.
@@ -195,7 +195,7 @@ def _file_to_chunks(input: Dict[str, Any],
195
195
  try:
196
196
  out = {key: value for key, value in input.items() if key != field}
197
197
  out.update({"chunk_overlap": overlap, "chunk_threshold": threshold})
198
-
198
+
199
199
  chunks = chunk_text(input[field], chunk_size=chunk_size, overlap=overlap, threshold=threshold)
200
200
  logs = []
201
201
  for i, chunk in enumerate(chunks):
@@ -209,22 +209,22 @@ def _file_to_chunks(input: Dict[str, Any],
209
209
  logs.append(chunk_dict)
210
210
 
211
211
  return logs
212
-
212
+
213
213
  except Exception as e:
214
214
  raise ValueError(f"An error occurred while chunking the file. {e}")
215
-
216
- def file_to_chunks(input,
217
- field: str = 'content',
218
- chunk_size: int = 1500,
219
- overlap: float = 0.2,
220
- threshold: int = 200,
221
- to_csv=False,
215
+
216
+ def file_to_chunks(input,
217
+ field: str = 'content',
218
+ chunk_size: int = 1500,
219
+ overlap: float = 0.2,
220
+ threshold: int = 200,
221
+ to_csv=False,
222
222
  project='project',
223
- output_dir='data/logs/sources/',
223
+ output_dir='data/logs/sources/',
224
224
  chunk_func = _file_to_chunks,
225
- filename=None,
226
- verbose=True,
227
- timestamp=True,
225
+ filename=None,
226
+ verbose=True,
227
+ timestamp=True,
228
228
  logger=None):
229
229
  """
230
230
  Splits text from a specified dictionary field into chunks and returns a list of dictionaries.
@@ -243,10 +243,10 @@ def file_to_chunks(input,
243
243
  timestamp: If True, include a timestamp in the exported file name.
244
244
  logger: An optional DataLogger instance for logging.
245
245
  """
246
-
246
+
247
247
  f = lambda x: chunk_func(x, field=field, chunk_size=chunk_size, overlap=overlap, threshold=threshold)
248
248
  logs = to_list(l_call(input, f), flat=True)
249
-
249
+
250
250
  if to_csv:
251
251
  filename = filename if filename else f"{project}_sources.csv"
252
252
  logger = DataLogger(log=logs) if not logger else logger
lionagi/utils/sys_util.py CHANGED
@@ -670,7 +670,7 @@ def create_id() -> str:
670
670
  random_bytes = os.urandom(16)
671
671
  return hashlib.sha256(current_time + random_bytes).hexdigest()[:16]
672
672
 
673
- def create_path(dir: str, filename: str, timestamp: bool = True, dir_exist_ok: bool = True) -> str:
673
+ def create_path(dir: str, filename: str, timestamp: bool = True, dir_exist_ok: bool = True, time_prefix=False) -> str:
674
674
  """
675
675
  Creates a file path by optionally appending a timestamp to the filename.
676
676
 
@@ -690,10 +690,14 @@ def create_path(dir: str, filename: str, timestamp: bool = True, dir_exist_ok: b
690
690
  >>> create_path('/tmp/', 'log.txt', timestamp=False)
691
691
  '/tmp/log.txt'
692
692
  """
693
+
694
+ dir = dir + '/' if str(dir)[-1] != '/' else dir
695
+ filename, ext = filename.split('.')
693
696
  os.makedirs(dir, exist_ok=dir_exist_ok)
697
+
694
698
  if timestamp:
695
699
  timestamp = get_timestamp()
696
- return f"{dir}{timestamp}{filename}"
700
+ return f"{dir}{timestamp}_{filename}.{ext}" if time_prefix else f"{dir}{filename}_{timestamp}.{ext}"
697
701
  else:
698
702
  return f"{dir}{filename}"
699
703
 
@@ -0,0 +1,194 @@
1
+ import json
2
+ import asyncio
3
+ from .sys_util import l_call
4
+
5
+
6
+ class ToolManager:
7
+ """
8
+ A manager class for handling and invoking registered tools and functions.
9
+
10
+ This class allows the registration of tools and functions, enabling their invocation.
11
+
12
+ Attributes:
13
+ registry (dict): A dictionary storing the registered tools and their corresponding functions.
14
+
15
+ Methods:
16
+ _to_dict(name, function, content=None) -> dict:
17
+ Convert tool information to a dictionary entry.
18
+
19
+ _name_existed(name) -> bool:
20
+ Check if a given name exists in the registry.
21
+
22
+ _register_function(name, function, content=None, update=False, new=False, prefix=None, postfix=None) -> None:
23
+ Register a function with a specified name in the registry.
24
+
25
+ invoke(name, args) -> Any:
26
+ Invoke a registered function with the provided arguments.
27
+
28
+ ainvoke(name, args) -> Any:
29
+ Asynchronously invoke a registered function with the provided arguments.
30
+
31
+ _get_function_call(response) -> Tuple[str, dict]:
32
+ Extract function name and arguments from a response JSON.
33
+
34
+ _from_tool(tool, func) -> Tuple[str, callable, list]:
35
+ Convert tool information to function registration parameters.
36
+
37
+ register_tools(tools, functions, update=False, new=False, prefix=None, postfix=None) -> None:
38
+ Register multiple tools and their corresponding functions.
39
+ """
40
+ def __init__(self):
41
+ """
42
+ Initialize a ToolManager object with an empty registry.
43
+ """
44
+ self.registry = {}
45
+
46
+ @staticmethod
47
+ def _to_dict(name, function, content=None):
48
+ """
49
+ Convert tool information to a dictionary entry.
50
+
51
+ Parameters:
52
+ name (str): The name of the tool.
53
+ function (callable): The function associated with the tool.
54
+ content (Optional[str]): Additional content for the tool.
55
+
56
+ Returns:
57
+ dict: A dictionary entry representing the tool.
58
+ """
59
+ return {name: {"function": function, "content": content or "none"}}
60
+
61
+ def _name_existed(self, name):
62
+ """
63
+ Check if a given name exists in the registry.
64
+
65
+ Parameters:
66
+ name (str): The name to check.
67
+
68
+ Returns:
69
+ bool: True if the name exists in the registry, False otherwise.
70
+
71
+ """
72
+ return True if name in self.registry.keys() else False
73
+
74
+ def _register_function(self, name, function, content=None, update=False, new=False, prefix=None, postfix=None):
75
+ """
76
+ Register a function with a specified name in the registry.
77
+
78
+ Parameters:
79
+ name (str): The name of the function.
80
+ function (callable): The function to register.
81
+ content (Optional[str]): Additional content for the function.
82
+ update (bool): Whether to update an existing function with the same name.
83
+ new (bool): Whether to create a new registry for an existing function.
84
+ prefix (Optional[str]): A prefix to add to the function name.
85
+ postfix (Optional[str]): A postfix to add to the function name.
86
+
87
+ """
88
+ if self._name_existed(name):
89
+ if update and new:
90
+ raise ValueError(f"Cannot both update and create new registry for existing function {name} at the same time")
91
+
92
+ name = f"{prefix or ''}{name}{postfix or '1'}" if new else name
93
+ self.registry.update(self._to_dict(name, function, content))
94
+
95
+ def invoke(self, name, args):
96
+ """
97
+ Invoke a registered function with the provided arguments.
98
+
99
+ Parameters:
100
+ name (str): The name of the function to invoke.
101
+ args (dict): The arguments to pass to the function.
102
+
103
+ Returns:
104
+ Any: The result of invoking the function.
105
+ """
106
+ if self._name_existed(name):
107
+ try:
108
+ return self.registry[name](**args)
109
+ except Exception as e:
110
+ raise ValueError(f"Error when invoking function {name} with arguments {args} with error message {e}")
111
+ else:
112
+ raise ValueError(f"Function {name} is not registered.")
113
+
114
+ async def ainvoke(self, name, args):
115
+ """
116
+ Asynchronously invoke a registered function with the provided arguments.
117
+
118
+ Parameters:
119
+ name (str): The name of the function to invoke.
120
+ args (dict): The arguments to pass to the function.
121
+
122
+ Returns:
123
+ Any: The result of invoking the function asynchronously.
124
+
125
+ """
126
+ if self._name_existed(name):
127
+ function = self.registry[name]["function"]
128
+ try:
129
+ if asyncio.iscoroutinefunction(function):
130
+ return await function(**args)
131
+ else:
132
+ return function(**args)
133
+ except Exception as e:
134
+ raise ValueError(f"Error when invoking function {name} with arguments {args} with error message {e}")
135
+ else:
136
+ raise ValueError(f"Function {name} is not registered.")
137
+
138
+ @staticmethod
139
+ def _get_function_call(response):
140
+ """
141
+ Extract function name and arguments from a response JSON.
142
+
143
+ Parameters:
144
+ response (str): The JSON response containing function information.
145
+
146
+ Returns:
147
+ Tuple[str, dict]: The function name and its arguments.
148
+ """
149
+ try:
150
+ out = json.loads(response)
151
+ func = out['function'][5:]
152
+ args = json.loads(out['arguments'])
153
+ return (func, args)
154
+ except:
155
+ try:
156
+ out = json.loads(response)
157
+ out = out['tool_uses'][0]
158
+ func = out['recipient_name'].split('.')[-1]
159
+ args = out['parameters']
160
+ return (func, args)
161
+ except:
162
+ raise ValueError('response is not a valid function call')
163
+
164
+ @staticmethod
165
+ def _from_tool(tool, func):
166
+ """
167
+ Convert tool information to function registration parameters.
168
+
169
+ Parameters:
170
+ tool (dict): The tool information.
171
+ func (callable): The function associated with the tool.
172
+
173
+ Returns:
174
+ Tuple[str, callable, list]: The function name, the function, and the list of function parameters.
175
+
176
+ """
177
+ return (tool['function']['name'], func,
178
+ tool['function']['parameters']['properties'].keys())
179
+
180
+ def register_tools(self, tools, functions, update=False, new=False, prefix=None, postfix=None):
181
+ """
182
+ Register multiple tools and their corresponding functions.
183
+
184
+ Parameters:
185
+ tools (list): The list of tool information dictionaries.
186
+ functions (list): The list of corresponding functions.
187
+ update (bool): Whether to update existing functions.
188
+ new (bool): Whether to create new registries for existing functions.
189
+ prefix (Optional[str]): A prefix to add to the function names.
190
+ postfix (Optional[str]): A postfix to add to the function names.
191
+
192
+ """
193
+ funcs = l_call(range(len(tools)), lambda i: self._from_tool(tools[i], functions[i]))
194
+ l_call(range(len(tools)), lambda i: self._register_function(funcs[i][0], funcs[i][1], update=update, new=new, prefix=prefix, postfix=postfix))
lionagi/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.0.104"
1
+ __version__ = "0.0.105"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lionagi
3
- Version: 0.0.104
3
+ Version: 0.0.105
4
4
  Summary: Towards automated general intelligence.
5
5
  Author: HaiyangLi
6
6
  Author-email: Haiyang Li <ocean@lionagi.ai>
@@ -227,7 +227,8 @@ Requires-Dist: httpx ==0.25.1
227
227
  - PyPI: https://pypi.org/project/lionagi/
228
228
  - Documentation: https://lionagi.readthedocs.io/en/latest/ (still a lot TODO)
229
229
  - Website: TODO
230
- - Discord: [Join Our Discord](https://discord.gg/ACnynvvPjt)
230
+ - Discord: [Join Our Discord](https://discord.gg/7RGWqpSxze)
231
+
231
232
 
232
233
  # LionAGI
233
234
  **Towards Automated General Intelligence**
@@ -286,7 +287,7 @@ Visit our notebooks for our examples.
286
287
 
287
288
  ### Community
288
289
 
289
- We encourage contributions to LionAGI and invite you to enrich its features and capabilities. Engage with us and other community members on [Discord](https://discord.gg/ACnynvvPjt)
290
+ We encourage contributions to LionAGI and invite you to enrich its features and capabilities. Engage with us and other community members [Join Our Discord](https://discord.gg/7RGWqpSxze)
290
291
 
291
292
  ### Citation
292
293
 
@@ -0,0 +1,21 @@
1
+ lionagi/__init__.py,sha256=2Rko3tw94ZFVN_GSvcxAY1O77FxswcaMxNHKH5Bj7jc,788
2
+ lionagi/version.py,sha256=WyIu1E1JGmXY5vMstqMyTqow6kk_Dcs2wEzR6Z1x6Ts,24
3
+ lionagi/api/__init__.py,sha256=RcmOxPnbaj5R6JYqQzQZ67KyVByJfyUw6QSw22KSo8g,134
4
+ lionagi/api/oai_config.py,sha256=yhyZ4aEaF6r3XBbhxI47r8CL2-amc-4IKJhbXv2W9CM,356
5
+ lionagi/api/oai_service.py,sha256=ctX4k3du_sl52n2LilSxXGHdce-igHXtEfpB6RrKbwQ,11209
6
+ lionagi/session/__init__.py,sha256=hbM6VwWz0Oh-Vld79JDFo5eYaCIqAn_OswmLiT0z4UA,58
7
+ lionagi/session/conversation.py,sha256=ZeaNJgmhA6aMG8cZMagRSF4gfsJNQKsNWAFxY6M2Y34,4057
8
+ lionagi/session/message.py,sha256=rjNeOSDgweW_eQfmsgsWTJ30slnfMEv0Tn4LHeAOgxo,6147
9
+ lionagi/session/session.py,sha256=007xhhUUbn60LpOqLsGlvRcio7t_77bx3z_GFir0rOk,12194
10
+ lionagi/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ lionagi/utils/__init__.py,sha256=jTZigmOboszESjWr9dP8PKtZ8XF_RqVd4Ni8s-GkaVs,760
12
+ lionagi/utils/api_util.py,sha256=WE51kMpKzmBwRqD0dkzxAMWzK04_k_5dth2kiOjVkMA,14837
13
+ lionagi/utils/doc_util.py,sha256=uT2paXguEs26kkW7oe2rR3CozQmpP2P9eJJdnZ9uM_E,12338
14
+ lionagi/utils/log_util.py,sha256=qbmaZxiX_bKY-LLaZcpMbTwi3aeBcK9-Lc93vkLIBuk,3103
15
+ lionagi/utils/sys_util.py,sha256=K4dumJ0th082RITpoz_F_eUw-OwkaLOz-BHoezuxwlU,28045
16
+ lionagi/utils/tool_util.py,sha256=OWQsGqAxiyxz2Q7cVE_JmnF19GKN2D9BNvJ09c98DlM,7461
17
+ lionagi-0.0.105.dist-info/LICENSE,sha256=TBnSyG8fs_tMRtK805GzA1cIyExleKyzoN_kuVxT9IY,11358
18
+ lionagi-0.0.105.dist-info/METADATA,sha256=SACNHjsB9hpR-d3Y5kfIhUsox3cdMTe_dLPHHFl08YU,17370
19
+ lionagi-0.0.105.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
20
+ lionagi-0.0.105.dist-info/top_level.txt,sha256=szvch_d2jE1Lu9ZIKsl26Ll6BGfYfbOgt5lm-UpFSo4,8
21
+ lionagi-0.0.105.dist-info/RECORD,,
@@ -1,19 +0,0 @@
1
- lionagi/__init__.py,sha256=2Rko3tw94ZFVN_GSvcxAY1O77FxswcaMxNHKH5Bj7jc,788
2
- lionagi/version.py,sha256=m9tOf0gVCkqN3dmK4Ruh3l4dO8KbQ-WtCnvEBME8wSU,24
3
- lionagi/api/__init__.py,sha256=RcmOxPnbaj5R6JYqQzQZ67KyVByJfyUw6QSw22KSo8g,134
4
- lionagi/api/oai_config.py,sha256=yhyZ4aEaF6r3XBbhxI47r8CL2-amc-4IKJhbXv2W9CM,356
5
- lionagi/api/oai_service.py,sha256=ctX4k3du_sl52n2LilSxXGHdce-igHXtEfpB6RrKbwQ,11209
6
- lionagi/session/__init__.py,sha256=hbM6VwWz0Oh-Vld79JDFo5eYaCIqAn_OswmLiT0z4UA,58
7
- lionagi/session/conversation.py,sha256=dedqlGEfIT26WfTJhBOlYWpz_-BFad1BkzIya2mkFwA,3436
8
- lionagi/session/message.py,sha256=bxvJbR0z9z97suz4sMKbNYIuJYsHuAXuTDgj3CI0qnM,2851
9
- lionagi/session/session.py,sha256=zTRMNaV8R3DKD10hm-wOAW8dSRVobu_aa7_lAT8I9kg,6812
10
- lionagi/utils/__init__.py,sha256=-9k5ILJjZ9bTq6U4NA3vNURG2HS7wsUdE1fEWItTGqM,710
11
- lionagi/utils/api_util.py,sha256=WE51kMpKzmBwRqD0dkzxAMWzK04_k_5dth2kiOjVkMA,14837
12
- lionagi/utils/doc_util.py,sha256=kZ3qRIKc5kAXFjeR8Z6oDzM4vRQVDw6rG5YDavme2zQ,12461
13
- lionagi/utils/log_util.py,sha256=qbmaZxiX_bKY-LLaZcpMbTwi3aeBcK9-Lc93vkLIBuk,3103
14
- lionagi/utils/sys_util.py,sha256=8S1S7V3Sk_Yyp2pfqrGyO_9w-wDHQ3Kzpez4yGvpZuM,27860
15
- lionagi-0.0.104.dist-info/LICENSE,sha256=TBnSyG8fs_tMRtK805GzA1cIyExleKyzoN_kuVxT9IY,11358
16
- lionagi-0.0.104.dist-info/METADATA,sha256=640tGgNFlJ91RYqHBU2B4VLx1dcGVlMztLmbXBPXeEs,17363
17
- lionagi-0.0.104.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
18
- lionagi-0.0.104.dist-info/top_level.txt,sha256=szvch_d2jE1Lu9ZIKsl26Ll6BGfYfbOgt5lm-UpFSo4,8
19
- lionagi-0.0.104.dist-info/RECORD,,