autonomous-app 0.3.32__tar.gz → 0.3.34__tar.gz

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.
Files changed (77) hide show
  1. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/PKG-INFO +1 -1
  2. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/pyproject.toml +4 -0
  3. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/__init__.py +1 -1
  4. autonomous_app-0.3.34/src/autonomous/ai/audioagent.py +37 -0
  5. autonomous_app-0.3.34/src/autonomous/ai/baseagent.py +117 -0
  6. autonomous_app-0.3.34/src/autonomous/ai/imageagent.py +36 -0
  7. autonomous_app-0.3.34/src/autonomous/ai/jsonagent.py +36 -0
  8. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/ai/models/gemini.py +78 -59
  9. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/ai/models/local_model.py +49 -111
  10. autonomous_app-0.3.34/src/autonomous/ai/textagent.py +28 -0
  11. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/db_sync.py +7 -8
  12. autonomous_app-0.3.34/src/autonomous/taskrunner/__init__.py +1 -0
  13. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous_app.egg-info/PKG-INFO +1 -1
  14. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous_app.egg-info/SOURCES.txt +3 -6
  15. autonomous_app-0.3.32/src/autonomous/ai/audioagent.py +0 -28
  16. autonomous_app-0.3.32/src/autonomous/ai/baseagent.py +0 -33
  17. autonomous_app-0.3.32/src/autonomous/ai/imageagent.py +0 -15
  18. autonomous_app-0.3.32/src/autonomous/ai/jsonagent.py +0 -30
  19. autonomous_app-0.3.32/src/autonomous/ai/models/aws.py +0 -317
  20. autonomous_app-0.3.32/src/autonomous/ai/models/deepseek.py +0 -99
  21. autonomous_app-0.3.32/src/autonomous/ai/models/openai.py +0 -347
  22. autonomous_app-0.3.32/src/autonomous/ai/textagent.py +0 -24
  23. autonomous_app-0.3.32/src/autonomous/tasks/__init__.py +0 -1
  24. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/README.md +0 -0
  25. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/requirements.txt +0 -0
  26. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/setup.cfg +0 -0
  27. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/setup.py +0 -0
  28. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/ai/__init__.py +0 -0
  29. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/ai/models/__init__.py +0 -0
  30. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/apis/version_control/GHCallbacks.py +0 -0
  31. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/apis/version_control/GHOrganization.py +0 -0
  32. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/apis/version_control/GHRepo.py +0 -0
  33. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/apis/version_control/GHVersionControl.py +0 -0
  34. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/apis/version_control/__init__.py +0 -0
  35. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/auth/__init__.py +0 -0
  36. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/auth/autoauth.py +0 -0
  37. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/auth/github.py +0 -0
  38. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/auth/google.py +0 -0
  39. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/auth/user.py +0 -0
  40. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/cli.py +0 -0
  41. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/__init__.py +0 -0
  42. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/base/__init__.py +0 -0
  43. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/base/common.py +0 -0
  44. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/base/datastructures.py +0 -0
  45. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/base/document.py +0 -0
  46. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/base/fields.py +0 -0
  47. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/base/metaclasses.py +0 -0
  48. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/base/utils.py +0 -0
  49. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/common.py +0 -0
  50. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/connection.py +0 -0
  51. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/context_managers.py +0 -0
  52. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/dereference.py +0 -0
  53. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/document.py +0 -0
  54. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/errors.py +0 -0
  55. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/fields.py +0 -0
  56. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/mongodb_support.py +0 -0
  57. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/pymongo_support.py +0 -0
  58. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/queryset/__init__.py +0 -0
  59. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/queryset/base.py +0 -0
  60. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/queryset/field_list.py +0 -0
  61. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/queryset/manager.py +0 -0
  62. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/queryset/queryset.py +0 -0
  63. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/queryset/transform.py +0 -0
  64. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/queryset/visitor.py +0 -0
  65. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/db/signals.py +0 -0
  66. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/logger.py +0 -0
  67. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/model/autoattr.py +0 -0
  68. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/model/automodel.py +0 -0
  69. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/storage/__init__.py +0 -0
  70. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/storage/imagestorage.py +0 -0
  71. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/storage/localstorage.py +0 -0
  72. /autonomous_app-0.3.32/src/autonomous/tasks/autotask.py → /autonomous_app-0.3.34/src/autonomous/taskrunner/autotasks.py +0 -0
  73. {autonomous_app-0.3.32/src/autonomous/tasks → autonomous_app-0.3.34/src/autonomous/taskrunner}/task_router.py +0 -0
  74. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous/utils/markdown.py +0 -0
  75. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous_app.egg-info/dependency_links.txt +0 -0
  76. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous_app.egg-info/requires.txt +0 -0
  77. {autonomous_app-0.3.32 → autonomous_app-0.3.34}/src/autonomous_app.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: autonomous-app
3
- Version: 0.3.32
3
+ Version: 0.3.34
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
@@ -40,6 +40,10 @@ where = ["src"]
40
40
  include = ["autonomous*"]
41
41
 
42
42
  [tool.pytest.ini_options]
43
+ env_files = [
44
+ "tests/.testenv"
45
+ ]
46
+ env_override_existing_values = 1
43
47
  addopts = "--cov=autonomous -rx -l -x -s --log-level=INFO --ignore=src --no-cov-on-fail -v --pdb --cov-reset "
44
48
 
45
49
  testpaths = [
@@ -1,4 +1,4 @@
1
- __version__ = "0.3.32"
1
+ __version__ = "0.3.34"
2
2
 
3
3
  from dotenv import load_dotenv
4
4
 
@@ -0,0 +1,37 @@
1
+ import os
2
+
3
+ from autonomous import log
4
+ from autonomous.ai.baseagent import BaseAgent
5
+ from autonomous.model.autoattr import StringAttr
6
+
7
+
8
+ class AudioAgent(BaseAgent):
9
+ name = StringAttr(default="audioagent")
10
+
11
+ provider = StringAttr(default="gemini")
12
+
13
+ instructions = StringAttr(
14
+ default="You are highly skilled AI trained to assist with generating audio files."
15
+ )
16
+ description = StringAttr(
17
+ default="A helpful AI assistant trained to assist with generating audio files."
18
+ )
19
+
20
+ def generate(self, prompt, voice=None):
21
+ return self.get_client(
22
+ os.environ.get("TTS_AI_AGENT", self.provider)
23
+ ).generate_audio(prompt, voice=voice)
24
+
25
+ def transcribe(
26
+ self, audio, prompt="Transcribe this audio clip", display_name="audio.mp3"
27
+ ):
28
+ return self.get_client(
29
+ os.environ.get("TRANSCRIBE_AI_AGENT", self.provider)
30
+ ).generate_transcription(
31
+ audio,
32
+ prompt=prompt,
33
+ display_name=display_name,
34
+ )
35
+
36
+ def available_voices(self, filters=[]):
37
+ return self.get_client().list_voices(filters=filters)
@@ -0,0 +1,117 @@
1
+ from autonomous import log
2
+ from autonomous.model.autoattr import ReferenceAttr, StringAttr
3
+ from autonomous.model.automodel import AutoModel
4
+
5
+ from .models.gemini import GeminiAIModel
6
+ from .models.local_model import LocalAIModel
7
+
8
+
9
+ class BaseAgent(AutoModel):
10
+ meta = {"abstract": True, "allow_inheritance": True, "strict": False}
11
+
12
+ # 2. Map string names to classes
13
+ MODEL_REGISTRY = {
14
+ "local": LocalAIModel,
15
+ "gemini": GeminiAIModel,
16
+ }
17
+
18
+ # 3. Allow client to be ANY of the supported models
19
+ client = ReferenceAttr(choices=[LocalAIModel, GeminiAIModel])
20
+
21
+ # 4. Add a provider field (default to local, can be overridden per agent)
22
+ provider = StringAttr(default="gemini")
23
+
24
+ def delete(self):
25
+ if self.client:
26
+ self.client.delete()
27
+ return super().delete()
28
+
29
+ def get_agent_id(self):
30
+ return self.get_client().id
31
+
32
+ def get_client(self, provider=None):
33
+ # 5. Determine which class to use based on the provider string
34
+ model_class = self.MODEL_REGISTRY.get(provider or self.provider, LocalAIModel)
35
+ # If we already have a client, but it's the WRONG type (e.g. we switched providers), we might want to re-instantiate. For simplicity, we check if it exists first.
36
+ if not isinstance(self.client, model_class):
37
+ if self.client:
38
+ log(
39
+ f"Re-instantiating client for agent {self.name} from {type(self.client).__name__} to {model_class.__name__}"
40
+ )
41
+ self.client.delete()
42
+ self.client = model_class(
43
+ name=self.name,
44
+ instructions=self.instructions,
45
+ description=self.description,
46
+ )
47
+ self.client.save()
48
+ self.save()
49
+
50
+ return self.client
51
+
52
+ # def get_embedding(self, text):
53
+ # """Helper to get embeddings for vector search"""
54
+ # try:
55
+ # res = requests.post(f"{self._media_url}/embeddings", json={"text": text})
56
+ # res.raise_for_status()
57
+ # return res.json()["embedding"]
58
+ # except Exception:
59
+ # return []
60
+
61
+ # def gather_context(self, prompt, focus_object_id=None):
62
+ # """
63
+ # Retrieves context string from Mongo/Redis.
64
+ # Previously 'build_hybrid_context' in LocalAIModel.
65
+ # """
66
+ # context_str = ""
67
+
68
+ # # 1. Fetch from MongoDB (Focus Object)
69
+ # if focus_object_id:
70
+ # try:
71
+ # oid = (
72
+ # ObjectId(focus_object_id)
73
+ # if isinstance(focus_object_id, str)
74
+ # else focus_object_id
75
+ # )
76
+ # if main_obj := self._mongo_db.objects.find_one({"_id": oid}):
77
+ # context_str += f"### FOCUS OBJECT ###\n{main_obj}\n"
78
+ # ref_ids = main_obj.get("associations", []) or []
79
+ # if world_id := main_obj.get("world"):
80
+ # ref_ids.append(world_id)
81
+ # ref_ids.extend(main_obj.get("stories", []) or [])
82
+ # ref_ids.extend(main_obj.get("events", []) or [])
83
+
84
+ # if ref_ids:
85
+ # valid_oids = [
86
+ # ObjectId(rid) if isinstance(rid, str) else rid
87
+ # for rid in ref_ids
88
+ # ]
89
+ # if valid_oids:
90
+ # associated_objs = self._mongo_db.objects.find(
91
+ # {"_id": {"$in": valid_oids}}
92
+ # )
93
+ # context_str += "\n### ASSOCIATED REFERENCES ###\n"
94
+ # for obj in associated_objs:
95
+ # context_str += f"- {obj}\n"
96
+ # context_str += "\n"
97
+ # except Exception as e:
98
+ # print(f"Context Error: {e}")
99
+
100
+ # # 2. Fetch from Redis (Vector Search)
101
+ # if len(prompt) > 10:
102
+ # vector = self.get_embedding(prompt)
103
+ # if vector:
104
+ # try:
105
+ # q = "*=>[KNN 2 @vector $blob AS score]"
106
+ # params = {"blob": np.array(vector, dtype=np.float32).tobytes()}
107
+ # results = self._redis.ft("search_index").search(
108
+ # q, query_params=params
109
+ # )
110
+ # if results.docs:
111
+ # context_str += "\n### RELEVANT LORE ###\n"
112
+ # for doc in results.docs:
113
+ # context_str += f"- {doc.content}\n"
114
+ # except Exception:
115
+ # pass
116
+
117
+ # return context_str
@@ -0,0 +1,36 @@
1
+ import os
2
+
3
+ from autonomous.ai.baseagent import BaseAgent
4
+ from autonomous.model.autoattr import StringAttr
5
+
6
+
7
+ class ImageAgent(BaseAgent):
8
+ name = StringAttr(default="imageagent")
9
+
10
+ # Force this agent to use Gemini
11
+ provider = StringAttr(default="gemini")
12
+
13
+ instructions = StringAttr(
14
+ default="You are highly skilled AI trained to assist with generating images."
15
+ )
16
+ description = StringAttr(
17
+ default="A helpful AI assistant trained to assist with generating images."
18
+ )
19
+
20
+ def generate(
21
+ self,
22
+ prompt,
23
+ negative_prompt="",
24
+ aspect_ratio="3:4",
25
+ image_size="2K",
26
+ files=None,
27
+ ):
28
+ return self.get_client(
29
+ os.environ.get("IMAGE_AI_AGENT", self.provider)
30
+ ).generate_image(
31
+ prompt,
32
+ aspect_ratio=aspect_ratio,
33
+ negative_prompt=negative_prompt,
34
+ image_size=image_size,
35
+ files=files,
36
+ )
@@ -0,0 +1,36 @@
1
+ import json
2
+ import os
3
+
4
+ from autonomous.ai.baseagent import BaseAgent
5
+ from autonomous.model.autoattr import StringAttr
6
+
7
+
8
+ class JSONAgent(BaseAgent):
9
+ name = StringAttr(default="jsonagent")
10
+
11
+ # Force this agent to use Gemini
12
+ provider = StringAttr(default="gemini")
13
+
14
+ instructions = StringAttr(
15
+ default="You are highly skilled AI trained to assist with generating JSON formatted data."
16
+ )
17
+ description = StringAttr(
18
+ default="A helpful AI assistant trained to assist with generating JSON formatted data."
19
+ )
20
+
21
+ def generate(
22
+ self, message, function, additional_instructions="", uri="", context=""
23
+ ):
24
+ result = self.get_client(
25
+ os.environ.get("JSON_AI_AGENT", self.provider)
26
+ ).generate_json(
27
+ message, function, additional_instructions, uri=uri, context=context
28
+ )
29
+ if isinstance(result, str):
30
+ try:
31
+ result = json.loads(result)
32
+ except json.JSONDecodeError:
33
+ raise ValueError(f"Invalid JSON response from AI model.\n\n{result}")
34
+ elif not isinstance(result, dict):
35
+ raise ValueError(f"Invalid JSON response from AI model.\n\n{result}")
36
+ return result
@@ -1,4 +1,5 @@
1
1
  import io
2
+ import json
2
3
  import os
3
4
  import random
4
5
  import re
@@ -32,6 +33,7 @@ class GeminiAIModel(AutoModel):
32
33
  description = StringAttr(
33
34
  default="A helpful AI assistant trained to assist with various tasks."
34
35
  )
36
+ file_refs = ListAttr(StringAttr(default=[]))
35
37
 
36
38
  MAX_FILES = 14
37
39
  MAX_SUMMARY_TOKEN_LENGTH = 10000
@@ -111,56 +113,69 @@ class GeminiAIModel(AutoModel):
111
113
  buffer.seek(0)
112
114
  return buffer
113
115
 
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)
116
+ def _add_context(self, context):
117
+ # Create in-memory file
118
+ context_data = (
119
+ json.dumps(context, indent=2) if isinstance(context, dict) else str(context)
120
+ )
121
+
122
+ f = io.BytesIO(context_data.encode("utf-8"))
123
+ f.name = f"context-{self.pk}"
124
+ return self._add_files([{"name": f.name, "file": f}])
125
+
126
+ def _add_files(self, file_list, mime_type="application/json"):
127
+ uploaded_files = []
128
+ for f in file_list[: self.MAX_FILES]:
129
+ fn = f["name"]
130
+ try:
131
+ result = self.client.files.delete(name=fn)
132
+ except Exception as e:
133
+ pass
134
+ # log(f"No existing file to delete for {fn}: {e}", _print=True)
135
+ else:
136
+ pass
137
+ # log(f"Deleting old version of {fn}: {result}", _print=True)
138
+
139
+ # If the content is raw bytes, wrap it in BytesIO
140
+ file_content = f["file"]
141
+ if isinstance(file_content, bytes):
142
+ fileobj = io.BytesIO(file_content)
143
+ else:
144
+ fileobj = file_content
133
145
  uploaded_file = self.client.files.upload(
134
- file=fileobj.name,
135
- config={"mime_type": "application/json", "display_name": fn},
146
+ file=fileobj,
147
+ config={"mime_type": mime_type, "display_name": fn},
136
148
  )
137
- # 4. Wait for processing (Usually instant for JSON, critical for Video/PDF)
149
+ uploaded_files.append(uploaded_file)
138
150
 
139
151
  # This ensures the file is 'ACTIVE' before you use it in a prompt.
140
152
  while uploaded_file.state.name == "PROCESSING":
141
- time.sleep(1)
153
+ time.sleep(0.5)
142
154
  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])
155
+ self.file_refs = [f.name for f in self.client.files.list()] # Update file_refs
156
+ self.save()
157
+ return uploaded_files
148
158
 
149
- def generate_json(self, message, function, additional_instructions="", **kwargs):
150
- # The API call must use the 'tools' parameter instead of 'response_json_schema'
159
+ def generate_json(
160
+ self, message, function, additional_instructions="", uri="", context={}
161
+ ):
151
162
  function_definition = self._add_function(function)
152
163
 
153
164
  contents = [message]
154
- if uri := kwargs.get("uri"):
165
+ if context:
166
+ contents.extend(self._add_context(context))
167
+ additional_instructions += (
168
+ f"\nUse the uploaded context file for reference: context-{self.pk}\n"
169
+ )
170
+
171
+ if uri:
155
172
  contents.append(
156
173
  Part.from_uri(
157
174
  file_uri=uri,
158
175
  mime_type="application/json",
159
176
  ),
160
177
  )
161
-
162
- if files := kwargs.get("files"):
163
- contents += self._add_files(files)
178
+ additional_instructions += "\nUse the provided uri file for reference\n"
164
179
 
165
180
  response = self.client.models.generate_content(
166
181
  model=self._json_model,
@@ -192,9 +207,15 @@ class GeminiAIModel(AutoModel):
192
207
  log(f"==== Failed to parse ToolCall response: {e} ====")
193
208
  return {}
194
209
 
195
- def generate_text(self, message, additional_instructions="", **kwargs):
210
+ def generate_text(self, message, additional_instructions="", uri="", context={}):
196
211
  contents = [message]
197
- if uri := kwargs.get("uri"):
212
+ if context:
213
+ contents.extend(self._add_context(context))
214
+ additional_instructions += (
215
+ f"\nUse the uploaded context file for reference: context-{self.pk}\n"
216
+ )
217
+
218
+ if uri:
198
219
  contents.append(
199
220
  Part.from_uri(
200
221
  file_uri=uri,
@@ -202,9 +223,6 @@ class GeminiAIModel(AutoModel):
202
223
  ),
203
224
  )
204
225
 
205
- if files := kwargs.get("files"):
206
- contents += self._add_files(files)
207
-
208
226
  response = self.client.models.generate_content(
209
227
  model=self._text_model,
210
228
  config=types.GenerateContentConfig(
@@ -217,7 +235,7 @@ class GeminiAIModel(AutoModel):
217
235
  # log("=================== END REPORT ===================", _print=True)
218
236
  return response.text
219
237
 
220
- def summarize_text(self, text, primer="", **kwargs):
238
+ def summarize_text(self, text, primer=""):
221
239
  primer = primer or self.instructions
222
240
 
223
241
  updated_prompt_list = []
@@ -248,14 +266,17 @@ class GeminiAIModel(AutoModel):
248
266
  full_summary += summary + "\n"
249
267
  return summary
250
268
 
251
- def generate_audio_text(
252
- self, audio_file, prompt="Transcribe this audio clip", **kwargs
269
+ def generate_transcription(
270
+ self,
271
+ audio_file,
272
+ prompt="Transcribe this audio clip",
273
+ display_name="audio.mp3",
253
274
  ):
254
275
  myfile = self.client.files.upload(
255
276
  file=io.BytesIO(audio_file),
256
277
  config={
257
278
  "mime_type": "audio/mp3",
258
- "display_name": kwargs.get("display_name", "audio.mp3"),
279
+ "display_name": display_name,
259
280
  },
260
281
  )
261
282
 
@@ -277,7 +298,7 @@ class GeminiAIModel(AutoModel):
277
298
  voices.append(voice)
278
299
  return voices
279
300
 
280
- def generate_audio(self, prompt, voice=None, **kwargs):
301
+ def generate_audio(self, prompt, voice=None):
281
302
  voice = voice or random.choice(self.list_voices())
282
303
  try:
283
304
  response = self.client.models.generate_content(
@@ -318,22 +339,20 @@ class GeminiAIModel(AutoModel):
318
339
  # You can return a default empty byte string or re-raise the exception
319
340
  raise e
320
341
 
321
- def generate_image(self, prompt, **kwargs):
342
+ def generate_image(
343
+ self,
344
+ prompt,
345
+ negative_prompt="",
346
+ files=None,
347
+ aspect_ratio="3:4",
348
+ image_size="2K",
349
+ ):
322
350
  image = None
323
351
  contents = [prompt]
324
352
 
325
- if kwargs.get("files"):
326
- counter = 0
327
- for fn, f in kwargs.get("files").items():
328
- media = io.BytesIO(f)
329
- myfile = self.client.files.upload(
330
- file=media,
331
- config={"mime_type": "image/webp", "display_name": fn},
332
- )
333
- contents += [myfile]
334
- counter += 1
335
- if counter >= self.MAX_FILES:
336
- break
353
+ if files:
354
+ filerefs = self._add_files(files, mime_type="image/webp")
355
+ contents.extend(filerefs)
337
356
 
338
357
  try:
339
358
  # log(self._image_model, contents, _print=True)
@@ -364,8 +383,8 @@ class GeminiAIModel(AutoModel):
364
383
  ),
365
384
  ],
366
385
  image_config=types.ImageConfig(
367
- aspect_ratio=kwargs.get("aspect_ratio", "3:4"),
368
- image_size=kwargs.get("image_size", "2K"),
386
+ aspect_ratio=aspect_ratio,
387
+ image_size=image_size,
369
388
  ),
370
389
  ),
371
390
  )