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,94 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from os import getenv
|
|
3
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
4
|
+
|
|
5
|
+
from agno.knowledge.embedder.base import Embedder
|
|
6
|
+
from agno.utils.log import log_error, log_warning
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
from huggingface_hub import AsyncInferenceClient, InferenceClient
|
|
10
|
+
except ImportError:
|
|
11
|
+
log_error("`huggingface-hub` not installed, please run `pip install huggingface-hub`")
|
|
12
|
+
raise
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class HuggingfaceCustomEmbedder(Embedder):
|
|
17
|
+
"""Huggingface Custom Embedder"""
|
|
18
|
+
|
|
19
|
+
id: str = "intfloat/multilingual-e5-large"
|
|
20
|
+
api_key: Optional[str] = getenv("HUGGINGFACE_API_KEY")
|
|
21
|
+
client_params: Optional[Dict[str, Any]] = None
|
|
22
|
+
huggingface_client: Optional[InferenceClient] = None
|
|
23
|
+
async_client: Optional[AsyncInferenceClient] = None
|
|
24
|
+
|
|
25
|
+
def __post_init__(self):
|
|
26
|
+
if self.enable_batch:
|
|
27
|
+
log_warning("HuggingfaceEmbedder does not support batch embeddings, setting enable_batch to False")
|
|
28
|
+
self.enable_batch = False
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def client(self) -> InferenceClient:
|
|
32
|
+
if self.huggingface_client:
|
|
33
|
+
return self.huggingface_client
|
|
34
|
+
_client_params: Dict[str, Any] = {}
|
|
35
|
+
if self.api_key:
|
|
36
|
+
_client_params["api_key"] = self.api_key
|
|
37
|
+
if self.client_params:
|
|
38
|
+
_client_params.update(self.client_params)
|
|
39
|
+
self.huggingface_client = InferenceClient(**_client_params)
|
|
40
|
+
return self.huggingface_client
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def aclient(self) -> AsyncInferenceClient:
|
|
44
|
+
if self.async_client:
|
|
45
|
+
return self.async_client
|
|
46
|
+
_client_params: Dict[str, Any] = {}
|
|
47
|
+
if self.api_key:
|
|
48
|
+
_client_params["api_key"] = self.api_key
|
|
49
|
+
if self.client_params:
|
|
50
|
+
_client_params.update(self.client_params)
|
|
51
|
+
self.async_client = AsyncInferenceClient(**_client_params)
|
|
52
|
+
return self.async_client
|
|
53
|
+
|
|
54
|
+
def _response(self, text: str):
|
|
55
|
+
return self.client.feature_extraction(text=text, model=self.id)
|
|
56
|
+
|
|
57
|
+
def get_embedding(self, text: str) -> List[float]:
|
|
58
|
+
response = self._response(text=text)
|
|
59
|
+
try:
|
|
60
|
+
# If already a list, return directly
|
|
61
|
+
if isinstance(response, list):
|
|
62
|
+
return response
|
|
63
|
+
# If numpy array, convert to list
|
|
64
|
+
elif hasattr(response, "tolist"):
|
|
65
|
+
return response.tolist()
|
|
66
|
+
else:
|
|
67
|
+
return list(response)
|
|
68
|
+
except Exception as e:
|
|
69
|
+
log_warning(f"Failed to process embeddings: {e}")
|
|
70
|
+
return []
|
|
71
|
+
|
|
72
|
+
def get_embedding_and_usage(self, text: str) -> Tuple[List[float], Optional[Dict]]:
|
|
73
|
+
return self.get_embedding(text=text), None
|
|
74
|
+
|
|
75
|
+
async def async_get_embedding(self, text: str) -> List[float]:
|
|
76
|
+
"""Async version of get_embedding using AsyncInferenceClient."""
|
|
77
|
+
response = await self.aclient.feature_extraction(text=text, model=self.id)
|
|
78
|
+
try:
|
|
79
|
+
# If already a list, return directly
|
|
80
|
+
if isinstance(response, list):
|
|
81
|
+
return response
|
|
82
|
+
# If numpy array, convert to list
|
|
83
|
+
elif hasattr(response, "tolist"):
|
|
84
|
+
return response.tolist()
|
|
85
|
+
else:
|
|
86
|
+
return list(response)
|
|
87
|
+
except Exception as e:
|
|
88
|
+
log_warning(f"Failed to process embeddings: {e}")
|
|
89
|
+
return []
|
|
90
|
+
|
|
91
|
+
async def async_get_embedding_and_usage(self, text: str) -> Tuple[List[float], Optional[Dict]]:
|
|
92
|
+
"""Async version of get_embedding_and_usage."""
|
|
93
|
+
embedding = await self.async_get_embedding(text=text)
|
|
94
|
+
return embedding, None
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from os import getenv
|
|
3
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
4
|
+
|
|
5
|
+
from typing_extensions import Literal
|
|
6
|
+
|
|
7
|
+
from agno.knowledge.embedder.base import Embedder
|
|
8
|
+
from agno.utils.log import logger
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
import requests
|
|
12
|
+
except ImportError:
|
|
13
|
+
raise ImportError("`requests` not installed, use pip install requests")
|
|
14
|
+
|
|
15
|
+
try:
|
|
16
|
+
import aiohttp
|
|
17
|
+
except ImportError:
|
|
18
|
+
raise ImportError("`aiohttp` not installed, use pip install aiohttp")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class JinaEmbedder(Embedder):
|
|
23
|
+
id: str = "jina-embeddings-v3"
|
|
24
|
+
dimensions: int = 1024
|
|
25
|
+
embedding_type: Literal["float", "base64", "int8"] = "float"
|
|
26
|
+
late_chunking: bool = False
|
|
27
|
+
user: Optional[str] = None
|
|
28
|
+
api_key: Optional[str] = getenv("JINA_API_KEY")
|
|
29
|
+
base_url: str = "https://api.jina.ai/v1/embeddings"
|
|
30
|
+
headers: Optional[Dict[str, str]] = None
|
|
31
|
+
request_params: Optional[Dict[str, Any]] = None
|
|
32
|
+
timeout: Optional[float] = None
|
|
33
|
+
|
|
34
|
+
def _get_headers(self) -> Dict[str, str]:
|
|
35
|
+
if not self.api_key:
|
|
36
|
+
raise ValueError(
|
|
37
|
+
"API key is required for Jina embedder. Set JINA_API_KEY environment variable or pass api_key parameter."
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
headers = {"Content-Type": "application/json", "Authorization": f"Bearer {self.api_key}"}
|
|
41
|
+
if self.headers:
|
|
42
|
+
headers.update(self.headers)
|
|
43
|
+
return headers
|
|
44
|
+
|
|
45
|
+
def _response(self, text: str) -> Dict[str, Any]:
|
|
46
|
+
data = {
|
|
47
|
+
"model": self.id,
|
|
48
|
+
"late_chunking": self.late_chunking,
|
|
49
|
+
"dimensions": self.dimensions,
|
|
50
|
+
"embedding_type": self.embedding_type,
|
|
51
|
+
"input": [text], # Jina API expects a list
|
|
52
|
+
}
|
|
53
|
+
if self.user is not None:
|
|
54
|
+
data["user"] = self.user
|
|
55
|
+
if self.request_params:
|
|
56
|
+
data.update(self.request_params)
|
|
57
|
+
|
|
58
|
+
response = requests.post(self.base_url, headers=self._get_headers(), json=data, timeout=self.timeout)
|
|
59
|
+
response.raise_for_status()
|
|
60
|
+
return response.json()
|
|
61
|
+
|
|
62
|
+
def get_embedding(self, text: str) -> List[float]:
|
|
63
|
+
try:
|
|
64
|
+
result = self._response(text)
|
|
65
|
+
return result["data"][0]["embedding"]
|
|
66
|
+
except Exception as e:
|
|
67
|
+
logger.warning(f"Failed to get embedding: {e}")
|
|
68
|
+
return []
|
|
69
|
+
|
|
70
|
+
def get_embedding_and_usage(self, text: str) -> Tuple[List[float], Optional[Dict]]:
|
|
71
|
+
try:
|
|
72
|
+
result = self._response(text)
|
|
73
|
+
embedding = result["data"][0]["embedding"]
|
|
74
|
+
usage = result.get("usage")
|
|
75
|
+
return embedding, usage
|
|
76
|
+
except Exception as e:
|
|
77
|
+
logger.warning(f"Failed to get embedding and usage: {e}")
|
|
78
|
+
return [], None
|
|
79
|
+
|
|
80
|
+
async def _async_response(self, text: str) -> Dict[str, Any]:
|
|
81
|
+
"""Async version of _response using aiohttp."""
|
|
82
|
+
data = {
|
|
83
|
+
"model": self.id,
|
|
84
|
+
"late_chunking": self.late_chunking,
|
|
85
|
+
"dimensions": self.dimensions,
|
|
86
|
+
"embedding_type": self.embedding_type,
|
|
87
|
+
"input": [text], # Jina API expects a list
|
|
88
|
+
}
|
|
89
|
+
if self.user is not None:
|
|
90
|
+
data["user"] = self.user
|
|
91
|
+
if self.request_params:
|
|
92
|
+
data.update(self.request_params)
|
|
93
|
+
|
|
94
|
+
timeout = aiohttp.ClientTimeout(total=self.timeout) if self.timeout else None
|
|
95
|
+
|
|
96
|
+
async with aiohttp.ClientSession(timeout=timeout) as session:
|
|
97
|
+
async with session.post(self.base_url, headers=self._get_headers(), json=data) as response:
|
|
98
|
+
response.raise_for_status()
|
|
99
|
+
return await response.json()
|
|
100
|
+
|
|
101
|
+
async def async_get_embedding(self, text: str) -> List[float]:
|
|
102
|
+
"""Async version of get_embedding."""
|
|
103
|
+
try:
|
|
104
|
+
result = await self._async_response(text)
|
|
105
|
+
return result["data"][0]["embedding"]
|
|
106
|
+
except Exception as e:
|
|
107
|
+
logger.warning(f"Failed to get embedding: {e}")
|
|
108
|
+
return []
|
|
109
|
+
|
|
110
|
+
async def async_get_embedding_and_usage(self, text: str) -> Tuple[List[float], Optional[Dict]]:
|
|
111
|
+
"""Async version of get_embedding_and_usage."""
|
|
112
|
+
try:
|
|
113
|
+
result = await self._async_response(text)
|
|
114
|
+
embedding = result["data"][0]["embedding"]
|
|
115
|
+
usage = result.get("usage")
|
|
116
|
+
return embedding, usage
|
|
117
|
+
except Exception as e:
|
|
118
|
+
logger.warning(f"Failed to get embedding and usage: {e}")
|
|
119
|
+
return [], None
|
|
120
|
+
|
|
121
|
+
async def _async_batch_response(self, texts: List[str]) -> Dict[str, Any]:
|
|
122
|
+
"""Async batch version of _response using aiohttp."""
|
|
123
|
+
data = {
|
|
124
|
+
"model": self.id,
|
|
125
|
+
"late_chunking": self.late_chunking,
|
|
126
|
+
"dimensions": self.dimensions,
|
|
127
|
+
"embedding_type": self.embedding_type,
|
|
128
|
+
"input": texts, # Jina API expects a list of texts for batch processing
|
|
129
|
+
}
|
|
130
|
+
if self.user is not None:
|
|
131
|
+
data["user"] = self.user
|
|
132
|
+
if self.request_params:
|
|
133
|
+
data.update(self.request_params)
|
|
134
|
+
|
|
135
|
+
timeout = aiohttp.ClientTimeout(total=self.timeout) if self.timeout else None
|
|
136
|
+
|
|
137
|
+
async with aiohttp.ClientSession(timeout=timeout) as session:
|
|
138
|
+
async with session.post(self.base_url, headers=self._get_headers(), json=data) as response:
|
|
139
|
+
response.raise_for_status()
|
|
140
|
+
return await response.json()
|
|
141
|
+
|
|
142
|
+
async def async_get_embeddings_batch_and_usage(
|
|
143
|
+
self, texts: List[str]
|
|
144
|
+
) -> Tuple[List[List[float]], List[Optional[Dict]]]:
|
|
145
|
+
"""
|
|
146
|
+
Get embeddings and usage for multiple texts in batches.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
texts: List of text strings to embed
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
Tuple of (List of embedding vectors, List of usage dictionaries)
|
|
153
|
+
"""
|
|
154
|
+
all_embeddings = []
|
|
155
|
+
all_usage = []
|
|
156
|
+
logger.info(f"Getting embeddings and usage for {len(texts)} texts in batches of {self.batch_size}")
|
|
157
|
+
|
|
158
|
+
for i in range(0, len(texts), self.batch_size):
|
|
159
|
+
batch_texts = texts[i : i + self.batch_size]
|
|
160
|
+
|
|
161
|
+
try:
|
|
162
|
+
result = await self._async_batch_response(batch_texts)
|
|
163
|
+
batch_embeddings = [data["embedding"] for data in result["data"]]
|
|
164
|
+
all_embeddings.extend(batch_embeddings)
|
|
165
|
+
|
|
166
|
+
# For each embedding in the batch, add the same usage information
|
|
167
|
+
usage_dict = result.get("usage")
|
|
168
|
+
all_usage.extend([usage_dict] * len(batch_embeddings))
|
|
169
|
+
except Exception as e:
|
|
170
|
+
logger.warning(f"Error in async batch embedding: {e}")
|
|
171
|
+
# Fallback to individual calls for this batch
|
|
172
|
+
for text in batch_texts:
|
|
173
|
+
try:
|
|
174
|
+
embedding, usage = await self.async_get_embedding_and_usage(text)
|
|
175
|
+
all_embeddings.append(embedding)
|
|
176
|
+
all_usage.append(usage)
|
|
177
|
+
except Exception as e2:
|
|
178
|
+
logger.warning(f"Error in individual async embedding fallback: {e2}")
|
|
179
|
+
all_embeddings.append([])
|
|
180
|
+
all_usage.append(None)
|
|
181
|
+
|
|
182
|
+
return all_embeddings, all_usage
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from os import getenv
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from agno.knowledge.embedder.openai import OpenAIEmbedder
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass
|
|
9
|
+
class LangDBEmbedder(OpenAIEmbedder):
|
|
10
|
+
id: str = "text-embedding-ada-002"
|
|
11
|
+
dimensions: int = 1536
|
|
12
|
+
api_key: Optional[str] = getenv("LANGDB_API_KEY")
|
|
13
|
+
project_id: Optional[str] = getenv("LANGDB_PROJECT_ID")
|
|
14
|
+
base_url: Optional[str] = None
|
|
15
|
+
|
|
16
|
+
def __post_init__(self):
|
|
17
|
+
"""Set the base_url based on project_id if not provided."""
|
|
18
|
+
if not self.project_id:
|
|
19
|
+
raise ValueError("LANGDB_PROJECT_ID not set in the environment")
|
|
20
|
+
|
|
21
|
+
if not self.base_url:
|
|
22
|
+
self.base_url = f"https://api.us-east-1.langdb.ai/{self.project_id}/v1"
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from os import getenv
|
|
3
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
4
|
+
|
|
5
|
+
from agno.knowledge.embedder.base import Embedder
|
|
6
|
+
from agno.utils.log import log_error, log_info, log_warning
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
from mistralai import Mistral # type: ignore
|
|
10
|
+
from mistralai.models.embeddingresponse import EmbeddingResponse # type: ignore
|
|
11
|
+
except ImportError:
|
|
12
|
+
log_error("`mistralai` not installed")
|
|
13
|
+
raise
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class MistralEmbedder(Embedder):
|
|
18
|
+
id: str = "mistral-embed"
|
|
19
|
+
dimensions: int = 1024
|
|
20
|
+
# -*- Request parameters
|
|
21
|
+
request_params: Optional[Dict[str, Any]] = None
|
|
22
|
+
# -*- Client parameters
|
|
23
|
+
api_key: Optional[str] = getenv("MISTRAL_API_KEY")
|
|
24
|
+
endpoint: Optional[str] = None
|
|
25
|
+
max_retries: Optional[int] = None
|
|
26
|
+
timeout: Optional[int] = None
|
|
27
|
+
client_params: Optional[Dict[str, Any]] = None
|
|
28
|
+
# -*- Provide the Mistral Client manually
|
|
29
|
+
mistral_client: Optional[Mistral] = None
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def client(self) -> Mistral:
|
|
33
|
+
if self.mistral_client:
|
|
34
|
+
return self.mistral_client
|
|
35
|
+
|
|
36
|
+
_client_params: Dict[str, Any] = {
|
|
37
|
+
"api_key": self.api_key,
|
|
38
|
+
"endpoint": self.endpoint,
|
|
39
|
+
"max_retries": self.max_retries,
|
|
40
|
+
"timeout": self.timeout,
|
|
41
|
+
}
|
|
42
|
+
_client_params = {k: v for k, v in _client_params.items() if v is not None}
|
|
43
|
+
|
|
44
|
+
if self.client_params:
|
|
45
|
+
_client_params.update(self.client_params)
|
|
46
|
+
|
|
47
|
+
self.mistral_client = Mistral(**_client_params)
|
|
48
|
+
|
|
49
|
+
return self.mistral_client
|
|
50
|
+
|
|
51
|
+
def _response(self, text: str) -> EmbeddingResponse:
|
|
52
|
+
_request_params: Dict[str, Any] = {
|
|
53
|
+
"inputs": [text], # Mistral API expects a list
|
|
54
|
+
"model": self.id,
|
|
55
|
+
}
|
|
56
|
+
if self.request_params:
|
|
57
|
+
_request_params.update(self.request_params)
|
|
58
|
+
response = self.client.embeddings.create(**_request_params)
|
|
59
|
+
if response is None:
|
|
60
|
+
raise ValueError("Failed to get embedding response")
|
|
61
|
+
return response
|
|
62
|
+
|
|
63
|
+
def get_embedding(self, text: str) -> List[float]:
|
|
64
|
+
try:
|
|
65
|
+
response: EmbeddingResponse = self._response(text=text)
|
|
66
|
+
if response.data and response.data[0].embedding:
|
|
67
|
+
return response.data[0].embedding
|
|
68
|
+
return []
|
|
69
|
+
except Exception as e:
|
|
70
|
+
log_warning(f"Error getting embedding: {e}")
|
|
71
|
+
return []
|
|
72
|
+
|
|
73
|
+
def get_embedding_and_usage(self, text: str) -> Tuple[List[float], Dict[str, Any]]:
|
|
74
|
+
try:
|
|
75
|
+
response: EmbeddingResponse = self._response(text=text)
|
|
76
|
+
embedding: List[float] = (
|
|
77
|
+
response.data[0].embedding if (response.data and response.data[0].embedding) else []
|
|
78
|
+
)
|
|
79
|
+
usage: Dict[str, Any] = response.usage.model_dump() if response.usage else {}
|
|
80
|
+
return embedding, usage
|
|
81
|
+
except Exception as e:
|
|
82
|
+
log_warning(f"Error getting embedding and usage: {e}")
|
|
83
|
+
return [], {}
|
|
84
|
+
|
|
85
|
+
async def async_get_embedding(self, text: str) -> List[float]:
|
|
86
|
+
"""Async version of get_embedding."""
|
|
87
|
+
try:
|
|
88
|
+
# Check if the client has an async version of embeddings.create
|
|
89
|
+
if hasattr(self.client.embeddings, "create_async"):
|
|
90
|
+
response: EmbeddingResponse = await self.client.embeddings.create_async(
|
|
91
|
+
inputs=[text], model=self.id, **self.request_params if self.request_params else {}
|
|
92
|
+
)
|
|
93
|
+
else:
|
|
94
|
+
# Fallback to running sync method in thread executor
|
|
95
|
+
import asyncio
|
|
96
|
+
|
|
97
|
+
loop = asyncio.get_running_loop()
|
|
98
|
+
response: EmbeddingResponse = await loop.run_in_executor( # type: ignore
|
|
99
|
+
None,
|
|
100
|
+
lambda: self.client.embeddings.create(
|
|
101
|
+
inputs=[text], model=self.id, **self.request_params if self.request_params else {}
|
|
102
|
+
),
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
if response.data and response.data[0].embedding:
|
|
106
|
+
return response.data[0].embedding
|
|
107
|
+
return []
|
|
108
|
+
except Exception as e:
|
|
109
|
+
log_warning(f"Error getting embedding: {e}")
|
|
110
|
+
return []
|
|
111
|
+
|
|
112
|
+
async def async_get_embedding_and_usage(self, text: str) -> Tuple[List[float], Dict[str, Any]]:
|
|
113
|
+
"""Async version of get_embedding_and_usage."""
|
|
114
|
+
try:
|
|
115
|
+
# Check if the client has an async version of embeddings.create
|
|
116
|
+
if hasattr(self.client.embeddings, "create_async"):
|
|
117
|
+
response: EmbeddingResponse = await self.client.embeddings.create_async(
|
|
118
|
+
inputs=[text], model=self.id, **self.request_params if self.request_params else {}
|
|
119
|
+
)
|
|
120
|
+
else:
|
|
121
|
+
# Fallback to running sync method in thread executor
|
|
122
|
+
import asyncio
|
|
123
|
+
|
|
124
|
+
loop = asyncio.get_running_loop()
|
|
125
|
+
response: EmbeddingResponse = await loop.run_in_executor( # type: ignore
|
|
126
|
+
None,
|
|
127
|
+
lambda: self.client.embeddings.create(
|
|
128
|
+
inputs=[text], model=self.id, **self.request_params if self.request_params else {}
|
|
129
|
+
),
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
embedding: List[float] = (
|
|
133
|
+
response.data[0].embedding if (response.data and response.data[0].embedding) else []
|
|
134
|
+
)
|
|
135
|
+
usage: Dict[str, Any] = response.usage.model_dump() if response.usage else {}
|
|
136
|
+
return embedding, usage
|
|
137
|
+
except Exception as e:
|
|
138
|
+
log_warning(f"Error getting embedding and usage: {e}")
|
|
139
|
+
return [], {}
|
|
140
|
+
|
|
141
|
+
async def async_get_embeddings_batch_and_usage(
|
|
142
|
+
self, texts: List[str]
|
|
143
|
+
) -> Tuple[List[List[float]], List[Optional[Dict[str, Any]]]]:
|
|
144
|
+
"""
|
|
145
|
+
Get embeddings and usage for multiple texts in batches.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
texts: List of text strings to embed
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
Tuple of (List of embedding vectors, List of usage dictionaries)
|
|
152
|
+
"""
|
|
153
|
+
all_embeddings = []
|
|
154
|
+
all_usage = []
|
|
155
|
+
log_info(f"Getting embeddings and usage for {len(texts)} texts in batches of {self.batch_size}")
|
|
156
|
+
|
|
157
|
+
for i in range(0, len(texts), self.batch_size):
|
|
158
|
+
batch_texts = texts[i : i + self.batch_size]
|
|
159
|
+
|
|
160
|
+
_request_params: Dict[str, Any] = {
|
|
161
|
+
"inputs": batch_texts, # Mistral API expects a list for batch processing
|
|
162
|
+
"model": self.id,
|
|
163
|
+
}
|
|
164
|
+
if self.request_params:
|
|
165
|
+
_request_params.update(self.request_params)
|
|
166
|
+
|
|
167
|
+
try:
|
|
168
|
+
# Check if the client has an async version of embeddings.create
|
|
169
|
+
if hasattr(self.client.embeddings, "create_async"):
|
|
170
|
+
response: EmbeddingResponse = await self.client.embeddings.create_async(**_request_params)
|
|
171
|
+
else:
|
|
172
|
+
# Fallback to running sync method in thread executor
|
|
173
|
+
import asyncio
|
|
174
|
+
|
|
175
|
+
loop = asyncio.get_running_loop()
|
|
176
|
+
response: EmbeddingResponse = await loop.run_in_executor( # type: ignore
|
|
177
|
+
None, lambda: self.client.embeddings.create(**_request_params)
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
# Extract embeddings from batch response
|
|
181
|
+
if response.data:
|
|
182
|
+
batch_embeddings = [data.embedding for data in response.data if data.embedding]
|
|
183
|
+
all_embeddings.extend(batch_embeddings)
|
|
184
|
+
else:
|
|
185
|
+
# If no embeddings, add empty lists for each text in batch
|
|
186
|
+
all_embeddings.extend([[] for _ in batch_texts])
|
|
187
|
+
|
|
188
|
+
# Extract usage information
|
|
189
|
+
usage_dict = response.usage.model_dump() if response.usage else None
|
|
190
|
+
# Add same usage info for each embedding in the batch
|
|
191
|
+
all_usage.extend([usage_dict] * len(batch_texts))
|
|
192
|
+
|
|
193
|
+
except Exception as e:
|
|
194
|
+
log_warning(f"Error in async batch embedding: {e}")
|
|
195
|
+
# Fallback to individual calls for this batch
|
|
196
|
+
for text in batch_texts:
|
|
197
|
+
try:
|
|
198
|
+
embedding, usage = await self.async_get_embedding_and_usage(text)
|
|
199
|
+
all_embeddings.append(embedding)
|
|
200
|
+
all_usage.append(usage)
|
|
201
|
+
except Exception as e2:
|
|
202
|
+
log_warning(f"Error in individual async embedding fallback: {e2}")
|
|
203
|
+
all_embeddings.append([])
|
|
204
|
+
all_usage.append(None)
|
|
205
|
+
|
|
206
|
+
return all_embeddings, all_usage
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from os import getenv
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from agno.knowledge.embedder.openai import OpenAIEmbedder
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass
|
|
9
|
+
class NebiusEmbedder(OpenAIEmbedder):
|
|
10
|
+
id: str = "BAAI/bge-en-icl"
|
|
11
|
+
dimensions: int = 1024
|
|
12
|
+
api_key: Optional[str] = getenv("NEBIUS_API_KEY")
|
|
13
|
+
base_url: str = "https://api.tokenfactory.nebius.com/v1/"
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
3
|
+
|
|
4
|
+
from agno.knowledge.embedder.base import Embedder
|
|
5
|
+
from agno.utils.log import log_error, logger
|
|
6
|
+
|
|
7
|
+
try:
|
|
8
|
+
import importlib.metadata as metadata
|
|
9
|
+
|
|
10
|
+
from ollama import AsyncClient as AsyncOllamaClient
|
|
11
|
+
from ollama import Client as OllamaClient
|
|
12
|
+
from packaging import version
|
|
13
|
+
|
|
14
|
+
# Get installed Ollama version
|
|
15
|
+
ollama_version = metadata.version("ollama")
|
|
16
|
+
|
|
17
|
+
# Check version compatibility (requires v0.3.x or higher)
|
|
18
|
+
parsed_version = version.parse(ollama_version)
|
|
19
|
+
if parsed_version.major == 0 and parsed_version.minor < 3:
|
|
20
|
+
import warnings
|
|
21
|
+
|
|
22
|
+
warnings.warn("Only Ollama v0.3.x and above are supported", UserWarning)
|
|
23
|
+
raise RuntimeError("Incompatible Ollama version detected")
|
|
24
|
+
|
|
25
|
+
except ImportError as e:
|
|
26
|
+
# Handle different import error scenarios
|
|
27
|
+
if "ollama" in str(e):
|
|
28
|
+
raise ImportError("Ollama not installed. Install with `pip install ollama`") from e
|
|
29
|
+
else:
|
|
30
|
+
raise ImportError("Missing dependencies. Install with `pip install packaging importlib-metadata`") from e
|
|
31
|
+
|
|
32
|
+
except Exception as e:
|
|
33
|
+
# Catch-all for unexpected errors
|
|
34
|
+
log_error(f"An unexpected error occurred: {e}")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass
|
|
38
|
+
class OllamaEmbedder(Embedder):
|
|
39
|
+
id: str = "openhermes"
|
|
40
|
+
dimensions: int = 4096
|
|
41
|
+
host: Optional[str] = None
|
|
42
|
+
timeout: Optional[Any] = None
|
|
43
|
+
options: Optional[Any] = None
|
|
44
|
+
client_kwargs: Optional[Dict[str, Any]] = None
|
|
45
|
+
ollama_client: Optional[OllamaClient] = None
|
|
46
|
+
async_client: Optional[AsyncOllamaClient] = None
|
|
47
|
+
|
|
48
|
+
def __post_init__(self):
|
|
49
|
+
if self.enable_batch:
|
|
50
|
+
logger.warning("OllamaEmbedder does not support batch embeddings, setting enable_batch to False")
|
|
51
|
+
self.enable_batch = False
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def client(self) -> OllamaClient:
|
|
55
|
+
if self.ollama_client:
|
|
56
|
+
return self.ollama_client
|
|
57
|
+
|
|
58
|
+
_ollama_params: Dict[str, Any] = {
|
|
59
|
+
"host": self.host,
|
|
60
|
+
"timeout": self.timeout,
|
|
61
|
+
}
|
|
62
|
+
_ollama_params = {k: v for k, v in _ollama_params.items() if v is not None}
|
|
63
|
+
if self.client_kwargs:
|
|
64
|
+
_ollama_params.update(self.client_kwargs)
|
|
65
|
+
self.ollama_client = OllamaClient(**_ollama_params)
|
|
66
|
+
return self.ollama_client
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def aclient(self) -> AsyncOllamaClient:
|
|
70
|
+
if self.async_client:
|
|
71
|
+
return self.async_client
|
|
72
|
+
|
|
73
|
+
_ollama_params: Dict[str, Any] = {
|
|
74
|
+
"host": self.host,
|
|
75
|
+
"timeout": self.timeout,
|
|
76
|
+
}
|
|
77
|
+
_ollama_params = {k: v for k, v in _ollama_params.items() if v is not None}
|
|
78
|
+
if self.client_kwargs:
|
|
79
|
+
_ollama_params.update(self.client_kwargs)
|
|
80
|
+
self.async_client = AsyncOllamaClient(**_ollama_params)
|
|
81
|
+
return self.async_client
|
|
82
|
+
|
|
83
|
+
def _response(self, text: str) -> Dict[str, Any]:
|
|
84
|
+
kwargs: Dict[str, Any] = {}
|
|
85
|
+
if self.options is not None:
|
|
86
|
+
kwargs["options"] = self.options
|
|
87
|
+
|
|
88
|
+
# Add dimensions parameter for models that support it
|
|
89
|
+
if self.dimensions is not None:
|
|
90
|
+
kwargs["dimensions"] = self.dimensions
|
|
91
|
+
|
|
92
|
+
response = self.client.embed(input=text, model=self.id, **kwargs)
|
|
93
|
+
if response and "embeddings" in response:
|
|
94
|
+
embeddings = response["embeddings"]
|
|
95
|
+
if isinstance(embeddings, list) and len(embeddings) > 0 and isinstance(embeddings[0], list):
|
|
96
|
+
return {"embeddings": embeddings[0]} # Use the first element
|
|
97
|
+
elif isinstance(embeddings, list) and all(isinstance(x, (int, float)) for x in embeddings):
|
|
98
|
+
return {"embeddings": embeddings} # Return as-is if already flat
|
|
99
|
+
return {"embeddings": []} # Return an empty list if no valid embedding is found
|
|
100
|
+
|
|
101
|
+
def get_embedding(self, text: str) -> List[float]:
|
|
102
|
+
try:
|
|
103
|
+
response = self._response(text=text)
|
|
104
|
+
embedding = response.get("embeddings", [])
|
|
105
|
+
if len(embedding) != self.dimensions:
|
|
106
|
+
logger.warning(f"Expected embedding dimension {self.dimensions}, but got {len(embedding)}")
|
|
107
|
+
return []
|
|
108
|
+
return embedding
|
|
109
|
+
except Exception as e:
|
|
110
|
+
logger.warning(e)
|
|
111
|
+
return []
|
|
112
|
+
|
|
113
|
+
def get_embedding_and_usage(self, text: str) -> Tuple[List[float], Optional[Dict]]:
|
|
114
|
+
embedding = self.get_embedding(text=text)
|
|
115
|
+
usage = None
|
|
116
|
+
return embedding, usage
|
|
117
|
+
|
|
118
|
+
async def _async_response(self, text: str) -> Dict[str, Any]:
|
|
119
|
+
"""Async version of _response using AsyncOllamaClient."""
|
|
120
|
+
kwargs: Dict[str, Any] = {}
|
|
121
|
+
if self.options is not None:
|
|
122
|
+
kwargs["options"] = self.options
|
|
123
|
+
|
|
124
|
+
# Add dimensions parameter for models that support it
|
|
125
|
+
if self.dimensions is not None:
|
|
126
|
+
kwargs["dimensions"] = self.dimensions
|
|
127
|
+
|
|
128
|
+
response = await self.aclient.embed(input=text, model=self.id, **kwargs)
|
|
129
|
+
if response and "embeddings" in response:
|
|
130
|
+
embeddings = response["embeddings"]
|
|
131
|
+
if isinstance(embeddings, list) and len(embeddings) > 0 and isinstance(embeddings[0], list):
|
|
132
|
+
return {"embeddings": embeddings[0]} # Use the first element
|
|
133
|
+
elif isinstance(embeddings, list) and all(isinstance(x, (int, float)) for x in embeddings):
|
|
134
|
+
return {"embeddings": embeddings} # Return as-is if already flat
|
|
135
|
+
return {"embeddings": []} # Return an empty list if no valid embedding is found
|
|
136
|
+
|
|
137
|
+
async def async_get_embedding(self, text: str) -> List[float]:
|
|
138
|
+
"""Async version of get_embedding."""
|
|
139
|
+
try:
|
|
140
|
+
response = await self._async_response(text=text)
|
|
141
|
+
embedding = response.get("embeddings", [])
|
|
142
|
+
if len(embedding) != self.dimensions:
|
|
143
|
+
logger.warning(f"Expected embedding dimension {self.dimensions}, but got {len(embedding)}")
|
|
144
|
+
return []
|
|
145
|
+
return embedding
|
|
146
|
+
except Exception as e:
|
|
147
|
+
logger.warning(f"Error getting embedding: {e}")
|
|
148
|
+
return []
|
|
149
|
+
|
|
150
|
+
async def async_get_embedding_and_usage(self, text: str) -> Tuple[List[float], Optional[Dict]]:
|
|
151
|
+
"""Async version of get_embedding_and_usage."""
|
|
152
|
+
embedding = await self.async_get_embedding(text=text)
|
|
153
|
+
usage = None
|
|
154
|
+
return embedding, usage
|