autonomous-app 0.3.26__py3-none-any.whl → 0.3.28__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- autonomous/__init__.py +1 -1
- autonomous/ai/jsonagent.py +7 -3
- autonomous/ai/models/gemini.py +107 -30
- autonomous/ai/textagent.py +8 -5
- {autonomous_app-0.3.26.dist-info → autonomous_app-0.3.28.dist-info}/METADATA +1 -1
- {autonomous_app-0.3.26.dist-info → autonomous_app-0.3.28.dist-info}/RECORD +8 -8
- {autonomous_app-0.3.26.dist-info → autonomous_app-0.3.28.dist-info}/WHEEL +0 -0
- {autonomous_app-0.3.26.dist-info → autonomous_app-0.3.28.dist-info}/top_level.txt +0 -0
autonomous/__init__.py
CHANGED
autonomous/ai/jsonagent.py
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import json
|
|
2
2
|
|
|
3
|
+
from autonomous.ai.baseagent import BaseAgent
|
|
3
4
|
from autonomous.model.autoattr import ReferenceAttr, StringAttr
|
|
4
5
|
from autonomous.model.automodel import AutoModel
|
|
5
|
-
|
|
6
|
+
|
|
6
7
|
from .models.openai import OpenAIModel
|
|
7
8
|
|
|
8
9
|
|
|
@@ -15,12 +16,15 @@ class JSONAgent(BaseAgent):
|
|
|
15
16
|
default="A helpful AI assistant trained to assist with generating JSON formatted data."
|
|
16
17
|
)
|
|
17
18
|
|
|
18
|
-
def generate(self, messages, function, additional_instructions=""):
|
|
19
|
+
def generate(self, messages, function, additional_instructions="", **kwargs):
|
|
19
20
|
result = self.get_client().generate_json(
|
|
20
|
-
messages, function, additional_instructions
|
|
21
|
+
messages, function, additional_instructions, **kwargs
|
|
21
22
|
)
|
|
22
23
|
if isinstance(result, str):
|
|
23
24
|
result = json.loads(result)
|
|
24
25
|
elif not isinstance(result, dict):
|
|
25
26
|
raise ValueError(f"Invalid JSON response from AI model.\n\n{result}")
|
|
26
27
|
return result
|
|
28
|
+
|
|
29
|
+
def upload(self, file):
|
|
30
|
+
return self.get_client().upload(file=file)
|
autonomous/ai/models/gemini.py
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import io
|
|
2
2
|
import os
|
|
3
3
|
import random
|
|
4
|
+
import re
|
|
5
|
+
import time
|
|
4
6
|
import wave
|
|
5
7
|
|
|
6
8
|
from google import genai
|
|
7
9
|
from google.genai import types
|
|
10
|
+
from google.genai.types import Part
|
|
8
11
|
from pydub import AudioSegment
|
|
9
12
|
|
|
10
13
|
from autonomous import log
|
|
@@ -20,7 +23,18 @@ class GeminiAIModel(AutoModel):
|
|
|
20
23
|
_json_model = "gemini-3-pro-preview"
|
|
21
24
|
_stt_model = "gemini-3-pro-preview"
|
|
22
25
|
_tts_model = "gemini-2.5-flash-preview-tts"
|
|
26
|
+
|
|
27
|
+
messages = ListAttr(StringAttr(default=[]))
|
|
28
|
+
name = StringAttr(default="agent")
|
|
29
|
+
instructions = StringAttr(
|
|
30
|
+
default="You are highly skilled AI trained to assist with various tasks."
|
|
31
|
+
)
|
|
32
|
+
description = StringAttr(
|
|
33
|
+
default="A helpful AI assistant trained to assist with various tasks."
|
|
34
|
+
)
|
|
35
|
+
|
|
23
36
|
MAX_FILES = 14
|
|
37
|
+
MAX_SUMMARY_TOKEN_LENGTH = 10000
|
|
24
38
|
VOICES = {
|
|
25
39
|
"Zephyr": ["female"],
|
|
26
40
|
"Puck": ["male"],
|
|
@@ -54,15 +68,6 @@ class GeminiAIModel(AutoModel):
|
|
|
54
68
|
"Sulafar": ["female"],
|
|
55
69
|
}
|
|
56
70
|
|
|
57
|
-
messages = ListAttr(StringAttr(default=[]))
|
|
58
|
-
name = StringAttr(default="agent")
|
|
59
|
-
instructions = StringAttr(
|
|
60
|
-
default="You are highly skilled AI trained to assist with various tasks."
|
|
61
|
-
)
|
|
62
|
-
description = StringAttr(
|
|
63
|
-
default="A helpful AI assistant trained to assist with various tasks."
|
|
64
|
-
)
|
|
65
|
-
|
|
66
71
|
@property
|
|
67
72
|
def client(self):
|
|
68
73
|
if not self._client:
|
|
@@ -106,13 +111,60 @@ class GeminiAIModel(AutoModel):
|
|
|
106
111
|
buffer.seek(0)
|
|
107
112
|
return buffer
|
|
108
113
|
|
|
109
|
-
def
|
|
114
|
+
def _add_files(self, file_list):
|
|
115
|
+
existing_files = self.client.files.list()
|
|
116
|
+
log(f"Existing files: {[f.display_name for f in existing_files]}", _print=True)
|
|
117
|
+
for f in existing_files:
|
|
118
|
+
# Delete old files (older than 10 minutes)
|
|
119
|
+
age_seconds = (
|
|
120
|
+
(time.time() - f.update_time.timestamp())
|
|
121
|
+
if f.update_time
|
|
122
|
+
else (time.time() - f.create_time.timestamp())
|
|
123
|
+
)
|
|
124
|
+
log(age_seconds, _print=True)
|
|
125
|
+
if age_seconds > 900:
|
|
126
|
+
result = self.client.files.delete(name=f.name)
|
|
127
|
+
log(f"Deleting old version of {f.name}: {result}", _print=True)
|
|
128
|
+
file_refs = []
|
|
129
|
+
for file_dict in file_list:
|
|
130
|
+
fn = file_dict["name"]
|
|
131
|
+
fileobj = file_dict["file"]
|
|
132
|
+
log(f"Uploading new {fn}...", _print=True)
|
|
133
|
+
uploaded_file = self.client.files.upload(
|
|
134
|
+
file=fileobj.name,
|
|
135
|
+
config={"mime_type": "application/json", "display_name": fn},
|
|
136
|
+
)
|
|
137
|
+
# 4. Wait for processing (Usually instant for JSON, critical for Video/PDF)
|
|
138
|
+
|
|
139
|
+
# This ensures the file is 'ACTIVE' before you use it in a prompt.
|
|
140
|
+
while uploaded_file.state.name == "PROCESSING":
|
|
141
|
+
time.sleep(1)
|
|
142
|
+
uploaded_file = self.client.get_file(uploaded_file.name)
|
|
143
|
+
file_refs.append(uploaded_file)
|
|
144
|
+
return file_refs
|
|
145
|
+
|
|
146
|
+
def upload(self, file):
|
|
147
|
+
return self._add_files([file])
|
|
148
|
+
|
|
149
|
+
def generate_json(self, message, function, additional_instructions="", **kwargs):
|
|
110
150
|
# The API call must use the 'tools' parameter instead of 'response_json_schema'
|
|
111
151
|
function_definition = self._add_function(function)
|
|
112
152
|
|
|
153
|
+
contents = [message]
|
|
154
|
+
if uri := kwargs.get("uri"):
|
|
155
|
+
contents.append(
|
|
156
|
+
Part.from_uri(
|
|
157
|
+
file_uri=uri,
|
|
158
|
+
mime_type="application/json",
|
|
159
|
+
),
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
if files := kwargs.get("files"):
|
|
163
|
+
contents += self._add_files(files)
|
|
164
|
+
|
|
113
165
|
response = self.client.models.generate_content(
|
|
114
166
|
model=self._json_model,
|
|
115
|
-
contents=
|
|
167
|
+
contents=contents,
|
|
116
168
|
config=types.GenerateContentConfig(
|
|
117
169
|
system_instruction=f"{self.instructions}.{additional_instructions}",
|
|
118
170
|
tools=[types.Tool(function_declarations=[function_definition])],
|
|
@@ -140,36 +192,61 @@ class GeminiAIModel(AutoModel):
|
|
|
140
192
|
log(f"==== Failed to parse ToolCall response: {e} ====")
|
|
141
193
|
return {}
|
|
142
194
|
|
|
143
|
-
def generate_text(self, message, additional_instructions=""):
|
|
195
|
+
def generate_text(self, message, additional_instructions="", **kwargs):
|
|
196
|
+
contents = [message]
|
|
197
|
+
if uri := kwargs.get("uri"):
|
|
198
|
+
contents.append(
|
|
199
|
+
Part.from_uri(
|
|
200
|
+
file_uri=uri,
|
|
201
|
+
mime_type="application/json",
|
|
202
|
+
),
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
if files := kwargs.get("files"):
|
|
206
|
+
contents += self._add_files(files)
|
|
207
|
+
|
|
144
208
|
response = self.client.models.generate_content(
|
|
145
209
|
model=self._text_model,
|
|
146
210
|
config=types.GenerateContentConfig(
|
|
147
211
|
system_instruction=f"{self.instructions}.{additional_instructions}",
|
|
148
212
|
),
|
|
149
|
-
contents=
|
|
213
|
+
contents=contents,
|
|
150
214
|
)
|
|
151
215
|
|
|
152
216
|
# log(results, _print=True)
|
|
153
217
|
# log("=================== END REPORT ===================", _print=True)
|
|
154
218
|
return response.text
|
|
155
219
|
|
|
156
|
-
def summarize_text(self, text, primer=""):
|
|
220
|
+
def summarize_text(self, text, primer="", **kwargs):
|
|
157
221
|
primer = primer or self.instructions
|
|
158
|
-
response = self.client.models.generate_content(
|
|
159
|
-
model=self._summary_model,
|
|
160
|
-
config=types.GenerateContentConfig(
|
|
161
|
-
system_instruction=f"{primer}",
|
|
162
|
-
),
|
|
163
|
-
contents=text,
|
|
164
|
-
)
|
|
165
|
-
log(response)
|
|
166
|
-
try:
|
|
167
|
-
result = response.candidates[0].content.parts[0].text
|
|
168
|
-
except Exception as e:
|
|
169
|
-
log(f"{type(e)}:{e}\n\n Unable to generate content ====")
|
|
170
|
-
return None
|
|
171
222
|
|
|
172
|
-
|
|
223
|
+
updated_prompt_list = []
|
|
224
|
+
# Find all words in the prompt
|
|
225
|
+
words = re.findall(r"\w+", text)
|
|
226
|
+
# Split the words into chunks
|
|
227
|
+
for i in range(0, len(words), self.MAX_SUMMARY_TOKEN_LENGTH):
|
|
228
|
+
# Join a chunk of words and add to the list
|
|
229
|
+
updated_prompt_list.append(
|
|
230
|
+
" ".join(words[i : i + self.MAX_SUMMARY_TOKEN_LENGTH])
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
full_summary = ""
|
|
234
|
+
for p in updated_prompt_list:
|
|
235
|
+
response = self.client.models.generate_content(
|
|
236
|
+
model=self._summary_model,
|
|
237
|
+
config=types.GenerateContentConfig(
|
|
238
|
+
system_instruction=f"{primer}",
|
|
239
|
+
),
|
|
240
|
+
contents=text,
|
|
241
|
+
)
|
|
242
|
+
try:
|
|
243
|
+
summary = response.candidates[0].content.parts[0].text
|
|
244
|
+
except Exception as e:
|
|
245
|
+
log(f"{type(e)}:{e}\n\n Unable to generate content ====", _print=True)
|
|
246
|
+
break
|
|
247
|
+
else:
|
|
248
|
+
full_summary += summary + "\n"
|
|
249
|
+
return summary
|
|
173
250
|
|
|
174
251
|
def generate_audio_text(
|
|
175
252
|
self, audio_file, prompt="Transcribe this audio clip", **kwargs
|
|
@@ -292,8 +369,8 @@ class GeminiAIModel(AutoModel):
|
|
|
292
369
|
),
|
|
293
370
|
),
|
|
294
371
|
)
|
|
295
|
-
|
|
296
|
-
|
|
372
|
+
log(response, _print=True)
|
|
373
|
+
log(response.candidates, _print=True)
|
|
297
374
|
image_parts = [
|
|
298
375
|
part.inline_data.data
|
|
299
376
|
for part in response.candidates[0].content.parts
|
autonomous/ai/textagent.py
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
from autonomous import log
|
|
2
|
+
from autonomous.ai.baseagent import BaseAgent
|
|
2
3
|
from autonomous.model.autoattr import ReferenceAttr, StringAttr
|
|
3
4
|
from autonomous.model.automodel import AutoModel
|
|
4
|
-
|
|
5
|
+
|
|
5
6
|
from .models.openai import OpenAIModel
|
|
6
7
|
|
|
7
8
|
|
|
@@ -14,8 +15,10 @@ class TextAgent(BaseAgent):
|
|
|
14
15
|
default="A helpful AI assistant trained to assist with generating text according to the given requirements."
|
|
15
16
|
)
|
|
16
17
|
|
|
17
|
-
def summarize_text(self, text, primer=""):
|
|
18
|
-
return self.get_client().summarize_text(text, primer)
|
|
18
|
+
def summarize_text(self, text, primer="", **kwargs):
|
|
19
|
+
return self.get_client().summarize_text(text, primer, **kwargs)
|
|
19
20
|
|
|
20
|
-
def generate(self, messages, additional_instructions=""):
|
|
21
|
-
return self.get_client().generate_text(
|
|
21
|
+
def generate(self, messages, additional_instructions="", **kwargs):
|
|
22
|
+
return self.get_client().generate_text(
|
|
23
|
+
messages, additional_instructions, **kwargs
|
|
24
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: autonomous-app
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.28
|
|
4
4
|
Summary: Containerized application framework built on Flask with additional libraries and tools for rapid development of web applications.
|
|
5
5
|
Author-email: Steven A Moore <samoore@binghamton.edu>
|
|
6
6
|
Project-URL: homepage, https://github.com/Sallenmoore/autonomous
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
autonomous/__init__.py,sha256=
|
|
1
|
+
autonomous/__init__.py,sha256=cf_i1xIW4gWRL34z5iRAHqNKq4XELsusys3f4hdY1sQ,95
|
|
2
2
|
autonomous/cli.py,sha256=z4AaGeWNW_uBLFAHng0J_lfS9v3fXemK1PeT85u4Eo4,42
|
|
3
3
|
autonomous/logger.py,sha256=NQtgEaTWNAWfLSgqSP7ksXj1GpOuCgoUV711kSMm-WA,2022
|
|
4
4
|
autonomous/ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
autonomous/ai/audioagent.py,sha256=SvPLzKgqUnrkcsR7y93aURSrStIrryuntQMPS1SzUXw,1033
|
|
6
6
|
autonomous/ai/baseagent.py,sha256=HYCqC4HmK5afNMunmTkhRE8O0OaONl2GxXnISkdOM58,1094
|
|
7
7
|
autonomous/ai/imageagent.py,sha256=bIOrgg_CM-rgfyLme7V9vPqP8WKVMIAVoB2E9lLtIRk,521
|
|
8
|
-
autonomous/ai/jsonagent.py,sha256=
|
|
9
|
-
autonomous/ai/textagent.py,sha256=
|
|
8
|
+
autonomous/ai/jsonagent.py,sha256=VQGhK0RFo0H_eVH9dAyf4_lp-RIpdgH988joLoKjm94,1065
|
|
9
|
+
autonomous/ai/textagent.py,sha256=1yM1aMvws64PocvG_L-POMDKjxq2JDuGqgc3haUHybU,926
|
|
10
10
|
autonomous/ai/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
11
|
autonomous/ai/models/aws.py,sha256=bGDjnGTm350zOqor9IsICzUkBUN2bubGI_ZssQuSXIw,12715
|
|
12
12
|
autonomous/ai/models/deepseek.py,sha256=fkoi-hJp60yFlZ9Cb9PdUrmNSErYltQ5ezkUI75llXc,2734
|
|
13
|
-
autonomous/ai/models/gemini.py,sha256=
|
|
13
|
+
autonomous/ai/models/gemini.py,sha256=jrTMbh8SAdzzz27elOhs82iwjyutYcy8fvTOSdW-GFQ,14247
|
|
14
14
|
autonomous/ai/models/local.py,sha256=fkoi-hJp60yFlZ9Cb9PdUrmNSErYltQ5ezkUI75llXc,2734
|
|
15
15
|
autonomous/ai/models/openai.py,sha256=2-LttCm6woGklaLbs1H5LjlbfM-7leDwGmC9vksSqW4,13135
|
|
16
16
|
autonomous/apis/version_control/GHCallbacks.py,sha256=AyiUlYfV5JePi11GVyqYyXoj5UTbPKzS-HRRI94rjJo,1069
|
|
@@ -57,7 +57,7 @@ autonomous/storage/localstorage.py,sha256=FzrR6O9mMGAZt5dDgqzkeOQVfGRXCygR0kksz2
|
|
|
57
57
|
autonomous/tasks/__init__.py,sha256=pn7iZ14MhcHUdzcLkfkd4-45wgPP0tXahAz_cFgb_Tg,32
|
|
58
58
|
autonomous/tasks/autotask.py,sha256=aK5iapDhgcAic3F5ZYMAhNKJkOepj8yWwbMizKDzUwQ,4153
|
|
59
59
|
autonomous/utils/markdown.py,sha256=tf8vlHARiQO1X_aGbqlYozzP_TbdiDRT9EEP6aFRQo0,2153
|
|
60
|
-
autonomous_app-0.3.
|
|
61
|
-
autonomous_app-0.3.
|
|
62
|
-
autonomous_app-0.3.
|
|
63
|
-
autonomous_app-0.3.
|
|
60
|
+
autonomous_app-0.3.28.dist-info/METADATA,sha256=HgUXCoGnskzg9FAnSZwfEGXB-5l1Rksw0XTMnGp6bBk,3015
|
|
61
|
+
autonomous_app-0.3.28.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
62
|
+
autonomous_app-0.3.28.dist-info/top_level.txt,sha256=ZyxWWDdbvZekF3UFunxl4BQsVDb_FOW3eTn0vun_jb4,11
|
|
63
|
+
autonomous_app-0.3.28.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|