agno 1.8.0__py3-none-any.whl → 2.0.0a1__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/__init__.py +8 -0
- agno/agent/__init__.py +19 -27
- agno/agent/agent.py +2781 -4126
- agno/api/agent.py +9 -65
- agno/api/api.py +5 -46
- agno/api/evals.py +6 -17
- agno/api/os.py +17 -0
- agno/api/routes.py +6 -41
- agno/api/schemas/__init__.py +9 -0
- agno/api/schemas/agent.py +5 -21
- agno/api/schemas/evals.py +7 -16
- agno/api/schemas/os.py +14 -0
- agno/api/schemas/team.py +5 -21
- agno/api/schemas/utils.py +21 -0
- agno/api/schemas/workflows.py +11 -7
- agno/api/settings.py +53 -0
- agno/api/team.py +9 -64
- agno/api/workflow.py +28 -0
- agno/cloud/aws/base.py +214 -0
- agno/cloud/aws/s3/__init__.py +2 -0
- agno/cloud/aws/s3/api_client.py +43 -0
- agno/cloud/aws/s3/bucket.py +195 -0
- agno/cloud/aws/s3/object.py +57 -0
- agno/db/__init__.py +24 -0
- agno/db/base.py +245 -0
- agno/db/dynamo/__init__.py +3 -0
- agno/db/dynamo/dynamo.py +1749 -0
- agno/db/dynamo/schemas.py +278 -0
- agno/db/dynamo/utils.py +684 -0
- agno/db/firestore/__init__.py +3 -0
- agno/db/firestore/firestore.py +1438 -0
- agno/db/firestore/schemas.py +130 -0
- agno/db/firestore/utils.py +278 -0
- agno/db/gcs_json/__init__.py +3 -0
- agno/db/gcs_json/gcs_json_db.py +1001 -0
- agno/db/gcs_json/utils.py +194 -0
- agno/db/in_memory/__init__.py +3 -0
- agno/db/in_memory/in_memory_db.py +888 -0
- agno/db/in_memory/utils.py +172 -0
- agno/db/json/__init__.py +3 -0
- agno/db/json/json_db.py +1051 -0
- agno/db/json/utils.py +196 -0
- agno/db/migrations/v1_to_v2.py +162 -0
- agno/db/mongo/__init__.py +3 -0
- agno/db/mongo/mongo.py +1417 -0
- agno/db/mongo/schemas.py +77 -0
- agno/db/mongo/utils.py +204 -0
- agno/db/mysql/__init__.py +3 -0
- agno/db/mysql/mysql.py +1719 -0
- agno/db/mysql/schemas.py +124 -0
- agno/db/mysql/utils.py +298 -0
- agno/db/postgres/__init__.py +3 -0
- agno/db/postgres/postgres.py +1720 -0
- agno/db/postgres/schemas.py +124 -0
- agno/db/postgres/utils.py +281 -0
- agno/db/redis/__init__.py +3 -0
- agno/db/redis/redis.py +1371 -0
- agno/db/redis/schemas.py +109 -0
- agno/db/redis/utils.py +288 -0
- agno/db/schemas/__init__.py +3 -0
- agno/db/schemas/evals.py +33 -0
- agno/db/schemas/knowledge.py +40 -0
- agno/db/schemas/memory.py +46 -0
- agno/db/singlestore/__init__.py +3 -0
- agno/db/singlestore/schemas.py +116 -0
- agno/db/singlestore/singlestore.py +1722 -0
- agno/db/singlestore/utils.py +327 -0
- agno/db/sqlite/__init__.py +3 -0
- agno/db/sqlite/schemas.py +119 -0
- agno/db/sqlite/sqlite.py +1680 -0
- agno/db/sqlite/utils.py +269 -0
- agno/db/utils.py +88 -0
- agno/eval/__init__.py +14 -0
- agno/eval/accuracy.py +142 -43
- agno/eval/performance.py +88 -23
- agno/eval/reliability.py +73 -20
- agno/eval/utils.py +23 -13
- agno/integrations/discord/__init__.py +3 -0
- agno/{app → integrations}/discord/client.py +10 -10
- agno/knowledge/__init__.py +2 -2
- agno/{document → knowledge}/chunking/agentic.py +2 -2
- agno/{document → knowledge}/chunking/document.py +2 -2
- agno/{document → knowledge}/chunking/fixed.py +3 -3
- agno/{document → knowledge}/chunking/markdown.py +2 -2
- agno/{document → knowledge}/chunking/recursive.py +2 -2
- agno/{document → knowledge}/chunking/row.py +2 -2
- agno/knowledge/chunking/semantic.py +59 -0
- agno/knowledge/chunking/strategy.py +121 -0
- agno/knowledge/content.py +74 -0
- agno/knowledge/document/__init__.py +5 -0
- agno/{document → knowledge/document}/base.py +12 -2
- agno/knowledge/embedder/__init__.py +5 -0
- agno/{embedder → knowledge/embedder}/aws_bedrock.py +127 -1
- agno/{embedder → knowledge/embedder}/azure_openai.py +65 -1
- agno/{embedder → knowledge/embedder}/base.py +6 -0
- agno/{embedder → knowledge/embedder}/cohere.py +72 -1
- agno/{embedder → knowledge/embedder}/fastembed.py +17 -1
- agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
- agno/{embedder → knowledge/embedder}/google.py +74 -1
- agno/{embedder → knowledge/embedder}/huggingface.py +36 -2
- agno/{embedder → knowledge/embedder}/jina.py +48 -2
- agno/knowledge/embedder/langdb.py +22 -0
- agno/knowledge/embedder/mistral.py +139 -0
- agno/{embedder → knowledge/embedder}/nebius.py +1 -1
- agno/{embedder → knowledge/embedder}/ollama.py +54 -3
- agno/knowledge/embedder/openai.py +223 -0
- agno/{embedder → knowledge/embedder}/sentence_transformer.py +16 -1
- agno/{embedder → knowledge/embedder}/together.py +1 -1
- agno/{embedder → knowledge/embedder}/voyageai.py +49 -1
- agno/knowledge/knowledge.py +1515 -0
- agno/knowledge/reader/__init__.py +7 -0
- agno/{document → knowledge}/reader/arxiv_reader.py +32 -4
- agno/knowledge/reader/base.py +88 -0
- agno/{document → knowledge}/reader/csv_reader.py +68 -15
- agno/knowledge/reader/docx_reader.py +83 -0
- agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
- agno/knowledge/reader/gcs_reader.py +67 -0
- agno/{document → knowledge}/reader/json_reader.py +30 -9
- agno/{document → knowledge}/reader/markdown_reader.py +36 -9
- agno/{document → knowledge}/reader/pdf_reader.py +79 -21
- agno/knowledge/reader/reader_factory.py +275 -0
- agno/knowledge/reader/s3_reader.py +171 -0
- agno/{document → knowledge}/reader/text_reader.py +31 -10
- agno/knowledge/reader/url_reader.py +84 -0
- agno/knowledge/reader/web_search_reader.py +389 -0
- agno/{document → knowledge}/reader/website_reader.py +37 -10
- agno/knowledge/reader/wikipedia_reader.py +59 -0
- agno/knowledge/reader/youtube_reader.py +78 -0
- agno/knowledge/remote_content/remote_content.py +88 -0
- agno/{reranker → knowledge/reranker}/base.py +1 -1
- agno/{reranker → knowledge/reranker}/cohere.py +2 -2
- agno/{reranker → knowledge/reranker}/infinity.py +2 -2
- agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
- agno/knowledge/types.py +30 -0
- agno/knowledge/utils.py +169 -0
- agno/media.py +2 -2
- agno/memory/__init__.py +2 -10
- agno/memory/manager.py +1003 -148
- agno/models/aimlapi/__init__.py +2 -2
- agno/models/aimlapi/aimlapi.py +6 -6
- agno/models/anthropic/claude.py +129 -82
- agno/models/aws/bedrock.py +107 -175
- agno/models/aws/claude.py +64 -18
- agno/models/azure/ai_foundry.py +73 -23
- agno/models/base.py +347 -287
- agno/models/cerebras/cerebras.py +84 -27
- agno/models/cohere/chat.py +106 -98
- agno/models/dashscope/dashscope.py +14 -5
- agno/models/google/gemini.py +123 -53
- agno/models/groq/groq.py +97 -35
- agno/models/huggingface/huggingface.py +92 -27
- agno/models/ibm/watsonx.py +72 -13
- agno/models/litellm/chat.py +85 -13
- agno/models/message.py +38 -144
- agno/models/meta/llama.py +85 -49
- agno/models/metrics.py +120 -0
- agno/models/mistral/mistral.py +90 -21
- agno/models/ollama/__init__.py +0 -2
- agno/models/ollama/chat.py +84 -46
- agno/models/openai/chat.py +135 -27
- agno/models/openai/responses.py +233 -115
- agno/models/perplexity/perplexity.py +26 -2
- agno/models/portkey/portkey.py +0 -7
- agno/models/response.py +14 -8
- agno/models/utils.py +20 -0
- agno/models/vercel/__init__.py +2 -2
- agno/models/vercel/v0.py +1 -1
- agno/models/vllm/__init__.py +2 -2
- agno/models/vllm/vllm.py +3 -3
- agno/models/xai/xai.py +10 -10
- agno/os/__init__.py +3 -0
- agno/os/app.py +393 -0
- agno/os/auth.py +47 -0
- agno/os/config.py +103 -0
- agno/os/interfaces/agui/__init__.py +3 -0
- agno/os/interfaces/agui/agui.py +31 -0
- agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
- agno/{app → os/interfaces}/agui/utils.py +65 -28
- agno/os/interfaces/base.py +21 -0
- agno/os/interfaces/slack/__init__.py +3 -0
- agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
- agno/os/interfaces/slack/slack.py +33 -0
- agno/os/interfaces/whatsapp/__init__.py +3 -0
- agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
- agno/os/interfaces/whatsapp/whatsapp.py +30 -0
- agno/os/router.py +843 -0
- agno/os/routers/__init__.py +3 -0
- agno/os/routers/evals/__init__.py +3 -0
- agno/os/routers/evals/evals.py +204 -0
- agno/os/routers/evals/schemas.py +142 -0
- agno/os/routers/evals/utils.py +161 -0
- agno/os/routers/knowledge/__init__.py +3 -0
- agno/os/routers/knowledge/knowledge.py +413 -0
- agno/os/routers/knowledge/schemas.py +118 -0
- agno/os/routers/memory/__init__.py +3 -0
- agno/os/routers/memory/memory.py +179 -0
- agno/os/routers/memory/schemas.py +58 -0
- agno/os/routers/metrics/__init__.py +3 -0
- agno/os/routers/metrics/metrics.py +58 -0
- agno/os/routers/metrics/schemas.py +47 -0
- agno/os/routers/session/__init__.py +3 -0
- agno/os/routers/session/session.py +163 -0
- agno/os/schema.py +892 -0
- agno/{app/playground → os}/settings.py +8 -15
- agno/os/utils.py +270 -0
- agno/reasoning/azure_ai_foundry.py +4 -4
- agno/reasoning/deepseek.py +4 -4
- agno/reasoning/default.py +6 -11
- agno/reasoning/groq.py +4 -4
- agno/reasoning/helpers.py +4 -6
- agno/reasoning/ollama.py +4 -4
- agno/reasoning/openai.py +4 -4
- agno/run/{response.py → agent.py} +144 -72
- agno/run/base.py +44 -58
- agno/run/cancel.py +83 -0
- agno/run/team.py +133 -77
- agno/run/workflow.py +537 -12
- agno/session/__init__.py +10 -0
- agno/session/agent.py +244 -0
- agno/session/summary.py +225 -0
- agno/session/team.py +262 -0
- agno/{storage/session/v2 → session}/workflow.py +47 -24
- agno/team/__init__.py +15 -16
- agno/team/team.py +2967 -4243
- agno/tools/agentql.py +14 -5
- agno/tools/airflow.py +9 -4
- agno/tools/api.py +7 -3
- agno/tools/apify.py +2 -46
- agno/tools/arxiv.py +8 -3
- agno/tools/aws_lambda.py +7 -5
- agno/tools/aws_ses.py +7 -1
- agno/tools/baidusearch.py +4 -1
- agno/tools/bitbucket.py +4 -4
- agno/tools/brandfetch.py +14 -11
- agno/tools/bravesearch.py +4 -1
- agno/tools/brightdata.py +42 -22
- agno/tools/browserbase.py +13 -4
- agno/tools/calcom.py +12 -10
- agno/tools/calculator.py +10 -27
- agno/tools/cartesia.py +18 -13
- agno/tools/{clickup_tool.py → clickup.py} +12 -25
- agno/tools/confluence.py +71 -18
- agno/tools/crawl4ai.py +7 -1
- agno/tools/csv_toolkit.py +9 -8
- agno/tools/dalle.py +18 -11
- agno/tools/daytona.py +13 -16
- agno/tools/decorator.py +6 -3
- agno/tools/desi_vocal.py +16 -7
- agno/tools/discord.py +11 -8
- agno/tools/docker.py +30 -42
- agno/tools/duckdb.py +34 -53
- agno/tools/duckduckgo.py +8 -7
- agno/tools/e2b.py +62 -62
- agno/tools/eleven_labs.py +35 -28
- agno/tools/email.py +4 -1
- agno/tools/evm.py +7 -1
- agno/tools/exa.py +19 -14
- agno/tools/fal.py +29 -29
- agno/tools/file.py +9 -8
- agno/tools/financial_datasets.py +25 -44
- agno/tools/firecrawl.py +22 -22
- agno/tools/function.py +68 -17
- agno/tools/giphy.py +22 -10
- agno/tools/github.py +48 -126
- agno/tools/gmail.py +46 -62
- agno/tools/google_bigquery.py +7 -6
- agno/tools/google_maps.py +11 -26
- agno/tools/googlesearch.py +7 -2
- agno/tools/googlesheets.py +21 -17
- agno/tools/hackernews.py +9 -5
- agno/tools/jina.py +5 -4
- agno/tools/jira.py +18 -9
- agno/tools/knowledge.py +31 -32
- agno/tools/linear.py +18 -33
- agno/tools/linkup.py +5 -1
- agno/tools/local_file_system.py +8 -5
- agno/tools/lumalab.py +31 -19
- agno/tools/mem0.py +18 -12
- agno/tools/memori.py +14 -10
- agno/tools/mlx_transcribe.py +3 -2
- agno/tools/models/azure_openai.py +32 -14
- agno/tools/models/gemini.py +58 -31
- agno/tools/models/groq.py +29 -20
- agno/tools/models/nebius.py +27 -11
- agno/tools/models_labs.py +39 -15
- agno/tools/moviepy_video.py +7 -6
- agno/tools/neo4j.py +134 -0
- agno/tools/newspaper.py +7 -2
- agno/tools/newspaper4k.py +8 -3
- agno/tools/openai.py +57 -26
- agno/tools/openbb.py +12 -11
- agno/tools/opencv.py +62 -46
- agno/tools/openweather.py +14 -12
- agno/tools/pandas.py +11 -3
- agno/tools/postgres.py +4 -12
- agno/tools/pubmed.py +4 -1
- agno/tools/python.py +9 -22
- agno/tools/reasoning.py +35 -27
- agno/tools/reddit.py +11 -26
- agno/tools/replicate.py +54 -41
- agno/tools/resend.py +4 -1
- agno/tools/scrapegraph.py +15 -14
- agno/tools/searxng.py +10 -23
- agno/tools/serpapi.py +6 -3
- agno/tools/serper.py +13 -4
- agno/tools/shell.py +9 -2
- agno/tools/slack.py +12 -11
- agno/tools/sleep.py +3 -2
- agno/tools/spider.py +24 -4
- agno/tools/sql.py +7 -6
- agno/tools/tavily.py +6 -4
- agno/tools/telegram.py +12 -4
- agno/tools/todoist.py +11 -31
- agno/tools/toolkit.py +1 -1
- agno/tools/trafilatura.py +22 -6
- agno/tools/trello.py +9 -22
- agno/tools/twilio.py +10 -3
- agno/tools/user_control_flow.py +6 -1
- agno/tools/valyu.py +34 -5
- agno/tools/visualization.py +19 -28
- agno/tools/webbrowser.py +4 -3
- agno/tools/webex.py +11 -7
- agno/tools/website.py +15 -46
- agno/tools/webtools.py +12 -4
- agno/tools/whatsapp.py +5 -9
- agno/tools/wikipedia.py +20 -13
- agno/tools/x.py +14 -13
- agno/tools/yfinance.py +13 -40
- agno/tools/youtube.py +26 -20
- agno/tools/zendesk.py +7 -2
- agno/tools/zep.py +10 -7
- agno/tools/zoom.py +10 -9
- agno/utils/common.py +1 -19
- agno/utils/events.py +95 -118
- agno/utils/knowledge.py +29 -0
- agno/utils/location.py +2 -2
- agno/utils/log.py +2 -2
- agno/utils/mcp.py +11 -5
- agno/utils/media.py +39 -0
- agno/utils/message.py +12 -1
- agno/utils/models/claude.py +6 -4
- agno/utils/models/mistral.py +8 -7
- agno/utils/models/schema_utils.py +3 -3
- agno/utils/pprint.py +33 -32
- agno/utils/print_response/agent.py +779 -0
- agno/utils/print_response/team.py +1565 -0
- agno/utils/print_response/workflow.py +1451 -0
- agno/utils/prompts.py +14 -14
- agno/utils/reasoning.py +87 -0
- agno/utils/response.py +42 -42
- agno/utils/string.py +8 -22
- agno/utils/team.py +50 -0
- agno/utils/timer.py +2 -2
- agno/vectordb/base.py +33 -21
- agno/vectordb/cassandra/cassandra.py +287 -23
- agno/vectordb/chroma/chromadb.py +482 -59
- agno/vectordb/clickhouse/clickhousedb.py +270 -63
- agno/vectordb/couchbase/couchbase.py +309 -29
- agno/vectordb/lancedb/lance_db.py +360 -21
- agno/vectordb/langchaindb/__init__.py +5 -0
- agno/vectordb/langchaindb/langchaindb.py +145 -0
- agno/vectordb/lightrag/__init__.py +5 -0
- agno/vectordb/lightrag/lightrag.py +374 -0
- agno/vectordb/llamaindex/llamaindexdb.py +127 -0
- agno/vectordb/milvus/milvus.py +242 -32
- agno/vectordb/mongodb/mongodb.py +200 -24
- agno/vectordb/pgvector/pgvector.py +319 -37
- agno/vectordb/pineconedb/pineconedb.py +221 -27
- agno/vectordb/qdrant/qdrant.py +356 -14
- agno/vectordb/singlestore/singlestore.py +286 -29
- agno/vectordb/surrealdb/surrealdb.py +187 -7
- agno/vectordb/upstashdb/upstashdb.py +342 -26
- agno/vectordb/weaviate/weaviate.py +227 -165
- agno/workflow/__init__.py +17 -13
- agno/workflow/{v2/condition.py → condition.py} +135 -32
- agno/workflow/{v2/loop.py → loop.py} +115 -28
- agno/workflow/{v2/parallel.py → parallel.py} +138 -108
- agno/workflow/{v2/router.py → router.py} +133 -32
- agno/workflow/{v2/step.py → step.py} +200 -42
- agno/workflow/{v2/steps.py → steps.py} +147 -66
- agno/workflow/types.py +482 -0
- agno/workflow/workflow.py +2394 -696
- agno-2.0.0a1.dist-info/METADATA +355 -0
- agno-2.0.0a1.dist-info/RECORD +514 -0
- agno/agent/metrics.py +0 -107
- agno/api/app.py +0 -35
- agno/api/playground.py +0 -92
- agno/api/schemas/app.py +0 -12
- agno/api/schemas/playground.py +0 -22
- agno/api/schemas/user.py +0 -35
- agno/api/schemas/workspace.py +0 -46
- agno/api/user.py +0 -160
- agno/api/workflows.py +0 -33
- agno/api/workspace.py +0 -175
- agno/app/agui/__init__.py +0 -3
- agno/app/agui/app.py +0 -17
- agno/app/agui/sync_router.py +0 -120
- agno/app/base.py +0 -186
- agno/app/discord/__init__.py +0 -3
- agno/app/fastapi/__init__.py +0 -3
- agno/app/fastapi/app.py +0 -107
- agno/app/fastapi/async_router.py +0 -457
- agno/app/fastapi/sync_router.py +0 -448
- agno/app/playground/app.py +0 -228
- agno/app/playground/async_router.py +0 -1050
- agno/app/playground/deploy.py +0 -249
- agno/app/playground/operator.py +0 -183
- agno/app/playground/schemas.py +0 -220
- agno/app/playground/serve.py +0 -55
- agno/app/playground/sync_router.py +0 -1042
- agno/app/playground/utils.py +0 -46
- agno/app/settings.py +0 -15
- agno/app/slack/__init__.py +0 -3
- agno/app/slack/app.py +0 -19
- agno/app/slack/sync_router.py +0 -92
- agno/app/utils.py +0 -54
- agno/app/whatsapp/__init__.py +0 -3
- agno/app/whatsapp/app.py +0 -15
- agno/app/whatsapp/sync_router.py +0 -197
- agno/cli/auth_server.py +0 -249
- agno/cli/config.py +0 -274
- agno/cli/console.py +0 -88
- agno/cli/credentials.py +0 -23
- agno/cli/entrypoint.py +0 -571
- agno/cli/operator.py +0 -357
- agno/cli/settings.py +0 -96
- agno/cli/ws/ws_cli.py +0 -817
- agno/constants.py +0 -13
- agno/document/__init__.py +0 -5
- agno/document/chunking/semantic.py +0 -45
- agno/document/chunking/strategy.py +0 -31
- agno/document/reader/__init__.py +0 -5
- agno/document/reader/base.py +0 -47
- agno/document/reader/docx_reader.py +0 -60
- agno/document/reader/gcs/pdf_reader.py +0 -44
- agno/document/reader/s3/pdf_reader.py +0 -59
- agno/document/reader/s3/text_reader.py +0 -63
- agno/document/reader/url_reader.py +0 -59
- agno/document/reader/youtube_reader.py +0 -58
- agno/embedder/__init__.py +0 -5
- agno/embedder/langdb.py +0 -80
- agno/embedder/mistral.py +0 -82
- agno/embedder/openai.py +0 -78
- agno/file/__init__.py +0 -5
- agno/file/file.py +0 -16
- agno/file/local/csv.py +0 -32
- agno/file/local/txt.py +0 -19
- agno/infra/app.py +0 -240
- agno/infra/base.py +0 -144
- agno/infra/context.py +0 -20
- agno/infra/db_app.py +0 -52
- agno/infra/resource.py +0 -205
- agno/infra/resources.py +0 -55
- agno/knowledge/agent.py +0 -698
- agno/knowledge/arxiv.py +0 -33
- agno/knowledge/combined.py +0 -36
- agno/knowledge/csv.py +0 -144
- agno/knowledge/csv_url.py +0 -124
- agno/knowledge/document.py +0 -223
- agno/knowledge/docx.py +0 -137
- agno/knowledge/firecrawl.py +0 -34
- agno/knowledge/gcs/__init__.py +0 -0
- agno/knowledge/gcs/base.py +0 -39
- agno/knowledge/gcs/pdf.py +0 -125
- agno/knowledge/json.py +0 -137
- agno/knowledge/langchain.py +0 -71
- agno/knowledge/light_rag.py +0 -273
- agno/knowledge/llamaindex.py +0 -66
- agno/knowledge/markdown.py +0 -154
- agno/knowledge/pdf.py +0 -164
- agno/knowledge/pdf_bytes.py +0 -42
- agno/knowledge/pdf_url.py +0 -148
- agno/knowledge/s3/__init__.py +0 -0
- agno/knowledge/s3/base.py +0 -64
- agno/knowledge/s3/pdf.py +0 -33
- agno/knowledge/s3/text.py +0 -34
- agno/knowledge/text.py +0 -141
- agno/knowledge/url.py +0 -46
- agno/knowledge/website.py +0 -179
- agno/knowledge/wikipedia.py +0 -32
- agno/knowledge/youtube.py +0 -35
- agno/memory/agent.py +0 -423
- agno/memory/classifier.py +0 -104
- agno/memory/db/__init__.py +0 -5
- agno/memory/db/base.py +0 -42
- agno/memory/db/mongodb.py +0 -189
- agno/memory/db/postgres.py +0 -203
- agno/memory/db/sqlite.py +0 -193
- agno/memory/memory.py +0 -22
- agno/memory/row.py +0 -36
- agno/memory/summarizer.py +0 -201
- agno/memory/summary.py +0 -19
- agno/memory/team.py +0 -415
- agno/memory/v2/__init__.py +0 -2
- agno/memory/v2/db/__init__.py +0 -1
- agno/memory/v2/db/base.py +0 -42
- agno/memory/v2/db/firestore.py +0 -339
- agno/memory/v2/db/mongodb.py +0 -196
- agno/memory/v2/db/postgres.py +0 -214
- agno/memory/v2/db/redis.py +0 -187
- agno/memory/v2/db/schema.py +0 -54
- agno/memory/v2/db/sqlite.py +0 -209
- agno/memory/v2/manager.py +0 -437
- agno/memory/v2/memory.py +0 -1097
- agno/memory/v2/schema.py +0 -55
- agno/memory/v2/summarizer.py +0 -215
- agno/memory/workflow.py +0 -38
- agno/models/ollama/tools.py +0 -430
- agno/models/qwen/__init__.py +0 -5
- agno/playground/__init__.py +0 -10
- agno/playground/deploy.py +0 -3
- agno/playground/playground.py +0 -3
- agno/playground/serve.py +0 -3
- agno/playground/settings.py +0 -3
- agno/reranker/__init__.py +0 -0
- agno/run/v2/__init__.py +0 -0
- agno/run/v2/workflow.py +0 -567
- agno/storage/__init__.py +0 -0
- agno/storage/agent/__init__.py +0 -0
- agno/storage/agent/dynamodb.py +0 -1
- agno/storage/agent/json.py +0 -1
- agno/storage/agent/mongodb.py +0 -1
- agno/storage/agent/postgres.py +0 -1
- agno/storage/agent/singlestore.py +0 -1
- agno/storage/agent/sqlite.py +0 -1
- agno/storage/agent/yaml.py +0 -1
- agno/storage/base.py +0 -60
- agno/storage/dynamodb.py +0 -673
- agno/storage/firestore.py +0 -297
- agno/storage/gcs_json.py +0 -261
- agno/storage/in_memory.py +0 -234
- agno/storage/json.py +0 -237
- agno/storage/mongodb.py +0 -328
- agno/storage/mysql.py +0 -685
- agno/storage/postgres.py +0 -682
- agno/storage/redis.py +0 -336
- agno/storage/session/__init__.py +0 -16
- agno/storage/session/agent.py +0 -64
- agno/storage/session/team.py +0 -63
- agno/storage/session/v2/__init__.py +0 -5
- agno/storage/session/workflow.py +0 -61
- agno/storage/singlestore.py +0 -606
- agno/storage/sqlite.py +0 -646
- agno/storage/workflow/__init__.py +0 -0
- agno/storage/workflow/mongodb.py +0 -1
- agno/storage/workflow/postgres.py +0 -1
- agno/storage/workflow/sqlite.py +0 -1
- agno/storage/yaml.py +0 -241
- agno/tools/thinking.py +0 -73
- agno/utils/defaults.py +0 -57
- agno/utils/filesystem.py +0 -39
- agno/utils/git.py +0 -52
- agno/utils/json_io.py +0 -30
- agno/utils/load_env.py +0 -19
- agno/utils/py_io.py +0 -19
- agno/utils/pyproject.py +0 -18
- agno/utils/resource_filter.py +0 -31
- agno/workflow/v2/__init__.py +0 -21
- agno/workflow/v2/types.py +0 -357
- agno/workflow/v2/workflow.py +0 -3312
- agno/workspace/__init__.py +0 -0
- agno/workspace/config.py +0 -325
- agno/workspace/enums.py +0 -6
- agno/workspace/helpers.py +0 -52
- agno/workspace/operator.py +0 -757
- agno/workspace/settings.py +0 -158
- agno-1.8.0.dist-info/METADATA +0 -979
- agno-1.8.0.dist-info/RECORD +0 -565
- agno-1.8.0.dist-info/entry_points.txt +0 -3
- /agno/{app → db/migrations}/__init__.py +0 -0
- /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
- /agno/{cli → integrations}/__init__.py +0 -0
- /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
- /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
- /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
- /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
- /agno/{app → os/interfaces}/slack/security.py +0 -0
- /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
- /agno/{file/local → utils/print_response}/__init__.py +0 -0
- /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
- {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/WHEEL +0 -0
- {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/licenses/LICENSE +0 -0
- {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/top_level.txt +0 -0
agno/utils/prompts.py
CHANGED
|
@@ -6,28 +6,28 @@ from pydantic import BaseModel
|
|
|
6
6
|
from agno.utils.log import log_warning
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
def get_json_output_prompt(
|
|
9
|
+
def get_json_output_prompt(output_schema: Union[str, list, BaseModel]) -> str:
|
|
10
10
|
"""Return the JSON output prompt for the Agent.
|
|
11
11
|
|
|
12
|
-
This is added to the system prompt when the
|
|
12
|
+
This is added to the system prompt when the output_schema is set and structured_outputs is False.
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
15
|
json_output_prompt = "Provide your output as a JSON containing the following fields:"
|
|
16
|
-
if
|
|
17
|
-
if isinstance(
|
|
16
|
+
if output_schema is not None:
|
|
17
|
+
if isinstance(output_schema, str):
|
|
18
18
|
json_output_prompt += "\n<json_fields>"
|
|
19
|
-
json_output_prompt += f"\n{
|
|
19
|
+
json_output_prompt += f"\n{output_schema}"
|
|
20
20
|
json_output_prompt += "\n</json_fields>"
|
|
21
|
-
elif isinstance(
|
|
21
|
+
elif isinstance(output_schema, list):
|
|
22
22
|
json_output_prompt += "\n<json_fields>"
|
|
23
|
-
json_output_prompt += f"\n{json.dumps(
|
|
23
|
+
json_output_prompt += f"\n{json.dumps(output_schema)}"
|
|
24
24
|
json_output_prompt += "\n</json_fields>"
|
|
25
25
|
elif (
|
|
26
|
-
issubclass(type(
|
|
27
|
-
or issubclass(
|
|
28
|
-
or isinstance(
|
|
26
|
+
issubclass(type(output_schema), BaseModel)
|
|
27
|
+
or issubclass(output_schema, BaseModel) # type: ignore
|
|
28
|
+
or isinstance(output_schema, BaseModel)
|
|
29
29
|
): # type: ignore
|
|
30
|
-
json_schema =
|
|
30
|
+
json_schema = output_schema.model_json_schema()
|
|
31
31
|
if json_schema is not None:
|
|
32
32
|
response_model_properties = {}
|
|
33
33
|
json_schema_properties = json_schema.get("properties")
|
|
@@ -85,7 +85,7 @@ def get_json_output_prompt(response_model: Union[str, list, BaseModel]) -> str:
|
|
|
85
85
|
json_output_prompt += f"\n{json.dumps(response_model_properties, indent=2)}"
|
|
86
86
|
json_output_prompt += "\n</json_field_properties>"
|
|
87
87
|
else:
|
|
88
|
-
log_warning(f"Could not build json schema for {
|
|
88
|
+
log_warning(f"Could not build json schema for {output_schema}")
|
|
89
89
|
else:
|
|
90
90
|
json_output_prompt += "Provide the output as JSON."
|
|
91
91
|
|
|
@@ -95,13 +95,13 @@ def get_json_output_prompt(response_model: Union[str, list, BaseModel]) -> str:
|
|
|
95
95
|
return json_output_prompt
|
|
96
96
|
|
|
97
97
|
|
|
98
|
-
def get_response_model_format_prompt(
|
|
98
|
+
def get_response_model_format_prompt(output_schema: Type[BaseModel]) -> str:
|
|
99
99
|
"""Return the format prompt for the response model."""
|
|
100
100
|
|
|
101
101
|
message = "Make sure your response is a valid string (NOT JSON) that mentions the following topics:"
|
|
102
102
|
|
|
103
103
|
# Extract field names and descriptions
|
|
104
|
-
for field_name, field_info in
|
|
104
|
+
for field_name, field_info in output_schema.model_fields.items():
|
|
105
105
|
description = field_info.description or ""
|
|
106
106
|
if description:
|
|
107
107
|
message += f"\n- {field_name}: {description}"
|
agno/utils/reasoning.py
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, List, Union
|
|
2
|
+
|
|
3
|
+
from agno.models.message import Message
|
|
4
|
+
from agno.models.metrics import Metrics
|
|
5
|
+
from agno.reasoning.step import ReasoningStep
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from agno.run.agent import RunOutput
|
|
9
|
+
from agno.team.team import TeamRunOutput
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def append_to_reasoning_content(run_response: Union["RunOutput", "TeamRunOutput"], content: str) -> None:
|
|
13
|
+
"""Helper to append content to the reasoning_content field."""
|
|
14
|
+
if not hasattr(run_response, "reasoning_content") or not run_response.reasoning_content: # type: ignore
|
|
15
|
+
run_response.reasoning_content = content # type: ignore
|
|
16
|
+
else:
|
|
17
|
+
run_response.reasoning_content += content # type: ignore
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def add_reasoning_step_to_metadata(
|
|
21
|
+
run_response: Union["RunOutput", "TeamRunOutput"], reasoning_step: ReasoningStep
|
|
22
|
+
) -> None:
|
|
23
|
+
if run_response.reasoning_steps is None:
|
|
24
|
+
run_response.reasoning_steps = []
|
|
25
|
+
|
|
26
|
+
run_response.reasoning_steps.append(reasoning_step)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def add_reasoning_metrics_to_metadata(
|
|
30
|
+
run_response: Union["RunOutput", "TeamRunOutput"], reasoning_time_taken: float
|
|
31
|
+
) -> None:
|
|
32
|
+
try:
|
|
33
|
+
# Initialize reasoning_messages if it doesn't exist
|
|
34
|
+
if run_response.reasoning_messages is None:
|
|
35
|
+
run_response.reasoning_messages = []
|
|
36
|
+
|
|
37
|
+
metrics_message = Message(
|
|
38
|
+
role="assistant",
|
|
39
|
+
content=run_response.reasoning_content,
|
|
40
|
+
metrics=Metrics(duration=reasoning_time_taken),
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# Add the metrics message to the reasoning_messages
|
|
44
|
+
run_response.reasoning_messages.append(metrics_message)
|
|
45
|
+
|
|
46
|
+
except Exception as e:
|
|
47
|
+
# Log the error but don't crash
|
|
48
|
+
from agno.utils.log import log_error
|
|
49
|
+
|
|
50
|
+
log_error(f"Failed to add reasoning metrics to metadata: {str(e)}")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def update_run_output_with_reasoning(
|
|
54
|
+
run_response: Union["RunOutput", "TeamRunOutput"],
|
|
55
|
+
reasoning_steps: List[ReasoningStep],
|
|
56
|
+
reasoning_agent_messages: List[Message],
|
|
57
|
+
) -> None:
|
|
58
|
+
# Update reasoning_steps
|
|
59
|
+
if run_response.reasoning_steps is None:
|
|
60
|
+
run_response.reasoning_steps = reasoning_steps
|
|
61
|
+
else:
|
|
62
|
+
run_response.reasoning_steps.extend(reasoning_steps)
|
|
63
|
+
|
|
64
|
+
# Update reasoning_messages
|
|
65
|
+
if run_response.reasoning_messages is None:
|
|
66
|
+
run_response.reasoning_messages = reasoning_agent_messages
|
|
67
|
+
else:
|
|
68
|
+
run_response.reasoning_messages.extend(reasoning_agent_messages)
|
|
69
|
+
|
|
70
|
+
# Create and store reasoning_content
|
|
71
|
+
reasoning_content = ""
|
|
72
|
+
for step in reasoning_steps:
|
|
73
|
+
if step.title:
|
|
74
|
+
reasoning_content += f"## {step.title}\n"
|
|
75
|
+
if step.reasoning:
|
|
76
|
+
reasoning_content += f"{step.reasoning}\n"
|
|
77
|
+
if step.action:
|
|
78
|
+
reasoning_content += f"Action: {step.action}\n"
|
|
79
|
+
if step.result:
|
|
80
|
+
reasoning_content += f"Result: {step.result}\n"
|
|
81
|
+
reasoning_content += "\n"
|
|
82
|
+
|
|
83
|
+
# Add to existing reasoning_content or set it
|
|
84
|
+
if not run_response.reasoning_content:
|
|
85
|
+
run_response.reasoning_content = reasoning_content
|
|
86
|
+
else:
|
|
87
|
+
run_response.reasoning_content += reasoning_content
|
agno/utils/response.py
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
from typing import AsyncIterator, Iterator, List, Set, Union
|
|
2
2
|
|
|
3
3
|
from agno.exceptions import RunCancelledException
|
|
4
|
-
from agno.models.message import Message
|
|
5
4
|
from agno.models.response import ToolExecution
|
|
6
5
|
from agno.reasoning.step import ReasoningStep
|
|
7
|
-
from agno.run.
|
|
8
|
-
from agno.run.
|
|
9
|
-
from agno.run.team import TeamRunResponse, TeamRunResponseEvent
|
|
6
|
+
from agno.run.agent import RunOutput, RunOutputEvent, RunPausedEvent
|
|
7
|
+
from agno.run.team import TeamRunOutput, TeamRunOutputEvent
|
|
10
8
|
|
|
11
9
|
|
|
12
10
|
def create_panel(content, title, border_style="blue"):
|
|
@@ -18,6 +16,29 @@ def create_panel(content, title, border_style="blue"):
|
|
|
18
16
|
)
|
|
19
17
|
|
|
20
18
|
|
|
19
|
+
def build_reasoning_step_panel(
|
|
20
|
+
step_idx: int, step: ReasoningStep, show_full_reasoning: bool = False, color: str = "green"
|
|
21
|
+
):
|
|
22
|
+
from rich.text import Text
|
|
23
|
+
|
|
24
|
+
# Build step content
|
|
25
|
+
step_content = Text.assemble()
|
|
26
|
+
if step.title is not None:
|
|
27
|
+
step_content.append(f"{step.title}\n", "bold")
|
|
28
|
+
if step.action is not None:
|
|
29
|
+
step_content.append(Text.from_markup(f"[bold]Action:[/bold] {step.action}\n", style="dim"))
|
|
30
|
+
if step.result is not None:
|
|
31
|
+
step_content.append(Text.from_markup(step.result, style="dim"))
|
|
32
|
+
|
|
33
|
+
if show_full_reasoning:
|
|
34
|
+
# Add detailed reasoning information if available
|
|
35
|
+
if step.reasoning is not None:
|
|
36
|
+
step_content.append(Text.from_markup(f"\n[bold]Reasoning:[/bold] {step.reasoning}", style="dim"))
|
|
37
|
+
if step.confidence is not None:
|
|
38
|
+
step_content.append(Text.from_markup(f"\n[bold]Confidence:[/bold] {step.confidence}", style="dim"))
|
|
39
|
+
return create_panel(content=step_content, title=f"Reasoning step {step_idx}", border_style=color)
|
|
40
|
+
|
|
41
|
+
|
|
21
42
|
def escape_markdown_tags(content: str, tags: Set[str]) -> str:
|
|
22
43
|
"""Escape special tags in markdown content."""
|
|
23
44
|
escaped_content = content
|
|
@@ -29,32 +50,11 @@ def escape_markdown_tags(content: str, tags: Set[str]) -> str:
|
|
|
29
50
|
return escaped_content
|
|
30
51
|
|
|
31
52
|
|
|
32
|
-
def check_if_run_cancelled(
|
|
33
|
-
if
|
|
53
|
+
def check_if_run_cancelled(run_output: Union[RunOutput, RunOutputEvent, TeamRunOutput, TeamRunOutputEvent]):
|
|
54
|
+
if run_output.is_cancelled:
|
|
34
55
|
raise RunCancelledException()
|
|
35
56
|
|
|
36
57
|
|
|
37
|
-
def update_run_response_with_reasoning(
|
|
38
|
-
run_response: Union[RunResponse, TeamRunResponse],
|
|
39
|
-
reasoning_steps: List[ReasoningStep],
|
|
40
|
-
reasoning_agent_messages: List[Message],
|
|
41
|
-
) -> None:
|
|
42
|
-
if run_response.extra_data is None:
|
|
43
|
-
run_response.extra_data = RunResponseExtraData()
|
|
44
|
-
|
|
45
|
-
# Update reasoning_steps
|
|
46
|
-
if run_response.extra_data.reasoning_steps is None:
|
|
47
|
-
run_response.extra_data.reasoning_steps = reasoning_steps
|
|
48
|
-
else:
|
|
49
|
-
run_response.extra_data.reasoning_steps.extend(reasoning_steps)
|
|
50
|
-
|
|
51
|
-
# Update reasoning_messages
|
|
52
|
-
if run_response.extra_data.reasoning_messages is None:
|
|
53
|
-
run_response.extra_data.reasoning_messages = reasoning_agent_messages
|
|
54
|
-
else:
|
|
55
|
-
run_response.extra_data.reasoning_messages.extend(reasoning_agent_messages)
|
|
56
|
-
|
|
57
|
-
|
|
58
58
|
def format_tool_calls(tool_calls: List[ToolExecution]) -> List[str]:
|
|
59
59
|
"""Format tool calls for display in a readable format.
|
|
60
60
|
|
|
@@ -70,39 +70,39 @@ def format_tool_calls(tool_calls: List[ToolExecution]) -> List[str]:
|
|
|
70
70
|
if tool_call.tool_name is not None:
|
|
71
71
|
tool_name = tool_call.tool_name
|
|
72
72
|
args_str = ""
|
|
73
|
-
if tool_call.tool_args is not None:
|
|
73
|
+
if tool_call.tool_args is not None and tool_call.tool_args: # Check if args exist and are non-empty
|
|
74
74
|
args_str = ", ".join(f"{k}={v}" for k, v in tool_call.tool_args.items())
|
|
75
75
|
formatted_tool_calls.append(f"{tool_name}({args_str})")
|
|
76
76
|
|
|
77
77
|
return formatted_tool_calls
|
|
78
78
|
|
|
79
79
|
|
|
80
|
-
def
|
|
80
|
+
def create_paused_run_output_panel(run_output: Union[RunPausedEvent, RunOutput]):
|
|
81
81
|
from rich.text import Text
|
|
82
82
|
|
|
83
83
|
tool_calls_content = Text("Run is paused. ")
|
|
84
|
-
if
|
|
85
|
-
if any(tc.requires_confirmation for tc in
|
|
84
|
+
if run_output.tools is not None:
|
|
85
|
+
if any(tc.requires_confirmation for tc in run_output.tools):
|
|
86
86
|
tool_calls_content.append("The following tool calls require confirmation:\n")
|
|
87
|
-
for tool_call in
|
|
87
|
+
for tool_call in run_output.tools:
|
|
88
88
|
if tool_call.requires_confirmation:
|
|
89
89
|
args_str = ""
|
|
90
90
|
for arg, value in tool_call.tool_args.items() if tool_call.tool_args else {}:
|
|
91
91
|
args_str += f"{arg}={value}, "
|
|
92
92
|
args_str = args_str.rstrip(", ")
|
|
93
93
|
tool_calls_content.append(f"• {tool_call.tool_name}({args_str})\n")
|
|
94
|
-
if any(tc.requires_user_input for tc in
|
|
94
|
+
if any(tc.requires_user_input for tc in run_output.tools):
|
|
95
95
|
tool_calls_content.append("The following tool calls require user input:\n")
|
|
96
|
-
for tool_call in
|
|
96
|
+
for tool_call in run_output.tools:
|
|
97
97
|
if tool_call.requires_user_input:
|
|
98
98
|
args_str = ""
|
|
99
99
|
for arg, value in tool_call.tool_args.items() if tool_call.tool_args else {}:
|
|
100
100
|
args_str += f"{arg}={value}, "
|
|
101
101
|
args_str = args_str.rstrip(", ")
|
|
102
102
|
tool_calls_content.append(f"• {tool_call.tool_name}({args_str})\n")
|
|
103
|
-
if any(tc.external_execution_required for tc in
|
|
103
|
+
if any(tc.external_execution_required for tc in run_output.tools):
|
|
104
104
|
tool_calls_content.append("The following tool calls require external execution:\n")
|
|
105
|
-
for tool_call in
|
|
105
|
+
for tool_call in run_output.tools:
|
|
106
106
|
if tool_call.external_execution_required:
|
|
107
107
|
args_str = ""
|
|
108
108
|
for arg, value in tool_call.tool_args.items() if tool_call.tool_args else {}:
|
|
@@ -119,9 +119,9 @@ def create_paused_run_response_panel(run_response: Union[RunResponsePausedEvent,
|
|
|
119
119
|
return response_panel
|
|
120
120
|
|
|
121
121
|
|
|
122
|
-
def get_paused_content(
|
|
122
|
+
def get_paused_content(run_output: RunOutput) -> str:
|
|
123
123
|
paused_content = ""
|
|
124
|
-
for tool in
|
|
124
|
+
for tool in run_output.tools or []:
|
|
125
125
|
# Initialize flags for each tool
|
|
126
126
|
confirmation_required = False
|
|
127
127
|
user_input_required = False
|
|
@@ -152,12 +152,12 @@ def get_paused_content(run_response: RunResponse) -> str:
|
|
|
152
152
|
|
|
153
153
|
|
|
154
154
|
def generator_wrapper(
|
|
155
|
-
event: Union[
|
|
156
|
-
) -> Iterator[Union[
|
|
155
|
+
event: Union[RunOutputEvent, TeamRunOutputEvent],
|
|
156
|
+
) -> Iterator[Union[RunOutputEvent, TeamRunOutputEvent]]:
|
|
157
157
|
yield event
|
|
158
158
|
|
|
159
159
|
|
|
160
160
|
async def async_generator_wrapper(
|
|
161
|
-
event: Union[
|
|
162
|
-
) -> AsyncIterator[Union[
|
|
161
|
+
event: Union[RunOutputEvent, TeamRunOutputEvent],
|
|
162
|
+
) -> AsyncIterator[Union[RunOutputEvent, TeamRunOutputEvent]]:
|
|
163
163
|
yield event
|
agno/utils/string.py
CHANGED
|
@@ -27,20 +27,6 @@ def is_valid_uuid(uuid_str: str) -> bool:
|
|
|
27
27
|
return False
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
def safe_content_hash(content: str) -> str:
|
|
31
|
-
"""
|
|
32
|
-
Return an MD5 hash of the input string, replacing null bytes and invalid surrogates for safe hashing.
|
|
33
|
-
"""
|
|
34
|
-
cleaned_content = content.replace("\x00", "\ufffd")
|
|
35
|
-
try:
|
|
36
|
-
content_hash = hashlib.md5(cleaned_content.encode("utf-8")).hexdigest()
|
|
37
|
-
except UnicodeEncodeError:
|
|
38
|
-
cleaned_content = "".join("\ufffd" if "\ud800" <= c <= "\udfff" else c for c in cleaned_content)
|
|
39
|
-
content_hash = hashlib.md5(cleaned_content.encode("utf-8")).hexdigest()
|
|
40
|
-
|
|
41
|
-
return content_hash
|
|
42
|
-
|
|
43
|
-
|
|
44
30
|
def url_safe_string(input_string):
|
|
45
31
|
# Replace spaces with dashes
|
|
46
32
|
safe_string = input_string.replace(" ", "-")
|
|
@@ -130,13 +116,13 @@ def _clean_json_content(content: str) -> str:
|
|
|
130
116
|
return content
|
|
131
117
|
|
|
132
118
|
|
|
133
|
-
def _parse_individual_json(content: str,
|
|
119
|
+
def _parse_individual_json(content: str, output_schema: Type[BaseModel]) -> Optional[BaseModel]:
|
|
134
120
|
"""Parse individual JSON objects from content and merge them based on response model fields."""
|
|
135
121
|
candidate_jsons = _extract_json_objects(content)
|
|
136
122
|
merged_data: dict = {}
|
|
137
123
|
|
|
138
124
|
# Get the expected fields from the response model
|
|
139
|
-
model_fields =
|
|
125
|
+
model_fields = output_schema.model_fields if hasattr(output_schema, "model_fields") else {}
|
|
140
126
|
|
|
141
127
|
for candidate in candidate_jsons:
|
|
142
128
|
try:
|
|
@@ -161,13 +147,13 @@ def _parse_individual_json(content: str, response_model: Type[BaseModel]) -> Opt
|
|
|
161
147
|
return None
|
|
162
148
|
|
|
163
149
|
try:
|
|
164
|
-
return
|
|
150
|
+
return output_schema.model_validate(merged_data)
|
|
165
151
|
except ValidationError as e:
|
|
166
152
|
logger.warning("Validation failed on merged data: %s", e)
|
|
167
153
|
return None
|
|
168
154
|
|
|
169
155
|
|
|
170
|
-
def parse_response_model_str(content: str,
|
|
156
|
+
def parse_response_model_str(content: str, output_schema: Type[BaseModel]) -> Optional[BaseModel]:
|
|
171
157
|
structured_output = None
|
|
172
158
|
|
|
173
159
|
# Clean content first to simplify all parsing attempts
|
|
@@ -175,12 +161,12 @@ def parse_response_model_str(content: str, response_model: Type[BaseModel]) -> O
|
|
|
175
161
|
|
|
176
162
|
try:
|
|
177
163
|
# First attempt: direct JSON validation on cleaned content
|
|
178
|
-
structured_output =
|
|
164
|
+
structured_output = output_schema.model_validate_json(cleaned_content)
|
|
179
165
|
except (ValidationError, json.JSONDecodeError):
|
|
180
166
|
try:
|
|
181
167
|
# Second attempt: Parse as Python dict
|
|
182
168
|
data = json.loads(cleaned_content)
|
|
183
|
-
structured_output =
|
|
169
|
+
structured_output = output_schema.model_validate(data)
|
|
184
170
|
except (ValidationError, json.JSONDecodeError) as e:
|
|
185
171
|
logger.warning(f"Failed to parse cleaned JSON: {e}")
|
|
186
172
|
|
|
@@ -191,13 +177,13 @@ def parse_response_model_str(content: str, response_model: Type[BaseModel]) -> O
|
|
|
191
177
|
# Single JSON object - try to parse it directly
|
|
192
178
|
try:
|
|
193
179
|
data = json.loads(candidate_jsons[0])
|
|
194
|
-
structured_output =
|
|
180
|
+
structured_output = output_schema.model_validate(data)
|
|
195
181
|
except (ValidationError, json.JSONDecodeError):
|
|
196
182
|
pass
|
|
197
183
|
|
|
198
184
|
if structured_output is None:
|
|
199
185
|
# Final attempt: Handle concatenated JSON objects with field merging
|
|
200
|
-
structured_output = _parse_individual_json(cleaned_content,
|
|
186
|
+
structured_output = _parse_individual_json(cleaned_content, output_schema)
|
|
201
187
|
if structured_output is None:
|
|
202
188
|
logger.warning("All parsing attempts failed.")
|
|
203
189
|
|
agno/utils/team.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Optional, Union
|
|
2
|
+
|
|
3
|
+
from agno.agent import Agent
|
|
4
|
+
from agno.utils.string import is_valid_uuid, url_safe_string
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from agno.team.team import Team
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def format_member_agent_task(
|
|
11
|
+
task_description: str,
|
|
12
|
+
expected_output: Optional[str] = None,
|
|
13
|
+
team_member_interactions_str: Optional[str] = None,
|
|
14
|
+
) -> str:
|
|
15
|
+
member_agent_task = "You are a member of a team of agents. Your goal is to complete the following task:"
|
|
16
|
+
member_agent_task += f"\n\n<task>\n{task_description}\n</task>"
|
|
17
|
+
|
|
18
|
+
if expected_output is not None:
|
|
19
|
+
member_agent_task += f"\n\n<expected_output>\n{expected_output}\n</expected_output>"
|
|
20
|
+
|
|
21
|
+
if team_member_interactions_str:
|
|
22
|
+
member_agent_task += f"\n\n{team_member_interactions_str}"
|
|
23
|
+
|
|
24
|
+
return member_agent_task
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_member_id(member: Union[Agent, "Team"]) -> str:
|
|
28
|
+
"""
|
|
29
|
+
Get the ID of a member
|
|
30
|
+
|
|
31
|
+
If the member has an agent_id or team_id, use that if it is not a valid UUID.
|
|
32
|
+
Then if the member has a name, convert that to a URL safe string.
|
|
33
|
+
Then if the member has the default UUID ID, use that.
|
|
34
|
+
Otherwise, return None.
|
|
35
|
+
"""
|
|
36
|
+
from agno.team.team import Team
|
|
37
|
+
|
|
38
|
+
if isinstance(member, Agent) and member.id is not None and (not is_valid_uuid(member.id)):
|
|
39
|
+
url_safe_member_id = url_safe_string(member.id)
|
|
40
|
+
elif isinstance(member, Team) and member.id is not None and (not is_valid_uuid(member.id)):
|
|
41
|
+
url_safe_member_id = url_safe_string(member.id)
|
|
42
|
+
elif member.name is not None:
|
|
43
|
+
url_safe_member_id = url_safe_string(member.name)
|
|
44
|
+
elif isinstance(member, Agent) and member.id is not None:
|
|
45
|
+
url_safe_member_id = member.id
|
|
46
|
+
elif isinstance(member, Team) and member.id is not None:
|
|
47
|
+
url_safe_member_id = member.id
|
|
48
|
+
else:
|
|
49
|
+
url_safe_member_id = None
|
|
50
|
+
return url_safe_member_id
|
agno/utils/timer.py
CHANGED
|
@@ -24,11 +24,11 @@ class Timer:
|
|
|
24
24
|
self.elapsed_time = self.end_time - self.start_time
|
|
25
25
|
return self.end_time
|
|
26
26
|
|
|
27
|
-
def __enter__(self):
|
|
27
|
+
def __enter__(self) -> "Timer":
|
|
28
28
|
self.start_time = perf_counter()
|
|
29
29
|
return self
|
|
30
30
|
|
|
31
|
-
def __exit__(self, *args):
|
|
31
|
+
def __exit__(self, *args) -> None:
|
|
32
32
|
self.end_time = perf_counter()
|
|
33
33
|
if self.start_time is not None:
|
|
34
34
|
self.elapsed_time = self.end_time - self.start_time
|
agno/vectordb/base.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
2
|
from typing import Any, Dict, List, Optional
|
|
3
3
|
|
|
4
|
-
from agno.document import Document
|
|
4
|
+
from agno.knowledge.document import Document
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class VectorDb(ABC):
|
|
@@ -16,41 +16,42 @@ class VectorDb(ABC):
|
|
|
16
16
|
raise NotImplementedError
|
|
17
17
|
|
|
18
18
|
@abstractmethod
|
|
19
|
-
def
|
|
19
|
+
def name_exists(self, name: str) -> bool:
|
|
20
20
|
raise NotImplementedError
|
|
21
21
|
|
|
22
22
|
@abstractmethod
|
|
23
|
-
|
|
23
|
+
def async_name_exists(self, name: str) -> bool:
|
|
24
24
|
raise NotImplementedError
|
|
25
25
|
|
|
26
26
|
@abstractmethod
|
|
27
|
-
def
|
|
27
|
+
def id_exists(self, id: str) -> bool:
|
|
28
28
|
raise NotImplementedError
|
|
29
29
|
|
|
30
30
|
@abstractmethod
|
|
31
|
-
def
|
|
32
|
-
raise NotImplementedError
|
|
33
|
-
|
|
34
|
-
def id_exists(self, id: str) -> bool:
|
|
31
|
+
def content_hash_exists(self, content_hash: str) -> bool:
|
|
35
32
|
raise NotImplementedError
|
|
36
33
|
|
|
37
34
|
@abstractmethod
|
|
38
|
-
def insert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
|
|
35
|
+
def insert(self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
|
|
39
36
|
raise NotImplementedError
|
|
40
37
|
|
|
41
38
|
@abstractmethod
|
|
42
|
-
async def async_insert(
|
|
39
|
+
async def async_insert(
|
|
40
|
+
self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
|
|
41
|
+
) -> None:
|
|
43
42
|
raise NotImplementedError
|
|
44
43
|
|
|
45
44
|
def upsert_available(self) -> bool:
|
|
46
45
|
return False
|
|
47
46
|
|
|
48
47
|
@abstractmethod
|
|
49
|
-
def upsert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
|
|
48
|
+
def upsert(self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
|
|
50
49
|
raise NotImplementedError
|
|
51
50
|
|
|
52
51
|
@abstractmethod
|
|
53
|
-
async def async_upsert(
|
|
52
|
+
async def async_upsert(
|
|
53
|
+
self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
|
|
54
|
+
) -> None:
|
|
54
55
|
raise NotImplementedError
|
|
55
56
|
|
|
56
57
|
@abstractmethod
|
|
@@ -63,15 +64,6 @@ class VectorDb(ABC):
|
|
|
63
64
|
) -> List[Document]:
|
|
64
65
|
raise NotImplementedError
|
|
65
66
|
|
|
66
|
-
def vector_search(self, query: str, limit: int = 5) -> List[Document]:
|
|
67
|
-
raise NotImplementedError
|
|
68
|
-
|
|
69
|
-
def keyword_search(self, query: str, limit: int = 5) -> List[Document]:
|
|
70
|
-
raise NotImplementedError
|
|
71
|
-
|
|
72
|
-
def hybrid_search(self, query: str, limit: int = 5) -> List[Document]:
|
|
73
|
-
raise NotImplementedError
|
|
74
|
-
|
|
75
67
|
@abstractmethod
|
|
76
68
|
def drop(self) -> None:
|
|
77
69
|
raise NotImplementedError
|
|
@@ -94,3 +86,23 @@ class VectorDb(ABC):
|
|
|
94
86
|
@abstractmethod
|
|
95
87
|
def delete(self) -> bool:
|
|
96
88
|
raise NotImplementedError
|
|
89
|
+
|
|
90
|
+
@abstractmethod
|
|
91
|
+
def delete_by_id(self, id: str) -> bool:
|
|
92
|
+
raise NotImplementedError
|
|
93
|
+
|
|
94
|
+
@abstractmethod
|
|
95
|
+
def delete_by_name(self, name: str) -> bool:
|
|
96
|
+
raise NotImplementedError
|
|
97
|
+
|
|
98
|
+
@abstractmethod
|
|
99
|
+
def delete_by_metadata(self, metadata: Dict[str, Any]) -> bool:
|
|
100
|
+
raise NotImplementedError
|
|
101
|
+
|
|
102
|
+
@abstractmethod
|
|
103
|
+
def update_metadata(self, content_id: str, metadata: Dict[str, Any]) -> None:
|
|
104
|
+
raise NotImplementedError
|
|
105
|
+
|
|
106
|
+
@abstractmethod
|
|
107
|
+
def delete_by_content_id(self, content_id: str) -> bool:
|
|
108
|
+
raise NotImplementedError
|