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 CHANGED
@@ -1,4 +1,4 @@
1
- __version__ = "0.3.26"
1
+ __version__ = "0.3.28"
2
2
 
3
3
  from dotenv import load_dotenv
4
4
 
@@ -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
- from autonomous.ai.baseagent import BaseAgent
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)
@@ -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 generate_json(self, message, function, additional_instructions=""):
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=message,
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=message,
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
- return result
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
- # log(response, _print=True)
296
- # log(response.candidates, _print=True)
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
@@ -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
- from autonomous.ai.baseagent import BaseAgent
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(messages, additional_instructions)
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.26
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=eHK_4nSf5khgoBM8Apv6KPdX96gXt_nvOhMDeZTQiAs,95
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=a_l4HyyVRj3FB6py_P1xdc4Bj9uNI1YmJrWQXAksIvs,964
9
- autonomous/ai/textagent.py,sha256=wI1-VC9zscKYyxYBg4pZ0ZyNJ5ZvKkLfWsIY1vJFChk,863
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=lqTNcpU7Z1Go2juSEDDJQnRQXET0XERDgZ5ZXTpqoYI,11369
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.26.dist-info/METADATA,sha256=L5ATWHM6-Znc6E-iK3cr5IYwuJ8d3HhBHb3byk8U9DE,3015
61
- autonomous_app-0.3.26.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
62
- autonomous_app-0.3.26.dist-info/top_level.txt,sha256=ZyxWWDdbvZekF3UFunxl4BQsVDb_FOW3eTn0vun_jb4,11
63
- autonomous_app-0.3.26.dist-info/RECORD,,
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,,