agno 2.2.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 +51 -0
- agno/agent/agent.py +10405 -0
- agno/api/__init__.py +0 -0
- agno/api/agent.py +28 -0
- agno/api/api.py +40 -0
- agno/api/evals.py +22 -0
- agno/api/os.py +17 -0
- agno/api/routes.py +13 -0
- agno/api/schemas/__init__.py +9 -0
- agno/api/schemas/agent.py +16 -0
- agno/api/schemas/evals.py +16 -0
- agno/api/schemas/os.py +14 -0
- agno/api/schemas/response.py +6 -0
- agno/api/schemas/team.py +16 -0
- agno/api/schemas/utils.py +21 -0
- agno/api/schemas/workflows.py +16 -0
- agno/api/settings.py +53 -0
- agno/api/team.py +30 -0
- 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/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 +598 -0
- agno/db/dynamo/__init__.py +3 -0
- agno/db/dynamo/dynamo.py +2042 -0
- agno/db/dynamo/schemas.py +314 -0
- agno/db/dynamo/utils.py +743 -0
- agno/db/firestore/__init__.py +3 -0
- agno/db/firestore/firestore.py +1795 -0
- agno/db/firestore/schemas.py +140 -0
- agno/db/firestore/utils.py +376 -0
- agno/db/gcs_json/__init__.py +3 -0
- agno/db/gcs_json/gcs_json_db.py +1335 -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 +1160 -0
- agno/db/in_memory/utils.py +230 -0
- agno/db/json/__init__.py +3 -0
- agno/db/json/json_db.py +1328 -0
- agno/db/json/utils.py +230 -0
- agno/db/migrations/__init__.py +0 -0
- agno/db/migrations/v1_to_v2.py +635 -0
- agno/db/mongo/__init__.py +17 -0
- agno/db/mongo/async_mongo.py +2026 -0
- agno/db/mongo/mongo.py +1982 -0
- agno/db/mongo/schemas.py +87 -0
- agno/db/mongo/utils.py +259 -0
- agno/db/mysql/__init__.py +3 -0
- agno/db/mysql/mysql.py +2308 -0
- agno/db/mysql/schemas.py +138 -0
- agno/db/mysql/utils.py +355 -0
- agno/db/postgres/__init__.py +4 -0
- agno/db/postgres/async_postgres.py +1927 -0
- agno/db/postgres/postgres.py +2260 -0
- agno/db/postgres/schemas.py +139 -0
- agno/db/postgres/utils.py +442 -0
- agno/db/redis/__init__.py +3 -0
- agno/db/redis/redis.py +1660 -0
- agno/db/redis/schemas.py +123 -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 +33 -0
- agno/db/schemas/knowledge.py +40 -0
- agno/db/schemas/memory.py +46 -0
- agno/db/schemas/metrics.py +0 -0
- agno/db/singlestore/__init__.py +3 -0
- agno/db/singlestore/schemas.py +130 -0
- agno/db/singlestore/singlestore.py +2272 -0
- agno/db/singlestore/utils.py +384 -0
- agno/db/sqlite/__init__.py +4 -0
- agno/db/sqlite/async_sqlite.py +2293 -0
- agno/db/sqlite/schemas.py +133 -0
- agno/db/sqlite/sqlite.py +2288 -0
- agno/db/sqlite/utils.py +431 -0
- agno/db/surrealdb/__init__.py +3 -0
- agno/db/surrealdb/metrics.py +292 -0
- agno/db/surrealdb/models.py +309 -0
- agno/db/surrealdb/queries.py +71 -0
- agno/db/surrealdb/surrealdb.py +1353 -0
- agno/db/surrealdb/utils.py +147 -0
- agno/db/utils.py +116 -0
- agno/debug.py +18 -0
- agno/eval/__init__.py +14 -0
- agno/eval/accuracy.py +834 -0
- agno/eval/performance.py +773 -0
- agno/eval/reliability.py +306 -0
- agno/eval/utils.py +119 -0
- agno/exceptions.py +161 -0
- 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/integrations/__init__.py +0 -0
- agno/integrations/discord/__init__.py +3 -0
- agno/integrations/discord/client.py +203 -0
- agno/knowledge/__init__.py +5 -0
- agno/knowledge/chunking/__init__.py +0 -0
- agno/knowledge/chunking/agentic.py +79 -0
- agno/knowledge/chunking/document.py +91 -0
- agno/knowledge/chunking/fixed.py +57 -0
- agno/knowledge/chunking/markdown.py +151 -0
- agno/knowledge/chunking/recursive.py +63 -0
- agno/knowledge/chunking/row.py +39 -0
- agno/knowledge/chunking/semantic.py +86 -0
- agno/knowledge/chunking/strategy.py +165 -0
- agno/knowledge/content.py +74 -0
- agno/knowledge/document/__init__.py +5 -0
- agno/knowledge/document/base.py +58 -0
- agno/knowledge/embedder/__init__.py +5 -0
- agno/knowledge/embedder/aws_bedrock.py +343 -0
- agno/knowledge/embedder/azure_openai.py +210 -0
- agno/knowledge/embedder/base.py +23 -0
- agno/knowledge/embedder/cohere.py +323 -0
- agno/knowledge/embedder/fastembed.py +62 -0
- agno/knowledge/embedder/fireworks.py +13 -0
- 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/knowledge/embedder/together.py +13 -0
- agno/knowledge/embedder/vllm.py +262 -0
- agno/knowledge/embedder/voyageai.py +165 -0
- agno/knowledge/knowledge.py +1988 -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 +166 -0
- agno/knowledge/reader/docx_reader.py +82 -0
- agno/knowledge/reader/field_labeled_csv_reader.py +292 -0
- agno/knowledge/reader/firecrawl_reader.py +201 -0
- agno/knowledge/reader/json_reader.py +87 -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 +194 -0
- agno/knowledge/reader/text_reader.py +115 -0
- agno/knowledge/reader/web_search_reader.py +372 -0
- agno/knowledge/reader/website_reader.py +455 -0
- agno/knowledge/reader/wikipedia_reader.py +59 -0
- agno/knowledge/reader/youtube_reader.py +78 -0
- agno/knowledge/remote_content/__init__.py +0 -0
- agno/knowledge/remote_content/remote_content.py +88 -0
- agno/knowledge/reranker/__init__.py +3 -0
- agno/knowledge/reranker/base.py +14 -0
- agno/knowledge/reranker/cohere.py +64 -0
- 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 +189 -0
- agno/media.py +462 -0
- agno/memory/__init__.py +3 -0
- agno/memory/manager.py +1327 -0
- agno/models/__init__.py +0 -0
- agno/models/aimlapi/__init__.py +5 -0
- agno/models/aimlapi/aimlapi.py +45 -0
- agno/models/anthropic/__init__.py +5 -0
- agno/models/anthropic/claude.py +757 -0
- agno/models/aws/__init__.py +15 -0
- agno/models/aws/bedrock.py +701 -0
- agno/models/aws/claude.py +378 -0
- agno/models/azure/__init__.py +18 -0
- agno/models/azure/ai_foundry.py +485 -0
- agno/models/azure/openai_chat.py +131 -0
- agno/models/base.py +2175 -0
- agno/models/cerebras/__init__.py +12 -0
- agno/models/cerebras/cerebras.py +501 -0
- agno/models/cerebras/cerebras_openai.py +112 -0
- agno/models/cohere/__init__.py +5 -0
- agno/models/cohere/chat.py +389 -0
- agno/models/cometapi/__init__.py +5 -0
- agno/models/cometapi/cometapi.py +57 -0
- agno/models/dashscope/__init__.py +5 -0
- agno/models/dashscope/dashscope.py +91 -0
- agno/models/deepinfra/__init__.py +5 -0
- agno/models/deepinfra/deepinfra.py +28 -0
- agno/models/deepseek/__init__.py +5 -0
- agno/models/deepseek/deepseek.py +61 -0
- agno/models/defaults.py +1 -0
- agno/models/fireworks/__init__.py +5 -0
- agno/models/fireworks/fireworks.py +26 -0
- agno/models/google/__init__.py +5 -0
- agno/models/google/gemini.py +1085 -0
- agno/models/groq/__init__.py +5 -0
- agno/models/groq/groq.py +556 -0
- agno/models/huggingface/__init__.py +5 -0
- agno/models/huggingface/huggingface.py +491 -0
- agno/models/ibm/__init__.py +5 -0
- agno/models/ibm/watsonx.py +422 -0
- agno/models/internlm/__init__.py +3 -0
- agno/models/internlm/internlm.py +26 -0
- agno/models/langdb/__init__.py +1 -0
- agno/models/langdb/langdb.py +48 -0
- agno/models/litellm/__init__.py +14 -0
- agno/models/litellm/chat.py +468 -0
- agno/models/litellm/litellm_openai.py +25 -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 +434 -0
- agno/models/meta/__init__.py +12 -0
- agno/models/meta/llama.py +475 -0
- agno/models/meta/llama_openai.py +78 -0
- agno/models/metrics.py +120 -0
- agno/models/mistral/__init__.py +5 -0
- agno/models/mistral/mistral.py +432 -0
- agno/models/nebius/__init__.py +3 -0
- agno/models/nebius/nebius.py +54 -0
- agno/models/nexus/__init__.py +3 -0
- agno/models/nexus/nexus.py +22 -0
- agno/models/nvidia/__init__.py +5 -0
- agno/models/nvidia/nvidia.py +28 -0
- agno/models/ollama/__init__.py +5 -0
- agno/models/ollama/chat.py +441 -0
- agno/models/openai/__init__.py +9 -0
- agno/models/openai/chat.py +883 -0
- agno/models/openai/like.py +27 -0
- agno/models/openai/responses.py +1050 -0
- agno/models/openrouter/__init__.py +5 -0
- agno/models/openrouter/openrouter.py +66 -0
- agno/models/perplexity/__init__.py +5 -0
- agno/models/perplexity/perplexity.py +187 -0
- agno/models/portkey/__init__.py +3 -0
- agno/models/portkey/portkey.py +81 -0
- agno/models/requesty/__init__.py +5 -0
- agno/models/requesty/requesty.py +52 -0
- agno/models/response.py +199 -0
- agno/models/sambanova/__init__.py +5 -0
- agno/models/sambanova/sambanova.py +28 -0
- agno/models/siliconflow/__init__.py +5 -0
- agno/models/siliconflow/siliconflow.py +25 -0
- agno/models/together/__init__.py +5 -0
- agno/models/together/together.py +25 -0
- agno/models/utils.py +266 -0
- agno/models/vercel/__init__.py +3 -0
- agno/models/vercel/v0.py +26 -0
- agno/models/vertexai/__init__.py +0 -0
- agno/models/vertexai/claude.py +70 -0
- agno/models/vllm/__init__.py +3 -0
- agno/models/vllm/vllm.py +78 -0
- agno/models/xai/__init__.py +3 -0
- agno/models/xai/xai.py +113 -0
- agno/os/__init__.py +3 -0
- agno/os/app.py +876 -0
- agno/os/auth.py +57 -0
- agno/os/config.py +104 -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 +250 -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 +144 -0
- agno/os/interfaces/agui/utils.py +534 -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 +211 -0
- agno/os/interfaces/whatsapp/security.py +53 -0
- agno/os/interfaces/whatsapp/whatsapp.py +36 -0
- agno/os/mcp.py +292 -0
- agno/os/middleware/__init__.py +7 -0
- agno/os/middleware/jwt.py +233 -0
- agno/os/router.py +1763 -0
- agno/os/routers/__init__.py +3 -0
- agno/os/routers/evals/__init__.py +3 -0
- agno/os/routers/evals/evals.py +430 -0
- agno/os/routers/evals/schemas.py +142 -0
- agno/os/routers/evals/utils.py +162 -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 +997 -0
- agno/os/routers/knowledge/schemas.py +178 -0
- agno/os/routers/memory/__init__.py +3 -0
- agno/os/routers/memory/memory.py +515 -0
- agno/os/routers/memory/schemas.py +62 -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/schema.py +1055 -0
- agno/os/settings.py +43 -0
- agno/os/utils.py +630 -0
- agno/py.typed +0 -0
- agno/reasoning/__init__.py +0 -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 +63 -0
- agno/reasoning/ollama.py +67 -0
- agno/reasoning/openai.py +86 -0
- agno/reasoning/step.py +31 -0
- agno/reasoning/vertexai.py +76 -0
- agno/run/__init__.py +6 -0
- agno/run/agent.py +787 -0
- agno/run/base.py +229 -0
- agno/run/cancel.py +81 -0
- agno/run/messages.py +32 -0
- agno/run/team.py +753 -0
- agno/run/workflow.py +708 -0
- agno/session/__init__.py +10 -0
- agno/session/agent.py +295 -0
- agno/session/summary.py +265 -0
- agno/session/team.py +392 -0
- agno/session/workflow.py +205 -0
- agno/team/__init__.py +37 -0
- agno/team/team.py +8793 -0
- agno/tools/__init__.py +10 -0
- agno/tools/agentql.py +120 -0
- agno/tools/airflow.py +69 -0
- agno/tools/api.py +122 -0
- agno/tools/apify.py +314 -0
- agno/tools/arxiv.py +127 -0
- agno/tools/aws_lambda.py +53 -0
- agno/tools/aws_ses.py +66 -0
- agno/tools/baidusearch.py +89 -0
- 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 +255 -0
- agno/tools/calculator.py +151 -0
- agno/tools/cartesia.py +187 -0
- agno/tools/clickup.py +244 -0
- agno/tools/confluence.py +240 -0
- agno/tools/crawl4ai.py +158 -0
- agno/tools/csv_toolkit.py +185 -0
- agno/tools/dalle.py +110 -0
- agno/tools/daytona.py +475 -0
- agno/tools/decorator.py +262 -0
- agno/tools/desi_vocal.py +108 -0
- agno/tools/discord.py +161 -0
- agno/tools/docker.py +716 -0
- agno/tools/duckdb.py +379 -0
- agno/tools/duckduckgo.py +91 -0
- agno/tools/e2b.py +703 -0
- agno/tools/eleven_labs.py +196 -0
- agno/tools/email.py +67 -0
- agno/tools/evm.py +129 -0
- agno/tools/exa.py +396 -0
- agno/tools/fal.py +127 -0
- agno/tools/file.py +240 -0
- agno/tools/file_generation.py +350 -0
- agno/tools/financial_datasets.py +288 -0
- agno/tools/firecrawl.py +143 -0
- agno/tools/function.py +1187 -0
- agno/tools/giphy.py +93 -0
- agno/tools/github.py +1760 -0
- agno/tools/gmail.py +922 -0
- agno/tools/google_bigquery.py +117 -0
- agno/tools/google_drive.py +270 -0
- agno/tools/google_maps.py +253 -0
- agno/tools/googlecalendar.py +674 -0
- agno/tools/googlesearch.py +98 -0
- agno/tools/googlesheets.py +377 -0
- agno/tools/hackernews.py +77 -0
- agno/tools/jina.py +101 -0
- agno/tools/jira.py +170 -0
- agno/tools/knowledge.py +218 -0
- agno/tools/linear.py +426 -0
- agno/tools/linkup.py +58 -0
- agno/tools/local_file_system.py +90 -0
- agno/tools/lumalab.py +183 -0
- 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/memori.py +339 -0
- agno/tools/memory.py +419 -0
- agno/tools/mlx_transcribe.py +139 -0
- agno/tools/models/__init__.py +0 -0
- 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 +195 -0
- agno/tools/moviepy_video.py +349 -0
- agno/tools/neo4j.py +134 -0
- agno/tools/newspaper.py +46 -0
- agno/tools/newspaper4k.py +93 -0
- agno/tools/notion.py +204 -0
- agno/tools/openai.py +202 -0
- agno/tools/openbb.py +160 -0
- agno/tools/opencv.py +321 -0
- agno/tools/openweather.py +233 -0
- agno/tools/oxylabs.py +385 -0
- agno/tools/pandas.py +102 -0
- agno/tools/parallel.py +314 -0
- agno/tools/postgres.py +257 -0
- agno/tools/pubmed.py +188 -0
- agno/tools/python.py +205 -0
- agno/tools/reasoning.py +283 -0
- agno/tools/reddit.py +467 -0
- agno/tools/replicate.py +117 -0
- agno/tools/resend.py +62 -0
- agno/tools/scrapegraph.py +222 -0
- agno/tools/searxng.py +152 -0
- agno/tools/serpapi.py +116 -0
- agno/tools/serper.py +255 -0
- agno/tools/shell.py +53 -0
- agno/tools/slack.py +136 -0
- agno/tools/sleep.py +20 -0
- agno/tools/spider.py +116 -0
- agno/tools/sql.py +154 -0
- agno/tools/streamlit/__init__.py +0 -0
- agno/tools/streamlit/components.py +113 -0
- agno/tools/tavily.py +254 -0
- agno/tools/telegram.py +48 -0
- agno/tools/todoist.py +218 -0
- agno/tools/tool_registry.py +1 -0
- agno/tools/toolkit.py +146 -0
- agno/tools/trafilatura.py +388 -0
- agno/tools/trello.py +274 -0
- agno/tools/twilio.py +186 -0
- 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 +54 -0
- agno/tools/webtools.py +45 -0
- agno/tools/whatsapp.py +286 -0
- agno/tools/wikipedia.py +63 -0
- agno/tools/workflow.py +278 -0
- agno/tools/x.py +335 -0
- agno/tools/yfinance.py +257 -0
- agno/tools/youtube.py +184 -0
- agno/tools/zendesk.py +82 -0
- agno/tools/zep.py +454 -0
- agno/tools/zoom.py +382 -0
- agno/utils/__init__.py +0 -0
- agno/utils/agent.py +820 -0
- agno/utils/audio.py +49 -0
- agno/utils/certs.py +27 -0
- agno/utils/code_execution.py +11 -0
- agno/utils/common.py +132 -0
- agno/utils/dttm.py +13 -0
- agno/utils/enum.py +22 -0
- agno/utils/env.py +11 -0
- agno/utils/events.py +696 -0
- agno/utils/format_str.py +16 -0
- agno/utils/functions.py +166 -0
- agno/utils/gemini.py +426 -0
- agno/utils/hooks.py +57 -0
- agno/utils/http.py +74 -0
- agno/utils/json_schema.py +234 -0
- agno/utils/knowledge.py +36 -0
- agno/utils/location.py +19 -0
- agno/utils/log.py +255 -0
- agno/utils/mcp.py +214 -0
- agno/utils/media.py +352 -0
- agno/utils/merge_dict.py +41 -0
- agno/utils/message.py +118 -0
- agno/utils/models/__init__.py +0 -0
- agno/utils/models/ai_foundry.py +43 -0
- agno/utils/models/claude.py +358 -0
- agno/utils/models/cohere.py +87 -0
- agno/utils/models/llama.py +78 -0
- agno/utils/models/mistral.py +98 -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 +32 -0
- agno/utils/pprint.py +178 -0
- agno/utils/print_response/__init__.py +0 -0
- agno/utils/print_response/agent.py +842 -0
- agno/utils/print_response/team.py +1724 -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/response_iterator.py +17 -0
- agno/utils/safe_formatter.py +24 -0
- agno/utils/serialize.py +32 -0
- agno/utils/shell.py +22 -0
- agno/utils/streamlit.py +487 -0
- agno/utils/string.py +231 -0
- agno/utils/team.py +139 -0
- agno/utils/timer.py +41 -0
- agno/utils/tools.py +102 -0
- agno/utils/web.py +23 -0
- agno/utils/whatsapp.py +305 -0
- agno/utils/yaml_io.py +25 -0
- agno/vectordb/__init__.py +3 -0
- agno/vectordb/base.py +127 -0
- agno/vectordb/cassandra/__init__.py +5 -0
- agno/vectordb/cassandra/cassandra.py +501 -0
- agno/vectordb/cassandra/extra_param_mixin.py +11 -0
- agno/vectordb/cassandra/index.py +13 -0
- agno/vectordb/chroma/__init__.py +5 -0
- agno/vectordb/chroma/chromadb.py +929 -0
- agno/vectordb/clickhouse/__init__.py +9 -0
- agno/vectordb/clickhouse/clickhousedb.py +835 -0
- agno/vectordb/clickhouse/index.py +9 -0
- agno/vectordb/couchbase/__init__.py +3 -0
- agno/vectordb/couchbase/couchbase.py +1442 -0
- agno/vectordb/distance.py +7 -0
- agno/vectordb/lancedb/__init__.py +6 -0
- agno/vectordb/lancedb/lance_db.py +995 -0
- 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 +4 -0
- agno/vectordb/milvus/milvus.py +1182 -0
- agno/vectordb/mongodb/__init__.py +9 -0
- agno/vectordb/mongodb/mongodb.py +1417 -0
- agno/vectordb/pgvector/__init__.py +12 -0
- agno/vectordb/pgvector/index.py +23 -0
- agno/vectordb/pgvector/pgvector.py +1462 -0
- agno/vectordb/pineconedb/__init__.py +5 -0
- agno/vectordb/pineconedb/pineconedb.py +747 -0
- agno/vectordb/qdrant/__init__.py +5 -0
- agno/vectordb/qdrant/qdrant.py +1134 -0
- agno/vectordb/redis/__init__.py +9 -0
- agno/vectordb/redis/redisdb.py +694 -0
- agno/vectordb/search.py +7 -0
- agno/vectordb/singlestore/__init__.py +10 -0
- agno/vectordb/singlestore/index.py +41 -0
- agno/vectordb/singlestore/singlestore.py +763 -0
- agno/vectordb/surrealdb/__init__.py +3 -0
- agno/vectordb/surrealdb/surrealdb.py +699 -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 +1005 -0
- agno/workflow/__init__.py +23 -0
- agno/workflow/agent.py +299 -0
- agno/workflow/condition.py +738 -0
- agno/workflow/loop.py +735 -0
- agno/workflow/parallel.py +824 -0
- agno/workflow/router.py +702 -0
- agno/workflow/step.py +1432 -0
- agno/workflow/steps.py +592 -0
- agno/workflow/types.py +520 -0
- agno/workflow/workflow.py +4321 -0
- agno-2.2.13.dist-info/METADATA +614 -0
- agno-2.2.13.dist-info/RECORD +575 -0
- agno-2.2.13.dist-info/WHEEL +5 -0
- agno-2.2.13.dist-info/licenses/LICENSE +201 -0
- agno-2.2.13.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, ConfigDict
|
|
4
|
+
|
|
5
|
+
from agno.knowledge.document import Document
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Reranker(BaseModel):
|
|
9
|
+
"""Base class for rerankers"""
|
|
10
|
+
|
|
11
|
+
model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True)
|
|
12
|
+
|
|
13
|
+
def rerank(self, query: str, documents: List[Document]) -> List[Document]:
|
|
14
|
+
raise NotImplementedError
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
from typing import Any, Dict, List, Optional
|
|
2
|
+
|
|
3
|
+
from agno.knowledge.document import Document
|
|
4
|
+
from agno.knowledge.reranker.base import Reranker
|
|
5
|
+
from agno.utils.log import logger
|
|
6
|
+
|
|
7
|
+
try:
|
|
8
|
+
from cohere import Client as CohereClient
|
|
9
|
+
except ImportError:
|
|
10
|
+
raise ImportError("cohere not installed, please run pip install cohere")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class CohereReranker(Reranker):
|
|
14
|
+
model: str = "rerank-multilingual-v3.0"
|
|
15
|
+
api_key: Optional[str] = None
|
|
16
|
+
cohere_client: Optional[CohereClient] = None
|
|
17
|
+
top_n: Optional[int] = None
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def client(self) -> CohereClient:
|
|
21
|
+
if self.cohere_client:
|
|
22
|
+
return self.cohere_client
|
|
23
|
+
|
|
24
|
+
_client_params: Dict[str, Any] = {}
|
|
25
|
+
if self.api_key:
|
|
26
|
+
_client_params["api_key"] = self.api_key
|
|
27
|
+
return CohereClient(**_client_params)
|
|
28
|
+
|
|
29
|
+
def _rerank(self, query: str, documents: List[Document]) -> List[Document]:
|
|
30
|
+
# Validate input documents and top_n
|
|
31
|
+
if not documents:
|
|
32
|
+
return []
|
|
33
|
+
|
|
34
|
+
top_n = self.top_n
|
|
35
|
+
if top_n and not (0 < top_n):
|
|
36
|
+
logger.warning(f"top_n should be a positive integer, got {self.top_n}, setting top_n to None")
|
|
37
|
+
top_n = None
|
|
38
|
+
|
|
39
|
+
compressed_docs: list[Document] = []
|
|
40
|
+
_docs = [doc.content for doc in documents]
|
|
41
|
+
response = self.client.rerank(query=query, documents=_docs, model=self.model)
|
|
42
|
+
for r in response.results:
|
|
43
|
+
doc = documents[r.index]
|
|
44
|
+
doc.reranking_score = r.relevance_score
|
|
45
|
+
compressed_docs.append(doc)
|
|
46
|
+
|
|
47
|
+
# Order by relevance score
|
|
48
|
+
compressed_docs.sort(
|
|
49
|
+
key=lambda x: x.reranking_score if x.reranking_score is not None else float("-inf"),
|
|
50
|
+
reverse=True,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
# Limit to top_n if specified
|
|
54
|
+
if top_n:
|
|
55
|
+
compressed_docs = compressed_docs[:top_n]
|
|
56
|
+
|
|
57
|
+
return compressed_docs
|
|
58
|
+
|
|
59
|
+
def rerank(self, query: str, documents: List[Document]) -> List[Document]:
|
|
60
|
+
try:
|
|
61
|
+
return self._rerank(query=query, documents=documents)
|
|
62
|
+
except Exception as e:
|
|
63
|
+
logger.error(f"Error reranking documents: {e}. Returning original documents")
|
|
64
|
+
return documents
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
from typing import Any, List, Optional
|
|
2
|
+
from urllib.parse import urlparse
|
|
3
|
+
|
|
4
|
+
from agno.knowledge.document import Document
|
|
5
|
+
from agno.knowledge.reranker.base import Reranker
|
|
6
|
+
from agno.utils.log import logger
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
from infinity_client import AuthenticatedClient, Client
|
|
10
|
+
from infinity_client.api.default import rerank
|
|
11
|
+
from infinity_client.models import RerankInput
|
|
12
|
+
except ImportError:
|
|
13
|
+
raise ImportError("infinity_client not installed, please run `pip install infinity_client`")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class InfinityReranker(Reranker):
|
|
17
|
+
model: str = "BAAI/bge-reranker-base"
|
|
18
|
+
host: str = "localhost"
|
|
19
|
+
port: int = 7997
|
|
20
|
+
url: Optional[str] = None
|
|
21
|
+
top_n: Optional[int] = None
|
|
22
|
+
api_key: Optional[str] = None
|
|
23
|
+
verify_ssl: bool = True
|
|
24
|
+
_client: Optional[Any] = None
|
|
25
|
+
|
|
26
|
+
def __init__(self, **kwargs):
|
|
27
|
+
super().__init__(**kwargs)
|
|
28
|
+
if self.url:
|
|
29
|
+
self._parse_url()
|
|
30
|
+
|
|
31
|
+
def _parse_url(self):
|
|
32
|
+
"""Parse URL to extract host, port and path"""
|
|
33
|
+
if self.url:
|
|
34
|
+
parsed = urlparse(self.url)
|
|
35
|
+
if parsed.hostname:
|
|
36
|
+
self.host = parsed.hostname
|
|
37
|
+
if parsed.port:
|
|
38
|
+
self.port = parsed.port
|
|
39
|
+
# If no port specified in URL, keep default port
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def base_url(self) -> str:
|
|
43
|
+
"""Construct the base URL for the Infinity server"""
|
|
44
|
+
return f"http://{self.host}:{self.port}"
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def client(self) -> Any:
|
|
48
|
+
"""Get or create the infinity client"""
|
|
49
|
+
if self._client:
|
|
50
|
+
return self._client
|
|
51
|
+
|
|
52
|
+
base_url = self.base_url
|
|
53
|
+
|
|
54
|
+
if self.api_key:
|
|
55
|
+
self._client = AuthenticatedClient(base_url=base_url, token=self.api_key, verify_ssl=self.verify_ssl)
|
|
56
|
+
else:
|
|
57
|
+
self._client = Client(base_url=base_url, verify_ssl=self.verify_ssl)
|
|
58
|
+
|
|
59
|
+
return self._client
|
|
60
|
+
|
|
61
|
+
def _rerank(self, query: str, documents: List[Document]) -> List[Document]:
|
|
62
|
+
# Validate input documents and top_n
|
|
63
|
+
if not documents:
|
|
64
|
+
return []
|
|
65
|
+
|
|
66
|
+
top_n = self.top_n
|
|
67
|
+
if top_n and not (0 < top_n):
|
|
68
|
+
logger.warning(f"top_n should be a positive integer, got {self.top_n}, setting top_n to None")
|
|
69
|
+
top_n = None
|
|
70
|
+
|
|
71
|
+
compressed_docs: list[Document] = []
|
|
72
|
+
|
|
73
|
+
try:
|
|
74
|
+
# Prepare the request body for Infinity reranking
|
|
75
|
+
rerank_input = {
|
|
76
|
+
"model": self.model,
|
|
77
|
+
"query": query,
|
|
78
|
+
"documents": [doc.content for doc in documents],
|
|
79
|
+
"return_documents": False, # We only need scores, we already have documents
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
# Add top_n to payload if specified
|
|
83
|
+
if top_n:
|
|
84
|
+
rerank_input["top_n"] = top_n
|
|
85
|
+
|
|
86
|
+
# Create the input object
|
|
87
|
+
body = RerankInput.from_dict(rerank_input)
|
|
88
|
+
|
|
89
|
+
# Make request to Infinity rerank endpoint using the client
|
|
90
|
+
with self.client as client:
|
|
91
|
+
result = rerank.sync(client=client, body=body)
|
|
92
|
+
|
|
93
|
+
if result is None:
|
|
94
|
+
logger.error("Rerank request returned None")
|
|
95
|
+
return documents
|
|
96
|
+
|
|
97
|
+
# Process the response
|
|
98
|
+
# Infinity returns results with index and relevance_score
|
|
99
|
+
if hasattr(result, "results") and result.results:
|
|
100
|
+
for item in result.results:
|
|
101
|
+
doc_index = item.index
|
|
102
|
+
relevance_score = item.relevance_score
|
|
103
|
+
|
|
104
|
+
if doc_index < len(documents):
|
|
105
|
+
doc = documents[doc_index]
|
|
106
|
+
doc.reranking_score = relevance_score
|
|
107
|
+
compressed_docs.append(doc)
|
|
108
|
+
|
|
109
|
+
# Order by relevance score
|
|
110
|
+
compressed_docs.sort(
|
|
111
|
+
key=lambda x: x.reranking_score if x.reranking_score is not None else float("-inf"),
|
|
112
|
+
reverse=True,
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
# Limit to top_n if specified and not already limited by the API
|
|
116
|
+
if top_n and len(compressed_docs) > top_n:
|
|
117
|
+
compressed_docs = compressed_docs[:top_n]
|
|
118
|
+
|
|
119
|
+
except Exception as e:
|
|
120
|
+
logger.error(f"Error connecting to Infinity server at {self.base_url}: {e}")
|
|
121
|
+
return documents
|
|
122
|
+
|
|
123
|
+
return compressed_docs
|
|
124
|
+
|
|
125
|
+
def rerank(self, query: str, documents: List[Document]) -> List[Document]:
|
|
126
|
+
try:
|
|
127
|
+
return self._rerank(query=query, documents=documents)
|
|
128
|
+
except Exception as e:
|
|
129
|
+
logger.error(f"Error reranking documents: {e}. Returning original documents")
|
|
130
|
+
return documents
|
|
131
|
+
|
|
132
|
+
async def arerank(self, query: str, documents: List[Document]) -> List[Document]:
|
|
133
|
+
"""Async version of rerank"""
|
|
134
|
+
# Validate input documents and top_n
|
|
135
|
+
if not documents:
|
|
136
|
+
return []
|
|
137
|
+
|
|
138
|
+
top_n = self.top_n
|
|
139
|
+
if top_n and not (0 < top_n):
|
|
140
|
+
logger.warning(f"top_n should be a positive integer, got {self.top_n}, setting top_n to None")
|
|
141
|
+
top_n = None
|
|
142
|
+
|
|
143
|
+
compressed_docs: list[Document] = []
|
|
144
|
+
|
|
145
|
+
try:
|
|
146
|
+
# Prepare the request body for Infinity reranking
|
|
147
|
+
rerank_input = {
|
|
148
|
+
"model": self.model,
|
|
149
|
+
"query": query,
|
|
150
|
+
"documents": [doc.content for doc in documents],
|
|
151
|
+
"return_documents": False, # We only need scores, we already have documents
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
# Add top_n to payload if specified
|
|
155
|
+
if top_n:
|
|
156
|
+
rerank_input["top_n"] = top_n
|
|
157
|
+
|
|
158
|
+
# Create the input object
|
|
159
|
+
body = RerankInput.from_dict(rerank_input)
|
|
160
|
+
|
|
161
|
+
# Make async request to Infinity rerank endpoint using the client
|
|
162
|
+
async with self.client as client:
|
|
163
|
+
result = await rerank.asyncio(client=client, body=body)
|
|
164
|
+
|
|
165
|
+
if result is None:
|
|
166
|
+
logger.error("Async rerank request returned None")
|
|
167
|
+
return documents
|
|
168
|
+
|
|
169
|
+
# Process the response
|
|
170
|
+
# Infinity returns results with index and relevance_score
|
|
171
|
+
if hasattr(result, "results") and result.results:
|
|
172
|
+
for item in result.results:
|
|
173
|
+
doc_index = item.index
|
|
174
|
+
relevance_score = item.relevance_score
|
|
175
|
+
|
|
176
|
+
if doc_index < len(documents):
|
|
177
|
+
doc = documents[doc_index]
|
|
178
|
+
doc.reranking_score = relevance_score
|
|
179
|
+
compressed_docs.append(doc)
|
|
180
|
+
|
|
181
|
+
# Order by relevance score
|
|
182
|
+
compressed_docs.sort(
|
|
183
|
+
key=lambda x: x.reranking_score if x.reranking_score is not None else float("-inf"),
|
|
184
|
+
reverse=True,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
# Limit to top_n if specified and not already limited by the API
|
|
188
|
+
if top_n and len(compressed_docs) > top_n:
|
|
189
|
+
compressed_docs = compressed_docs[:top_n]
|
|
190
|
+
|
|
191
|
+
except Exception as e:
|
|
192
|
+
logger.error(f"Error connecting to Infinity server at {self.base_url}: {e}")
|
|
193
|
+
return documents
|
|
194
|
+
|
|
195
|
+
return compressed_docs
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
from typing import Any, Dict, List, Optional
|
|
2
|
+
|
|
3
|
+
from agno.knowledge.document import Document
|
|
4
|
+
from agno.knowledge.reranker.base import Reranker
|
|
5
|
+
from agno.utils.log import logger
|
|
6
|
+
|
|
7
|
+
try:
|
|
8
|
+
from sentence_transformers import CrossEncoder
|
|
9
|
+
except ImportError:
|
|
10
|
+
raise ImportError("`sentence-transformers` not installed, please run `pip install sentence-transformers`")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class SentenceTransformerReranker(Reranker):
|
|
14
|
+
model: str = "BAAI/bge-reranker-v2-m3"
|
|
15
|
+
model_kwargs: Optional[Dict[str, Any]] = None
|
|
16
|
+
top_n: Optional[int] = None
|
|
17
|
+
|
|
18
|
+
def _rerank(self, query: str, documents: List[Document]) -> List[Document]:
|
|
19
|
+
if not documents:
|
|
20
|
+
return []
|
|
21
|
+
|
|
22
|
+
sentence_transformer_client = CrossEncoder(model_name_or_path=self.model, model_kwargs=self.model_kwargs)
|
|
23
|
+
|
|
24
|
+
top_n = self.top_n
|
|
25
|
+
if top_n and not (0 < top_n):
|
|
26
|
+
logger.warning(f"top_n should be a positive integer, got {self.top_n}, setting top_n to None")
|
|
27
|
+
top_n = None
|
|
28
|
+
|
|
29
|
+
compressed_docs: list[Document] = []
|
|
30
|
+
|
|
31
|
+
sentence_pairs = [[query, doc.content] for doc in documents]
|
|
32
|
+
|
|
33
|
+
scores = sentence_transformer_client.predict(sentence_pairs).tolist()
|
|
34
|
+
for index, score in enumerate(scores):
|
|
35
|
+
doc = documents[index]
|
|
36
|
+
doc.reranking_score = score
|
|
37
|
+
compressed_docs.append(doc)
|
|
38
|
+
|
|
39
|
+
compressed_docs.sort(
|
|
40
|
+
key=lambda x: x.reranking_score if x.reranking_score is not None else float("-inf"),
|
|
41
|
+
reverse=True,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
if top_n:
|
|
45
|
+
compressed_docs = compressed_docs[:top_n]
|
|
46
|
+
|
|
47
|
+
return compressed_docs
|
|
48
|
+
|
|
49
|
+
def rerank(self, query: str, documents: List[Document]) -> List[Document]:
|
|
50
|
+
try:
|
|
51
|
+
return self._rerank(query=query, documents=documents)
|
|
52
|
+
except Exception as e:
|
|
53
|
+
logger.error(f"Error reranking documents: {e}. Returning original documents")
|
|
54
|
+
return documents
|
agno/knowledge/types.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ContentType(str, Enum):
|
|
8
|
+
"""Enum for content types supported by knowledge readers."""
|
|
9
|
+
|
|
10
|
+
# Generic types
|
|
11
|
+
FILE = "file"
|
|
12
|
+
URL = "url"
|
|
13
|
+
TEXT = "text"
|
|
14
|
+
TOPIC = "topic"
|
|
15
|
+
YOUTUBE = "youtube"
|
|
16
|
+
|
|
17
|
+
# Document file extensions
|
|
18
|
+
PDF = ".pdf"
|
|
19
|
+
TXT = ".txt"
|
|
20
|
+
MARKDOWN = ".md"
|
|
21
|
+
DOCX = ".docx"
|
|
22
|
+
DOC = ".doc"
|
|
23
|
+
PPTX = ".pptx"
|
|
24
|
+
JSON = ".json"
|
|
25
|
+
|
|
26
|
+
# Spreadsheet file extensions
|
|
27
|
+
CSV = ".csv"
|
|
28
|
+
XLSX = ".xlsx"
|
|
29
|
+
XLS = ".xls"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get_content_type_enum(content_type_str: str) -> ContentType:
|
|
33
|
+
"""Convert a content type string to ContentType enum."""
|
|
34
|
+
return ContentType(content_type_str)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class KnowledgeFilter(BaseModel):
|
|
38
|
+
key: str
|
|
39
|
+
value: Any
|
agno/knowledge/utils.py
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
from typing import Dict, List
|
|
2
|
+
|
|
3
|
+
from agno.knowledge.reader.reader_factory import ReaderFactory
|
|
4
|
+
from agno.knowledge.types import ContentType
|
|
5
|
+
from agno.utils.log import log_debug
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _get_chunker_class(strategy_type):
|
|
9
|
+
"""Get the chunker class for a given strategy type without instantiation."""
|
|
10
|
+
from agno.knowledge.chunking.strategy import ChunkingStrategyType
|
|
11
|
+
|
|
12
|
+
# Map strategy types to their corresponding classes
|
|
13
|
+
strategy_class_mapping = {
|
|
14
|
+
ChunkingStrategyType.AGENTIC_CHUNKER: lambda: _import_class(
|
|
15
|
+
"agno.knowledge.chunking.agentic", "AgenticChunking"
|
|
16
|
+
),
|
|
17
|
+
ChunkingStrategyType.DOCUMENT_CHUNKER: lambda: _import_class(
|
|
18
|
+
"agno.knowledge.chunking.document", "DocumentChunking"
|
|
19
|
+
),
|
|
20
|
+
ChunkingStrategyType.RECURSIVE_CHUNKER: lambda: _import_class(
|
|
21
|
+
"agno.knowledge.chunking.recursive", "RecursiveChunking"
|
|
22
|
+
),
|
|
23
|
+
ChunkingStrategyType.SEMANTIC_CHUNKER: lambda: _import_class(
|
|
24
|
+
"agno.knowledge.chunking.semantic", "SemanticChunking"
|
|
25
|
+
),
|
|
26
|
+
ChunkingStrategyType.FIXED_SIZE_CHUNKER: lambda: _import_class(
|
|
27
|
+
"agno.knowledge.chunking.fixed", "FixedSizeChunking"
|
|
28
|
+
),
|
|
29
|
+
ChunkingStrategyType.ROW_CHUNKER: lambda: _import_class("agno.knowledge.chunking.row", "RowChunking"),
|
|
30
|
+
ChunkingStrategyType.MARKDOWN_CHUNKER: lambda: _import_class(
|
|
31
|
+
"agno.knowledge.chunking.markdown", "MarkdownChunking"
|
|
32
|
+
),
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if strategy_type not in strategy_class_mapping:
|
|
36
|
+
raise ValueError(f"Unknown strategy type: {strategy_type}")
|
|
37
|
+
|
|
38
|
+
return strategy_class_mapping[strategy_type]()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _import_class(module_name: str, class_name: str):
|
|
42
|
+
"""Dynamically import a class from a module."""
|
|
43
|
+
import importlib
|
|
44
|
+
|
|
45
|
+
module = importlib.import_module(module_name)
|
|
46
|
+
return getattr(module, class_name)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def get_reader_info(reader_key: str) -> Dict:
|
|
50
|
+
"""Get information about a reader without instantiating it."""
|
|
51
|
+
# Try to create the reader to get its info, but don't cache it
|
|
52
|
+
try:
|
|
53
|
+
reader_factory_method = ReaderFactory._get_reader_method(reader_key)
|
|
54
|
+
|
|
55
|
+
# Create an instance to get the class, then call class methods
|
|
56
|
+
reader_instance = reader_factory_method()
|
|
57
|
+
reader_class = reader_instance.__class__
|
|
58
|
+
|
|
59
|
+
supported_strategies = reader_class.get_supported_chunking_strategies()
|
|
60
|
+
supported_content_types = reader_class.get_supported_content_types()
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
"id": reader_key,
|
|
64
|
+
"name": "".join(word.capitalize() for word in reader_key.split("_")) + "Reader",
|
|
65
|
+
"description": reader_instance.description,
|
|
66
|
+
"chunking_strategies": [
|
|
67
|
+
strategy.value for strategy in supported_strategies
|
|
68
|
+
], # Convert enums to string values
|
|
69
|
+
"content_types": [ct.value for ct in supported_content_types], # Convert enums to string values
|
|
70
|
+
}
|
|
71
|
+
except ImportError as e:
|
|
72
|
+
# Skip readers with missing dependencies
|
|
73
|
+
raise ValueError(f"Reader '{reader_key}' has missing dependencies: {str(e)}")
|
|
74
|
+
except Exception as e:
|
|
75
|
+
raise ValueError(f"Unknown reader: {reader_key}. Error: {str(e)}")
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def get_all_readers_info() -> List[Dict]:
|
|
79
|
+
"""Get information about all available readers."""
|
|
80
|
+
readers_info = []
|
|
81
|
+
keys = ReaderFactory.get_all_reader_keys()
|
|
82
|
+
for key in keys:
|
|
83
|
+
try:
|
|
84
|
+
reader_info = get_reader_info(key)
|
|
85
|
+
readers_info.append(reader_info)
|
|
86
|
+
except ValueError as e:
|
|
87
|
+
# Skip readers with missing dependencies or other issues
|
|
88
|
+
# Log the error but don't fail the entire request
|
|
89
|
+
log_debug(f"Skipping reader '{key}': {e}")
|
|
90
|
+
continue
|
|
91
|
+
return readers_info
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def get_content_types_to_readers_mapping() -> Dict[str, List[str]]:
|
|
95
|
+
"""Get mapping of content types to list of reader IDs that support them.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
Dictionary mapping content type strings (ContentType enum values) to list of reader IDs.
|
|
99
|
+
"""
|
|
100
|
+
content_type_mapping: Dict[str, List[str]] = {}
|
|
101
|
+
readers_info = get_all_readers_info()
|
|
102
|
+
|
|
103
|
+
for reader_info in readers_info:
|
|
104
|
+
reader_id = reader_info["id"]
|
|
105
|
+
content_types = reader_info.get("content_types", [])
|
|
106
|
+
|
|
107
|
+
for content_type in content_types:
|
|
108
|
+
if content_type not in content_type_mapping:
|
|
109
|
+
content_type_mapping[content_type] = []
|
|
110
|
+
content_type_mapping[content_type].append(reader_id)
|
|
111
|
+
|
|
112
|
+
return content_type_mapping
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def get_chunker_info(chunker_key: str) -> Dict:
|
|
116
|
+
"""Get information about a chunker without instantiating it."""
|
|
117
|
+
try:
|
|
118
|
+
# Use chunking strategies directly
|
|
119
|
+
from agno.knowledge.chunking.strategy import ChunkingStrategyType
|
|
120
|
+
|
|
121
|
+
try:
|
|
122
|
+
# Use the chunker key directly as the strategy type value
|
|
123
|
+
strategy_type = ChunkingStrategyType.from_string(chunker_key)
|
|
124
|
+
|
|
125
|
+
# Get class directly without instantiation
|
|
126
|
+
chunker_class = _get_chunker_class(strategy_type)
|
|
127
|
+
|
|
128
|
+
# Extract class information
|
|
129
|
+
class_name = chunker_class.__name__
|
|
130
|
+
docstring = chunker_class.__doc__ or f"{class_name} chunking strategy"
|
|
131
|
+
|
|
132
|
+
# Check class __init__ signature for chunk_size and overlap parameters
|
|
133
|
+
metadata = {}
|
|
134
|
+
import inspect
|
|
135
|
+
|
|
136
|
+
try:
|
|
137
|
+
sig = inspect.signature(chunker_class.__init__)
|
|
138
|
+
param_names = set(sig.parameters.keys())
|
|
139
|
+
|
|
140
|
+
# If class has chunk_size or max_chunk_size parameter, set default chunk_size
|
|
141
|
+
if "chunk_size" in param_names or "max_chunk_size" in param_names:
|
|
142
|
+
metadata["chunk_size"] = 5000
|
|
143
|
+
|
|
144
|
+
# If class has overlap parameter, set default overlap
|
|
145
|
+
if "overlap" in param_names:
|
|
146
|
+
metadata["chunk_overlap"] = 0
|
|
147
|
+
except Exception:
|
|
148
|
+
# If we can't inspect, skip metadata
|
|
149
|
+
pass
|
|
150
|
+
|
|
151
|
+
return {
|
|
152
|
+
"key": chunker_key,
|
|
153
|
+
"class_name": class_name,
|
|
154
|
+
"name": chunker_key,
|
|
155
|
+
"description": docstring.strip(),
|
|
156
|
+
"strategy_type": strategy_type.value,
|
|
157
|
+
"metadata": metadata,
|
|
158
|
+
}
|
|
159
|
+
except ValueError:
|
|
160
|
+
raise ValueError(f"Unknown chunker key: {chunker_key}")
|
|
161
|
+
|
|
162
|
+
except ImportError as e:
|
|
163
|
+
# Skip chunkers with missing dependencies
|
|
164
|
+
raise ValueError(f"Chunker '{chunker_key}' has missing dependencies: {str(e)}")
|
|
165
|
+
except Exception as e:
|
|
166
|
+
raise ValueError(f"Unknown chunker: {chunker_key}. Error: {str(e)}")
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def get_all_content_types() -> List[ContentType]:
|
|
170
|
+
"""Get all available content types as ContentType enums."""
|
|
171
|
+
return list(ContentType)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def get_all_chunkers_info() -> List[Dict]:
|
|
175
|
+
"""Get information about all available chunkers."""
|
|
176
|
+
chunkers_info = []
|
|
177
|
+
|
|
178
|
+
from agno.knowledge.chunking.strategy import ChunkingStrategyType
|
|
179
|
+
|
|
180
|
+
keys = [strategy_type.value for strategy_type in ChunkingStrategyType]
|
|
181
|
+
|
|
182
|
+
for key in keys:
|
|
183
|
+
try:
|
|
184
|
+
chunker_info = get_chunker_info(key)
|
|
185
|
+
chunkers_info.append(chunker_info)
|
|
186
|
+
except ValueError as e:
|
|
187
|
+
log_debug(f"Skipping chunker '{key}': {e}")
|
|
188
|
+
continue
|
|
189
|
+
return chunkers_info
|