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,186 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from os import getenv
|
|
3
|
+
from textwrap import dedent
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
from agno.tools import Toolkit
|
|
7
|
+
from agno.utils.log import log_debug, log_error
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
from openai import OpenAI
|
|
11
|
+
except ImportError:
|
|
12
|
+
raise ImportError("`openai` not installed. Please install using `pip install openai`")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class MorphTools(Toolkit):
|
|
16
|
+
"""Tools for interacting with Morph's Fast Apply API for code editing"""
|
|
17
|
+
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
api_key: Optional[str] = None,
|
|
21
|
+
base_url: str = "https://api.morphllm.com/v1",
|
|
22
|
+
instructions: Optional[str] = None,
|
|
23
|
+
add_instructions: bool = True,
|
|
24
|
+
model: str = "morph-v3-large",
|
|
25
|
+
**kwargs,
|
|
26
|
+
):
|
|
27
|
+
"""Initialize Morph Fast Apply tools.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
api_key: Morph API key. If not provided, will look for MORPH_API_KEY environment variable.
|
|
31
|
+
base_url: The base URL for the Morph API.
|
|
32
|
+
model: The Morph model to use. Options:
|
|
33
|
+
- "morph-v3-fast" (4500+ tok/sec, 96% accuracy)
|
|
34
|
+
- "morph-v3-large" (2500+ tok/sec, 98% accuracy)
|
|
35
|
+
- "auto" (automatic selection)
|
|
36
|
+
**kwargs: Additional arguments to pass to Toolkit.
|
|
37
|
+
"""
|
|
38
|
+
# Set up instructions
|
|
39
|
+
if instructions is None:
|
|
40
|
+
self.instructions = self.DEFAULT_INSTRUCTIONS
|
|
41
|
+
else:
|
|
42
|
+
self.instructions = instructions
|
|
43
|
+
|
|
44
|
+
super().__init__(
|
|
45
|
+
name="morph_tools",
|
|
46
|
+
tools=[self.edit_file],
|
|
47
|
+
instructions=self.instructions,
|
|
48
|
+
add_instructions=add_instructions,
|
|
49
|
+
**kwargs,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
self.api_key = api_key or getenv("MORPH_API_KEY")
|
|
53
|
+
if not self.api_key:
|
|
54
|
+
raise ValueError("MORPH_API_KEY not set. Please set the MORPH_API_KEY environment variable.")
|
|
55
|
+
|
|
56
|
+
self.base_url = base_url
|
|
57
|
+
self.model = model
|
|
58
|
+
self._morph_client: Optional[OpenAI] = None
|
|
59
|
+
|
|
60
|
+
def _get_client(self):
|
|
61
|
+
"""Get or create the Morph OpenAI client."""
|
|
62
|
+
if self._morph_client is None:
|
|
63
|
+
self._morph_client = OpenAI(
|
|
64
|
+
api_key=self.api_key,
|
|
65
|
+
base_url=self.base_url,
|
|
66
|
+
)
|
|
67
|
+
return self._morph_client
|
|
68
|
+
|
|
69
|
+
def edit_file(
|
|
70
|
+
self,
|
|
71
|
+
target_file: str,
|
|
72
|
+
instructions: str,
|
|
73
|
+
code_edit: str,
|
|
74
|
+
original_code: Optional[str] = None,
|
|
75
|
+
) -> str:
|
|
76
|
+
"""
|
|
77
|
+
Apply code edits to a target file using Morph's Fast Apply API.
|
|
78
|
+
|
|
79
|
+
This function reads the specified file, sends its content along with
|
|
80
|
+
editing instructions and code edits to Morph's API, and writes the
|
|
81
|
+
resulting code back to the file. A backup of the original file is
|
|
82
|
+
created before writing changes.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
target_file (str): Path to the file to be edited.
|
|
86
|
+
instructions (str): High-level instructions describing the intended change.
|
|
87
|
+
code_edit (str): Specific code edit or change to apply.
|
|
88
|
+
original_code (Optional[str], optional): Original content of the file.
|
|
89
|
+
If not provided, the function reads from target_file.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
str: Result message indicating success or failure, and details about
|
|
93
|
+
the backup and any errors encountered.
|
|
94
|
+
"""
|
|
95
|
+
try:
|
|
96
|
+
# Always read the actual file content for backup purposes
|
|
97
|
+
actual_file_content = None
|
|
98
|
+
if os.path.exists(target_file):
|
|
99
|
+
try:
|
|
100
|
+
with open(target_file, "r", encoding="utf-8") as f:
|
|
101
|
+
actual_file_content = f.read()
|
|
102
|
+
except Exception as e:
|
|
103
|
+
return f"Error reading {target_file} for backup: {e}"
|
|
104
|
+
else:
|
|
105
|
+
return f"Error: File {target_file} does not exist."
|
|
106
|
+
|
|
107
|
+
# Use provided original_code or fall back to file content
|
|
108
|
+
code_to_process = original_code if original_code is not None else actual_file_content
|
|
109
|
+
|
|
110
|
+
# Format the message for Morph's Fast Apply API
|
|
111
|
+
content = f"<instruction>{instructions}</instruction>\n<code>{code_to_process}</code>\n<update>{code_edit}</update>"
|
|
112
|
+
|
|
113
|
+
log_debug(f"Input to Morph: {content}")
|
|
114
|
+
|
|
115
|
+
client = self._get_client()
|
|
116
|
+
|
|
117
|
+
response = client.chat.completions.create(
|
|
118
|
+
model=self.model,
|
|
119
|
+
messages=[
|
|
120
|
+
{
|
|
121
|
+
"role": "user",
|
|
122
|
+
"content": content,
|
|
123
|
+
}
|
|
124
|
+
],
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
if response.choices and response.choices[0].message.content:
|
|
128
|
+
final_code = response.choices[0].message.content
|
|
129
|
+
|
|
130
|
+
try:
|
|
131
|
+
backup_file = f"{target_file}.backup"
|
|
132
|
+
with open(backup_file, "w", encoding="utf-8") as f:
|
|
133
|
+
f.write(actual_file_content)
|
|
134
|
+
|
|
135
|
+
# Write the new code
|
|
136
|
+
with open(target_file, "w", encoding="utf-8") as f:
|
|
137
|
+
f.write(final_code)
|
|
138
|
+
return f"Successfully applied edit to {target_file} using Morph Fast Apply! Original content backed up as {backup_file}"
|
|
139
|
+
|
|
140
|
+
except Exception as e:
|
|
141
|
+
return f"Successfully applied edit but failed to write back to {target_file}: {e}"
|
|
142
|
+
|
|
143
|
+
else:
|
|
144
|
+
return f"Failed to apply edit to {target_file}: No response from Morph API"
|
|
145
|
+
|
|
146
|
+
except Exception as e:
|
|
147
|
+
log_error(f"Failed to apply edit using Morph Fast Apply: {e}")
|
|
148
|
+
return f"Failed to apply edit to {target_file}: {e}"
|
|
149
|
+
|
|
150
|
+
DEFAULT_INSTRUCTIONS = dedent("""\
|
|
151
|
+
You have access to Morph Fast Apply for ultra-fast code editing with 98% accuracy at 2500+ tokens/second.
|
|
152
|
+
|
|
153
|
+
## How to use the edit_file tool:
|
|
154
|
+
|
|
155
|
+
**Critical Requirements:**
|
|
156
|
+
1. **Instructions Parameter**: Generate clear first-person instructions describing what you're doing
|
|
157
|
+
- Example: "I am adding type hints to all functions and methods"
|
|
158
|
+
- Example: "I am refactoring the error handling to use try-catch blocks"
|
|
159
|
+
|
|
160
|
+
2. **Code Edit Parameter**: Specify ONLY the lines you want to change
|
|
161
|
+
- Use `# ... existing code ...` (or `// ... existing code ...` for JS/Java) to represent unchanged sections
|
|
162
|
+
- NEVER write out unchanged code in the code_edit parameter
|
|
163
|
+
- Include sufficient context around changes to resolve ambiguity
|
|
164
|
+
|
|
165
|
+
3. **Single Edit Call**: Make ALL edits to a file in a single edit_file call. The apply model can handle many distinct edits at once.
|
|
166
|
+
|
|
167
|
+
**Example Format:**
|
|
168
|
+
```
|
|
169
|
+
# ... existing code ...
|
|
170
|
+
def add(a: int, b: int) -> int:
|
|
171
|
+
\"\"\"Add two numbers together.\"\"\"
|
|
172
|
+
return a + b
|
|
173
|
+
# ... existing code ...
|
|
174
|
+
def multiply(x: int, y: int) -> int:
|
|
175
|
+
\"\"\"Multiply two numbers.\"\"\"
|
|
176
|
+
return x * y
|
|
177
|
+
# ... existing code ...
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**Important Guidelines:**
|
|
181
|
+
- Bias towards repeating as few lines as possible while conveying the change clearly
|
|
182
|
+
- Each edit should contain sufficient context of unchanged lines around the code you're editing
|
|
183
|
+
- DO NOT omit spans of pre-existing code without using the `# ... existing code ...` comment
|
|
184
|
+
- If deleting a section, provide context before and after to clearly indicate the deletion
|
|
185
|
+
- The tool automatically creates backup files before applying changes\
|
|
186
|
+
""")
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
from os import getenv
|
|
3
|
+
from typing import Optional
|
|
4
|
+
from uuid import uuid4
|
|
5
|
+
|
|
6
|
+
from agno.agent import Agent
|
|
7
|
+
from agno.media import Image
|
|
8
|
+
from agno.models.nebius import Nebius
|
|
9
|
+
from agno.tools import Toolkit
|
|
10
|
+
from agno.tools.function import ToolResult
|
|
11
|
+
from agno.utils.log import log_error, log_warning
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class NebiusTools(Toolkit):
|
|
15
|
+
"""Tools for interacting with Nebius Token Factory's text-to-image API"""
|
|
16
|
+
|
|
17
|
+
def __init__(
|
|
18
|
+
self,
|
|
19
|
+
api_key: Optional[str] = None,
|
|
20
|
+
base_url: str = "https://api.tokenfactory.nebius.com/v1",
|
|
21
|
+
image_model: str = "black-forest-labs/flux-schnell",
|
|
22
|
+
image_quality: Optional[str] = "standard",
|
|
23
|
+
image_size: Optional[str] = "1024x1024",
|
|
24
|
+
image_style: Optional[str] = None,
|
|
25
|
+
enable_generate_image: bool = True,
|
|
26
|
+
all: bool = False,
|
|
27
|
+
**kwargs,
|
|
28
|
+
):
|
|
29
|
+
"""Initialize Nebius Token Factory text-to-image tools.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
api_key: Nebius API key. If not provided, will look for NEBIUS_API_KEY environment variable.
|
|
33
|
+
base_url: The base URL for the Nebius Token Factory API. This should be configured according to Nebius's documentation.
|
|
34
|
+
image_model: The model to use for generation. Options include:
|
|
35
|
+
- "black-forest-labs/flux-schnell" (fastest)
|
|
36
|
+
- "black-forest-labs/flux-dev" (balanced)
|
|
37
|
+
- "stability-ai/sdxl" (highest quality)
|
|
38
|
+
image_quality: Image quality. Options: "standard", "hd".
|
|
39
|
+
image_size: Image size in format "WIDTHxHEIGHT". Max supported: 2000x2000.
|
|
40
|
+
image_style: Optional style preset to apply.
|
|
41
|
+
enable_generate_image: Enable image generation functionality.
|
|
42
|
+
all: Enable all functions.
|
|
43
|
+
**kwargs: Additional arguments to pass to Toolkit.
|
|
44
|
+
"""
|
|
45
|
+
tools = []
|
|
46
|
+
if all or enable_generate_image:
|
|
47
|
+
tools.append(self.generate_image)
|
|
48
|
+
|
|
49
|
+
super().__init__(name="nebius_tools", tools=tools, **kwargs)
|
|
50
|
+
|
|
51
|
+
self.api_key = api_key or getenv("NEBIUS_API_KEY")
|
|
52
|
+
if not self.api_key:
|
|
53
|
+
raise ValueError("NEBIUS_API_KEY not set. Please set the NEBIUS_API_KEY environment variable.")
|
|
54
|
+
|
|
55
|
+
self.base_url = base_url
|
|
56
|
+
self.image_model = image_model
|
|
57
|
+
self.image_quality = image_quality
|
|
58
|
+
self.image_size = image_size
|
|
59
|
+
self.image_style = image_style
|
|
60
|
+
self._nebius_client: Optional[Nebius] = None
|
|
61
|
+
|
|
62
|
+
def _get_client(self):
|
|
63
|
+
if self._nebius_client is None:
|
|
64
|
+
self._nebius_client = Nebius(api_key=self.api_key, base_url=self.base_url, id=self.image_model).get_client() # type: ignore
|
|
65
|
+
return self._nebius_client
|
|
66
|
+
|
|
67
|
+
def generate_image(
|
|
68
|
+
self,
|
|
69
|
+
agent: Agent,
|
|
70
|
+
prompt: str,
|
|
71
|
+
) -> ToolResult:
|
|
72
|
+
"""Generate images based on a text prompt using Nebius Token Factory.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
agent: The agent instance for adding images
|
|
76
|
+
prompt: The text prompt to generate images from.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
ToolResult: A ToolResult containing the generated image or error message.
|
|
80
|
+
"""
|
|
81
|
+
try:
|
|
82
|
+
extra_params = {
|
|
83
|
+
"size": self.image_size,
|
|
84
|
+
"quality": self.image_quality,
|
|
85
|
+
"style": self.image_style,
|
|
86
|
+
}
|
|
87
|
+
extra_params = {k: v for k, v in extra_params.items() if v is not None}
|
|
88
|
+
|
|
89
|
+
client = self._get_client()
|
|
90
|
+
|
|
91
|
+
response = client.images.generate(
|
|
92
|
+
model=self.image_model,
|
|
93
|
+
prompt=prompt,
|
|
94
|
+
response_format="b64_json",
|
|
95
|
+
**extra_params,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
data = None
|
|
99
|
+
if hasattr(response, "data") and response.data:
|
|
100
|
+
data = response.data[0]
|
|
101
|
+
if data is None:
|
|
102
|
+
log_warning("Nebius API did not return any data.")
|
|
103
|
+
return ToolResult(content="Failed to generate image: No data received from API.")
|
|
104
|
+
|
|
105
|
+
if hasattr(data, "b64_json") and data.b64_json:
|
|
106
|
+
image_base64 = data.b64_json
|
|
107
|
+
image_content_bytes = base64.b64decode(image_base64)
|
|
108
|
+
media_id = str(uuid4())
|
|
109
|
+
|
|
110
|
+
# Create ImageArtifact with raw bytes
|
|
111
|
+
image_artifact = Image(
|
|
112
|
+
id=media_id, content=image_content_bytes, mime_type="image/png", original_prompt=prompt
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
return ToolResult(
|
|
116
|
+
content="Image generated successfully.",
|
|
117
|
+
images=[image_artifact],
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
return ToolResult(content="Failed to generate image: No content received from API.")
|
|
121
|
+
|
|
122
|
+
except Exception as e:
|
|
123
|
+
log_error(f"Failed to generate image using {self.image_model}: {e}")
|
|
124
|
+
return ToolResult(content=f"Failed to generate image: {e}")
|
agno/tools/models_labs.py
CHANGED
|
@@ -1,124 +1,205 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import time
|
|
3
3
|
from os import getenv
|
|
4
|
-
from typing import Optional
|
|
4
|
+
from typing import Any, Dict, List, Optional, Union
|
|
5
5
|
from uuid import uuid4
|
|
6
6
|
|
|
7
|
-
from agno.
|
|
8
|
-
from agno.media import ImageArtifact, VideoArtifact
|
|
7
|
+
from agno.media import Audio, Image, Video
|
|
9
8
|
from agno.models.response import FileType
|
|
10
9
|
from agno.tools import Toolkit
|
|
11
|
-
from agno.
|
|
10
|
+
from agno.tools.function import ToolResult
|
|
11
|
+
from agno.utils.log import log_debug, log_info, logger
|
|
12
12
|
|
|
13
13
|
try:
|
|
14
14
|
import requests
|
|
15
|
+
from requests.exceptions import RequestException
|
|
15
16
|
except ImportError:
|
|
16
17
|
raise ImportError("`requests` not installed. Please install using `pip install requests`")
|
|
17
18
|
|
|
19
|
+
MODELS_LAB_URLS = {
|
|
20
|
+
"MP4": "https://modelslab.com/api/v6/video/text2video",
|
|
21
|
+
"MP3": "https://modelslab.com/api/v6/voice/music_gen",
|
|
22
|
+
"GIF": "https://modelslab.com/api/v6/video/text2video",
|
|
23
|
+
"WAV": "https://modelslab.com/api/v6/voice/sfx",
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
MODELS_LAB_FETCH_URLS = {
|
|
27
|
+
"MP4": "https://modelslab.com/api/v6/video/fetch",
|
|
28
|
+
"MP3": "https://modelslab.com/api/v6/voice/fetch",
|
|
29
|
+
"GIF": "https://modelslab.com/api/v6/video/fetch",
|
|
30
|
+
"WAV": "https://modelslab.com/api/v6/voice/fetch",
|
|
31
|
+
}
|
|
32
|
+
|
|
18
33
|
|
|
19
34
|
class ModelsLabTools(Toolkit):
|
|
20
35
|
def __init__(
|
|
21
36
|
self,
|
|
22
37
|
api_key: Optional[str] = None,
|
|
23
|
-
url: str = "https://modelslab.com/api/v6/video/text2video",
|
|
24
|
-
fetch_url: str = "https://modelslab.com/api/v6/video/fetch",
|
|
25
|
-
# Whether to wait for the video to be ready
|
|
26
38
|
wait_for_completion: bool = False,
|
|
27
|
-
# Time to add to the ETA to account for the time it takes to fetch the video
|
|
28
39
|
add_to_eta: int = 15,
|
|
29
|
-
# Maximum time to wait for the video to be ready
|
|
30
40
|
max_wait_time: int = 60,
|
|
31
41
|
file_type: FileType = FileType.MP4,
|
|
42
|
+
**kwargs,
|
|
32
43
|
):
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
self.
|
|
36
|
-
self.fetch_url = fetch_url
|
|
44
|
+
file_type_str = file_type.value.upper()
|
|
45
|
+
self.url = MODELS_LAB_URLS[file_type_str]
|
|
46
|
+
self.fetch_url = MODELS_LAB_FETCH_URLS[file_type_str]
|
|
37
47
|
self.wait_for_completion = wait_for_completion
|
|
38
48
|
self.add_to_eta = add_to_eta
|
|
39
49
|
self.max_wait_time = max_wait_time
|
|
40
50
|
self.file_type = file_type
|
|
41
51
|
self.api_key = api_key or getenv("MODELS_LAB_API_KEY")
|
|
52
|
+
|
|
42
53
|
if not self.api_key:
|
|
43
54
|
logger.error("MODELS_LAB_API_KEY not set. Please set the MODELS_LAB_API_KEY environment variable.")
|
|
44
55
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
""
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
tools: List[Any] = []
|
|
57
|
+
tools.append(self.generate_media)
|
|
58
|
+
|
|
59
|
+
super().__init__(name="models_labs", tools=tools, **kwargs)
|
|
60
|
+
|
|
61
|
+
def _create_payload(self, prompt: str) -> Dict[str, Any]:
|
|
62
|
+
"""Create payload based on file type."""
|
|
63
|
+
base_payload: Dict[str, Any] = {
|
|
64
|
+
"key": self.api_key,
|
|
65
|
+
"prompt": prompt,
|
|
66
|
+
"webhook": None,
|
|
67
|
+
"track_id": None,
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if self.file_type in [FileType.MP4, FileType.GIF]:
|
|
71
|
+
video_template = {
|
|
72
|
+
"height": 512,
|
|
73
|
+
"width": 512,
|
|
74
|
+
"num_frames": 25,
|
|
75
|
+
"negative_prompt": "low quality",
|
|
76
|
+
"model_id": "cogvideox",
|
|
77
|
+
"instant_response": False,
|
|
78
|
+
"output_type": self.file_type.value,
|
|
79
|
+
}
|
|
80
|
+
base_payload |= video_template # Use |= instead of update()
|
|
81
|
+
elif self.file_type == FileType.WAV:
|
|
82
|
+
sfx_template = {
|
|
83
|
+
"duration": 10,
|
|
84
|
+
"output_format": "wav",
|
|
85
|
+
"temp": False,
|
|
86
|
+
}
|
|
87
|
+
base_payload |= sfx_template # Use |= instead of update()
|
|
88
|
+
else:
|
|
89
|
+
audio_template = {
|
|
90
|
+
"base64": False,
|
|
91
|
+
"temp": False,
|
|
92
|
+
}
|
|
93
|
+
base_payload |= audio_template # Use |= instead of update()
|
|
94
|
+
|
|
95
|
+
return base_payload
|
|
96
|
+
|
|
97
|
+
def _create_media_artifacts(self, media_id: str, media_url: str, eta: Optional[str] = None) -> Dict[str, List]:
|
|
98
|
+
"""Create appropriate media artifacts based on file type."""
|
|
99
|
+
artifacts: Dict[str, List[Union[Image, Video, Audio]]] = {
|
|
100
|
+
"images": [],
|
|
101
|
+
"videos": [],
|
|
102
|
+
"audios": [],
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if self.file_type == FileType.MP4:
|
|
106
|
+
video_artifact = Video(id=str(media_id), url=media_url, eta=str(eta))
|
|
107
|
+
artifacts["videos"].append(video_artifact)
|
|
108
|
+
elif self.file_type == FileType.GIF:
|
|
109
|
+
image_artifact = Image(id=str(media_id), url=media_url)
|
|
110
|
+
artifacts["images"].append(image_artifact)
|
|
111
|
+
elif self.file_type in [FileType.MP3, FileType.WAV]:
|
|
112
|
+
audio_artifact = Audio(id=str(media_id), url=media_url)
|
|
113
|
+
artifacts["audios"].append(audio_artifact)
|
|
114
|
+
|
|
115
|
+
return artifacts
|
|
116
|
+
|
|
117
|
+
def _wait_for_media(self, media_id: str, eta: int) -> bool:
|
|
118
|
+
"""Wait for media generation to complete."""
|
|
119
|
+
time_to_wait = min(eta + self.add_to_eta, self.max_wait_time)
|
|
120
|
+
log_info(f"Waiting for {time_to_wait} seconds for {self.file_type.value} to be ready")
|
|
121
|
+
|
|
122
|
+
for seconds_waited in range(time_to_wait):
|
|
123
|
+
try:
|
|
124
|
+
fetch_response = requests.post(
|
|
125
|
+
f"{self.fetch_url}/{media_id}",
|
|
126
|
+
json={"key": self.api_key},
|
|
127
|
+
headers={"Content-Type": "application/json"},
|
|
128
|
+
)
|
|
129
|
+
fetch_result = fetch_response.json()
|
|
130
|
+
|
|
131
|
+
if fetch_result.get("status") == "success":
|
|
132
|
+
return True
|
|
133
|
+
|
|
134
|
+
time.sleep(1)
|
|
135
|
+
|
|
136
|
+
except RequestException as e:
|
|
137
|
+
logger.warning(f"Error during fetch attempt {seconds_waited}: {e}")
|
|
138
|
+
|
|
139
|
+
return False
|
|
140
|
+
|
|
141
|
+
def generate_media(self, prompt: str) -> ToolResult:
|
|
142
|
+
"""Generate media (video, image, or audio) given a prompt."""
|
|
56
143
|
if not self.api_key:
|
|
57
|
-
return "Please set the MODELS_LAB_API_KEY"
|
|
144
|
+
return ToolResult(content="Please set the MODELS_LAB_API_KEY")
|
|
58
145
|
|
|
59
146
|
try:
|
|
60
|
-
payload = json.dumps(
|
|
61
|
-
{
|
|
62
|
-
"key": self.api_key,
|
|
63
|
-
"prompt": prompt,
|
|
64
|
-
"height": 512,
|
|
65
|
-
"width": 512,
|
|
66
|
-
"num_frames": 25,
|
|
67
|
-
"webhook": None,
|
|
68
|
-
"output_type": self.file_type.value,
|
|
69
|
-
"track_id": None,
|
|
70
|
-
"negative_prompt": "low quality",
|
|
71
|
-
"model_id": "cogvideox",
|
|
72
|
-
"instant_response": False,
|
|
73
|
-
}
|
|
74
|
-
)
|
|
75
|
-
|
|
147
|
+
payload = json.dumps(self._create_payload(prompt))
|
|
76
148
|
headers = {"Content-Type": "application/json"}
|
|
77
|
-
|
|
78
|
-
|
|
149
|
+
|
|
150
|
+
log_debug(f"Generating {self.file_type.value} for prompt: {prompt}")
|
|
151
|
+
response = requests.post(self.url, data=payload, headers=headers)
|
|
79
152
|
response.raise_for_status()
|
|
80
153
|
|
|
81
154
|
result = response.json()
|
|
82
|
-
if "error" in result:
|
|
83
|
-
logger.error(f"Failed to generate video: {result['error']}")
|
|
84
|
-
return f"Error: {result['error']}"
|
|
85
|
-
|
|
86
|
-
eta = result["eta"]
|
|
87
|
-
url_links = result["future_links"]
|
|
88
|
-
logger.info(f"Media will be ready in {eta} seconds")
|
|
89
|
-
logger.info(f"Media URLs: {url_links}")
|
|
90
155
|
|
|
91
|
-
|
|
156
|
+
status = result.get("status")
|
|
157
|
+
if status == "error":
|
|
158
|
+
logger.error(f"Error in response: {result.get('message')}")
|
|
159
|
+
return ToolResult(content=f"Error: {result.get('message')}")
|
|
92
160
|
|
|
93
|
-
|
|
161
|
+
if "error" in result:
|
|
162
|
+
error_msg = f"Failed to generate {self.file_type.value}: {result['error']}"
|
|
163
|
+
logger.error(error_msg)
|
|
164
|
+
return ToolResult(content=f"Error: {result['error']}")
|
|
165
|
+
|
|
166
|
+
eta = result.get("eta")
|
|
167
|
+
media_id = str(uuid4())
|
|
168
|
+
|
|
169
|
+
# Collect all media artifacts
|
|
170
|
+
all_images = []
|
|
171
|
+
all_videos = []
|
|
172
|
+
all_audios = []
|
|
173
|
+
|
|
174
|
+
if self.file_type == FileType.WAV:
|
|
175
|
+
url_links = result.get("output", [])
|
|
176
|
+
else:
|
|
177
|
+
url_links = result.get("future_links")
|
|
94
178
|
for media_url in url_links:
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
video_ready = True
|
|
119
|
-
break
|
|
120
|
-
|
|
121
|
-
return f"Video has been generated successfully and will be ready in {eta} seconds"
|
|
179
|
+
artifacts = self._create_media_artifacts(media_id, media_url, str(eta))
|
|
180
|
+
all_images.extend(artifacts["images"])
|
|
181
|
+
all_videos.extend(artifacts["videos"])
|
|
182
|
+
all_audios.extend(artifacts["audios"])
|
|
183
|
+
|
|
184
|
+
if self.wait_for_completion and isinstance(eta, int):
|
|
185
|
+
if self._wait_for_media(media_id, eta):
|
|
186
|
+
log_info("Media generation completed successfully")
|
|
187
|
+
else:
|
|
188
|
+
logger.warning("Media generation timed out")
|
|
189
|
+
|
|
190
|
+
# Return ToolResult with appropriate media artifacts
|
|
191
|
+
return ToolResult(
|
|
192
|
+
content=f"{self.file_type.value.capitalize()} has been generated successfully and will be ready in {eta} seconds",
|
|
193
|
+
images=all_images if all_images else None,
|
|
194
|
+
videos=all_videos if all_videos else None,
|
|
195
|
+
audios=all_audios if all_audios else None,
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
except RequestException as e:
|
|
199
|
+
error_msg = f"Network error while generating {self.file_type.value}: {e}"
|
|
200
|
+
logger.error(error_msg)
|
|
201
|
+
return ToolResult(content=f"Error: {error_msg}")
|
|
122
202
|
except Exception as e:
|
|
123
|
-
|
|
124
|
-
|
|
203
|
+
error_msg = f"Unexpected error while generating {self.file_type.value}: {e}"
|
|
204
|
+
logger.error(error_msg)
|
|
205
|
+
return ToolResult(content=f"Error: {error_msg}")
|
agno/tools/moviepy_video.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
from typing import Dict, List, Optional
|
|
1
|
+
from typing import Any, Dict, List, Optional
|
|
2
2
|
|
|
3
3
|
from agno.tools import Toolkit
|
|
4
|
-
from agno.utils.log import logger
|
|
4
|
+
from agno.utils.log import log_debug, log_info, logger
|
|
5
5
|
|
|
6
6
|
try:
|
|
7
7
|
from moviepy import ColorClip, CompositeVideoClip, TextClip, VideoFileClip # type: ignore
|
|
@@ -14,18 +14,21 @@ class MoviePyVideoTools(Toolkit):
|
|
|
14
14
|
|
|
15
15
|
def __init__(
|
|
16
16
|
self,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
enable_process_video: bool = True,
|
|
18
|
+
enable_generate_captions: bool = True,
|
|
19
|
+
enable_embed_captions: bool = True,
|
|
20
|
+
all: bool = False,
|
|
21
|
+
**kwargs,
|
|
20
22
|
):
|
|
21
|
-
|
|
23
|
+
tools: List[Any] = []
|
|
24
|
+
if enable_process_video or all:
|
|
25
|
+
tools.append(self.extract_audio)
|
|
26
|
+
if enable_generate_captions or all:
|
|
27
|
+
tools.append(self.create_srt)
|
|
28
|
+
if enable_embed_captions or all:
|
|
29
|
+
tools.append(self.embed_captions)
|
|
22
30
|
|
|
23
|
-
|
|
24
|
-
self.register(self.extract_audio)
|
|
25
|
-
if generate_captions:
|
|
26
|
-
self.register(self.create_srt)
|
|
27
|
-
if embed_captions:
|
|
28
|
-
self.register(self.embed_captions)
|
|
31
|
+
super().__init__(name="video_tools", tools=tools, **kwargs)
|
|
29
32
|
|
|
30
33
|
def split_text_into_lines(self, words: List[Dict]) -> List[Dict]:
|
|
31
34
|
"""Split transcribed words into lines based on duration and length constraints
|
|
@@ -227,9 +230,10 @@ class MoviePyVideoTools(Toolkit):
|
|
|
227
230
|
str: Path to the extracted audio file
|
|
228
231
|
"""
|
|
229
232
|
try:
|
|
233
|
+
log_debug(f"Extracting audio from {video_path}")
|
|
230
234
|
video = VideoFileClip(video_path)
|
|
231
235
|
video.audio.write_audiofile(output_path)
|
|
232
|
-
|
|
236
|
+
log_info(f"Audio extracted to {output_path}")
|
|
233
237
|
return output_path
|
|
234
238
|
except Exception as e:
|
|
235
239
|
logger.error(f"Failed to extract audio: {str(e)}")
|
|
@@ -244,6 +248,7 @@ class MoviePyVideoTools(Toolkit):
|
|
|
244
248
|
str: Path to the created SRT file, or error message if failed
|
|
245
249
|
"""
|
|
246
250
|
try:
|
|
251
|
+
log_debug(f"Creating SRT file at {output_path}")
|
|
247
252
|
# Since we're getting SRT format from Whisper API now,
|
|
248
253
|
# we can just write it directly to file
|
|
249
254
|
with open(output_path, "w", encoding="utf-8") as f:
|