agno 2.0.0rc2__py3-none-any.whl → 2.0.2__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.
- agno/agent/agent.py +78 -135
- agno/knowledge/knowledge.py +1 -1
- agno/knowledge/reranker/__init__.py +3 -0
- agno/media.py +269 -268
- agno/models/base.py +13 -48
- agno/models/google/gemini.py +11 -10
- agno/models/message.py +4 -4
- agno/models/ollama/chat.py +1 -1
- agno/models/openai/chat.py +33 -14
- agno/models/response.py +5 -5
- agno/os/app.py +8 -5
- agno/run/agent.py +28 -28
- agno/run/base.py +9 -19
- agno/run/team.py +24 -24
- agno/run/workflow.py +16 -16
- agno/team/team.py +72 -154
- agno/tools/brightdata.py +3 -3
- agno/tools/cartesia.py +3 -5
- agno/tools/dalle.py +7 -4
- agno/tools/desi_vocal.py +2 -2
- agno/tools/e2b.py +6 -6
- agno/tools/eleven_labs.py +3 -3
- agno/tools/fal.py +4 -4
- agno/tools/function.py +7 -7
- agno/tools/giphy.py +2 -2
- agno/tools/lumalab.py +3 -3
- agno/tools/models/azure_openai.py +2 -2
- agno/tools/models/gemini.py +3 -3
- agno/tools/models/groq.py +3 -5
- agno/tools/models/nebius.py +2 -2
- agno/tools/models_labs.py +5 -5
- agno/tools/openai.py +4 -9
- agno/tools/opencv.py +3 -3
- agno/tools/replicate.py +7 -7
- agno/utils/events.py +5 -5
- agno/utils/gemini.py +1 -1
- agno/utils/mcp.py +3 -3
- agno/utils/models/aws_claude.py +1 -1
- agno/utils/models/cohere.py +1 -1
- agno/utils/models/watsonx.py +1 -1
- agno/utils/openai.py +1 -1
- agno/vectordb/lancedb/lance_db.py +82 -25
- agno/workflow/step.py +7 -7
- agno/workflow/types.py +13 -13
- agno/workflow/workflow.py +28 -28
- {agno-2.0.0rc2.dist-info → agno-2.0.2.dist-info}/METADATA +140 -1
- {agno-2.0.0rc2.dist-info → agno-2.0.2.dist-info}/RECORD +50 -50
- agno-2.0.2.dist-info/licenses/LICENSE +201 -0
- agno-2.0.0rc2.dist-info/licenses/LICENSE +0 -375
- {agno-2.0.0rc2.dist-info → agno-2.0.2.dist-info}/WHEEL +0 -0
- {agno-2.0.0rc2.dist-info → agno-2.0.2.dist-info}/top_level.txt +0 -0
agno/agent/agent.py
CHANGED
|
@@ -30,7 +30,7 @@ from pydantic import BaseModel
|
|
|
30
30
|
from agno.db.base import BaseDb, SessionType, UserMemory
|
|
31
31
|
from agno.exceptions import ModelProviderError, RunCancelledException, StopAgentRun
|
|
32
32
|
from agno.knowledge.knowledge import Knowledge
|
|
33
|
-
from agno.media import Audio,
|
|
33
|
+
from agno.media import Audio, File, Image, Video
|
|
34
34
|
from agno.memory import MemoryManager
|
|
35
35
|
from agno.models.base import Model
|
|
36
36
|
from agno.models.message import Message, MessageReferences
|
|
@@ -1078,7 +1078,7 @@ class Agent:
|
|
|
1078
1078
|
# Initialize the Agent
|
|
1079
1079
|
self.initialize_agent(debug_mode=debug_mode)
|
|
1080
1080
|
|
|
1081
|
-
image_artifacts, video_artifacts, audio_artifacts = self.
|
|
1081
|
+
image_artifacts, video_artifacts, audio_artifacts = self._validate_media_object_id(
|
|
1082
1082
|
images=images, videos=videos, audios=audio
|
|
1083
1083
|
)
|
|
1084
1084
|
|
|
@@ -1647,7 +1647,7 @@ class Agent:
|
|
|
1647
1647
|
# Initialize the Agent
|
|
1648
1648
|
self.initialize_agent(debug_mode=debug_mode)
|
|
1649
1649
|
|
|
1650
|
-
image_artifacts, video_artifacts, audio_artifacts = self.
|
|
1650
|
+
image_artifacts, video_artifacts, audio_artifacts = self._validate_media_object_id(
|
|
1651
1651
|
images=images, videos=videos, audios=audio
|
|
1652
1652
|
)
|
|
1653
1653
|
|
|
@@ -3320,23 +3320,47 @@ class Agent:
|
|
|
3320
3320
|
# Process audio
|
|
3321
3321
|
if model_response_event.audio is not None:
|
|
3322
3322
|
if model_response.audio is None:
|
|
3323
|
-
model_response.audio =
|
|
3323
|
+
model_response.audio = Audio(id=str(uuid4()), content=b"", transcript="")
|
|
3324
3324
|
|
|
3325
3325
|
if model_response_event.audio.id is not None:
|
|
3326
3326
|
model_response.audio.id = model_response_event.audio.id # type: ignore
|
|
3327
|
+
|
|
3327
3328
|
if model_response_event.audio.content is not None:
|
|
3328
|
-
|
|
3329
|
+
# Handle both base64 string and bytes content
|
|
3330
|
+
if isinstance(model_response_event.audio.content, str):
|
|
3331
|
+
# Decode base64 string to bytes
|
|
3332
|
+
try:
|
|
3333
|
+
import base64
|
|
3334
|
+
|
|
3335
|
+
decoded_content = base64.b64decode(model_response_event.audio.content)
|
|
3336
|
+
if model_response.audio.content is None:
|
|
3337
|
+
model_response.audio.content = b""
|
|
3338
|
+
model_response.audio.content += decoded_content
|
|
3339
|
+
except Exception:
|
|
3340
|
+
# If decode fails, encode string as bytes
|
|
3341
|
+
if model_response.audio.content is None:
|
|
3342
|
+
model_response.audio.content = b""
|
|
3343
|
+
model_response.audio.content += model_response_event.audio.content.encode("utf-8")
|
|
3344
|
+
elif isinstance(model_response_event.audio.content, bytes):
|
|
3345
|
+
# Content is already bytes
|
|
3346
|
+
if model_response.audio.content is None:
|
|
3347
|
+
model_response.audio.content = b""
|
|
3348
|
+
model_response.audio.content += model_response_event.audio.content
|
|
3349
|
+
|
|
3329
3350
|
if model_response_event.audio.transcript is not None:
|
|
3330
3351
|
model_response.audio.transcript += model_response_event.audio.transcript # type: ignore
|
|
3352
|
+
|
|
3331
3353
|
if model_response_event.audio.expires_at is not None:
|
|
3332
3354
|
model_response.audio.expires_at = model_response_event.audio.expires_at # type: ignore
|
|
3333
3355
|
if model_response_event.audio.mime_type is not None:
|
|
3334
3356
|
model_response.audio.mime_type = model_response_event.audio.mime_type # type: ignore
|
|
3335
|
-
|
|
3336
|
-
|
|
3357
|
+
if model_response_event.audio.sample_rate is not None:
|
|
3358
|
+
model_response.audio.sample_rate = model_response_event.audio.sample_rate
|
|
3359
|
+
if model_response_event.audio.channels is not None:
|
|
3360
|
+
model_response.audio.channels = model_response_event.audio.channels
|
|
3337
3361
|
|
|
3338
3362
|
# Yield the audio and transcript bit by bit
|
|
3339
|
-
run_response.response_audio =
|
|
3363
|
+
run_response.response_audio = Audio(
|
|
3340
3364
|
id=model_response_event.audio.id,
|
|
3341
3365
|
content=model_response_event.audio.content,
|
|
3342
3366
|
transcript=model_response_event.audio.transcript,
|
|
@@ -3364,6 +3388,14 @@ class Agent:
|
|
|
3364
3388
|
workflow_context=workflow_context,
|
|
3365
3389
|
)
|
|
3366
3390
|
|
|
3391
|
+
if model_response.images is None:
|
|
3392
|
+
model_response.images = []
|
|
3393
|
+
model_response.images.extend(model_response_event.images)
|
|
3394
|
+
# Store media in run_response if store_media is enabled
|
|
3395
|
+
if self.store_media:
|
|
3396
|
+
for image in model_response_event.images:
|
|
3397
|
+
self._add_image(image, run_response)
|
|
3398
|
+
|
|
3367
3399
|
# Handle tool interruption events
|
|
3368
3400
|
elif model_response_event.event == ModelResponseEvent.tool_call_paused.value:
|
|
3369
3401
|
# Add tool calls to the run_response
|
|
@@ -3762,19 +3794,11 @@ class Agent:
|
|
|
3762
3794
|
session: Optional[AgentSession] = None,
|
|
3763
3795
|
) -> Optional[Sequence[Image]]:
|
|
3764
3796
|
"""Collect images from input, session history, and current run response."""
|
|
3765
|
-
joint_images = []
|
|
3797
|
+
joint_images: List[Image] = []
|
|
3766
3798
|
|
|
3767
3799
|
# 1. Add images from current input
|
|
3768
3800
|
if run_input and run_input.images:
|
|
3769
|
-
|
|
3770
|
-
try:
|
|
3771
|
-
if artifact.url:
|
|
3772
|
-
joint_images.append(Image(url=artifact.url))
|
|
3773
|
-
elif artifact.content:
|
|
3774
|
-
joint_images.append(Image(content=artifact.content))
|
|
3775
|
-
except Exception as e:
|
|
3776
|
-
log_warning(f"Error converting ImageArtifact to Image: {e}")
|
|
3777
|
-
continue
|
|
3801
|
+
joint_images.extend(run_input.images)
|
|
3778
3802
|
log_debug(f"Added {len(run_input.images)} input images to joint list")
|
|
3779
3803
|
|
|
3780
3804
|
# 2. Add images from session history (from both input and generated sources)
|
|
@@ -3783,30 +3807,14 @@ class Agent:
|
|
|
3783
3807
|
for historical_run in session.runs:
|
|
3784
3808
|
# Add generated images from previous runs
|
|
3785
3809
|
if historical_run.images:
|
|
3786
|
-
|
|
3787
|
-
try:
|
|
3788
|
-
if artifact.url:
|
|
3789
|
-
joint_images.append(Image(url=artifact.url))
|
|
3790
|
-
elif artifact.content:
|
|
3791
|
-
joint_images.append(Image(content=artifact.content))
|
|
3792
|
-
except Exception as e:
|
|
3793
|
-
log_warning(f"Error converting historical ImageArtifact to Image: {e}")
|
|
3794
|
-
continue
|
|
3810
|
+
joint_images.extend(historical_run.images)
|
|
3795
3811
|
log_debug(
|
|
3796
3812
|
f"Added {len(historical_run.images)} generated images from historical run {historical_run.run_id}"
|
|
3797
3813
|
)
|
|
3798
3814
|
|
|
3799
3815
|
# Add input images from previous runs
|
|
3800
3816
|
if historical_run.input and historical_run.input.images:
|
|
3801
|
-
|
|
3802
|
-
try:
|
|
3803
|
-
if artifact.url:
|
|
3804
|
-
joint_images.append(Image(url=artifact.url))
|
|
3805
|
-
elif artifact.content:
|
|
3806
|
-
joint_images.append(Image(content=artifact.content))
|
|
3807
|
-
except Exception as e:
|
|
3808
|
-
log_warning(f"Error converting input ImageArtifact to Image: {e}")
|
|
3809
|
-
continue
|
|
3817
|
+
joint_images.extend(historical_run.input.images)
|
|
3810
3818
|
log_debug(
|
|
3811
3819
|
f"Added {len(historical_run.input.images)} input images from historical run {historical_run.run_id}"
|
|
3812
3820
|
)
|
|
@@ -3823,19 +3831,11 @@ class Agent:
|
|
|
3823
3831
|
session: Optional[AgentSession] = None,
|
|
3824
3832
|
) -> Optional[Sequence[Video]]:
|
|
3825
3833
|
"""Collect videos from input, session history, and current run response."""
|
|
3826
|
-
joint_videos = []
|
|
3834
|
+
joint_videos: List[Video] = []
|
|
3827
3835
|
|
|
3828
3836
|
# 1. Add videos from current input
|
|
3829
3837
|
if run_input and run_input.videos:
|
|
3830
|
-
|
|
3831
|
-
try:
|
|
3832
|
-
if artifact.url:
|
|
3833
|
-
joint_videos.append(Video(url=artifact.url))
|
|
3834
|
-
elif artifact.content:
|
|
3835
|
-
joint_videos.append(Video(content=artifact.content))
|
|
3836
|
-
except Exception as e:
|
|
3837
|
-
log_warning(f"Error converting VideoArtifact to Video: {e}")
|
|
3838
|
-
continue
|
|
3838
|
+
joint_videos.extend(run_input.videos)
|
|
3839
3839
|
log_debug(f"Added {len(run_input.videos)} input videos to joint list")
|
|
3840
3840
|
|
|
3841
3841
|
# 2. Add videos from session history (from both input and generated sources)
|
|
@@ -3844,30 +3844,14 @@ class Agent:
|
|
|
3844
3844
|
for historical_run in session.runs:
|
|
3845
3845
|
# Add generated videos from previous runs
|
|
3846
3846
|
if historical_run.videos:
|
|
3847
|
-
|
|
3848
|
-
try:
|
|
3849
|
-
if artifact.url:
|
|
3850
|
-
joint_videos.append(Video(url=artifact.url))
|
|
3851
|
-
elif artifact.content:
|
|
3852
|
-
joint_videos.append(Video(content=artifact.content))
|
|
3853
|
-
except Exception as e:
|
|
3854
|
-
log_warning(f"Error converting historical VideoArtifact to Video: {e}")
|
|
3855
|
-
continue
|
|
3847
|
+
joint_videos.extend(historical_run.videos)
|
|
3856
3848
|
log_debug(
|
|
3857
3849
|
f"Added {len(historical_run.videos)} generated videos from historical run {historical_run.run_id}"
|
|
3858
3850
|
)
|
|
3859
3851
|
|
|
3860
3852
|
# Add input videos from previous runs
|
|
3861
3853
|
if historical_run.input and historical_run.input.videos:
|
|
3862
|
-
|
|
3863
|
-
try:
|
|
3864
|
-
if artifact.url:
|
|
3865
|
-
joint_videos.append(Video(url=artifact.url))
|
|
3866
|
-
elif artifact.content:
|
|
3867
|
-
joint_videos.append(Video(content=artifact.content))
|
|
3868
|
-
except Exception as e:
|
|
3869
|
-
log_warning(f"Error converting input VideoArtifact to Video: {e}")
|
|
3870
|
-
continue
|
|
3854
|
+
joint_videos.extend(historical_run.input.videos)
|
|
3871
3855
|
log_debug(
|
|
3872
3856
|
f"Added {len(historical_run.input.videos)} input videos from historical run {historical_run.run_id}"
|
|
3873
3857
|
)
|
|
@@ -3884,19 +3868,11 @@ class Agent:
|
|
|
3884
3868
|
session: Optional[AgentSession] = None,
|
|
3885
3869
|
) -> Optional[Sequence[Audio]]:
|
|
3886
3870
|
"""Collect audios from input, session history, and current run response."""
|
|
3887
|
-
joint_audios = []
|
|
3871
|
+
joint_audios: List[Audio] = []
|
|
3888
3872
|
|
|
3889
3873
|
# 1. Add audios from current input
|
|
3890
3874
|
if run_input and run_input.audios:
|
|
3891
|
-
|
|
3892
|
-
try:
|
|
3893
|
-
if artifact.url:
|
|
3894
|
-
joint_audios.append(Audio(url=artifact.url))
|
|
3895
|
-
elif artifact.base64_audio:
|
|
3896
|
-
joint_audios.append(Audio(content=artifact.base64_audio))
|
|
3897
|
-
except Exception as e:
|
|
3898
|
-
log_warning(f"Error converting AudioArtifact to Audio: {e}")
|
|
3899
|
-
continue
|
|
3875
|
+
joint_audios.extend(run_input.audios)
|
|
3900
3876
|
log_debug(f"Added {len(run_input.audios)} input audios to joint list")
|
|
3901
3877
|
|
|
3902
3878
|
# 2. Add audios from session history (from both input and generated sources)
|
|
@@ -3905,30 +3881,14 @@ class Agent:
|
|
|
3905
3881
|
for historical_run in session.runs:
|
|
3906
3882
|
# Add generated audios from previous runs
|
|
3907
3883
|
if historical_run.audio:
|
|
3908
|
-
|
|
3909
|
-
try:
|
|
3910
|
-
if artifact.url:
|
|
3911
|
-
joint_audios.append(Audio(url=artifact.url))
|
|
3912
|
-
elif artifact.base64_audio:
|
|
3913
|
-
joint_audios.append(Audio(content=artifact.base64_audio))
|
|
3914
|
-
except Exception as e:
|
|
3915
|
-
log_warning(f"Error converting historical AudioArtifact to Audio: {e}")
|
|
3916
|
-
continue
|
|
3884
|
+
joint_audios.extend(historical_run.audio)
|
|
3917
3885
|
log_debug(
|
|
3918
3886
|
f"Added {len(historical_run.audio)} generated audios from historical run {historical_run.run_id}"
|
|
3919
3887
|
)
|
|
3920
3888
|
|
|
3921
3889
|
# Add input audios from previous runs
|
|
3922
3890
|
if historical_run.input and historical_run.input.audios:
|
|
3923
|
-
|
|
3924
|
-
try:
|
|
3925
|
-
if artifact.url:
|
|
3926
|
-
joint_audios.append(Audio(url=artifact.url))
|
|
3927
|
-
elif artifact.base64_audio:
|
|
3928
|
-
joint_audios.append(Audio(content=artifact.base64_audio))
|
|
3929
|
-
except Exception as e:
|
|
3930
|
-
log_warning(f"Error converting input AudioArtifact to Audio: {e}")
|
|
3931
|
-
continue
|
|
3891
|
+
joint_audios.extend(historical_run.input.audios)
|
|
3932
3892
|
log_debug(
|
|
3933
3893
|
f"Added {len(historical_run.input.audios)} input audios from historical run {historical_run.run_id}"
|
|
3934
3894
|
)
|
|
@@ -5669,21 +5629,21 @@ class Agent:
|
|
|
5669
5629
|
# Handle images, videos and audio
|
|
5670
5630
|
###########################################################################
|
|
5671
5631
|
|
|
5672
|
-
def _add_image(self, image:
|
|
5632
|
+
def _add_image(self, image: Image, run_response: RunOutput) -> None:
|
|
5673
5633
|
"""Add an image to both the agent's stateful storage and the current run response"""
|
|
5674
5634
|
# Add to run response
|
|
5675
5635
|
if run_response.images is None:
|
|
5676
5636
|
run_response.images = []
|
|
5677
5637
|
run_response.images.append(image)
|
|
5678
5638
|
|
|
5679
|
-
def _add_video(self, video:
|
|
5639
|
+
def _add_video(self, video: Video, run_response: RunOutput) -> None:
|
|
5680
5640
|
"""Add a video to both the agent's stateful storage and the current run response"""
|
|
5681
5641
|
# Add to run response
|
|
5682
5642
|
if run_response.videos is None:
|
|
5683
5643
|
run_response.videos = []
|
|
5684
5644
|
run_response.videos.append(video)
|
|
5685
5645
|
|
|
5686
|
-
def _add_audio(self, audio:
|
|
5646
|
+
def _add_audio(self, audio: Audio, run_response: RunOutput) -> None:
|
|
5687
5647
|
"""Add audio to both the agent's stateful storage and the current run response"""
|
|
5688
5648
|
# Add to run response
|
|
5689
5649
|
if run_response.audio is None:
|
|
@@ -7168,63 +7128,46 @@ class Agent:
|
|
|
7168
7128
|
message.image_output = None
|
|
7169
7129
|
message.video_output = None
|
|
7170
7130
|
|
|
7171
|
-
def
|
|
7131
|
+
def _validate_media_object_id(
|
|
7172
7132
|
self,
|
|
7173
7133
|
images: Optional[Sequence[Image]] = None,
|
|
7174
7134
|
videos: Optional[Sequence[Video]] = None,
|
|
7175
7135
|
audios: Optional[Sequence[Audio]] = None,
|
|
7176
7136
|
) -> tuple:
|
|
7177
|
-
"""Convert raw Image/Video/Audio objects
|
|
7178
|
-
|
|
7179
|
-
|
|
7180
|
-
from agno.media import AudioArtifact, ImageArtifact, VideoArtifact
|
|
7181
|
-
|
|
7182
|
-
image_artifacts = None
|
|
7137
|
+
"""Convert raw Image/Video/Audio objects - now unified, so just return as-is."""
|
|
7138
|
+
# With unified classes, no conversion needed - just ensure IDs are set
|
|
7139
|
+
image_list = None
|
|
7183
7140
|
if images:
|
|
7184
|
-
|
|
7141
|
+
image_list = []
|
|
7185
7142
|
for img in images:
|
|
7186
|
-
|
|
7187
|
-
|
|
7143
|
+
# Ensure ID is set (validation should handle this, but double-check)
|
|
7144
|
+
if not img.id:
|
|
7145
|
+
from uuid import uuid4
|
|
7188
7146
|
|
|
7189
|
-
|
|
7190
|
-
|
|
7191
|
-
elif img.content:
|
|
7192
|
-
image_artifacts.append(ImageArtifact(id=artifact_id, content=img.content))
|
|
7193
|
-
except Exception as e:
|
|
7194
|
-
log_warning(f"Error creating ImageArtifact: {e}")
|
|
7195
|
-
continue
|
|
7147
|
+
img.id = str(uuid4())
|
|
7148
|
+
image_list.append(img)
|
|
7196
7149
|
|
|
7197
|
-
|
|
7150
|
+
video_list = None
|
|
7198
7151
|
if videos:
|
|
7199
|
-
|
|
7152
|
+
video_list = []
|
|
7200
7153
|
for vid in videos:
|
|
7201
|
-
|
|
7202
|
-
|
|
7154
|
+
if not vid.id:
|
|
7155
|
+
from uuid import uuid4
|
|
7203
7156
|
|
|
7204
|
-
|
|
7205
|
-
|
|
7206
|
-
elif vid.content:
|
|
7207
|
-
video_artifacts.append(VideoArtifact(id=artifact_id, content=vid.content))
|
|
7208
|
-
except Exception as e:
|
|
7209
|
-
log_warning(f"Error creating VideoArtifact: {e}")
|
|
7210
|
-
continue
|
|
7157
|
+
vid.id = str(uuid4())
|
|
7158
|
+
video_list.append(vid)
|
|
7211
7159
|
|
|
7212
|
-
|
|
7160
|
+
audio_list = None
|
|
7213
7161
|
if audios:
|
|
7214
|
-
|
|
7162
|
+
audio_list = []
|
|
7215
7163
|
for aud in audios:
|
|
7216
|
-
|
|
7217
|
-
|
|
7164
|
+
if not aud.id:
|
|
7165
|
+
from uuid import uuid4
|
|
7218
7166
|
|
|
7219
|
-
|
|
7220
|
-
|
|
7221
|
-
elif aud.content:
|
|
7222
|
-
audio_artifacts.append(AudioArtifact(id=artifact_id, content=aud.content))
|
|
7223
|
-
except Exception as e:
|
|
7224
|
-
log_warning(f"Error creating AudioArtifact: {e}")
|
|
7225
|
-
continue
|
|
7167
|
+
aud.id = str(uuid4())
|
|
7168
|
+
audio_list.append(aud)
|
|
7226
7169
|
|
|
7227
|
-
return
|
|
7170
|
+
return image_list, video_list, audio_list
|
|
7228
7171
|
|
|
7229
7172
|
def cli_app(
|
|
7230
7173
|
self,
|
agno/knowledge/knowledge.py
CHANGED
|
@@ -474,7 +474,7 @@ class Knowledge:
|
|
|
474
474
|
# 4. Select reader
|
|
475
475
|
# If a reader was provided by the user, use it
|
|
476
476
|
reader = content.reader
|
|
477
|
-
name = content.name
|
|
477
|
+
name = content.name if content.name else content.url
|
|
478
478
|
# Else select based on file extension
|
|
479
479
|
if reader is None:
|
|
480
480
|
url_path = Path(parsed_url.path)
|