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
agno/tools/openai.py
CHANGED
|
@@ -1,38 +1,202 @@
|
|
|
1
|
+
from os import getenv
|
|
2
|
+
from typing import Any, List, Literal, Optional, Union
|
|
3
|
+
from uuid import uuid4
|
|
4
|
+
|
|
5
|
+
from agno.agent import Agent
|
|
6
|
+
from agno.media import Audio, Image
|
|
7
|
+
from agno.team.team import Team
|
|
1
8
|
from agno.tools import Toolkit
|
|
2
|
-
from agno.
|
|
9
|
+
from agno.tools.function import ToolResult
|
|
10
|
+
from agno.utils.log import log_debug, log_error, log_warning
|
|
3
11
|
|
|
4
12
|
try:
|
|
5
13
|
from openai import OpenAI as OpenAIClient
|
|
6
14
|
except (ModuleNotFoundError, ImportError):
|
|
7
15
|
raise ImportError("`openai` not installed. Please install using `pip install openai`")
|
|
8
16
|
|
|
9
|
-
|
|
10
|
-
|
|
17
|
+
# Define only types specifically needed by OpenAITools class
|
|
18
|
+
OpenAIVoice = Literal["alloy", "echo", "fable", "onyx", "nova", "shimmer"]
|
|
19
|
+
OpenAITTSModel = Literal["tts-1", "tts-1-hd"]
|
|
20
|
+
OpenAITTSFormat = Literal["mp3", "opus", "aac", "flac", "wav", "pcm"]
|
|
11
21
|
|
|
12
22
|
|
|
13
23
|
class OpenAITools(Toolkit):
|
|
14
|
-
"""Tools for interacting with
|
|
24
|
+
"""Tools for interacting with OpenAI API.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
api_key (str, optional): OpenAI API key. Retrieved from OPENAI_API_KEY env variable if not provided.
|
|
28
|
+
enable_transcription (bool): Enable audio transcription functionality. Default is True.
|
|
29
|
+
enable_image_generation (bool): Enable image generation functionality. Default is True.
|
|
30
|
+
enable_speech_generation (bool): Enable speech generation functionality. Default is True.
|
|
31
|
+
all (bool): Enable all tools. Overrides individual flags when True. Default is False.
|
|
32
|
+
transcription_model (str): Model to use for transcription. Default is "whisper-1".
|
|
33
|
+
text_to_speech_voice (OpenAIVoice): Voice to use for TTS. Default is "alloy".
|
|
34
|
+
text_to_speech_model (OpenAITTSModel): Model to use for TTS. Default is "tts-1".
|
|
35
|
+
text_to_speech_format (OpenAITTSFormat): Audio format for TTS. Default is "mp3".
|
|
36
|
+
image_model (str, optional): Model to use for image generation. Default is "dall-e-3".
|
|
37
|
+
image_quality (str, optional): Quality setting for image generation.
|
|
38
|
+
image_size (str, optional): Size setting for image generation.
|
|
39
|
+
image_style (str, optional): Style setting for image generation.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def __init__(
|
|
43
|
+
self,
|
|
44
|
+
api_key: Optional[str] = None,
|
|
45
|
+
enable_transcription: bool = True,
|
|
46
|
+
enable_image_generation: bool = True,
|
|
47
|
+
enable_speech_generation: bool = True,
|
|
48
|
+
all: bool = False,
|
|
49
|
+
transcription_model: str = "whisper-1",
|
|
50
|
+
text_to_speech_voice: OpenAIVoice = "alloy",
|
|
51
|
+
text_to_speech_model: OpenAITTSModel = "tts-1",
|
|
52
|
+
text_to_speech_format: OpenAITTSFormat = "mp3",
|
|
53
|
+
image_model: Optional[str] = "dall-e-3",
|
|
54
|
+
image_quality: Optional[str] = None,
|
|
55
|
+
image_size: Optional[Literal["256x256", "512x512", "1024x1024", "1792x1024", "1024x1792"]] = None,
|
|
56
|
+
image_style: Optional[Literal["vivid", "natural"]] = None,
|
|
57
|
+
**kwargs,
|
|
58
|
+
):
|
|
59
|
+
self.api_key = api_key or getenv("OPENAI_API_KEY")
|
|
60
|
+
if not self.api_key:
|
|
61
|
+
raise ValueError("OPENAI_API_KEY not set. Please set the OPENAI_API_KEY environment variable.")
|
|
15
62
|
|
|
16
|
-
|
|
17
|
-
|
|
63
|
+
self.transcription_model = transcription_model
|
|
64
|
+
# Store TTS defaults
|
|
65
|
+
self.tts_voice = text_to_speech_voice
|
|
66
|
+
self.tts_model = text_to_speech_model
|
|
67
|
+
self.tts_format = text_to_speech_format
|
|
68
|
+
self.image_model = image_model
|
|
69
|
+
self.image_quality = image_quality
|
|
70
|
+
self.image_style = image_style
|
|
71
|
+
self.image_size = image_size
|
|
18
72
|
|
|
19
|
-
|
|
73
|
+
tools: List[Any] = []
|
|
74
|
+
if all or enable_transcription:
|
|
75
|
+
tools.append(self.transcribe_audio)
|
|
76
|
+
if all or enable_image_generation:
|
|
77
|
+
tools.append(self.generate_image)
|
|
78
|
+
if all or enable_speech_generation:
|
|
79
|
+
tools.append(self.generate_speech)
|
|
80
|
+
|
|
81
|
+
super().__init__(name="openai_tools", tools=tools, **kwargs)
|
|
20
82
|
|
|
21
83
|
def transcribe_audio(self, audio_path: str) -> str:
|
|
22
84
|
"""Transcribe audio file using OpenAI's Whisper API
|
|
23
85
|
Args:
|
|
24
86
|
audio_path: Path to the audio file
|
|
25
|
-
Returns:
|
|
26
|
-
str: Transcribed text
|
|
27
87
|
"""
|
|
28
|
-
|
|
88
|
+
log_debug(f"Transcribing audio from {audio_path}")
|
|
89
|
+
try:
|
|
90
|
+
audio_file = open(audio_path, "rb")
|
|
91
|
+
|
|
92
|
+
transcript = OpenAIClient(api_key=self.api_key).audio.transcriptions.create(
|
|
93
|
+
model=self.transcription_model,
|
|
94
|
+
file=audio_file,
|
|
95
|
+
response_format="text",
|
|
96
|
+
)
|
|
97
|
+
except Exception as e: # type: ignore[return]
|
|
98
|
+
log_error(f"Failed to transcribe audio: {str(e)}")
|
|
99
|
+
return f"Failed to transcribe audio: {str(e)}"
|
|
100
|
+
|
|
101
|
+
log_debug(f"Transcript: {transcript}")
|
|
102
|
+
return transcript # type: ignore[return-value]
|
|
103
|
+
|
|
104
|
+
def generate_image(
|
|
105
|
+
self,
|
|
106
|
+
prompt: str,
|
|
107
|
+
) -> ToolResult:
|
|
108
|
+
"""Generate images based on a text prompt.
|
|
109
|
+
Args:
|
|
110
|
+
prompt (str): The text prompt to generate the image from.
|
|
111
|
+
"""
|
|
29
112
|
try:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
113
|
+
import base64
|
|
114
|
+
|
|
115
|
+
extra_params = {
|
|
116
|
+
"size": self.image_size,
|
|
117
|
+
"quality": self.image_quality,
|
|
118
|
+
"style": self.image_style,
|
|
119
|
+
}
|
|
120
|
+
extra_params = {k: v for k, v in extra_params.items() if v is not None}
|
|
121
|
+
|
|
122
|
+
# gpt-image-1 by default outputs a base64 encoded image but other models do not
|
|
123
|
+
# so we add a response_format parameter to have consistent output.
|
|
124
|
+
if self.image_model and self.image_model.startswith("gpt-image"):
|
|
125
|
+
response = OpenAIClient(api_key=self.api_key).images.generate(
|
|
126
|
+
model=self.image_model,
|
|
127
|
+
prompt=prompt,
|
|
128
|
+
**extra_params, # type: ignore
|
|
33
129
|
)
|
|
34
|
-
|
|
35
|
-
|
|
130
|
+
else:
|
|
131
|
+
response = OpenAIClient(api_key=self.api_key).images.generate(
|
|
132
|
+
model=self.image_model,
|
|
133
|
+
prompt=prompt,
|
|
134
|
+
response_format="b64_json",
|
|
135
|
+
**extra_params, # type: ignore
|
|
136
|
+
)
|
|
137
|
+
data = None
|
|
138
|
+
if hasattr(response, "data") and response.data:
|
|
139
|
+
data = response.data[0]
|
|
140
|
+
if data is None:
|
|
141
|
+
log_warning("OpenAI API did not return any data.")
|
|
142
|
+
return ToolResult(content="Failed to generate image: No data received from API.")
|
|
143
|
+
|
|
144
|
+
if hasattr(data, "b64_json") and data.b64_json:
|
|
145
|
+
image_base64 = data.b64_json
|
|
146
|
+
media_id = str(uuid4())
|
|
147
|
+
|
|
148
|
+
# Decode base64 to bytes for proper storage
|
|
149
|
+
image_bytes = base64.b64decode(image_base64)
|
|
150
|
+
|
|
151
|
+
# Create ImageArtifact and return in ToolResult
|
|
152
|
+
image_artifact = Image(
|
|
153
|
+
id=media_id,
|
|
154
|
+
content=image_bytes, # ← Store as bytes, not encoded string
|
|
155
|
+
mime_type="image/png",
|
|
156
|
+
original_prompt=prompt,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
return ToolResult(
|
|
160
|
+
content="Image generated successfully.",
|
|
161
|
+
images=[image_artifact],
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
return ToolResult(content="Failed to generate image: No content received from API.")
|
|
36
165
|
except Exception as e:
|
|
37
|
-
|
|
38
|
-
return f"Failed to
|
|
166
|
+
log_error(f"Failed to generate image using {self.image_model}: {e}")
|
|
167
|
+
return ToolResult(content=f"Failed to generate image: {e}")
|
|
168
|
+
|
|
169
|
+
def generate_speech(
|
|
170
|
+
self,
|
|
171
|
+
agent: Union[Agent, Team],
|
|
172
|
+
text_input: str,
|
|
173
|
+
) -> ToolResult: # Changed return type
|
|
174
|
+
"""Generate speech from text using OpenAI's Text-to-Speech API.
|
|
175
|
+
Args:
|
|
176
|
+
text_input (str): The text to synthesize into speech.
|
|
177
|
+
"""
|
|
178
|
+
try:
|
|
179
|
+
response = OpenAIClient(api_key=self.api_key).audio.speech.create(
|
|
180
|
+
model=self.tts_model,
|
|
181
|
+
voice=self.tts_voice,
|
|
182
|
+
input=text_input,
|
|
183
|
+
response_format=self.tts_format,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
# Get raw audio data for artifact creation before potentially saving
|
|
187
|
+
audio_data: bytes = response.content
|
|
188
|
+
|
|
189
|
+
# Create AudioArtifact and return in ToolResult
|
|
190
|
+
media_id = str(uuid4())
|
|
191
|
+
audio_artifact = Audio(
|
|
192
|
+
id=media_id,
|
|
193
|
+
content=audio_data,
|
|
194
|
+
mime_type=f"audio/{self.tts_format}",
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
return ToolResult(
|
|
198
|
+
content=f"Speech generated successfully with ID: {media_id}",
|
|
199
|
+
audios=[audio_artifact],
|
|
200
|
+
)
|
|
201
|
+
except Exception as e:
|
|
202
|
+
return ToolResult(content=f"Failed to generate speech: {str(e)}")
|
agno/tools/openbb.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from os import getenv
|
|
3
|
-
from typing import Any, Literal, Optional
|
|
3
|
+
from typing import Any, List, Literal, Optional
|
|
4
4
|
|
|
5
5
|
from agno.tools import Toolkit
|
|
6
|
-
from agno.utils.log import logger
|
|
6
|
+
from agno.utils.log import log_debug, logger
|
|
7
7
|
|
|
8
8
|
try:
|
|
9
9
|
from openbb import obb as openbb_app
|
|
@@ -17,14 +17,14 @@ class OpenBBTools(Toolkit):
|
|
|
17
17
|
obb: Optional[Any] = None,
|
|
18
18
|
openbb_pat: Optional[str] = None,
|
|
19
19
|
provider: Literal["benzinga", "fmp", "intrinio", "polygon", "tiingo", "tmx", "yfinance"] = "yfinance",
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
enable_get_stock_price: bool = True,
|
|
21
|
+
enable_search_company_symbol: bool = False,
|
|
22
|
+
enable_get_company_news: bool = False,
|
|
23
|
+
enable_get_company_profile: bool = False,
|
|
24
|
+
enable_get_price_targets: bool = False,
|
|
25
|
+
all: bool = False,
|
|
26
|
+
**kwargs,
|
|
25
27
|
):
|
|
26
|
-
super().__init__(name="yfinance_tools")
|
|
27
|
-
|
|
28
28
|
self.obb = obb or openbb_app
|
|
29
29
|
try:
|
|
30
30
|
if openbb_pat or getenv("OPENBB_PAT"):
|
|
@@ -34,16 +34,19 @@ class OpenBBTools(Toolkit):
|
|
|
34
34
|
|
|
35
35
|
self.provider: Literal["benzinga", "fmp", "intrinio", "polygon", "tiingo", "tmx", "yfinance"] = provider
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
37
|
+
tools: List[Any] = []
|
|
38
|
+
if enable_get_stock_price or all:
|
|
39
|
+
tools.append(self.get_stock_price)
|
|
40
|
+
if enable_search_company_symbol or all:
|
|
41
|
+
tools.append(self.search_company_symbol)
|
|
42
|
+
if enable_get_company_news or all:
|
|
43
|
+
tools.append(self.get_company_news)
|
|
44
|
+
if enable_get_company_profile or all:
|
|
45
|
+
tools.append(self.get_company_profile)
|
|
46
|
+
if enable_get_price_targets or all:
|
|
47
|
+
tools.append(self.get_price_targets)
|
|
48
|
+
|
|
49
|
+
super().__init__(name="openbb_tools", tools=tools, **kwargs)
|
|
47
50
|
|
|
48
51
|
def get_stock_price(self, symbol: str) -> str:
|
|
49
52
|
"""Use this function to get the current stock price for a stock symbol or list of symbols.
|
|
@@ -56,6 +59,7 @@ class OpenBBTools(Toolkit):
|
|
|
56
59
|
str: The current stock prices or error message.
|
|
57
60
|
"""
|
|
58
61
|
try:
|
|
62
|
+
log_debug(f"Fetching current price for {symbol}")
|
|
59
63
|
result = self.obb.equity.price.quote(symbol=symbol, provider=self.provider).to_polars() # type: ignore
|
|
60
64
|
clean_results = []
|
|
61
65
|
for row in result.to_dicts():
|
|
@@ -89,7 +93,7 @@ class OpenBBTools(Toolkit):
|
|
|
89
93
|
str: A JSON string containing the ticker symbols.
|
|
90
94
|
"""
|
|
91
95
|
|
|
92
|
-
|
|
96
|
+
log_debug(f"Search ticker for {company_name}")
|
|
93
97
|
result = self.obb.equity.search(company_name).to_polars() # type: ignore
|
|
94
98
|
clean_results = []
|
|
95
99
|
if len(result) > 0:
|
|
@@ -109,6 +113,7 @@ class OpenBBTools(Toolkit):
|
|
|
109
113
|
str: JSON containing consensus price target and recommendations.
|
|
110
114
|
"""
|
|
111
115
|
try:
|
|
116
|
+
log_debug(f"Fetching price targets for {symbol}")
|
|
112
117
|
result = self.obb.equity.estimates.consensus(symbol=symbol, provider=self.provider).to_polars() # type: ignore
|
|
113
118
|
return json.dumps(result.to_dicts(), indent=2, default=str)
|
|
114
119
|
except Exception as e:
|
|
@@ -126,6 +131,7 @@ class OpenBBTools(Toolkit):
|
|
|
126
131
|
str: JSON containing company news and press releases.
|
|
127
132
|
"""
|
|
128
133
|
try:
|
|
134
|
+
log_debug(f"Fetching news for {symbol}")
|
|
129
135
|
result = self.obb.news.company(symbol=symbol, provider=self.provider, limit=num_stories).to_polars() # type: ignore
|
|
130
136
|
clean_results = []
|
|
131
137
|
if len(result) > 0:
|
|
@@ -147,6 +153,7 @@ class OpenBBTools(Toolkit):
|
|
|
147
153
|
str: JSON containing company profile and overview.
|
|
148
154
|
"""
|
|
149
155
|
try:
|
|
156
|
+
log_debug(f"Fetching company profile for {symbol}")
|
|
150
157
|
result = self.obb.equity.profile(symbol=symbol, provider=self.provider).to_polars() # type: ignore
|
|
151
158
|
return json.dumps(result.to_dicts(), indent=2, default=str)
|
|
152
159
|
except Exception as e:
|
agno/tools/opencv.py
ADDED
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import time
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Callable, List
|
|
4
|
+
from uuid import uuid4
|
|
5
|
+
|
|
6
|
+
from agno.agent import Agent
|
|
7
|
+
from agno.media import Image, Video
|
|
8
|
+
from agno.tools import Toolkit
|
|
9
|
+
from agno.tools.function import ToolResult
|
|
10
|
+
from agno.utils.log import log_debug, log_error, log_info
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
import cv2
|
|
14
|
+
except ImportError:
|
|
15
|
+
raise ImportError("`opencv-python` package not found. Please install it with `pip install opencv-python`")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class OpenCVTools(Toolkit):
|
|
19
|
+
"""Tools for capturing images and videos from the webcam using OpenCV"""
|
|
20
|
+
|
|
21
|
+
def __init__(
|
|
22
|
+
self,
|
|
23
|
+
show_preview=False,
|
|
24
|
+
enable_capture_image: bool = True,
|
|
25
|
+
enable_capture_video: bool = True,
|
|
26
|
+
all: bool = False,
|
|
27
|
+
**kwargs,
|
|
28
|
+
):
|
|
29
|
+
self.show_preview = show_preview
|
|
30
|
+
|
|
31
|
+
tools: List[Callable] = []
|
|
32
|
+
if all or enable_capture_image:
|
|
33
|
+
tools.append(self.capture_image)
|
|
34
|
+
if all or enable_capture_video:
|
|
35
|
+
tools.append(self.capture_video)
|
|
36
|
+
|
|
37
|
+
super().__init__(
|
|
38
|
+
name="opencv_tools",
|
|
39
|
+
tools=tools,
|
|
40
|
+
**kwargs,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
def capture_image(
|
|
44
|
+
self,
|
|
45
|
+
agent: Agent,
|
|
46
|
+
prompt: str = "Webcam capture",
|
|
47
|
+
) -> ToolResult:
|
|
48
|
+
"""Capture an image from the webcam.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
prompt (str): Description of the image capture. Defaults to "Webcam capture".
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
ToolResult: A ToolResult containing the captured image or error message.
|
|
55
|
+
"""
|
|
56
|
+
try:
|
|
57
|
+
log_debug("Initializing webcam for image capture...")
|
|
58
|
+
cam = cv2.VideoCapture(0)
|
|
59
|
+
|
|
60
|
+
if not cam.isOpened():
|
|
61
|
+
cam = cv2.VideoCapture(0, cv2.CAP_AVFOUNDATION) # macOS
|
|
62
|
+
if not cam.isOpened():
|
|
63
|
+
cam = cv2.VideoCapture(0, cv2.CAP_DSHOW) # Windows
|
|
64
|
+
if not cam.isOpened():
|
|
65
|
+
cam = cv2.VideoCapture(0, cv2.CAP_V4L2) # Linux
|
|
66
|
+
|
|
67
|
+
if not cam.isOpened():
|
|
68
|
+
error_msg = "Could not open webcam. Please ensure your terminal has camera permissions and the camera is not being used by another application."
|
|
69
|
+
log_error(error_msg)
|
|
70
|
+
return ToolResult(content=error_msg)
|
|
71
|
+
|
|
72
|
+
try:
|
|
73
|
+
cam.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
|
|
74
|
+
cam.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
|
|
75
|
+
cam.set(cv2.CAP_PROP_FPS, 30)
|
|
76
|
+
|
|
77
|
+
log_debug("Camera initialized successfully")
|
|
78
|
+
captured_frame = None
|
|
79
|
+
|
|
80
|
+
if self.show_preview:
|
|
81
|
+
log_info("Live preview started. Press 'c' to capture image, 'q' to quit.")
|
|
82
|
+
|
|
83
|
+
while True:
|
|
84
|
+
ret, frame = cam.read()
|
|
85
|
+
if not ret:
|
|
86
|
+
error_msg = "Failed to read frame from webcam"
|
|
87
|
+
log_error(error_msg)
|
|
88
|
+
return ToolResult(content=error_msg)
|
|
89
|
+
|
|
90
|
+
cv2.imshow('Camera Preview - Press "c" to capture, "q" to quit', frame)
|
|
91
|
+
|
|
92
|
+
key = cv2.waitKey(1) & 0xFF
|
|
93
|
+
if key == ord("c"):
|
|
94
|
+
captured_frame = frame.copy()
|
|
95
|
+
log_info("Image captured!")
|
|
96
|
+
break
|
|
97
|
+
elif key == ord("q"):
|
|
98
|
+
log_info("Capture cancelled by user")
|
|
99
|
+
return ToolResult(content="Image capture cancelled by user")
|
|
100
|
+
else:
|
|
101
|
+
ret, captured_frame = cam.read()
|
|
102
|
+
if not ret:
|
|
103
|
+
error_msg = "Failed to capture image from webcam"
|
|
104
|
+
log_error(error_msg)
|
|
105
|
+
return ToolResult(content=error_msg)
|
|
106
|
+
|
|
107
|
+
if captured_frame is None:
|
|
108
|
+
error_msg = "No frame captured"
|
|
109
|
+
log_error(error_msg)
|
|
110
|
+
return ToolResult(content=error_msg)
|
|
111
|
+
|
|
112
|
+
success, encoded_image = cv2.imencode(".png", captured_frame)
|
|
113
|
+
|
|
114
|
+
if not success:
|
|
115
|
+
error_msg = "Failed to encode captured image"
|
|
116
|
+
log_error(error_msg)
|
|
117
|
+
return ToolResult(content=error_msg)
|
|
118
|
+
|
|
119
|
+
image_bytes = encoded_image.tobytes()
|
|
120
|
+
media_id = str(uuid4())
|
|
121
|
+
|
|
122
|
+
# Create ImageArtifact with raw bytes (not base64 encoded)
|
|
123
|
+
image_artifact = Image(
|
|
124
|
+
id=media_id,
|
|
125
|
+
content=image_bytes, # Store as raw bytes
|
|
126
|
+
original_prompt=prompt,
|
|
127
|
+
mime_type="image/png",
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
log_debug(f"Successfully captured and attached image {media_id}")
|
|
131
|
+
return ToolResult(
|
|
132
|
+
content="Image captured successfully",
|
|
133
|
+
images=[image_artifact],
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
finally:
|
|
137
|
+
# Release the camera and close windows
|
|
138
|
+
cam.release()
|
|
139
|
+
cv2.destroyAllWindows()
|
|
140
|
+
log_debug("Camera resources released")
|
|
141
|
+
|
|
142
|
+
except Exception as e:
|
|
143
|
+
error_msg = f"Error capturing image: {str(e)}"
|
|
144
|
+
log_error(error_msg)
|
|
145
|
+
return ToolResult(content=error_msg)
|
|
146
|
+
|
|
147
|
+
def capture_video(
|
|
148
|
+
self,
|
|
149
|
+
agent: Agent,
|
|
150
|
+
duration: int = 10,
|
|
151
|
+
prompt: str = "Webcam video capture",
|
|
152
|
+
) -> ToolResult:
|
|
153
|
+
"""Capture a video from the webcam.
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
duration (int): Duration in seconds to record video. Defaults to 10 seconds.
|
|
157
|
+
prompt (str): Description of the video capture. Defaults to "Webcam video capture".
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
ToolResult: A ToolResult containing the captured video or error message.
|
|
161
|
+
"""
|
|
162
|
+
try:
|
|
163
|
+
log_debug("Initializing webcam for video capture...")
|
|
164
|
+
cap = cv2.VideoCapture(0)
|
|
165
|
+
|
|
166
|
+
# Try different backends for better compatibility
|
|
167
|
+
if not cap.isOpened():
|
|
168
|
+
cap = cv2.VideoCapture(0, cv2.CAP_AVFOUNDATION) # macOS
|
|
169
|
+
if not cap.isOpened():
|
|
170
|
+
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW) # Windows
|
|
171
|
+
if not cap.isOpened():
|
|
172
|
+
cap = cv2.VideoCapture(0, cv2.CAP_V4L2) # Linux
|
|
173
|
+
|
|
174
|
+
if not cap.isOpened():
|
|
175
|
+
error_msg = "Could not open webcam. Please ensure your terminal has camera permissions and the camera is not being used by another application."
|
|
176
|
+
log_error(error_msg)
|
|
177
|
+
return ToolResult(content=error_msg)
|
|
178
|
+
|
|
179
|
+
try:
|
|
180
|
+
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
|
|
181
|
+
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
|
|
182
|
+
actual_fps = cap.get(cv2.CAP_PROP_FPS)
|
|
183
|
+
|
|
184
|
+
# Use actual FPS or default to 30 if detection fails
|
|
185
|
+
if actual_fps <= 0 or actual_fps > 60:
|
|
186
|
+
actual_fps = 30.0
|
|
187
|
+
|
|
188
|
+
log_debug(f"Video properties: {frame_width}x{frame_height} at {actual_fps} FPS")
|
|
189
|
+
|
|
190
|
+
# Try different codecs in order of preference for compatibility
|
|
191
|
+
codecs_to_try = [
|
|
192
|
+
("avc1", "H.264"), # Most compatible
|
|
193
|
+
("mp4v", "MPEG-4"), # Fallback
|
|
194
|
+
("XVID", "Xvid"), # Another fallback
|
|
195
|
+
]
|
|
196
|
+
|
|
197
|
+
import os
|
|
198
|
+
import tempfile
|
|
199
|
+
|
|
200
|
+
with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as temp_file:
|
|
201
|
+
temp_filepath = temp_file.name
|
|
202
|
+
|
|
203
|
+
out = None
|
|
204
|
+
successful_codec = None
|
|
205
|
+
|
|
206
|
+
for codec_fourcc, codec_name in codecs_to_try:
|
|
207
|
+
try:
|
|
208
|
+
fourcc = getattr(cv2, "VideoWriter_fourcc")(*codec_fourcc)
|
|
209
|
+
out = cv2.VideoWriter(temp_filepath, fourcc, actual_fps, (frame_width, frame_height))
|
|
210
|
+
|
|
211
|
+
if out.isOpened():
|
|
212
|
+
successful_codec = codec_name
|
|
213
|
+
log_debug(f"Successfully initialized video writer with {codec_name} codec")
|
|
214
|
+
break
|
|
215
|
+
else:
|
|
216
|
+
out.release()
|
|
217
|
+
out = None
|
|
218
|
+
except Exception as e:
|
|
219
|
+
log_debug(f"Failed to initialize {codec_name} codec: {e}")
|
|
220
|
+
if out:
|
|
221
|
+
out.release()
|
|
222
|
+
out = None
|
|
223
|
+
|
|
224
|
+
if not out or not out.isOpened():
|
|
225
|
+
error_msg = "Failed to initialize video writer with any codec"
|
|
226
|
+
log_error(error_msg)
|
|
227
|
+
return ToolResult(content=error_msg)
|
|
228
|
+
|
|
229
|
+
start_time = time.time()
|
|
230
|
+
frame_count = 0
|
|
231
|
+
|
|
232
|
+
if self.show_preview:
|
|
233
|
+
log_info(f"Recording {duration}s video with live preview using {successful_codec} codec...")
|
|
234
|
+
else:
|
|
235
|
+
log_info(f"Recording {duration}s video using {successful_codec} codec...")
|
|
236
|
+
|
|
237
|
+
while True:
|
|
238
|
+
ret, frame = cap.read()
|
|
239
|
+
|
|
240
|
+
if not ret:
|
|
241
|
+
error_msg = "Failed to capture video frame"
|
|
242
|
+
log_error(error_msg)
|
|
243
|
+
return ToolResult(content=error_msg)
|
|
244
|
+
|
|
245
|
+
# Write the frame to the output file
|
|
246
|
+
out.write(frame)
|
|
247
|
+
frame_count += 1
|
|
248
|
+
|
|
249
|
+
# Show live preview if enabled
|
|
250
|
+
if self.show_preview:
|
|
251
|
+
# Add recording indicator
|
|
252
|
+
elapsed = time.time() - start_time
|
|
253
|
+
remaining = max(0, duration - elapsed)
|
|
254
|
+
|
|
255
|
+
# Draw recording info on frame
|
|
256
|
+
display_frame = frame.copy()
|
|
257
|
+
cv2.putText(
|
|
258
|
+
display_frame,
|
|
259
|
+
f"REC {remaining:.1f}s",
|
|
260
|
+
(10, 30),
|
|
261
|
+
cv2.FONT_HERSHEY_SIMPLEX,
|
|
262
|
+
1,
|
|
263
|
+
(0, 0, 255),
|
|
264
|
+
2,
|
|
265
|
+
)
|
|
266
|
+
cv2.circle(display_frame, (30, 60), 10, (0, 0, 255), -1) # Red dot
|
|
267
|
+
|
|
268
|
+
cv2.imshow(f"Recording Video - {remaining:.1f}s remaining", display_frame)
|
|
269
|
+
cv2.waitKey(1)
|
|
270
|
+
|
|
271
|
+
# Check if recording duration is reached
|
|
272
|
+
if time.time() - start_time >= duration:
|
|
273
|
+
break
|
|
274
|
+
|
|
275
|
+
# Release video writer
|
|
276
|
+
out.release()
|
|
277
|
+
|
|
278
|
+
# Verify the file was created and has content
|
|
279
|
+
temp_path = Path(temp_filepath)
|
|
280
|
+
if not temp_path.exists() or temp_path.stat().st_size == 0:
|
|
281
|
+
error_msg = "Video file was not created or is empty"
|
|
282
|
+
log_error(error_msg)
|
|
283
|
+
return ToolResult(content=error_msg)
|
|
284
|
+
|
|
285
|
+
# Read the video file and encode to base64
|
|
286
|
+
with open(temp_filepath, "rb") as video_file:
|
|
287
|
+
video_bytes = video_file.read()
|
|
288
|
+
|
|
289
|
+
# Clean up temporary file
|
|
290
|
+
os.unlink(temp_filepath)
|
|
291
|
+
|
|
292
|
+
media_id = str(uuid4())
|
|
293
|
+
|
|
294
|
+
# Create VideoArtifact with base64 encoded content
|
|
295
|
+
video_artifact = Video(
|
|
296
|
+
id=media_id,
|
|
297
|
+
content=video_bytes,
|
|
298
|
+
original_prompt=prompt,
|
|
299
|
+
mime_type="video/mp4",
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
actual_duration = time.time() - start_time
|
|
303
|
+
log_debug(
|
|
304
|
+
f"Successfully captured and attached video {media_id} ({actual_duration:.1f}s, {frame_count} frames)"
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
return ToolResult(
|
|
308
|
+
content=f"Video captured successfully and attached as artifact {media_id} ({actual_duration:.1f}s, {frame_count} frames, {successful_codec} codec)",
|
|
309
|
+
videos=[video_artifact],
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
finally:
|
|
313
|
+
if "cap" in locals():
|
|
314
|
+
cap.release()
|
|
315
|
+
cv2.destroyAllWindows()
|
|
316
|
+
log_debug("Video capture resources released")
|
|
317
|
+
|
|
318
|
+
except Exception as e:
|
|
319
|
+
error_msg = f"Error capturing video: {str(e)}"
|
|
320
|
+
log_error(error_msg)
|
|
321
|
+
return ToolResult(content=error_msg)
|