agno 2.0.0rc1__py3-none-any.whl → 2.0.1__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 +101 -140
- agno/db/mongo/mongo.py +8 -3
- agno/eval/accuracy.py +12 -5
- agno/knowledge/chunking/strategy.py +14 -14
- agno/knowledge/knowledge.py +156 -120
- agno/knowledge/reader/arxiv_reader.py +5 -5
- agno/knowledge/reader/csv_reader.py +6 -77
- agno/knowledge/reader/docx_reader.py +5 -5
- agno/knowledge/reader/firecrawl_reader.py +5 -5
- agno/knowledge/reader/json_reader.py +5 -5
- agno/knowledge/reader/markdown_reader.py +31 -9
- agno/knowledge/reader/pdf_reader.py +10 -123
- agno/knowledge/reader/reader_factory.py +65 -72
- agno/knowledge/reader/s3_reader.py +44 -114
- agno/knowledge/reader/text_reader.py +5 -5
- agno/knowledge/reader/url_reader.py +75 -31
- agno/knowledge/reader/web_search_reader.py +6 -29
- agno/knowledge/reader/website_reader.py +5 -5
- agno/knowledge/reader/wikipedia_reader.py +5 -5
- agno/knowledge/reader/youtube_reader.py +6 -6
- agno/knowledge/reranker/__init__.py +9 -0
- agno/knowledge/utils.py +10 -10
- agno/media.py +269 -268
- agno/models/aws/bedrock.py +3 -7
- agno/models/base.py +50 -54
- 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 +40 -29
- agno/os/mcp.py +39 -59
- agno/os/router.py +547 -16
- agno/os/routers/evals/evals.py +197 -12
- agno/os/routers/knowledge/knowledge.py +428 -14
- agno/os/routers/memory/memory.py +250 -28
- agno/os/routers/metrics/metrics.py +125 -7
- agno/os/routers/session/session.py +393 -25
- agno/os/schema.py +55 -2
- agno/run/agent.py +37 -28
- agno/run/base.py +9 -19
- agno/run/team.py +110 -19
- agno/run/workflow.py +41 -28
- agno/team/team.py +808 -1080
- 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/mcp.py +1 -2
- 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/log.py +52 -2
- agno/utils/mcp.py +57 -5
- agno/utils/models/aws_claude.py +1 -1
- agno/utils/models/claude.py +0 -8
- agno/utils/models/cohere.py +1 -1
- agno/utils/models/watsonx.py +1 -1
- agno/utils/openai.py +1 -1
- agno/utils/print_response/team.py +177 -73
- agno/utils/streamlit.py +27 -0
- agno/vectordb/lancedb/lance_db.py +82 -25
- agno/workflow/step.py +7 -7
- agno/workflow/types.py +13 -13
- agno/workflow/workflow.py +37 -28
- {agno-2.0.0rc1.dist-info → agno-2.0.1.dist-info}/METADATA +140 -1
- {agno-2.0.0rc1.dist-info → agno-2.0.1.dist-info}/RECORD +83 -84
- agno-2.0.1.dist-info/licenses/LICENSE +201 -0
- agno/knowledge/reader/gcs_reader.py +0 -67
- agno-2.0.0rc1.dist-info/licenses/LICENSE +0 -375
- {agno-2.0.0rc1.dist-info → agno-2.0.1.dist-info}/WHEEL +0 -0
- {agno-2.0.0rc1.dist-info → agno-2.0.1.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
|
|
@@ -129,10 +129,10 @@ class Agent:
|
|
|
129
129
|
session_id: Optional[str] = None
|
|
130
130
|
# Default session state (stored in the database to persist across runs)
|
|
131
131
|
session_state: Optional[Dict[str, Any]] = None
|
|
132
|
-
#
|
|
133
|
-
enable_agentic_state: bool = False
|
|
134
|
-
# If True, add the session state to the user prompt
|
|
132
|
+
# Set to True to add the session_state to the context
|
|
135
133
|
add_session_state_to_context: bool = False
|
|
134
|
+
# Set to True to give the agent tools to update the session_state dynamically
|
|
135
|
+
enable_agentic_state: bool = False
|
|
136
136
|
# If True, cache the current Agent session in memory for faster access
|
|
137
137
|
cache_session: bool = False
|
|
138
138
|
|
|
@@ -321,8 +321,6 @@ class Agent:
|
|
|
321
321
|
# --- If this Agent is part of a workflow ---
|
|
322
322
|
# Optional workflow ID. Indicates this agent is part of a workflow.
|
|
323
323
|
workflow_id: Optional[str] = None
|
|
324
|
-
# Set when this agent is part of a workflow.
|
|
325
|
-
workflow_session_id: Optional[str] = None
|
|
326
324
|
|
|
327
325
|
# Metadata stored with this agent
|
|
328
326
|
metadata: Optional[Dict[str, Any]] = None
|
|
@@ -345,7 +343,6 @@ class Agent:
|
|
|
345
343
|
id: Optional[str] = None,
|
|
346
344
|
introduction: Optional[str] = None,
|
|
347
345
|
user_id: Optional[str] = None,
|
|
348
|
-
app_id: Optional[str] = None,
|
|
349
346
|
session_id: Optional[str] = None,
|
|
350
347
|
session_state: Optional[Dict[str, Any]] = None,
|
|
351
348
|
add_session_state_to_context: bool = False,
|
|
@@ -429,7 +426,6 @@ class Agent:
|
|
|
429
426
|
self.id = id
|
|
430
427
|
self.introduction = introduction
|
|
431
428
|
self.user_id = user_id
|
|
432
|
-
self.app_id = app_id
|
|
433
429
|
|
|
434
430
|
self.session_id = session_id
|
|
435
431
|
self.session_state = session_state
|
|
@@ -593,6 +589,15 @@ class Agent:
|
|
|
593
589
|
if isinstance(input, Message):
|
|
594
590
|
input = input.content # type: ignore
|
|
595
591
|
|
|
592
|
+
# If input is a string, convert it to a dict
|
|
593
|
+
if isinstance(input, str):
|
|
594
|
+
import json
|
|
595
|
+
|
|
596
|
+
try:
|
|
597
|
+
input = json.loads(input)
|
|
598
|
+
except Exception as e:
|
|
599
|
+
raise ValueError(f"Failed to parse input. Is it a valid JSON string?: {e}")
|
|
600
|
+
|
|
596
601
|
# Case 1: Message is already a BaseModel instance
|
|
597
602
|
if isinstance(input, BaseModel):
|
|
598
603
|
if isinstance(input, self.input_schema):
|
|
@@ -1073,7 +1078,7 @@ class Agent:
|
|
|
1073
1078
|
# Initialize the Agent
|
|
1074
1079
|
self.initialize_agent(debug_mode=debug_mode)
|
|
1075
1080
|
|
|
1076
|
-
image_artifacts, video_artifacts, audio_artifacts = self.
|
|
1081
|
+
image_artifacts, video_artifacts, audio_artifacts = self._validate_media_object_id(
|
|
1077
1082
|
images=images, videos=videos, audios=audio
|
|
1078
1083
|
)
|
|
1079
1084
|
|
|
@@ -1642,7 +1647,7 @@ class Agent:
|
|
|
1642
1647
|
# Initialize the Agent
|
|
1643
1648
|
self.initialize_agent(debug_mode=debug_mode)
|
|
1644
1649
|
|
|
1645
|
-
image_artifacts, video_artifacts, audio_artifacts = self.
|
|
1650
|
+
image_artifacts, video_artifacts, audio_artifacts = self._validate_media_object_id(
|
|
1646
1651
|
images=images, videos=videos, audios=audio
|
|
1647
1652
|
)
|
|
1648
1653
|
|
|
@@ -3231,6 +3236,12 @@ class Agent:
|
|
|
3231
3236
|
if isinstance(model_response_event, tuple(get_args(RunOutputEvent))) or isinstance(
|
|
3232
3237
|
model_response_event, tuple(get_args(TeamRunOutputEvent))
|
|
3233
3238
|
):
|
|
3239
|
+
if model_response_event.event == RunEvent.custom_event: # type: ignore
|
|
3240
|
+
model_response_event.agent_id = self.id # type: ignore
|
|
3241
|
+
model_response_event.agent_name = self.name # type: ignore
|
|
3242
|
+
model_response_event.session_id = session.session_id # type: ignore
|
|
3243
|
+
model_response_event.run_id = run_response.run_id # type: ignore
|
|
3244
|
+
|
|
3234
3245
|
# We just bubble the event up
|
|
3235
3246
|
yield self._handle_event(model_response_event, run_response) # type: ignore
|
|
3236
3247
|
else:
|
|
@@ -3309,23 +3320,47 @@ class Agent:
|
|
|
3309
3320
|
# Process audio
|
|
3310
3321
|
if model_response_event.audio is not None:
|
|
3311
3322
|
if model_response.audio is None:
|
|
3312
|
-
model_response.audio =
|
|
3323
|
+
model_response.audio = Audio(id=str(uuid4()), content=b"", transcript="")
|
|
3313
3324
|
|
|
3314
3325
|
if model_response_event.audio.id is not None:
|
|
3315
3326
|
model_response.audio.id = model_response_event.audio.id # type: ignore
|
|
3327
|
+
|
|
3316
3328
|
if model_response_event.audio.content is not None:
|
|
3317
|
-
|
|
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
|
+
|
|
3318
3350
|
if model_response_event.audio.transcript is not None:
|
|
3319
3351
|
model_response.audio.transcript += model_response_event.audio.transcript # type: ignore
|
|
3352
|
+
|
|
3320
3353
|
if model_response_event.audio.expires_at is not None:
|
|
3321
3354
|
model_response.audio.expires_at = model_response_event.audio.expires_at # type: ignore
|
|
3322
3355
|
if model_response_event.audio.mime_type is not None:
|
|
3323
3356
|
model_response.audio.mime_type = model_response_event.audio.mime_type # type: ignore
|
|
3324
|
-
|
|
3325
|
-
|
|
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
|
|
3326
3361
|
|
|
3327
3362
|
# Yield the audio and transcript bit by bit
|
|
3328
|
-
run_response.response_audio =
|
|
3363
|
+
run_response.response_audio = Audio(
|
|
3329
3364
|
id=model_response_event.audio.id,
|
|
3330
3365
|
content=model_response_event.audio.content,
|
|
3331
3366
|
transcript=model_response_event.audio.transcript,
|
|
@@ -3353,6 +3388,14 @@ class Agent:
|
|
|
3353
3388
|
workflow_context=workflow_context,
|
|
3354
3389
|
)
|
|
3355
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
|
+
|
|
3356
3399
|
# Handle tool interruption events
|
|
3357
3400
|
elif model_response_event.event == ModelResponseEvent.tool_call_paused.value:
|
|
3358
3401
|
# Add tool calls to the run_response
|
|
@@ -3751,19 +3794,11 @@ class Agent:
|
|
|
3751
3794
|
session: Optional[AgentSession] = None,
|
|
3752
3795
|
) -> Optional[Sequence[Image]]:
|
|
3753
3796
|
"""Collect images from input, session history, and current run response."""
|
|
3754
|
-
joint_images = []
|
|
3797
|
+
joint_images: List[Image] = []
|
|
3755
3798
|
|
|
3756
3799
|
# 1. Add images from current input
|
|
3757
3800
|
if run_input and run_input.images:
|
|
3758
|
-
|
|
3759
|
-
try:
|
|
3760
|
-
if artifact.url:
|
|
3761
|
-
joint_images.append(Image(url=artifact.url))
|
|
3762
|
-
elif artifact.content:
|
|
3763
|
-
joint_images.append(Image(content=artifact.content))
|
|
3764
|
-
except Exception as e:
|
|
3765
|
-
log_warning(f"Error converting ImageArtifact to Image: {e}")
|
|
3766
|
-
continue
|
|
3801
|
+
joint_images.extend(run_input.images)
|
|
3767
3802
|
log_debug(f"Added {len(run_input.images)} input images to joint list")
|
|
3768
3803
|
|
|
3769
3804
|
# 2. Add images from session history (from both input and generated sources)
|
|
@@ -3772,30 +3807,14 @@ class Agent:
|
|
|
3772
3807
|
for historical_run in session.runs:
|
|
3773
3808
|
# Add generated images from previous runs
|
|
3774
3809
|
if historical_run.images:
|
|
3775
|
-
|
|
3776
|
-
try:
|
|
3777
|
-
if artifact.url:
|
|
3778
|
-
joint_images.append(Image(url=artifact.url))
|
|
3779
|
-
elif artifact.content:
|
|
3780
|
-
joint_images.append(Image(content=artifact.content))
|
|
3781
|
-
except Exception as e:
|
|
3782
|
-
log_warning(f"Error converting historical ImageArtifact to Image: {e}")
|
|
3783
|
-
continue
|
|
3810
|
+
joint_images.extend(historical_run.images)
|
|
3784
3811
|
log_debug(
|
|
3785
3812
|
f"Added {len(historical_run.images)} generated images from historical run {historical_run.run_id}"
|
|
3786
3813
|
)
|
|
3787
3814
|
|
|
3788
3815
|
# Add input images from previous runs
|
|
3789
3816
|
if historical_run.input and historical_run.input.images:
|
|
3790
|
-
|
|
3791
|
-
try:
|
|
3792
|
-
if artifact.url:
|
|
3793
|
-
joint_images.append(Image(url=artifact.url))
|
|
3794
|
-
elif artifact.content:
|
|
3795
|
-
joint_images.append(Image(content=artifact.content))
|
|
3796
|
-
except Exception as e:
|
|
3797
|
-
log_warning(f"Error converting input ImageArtifact to Image: {e}")
|
|
3798
|
-
continue
|
|
3817
|
+
joint_images.extend(historical_run.input.images)
|
|
3799
3818
|
log_debug(
|
|
3800
3819
|
f"Added {len(historical_run.input.images)} input images from historical run {historical_run.run_id}"
|
|
3801
3820
|
)
|
|
@@ -3812,19 +3831,11 @@ class Agent:
|
|
|
3812
3831
|
session: Optional[AgentSession] = None,
|
|
3813
3832
|
) -> Optional[Sequence[Video]]:
|
|
3814
3833
|
"""Collect videos from input, session history, and current run response."""
|
|
3815
|
-
joint_videos = []
|
|
3834
|
+
joint_videos: List[Video] = []
|
|
3816
3835
|
|
|
3817
3836
|
# 1. Add videos from current input
|
|
3818
3837
|
if run_input and run_input.videos:
|
|
3819
|
-
|
|
3820
|
-
try:
|
|
3821
|
-
if artifact.url:
|
|
3822
|
-
joint_videos.append(Video(url=artifact.url))
|
|
3823
|
-
elif artifact.content:
|
|
3824
|
-
joint_videos.append(Video(content=artifact.content))
|
|
3825
|
-
except Exception as e:
|
|
3826
|
-
log_warning(f"Error converting VideoArtifact to Video: {e}")
|
|
3827
|
-
continue
|
|
3838
|
+
joint_videos.extend(run_input.videos)
|
|
3828
3839
|
log_debug(f"Added {len(run_input.videos)} input videos to joint list")
|
|
3829
3840
|
|
|
3830
3841
|
# 2. Add videos from session history (from both input and generated sources)
|
|
@@ -3833,30 +3844,14 @@ class Agent:
|
|
|
3833
3844
|
for historical_run in session.runs:
|
|
3834
3845
|
# Add generated videos from previous runs
|
|
3835
3846
|
if historical_run.videos:
|
|
3836
|
-
|
|
3837
|
-
try:
|
|
3838
|
-
if artifact.url:
|
|
3839
|
-
joint_videos.append(Video(url=artifact.url))
|
|
3840
|
-
elif artifact.content:
|
|
3841
|
-
joint_videos.append(Video(content=artifact.content))
|
|
3842
|
-
except Exception as e:
|
|
3843
|
-
log_warning(f"Error converting historical VideoArtifact to Video: {e}")
|
|
3844
|
-
continue
|
|
3847
|
+
joint_videos.extend(historical_run.videos)
|
|
3845
3848
|
log_debug(
|
|
3846
3849
|
f"Added {len(historical_run.videos)} generated videos from historical run {historical_run.run_id}"
|
|
3847
3850
|
)
|
|
3848
3851
|
|
|
3849
3852
|
# Add input videos from previous runs
|
|
3850
3853
|
if historical_run.input and historical_run.input.videos:
|
|
3851
|
-
|
|
3852
|
-
try:
|
|
3853
|
-
if artifact.url:
|
|
3854
|
-
joint_videos.append(Video(url=artifact.url))
|
|
3855
|
-
elif artifact.content:
|
|
3856
|
-
joint_videos.append(Video(content=artifact.content))
|
|
3857
|
-
except Exception as e:
|
|
3858
|
-
log_warning(f"Error converting input VideoArtifact to Video: {e}")
|
|
3859
|
-
continue
|
|
3854
|
+
joint_videos.extend(historical_run.input.videos)
|
|
3860
3855
|
log_debug(
|
|
3861
3856
|
f"Added {len(historical_run.input.videos)} input videos from historical run {historical_run.run_id}"
|
|
3862
3857
|
)
|
|
@@ -3873,19 +3868,11 @@ class Agent:
|
|
|
3873
3868
|
session: Optional[AgentSession] = None,
|
|
3874
3869
|
) -> Optional[Sequence[Audio]]:
|
|
3875
3870
|
"""Collect audios from input, session history, and current run response."""
|
|
3876
|
-
joint_audios = []
|
|
3871
|
+
joint_audios: List[Audio] = []
|
|
3877
3872
|
|
|
3878
3873
|
# 1. Add audios from current input
|
|
3879
3874
|
if run_input and run_input.audios:
|
|
3880
|
-
|
|
3881
|
-
try:
|
|
3882
|
-
if artifact.url:
|
|
3883
|
-
joint_audios.append(Audio(url=artifact.url))
|
|
3884
|
-
elif artifact.base64_audio:
|
|
3885
|
-
joint_audios.append(Audio(content=artifact.base64_audio))
|
|
3886
|
-
except Exception as e:
|
|
3887
|
-
log_warning(f"Error converting AudioArtifact to Audio: {e}")
|
|
3888
|
-
continue
|
|
3875
|
+
joint_audios.extend(run_input.audios)
|
|
3889
3876
|
log_debug(f"Added {len(run_input.audios)} input audios to joint list")
|
|
3890
3877
|
|
|
3891
3878
|
# 2. Add audios from session history (from both input and generated sources)
|
|
@@ -3894,30 +3881,14 @@ class Agent:
|
|
|
3894
3881
|
for historical_run in session.runs:
|
|
3895
3882
|
# Add generated audios from previous runs
|
|
3896
3883
|
if historical_run.audio:
|
|
3897
|
-
|
|
3898
|
-
try:
|
|
3899
|
-
if artifact.url:
|
|
3900
|
-
joint_audios.append(Audio(url=artifact.url))
|
|
3901
|
-
elif artifact.base64_audio:
|
|
3902
|
-
joint_audios.append(Audio(content=artifact.base64_audio))
|
|
3903
|
-
except Exception as e:
|
|
3904
|
-
log_warning(f"Error converting historical AudioArtifact to Audio: {e}")
|
|
3905
|
-
continue
|
|
3884
|
+
joint_audios.extend(historical_run.audio)
|
|
3906
3885
|
log_debug(
|
|
3907
3886
|
f"Added {len(historical_run.audio)} generated audios from historical run {historical_run.run_id}"
|
|
3908
3887
|
)
|
|
3909
3888
|
|
|
3910
3889
|
# Add input audios from previous runs
|
|
3911
3890
|
if historical_run.input and historical_run.input.audios:
|
|
3912
|
-
|
|
3913
|
-
try:
|
|
3914
|
-
if artifact.url:
|
|
3915
|
-
joint_audios.append(Audio(url=artifact.url))
|
|
3916
|
-
elif artifact.base64_audio:
|
|
3917
|
-
joint_audios.append(Audio(content=artifact.base64_audio))
|
|
3918
|
-
except Exception as e:
|
|
3919
|
-
log_warning(f"Error converting input AudioArtifact to Audio: {e}")
|
|
3920
|
-
continue
|
|
3891
|
+
joint_audios.extend(historical_run.input.audios)
|
|
3921
3892
|
log_debug(
|
|
3922
3893
|
f"Added {len(historical_run.input.audios)} input audios from historical run {historical_run.run_id}"
|
|
3923
3894
|
)
|
|
@@ -4365,7 +4336,7 @@ class Agent:
|
|
|
4365
4336
|
|
|
4366
4337
|
return agent_session
|
|
4367
4338
|
|
|
4368
|
-
|
|
4339
|
+
log_debug(f"AgentSession {session_id_to_load} not found in db")
|
|
4369
4340
|
return None
|
|
4370
4341
|
|
|
4371
4342
|
def save_session(self, session: AgentSession) -> None:
|
|
@@ -5658,21 +5629,21 @@ class Agent:
|
|
|
5658
5629
|
# Handle images, videos and audio
|
|
5659
5630
|
###########################################################################
|
|
5660
5631
|
|
|
5661
|
-
def _add_image(self, image:
|
|
5632
|
+
def _add_image(self, image: Image, run_response: RunOutput) -> None:
|
|
5662
5633
|
"""Add an image to both the agent's stateful storage and the current run response"""
|
|
5663
5634
|
# Add to run response
|
|
5664
5635
|
if run_response.images is None:
|
|
5665
5636
|
run_response.images = []
|
|
5666
5637
|
run_response.images.append(image)
|
|
5667
5638
|
|
|
5668
|
-
def _add_video(self, video:
|
|
5639
|
+
def _add_video(self, video: Video, run_response: RunOutput) -> None:
|
|
5669
5640
|
"""Add a video to both the agent's stateful storage and the current run response"""
|
|
5670
5641
|
# Add to run response
|
|
5671
5642
|
if run_response.videos is None:
|
|
5672
5643
|
run_response.videos = []
|
|
5673
5644
|
run_response.videos.append(video)
|
|
5674
5645
|
|
|
5675
|
-
def _add_audio(self, audio:
|
|
5646
|
+
def _add_audio(self, audio: Audio, run_response: RunOutput) -> None:
|
|
5676
5647
|
"""Add audio to both the agent's stateful storage and the current run response"""
|
|
5677
5648
|
# Add to run response
|
|
5678
5649
|
if run_response.audio is None:
|
|
@@ -6841,6 +6812,7 @@ class Agent:
|
|
|
6841
6812
|
|
|
6842
6813
|
if self.output_schema is not None:
|
|
6843
6814
|
markdown = False
|
|
6815
|
+
markdown = False
|
|
6844
6816
|
|
|
6845
6817
|
if stream is None:
|
|
6846
6818
|
stream = self.stream or False
|
|
@@ -7156,57 +7128,46 @@ class Agent:
|
|
|
7156
7128
|
message.image_output = None
|
|
7157
7129
|
message.video_output = None
|
|
7158
7130
|
|
|
7159
|
-
def
|
|
7131
|
+
def _validate_media_object_id(
|
|
7160
7132
|
self,
|
|
7161
7133
|
images: Optional[Sequence[Image]] = None,
|
|
7162
7134
|
videos: Optional[Sequence[Video]] = None,
|
|
7163
7135
|
audios: Optional[Sequence[Audio]] = None,
|
|
7164
7136
|
) -> tuple:
|
|
7165
|
-
"""Convert raw Image/Video/Audio objects
|
|
7166
|
-
|
|
7167
|
-
|
|
7168
|
-
from agno.media import AudioArtifact, ImageArtifact, VideoArtifact
|
|
7169
|
-
|
|
7170
|
-
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
|
|
7171
7140
|
if images:
|
|
7172
|
-
|
|
7141
|
+
image_list = []
|
|
7173
7142
|
for img in images:
|
|
7174
|
-
|
|
7175
|
-
|
|
7176
|
-
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
7180
|
-
log_warning(f"Error creating ImageArtifact: {e}")
|
|
7181
|
-
continue
|
|
7143
|
+
# Ensure ID is set (validation should handle this, but double-check)
|
|
7144
|
+
if not img.id:
|
|
7145
|
+
from uuid import uuid4
|
|
7146
|
+
|
|
7147
|
+
img.id = str(uuid4())
|
|
7148
|
+
image_list.append(img)
|
|
7182
7149
|
|
|
7183
|
-
|
|
7150
|
+
video_list = None
|
|
7184
7151
|
if videos:
|
|
7185
|
-
|
|
7152
|
+
video_list = []
|
|
7186
7153
|
for vid in videos:
|
|
7187
|
-
|
|
7188
|
-
|
|
7189
|
-
video_artifacts.append(VideoArtifact(id=str(uuid4()), url=vid.url))
|
|
7190
|
-
elif vid.content:
|
|
7191
|
-
video_artifacts.append(VideoArtifact(id=str(uuid4()), content=vid.content))
|
|
7192
|
-
except Exception as e:
|
|
7193
|
-
log_warning(f"Error creating VideoArtifact: {e}")
|
|
7194
|
-
continue
|
|
7154
|
+
if not vid.id:
|
|
7155
|
+
from uuid import uuid4
|
|
7195
7156
|
|
|
7196
|
-
|
|
7157
|
+
vid.id = str(uuid4())
|
|
7158
|
+
video_list.append(vid)
|
|
7159
|
+
|
|
7160
|
+
audio_list = None
|
|
7197
7161
|
if audios:
|
|
7198
|
-
|
|
7162
|
+
audio_list = []
|
|
7199
7163
|
for aud in audios:
|
|
7200
|
-
|
|
7201
|
-
|
|
7202
|
-
|
|
7203
|
-
|
|
7204
|
-
|
|
7205
|
-
except Exception as e:
|
|
7206
|
-
log_warning(f"Error creating AudioArtifact: {e}")
|
|
7207
|
-
continue
|
|
7164
|
+
if not aud.id:
|
|
7165
|
+
from uuid import uuid4
|
|
7166
|
+
|
|
7167
|
+
aud.id = str(uuid4())
|
|
7168
|
+
audio_list.append(aud)
|
|
7208
7169
|
|
|
7209
|
-
return
|
|
7170
|
+
return image_list, video_list, audio_list
|
|
7210
7171
|
|
|
7211
7172
|
def cli_app(
|
|
7212
7173
|
self,
|
agno/db/mongo/mongo.py
CHANGED
|
@@ -672,7 +672,9 @@ class MongoDb(BaseDb):
|
|
|
672
672
|
if result is None or not deserialize:
|
|
673
673
|
return result
|
|
674
674
|
|
|
675
|
-
|
|
675
|
+
# Remove MongoDB's _id field before creating UserMemory object
|
|
676
|
+
result_filtered = {k: v for k, v in result.items() if k != "_id"}
|
|
677
|
+
return UserMemory.from_dict(result_filtered)
|
|
676
678
|
|
|
677
679
|
except Exception as e:
|
|
678
680
|
log_error(f"Exception reading from collection: {e}")
|
|
@@ -750,7 +752,8 @@ class MongoDb(BaseDb):
|
|
|
750
752
|
if not deserialize:
|
|
751
753
|
return records, total_count
|
|
752
754
|
|
|
753
|
-
|
|
755
|
+
# Remove MongoDB's _id field before creating UserMemory objects
|
|
756
|
+
return [UserMemory.from_dict({k: v for k, v in record.items() if k != "_id"}) for record in records]
|
|
754
757
|
|
|
755
758
|
except Exception as e:
|
|
756
759
|
log_error(f"Exception reading from collection: {e}")
|
|
@@ -861,7 +864,9 @@ class MongoDb(BaseDb):
|
|
|
861
864
|
if not deserialize:
|
|
862
865
|
return update_doc
|
|
863
866
|
|
|
864
|
-
|
|
867
|
+
# Remove MongoDB's _id field before creating UserMemory object
|
|
868
|
+
update_doc_filtered = {k: v for k, v in update_doc.items() if k != "_id"}
|
|
869
|
+
return UserMemory.from_dict(update_doc_filtered)
|
|
865
870
|
|
|
866
871
|
except Exception as e:
|
|
867
872
|
log_error(f"Exception upserting user memory: {e}")
|
agno/eval/accuracy.py
CHANGED
|
@@ -97,11 +97,18 @@ class AccuracyResult:
|
|
|
97
97
|
title_justify="center",
|
|
98
98
|
)
|
|
99
99
|
summary_table.add_row("Number of Runs", f"{len(self.results)}")
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
100
|
+
|
|
101
|
+
if self.avg_score is not None:
|
|
102
|
+
summary_table.add_row("Average Score", f"{self.avg_score:.2f}")
|
|
103
|
+
if self.mean_score is not None:
|
|
104
|
+
summary_table.add_row("Mean Score", f"{self.mean_score:.2f}")
|
|
105
|
+
if self.min_score is not None:
|
|
106
|
+
summary_table.add_row("Minimum Score", f"{self.min_score:.2f}")
|
|
107
|
+
if self.max_score is not None:
|
|
108
|
+
summary_table.add_row("Maximum Score", f"{self.max_score:.2f}")
|
|
109
|
+
if self.std_dev_score is not None:
|
|
110
|
+
summary_table.add_row("Standard Deviation", f"{self.std_dev_score:.2f}")
|
|
111
|
+
|
|
105
112
|
console.print(summary_table)
|
|
106
113
|
|
|
107
114
|
def print_results(self, console: Optional["Console"] = None):
|
|
@@ -35,13 +35,13 @@ class ChunkingStrategy(ABC):
|
|
|
35
35
|
class ChunkingStrategyType(str, Enum):
|
|
36
36
|
"""Enumeration of available chunking strategies."""
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
AGENTIC_CHUNKER = "AgenticChunker"
|
|
39
|
+
DOCUMENT_CHUNKER = "DocumentChunker"
|
|
40
|
+
RECURSIVE_CHUNKER = "RecursiveChunker"
|
|
41
|
+
SEMANTIC_CHUNKER = "SemanticChunker"
|
|
42
|
+
FIXED_SIZE_CHUNKER = "FixedSizeChunker"
|
|
43
|
+
ROW_CHUNKER = "RowChunker"
|
|
44
|
+
MARKDOWN_CHUNKER = "MarkdownChunker"
|
|
45
45
|
|
|
46
46
|
@classmethod
|
|
47
47
|
def from_string(cls, strategy_name: str) -> "ChunkingStrategyType":
|
|
@@ -63,13 +63,13 @@ class ChunkingStrategyFactory:
|
|
|
63
63
|
def create_strategy(cls, strategy_type: ChunkingStrategyType, **kwargs) -> ChunkingStrategy:
|
|
64
64
|
"""Create an instance of the chunking strategy with the given parameters."""
|
|
65
65
|
strategy_map = {
|
|
66
|
-
ChunkingStrategyType.
|
|
67
|
-
ChunkingStrategyType.
|
|
68
|
-
ChunkingStrategyType.
|
|
69
|
-
ChunkingStrategyType.
|
|
70
|
-
ChunkingStrategyType.
|
|
71
|
-
ChunkingStrategyType.
|
|
72
|
-
ChunkingStrategyType.
|
|
66
|
+
ChunkingStrategyType.AGENTIC_CHUNKER: cls._create_agentic_chunking,
|
|
67
|
+
ChunkingStrategyType.DOCUMENT_CHUNKER: cls._create_document_chunking,
|
|
68
|
+
ChunkingStrategyType.RECURSIVE_CHUNKER: cls._create_recursive_chunking,
|
|
69
|
+
ChunkingStrategyType.SEMANTIC_CHUNKER: cls._create_semantic_chunking,
|
|
70
|
+
ChunkingStrategyType.FIXED_SIZE_CHUNKER: cls._create_fixed_chunking,
|
|
71
|
+
ChunkingStrategyType.ROW_CHUNKER: cls._create_row_chunking,
|
|
72
|
+
ChunkingStrategyType.MARKDOWN_CHUNKER: cls._create_markdown_chunking,
|
|
73
73
|
}
|
|
74
74
|
return strategy_map[strategy_type](**kwargs)
|
|
75
75
|
|