agno 0.1.2__py3-none-any.whl → 2.3.13__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 +44 -5
- agno/agent/agent.py +10531 -2975
- agno/api/agent.py +14 -53
- agno/api/api.py +7 -46
- agno/api/evals.py +22 -0
- agno/api/os.py +17 -0
- agno/api/routes.py +6 -25
- agno/api/schemas/__init__.py +9 -0
- agno/api/schemas/agent.py +6 -9
- agno/api/schemas/evals.py +16 -0
- agno/api/schemas/os.py +14 -0
- agno/api/schemas/team.py +10 -10
- agno/api/schemas/utils.py +21 -0
- agno/api/schemas/workflows.py +16 -0
- agno/api/settings.py +53 -0
- agno/api/team.py +22 -26
- 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/compression/__init__.py +3 -0
- agno/compression/manager.py +247 -0
- agno/culture/__init__.py +3 -0
- agno/culture/manager.py +956 -0
- agno/db/__init__.py +24 -0
- agno/db/async_postgres/__init__.py +3 -0
- agno/db/base.py +946 -0
- agno/db/dynamo/__init__.py +3 -0
- agno/db/dynamo/dynamo.py +2781 -0
- agno/db/dynamo/schemas.py +442 -0
- agno/db/dynamo/utils.py +743 -0
- agno/db/firestore/__init__.py +3 -0
- agno/db/firestore/firestore.py +2379 -0
- agno/db/firestore/schemas.py +181 -0
- agno/db/firestore/utils.py +376 -0
- agno/db/gcs_json/__init__.py +3 -0
- agno/db/gcs_json/gcs_json_db.py +1791 -0
- agno/db/gcs_json/utils.py +228 -0
- agno/db/in_memory/__init__.py +3 -0
- agno/db/in_memory/in_memory_db.py +1312 -0
- agno/db/in_memory/utils.py +230 -0
- agno/db/json/__init__.py +3 -0
- agno/db/json/json_db.py +1777 -0
- agno/db/json/utils.py +230 -0
- agno/db/migrations/manager.py +199 -0
- agno/db/migrations/v1_to_v2.py +635 -0
- agno/db/migrations/versions/v2_3_0.py +938 -0
- agno/db/mongo/__init__.py +17 -0
- agno/db/mongo/async_mongo.py +2760 -0
- agno/db/mongo/mongo.py +2597 -0
- agno/db/mongo/schemas.py +119 -0
- agno/db/mongo/utils.py +276 -0
- agno/db/mysql/__init__.py +4 -0
- agno/db/mysql/async_mysql.py +2912 -0
- agno/db/mysql/mysql.py +2923 -0
- agno/db/mysql/schemas.py +186 -0
- agno/db/mysql/utils.py +488 -0
- agno/db/postgres/__init__.py +4 -0
- agno/db/postgres/async_postgres.py +2579 -0
- agno/db/postgres/postgres.py +2870 -0
- agno/db/postgres/schemas.py +187 -0
- agno/db/postgres/utils.py +442 -0
- agno/db/redis/__init__.py +3 -0
- agno/db/redis/redis.py +2141 -0
- agno/db/redis/schemas.py +159 -0
- agno/db/redis/utils.py +346 -0
- agno/db/schemas/__init__.py +4 -0
- agno/db/schemas/culture.py +120 -0
- agno/db/schemas/evals.py +34 -0
- agno/db/schemas/knowledge.py +40 -0
- agno/db/schemas/memory.py +61 -0
- agno/db/singlestore/__init__.py +3 -0
- agno/db/singlestore/schemas.py +179 -0
- agno/db/singlestore/singlestore.py +2877 -0
- agno/db/singlestore/utils.py +384 -0
- agno/db/sqlite/__init__.py +4 -0
- agno/db/sqlite/async_sqlite.py +2911 -0
- agno/db/sqlite/schemas.py +181 -0
- agno/db/sqlite/sqlite.py +2908 -0
- agno/db/sqlite/utils.py +429 -0
- agno/db/surrealdb/__init__.py +3 -0
- agno/db/surrealdb/metrics.py +292 -0
- agno/db/surrealdb/models.py +334 -0
- agno/db/surrealdb/queries.py +71 -0
- agno/db/surrealdb/surrealdb.py +1908 -0
- agno/db/surrealdb/utils.py +147 -0
- agno/db/utils.py +118 -0
- agno/eval/__init__.py +24 -0
- agno/eval/accuracy.py +666 -276
- agno/eval/agent_as_judge.py +861 -0
- agno/eval/base.py +29 -0
- agno/eval/performance.py +779 -0
- agno/eval/reliability.py +241 -62
- agno/eval/utils.py +120 -0
- agno/exceptions.py +143 -1
- agno/filters.py +354 -0
- agno/guardrails/__init__.py +6 -0
- agno/guardrails/base.py +19 -0
- agno/guardrails/openai.py +144 -0
- agno/guardrails/pii.py +94 -0
- agno/guardrails/prompt_injection.py +52 -0
- agno/hooks/__init__.py +3 -0
- agno/hooks/decorator.py +164 -0
- agno/integrations/discord/__init__.py +3 -0
- agno/integrations/discord/client.py +203 -0
- agno/knowledge/__init__.py +5 -1
- agno/{document → knowledge}/chunking/agentic.py +22 -14
- agno/{document → knowledge}/chunking/document.py +2 -2
- agno/{document → knowledge}/chunking/fixed.py +7 -6
- agno/knowledge/chunking/markdown.py +151 -0
- agno/{document → knowledge}/chunking/recursive.py +15 -3
- agno/knowledge/chunking/row.py +39 -0
- agno/knowledge/chunking/semantic.py +91 -0
- agno/knowledge/chunking/strategy.py +165 -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/knowledge/embedder/aws_bedrock.py +343 -0
- agno/knowledge/embedder/azure_openai.py +210 -0
- agno/{embedder → knowledge/embedder}/base.py +8 -0
- agno/knowledge/embedder/cohere.py +323 -0
- agno/knowledge/embedder/fastembed.py +62 -0
- agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
- agno/knowledge/embedder/google.py +258 -0
- agno/knowledge/embedder/huggingface.py +94 -0
- agno/knowledge/embedder/jina.py +182 -0
- agno/knowledge/embedder/langdb.py +22 -0
- agno/knowledge/embedder/mistral.py +206 -0
- agno/knowledge/embedder/nebius.py +13 -0
- agno/knowledge/embedder/ollama.py +154 -0
- agno/knowledge/embedder/openai.py +195 -0
- agno/knowledge/embedder/sentence_transformer.py +63 -0
- agno/{embedder → knowledge/embedder}/together.py +1 -1
- agno/knowledge/embedder/vllm.py +262 -0
- agno/knowledge/embedder/voyageai.py +165 -0
- agno/knowledge/knowledge.py +3006 -0
- agno/knowledge/reader/__init__.py +7 -0
- agno/knowledge/reader/arxiv_reader.py +81 -0
- agno/knowledge/reader/base.py +95 -0
- agno/knowledge/reader/csv_reader.py +164 -0
- agno/knowledge/reader/docx_reader.py +82 -0
- agno/knowledge/reader/field_labeled_csv_reader.py +290 -0
- agno/knowledge/reader/firecrawl_reader.py +201 -0
- agno/knowledge/reader/json_reader.py +88 -0
- agno/knowledge/reader/markdown_reader.py +137 -0
- agno/knowledge/reader/pdf_reader.py +431 -0
- agno/knowledge/reader/pptx_reader.py +101 -0
- agno/knowledge/reader/reader_factory.py +313 -0
- agno/knowledge/reader/s3_reader.py +89 -0
- agno/knowledge/reader/tavily_reader.py +193 -0
- agno/knowledge/reader/text_reader.py +127 -0
- agno/knowledge/reader/web_search_reader.py +325 -0
- agno/knowledge/reader/website_reader.py +455 -0
- agno/knowledge/reader/wikipedia_reader.py +91 -0
- agno/knowledge/reader/youtube_reader.py +78 -0
- agno/knowledge/remote_content/remote_content.py +88 -0
- agno/knowledge/reranker/__init__.py +3 -0
- agno/{reranker → knowledge/reranker}/base.py +1 -1
- agno/{reranker → knowledge/reranker}/cohere.py +2 -2
- agno/knowledge/reranker/infinity.py +195 -0
- agno/knowledge/reranker/sentence_transformer.py +54 -0
- agno/knowledge/types.py +39 -0
- agno/knowledge/utils.py +234 -0
- agno/media.py +439 -95
- agno/memory/__init__.py +16 -3
- agno/memory/manager.py +1474 -123
- agno/memory/strategies/__init__.py +15 -0
- agno/memory/strategies/base.py +66 -0
- agno/memory/strategies/summarize.py +196 -0
- agno/memory/strategies/types.py +37 -0
- agno/models/aimlapi/__init__.py +5 -0
- agno/models/aimlapi/aimlapi.py +62 -0
- agno/models/anthropic/__init__.py +4 -0
- agno/models/anthropic/claude.py +960 -496
- agno/models/aws/__init__.py +15 -0
- agno/models/aws/bedrock.py +686 -451
- agno/models/aws/claude.py +190 -183
- agno/models/azure/__init__.py +18 -1
- agno/models/azure/ai_foundry.py +489 -0
- agno/models/azure/openai_chat.py +89 -40
- agno/models/base.py +2477 -550
- agno/models/cerebras/__init__.py +12 -0
- agno/models/cerebras/cerebras.py +565 -0
- agno/models/cerebras/cerebras_openai.py +131 -0
- agno/models/cohere/__init__.py +4 -0
- agno/models/cohere/chat.py +306 -492
- agno/models/cometapi/__init__.py +5 -0
- agno/models/cometapi/cometapi.py +74 -0
- agno/models/dashscope/__init__.py +5 -0
- agno/models/dashscope/dashscope.py +90 -0
- agno/models/deepinfra/__init__.py +5 -0
- agno/models/deepinfra/deepinfra.py +45 -0
- agno/models/deepseek/__init__.py +4 -0
- agno/models/deepseek/deepseek.py +110 -9
- agno/models/fireworks/__init__.py +4 -0
- agno/models/fireworks/fireworks.py +19 -22
- agno/models/google/__init__.py +3 -7
- agno/models/google/gemini.py +1717 -662
- agno/models/google/utils.py +22 -0
- agno/models/groq/__init__.py +4 -0
- agno/models/groq/groq.py +391 -666
- agno/models/huggingface/__init__.py +4 -0
- agno/models/huggingface/huggingface.py +266 -538
- agno/models/ibm/__init__.py +5 -0
- agno/models/ibm/watsonx.py +432 -0
- agno/models/internlm/__init__.py +3 -0
- agno/models/internlm/internlm.py +20 -3
- agno/models/langdb/__init__.py +1 -0
- agno/models/langdb/langdb.py +60 -0
- agno/models/litellm/__init__.py +14 -0
- agno/models/litellm/chat.py +503 -0
- agno/models/litellm/litellm_openai.py +42 -0
- agno/models/llama_cpp/__init__.py +5 -0
- agno/models/llama_cpp/llama_cpp.py +22 -0
- agno/models/lmstudio/__init__.py +5 -0
- agno/models/lmstudio/lmstudio.py +25 -0
- agno/models/message.py +361 -39
- agno/models/meta/__init__.py +12 -0
- agno/models/meta/llama.py +502 -0
- agno/models/meta/llama_openai.py +79 -0
- agno/models/metrics.py +120 -0
- agno/models/mistral/__init__.py +4 -0
- agno/models/mistral/mistral.py +293 -393
- agno/models/nebius/__init__.py +3 -0
- agno/models/nebius/nebius.py +53 -0
- agno/models/nexus/__init__.py +3 -0
- agno/models/nexus/nexus.py +22 -0
- agno/models/nvidia/__init__.py +4 -0
- agno/models/nvidia/nvidia.py +22 -3
- agno/models/ollama/__init__.py +4 -2
- agno/models/ollama/chat.py +257 -492
- agno/models/openai/__init__.py +7 -0
- agno/models/openai/chat.py +725 -770
- agno/models/openai/like.py +16 -2
- agno/models/openai/responses.py +1121 -0
- agno/models/openrouter/__init__.py +4 -0
- agno/models/openrouter/openrouter.py +62 -5
- agno/models/perplexity/__init__.py +5 -0
- agno/models/perplexity/perplexity.py +203 -0
- agno/models/portkey/__init__.py +3 -0
- agno/models/portkey/portkey.py +82 -0
- agno/models/requesty/__init__.py +5 -0
- agno/models/requesty/requesty.py +69 -0
- agno/models/response.py +177 -7
- agno/models/sambanova/__init__.py +4 -0
- agno/models/sambanova/sambanova.py +23 -4
- agno/models/siliconflow/__init__.py +5 -0
- agno/models/siliconflow/siliconflow.py +42 -0
- agno/models/together/__init__.py +4 -0
- agno/models/together/together.py +21 -164
- agno/models/utils.py +266 -0
- agno/models/vercel/__init__.py +3 -0
- agno/models/vercel/v0.py +43 -0
- agno/models/vertexai/__init__.py +0 -1
- agno/models/vertexai/claude.py +190 -0
- agno/models/vllm/__init__.py +3 -0
- agno/models/vllm/vllm.py +83 -0
- agno/models/xai/__init__.py +2 -0
- agno/models/xai/xai.py +111 -7
- agno/os/__init__.py +3 -0
- agno/os/app.py +1027 -0
- agno/os/auth.py +244 -0
- agno/os/config.py +126 -0
- agno/os/interfaces/__init__.py +1 -0
- agno/os/interfaces/a2a/__init__.py +3 -0
- agno/os/interfaces/a2a/a2a.py +42 -0
- agno/os/interfaces/a2a/router.py +249 -0
- agno/os/interfaces/a2a/utils.py +924 -0
- agno/os/interfaces/agui/__init__.py +3 -0
- agno/os/interfaces/agui/agui.py +47 -0
- agno/os/interfaces/agui/router.py +147 -0
- agno/os/interfaces/agui/utils.py +574 -0
- agno/os/interfaces/base.py +25 -0
- agno/os/interfaces/slack/__init__.py +3 -0
- agno/os/interfaces/slack/router.py +148 -0
- agno/os/interfaces/slack/security.py +30 -0
- agno/os/interfaces/slack/slack.py +47 -0
- agno/os/interfaces/whatsapp/__init__.py +3 -0
- agno/os/interfaces/whatsapp/router.py +210 -0
- agno/os/interfaces/whatsapp/security.py +55 -0
- agno/os/interfaces/whatsapp/whatsapp.py +36 -0
- agno/os/mcp.py +293 -0
- agno/os/middleware/__init__.py +9 -0
- agno/os/middleware/jwt.py +797 -0
- agno/os/router.py +258 -0
- agno/os/routers/__init__.py +3 -0
- agno/os/routers/agents/__init__.py +3 -0
- agno/os/routers/agents/router.py +599 -0
- agno/os/routers/agents/schema.py +261 -0
- agno/os/routers/evals/__init__.py +3 -0
- agno/os/routers/evals/evals.py +450 -0
- agno/os/routers/evals/schemas.py +174 -0
- agno/os/routers/evals/utils.py +231 -0
- agno/os/routers/health.py +31 -0
- agno/os/routers/home.py +52 -0
- agno/os/routers/knowledge/__init__.py +3 -0
- agno/os/routers/knowledge/knowledge.py +1008 -0
- agno/os/routers/knowledge/schemas.py +178 -0
- agno/os/routers/memory/__init__.py +3 -0
- agno/os/routers/memory/memory.py +661 -0
- agno/os/routers/memory/schemas.py +88 -0
- agno/os/routers/metrics/__init__.py +3 -0
- agno/os/routers/metrics/metrics.py +190 -0
- agno/os/routers/metrics/schemas.py +47 -0
- agno/os/routers/session/__init__.py +3 -0
- agno/os/routers/session/session.py +997 -0
- agno/os/routers/teams/__init__.py +3 -0
- agno/os/routers/teams/router.py +512 -0
- agno/os/routers/teams/schema.py +257 -0
- agno/os/routers/traces/__init__.py +3 -0
- agno/os/routers/traces/schemas.py +414 -0
- agno/os/routers/traces/traces.py +499 -0
- agno/os/routers/workflows/__init__.py +3 -0
- agno/os/routers/workflows/router.py +624 -0
- agno/os/routers/workflows/schema.py +75 -0
- agno/os/schema.py +534 -0
- agno/os/scopes.py +469 -0
- agno/{playground → os}/settings.py +7 -15
- agno/os/utils.py +973 -0
- agno/reasoning/anthropic.py +80 -0
- agno/reasoning/azure_ai_foundry.py +67 -0
- agno/reasoning/deepseek.py +63 -0
- agno/reasoning/default.py +97 -0
- agno/reasoning/gemini.py +73 -0
- agno/reasoning/groq.py +71 -0
- agno/reasoning/helpers.py +24 -1
- agno/reasoning/ollama.py +67 -0
- agno/reasoning/openai.py +86 -0
- agno/reasoning/step.py +2 -1
- agno/reasoning/vertexai.py +76 -0
- agno/run/__init__.py +6 -0
- agno/run/agent.py +822 -0
- agno/run/base.py +247 -0
- agno/run/cancel.py +81 -0
- agno/run/requirement.py +181 -0
- agno/run/team.py +767 -0
- agno/run/workflow.py +708 -0
- agno/session/__init__.py +10 -0
- agno/session/agent.py +260 -0
- agno/session/summary.py +265 -0
- agno/session/team.py +342 -0
- agno/session/workflow.py +501 -0
- agno/table.py +10 -0
- agno/team/__init__.py +37 -0
- agno/team/team.py +9536 -0
- agno/tools/__init__.py +7 -0
- agno/tools/agentql.py +120 -0
- agno/tools/airflow.py +22 -12
- agno/tools/api.py +122 -0
- agno/tools/apify.py +276 -83
- agno/tools/{arxiv_toolkit.py → arxiv.py} +20 -12
- agno/tools/aws_lambda.py +28 -7
- agno/tools/aws_ses.py +66 -0
- agno/tools/baidusearch.py +11 -4
- agno/tools/bitbucket.py +292 -0
- agno/tools/brandfetch.py +213 -0
- agno/tools/bravesearch.py +106 -0
- agno/tools/brightdata.py +367 -0
- agno/tools/browserbase.py +209 -0
- agno/tools/calcom.py +32 -23
- agno/tools/calculator.py +24 -37
- agno/tools/cartesia.py +187 -0
- agno/tools/{clickup_tool.py → clickup.py} +17 -28
- agno/tools/confluence.py +91 -26
- agno/tools/crawl4ai.py +139 -43
- agno/tools/csv_toolkit.py +28 -22
- agno/tools/dalle.py +36 -22
- agno/tools/daytona.py +475 -0
- agno/tools/decorator.py +169 -14
- agno/tools/desi_vocal.py +23 -11
- agno/tools/discord.py +32 -29
- agno/tools/docker.py +716 -0
- agno/tools/duckdb.py +76 -81
- agno/tools/duckduckgo.py +43 -40
- agno/tools/e2b.py +703 -0
- agno/tools/eleven_labs.py +65 -54
- agno/tools/email.py +13 -5
- agno/tools/evm.py +129 -0
- agno/tools/exa.py +324 -42
- agno/tools/fal.py +39 -35
- agno/tools/file.py +196 -30
- agno/tools/file_generation.py +356 -0
- agno/tools/financial_datasets.py +288 -0
- agno/tools/firecrawl.py +108 -33
- agno/tools/function.py +960 -122
- agno/tools/giphy.py +34 -12
- agno/tools/github.py +1294 -97
- agno/tools/gmail.py +922 -0
- agno/tools/google_bigquery.py +117 -0
- agno/tools/google_drive.py +271 -0
- agno/tools/google_maps.py +253 -0
- agno/tools/googlecalendar.py +607 -107
- agno/tools/googlesheets.py +377 -0
- agno/tools/hackernews.py +20 -12
- agno/tools/jina.py +24 -14
- agno/tools/jira.py +48 -19
- agno/tools/knowledge.py +218 -0
- agno/tools/linear.py +82 -43
- agno/tools/linkup.py +58 -0
- agno/tools/local_file_system.py +15 -7
- agno/tools/lumalab.py +41 -26
- agno/tools/mcp/__init__.py +10 -0
- agno/tools/mcp/mcp.py +331 -0
- agno/tools/mcp/multi_mcp.py +347 -0
- agno/tools/mcp/params.py +24 -0
- agno/tools/mcp_toolbox.py +284 -0
- agno/tools/mem0.py +193 -0
- agno/tools/memory.py +419 -0
- agno/tools/mlx_transcribe.py +11 -9
- agno/tools/models/azure_openai.py +190 -0
- agno/tools/models/gemini.py +203 -0
- agno/tools/models/groq.py +158 -0
- agno/tools/models/morph.py +186 -0
- agno/tools/models/nebius.py +124 -0
- agno/tools/models_labs.py +163 -82
- agno/tools/moviepy_video.py +18 -13
- agno/tools/nano_banana.py +151 -0
- agno/tools/neo4j.py +134 -0
- agno/tools/newspaper.py +15 -4
- agno/tools/newspaper4k.py +19 -6
- agno/tools/notion.py +204 -0
- agno/tools/openai.py +181 -17
- agno/tools/openbb.py +27 -20
- agno/tools/opencv.py +321 -0
- agno/tools/openweather.py +233 -0
- agno/tools/oxylabs.py +385 -0
- agno/tools/pandas.py +25 -15
- agno/tools/parallel.py +314 -0
- agno/tools/postgres.py +238 -185
- agno/tools/pubmed.py +125 -13
- agno/tools/python.py +48 -35
- agno/tools/reasoning.py +283 -0
- agno/tools/reddit.py +207 -29
- agno/tools/redshift.py +406 -0
- agno/tools/replicate.py +69 -26
- agno/tools/resend.py +11 -6
- agno/tools/scrapegraph.py +179 -19
- agno/tools/searxng.py +23 -31
- agno/tools/serpapi.py +15 -10
- agno/tools/serper.py +255 -0
- agno/tools/shell.py +23 -12
- agno/tools/shopify.py +1519 -0
- agno/tools/slack.py +56 -14
- agno/tools/sleep.py +8 -6
- agno/tools/spider.py +35 -11
- agno/tools/spotify.py +919 -0
- agno/tools/sql.py +34 -19
- agno/tools/tavily.py +158 -8
- agno/tools/telegram.py +18 -8
- agno/tools/todoist.py +218 -0
- agno/tools/toolkit.py +134 -9
- agno/tools/trafilatura.py +388 -0
- agno/tools/trello.py +25 -28
- agno/tools/twilio.py +18 -9
- agno/tools/user_control_flow.py +78 -0
- agno/tools/valyu.py +228 -0
- agno/tools/visualization.py +467 -0
- agno/tools/webbrowser.py +28 -0
- agno/tools/webex.py +76 -0
- agno/tools/website.py +23 -19
- agno/tools/webtools.py +45 -0
- agno/tools/whatsapp.py +286 -0
- agno/tools/wikipedia.py +28 -19
- agno/tools/workflow.py +285 -0
- agno/tools/{twitter.py → x.py} +142 -46
- agno/tools/yfinance.py +41 -39
- agno/tools/youtube.py +34 -17
- agno/tools/zendesk.py +15 -5
- agno/tools/zep.py +454 -0
- agno/tools/zoom.py +86 -37
- agno/tracing/__init__.py +12 -0
- agno/tracing/exporter.py +157 -0
- agno/tracing/schemas.py +276 -0
- agno/tracing/setup.py +111 -0
- agno/utils/agent.py +938 -0
- agno/utils/audio.py +37 -1
- agno/utils/certs.py +27 -0
- agno/utils/code_execution.py +11 -0
- agno/utils/common.py +103 -20
- agno/utils/cryptography.py +22 -0
- agno/utils/dttm.py +33 -0
- agno/utils/events.py +700 -0
- agno/utils/functions.py +107 -37
- agno/utils/gemini.py +426 -0
- agno/utils/hooks.py +171 -0
- agno/utils/http.py +185 -0
- agno/utils/json_schema.py +159 -37
- agno/utils/knowledge.py +36 -0
- agno/utils/location.py +19 -0
- agno/utils/log.py +221 -8
- agno/utils/mcp.py +214 -0
- agno/utils/media.py +335 -14
- agno/utils/merge_dict.py +22 -1
- agno/utils/message.py +77 -2
- agno/utils/models/ai_foundry.py +50 -0
- agno/utils/models/claude.py +373 -0
- agno/utils/models/cohere.py +94 -0
- agno/utils/models/llama.py +85 -0
- agno/utils/models/mistral.py +100 -0
- agno/utils/models/openai_responses.py +140 -0
- agno/utils/models/schema_utils.py +153 -0
- agno/utils/models/watsonx.py +41 -0
- agno/utils/openai.py +257 -0
- agno/utils/pickle.py +1 -1
- agno/utils/pprint.py +124 -8
- agno/utils/print_response/agent.py +930 -0
- agno/utils/print_response/team.py +1914 -0
- agno/utils/print_response/workflow.py +1668 -0
- agno/utils/prompts.py +111 -0
- agno/utils/reasoning.py +108 -0
- agno/utils/response.py +163 -0
- agno/utils/serialize.py +32 -0
- agno/utils/shell.py +4 -4
- agno/utils/streamlit.py +487 -0
- agno/utils/string.py +204 -51
- agno/utils/team.py +139 -0
- agno/utils/timer.py +9 -2
- agno/utils/tokens.py +657 -0
- agno/utils/tools.py +19 -1
- agno/utils/whatsapp.py +305 -0
- agno/utils/yaml_io.py +3 -3
- agno/vectordb/__init__.py +2 -0
- agno/vectordb/base.py +87 -9
- agno/vectordb/cassandra/__init__.py +5 -1
- agno/vectordb/cassandra/cassandra.py +383 -27
- agno/vectordb/chroma/__init__.py +4 -0
- agno/vectordb/chroma/chromadb.py +748 -83
- agno/vectordb/clickhouse/__init__.py +7 -1
- agno/vectordb/clickhouse/clickhousedb.py +554 -53
- agno/vectordb/couchbase/__init__.py +3 -0
- agno/vectordb/couchbase/couchbase.py +1446 -0
- agno/vectordb/lancedb/__init__.py +5 -0
- agno/vectordb/lancedb/lance_db.py +730 -98
- agno/vectordb/langchaindb/__init__.py +5 -0
- agno/vectordb/langchaindb/langchaindb.py +163 -0
- agno/vectordb/lightrag/__init__.py +5 -0
- agno/vectordb/lightrag/lightrag.py +388 -0
- agno/vectordb/llamaindex/__init__.py +3 -0
- agno/vectordb/llamaindex/llamaindexdb.py +166 -0
- agno/vectordb/milvus/__init__.py +3 -0
- agno/vectordb/milvus/milvus.py +966 -78
- agno/vectordb/mongodb/__init__.py +9 -1
- agno/vectordb/mongodb/mongodb.py +1175 -172
- agno/vectordb/pgvector/__init__.py +8 -0
- agno/vectordb/pgvector/pgvector.py +599 -115
- agno/vectordb/pineconedb/__init__.py +5 -1
- agno/vectordb/pineconedb/pineconedb.py +406 -43
- agno/vectordb/qdrant/__init__.py +4 -0
- agno/vectordb/qdrant/qdrant.py +914 -61
- agno/vectordb/redis/__init__.py +9 -0
- agno/vectordb/redis/redisdb.py +682 -0
- agno/vectordb/singlestore/__init__.py +8 -1
- agno/vectordb/singlestore/singlestore.py +771 -0
- agno/vectordb/surrealdb/__init__.py +3 -0
- agno/vectordb/surrealdb/surrealdb.py +663 -0
- agno/vectordb/upstashdb/__init__.py +5 -0
- agno/vectordb/upstashdb/upstashdb.py +718 -0
- agno/vectordb/weaviate/__init__.py +8 -0
- agno/vectordb/weaviate/index.py +15 -0
- agno/vectordb/weaviate/weaviate.py +1009 -0
- agno/workflow/__init__.py +23 -1
- agno/workflow/agent.py +299 -0
- agno/workflow/condition.py +759 -0
- agno/workflow/loop.py +756 -0
- agno/workflow/parallel.py +853 -0
- agno/workflow/router.py +723 -0
- agno/workflow/step.py +1564 -0
- agno/workflow/steps.py +613 -0
- agno/workflow/types.py +556 -0
- agno/workflow/workflow.py +4327 -514
- agno-2.3.13.dist-info/METADATA +639 -0
- agno-2.3.13.dist-info/RECORD +613 -0
- {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/WHEEL +1 -1
- agno-2.3.13.dist-info/licenses/LICENSE +201 -0
- agno/api/playground.py +0 -91
- agno/api/schemas/playground.py +0 -22
- agno/api/schemas/user.py +0 -22
- agno/api/schemas/workspace.py +0 -46
- agno/api/user.py +0 -160
- agno/api/workspace.py +0 -151
- agno/cli/auth_server.py +0 -118
- agno/cli/config.py +0 -275
- agno/cli/console.py +0 -88
- agno/cli/credentials.py +0 -23
- agno/cli/entrypoint.py +0 -571
- agno/cli/operator.py +0 -355
- agno/cli/settings.py +0 -85
- agno/cli/ws/ws_cli.py +0 -817
- agno/constants.py +0 -13
- agno/document/__init__.py +0 -1
- agno/document/chunking/semantic.py +0 -47
- agno/document/chunking/strategy.py +0 -31
- agno/document/reader/__init__.py +0 -1
- agno/document/reader/arxiv_reader.py +0 -41
- agno/document/reader/base.py +0 -22
- agno/document/reader/csv_reader.py +0 -84
- agno/document/reader/docx_reader.py +0 -46
- agno/document/reader/firecrawl_reader.py +0 -99
- agno/document/reader/json_reader.py +0 -43
- agno/document/reader/pdf_reader.py +0 -219
- agno/document/reader/s3/pdf_reader.py +0 -46
- agno/document/reader/s3/text_reader.py +0 -51
- agno/document/reader/text_reader.py +0 -41
- agno/document/reader/website_reader.py +0 -175
- agno/document/reader/youtube_reader.py +0 -50
- agno/embedder/__init__.py +0 -1
- agno/embedder/azure_openai.py +0 -86
- agno/embedder/cohere.py +0 -72
- agno/embedder/fastembed.py +0 -37
- agno/embedder/google.py +0 -73
- agno/embedder/huggingface.py +0 -54
- agno/embedder/mistral.py +0 -80
- agno/embedder/ollama.py +0 -57
- agno/embedder/openai.py +0 -74
- agno/embedder/sentence_transformer.py +0 -38
- agno/embedder/voyageai.py +0 -64
- agno/eval/perf.py +0 -201
- agno/file/__init__.py +0 -1
- 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 -230
- agno/knowledge/arxiv.py +0 -22
- agno/knowledge/combined.py +0 -22
- agno/knowledge/csv.py +0 -28
- agno/knowledge/csv_url.py +0 -19
- agno/knowledge/document.py +0 -20
- agno/knowledge/docx.py +0 -30
- agno/knowledge/json.py +0 -28
- agno/knowledge/langchain.py +0 -71
- agno/knowledge/llamaindex.py +0 -66
- agno/knowledge/pdf.py +0 -28
- agno/knowledge/pdf_url.py +0 -26
- agno/knowledge/s3/base.py +0 -60
- agno/knowledge/s3/pdf.py +0 -21
- agno/knowledge/s3/text.py +0 -23
- agno/knowledge/text.py +0 -30
- agno/knowledge/website.py +0 -88
- agno/knowledge/wikipedia.py +0 -31
- agno/knowledge/youtube.py +0 -22
- agno/memory/agent.py +0 -392
- agno/memory/classifier.py +0 -104
- agno/memory/db/__init__.py +0 -1
- 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 -15
- agno/memory/row.py +0 -36
- agno/memory/summarizer.py +0 -192
- agno/memory/summary.py +0 -19
- agno/memory/workflow.py +0 -38
- agno/models/google/gemini_openai.py +0 -26
- agno/models/ollama/hermes.py +0 -221
- agno/models/ollama/tools.py +0 -362
- agno/models/vertexai/gemini.py +0 -595
- agno/playground/__init__.py +0 -3
- agno/playground/async_router.py +0 -421
- agno/playground/deploy.py +0 -249
- agno/playground/operator.py +0 -92
- agno/playground/playground.py +0 -91
- agno/playground/schemas.py +0 -76
- agno/playground/serve.py +0 -55
- agno/playground/sync_router.py +0 -405
- agno/reasoning/agent.py +0 -68
- agno/run/response.py +0 -112
- agno/storage/agent/__init__.py +0 -0
- agno/storage/agent/base.py +0 -38
- agno/storage/agent/dynamodb.py +0 -350
- agno/storage/agent/json.py +0 -92
- agno/storage/agent/mongodb.py +0 -228
- agno/storage/agent/postgres.py +0 -367
- agno/storage/agent/session.py +0 -79
- agno/storage/agent/singlestore.py +0 -303
- agno/storage/agent/sqlite.py +0 -357
- agno/storage/agent/yaml.py +0 -93
- agno/storage/workflow/__init__.py +0 -0
- agno/storage/workflow/base.py +0 -40
- agno/storage/workflow/mongodb.py +0 -233
- agno/storage/workflow/postgres.py +0 -366
- agno/storage/workflow/session.py +0 -60
- agno/storage/workflow/sqlite.py +0 -359
- agno/tools/googlesearch.py +0 -88
- 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/vectordb/singlestore/s2vectordb.py +0 -390
- agno/vectordb/singlestore/s2vectordb2.py +0 -355
- agno/workspace/__init__.py +0 -0
- agno/workspace/config.py +0 -325
- agno/workspace/enums.py +0 -6
- agno/workspace/helpers.py +0 -48
- agno/workspace/operator.py +0 -758
- agno/workspace/settings.py +0 -63
- agno-0.1.2.dist-info/LICENSE +0 -375
- agno-0.1.2.dist-info/METADATA +0 -502
- agno-0.1.2.dist-info/RECORD +0 -352
- agno-0.1.2.dist-info/entry_points.txt +0 -3
- /agno/{cli → db/migrations}/__init__.py +0 -0
- /agno/{cli/ws → db/migrations/versions}/__init__.py +0 -0
- /agno/{document/chunking/__init__.py → db/schemas/metrics.py} +0 -0
- /agno/{document/reader/s3 → integrations}/__init__.py +0 -0
- /agno/{file/local → knowledge/chunking}/__init__.py +0 -0
- /agno/{infra → knowledge/remote_content}/__init__.py +0 -0
- /agno/{knowledge/s3 → tools/models}/__init__.py +0 -0
- /agno/{reranker → utils/models}/__init__.py +0 -0
- /agno/{storage → utils/print_response}/__init__.py +0 -0
- {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from typing import Any, Dict, List, Optional, Union
|
|
4
|
+
|
|
5
|
+
from agno.tools import Toolkit
|
|
6
|
+
from agno.utils.log import log_info, logger
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class VisualizationTools(Toolkit):
|
|
10
|
+
def __init__(
|
|
11
|
+
self,
|
|
12
|
+
output_dir: str = "charts",
|
|
13
|
+
enable_create_bar_chart: bool = True,
|
|
14
|
+
enable_create_line_chart: bool = True,
|
|
15
|
+
enable_create_pie_chart: bool = True,
|
|
16
|
+
enable_create_scatter_plot: bool = True,
|
|
17
|
+
enable_create_histogram: bool = True,
|
|
18
|
+
all: bool = False,
|
|
19
|
+
**kwargs,
|
|
20
|
+
):
|
|
21
|
+
"""
|
|
22
|
+
Initialize the VisualizationTools toolkit.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
output_dir (str): Directory to save charts. Default is "charts".
|
|
26
|
+
"""
|
|
27
|
+
# Check if matplotlib is available
|
|
28
|
+
try:
|
|
29
|
+
import matplotlib
|
|
30
|
+
|
|
31
|
+
# Use non-interactive backend to avoid display issues
|
|
32
|
+
matplotlib.use("Agg")
|
|
33
|
+
except ImportError:
|
|
34
|
+
raise ImportError("matplotlib is not installed. Please install it using: `pip install matplotlib`")
|
|
35
|
+
|
|
36
|
+
# Create output directory if it doesn't exist
|
|
37
|
+
if not os.path.exists(output_dir):
|
|
38
|
+
os.makedirs(output_dir)
|
|
39
|
+
|
|
40
|
+
self.output_dir = output_dir
|
|
41
|
+
|
|
42
|
+
tools: List[Any] = []
|
|
43
|
+
if enable_create_bar_chart or all:
|
|
44
|
+
tools.append(self.create_bar_chart)
|
|
45
|
+
if enable_create_line_chart or all:
|
|
46
|
+
tools.append(self.create_line_chart)
|
|
47
|
+
if enable_create_pie_chart or all:
|
|
48
|
+
tools.append(self.create_pie_chart)
|
|
49
|
+
if enable_create_scatter_plot or all:
|
|
50
|
+
tools.append(self.create_scatter_plot)
|
|
51
|
+
if enable_create_histogram or all:
|
|
52
|
+
tools.append(self.create_histogram)
|
|
53
|
+
|
|
54
|
+
super().__init__(name="visualization_tools", tools=tools, **kwargs)
|
|
55
|
+
|
|
56
|
+
def _normalize_data_for_charts(
|
|
57
|
+
self, data: Union[Dict[str, Any], List[Dict[str, Any]], List[Any], str]
|
|
58
|
+
) -> Dict[str, Union[int, float]]:
|
|
59
|
+
"""
|
|
60
|
+
Normalize various data formats into a simple dictionary format for charts.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
data: Can be a dict, list of dicts, or list of values
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
Dict with string keys and numeric values
|
|
67
|
+
"""
|
|
68
|
+
if isinstance(data, dict):
|
|
69
|
+
# Already in the right format, just ensure values are numeric
|
|
70
|
+
return {str(k): float(v) if isinstance(v, (int, float)) else 0 for k, v in data.items()}
|
|
71
|
+
|
|
72
|
+
elif isinstance(data, list) and len(data) > 0:
|
|
73
|
+
if isinstance(data[0], dict):
|
|
74
|
+
# List of dictionaries - try to find key-value pairs
|
|
75
|
+
result = {}
|
|
76
|
+
for item in data:
|
|
77
|
+
if isinstance(item, dict):
|
|
78
|
+
# Look for common key patterns
|
|
79
|
+
keys = list(item.keys())
|
|
80
|
+
if len(keys) >= 2:
|
|
81
|
+
# Use first key as label, second as value
|
|
82
|
+
label_key = keys[0]
|
|
83
|
+
value_key = keys[1]
|
|
84
|
+
result[str(item[label_key])] = (
|
|
85
|
+
float(item[value_key]) if isinstance(item[value_key], (int, float)) else 0
|
|
86
|
+
)
|
|
87
|
+
return result
|
|
88
|
+
else:
|
|
89
|
+
# List of values - create numbered keys
|
|
90
|
+
return {f"Item {i + 1}": float(v) if isinstance(v, (int, float)) else 0 for i, v in enumerate(data)}
|
|
91
|
+
|
|
92
|
+
# Fallback
|
|
93
|
+
return {"Data": 1.0}
|
|
94
|
+
|
|
95
|
+
def create_bar_chart(
|
|
96
|
+
self,
|
|
97
|
+
data: Union[Dict[str, Union[int, float]], List[Dict[str, Any]], str],
|
|
98
|
+
title: str = "Bar Chart",
|
|
99
|
+
x_label: str = "Categories",
|
|
100
|
+
y_label: str = "Values",
|
|
101
|
+
filename: Optional[str] = None,
|
|
102
|
+
) -> str:
|
|
103
|
+
"""
|
|
104
|
+
Create a bar chart from the provided data.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
data: Dictionary with categories as keys and values as numbers,
|
|
108
|
+
or list of dictionaries, or JSON string
|
|
109
|
+
title (str): Title of the chart
|
|
110
|
+
x_label (str): Label for x-axis
|
|
111
|
+
y_label (str): Label for y-axis
|
|
112
|
+
filename (Optional[str]): Custom filename for the chart image
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
str: JSON string with chart information and file path
|
|
116
|
+
"""
|
|
117
|
+
try:
|
|
118
|
+
import matplotlib.pyplot as plt
|
|
119
|
+
|
|
120
|
+
# Handle string input (JSON)
|
|
121
|
+
if isinstance(data, str):
|
|
122
|
+
try:
|
|
123
|
+
data = json.loads(data)
|
|
124
|
+
except json.JSONDecodeError:
|
|
125
|
+
pass
|
|
126
|
+
|
|
127
|
+
# Normalize data format
|
|
128
|
+
normalized_data = self._normalize_data_for_charts(data)
|
|
129
|
+
|
|
130
|
+
# Prepare data
|
|
131
|
+
categories = list(normalized_data.keys())
|
|
132
|
+
values = list(normalized_data.values())
|
|
133
|
+
|
|
134
|
+
# Create the chart
|
|
135
|
+
plt.figure(figsize=(10, 6))
|
|
136
|
+
plt.bar(categories, values)
|
|
137
|
+
plt.title(title)
|
|
138
|
+
plt.xlabel(x_label)
|
|
139
|
+
plt.ylabel(y_label)
|
|
140
|
+
plt.xticks(rotation=45, ha="right")
|
|
141
|
+
plt.tight_layout()
|
|
142
|
+
|
|
143
|
+
# Save the chart
|
|
144
|
+
if filename is None:
|
|
145
|
+
filename = f"bar_chart_{len(os.listdir(self.output_dir)) + 1}.png"
|
|
146
|
+
|
|
147
|
+
file_path = os.path.join(self.output_dir, filename)
|
|
148
|
+
plt.savefig(file_path, dpi=300, bbox_inches="tight")
|
|
149
|
+
plt.close()
|
|
150
|
+
|
|
151
|
+
log_info(f"Bar chart created and saved to {file_path}")
|
|
152
|
+
|
|
153
|
+
return json.dumps(
|
|
154
|
+
{
|
|
155
|
+
"chart_type": "bar_chart",
|
|
156
|
+
"title": title,
|
|
157
|
+
"file_path": file_path,
|
|
158
|
+
"data_points": len(normalized_data),
|
|
159
|
+
"status": "success",
|
|
160
|
+
}
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
except Exception as e:
|
|
164
|
+
logger.error(f"Error creating bar chart: {str(e)}")
|
|
165
|
+
return json.dumps({"chart_type": "bar_chart", "error": str(e), "status": "error"})
|
|
166
|
+
|
|
167
|
+
def create_line_chart(
|
|
168
|
+
self,
|
|
169
|
+
data: Union[Dict[str, Union[int, float]], List[Dict[str, Any]], str],
|
|
170
|
+
title: str = "Line Chart",
|
|
171
|
+
x_label: str = "X-axis",
|
|
172
|
+
y_label: str = "Y-axis",
|
|
173
|
+
filename: Optional[str] = None,
|
|
174
|
+
) -> str:
|
|
175
|
+
"""
|
|
176
|
+
Create a line chart from the provided data.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
data: Dictionary with x-values as keys and y-values as numbers,
|
|
180
|
+
or list of dictionaries, or JSON string
|
|
181
|
+
title (str): Title of the chart
|
|
182
|
+
x_label (str): Label for x-axis
|
|
183
|
+
y_label (str): Label for y-axis
|
|
184
|
+
filename (Optional[str]): Custom filename for the chart image
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
str: JSON string with chart information and file path
|
|
188
|
+
"""
|
|
189
|
+
try:
|
|
190
|
+
import matplotlib.pyplot as plt
|
|
191
|
+
|
|
192
|
+
# Handle string input (JSON)
|
|
193
|
+
if isinstance(data, str):
|
|
194
|
+
try:
|
|
195
|
+
data = json.loads(data)
|
|
196
|
+
except json.JSONDecodeError:
|
|
197
|
+
pass
|
|
198
|
+
|
|
199
|
+
# Normalize data format
|
|
200
|
+
normalized_data = self._normalize_data_for_charts(data)
|
|
201
|
+
|
|
202
|
+
# Prepare data
|
|
203
|
+
x_values = list(normalized_data.keys())
|
|
204
|
+
y_values = list(normalized_data.values())
|
|
205
|
+
|
|
206
|
+
# Create the chart
|
|
207
|
+
plt.figure(figsize=(10, 6))
|
|
208
|
+
plt.plot(x_values, y_values, marker="o", linewidth=2, markersize=6)
|
|
209
|
+
plt.title(title)
|
|
210
|
+
plt.xlabel(x_label)
|
|
211
|
+
plt.ylabel(y_label)
|
|
212
|
+
plt.xticks(rotation=45, ha="right")
|
|
213
|
+
plt.grid(True, alpha=0.3)
|
|
214
|
+
plt.tight_layout()
|
|
215
|
+
|
|
216
|
+
# Save the chart
|
|
217
|
+
if filename is None:
|
|
218
|
+
filename = f"line_chart_{len(os.listdir(self.output_dir)) + 1}.png"
|
|
219
|
+
|
|
220
|
+
file_path = os.path.join(self.output_dir, filename)
|
|
221
|
+
plt.savefig(file_path, dpi=300, bbox_inches="tight")
|
|
222
|
+
plt.close()
|
|
223
|
+
|
|
224
|
+
log_info(f"Line chart created and saved to {file_path}")
|
|
225
|
+
|
|
226
|
+
return json.dumps(
|
|
227
|
+
{
|
|
228
|
+
"chart_type": "line_chart",
|
|
229
|
+
"title": title,
|
|
230
|
+
"file_path": file_path,
|
|
231
|
+
"data_points": len(normalized_data),
|
|
232
|
+
"status": "success",
|
|
233
|
+
}
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
except Exception as e:
|
|
237
|
+
logger.error(f"Error creating line chart: {str(e)}")
|
|
238
|
+
return json.dumps({"chart_type": "line_chart", "error": str(e), "status": "error"})
|
|
239
|
+
|
|
240
|
+
def create_pie_chart(
|
|
241
|
+
self,
|
|
242
|
+
data: Union[Dict[str, Union[int, float]], List[Dict[str, Any]], str],
|
|
243
|
+
title: str = "Pie Chart",
|
|
244
|
+
filename: Optional[str] = None,
|
|
245
|
+
) -> str:
|
|
246
|
+
"""
|
|
247
|
+
Create a pie chart from the provided data.
|
|
248
|
+
|
|
249
|
+
Args:
|
|
250
|
+
data: Dictionary with categories as keys and values as numbers,
|
|
251
|
+
or list of dictionaries, or JSON string
|
|
252
|
+
title (str): Title of the chart
|
|
253
|
+
filename (Optional[str]): Custom filename for the chart image
|
|
254
|
+
|
|
255
|
+
Returns:
|
|
256
|
+
str: JSON string with chart information and file path
|
|
257
|
+
"""
|
|
258
|
+
try:
|
|
259
|
+
import matplotlib.pyplot as plt
|
|
260
|
+
|
|
261
|
+
# Handle string input (JSON)
|
|
262
|
+
if isinstance(data, str):
|
|
263
|
+
try:
|
|
264
|
+
data = json.loads(data)
|
|
265
|
+
except json.JSONDecodeError:
|
|
266
|
+
pass
|
|
267
|
+
|
|
268
|
+
# Normalize data format
|
|
269
|
+
normalized_data = self._normalize_data_for_charts(data)
|
|
270
|
+
|
|
271
|
+
# Prepare data
|
|
272
|
+
labels = list(normalized_data.keys())
|
|
273
|
+
values = list(normalized_data.values())
|
|
274
|
+
|
|
275
|
+
# Create the chart
|
|
276
|
+
plt.figure(figsize=(10, 8))
|
|
277
|
+
plt.pie(values, labels=labels, autopct="%1.1f%%", startangle=90)
|
|
278
|
+
plt.title(title)
|
|
279
|
+
plt.axis("equal") # Equal aspect ratio ensures that pie is drawn as a circle
|
|
280
|
+
|
|
281
|
+
# Save the chart
|
|
282
|
+
if filename is None:
|
|
283
|
+
filename = f"pie_chart_{len(os.listdir(self.output_dir)) + 1}.png"
|
|
284
|
+
|
|
285
|
+
file_path = os.path.join(self.output_dir, filename)
|
|
286
|
+
plt.savefig(file_path, dpi=300, bbox_inches="tight")
|
|
287
|
+
plt.close()
|
|
288
|
+
|
|
289
|
+
log_info(f"Pie chart created and saved to {file_path}")
|
|
290
|
+
|
|
291
|
+
return json.dumps(
|
|
292
|
+
{
|
|
293
|
+
"chart_type": "pie_chart",
|
|
294
|
+
"title": title,
|
|
295
|
+
"file_path": file_path,
|
|
296
|
+
"data_points": len(normalized_data),
|
|
297
|
+
"status": "success",
|
|
298
|
+
}
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
except Exception as e:
|
|
302
|
+
logger.error(f"Error creating pie chart: {str(e)}")
|
|
303
|
+
return json.dumps({"chart_type": "pie_chart", "error": str(e), "status": "error"})
|
|
304
|
+
|
|
305
|
+
def create_scatter_plot(
|
|
306
|
+
self,
|
|
307
|
+
x_data: Optional[List[Union[int, float]]] = None,
|
|
308
|
+
y_data: Optional[List[Union[int, float]]] = None,
|
|
309
|
+
title: str = "Scatter Plot",
|
|
310
|
+
x_label: str = "X-axis",
|
|
311
|
+
y_label: str = "Y-axis",
|
|
312
|
+
filename: Optional[str] = None,
|
|
313
|
+
# Alternative parameter names that agents might use
|
|
314
|
+
x: Optional[List[Union[int, float]]] = None,
|
|
315
|
+
y: Optional[List[Union[int, float]]] = None,
|
|
316
|
+
data: Optional[Union[List[List[Union[int, float]]], Dict[str, List[Union[int, float]]]]] = None,
|
|
317
|
+
) -> str:
|
|
318
|
+
"""
|
|
319
|
+
Create a scatter plot from the provided data.
|
|
320
|
+
|
|
321
|
+
Args:
|
|
322
|
+
x_data: List of x-values (can also use 'x' parameter)
|
|
323
|
+
y_data: List of y-values (can also use 'y' parameter)
|
|
324
|
+
title (str): Title of the chart
|
|
325
|
+
x_label (str): Label for x-axis
|
|
326
|
+
y_label (str): Label for y-axis
|
|
327
|
+
filename (Optional[str]): Custom filename for the chart image
|
|
328
|
+
data: Alternative format - list of [x,y] pairs or dict with 'x' and 'y' keys
|
|
329
|
+
|
|
330
|
+
Returns:
|
|
331
|
+
str: JSON string with chart information and file path
|
|
332
|
+
"""
|
|
333
|
+
try:
|
|
334
|
+
import matplotlib.pyplot as plt
|
|
335
|
+
|
|
336
|
+
# Handle different parameter formats
|
|
337
|
+
if x_data is None:
|
|
338
|
+
x_data = x
|
|
339
|
+
if y_data is None:
|
|
340
|
+
y_data = y
|
|
341
|
+
|
|
342
|
+
# Handle data parameter
|
|
343
|
+
if data is not None:
|
|
344
|
+
if isinstance(data, dict):
|
|
345
|
+
if "x" in data and "y" in data:
|
|
346
|
+
x_data = data["x"]
|
|
347
|
+
y_data = data["y"]
|
|
348
|
+
elif isinstance(data, list) and len(data) > 0:
|
|
349
|
+
if isinstance(data[0], list) and len(data[0]) == 2:
|
|
350
|
+
# List of [x,y] pairs
|
|
351
|
+
x_data = [point[0] for point in data]
|
|
352
|
+
y_data = [point[1] for point in data]
|
|
353
|
+
|
|
354
|
+
# Validate that we have data
|
|
355
|
+
if x_data is None or y_data is None:
|
|
356
|
+
raise ValueError("Missing x_data and y_data parameters")
|
|
357
|
+
|
|
358
|
+
if len(x_data) != len(y_data):
|
|
359
|
+
raise ValueError("x_data and y_data must have the same length")
|
|
360
|
+
|
|
361
|
+
# Create the chart
|
|
362
|
+
plt.figure(figsize=(10, 6))
|
|
363
|
+
plt.scatter(x_data, y_data, alpha=0.7, s=50)
|
|
364
|
+
plt.title(title)
|
|
365
|
+
plt.xlabel(x_label)
|
|
366
|
+
plt.ylabel(y_label)
|
|
367
|
+
plt.grid(True, alpha=0.3)
|
|
368
|
+
plt.tight_layout()
|
|
369
|
+
|
|
370
|
+
# Save the chart
|
|
371
|
+
if filename is None:
|
|
372
|
+
filename = f"scatter_plot_{len(os.listdir(self.output_dir)) + 1}.png"
|
|
373
|
+
|
|
374
|
+
file_path = os.path.join(self.output_dir, filename)
|
|
375
|
+
plt.savefig(file_path, dpi=300, bbox_inches="tight")
|
|
376
|
+
plt.close()
|
|
377
|
+
|
|
378
|
+
log_info(f"Scatter plot created and saved to {file_path}")
|
|
379
|
+
|
|
380
|
+
return json.dumps(
|
|
381
|
+
{
|
|
382
|
+
"chart_type": "scatter_plot",
|
|
383
|
+
"title": title,
|
|
384
|
+
"file_path": file_path,
|
|
385
|
+
"data_points": len(x_data),
|
|
386
|
+
"status": "success",
|
|
387
|
+
}
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
except Exception as e:
|
|
391
|
+
logger.error(f"Error creating scatter plot: {str(e)}")
|
|
392
|
+
return json.dumps({"chart_type": "scatter_plot", "error": str(e), "status": "error"})
|
|
393
|
+
|
|
394
|
+
def create_histogram(
|
|
395
|
+
self,
|
|
396
|
+
data: List[Union[int, float]],
|
|
397
|
+
bins: int = 10,
|
|
398
|
+
title: str = "Histogram",
|
|
399
|
+
x_label: str = "Values",
|
|
400
|
+
y_label: str = "Frequency",
|
|
401
|
+
filename: Optional[str] = None,
|
|
402
|
+
) -> str:
|
|
403
|
+
"""
|
|
404
|
+
Create a histogram from the provided data.
|
|
405
|
+
|
|
406
|
+
Args:
|
|
407
|
+
data: List of numeric values to plot
|
|
408
|
+
bins (int): Number of bins for the histogram
|
|
409
|
+
title (str): Title of the chart
|
|
410
|
+
x_label (str): Label for x-axis
|
|
411
|
+
y_label (str): Label for y-axis
|
|
412
|
+
filename (Optional[str]): Custom filename for the chart image
|
|
413
|
+
|
|
414
|
+
Returns:
|
|
415
|
+
str: JSON string with chart information and file path
|
|
416
|
+
"""
|
|
417
|
+
try:
|
|
418
|
+
import matplotlib.pyplot as plt
|
|
419
|
+
|
|
420
|
+
# Validate data
|
|
421
|
+
if not isinstance(data, list) or len(data) == 0:
|
|
422
|
+
raise ValueError("Data must be a non-empty list of numbers")
|
|
423
|
+
|
|
424
|
+
# Convert to numeric values
|
|
425
|
+
numeric_data = []
|
|
426
|
+
for value in data:
|
|
427
|
+
try:
|
|
428
|
+
numeric_data.append(float(value))
|
|
429
|
+
except (ValueError, TypeError):
|
|
430
|
+
continue
|
|
431
|
+
|
|
432
|
+
if len(numeric_data) == 0:
|
|
433
|
+
raise ValueError("No valid numeric data found")
|
|
434
|
+
|
|
435
|
+
# Create the chart
|
|
436
|
+
plt.figure(figsize=(10, 6))
|
|
437
|
+
plt.hist(numeric_data, bins=bins, alpha=0.7, edgecolor="black")
|
|
438
|
+
plt.title(title)
|
|
439
|
+
plt.xlabel(x_label)
|
|
440
|
+
plt.ylabel(y_label)
|
|
441
|
+
plt.grid(True, alpha=0.3)
|
|
442
|
+
plt.tight_layout()
|
|
443
|
+
|
|
444
|
+
# Save the chart
|
|
445
|
+
if filename is None:
|
|
446
|
+
filename = f"histogram_{len(os.listdir(self.output_dir)) + 1}.png"
|
|
447
|
+
|
|
448
|
+
file_path = os.path.join(self.output_dir, filename)
|
|
449
|
+
plt.savefig(file_path, dpi=300, bbox_inches="tight")
|
|
450
|
+
plt.close()
|
|
451
|
+
|
|
452
|
+
log_info(f"Histogram created and saved to {file_path}")
|
|
453
|
+
|
|
454
|
+
return json.dumps(
|
|
455
|
+
{
|
|
456
|
+
"chart_type": "histogram",
|
|
457
|
+
"title": title,
|
|
458
|
+
"file_path": file_path,
|
|
459
|
+
"data_points": len(numeric_data),
|
|
460
|
+
"bins": bins,
|
|
461
|
+
"status": "success",
|
|
462
|
+
}
|
|
463
|
+
)
|
|
464
|
+
|
|
465
|
+
except Exception as e:
|
|
466
|
+
logger.error(f"Error creating histogram: {str(e)}")
|
|
467
|
+
return json.dumps({"chart_type": "histogram", "error": str(e), "status": "error"})
|
agno/tools/webbrowser.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import webbrowser
|
|
2
|
+
from typing import Any, List
|
|
3
|
+
|
|
4
|
+
from agno.tools import Toolkit
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class WebBrowserTools(Toolkit):
|
|
8
|
+
"""Tools for opening a page on the web browser"""
|
|
9
|
+
|
|
10
|
+
def __init__(self, enable_open_page: bool = True, all: bool = False, **kwargs):
|
|
11
|
+
tools: List[Any] = []
|
|
12
|
+
if all or enable_open_page:
|
|
13
|
+
tools.append(self.open_page)
|
|
14
|
+
|
|
15
|
+
super().__init__(name="webbrowser_tools", tools=tools, **kwargs)
|
|
16
|
+
|
|
17
|
+
def open_page(self, url: str, new_window: bool = False):
|
|
18
|
+
"""Open a URL in a browser window
|
|
19
|
+
Args:
|
|
20
|
+
url (str): URL to open
|
|
21
|
+
new_window (bool): If True, open in a new window, otherwise open in a new tab. Default is False.
|
|
22
|
+
Returns:
|
|
23
|
+
None
|
|
24
|
+
"""
|
|
25
|
+
if new_window:
|
|
26
|
+
webbrowser.open_new(url)
|
|
27
|
+
else:
|
|
28
|
+
webbrowser.open_new_tab(url)
|
agno/tools/webex.py
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from os import getenv
|
|
3
|
+
from typing import Any, List, Optional
|
|
4
|
+
|
|
5
|
+
from agno.tools import Toolkit
|
|
6
|
+
from agno.utils.log import logger
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
from webexpythonsdk import WebexAPI
|
|
10
|
+
from webexpythonsdk.exceptions import ApiError
|
|
11
|
+
except ImportError:
|
|
12
|
+
logger.error("Webex tools require the `webexpythonsdk` package. Run `pip install webexpythonsdk` to install it.")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class WebexTools(Toolkit):
|
|
16
|
+
def __init__(
|
|
17
|
+
self,
|
|
18
|
+
enable_send_message: bool = True,
|
|
19
|
+
enable_list_rooms: bool = True,
|
|
20
|
+
all: bool = False,
|
|
21
|
+
access_token: Optional[str] = None,
|
|
22
|
+
**kwargs,
|
|
23
|
+
):
|
|
24
|
+
access_token = access_token or getenv("WEBEX_ACCESS_TOKEN")
|
|
25
|
+
if access_token is None:
|
|
26
|
+
raise ValueError("Webex access token is not set. Please set the WEBEX_ACCESS_TOKEN environment variable.")
|
|
27
|
+
|
|
28
|
+
self.client = WebexAPI(access_token=access_token)
|
|
29
|
+
|
|
30
|
+
tools: List[Any] = []
|
|
31
|
+
if all or enable_send_message:
|
|
32
|
+
tools.append(self.send_message)
|
|
33
|
+
if all or enable_list_rooms:
|
|
34
|
+
tools.append(self.list_rooms)
|
|
35
|
+
|
|
36
|
+
super().__init__(name="webex", tools=tools, **kwargs)
|
|
37
|
+
|
|
38
|
+
def send_message(self, room_id: str, text: str) -> str:
|
|
39
|
+
"""
|
|
40
|
+
Send a message to a Webex Room.
|
|
41
|
+
Args:
|
|
42
|
+
room_id (str): The Room ID to send the message to.
|
|
43
|
+
text (str): The text of the message to send.
|
|
44
|
+
Returns:
|
|
45
|
+
str: A JSON string containing the response from the Webex.
|
|
46
|
+
"""
|
|
47
|
+
try:
|
|
48
|
+
response = self.client.messages.create(roomId=room_id, text=text)
|
|
49
|
+
return json.dumps(response.json_data)
|
|
50
|
+
except ApiError as e:
|
|
51
|
+
logger.error(f"Error sending message: {e} in room: {room_id}")
|
|
52
|
+
return json.dumps({"error": str(e)})
|
|
53
|
+
|
|
54
|
+
def list_rooms(self) -> str:
|
|
55
|
+
"""
|
|
56
|
+
List all rooms in the Webex.
|
|
57
|
+
Returns:
|
|
58
|
+
str: A JSON string containing the list of rooms.
|
|
59
|
+
"""
|
|
60
|
+
try:
|
|
61
|
+
response = self.client.rooms.list()
|
|
62
|
+
rooms_list = [
|
|
63
|
+
{
|
|
64
|
+
"id": room.id,
|
|
65
|
+
"title": room.title,
|
|
66
|
+
"type": room.type,
|
|
67
|
+
"isPublic": room.isPublic,
|
|
68
|
+
"isReadOnly": room.isReadOnly,
|
|
69
|
+
}
|
|
70
|
+
for room in response
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
return json.dumps({"rooms": rooms_list}, indent=4)
|
|
74
|
+
except ApiError as e:
|
|
75
|
+
logger.error(f"Error listing rooms: {e}")
|
|
76
|
+
return json.dumps({"error": str(e)})
|
agno/tools/website.py
CHANGED
|
@@ -1,23 +1,29 @@
|
|
|
1
1
|
import json
|
|
2
|
-
from typing import List, Optional
|
|
2
|
+
from typing import Any, List, Optional
|
|
3
3
|
|
|
4
|
-
from agno.document import Document
|
|
5
|
-
from agno.knowledge.
|
|
4
|
+
from agno.knowledge.document import Document
|
|
5
|
+
from agno.knowledge.knowledge import Knowledge
|
|
6
6
|
from agno.tools import Toolkit
|
|
7
|
-
from agno.utils.log import
|
|
7
|
+
from agno.utils.log import log_debug
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class WebsiteTools(Toolkit):
|
|
11
|
-
def __init__(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
def __init__(
|
|
12
|
+
self,
|
|
13
|
+
knowledge: Optional[Knowledge] = None,
|
|
14
|
+
**kwargs,
|
|
15
|
+
):
|
|
16
|
+
self.knowledge: Optional[Knowledge] = knowledge
|
|
17
|
+
|
|
18
|
+
tools: List[Any] = []
|
|
19
|
+
if self.knowledge is not None:
|
|
20
|
+
tools.append(self.add_website_to_knowledge)
|
|
17
21
|
else:
|
|
18
|
-
|
|
22
|
+
tools.append(self.read_url)
|
|
23
|
+
|
|
24
|
+
super().__init__(name="website_tools", tools=tools, **kwargs)
|
|
19
25
|
|
|
20
|
-
def
|
|
26
|
+
def add_website_to_knowledge(self, url: str) -> str:
|
|
21
27
|
"""This function adds a websites content to the knowledge base.
|
|
22
28
|
NOTE: The website must start with https:// and should be a valid website.
|
|
23
29
|
|
|
@@ -26,13 +32,11 @@ class WebsiteTools(Toolkit):
|
|
|
26
32
|
:param url: The url of the website to add.
|
|
27
33
|
:return: 'Success' if the website was added to the knowledge base.
|
|
28
34
|
"""
|
|
29
|
-
if self.
|
|
35
|
+
if self.knowledge is None:
|
|
30
36
|
return "Knowledge base not provided"
|
|
31
37
|
|
|
32
|
-
|
|
33
|
-
self.
|
|
34
|
-
logger.debug("Loading knowledge base.")
|
|
35
|
-
self.knowledge_base.load(recreate=False)
|
|
38
|
+
log_debug(f"Adding to knowledge base: {url}")
|
|
39
|
+
self.knowledge.add_content(url=url)
|
|
36
40
|
return "Success"
|
|
37
41
|
|
|
38
42
|
def read_url(self, url: str) -> str:
|
|
@@ -41,10 +45,10 @@ class WebsiteTools(Toolkit):
|
|
|
41
45
|
:param url: The url of the website to read.
|
|
42
46
|
:return: Relevant documents from the website.
|
|
43
47
|
"""
|
|
44
|
-
from agno.
|
|
48
|
+
from agno.knowledge.reader.website_reader import WebsiteReader
|
|
45
49
|
|
|
46
50
|
website = WebsiteReader()
|
|
47
51
|
|
|
48
|
-
|
|
52
|
+
log_debug(f"Reading website: {url}")
|
|
49
53
|
relevant_docs: List[Document] = website.read(url=url)
|
|
50
54
|
return json.dumps([doc.to_dict() for doc in relevant_docs])
|
agno/tools/webtools.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
|
|
3
|
+
from agno.tools import Toolkit
|
|
4
|
+
from agno.utils.log import logger
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class WebTools(Toolkit):
|
|
8
|
+
"""
|
|
9
|
+
A toolkit for working with web-related tools.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
retries: int = 3,
|
|
15
|
+
enable_expand_url: bool = True,
|
|
16
|
+
all: bool = False,
|
|
17
|
+
**kwargs,
|
|
18
|
+
):
|
|
19
|
+
self.retries = retries
|
|
20
|
+
|
|
21
|
+
tools = []
|
|
22
|
+
if all or enable_expand_url:
|
|
23
|
+
tools.append(self.expand_url)
|
|
24
|
+
|
|
25
|
+
super().__init__(name="web_tools", tools=tools, **kwargs)
|
|
26
|
+
|
|
27
|
+
def expand_url(self, url: str) -> str:
|
|
28
|
+
"""
|
|
29
|
+
Expands a shortened URL to its final destination using HTTP HEAD requests with retries.
|
|
30
|
+
|
|
31
|
+
:param url: The URL to expand.
|
|
32
|
+
|
|
33
|
+
:return: The final destination URL if successful; otherwise, returns the original URL.
|
|
34
|
+
"""
|
|
35
|
+
timeout = 5
|
|
36
|
+
for attempt in range(1, self.retries + 1):
|
|
37
|
+
try:
|
|
38
|
+
response = httpx.head(url, follow_redirects=True, timeout=timeout)
|
|
39
|
+
final_url = response.url
|
|
40
|
+
logger.info(f"expand_url: {url} expanded to {final_url} on attempt {attempt}")
|
|
41
|
+
return str(final_url)
|
|
42
|
+
except Exception as e:
|
|
43
|
+
logger.error(f"Error expanding URL {url} on attempt {attempt}: {e}")
|
|
44
|
+
|
|
45
|
+
return url
|