lionagi 0.0.105__py3-none-any.whl → 0.0.107__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- lionagi/api/oai_service.py +25 -13
- lionagi/session/conversation.py +22 -12
- lionagi/session/message.py +57 -30
- lionagi/session/session.py +130 -45
- lionagi/utils/__init__.py +4 -7
- lionagi/utils/api_util.py +91 -45
- lionagi/utils/doc_util.py +69 -26
- lionagi/utils/log_util.py +15 -4
- lionagi/utils/sys_util.py +74 -11
- lionagi/utils/tool_util.py +44 -29
- lionagi/version.py +1 -1
- {lionagi-0.0.105.dist-info → lionagi-0.0.107.dist-info}/METADATA +7 -12
- lionagi-0.0.107.dist-info/RECORD +20 -0
- lionagi/tools/__init__.py +0 -0
- lionagi-0.0.105.dist-info/RECORD +0 -21
- {lionagi-0.0.105.dist-info → lionagi-0.0.107.dist-info}/LICENSE +0 -0
- {lionagi-0.0.105.dist-info → lionagi-0.0.107.dist-info}/WHEEL +0 -0
- {lionagi-0.0.105.dist-info → lionagi-0.0.107.dist-info}/top_level.txt +0 -0
lionagi/api/oai_service.py
CHANGED
@@ -19,20 +19,25 @@ class OpenAIRateLimiter(RateLimiter):
|
|
19
19
|
and replenishing these limits at regular intervals.
|
20
20
|
|
21
21
|
Attributes:
|
22
|
-
max_requests_per_minute (int):
|
23
|
-
|
22
|
+
max_requests_per_minute (int):
|
23
|
+
Maximum number of requests allowed per minute.
|
24
|
+
max_tokens_per_minute (int):
|
25
|
+
Maximum number of tokens allowed per minute.
|
24
26
|
|
25
27
|
Methods:
|
26
|
-
rate_limit_replenisher:
|
27
|
-
|
28
|
+
rate_limit_replenisher:
|
29
|
+
Coroutine to replenish rate limits over time.
|
30
|
+
calculate_num_token:
|
31
|
+
Calculates the required tokens for a request.
|
28
32
|
"""
|
29
33
|
|
30
34
|
def __init__(self, max_requests_per_minute: int, max_tokens_per_minute: int) -> None:
|
31
35
|
"""
|
32
36
|
Initializes the rate limiter with specific limits for OpenAI API.
|
33
37
|
|
34
|
-
|
38
|
+
Parameters:
|
35
39
|
max_requests_per_minute (int): The maximum number of requests allowed per minute.
|
40
|
+
|
36
41
|
max_tokens_per_minute (int): The maximum number of tokens that can accumulate per minute.
|
37
42
|
"""
|
38
43
|
super().__init__(max_requests_per_minute, max_tokens_per_minute)
|
@@ -66,8 +71,9 @@ class OpenAIRateLimiter(RateLimiter):
|
|
66
71
|
This method should be implemented in a subclass to provide the specific calculation logic
|
67
72
|
for the OpenAI API.
|
68
73
|
|
69
|
-
|
74
|
+
Parameters:
|
70
75
|
payload (Dict[str, Any]): The payload of the request.
|
76
|
+
|
71
77
|
api_endpoint (str): The specific API endpoint for the request.
|
72
78
|
|
73
79
|
Returns:
|
@@ -160,12 +166,17 @@ class OpenAIService(BaseAPIService):
|
|
160
166
|
"""
|
161
167
|
Initializes the OpenAI service with configuration for API interaction.
|
162
168
|
|
163
|
-
|
169
|
+
Parameters:
|
164
170
|
api_key (str): The API key for authenticating with OpenAI.
|
171
|
+
|
165
172
|
token_encoding_name (str): The name of the text encoding used by OpenAI.
|
173
|
+
|
166
174
|
max_attempts (int): The maximum number of attempts for calling an API endpoint.
|
175
|
+
|
167
176
|
status_tracker (Optional[StatusTracker]): Tracker for API call outcomes.
|
168
|
-
|
177
|
+
|
178
|
+
ratelimiter (Optional[OpenAIRateLimiter]): Rate limiter for OpenAI's limits.
|
179
|
+
|
169
180
|
queue (Optional[AsyncQueue]): Queue for managing asynchronous API calls.
|
170
181
|
|
171
182
|
Example:
|
@@ -183,15 +194,16 @@ class OpenAIService(BaseAPIService):
|
|
183
194
|
super().__init__(api_key, token_encoding_name, max_attempts,
|
184
195
|
max_requests_per_minute, max_tokens_per_minute,
|
185
196
|
ratelimiter, status_tracker, queue)
|
186
|
-
|
187
197
|
|
188
|
-
async def call_api(self, http_session, endpoint, payload: Dict[str, any] =None) -> Optional[Dict[str, any]]:
|
198
|
+
async def call_api(self, http_session, endpoint, payload: Dict[str, any] = None) -> Optional[Dict[str, any]]:
|
189
199
|
"""
|
190
200
|
Call an OpenAI API endpoint with a specific payload and handle the response.
|
191
201
|
|
192
|
-
|
193
|
-
|
194
|
-
|
202
|
+
Parameters:
|
203
|
+
http_session: The session object for making HTTP requests.
|
204
|
+
|
205
|
+
endpoint (str): The full URL of the OpenAI API endpoint to be called.
|
206
|
+
|
195
207
|
payload (Dict[str, any]): The payload to send with the API request.
|
196
208
|
|
197
209
|
Returns:
|
lionagi/session/conversation.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
from .message import Message
|
2
2
|
|
3
|
+
|
3
4
|
class Conversation:
|
4
5
|
"""
|
5
6
|
A class representing a conversation between users and the assistant.
|
@@ -8,21 +9,22 @@ class Conversation:
|
|
8
9
|
user instructions, and assistant responses.
|
9
10
|
|
10
11
|
Attributes:
|
11
|
-
response_counts (int):
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
response_counts (int):
|
13
|
+
The count of assistant responses in the conversation.
|
14
|
+
messages (list):
|
15
|
+
A list to store messages in the conversation.
|
16
|
+
msg (Message):
|
17
|
+
An instance of the Message class for creating messages.
|
18
|
+
responses (list):
|
19
|
+
A list to store assistant responses in the conversation.
|
15
20
|
|
16
21
|
Methods:
|
17
22
|
initiate_conversation(system, instruction, context=None, name=None):
|
18
23
|
Initiate a conversation with a system setting and user instruction.
|
19
|
-
|
20
24
|
add_messages(system, instruction, context=None, response=None, tool=None, name=None):
|
21
25
|
Add messages to the conversation, including system setting, user instruction, and assistant response.
|
22
|
-
|
23
26
|
change_system(system):
|
24
27
|
Change the system setting in the conversation.
|
25
|
-
|
26
28
|
keep_last_n_exchanges(n: int):
|
27
29
|
Keep the last n exchanges in the conversation.
|
28
30
|
"""
|
@@ -40,14 +42,17 @@ class Conversation:
|
|
40
42
|
self.msg = Message()
|
41
43
|
self.responses = []
|
42
44
|
|
43
|
-
def initiate_conversation(self, system, instruction, context=None, name=None):
|
45
|
+
def initiate_conversation(self, system=None, instruction=None, context=None, name=None):
|
44
46
|
"""
|
45
47
|
Initiate a conversation with a system setting and user instruction.
|
46
48
|
|
47
49
|
Parameters:
|
48
50
|
system (str): The system setting for the conversation.
|
51
|
+
|
49
52
|
instruction (str): The user instruction to initiate the conversation.
|
53
|
+
|
50
54
|
context (dict): Additional context for the conversation. Default is None.
|
55
|
+
|
51
56
|
name (str): The name associated with the user. Default is None.
|
52
57
|
"""
|
53
58
|
self.messages, self.responses = [], []
|
@@ -55,19 +60,23 @@ class Conversation:
|
|
55
60
|
self.add_messages(instruction=instruction, context=context, name=name)
|
56
61
|
|
57
62
|
# modify the message adding to accomodate tools
|
58
|
-
def add_messages(self, system=None, instruction=None, context=None, response=None,
|
63
|
+
def add_messages(self, system=None, instruction=None, context=None, response=None, name=None):
|
59
64
|
"""
|
60
65
|
Add messages to the conversation, including system setting, user instruction, and assistant response.
|
61
66
|
|
62
67
|
Parameters:
|
63
68
|
system (str): The system setting for the message. Default is None.
|
69
|
+
|
64
70
|
instruction (str): The instruction content for the message. Default is None.
|
71
|
+
|
65
72
|
context (dict): Additional context for the message. Default is None.
|
73
|
+
|
66
74
|
response (dict): The response content for the message. Default is None.
|
67
|
-
|
75
|
+
|
68
76
|
name (str): The name associated with the message. Default is None.
|
69
77
|
"""
|
70
|
-
msg = self.msg(system=system, instruction=instruction, context=context,
|
78
|
+
msg = self.msg(system=system, instruction=instruction, context=context,
|
79
|
+
response=response, name=name)
|
71
80
|
self.messages.append(msg)
|
72
81
|
|
73
82
|
def change_system(self, system):
|
@@ -92,4 +101,5 @@ class Conversation:
|
|
92
101
|
]
|
93
102
|
if len(response_indices) >= n:
|
94
103
|
first_index_to_keep = response_indices[-n] + 1
|
95
|
-
self.messages =
|
104
|
+
self.messages = self.messages[0] + self.messages[first_index_to_keep:]
|
105
|
+
|
lionagi/session/message.py
CHANGED
@@ -11,11 +11,16 @@ class Message:
|
|
11
11
|
This class encapsulates messages from users, the assistant, systems, and external tools.
|
12
12
|
|
13
13
|
Attributes:
|
14
|
-
role (str):
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
role (str):
|
15
|
+
The role of the message, indicating if it's from the user, assistant, system, or tool.
|
16
|
+
content:
|
17
|
+
The content of the message, which can be an instruction, response, system setting, or tool information.
|
18
|
+
name (str):
|
19
|
+
The name associated with the message, specifying the source (user, assistant, system, or tool).
|
20
|
+
metadata (dict):
|
21
|
+
Additional metadata including id, timestamp, and name.
|
22
|
+
_logger (DataLogger):
|
23
|
+
An instance of the DataLogger class for logging message details.
|
19
24
|
|
20
25
|
Methods:
|
21
26
|
create_message(system, instruction, context, response, tool, name):
|
@@ -40,37 +45,52 @@ class Message:
|
|
40
45
|
self.metadata = None
|
41
46
|
self._logger = DataLogger()
|
42
47
|
|
43
|
-
def create_message(self, system=None, instruction=None, context=None, response=None,
|
48
|
+
def create_message(self, system=None, instruction=None, context=None, response=None, name=None):
|
49
|
+
|
44
50
|
"""
|
45
51
|
Create a message based on the provided information.
|
46
52
|
|
47
53
|
Parameters:
|
48
54
|
system (str): The system setting for the message. Default is None.
|
55
|
+
|
49
56
|
instruction (str): The instruction content for the message. Default is None.
|
57
|
+
|
50
58
|
context (dict): Additional context for the message. Default is None.
|
59
|
+
|
51
60
|
response (dict): The response content for the message. Default is None.
|
52
|
-
|
61
|
+
|
53
62
|
name (str): The name associated with the message. Default is None.
|
54
63
|
"""
|
55
|
-
if sum(l_call([system, instruction, response
|
64
|
+
if sum(l_call([system, instruction, response], bool)) > 1:
|
56
65
|
raise ValueError("Error: Message cannot have more than one role.")
|
57
66
|
|
58
67
|
else:
|
59
68
|
if response:
|
60
69
|
self.role = "assistant"
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
70
|
+
try:
|
71
|
+
response = response["message"]
|
72
|
+
if str(response['content']) == "None":
|
73
|
+
try:
|
74
|
+
tool_count = 0
|
75
|
+
func_list = []
|
76
|
+
while tool_count < len(response['tool_calls']):
|
77
|
+
if response['tool_calls'][tool_count]['type'] == 'function':
|
78
|
+
func_content = {"function": ("func_" + response['tool_calls'][tool_count]['function']['name']),
|
79
|
+
"arguments": response['tool_calls'][tool_count]['function']['arguments']}
|
80
|
+
func_list.append(func_content)
|
81
|
+
tool_count += 1
|
82
|
+
|
83
|
+
self.name = name or "func_request"
|
84
|
+
self.content = {'function_list': func_list}
|
85
|
+
except:
|
86
|
+
raise ValueError("Response message must be one of regular response or function calling")
|
87
|
+
else:
|
88
|
+
self.content = response['content']
|
89
|
+
self.name = name or "assistant"
|
90
|
+
except:
|
91
|
+
self.name = name or "func_call"
|
92
|
+
self.content = response
|
93
|
+
|
74
94
|
elif instruction:
|
75
95
|
self.role = "user"
|
76
96
|
self.content = {"instruction": instruction}
|
@@ -81,17 +101,13 @@ class Message:
|
|
81
101
|
self.role = "system"
|
82
102
|
self.content = system
|
83
103
|
self.name = name or "system"
|
84
|
-
elif tool:
|
85
|
-
self.role = "tool"
|
86
|
-
self.content = tool
|
87
|
-
self.name = name or "tool"
|
88
104
|
|
89
105
|
def to_json(self):
|
90
106
|
"""
|
91
107
|
Convert the message to a JSON format.
|
92
108
|
|
93
109
|
Returns:
|
94
|
-
|
110
|
+
dict: The message in JSON format.
|
95
111
|
"""
|
96
112
|
out = {
|
97
113
|
"role": self.role,
|
@@ -106,22 +122,27 @@ class Message:
|
|
106
122
|
self._logger({**self.metadata, **out})
|
107
123
|
return out
|
108
124
|
|
109
|
-
def __call__(self, system=None, instruction=None, context=None,
|
125
|
+
def __call__(self, system=None, instruction=None, context=None,
|
126
|
+
response=None, name=None):
|
110
127
|
"""
|
111
128
|
Create and return a message in JSON format.
|
112
129
|
|
113
130
|
Parameters:
|
114
131
|
system (str): The system setting for the message. Default is None.
|
132
|
+
|
115
133
|
instruction (str): The instruction content for the message. Default is None.
|
134
|
+
|
116
135
|
context (dict): Additional context for the message. Default is None.
|
136
|
+
|
117
137
|
response (dict): The response content for the message. Default is None.
|
138
|
+
|
118
139
|
name (str): The name associated with the message. Default is None.
|
119
|
-
tool (dict): The tool information for the message. Default is None.
|
120
140
|
|
121
141
|
Returns:
|
122
142
|
dict: The message in JSON format.
|
123
143
|
"""
|
124
|
-
self.create_message(system, instruction,
|
144
|
+
self.create_message(system=system, instruction=instruction,
|
145
|
+
context=context, response=response, name=name)
|
125
146
|
return self.to_json()
|
126
147
|
|
127
148
|
def to_csv(self, dir=None, filename=None, verbose=True, timestamp=True, dir_exist_ok=True, file_exist_ok=False):
|
@@ -130,10 +151,16 @@ class Message:
|
|
130
151
|
|
131
152
|
Parameters:
|
132
153
|
dir (str): The directory path for saving the CSV file. Default is None.
|
154
|
+
|
133
155
|
filename (str): The filename for the CSV file. Default is None.
|
156
|
+
|
134
157
|
verbose (bool): Whether to include verbose information in the CSV. Default is True.
|
158
|
+
|
135
159
|
timestamp (bool): Whether to include timestamps in the CSV. Default is True.
|
160
|
+
|
136
161
|
dir_exist_ok (bool): Whether to allow the directory to exist. Default is True.
|
162
|
+
|
137
163
|
file_exist_ok (bool): Whether to allow the file to exist. Default is False.
|
138
164
|
"""
|
139
|
-
self._logger.to_csv(dir, filename, verbose, timestamp, dir_exist_ok, file_exist_ok)
|
165
|
+
self._logger.to_csv(dir, filename, verbose, timestamp, dir_exist_ok, file_exist_ok)
|
166
|
+
|
lionagi/session/session.py
CHANGED
@@ -1,20 +1,21 @@
|
|
1
1
|
import aiohttp
|
2
2
|
import asyncio
|
3
|
+
import json
|
3
4
|
from typing import Any
|
4
5
|
|
6
|
+
import lionagi
|
5
7
|
from .conversation import Conversation
|
6
|
-
from ..utils.sys_util import to_list
|
8
|
+
from ..utils.sys_util import to_list, l_call, al_call
|
7
9
|
from ..utils.log_util import DataLogger
|
8
10
|
from ..utils.api_util import StatusTracker
|
9
11
|
from ..utils.tool_util import ToolManager
|
10
12
|
from ..api.oai_service import OpenAIService
|
11
|
-
|
12
13
|
from ..api.oai_config import oai_llmconfig
|
13
14
|
|
14
|
-
|
15
15
|
status_tracker = StatusTracker()
|
16
16
|
OAIService = OpenAIService()
|
17
17
|
|
18
|
+
|
18
19
|
class Session():
|
19
20
|
"""
|
20
21
|
A class representing a conversation session with a conversational AI system.
|
@@ -22,12 +23,18 @@ class Session():
|
|
22
23
|
This class manages the flow of conversation, system settings, and interactions with external tools.
|
23
24
|
|
24
25
|
Attributes:
|
25
|
-
conversation (Conversation):
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
conversation (Conversation):
|
27
|
+
An instance of the Conversation class to manage messages.
|
28
|
+
system (str):
|
29
|
+
The current system setting for the conversation.
|
30
|
+
llmconfig (dict):
|
31
|
+
Configuration settings for the language model.
|
32
|
+
_logger (DataLogger):
|
33
|
+
An instance of the DataLogger class for logging conversation details.
|
34
|
+
api_service:
|
35
|
+
An instance of the API service for making calls to the conversational AI model.
|
36
|
+
_toolmanager (ToolManager):
|
37
|
+
An instance of the ToolManager class for managing external tools.
|
31
38
|
|
32
39
|
Methods:
|
33
40
|
set_dir(dir):
|
@@ -54,6 +61,9 @@ class Session():
|
|
54
61
|
followup(instruction, system=None, context=None, out=True, name=None, invoke=True, **kwargs) -> Any:
|
55
62
|
Continue the conversation with the provided instruction.
|
56
63
|
|
64
|
+
auto_followup(self, instruct, num=3, tool_parser=None, **kwags):
|
65
|
+
Automates the follow-up process for a specified number of times or until the session concludes.
|
66
|
+
|
57
67
|
create_payload_chatcompletion(**kwargs) -> dict:
|
58
68
|
Create a payload for chat completion based on the conversation state and configuration.
|
59
69
|
|
@@ -73,8 +83,11 @@ class Session():
|
|
73
83
|
|
74
84
|
Parameters:
|
75
85
|
system (str): The initial system setting for the conversation.
|
86
|
+
|
76
87
|
dir (Optional[str]): The directory for logging. Default is None.
|
88
|
+
|
77
89
|
llmconfig (Optional[dict]): Configuration settings for the language model. Default is oai_llmconfig.
|
90
|
+
|
78
91
|
api_service: An instance of the API service for making calls to the conversational AI model.
|
79
92
|
"""
|
80
93
|
self.conversation = Conversation()
|
@@ -82,7 +95,7 @@ class Session():
|
|
82
95
|
self.llmconfig = llmconfig
|
83
96
|
self._logger = DataLogger(dir=dir)
|
84
97
|
self.api_service = api_service
|
85
|
-
self.
|
98
|
+
self._toolmanager = ToolManager()
|
86
99
|
|
87
100
|
def set_dir(self, dir):
|
88
101
|
"""
|
@@ -120,55 +133,94 @@ class Session():
|
|
120
133
|
"""
|
121
134
|
self.api_service = api_service
|
122
135
|
|
123
|
-
async def _output(self,
|
136
|
+
async def _output(self, invoke=True, out=True, tool_parser=None):
|
124
137
|
"""
|
125
138
|
Process the output, invoke tools if needed, and optionally return the output.
|
126
139
|
|
127
140
|
Parameters:
|
128
|
-
output: The output to process.
|
129
141
|
invoke (bool): Whether to invoke tools based on the output. Default is True.
|
142
|
+
|
130
143
|
out (bool): Whether to return the output. Default is True.
|
131
144
|
|
132
145
|
Returns:
|
133
146
|
Any: The processed output.
|
134
147
|
"""
|
135
148
|
if invoke:
|
136
|
-
try:
|
137
|
-
|
138
|
-
|
139
|
-
|
149
|
+
try:
|
150
|
+
tool_uses = json.loads(self.conversation.responses[-1]['content'])
|
151
|
+
if 'function_list' in tool_uses.keys():
|
152
|
+
func_calls = l_call(tool_uses['function_list'], self._toolmanager._get_function_call)
|
153
|
+
|
154
|
+
else:
|
155
|
+
func_calls = l_call(tool_uses['tool_uses'], self._toolmanager._get_function_call)
|
156
|
+
|
157
|
+
outs = await al_call(func_calls, self._toolmanager.ainvoke)
|
158
|
+
if tool_parser:
|
159
|
+
outs = l_call(outs, tool_parser)
|
160
|
+
for out, f in zip(outs, func_calls):
|
161
|
+
response = {"function": f[0], "arguments": f[1], "output": out}
|
162
|
+
self.conversation.add_messages(response=response)
|
163
|
+
|
140
164
|
except:
|
141
165
|
pass
|
166
|
+
|
142
167
|
if out:
|
143
|
-
return
|
144
|
-
|
168
|
+
return self.conversation.responses[-1]['content']
|
169
|
+
|
170
|
+
def _is_invoked(self):
|
171
|
+
"""
|
172
|
+
Checks if the current message indicates the invocation of a function call.
|
173
|
+
|
174
|
+
Returns:
|
175
|
+
bool: True if a function call is detected in the content of the last message, False otherwise.
|
176
|
+
"""
|
177
|
+
msg = self.conversation.messages[-1]
|
178
|
+
try:
|
179
|
+
if json.loads(msg['content']).keys() >= {'function', 'arguments', 'output'}:
|
180
|
+
return True
|
181
|
+
except:
|
182
|
+
return False
|
183
|
+
|
145
184
|
def register_tools(self, tools, funcs, update=False, new=False, prefix=None, postfix=None):
|
146
185
|
"""
|
147
186
|
Register tools and their corresponding functions.
|
148
187
|
|
149
188
|
Parameters:
|
150
189
|
tools (list): The list of tool information dictionaries.
|
190
|
+
|
151
191
|
funcs (list): The list of corresponding functions.
|
192
|
+
|
152
193
|
update (bool): Whether to update existing functions.
|
194
|
+
|
153
195
|
new (bool): Whether to create new registries for existing functions.
|
196
|
+
|
154
197
|
prefix (Optional[str]): A prefix to add to the function names.
|
198
|
+
|
155
199
|
postfix (Optional[str]): A postfix to add to the function names.
|
156
200
|
"""
|
157
201
|
funcs = to_list(funcs)
|
158
|
-
self.
|
202
|
+
self._toolmanager.register_tools(tools, funcs, update, new, prefix, postfix)
|
159
203
|
|
160
|
-
async def initiate(self, instruction, system=None, context=None,
|
204
|
+
async def initiate(self, instruction, system=None, context=None, name=None, invoke=True, out=True, tool_parser=None, **kwargs) -> Any:
|
161
205
|
"""
|
162
206
|
Start a new conversation session with the provided instruction.
|
163
207
|
|
164
208
|
Parameters:
|
165
|
-
instruction (str): The instruction to initiate the conversation.
|
209
|
+
instruction (Union[str, dict]): The instruction to initiate the conversation.
|
210
|
+
|
166
211
|
system (Optional[str]): The system setting for the conversation. Default is None.
|
212
|
+
|
167
213
|
context (Optional[dict]): Additional context for the instruction. Default is None.
|
214
|
+
|
168
215
|
out (bool): Whether to return the output. Default is True.
|
216
|
+
|
169
217
|
name (Optional[str]): The name associated with the instruction. Default is None.
|
218
|
+
|
170
219
|
invoke (bool): Whether to invoke tools based on the output. Default is True.
|
171
|
-
|
220
|
+
|
221
|
+
tool_parser (Optional[callable]): A custom tool parser function. Default is None.
|
222
|
+
|
223
|
+
**kwargs: Additional keyword arguments for configuration.
|
172
224
|
|
173
225
|
Returns:
|
174
226
|
Any: The processed output.
|
@@ -176,23 +228,30 @@ class Session():
|
|
176
228
|
config = {**self.llmconfig, **kwargs}
|
177
229
|
system = system or self.system
|
178
230
|
self.conversation.initiate_conversation(system=system, instruction=instruction, context=context, name=name)
|
179
|
-
await self.
|
180
|
-
output = self.conversation.responses[-1]['content']
|
231
|
+
await self._call_chatcompletion(**config)
|
181
232
|
|
182
|
-
return await self._output(
|
233
|
+
return await self._output(invoke, out, tool_parser)
|
183
234
|
|
184
|
-
async def followup(self, instruction, system=None, context=None, out=True, name=None, invoke=True, **kwargs) -> Any:
|
235
|
+
async def followup(self, instruction, system=None, context=None, out=True, name=None, invoke=True, tool_parser=None, **kwargs) -> Any:
|
185
236
|
"""
|
186
237
|
Continue the conversation with the provided instruction.
|
187
238
|
|
188
239
|
Parameters:
|
189
|
-
instruction (str): The instruction to continue the conversation.
|
240
|
+
instruction (Union[str, dict]): The instruction to continue the conversation.
|
241
|
+
|
190
242
|
system (Optional[str]): The system setting for the conversation. Default is None.
|
243
|
+
|
191
244
|
context (Optional[dict]): Additional context for the instruction. Default is None.
|
245
|
+
|
192
246
|
out (bool): Whether to return the output. Default is True.
|
247
|
+
|
193
248
|
name (Optional[str]): The name associated with the instruction. Default is None.
|
249
|
+
|
194
250
|
invoke (bool): Whether to invoke tools based on the output. Default is True.
|
195
|
-
|
251
|
+
|
252
|
+
tool_parser (Optional[callable]): A custom tool parser function. Default is None.
|
253
|
+
|
254
|
+
**kwargs: Additional keyword arguments for configuration.
|
196
255
|
|
197
256
|
Returns:
|
198
257
|
Any: The processed output.
|
@@ -201,17 +260,38 @@ class Session():
|
|
201
260
|
self.conversation.change_system(system)
|
202
261
|
self.conversation.add_messages(instruction=instruction, context=context, name=name)
|
203
262
|
config = {**self.llmconfig, **kwargs}
|
204
|
-
await self.
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
263
|
+
await self._call_chatcompletion(**config)
|
264
|
+
|
265
|
+
return await self._output(invoke, out, tool_parser)
|
266
|
+
|
267
|
+
async def auto_followup(self, instruct, num=3, tool_parser=None, **kwargs):
|
268
|
+
"""
|
269
|
+
Automates the follow-up process for a specified number of times or until the session concludes.
|
270
|
+
|
271
|
+
Parameters:
|
272
|
+
instruct (Union[str, dict]): The instruction for the follow-up.
|
273
|
+
|
274
|
+
num (int, optional): The number of times to automatically follow up. Defaults to 3.
|
275
|
+
|
276
|
+
tool_parser (callable, optional): A custom tool parser function. Defaults to None.
|
277
|
+
|
278
|
+
**kwargs: Additional keyword arguments passed to the underlying `followup` method.
|
279
|
+
|
280
|
+
"""
|
281
|
+
cont_ = True
|
282
|
+
while num > 0 and cont_ is True:
|
283
|
+
await self.followup(instruct, tool_parser=tool_parser, tool_choice="auto", **kwargs)
|
284
|
+
num -= 1
|
285
|
+
cont_ = True if self._is_invoked() else False
|
286
|
+
if num == 0:
|
287
|
+
await self.followup(instruct, **kwargs)
|
288
|
+
|
289
|
+
def _create_payload_chatcompletion(self, **kwargs):
|
210
290
|
"""
|
211
291
|
Create a payload for chat completion based on the conversation state and configuration.
|
212
292
|
|
213
293
|
Parameters:
|
214
|
-
kwargs: Additional keyword arguments for configuration.
|
294
|
+
**kwargs: Additional keyword arguments for configuration.
|
215
295
|
|
216
296
|
Returns:
|
217
297
|
dict: The payload for chat completion.
|
@@ -235,22 +315,23 @@ class Session():
|
|
235
315
|
payload.update({key: config[key]})
|
236
316
|
return payload
|
237
317
|
|
238
|
-
async def
|
318
|
+
async def _call_chatcompletion(self, sleep=0.1, **kwargs):
|
239
319
|
"""
|
240
320
|
Make a call to the chat completion API and process the response.
|
241
321
|
|
242
322
|
Parameters:
|
243
323
|
sleep (float): The sleep duration after making the API call. Default is 0.1.
|
244
|
-
|
324
|
+
|
325
|
+
**kwargs: Additional keyword arguments for configuration.
|
245
326
|
"""
|
246
327
|
endpoint = f"chat/completions"
|
247
328
|
try:
|
248
329
|
async with aiohttp.ClientSession() as session:
|
249
|
-
payload = self.
|
330
|
+
payload = self._create_payload_chatcompletion(**kwargs)
|
250
331
|
completion = await self.api_service.call_api(
|
251
332
|
session, endpoint, payload)
|
252
333
|
if "choices" in completion:
|
253
|
-
self._logger({"input":payload, "output": completion})
|
334
|
+
self._logger({"input": payload, "output": completion})
|
254
335
|
self.conversation.add_messages(response=completion['choices'][0])
|
255
336
|
self.conversation.responses.append(self.conversation.messages[-1])
|
256
337
|
self.conversation.response_counts += 1
|
@@ -262,30 +343,34 @@ class Session():
|
|
262
343
|
status_tracker.num_tasks_failed += 1
|
263
344
|
raise e
|
264
345
|
|
265
|
-
def messages_to_csv(self, dir=None, filename="_messages.csv", **
|
346
|
+
def messages_to_csv(self, dir=None, filename="_messages.csv", **kwargs):
|
266
347
|
"""
|
267
348
|
Save conversation messages to a CSV file.
|
268
349
|
|
269
350
|
Parameters:
|
270
351
|
dir (Optional[str]): The directory path for saving the CSV file. Default is None.
|
352
|
+
|
271
353
|
filename (Optional[str]): The filename for the CSV file. Default is "_messages.csv".
|
272
|
-
|
354
|
+
|
355
|
+
**kwargs: Additional keyword arguments for CSV file settings.
|
273
356
|
"""
|
274
357
|
dir = dir or self._logger.dir
|
275
358
|
if dir is None:
|
276
359
|
raise ValueError("No directory specified.")
|
277
|
-
self.conversation.msg.to_csv(dir=dir, filename=filename, **
|
360
|
+
self.conversation.msg.to_csv(dir=dir, filename=filename, **kwargs)
|
278
361
|
|
279
|
-
def log_to_csv(self, dir=None, filename="_llmlog.csv", **
|
362
|
+
def log_to_csv(self, dir=None, filename="_llmlog.csv", **kwargs):
|
280
363
|
"""
|
281
364
|
Save conversation logs to a CSV file.
|
282
365
|
|
283
366
|
Parameters:
|
284
367
|
dir (Optional[str]): The directory path for saving the CSV file. Default is None.
|
368
|
+
|
285
369
|
filename (Optional[str]): The filename for the CSV file. Default is "_llmlog.csv".
|
286
|
-
|
370
|
+
|
371
|
+
**kwargs: Additional keyword arguments for CSV file settings.
|
287
372
|
"""
|
288
373
|
dir = dir or self._logger.dir
|
289
374
|
if dir is None:
|
290
375
|
raise ValueError("No directory specified.")
|
291
|
-
self._logger.to_csv(dir=dir, filename=filename, **
|
376
|
+
self._logger.to_csv(dir=dir, filename=filename, **kwargs)
|