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,502 @@
|
|
|
1
|
+
from collections.abc import AsyncIterator
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from os import getenv
|
|
4
|
+
from typing import Any, Dict, Iterator, List, Optional, Type, Union
|
|
5
|
+
|
|
6
|
+
import httpx
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
|
|
9
|
+
from agno.exceptions import ModelProviderError
|
|
10
|
+
from agno.models.base import Model
|
|
11
|
+
from agno.models.message import Message
|
|
12
|
+
from agno.models.metrics import Metrics
|
|
13
|
+
from agno.models.response import ModelResponse
|
|
14
|
+
from agno.run.agent import RunOutput
|
|
15
|
+
from agno.utils.http import get_default_async_client, get_default_sync_client
|
|
16
|
+
from agno.utils.log import log_debug, log_error, log_warning
|
|
17
|
+
from agno.utils.models.llama import format_message
|
|
18
|
+
|
|
19
|
+
try:
|
|
20
|
+
from llama_api_client import AsyncLlamaAPIClient, LlamaAPIClient
|
|
21
|
+
from llama_api_client.types.create_chat_completion_response import CreateChatCompletionResponse, Metric
|
|
22
|
+
from llama_api_client.types.create_chat_completion_response_stream_chunk import (
|
|
23
|
+
CreateChatCompletionResponseStreamChunk,
|
|
24
|
+
EventDeltaTextDelta,
|
|
25
|
+
EventDeltaToolCallDelta,
|
|
26
|
+
EventDeltaToolCallDeltaFunction,
|
|
27
|
+
EventMetric,
|
|
28
|
+
)
|
|
29
|
+
from llama_api_client.types.message_text_content_item import MessageTextContentItem
|
|
30
|
+
except ImportError:
|
|
31
|
+
raise ImportError("`llama-api-client` not installed. Please install using `pip install llama-api-client`")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass
|
|
35
|
+
class Llama(Model):
|
|
36
|
+
"""
|
|
37
|
+
A class for interacting with Llama models using the Llama API using the Llama SDK.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
id: str = "Llama-4-Maverick-17B-128E-Instruct-FP8"
|
|
41
|
+
name: str = "Llama"
|
|
42
|
+
provider: str = "Llama"
|
|
43
|
+
|
|
44
|
+
supports_native_structured_outputs: bool = False
|
|
45
|
+
supports_json_schema_outputs: bool = True
|
|
46
|
+
|
|
47
|
+
# Request parameters
|
|
48
|
+
max_completion_tokens: Optional[int] = None
|
|
49
|
+
repetition_penalty: Optional[float] = None
|
|
50
|
+
temperature: Optional[float] = None
|
|
51
|
+
top_p: Optional[float] = None
|
|
52
|
+
top_k: Optional[int] = None
|
|
53
|
+
extra_headers: Optional[Any] = None
|
|
54
|
+
extra_query: Optional[Any] = None
|
|
55
|
+
extra_body: Optional[Any] = None
|
|
56
|
+
request_params: Optional[Dict[str, Any]] = None
|
|
57
|
+
|
|
58
|
+
# Client parameters
|
|
59
|
+
api_key: Optional[str] = None
|
|
60
|
+
base_url: Optional[Union[str, httpx.URL]] = None
|
|
61
|
+
timeout: Optional[float] = None
|
|
62
|
+
max_retries: Optional[int] = None
|
|
63
|
+
default_headers: Optional[Any] = None
|
|
64
|
+
default_query: Optional[Any] = None
|
|
65
|
+
http_client: Optional[Union[httpx.Client, httpx.AsyncClient]] = None
|
|
66
|
+
client_params: Optional[Dict[str, Any]] = None
|
|
67
|
+
|
|
68
|
+
# OpenAI clients
|
|
69
|
+
client: Optional[LlamaAPIClient] = None
|
|
70
|
+
async_client: Optional[AsyncLlamaAPIClient] = None
|
|
71
|
+
|
|
72
|
+
def _get_client_params(self) -> Dict[str, Any]:
|
|
73
|
+
# Fetch API key from env if not already set
|
|
74
|
+
if not self.api_key:
|
|
75
|
+
self.api_key = getenv("LLAMA_API_KEY")
|
|
76
|
+
if not self.api_key:
|
|
77
|
+
log_error("LLAMA_API_KEY not set. Please set the LLAMA_API_KEY environment variable.")
|
|
78
|
+
|
|
79
|
+
# Define base client params
|
|
80
|
+
base_params = {
|
|
81
|
+
"api_key": self.api_key,
|
|
82
|
+
"base_url": self.base_url,
|
|
83
|
+
"timeout": self.timeout,
|
|
84
|
+
"max_retries": self.max_retries,
|
|
85
|
+
"default_headers": self.default_headers,
|
|
86
|
+
"default_query": self.default_query,
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
# Create client_params dict with non-None values
|
|
90
|
+
client_params = {k: v for k, v in base_params.items() if v is not None}
|
|
91
|
+
|
|
92
|
+
# Add additional client params if provided
|
|
93
|
+
if self.client_params:
|
|
94
|
+
client_params.update(self.client_params)
|
|
95
|
+
return client_params
|
|
96
|
+
|
|
97
|
+
def get_client(self) -> LlamaAPIClient:
|
|
98
|
+
"""
|
|
99
|
+
Returns a Llama client.
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
LlamaAPIClient: An instance of the Llama client.
|
|
103
|
+
"""
|
|
104
|
+
if self.client and not self.client.is_closed():
|
|
105
|
+
return self.client
|
|
106
|
+
|
|
107
|
+
client_params: Dict[str, Any] = self._get_client_params()
|
|
108
|
+
if self.http_client:
|
|
109
|
+
if isinstance(self.http_client, httpx.Client):
|
|
110
|
+
client_params["http_client"] = self.http_client
|
|
111
|
+
else:
|
|
112
|
+
log_warning("http_client is not an instance of httpx.Client. Using default global httpx.Client.")
|
|
113
|
+
# Use global sync client when user http_client is invalid
|
|
114
|
+
client_params["http_client"] = get_default_sync_client()
|
|
115
|
+
else:
|
|
116
|
+
# Use global sync client when no custom http_client is provided
|
|
117
|
+
client_params["http_client"] = get_default_sync_client()
|
|
118
|
+
self.client = LlamaAPIClient(**client_params)
|
|
119
|
+
return self.client
|
|
120
|
+
|
|
121
|
+
def get_async_client(self) -> AsyncLlamaAPIClient:
|
|
122
|
+
"""
|
|
123
|
+
Returns an asynchronous Llama client.
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
AsyncLlamaAPIClient: An instance of the asynchronous Llama client.
|
|
127
|
+
"""
|
|
128
|
+
if self.async_client and not self.async_client.is_closed():
|
|
129
|
+
return self.async_client
|
|
130
|
+
|
|
131
|
+
client_params: Dict[str, Any] = self._get_client_params()
|
|
132
|
+
if self.http_client:
|
|
133
|
+
if isinstance(self.http_client, httpx.AsyncClient):
|
|
134
|
+
client_params["http_client"] = self.http_client
|
|
135
|
+
else:
|
|
136
|
+
log_warning(
|
|
137
|
+
"http_client is not an instance of httpx.AsyncClient. Using default global httpx.AsyncClient."
|
|
138
|
+
)
|
|
139
|
+
# Use global async client when user http_client is invalid
|
|
140
|
+
client_params["http_client"] = get_default_async_client()
|
|
141
|
+
else:
|
|
142
|
+
# Use global async client when no custom http_client is provided
|
|
143
|
+
client_params["http_client"] = get_default_async_client()
|
|
144
|
+
|
|
145
|
+
# Create and cache the client
|
|
146
|
+
self.async_client = AsyncLlamaAPIClient(**client_params)
|
|
147
|
+
return self.async_client
|
|
148
|
+
|
|
149
|
+
def get_request_params(
|
|
150
|
+
self,
|
|
151
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
152
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
153
|
+
) -> Dict[str, Any]:
|
|
154
|
+
"""
|
|
155
|
+
Returns keyword arguments for API requests.
|
|
156
|
+
"""
|
|
157
|
+
# Define base request parameters
|
|
158
|
+
base_params = {
|
|
159
|
+
"max_completion_tokens": self.max_completion_tokens,
|
|
160
|
+
"repetition_penalty": self.repetition_penalty,
|
|
161
|
+
"temperature": self.temperature,
|
|
162
|
+
"top_p": self.top_p,
|
|
163
|
+
"top_k": self.top_k,
|
|
164
|
+
"extra_headers": self.extra_headers,
|
|
165
|
+
"extra_query": self.extra_query,
|
|
166
|
+
"extra_body": self.extra_body,
|
|
167
|
+
"request_params": self.request_params,
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
# Filter out None values
|
|
171
|
+
request_params = {k: v for k, v in base_params.items() if v is not None}
|
|
172
|
+
|
|
173
|
+
# Add tools
|
|
174
|
+
if tools is not None and len(tools) > 0:
|
|
175
|
+
request_params["tools"] = tools
|
|
176
|
+
|
|
177
|
+
if response_format is not None:
|
|
178
|
+
request_params["response_format"] = response_format
|
|
179
|
+
|
|
180
|
+
# Add additional request params if provided
|
|
181
|
+
if self.request_params:
|
|
182
|
+
request_params.update(self.request_params)
|
|
183
|
+
|
|
184
|
+
if request_params:
|
|
185
|
+
log_debug(f"Calling {self.provider} with request parameters: {request_params}", log_level=2)
|
|
186
|
+
return request_params
|
|
187
|
+
|
|
188
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
189
|
+
"""
|
|
190
|
+
Convert the model to a dictionary.
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
Dict[str, Any]: The dictionary representation of the model.
|
|
194
|
+
"""
|
|
195
|
+
model_dict = super().to_dict()
|
|
196
|
+
model_dict.update(
|
|
197
|
+
{
|
|
198
|
+
"max_completion_tokens": self.max_completion_tokens,
|
|
199
|
+
"repetition_penalty": self.repetition_penalty,
|
|
200
|
+
"temperature": self.temperature,
|
|
201
|
+
"top_p": self.top_p,
|
|
202
|
+
"top_k": self.top_k,
|
|
203
|
+
"extra_headers": self.extra_headers,
|
|
204
|
+
"extra_query": self.extra_query,
|
|
205
|
+
"extra_body": self.extra_body,
|
|
206
|
+
"request_params": self.request_params,
|
|
207
|
+
}
|
|
208
|
+
)
|
|
209
|
+
cleaned_dict = {k: v for k, v in model_dict.items() if v is not None}
|
|
210
|
+
return cleaned_dict
|
|
211
|
+
|
|
212
|
+
def invoke(
|
|
213
|
+
self,
|
|
214
|
+
messages: List[Message],
|
|
215
|
+
assistant_message: Message,
|
|
216
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
217
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
218
|
+
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
219
|
+
run_response: Optional[RunOutput] = None,
|
|
220
|
+
compress_tool_results: bool = False,
|
|
221
|
+
) -> ModelResponse:
|
|
222
|
+
"""
|
|
223
|
+
Send a chat completion request to the Llama API.
|
|
224
|
+
"""
|
|
225
|
+
assistant_message.metrics.start_timer()
|
|
226
|
+
|
|
227
|
+
provider_response = self.get_client().chat.completions.create(
|
|
228
|
+
model=self.id,
|
|
229
|
+
messages=[
|
|
230
|
+
format_message(m, tool_calls=bool(tools), compress_tool_results=compress_tool_results) # type: ignore
|
|
231
|
+
for m in messages
|
|
232
|
+
],
|
|
233
|
+
**self.get_request_params(tools=tools, response_format=response_format),
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
assistant_message.metrics.stop_timer()
|
|
237
|
+
|
|
238
|
+
model_response = self._parse_provider_response(provider_response, response_format=response_format)
|
|
239
|
+
return model_response
|
|
240
|
+
|
|
241
|
+
async def ainvoke(
|
|
242
|
+
self,
|
|
243
|
+
messages: List[Message],
|
|
244
|
+
assistant_message: Message,
|
|
245
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
246
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
247
|
+
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
248
|
+
run_response: Optional[RunOutput] = None,
|
|
249
|
+
compress_tool_results: bool = False,
|
|
250
|
+
) -> ModelResponse:
|
|
251
|
+
"""
|
|
252
|
+
Sends an asynchronous chat completion request to the Llama API.
|
|
253
|
+
"""
|
|
254
|
+
if run_response and run_response.metrics:
|
|
255
|
+
run_response.metrics.set_time_to_first_token()
|
|
256
|
+
|
|
257
|
+
assistant_message.metrics.start_timer()
|
|
258
|
+
|
|
259
|
+
provider_response = await self.get_async_client().chat.completions.create(
|
|
260
|
+
model=self.id,
|
|
261
|
+
messages=[
|
|
262
|
+
format_message(m, tool_calls=bool(tools), compress_tool_results=compress_tool_results) # type: ignore
|
|
263
|
+
for m in messages
|
|
264
|
+
],
|
|
265
|
+
**self.get_request_params(tools=tools, response_format=response_format),
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
assistant_message.metrics.stop_timer()
|
|
269
|
+
|
|
270
|
+
model_response = self._parse_provider_response(provider_response, response_format=response_format)
|
|
271
|
+
return model_response
|
|
272
|
+
|
|
273
|
+
def invoke_stream(
|
|
274
|
+
self,
|
|
275
|
+
messages: List[Message],
|
|
276
|
+
assistant_message: Message,
|
|
277
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
278
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
279
|
+
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
280
|
+
run_response: Optional[RunOutput] = None,
|
|
281
|
+
compress_tool_results: bool = False,
|
|
282
|
+
) -> Iterator[ModelResponse]:
|
|
283
|
+
"""
|
|
284
|
+
Send a streaming chat completion request to the Llama API.
|
|
285
|
+
"""
|
|
286
|
+
if run_response and run_response.metrics:
|
|
287
|
+
run_response.metrics.set_time_to_first_token()
|
|
288
|
+
|
|
289
|
+
try:
|
|
290
|
+
assistant_message.metrics.start_timer()
|
|
291
|
+
|
|
292
|
+
for chunk in self.get_client().chat.completions.create(
|
|
293
|
+
model=self.id,
|
|
294
|
+
messages=[
|
|
295
|
+
format_message(m, tool_calls=bool(tools), compress_tool_results=compress_tool_results) # type: ignore
|
|
296
|
+
for m in messages
|
|
297
|
+
],
|
|
298
|
+
stream=True,
|
|
299
|
+
**self.get_request_params(tools=tools, response_format=response_format),
|
|
300
|
+
):
|
|
301
|
+
yield self._parse_provider_response_delta(chunk) # type: ignore
|
|
302
|
+
|
|
303
|
+
assistant_message.metrics.stop_timer()
|
|
304
|
+
|
|
305
|
+
except Exception as e:
|
|
306
|
+
log_error(f"Error from Llama API: {e}")
|
|
307
|
+
raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
|
|
308
|
+
|
|
309
|
+
async def ainvoke_stream(
|
|
310
|
+
self,
|
|
311
|
+
messages: List[Message],
|
|
312
|
+
assistant_message: Message,
|
|
313
|
+
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
314
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
315
|
+
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
316
|
+
run_response: Optional[RunOutput] = None,
|
|
317
|
+
compress_tool_results: bool = False,
|
|
318
|
+
) -> AsyncIterator[ModelResponse]:
|
|
319
|
+
"""
|
|
320
|
+
Sends an asynchronous streaming chat completion request to the Llama API.
|
|
321
|
+
"""
|
|
322
|
+
if run_response and run_response.metrics:
|
|
323
|
+
run_response.metrics.set_time_to_first_token()
|
|
324
|
+
|
|
325
|
+
assistant_message.metrics.start_timer()
|
|
326
|
+
|
|
327
|
+
try:
|
|
328
|
+
async for chunk in await self.get_async_client().chat.completions.create(
|
|
329
|
+
model=self.id,
|
|
330
|
+
messages=[
|
|
331
|
+
format_message(m, tool_calls=bool(tools), compress_tool_results=compress_tool_results) # type: ignore
|
|
332
|
+
for m in messages
|
|
333
|
+
],
|
|
334
|
+
stream=True,
|
|
335
|
+
**self.get_request_params(tools=tools, response_format=response_format),
|
|
336
|
+
):
|
|
337
|
+
yield self._parse_provider_response_delta(chunk) # type: ignore
|
|
338
|
+
|
|
339
|
+
assistant_message.metrics.stop_timer()
|
|
340
|
+
|
|
341
|
+
except Exception as e:
|
|
342
|
+
log_error(f"Error from Llama API: {e}")
|
|
343
|
+
raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
|
|
344
|
+
|
|
345
|
+
def parse_tool_calls(self, tool_calls_data: List[EventDeltaToolCallDeltaFunction]) -> List[Dict[str, Any]]:
|
|
346
|
+
"""
|
|
347
|
+
Parse the tool calls from the Llama API.
|
|
348
|
+
|
|
349
|
+
Args:
|
|
350
|
+
tool_calls_data (List[Tuple[str, Any]]): The tool calls data.
|
|
351
|
+
|
|
352
|
+
Returns:
|
|
353
|
+
List[Dict[str, Any]]: The parsed tool calls.
|
|
354
|
+
"""
|
|
355
|
+
tool_calls: List[Dict[str, Any]] = []
|
|
356
|
+
|
|
357
|
+
_tool_call_id: Optional[str] = None
|
|
358
|
+
_function_name_parts: List[str] = []
|
|
359
|
+
_function_arguments_parts: List[str] = []
|
|
360
|
+
|
|
361
|
+
def _create_tool_call():
|
|
362
|
+
nonlocal _tool_call_id
|
|
363
|
+
if _tool_call_id and (_function_name_parts or _function_arguments_parts):
|
|
364
|
+
tool_calls.append(
|
|
365
|
+
{
|
|
366
|
+
"id": _tool_call_id,
|
|
367
|
+
"type": "function",
|
|
368
|
+
"function": {
|
|
369
|
+
"name": "".join(_function_name_parts),
|
|
370
|
+
"arguments": "".join(_function_arguments_parts),
|
|
371
|
+
},
|
|
372
|
+
}
|
|
373
|
+
)
|
|
374
|
+
_tool_call_id = None
|
|
375
|
+
_function_name_parts.clear()
|
|
376
|
+
_function_arguments_parts.clear()
|
|
377
|
+
|
|
378
|
+
for _field, _value in tool_calls_data:
|
|
379
|
+
if _field == "function" and isinstance(_value, EventDeltaToolCallDeltaFunction):
|
|
380
|
+
if _value.name and (_tool_call_id or _function_name_parts or _function_arguments_parts):
|
|
381
|
+
_create_tool_call()
|
|
382
|
+
if _value.name:
|
|
383
|
+
_function_name_parts.append(_value.name)
|
|
384
|
+
if _value.arguments:
|
|
385
|
+
_function_arguments_parts.append(_value.arguments)
|
|
386
|
+
|
|
387
|
+
elif _field == "id":
|
|
388
|
+
if _value and _tool_call_id:
|
|
389
|
+
_create_tool_call()
|
|
390
|
+
if _value:
|
|
391
|
+
_tool_call_id = _value # type: ignore
|
|
392
|
+
|
|
393
|
+
_create_tool_call()
|
|
394
|
+
|
|
395
|
+
return tool_calls
|
|
396
|
+
|
|
397
|
+
def _parse_provider_response(self, response: CreateChatCompletionResponse, **kwargs) -> ModelResponse:
|
|
398
|
+
"""
|
|
399
|
+
Parse the Llama response into a ModelResponse.
|
|
400
|
+
|
|
401
|
+
Args:
|
|
402
|
+
response: Response from invoke() method
|
|
403
|
+
|
|
404
|
+
Returns:
|
|
405
|
+
ModelResponse: Parsed response data
|
|
406
|
+
"""
|
|
407
|
+
model_response = ModelResponse()
|
|
408
|
+
|
|
409
|
+
# Get response message
|
|
410
|
+
response_message = response.completion_message
|
|
411
|
+
|
|
412
|
+
# Add role
|
|
413
|
+
if response_message.role is not None:
|
|
414
|
+
model_response.role = response_message.role
|
|
415
|
+
|
|
416
|
+
# Add content
|
|
417
|
+
if response_message.content is not None:
|
|
418
|
+
if isinstance(response_message.content, MessageTextContentItem):
|
|
419
|
+
model_response.content = response_message.content.text
|
|
420
|
+
else:
|
|
421
|
+
model_response.content = response_message.content
|
|
422
|
+
|
|
423
|
+
# Add tool calls
|
|
424
|
+
if response_message.tool_calls is not None and len(response_message.tool_calls) > 0:
|
|
425
|
+
try:
|
|
426
|
+
for tool_call in response_message.tool_calls:
|
|
427
|
+
tool_name = tool_call.function.name
|
|
428
|
+
tool_input = tool_call.function.arguments
|
|
429
|
+
|
|
430
|
+
function_def = {"name": tool_name}
|
|
431
|
+
if tool_input:
|
|
432
|
+
function_def["arguments"] = tool_input
|
|
433
|
+
|
|
434
|
+
model_response.tool_calls.append(
|
|
435
|
+
{
|
|
436
|
+
"id": tool_call.id,
|
|
437
|
+
"type": "function",
|
|
438
|
+
"function": function_def,
|
|
439
|
+
}
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
except Exception as e:
|
|
443
|
+
log_warning(f"Error processing tool calls: {e}")
|
|
444
|
+
|
|
445
|
+
# Add metrics from the metrics list
|
|
446
|
+
if hasattr(response, "metrics") and response.metrics is not None:
|
|
447
|
+
model_response.response_usage = self._get_metrics(response.metrics)
|
|
448
|
+
|
|
449
|
+
return model_response
|
|
450
|
+
|
|
451
|
+
def _parse_provider_response_delta(
|
|
452
|
+
self, response: CreateChatCompletionResponseStreamChunk, **kwargs
|
|
453
|
+
) -> ModelResponse:
|
|
454
|
+
"""
|
|
455
|
+
Parse the Llama streaming response into a ModelResponse.
|
|
456
|
+
|
|
457
|
+
Args:
|
|
458
|
+
response_delta: Raw response chunk from the Llama API
|
|
459
|
+
|
|
460
|
+
Returns:
|
|
461
|
+
ModelResponse: Parsed response data
|
|
462
|
+
"""
|
|
463
|
+
model_response = ModelResponse()
|
|
464
|
+
|
|
465
|
+
if response is not None:
|
|
466
|
+
delta = response.event
|
|
467
|
+
|
|
468
|
+
# Capture metrics event
|
|
469
|
+
if delta.event_type == "metrics" and delta.metrics is not None:
|
|
470
|
+
model_response.response_usage = self._get_metrics(delta.metrics)
|
|
471
|
+
|
|
472
|
+
if isinstance(delta.delta, EventDeltaTextDelta):
|
|
473
|
+
model_response.content = delta.delta.text
|
|
474
|
+
|
|
475
|
+
# Add tool calls
|
|
476
|
+
if isinstance(delta.delta, EventDeltaToolCallDelta):
|
|
477
|
+
model_response.tool_calls = delta.delta # type: ignore
|
|
478
|
+
|
|
479
|
+
return model_response
|
|
480
|
+
|
|
481
|
+
def _get_metrics(self, response_usage: Union[List[Metric], List[EventMetric]]) -> Metrics:
|
|
482
|
+
"""
|
|
483
|
+
Parse the given Llama usage into an Agno Metrics object.
|
|
484
|
+
|
|
485
|
+
Args:
|
|
486
|
+
response_usage: Usage data from Llama
|
|
487
|
+
|
|
488
|
+
Returns:
|
|
489
|
+
Metrics: Parsed metrics data
|
|
490
|
+
"""
|
|
491
|
+
metrics = Metrics()
|
|
492
|
+
|
|
493
|
+
for metric in response_usage:
|
|
494
|
+
metrics_field = metric.metric
|
|
495
|
+
if metrics_field == "num_prompt_tokens":
|
|
496
|
+
metrics.input_tokens = int(metric.value)
|
|
497
|
+
elif metrics_field == "num_completion_tokens":
|
|
498
|
+
metrics.output_tokens = int(metric.value)
|
|
499
|
+
|
|
500
|
+
metrics.total_tokens = metrics.input_tokens + metrics.output_tokens
|
|
501
|
+
|
|
502
|
+
return metrics
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from os import getenv
|
|
3
|
+
from typing import Any, Dict, Optional
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
from openai import AsyncOpenAI as AsyncOpenAIClient
|
|
7
|
+
except ImportError:
|
|
8
|
+
raise ImportError("`openai` not installed. Please install using `pip install openai`")
|
|
9
|
+
|
|
10
|
+
from agno.exceptions import ModelAuthenticationError
|
|
11
|
+
from agno.models.meta.llama import Message
|
|
12
|
+
from agno.models.openai.like import OpenAILike
|
|
13
|
+
from agno.utils.models.llama import format_message
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class LlamaOpenAI(OpenAILike):
|
|
18
|
+
"""
|
|
19
|
+
Class for interacting with the Llama API via OpenAI-like interface.
|
|
20
|
+
|
|
21
|
+
Attributes:
|
|
22
|
+
id (str): The ID of the language model.
|
|
23
|
+
name (str): The name of the API.
|
|
24
|
+
provider (str): The provider of the API.
|
|
25
|
+
api_key (Optional[str]): The API key for the xAI API.
|
|
26
|
+
base_url (Optional[str]): The base URL for the xAI API.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
id: str = "Llama-4-Maverick-17B-128E-Instruct-FP8"
|
|
30
|
+
name: str = "LlamaOpenAI"
|
|
31
|
+
provider: str = "LlamaOpenAI"
|
|
32
|
+
|
|
33
|
+
api_key: Optional[str] = None
|
|
34
|
+
base_url: Optional[str] = "https://api.llama.com/compat/v1/"
|
|
35
|
+
|
|
36
|
+
# Request parameters
|
|
37
|
+
max_completion_tokens: Optional[int] = None
|
|
38
|
+
repetition_penalty: Optional[float] = None
|
|
39
|
+
temperature: Optional[float] = None
|
|
40
|
+
top_p: Optional[float] = None
|
|
41
|
+
top_k: Optional[int] = None
|
|
42
|
+
extra_headers: Optional[Any] = None
|
|
43
|
+
extra_query: Optional[Any] = None
|
|
44
|
+
extra_body: Optional[Any] = None
|
|
45
|
+
request_params: Optional[Dict[str, Any]] = None
|
|
46
|
+
|
|
47
|
+
supports_native_structured_outputs: bool = False
|
|
48
|
+
supports_json_schema_outputs: bool = True
|
|
49
|
+
|
|
50
|
+
# Cached async client
|
|
51
|
+
openai_async_client: Optional[AsyncOpenAIClient] = None
|
|
52
|
+
|
|
53
|
+
def _get_client_params(self) -> Dict[str, Any]:
|
|
54
|
+
"""
|
|
55
|
+
Returns client parameters for API requests, checking for LLAMA_API_KEY.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
Dict[str, Any]: A dictionary of client parameters for API requests.
|
|
59
|
+
"""
|
|
60
|
+
if not self.api_key:
|
|
61
|
+
self.api_key = getenv("LLAMA_API_KEY")
|
|
62
|
+
if not self.api_key:
|
|
63
|
+
raise ModelAuthenticationError(
|
|
64
|
+
message="LLAMA_API_KEY not set. Please set the LLAMA_API_KEY environment variable.",
|
|
65
|
+
model_name=self.name,
|
|
66
|
+
)
|
|
67
|
+
return super()._get_client_params()
|
|
68
|
+
|
|
69
|
+
def _format_message(self, message: Message) -> Dict[str, Any]:
|
|
70
|
+
"""
|
|
71
|
+
Format a message into the format expected by Llama API.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
message (Message): The message to format.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
Dict[str, Any]: The formatted message.
|
|
78
|
+
"""
|
|
79
|
+
return format_message(message, openai_like=True)
|
agno/models/metrics.py
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
from dataclasses import asdict, dataclass
|
|
2
|
+
from typing import Any, Dict, Optional
|
|
3
|
+
|
|
4
|
+
from agno.utils.timer import Timer
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class Metrics:
|
|
9
|
+
"""All relevant metrics for a session, run or message."""
|
|
10
|
+
|
|
11
|
+
# Main token consumption values
|
|
12
|
+
input_tokens: int = 0
|
|
13
|
+
output_tokens: int = 0
|
|
14
|
+
total_tokens: int = 0
|
|
15
|
+
|
|
16
|
+
# Audio token usage
|
|
17
|
+
audio_input_tokens: int = 0
|
|
18
|
+
audio_output_tokens: int = 0
|
|
19
|
+
audio_total_tokens: int = 0
|
|
20
|
+
|
|
21
|
+
# Cache token usage
|
|
22
|
+
cache_read_tokens: int = 0
|
|
23
|
+
cache_write_tokens: int = 0
|
|
24
|
+
|
|
25
|
+
# Tokens employed in reasoning
|
|
26
|
+
reasoning_tokens: int = 0
|
|
27
|
+
|
|
28
|
+
# Time metrics
|
|
29
|
+
# Internal timer utility for tracking execution time
|
|
30
|
+
timer: Optional[Timer] = None
|
|
31
|
+
# Time from run start to first token generation, in seconds
|
|
32
|
+
time_to_first_token: Optional[float] = None
|
|
33
|
+
# Total run time, in seconds
|
|
34
|
+
duration: Optional[float] = None
|
|
35
|
+
|
|
36
|
+
# Provider-specific metrics
|
|
37
|
+
provider_metrics: Optional[dict] = None
|
|
38
|
+
|
|
39
|
+
# Any additional metrics
|
|
40
|
+
additional_metrics: Optional[dict] = None
|
|
41
|
+
|
|
42
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
43
|
+
metrics_dict = asdict(self)
|
|
44
|
+
# Remove the timer util if present
|
|
45
|
+
metrics_dict.pop("timer", None)
|
|
46
|
+
metrics_dict = {
|
|
47
|
+
k: v
|
|
48
|
+
for k, v in metrics_dict.items()
|
|
49
|
+
if v is not None and (not isinstance(v, (int, float)) or v != 0) and (not isinstance(v, dict) or len(v) > 0)
|
|
50
|
+
}
|
|
51
|
+
return metrics_dict
|
|
52
|
+
|
|
53
|
+
def __add__(self, other: "Metrics") -> "Metrics":
|
|
54
|
+
# Create new instance of the same type as self
|
|
55
|
+
result_class = type(self)
|
|
56
|
+
result = result_class(
|
|
57
|
+
input_tokens=self.input_tokens + other.input_tokens,
|
|
58
|
+
output_tokens=self.output_tokens + other.output_tokens,
|
|
59
|
+
total_tokens=self.total_tokens + other.total_tokens,
|
|
60
|
+
audio_total_tokens=self.audio_total_tokens + other.audio_total_tokens,
|
|
61
|
+
audio_input_tokens=self.audio_input_tokens + other.audio_input_tokens,
|
|
62
|
+
audio_output_tokens=self.audio_output_tokens + other.audio_output_tokens,
|
|
63
|
+
cache_read_tokens=self.cache_read_tokens + other.cache_read_tokens,
|
|
64
|
+
cache_write_tokens=self.cache_write_tokens + other.cache_write_tokens,
|
|
65
|
+
reasoning_tokens=self.reasoning_tokens + other.reasoning_tokens,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
# Handle provider_metrics
|
|
69
|
+
if self.provider_metrics or other.provider_metrics:
|
|
70
|
+
result.provider_metrics = {}
|
|
71
|
+
if self.provider_metrics:
|
|
72
|
+
result.provider_metrics.update(self.provider_metrics)
|
|
73
|
+
if other.provider_metrics:
|
|
74
|
+
result.provider_metrics.update(other.provider_metrics)
|
|
75
|
+
|
|
76
|
+
# Handle additional metrics
|
|
77
|
+
if self.additional_metrics or other.additional_metrics:
|
|
78
|
+
result.additional_metrics = {}
|
|
79
|
+
if self.additional_metrics:
|
|
80
|
+
result.additional_metrics.update(self.additional_metrics)
|
|
81
|
+
if other.additional_metrics:
|
|
82
|
+
result.additional_metrics.update(other.additional_metrics)
|
|
83
|
+
|
|
84
|
+
# Sum durations if both exist
|
|
85
|
+
if self.duration is not None and other.duration is not None:
|
|
86
|
+
result.duration = self.duration + other.duration
|
|
87
|
+
elif self.duration is not None:
|
|
88
|
+
result.duration = self.duration
|
|
89
|
+
elif other.duration is not None:
|
|
90
|
+
result.duration = other.duration
|
|
91
|
+
|
|
92
|
+
# Sum time to first token if both exist
|
|
93
|
+
if self.time_to_first_token is not None and other.time_to_first_token is not None:
|
|
94
|
+
result.time_to_first_token = self.time_to_first_token + other.time_to_first_token
|
|
95
|
+
elif self.time_to_first_token is not None:
|
|
96
|
+
result.time_to_first_token = self.time_to_first_token
|
|
97
|
+
elif other.time_to_first_token is not None:
|
|
98
|
+
result.time_to_first_token = other.time_to_first_token
|
|
99
|
+
|
|
100
|
+
return result
|
|
101
|
+
|
|
102
|
+
def __radd__(self, other: "Metrics") -> "Metrics":
|
|
103
|
+
if other == 0: # Handle sum() starting value
|
|
104
|
+
return self
|
|
105
|
+
return self + other
|
|
106
|
+
|
|
107
|
+
def start_timer(self):
|
|
108
|
+
if self.timer is None:
|
|
109
|
+
self.timer = Timer()
|
|
110
|
+
self.timer.start()
|
|
111
|
+
|
|
112
|
+
def stop_timer(self, set_duration: bool = True):
|
|
113
|
+
if self.timer is not None:
|
|
114
|
+
self.timer.stop()
|
|
115
|
+
if set_duration:
|
|
116
|
+
self.duration = self.timer.elapsed
|
|
117
|
+
|
|
118
|
+
def set_time_to_first_token(self):
|
|
119
|
+
if self.timer is not None:
|
|
120
|
+
self.time_to_first_token = self.timer.elapsed
|