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,313 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from typing import Any, Callable, Dict, List, Optional
|
|
3
|
+
|
|
4
|
+
from agno.knowledge.reader.base import Reader
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ReaderFactory:
|
|
8
|
+
"""Factory for creating and managing document readers with lazy loading."""
|
|
9
|
+
|
|
10
|
+
# Cache for instantiated readers
|
|
11
|
+
_reader_cache: Dict[str, Reader] = {}
|
|
12
|
+
|
|
13
|
+
@classmethod
|
|
14
|
+
def _get_pdf_reader(cls, **kwargs) -> Reader:
|
|
15
|
+
"""Get PDF reader instance."""
|
|
16
|
+
from agno.knowledge.reader.pdf_reader import PDFReader
|
|
17
|
+
|
|
18
|
+
config: Dict[str, Any] = {
|
|
19
|
+
"name": "PDF Reader",
|
|
20
|
+
"description": "Processes PDF documents with OCR support for images and text extraction",
|
|
21
|
+
}
|
|
22
|
+
config.update(kwargs)
|
|
23
|
+
return PDFReader(**config)
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
def _get_csv_reader(cls, **kwargs) -> Reader:
|
|
27
|
+
"""Get CSV reader instance."""
|
|
28
|
+
from agno.knowledge.reader.csv_reader import CSVReader
|
|
29
|
+
|
|
30
|
+
config: Dict[str, Any] = {
|
|
31
|
+
"name": "CSV Reader",
|
|
32
|
+
"description": "Parses CSV, XLSX, and XLS files with custom delimiter support",
|
|
33
|
+
}
|
|
34
|
+
config.update(kwargs)
|
|
35
|
+
return CSVReader(**config)
|
|
36
|
+
|
|
37
|
+
@classmethod
|
|
38
|
+
def _get_field_labeled_csv_reader(cls, **kwargs) -> Reader:
|
|
39
|
+
"""Get Field Labeled CSV reader instance."""
|
|
40
|
+
from agno.knowledge.reader.field_labeled_csv_reader import FieldLabeledCSVReader
|
|
41
|
+
|
|
42
|
+
config: Dict[str, Any] = {
|
|
43
|
+
"name": "Field Labeled CSV Reader",
|
|
44
|
+
"description": "Converts CSV rows to field-labeled text format for enhanced readability and context",
|
|
45
|
+
}
|
|
46
|
+
config.update(kwargs)
|
|
47
|
+
return FieldLabeledCSVReader(**config)
|
|
48
|
+
|
|
49
|
+
@classmethod
|
|
50
|
+
def _get_docx_reader(cls, **kwargs) -> Reader:
|
|
51
|
+
"""Get Docx reader instance."""
|
|
52
|
+
from agno.knowledge.reader.docx_reader import DocxReader
|
|
53
|
+
|
|
54
|
+
config: Dict[str, Any] = {
|
|
55
|
+
"name": "Docx Reader",
|
|
56
|
+
"description": "Extracts text content from Microsoft Word documents (.docx and .doc formats)",
|
|
57
|
+
}
|
|
58
|
+
config.update(kwargs)
|
|
59
|
+
return DocxReader(**config)
|
|
60
|
+
|
|
61
|
+
@classmethod
|
|
62
|
+
def _get_pptx_reader(cls, **kwargs) -> Reader:
|
|
63
|
+
"""Get PPTX reader instance."""
|
|
64
|
+
from agno.knowledge.reader.pptx_reader import PPTXReader
|
|
65
|
+
|
|
66
|
+
config: Dict[str, Any] = {
|
|
67
|
+
"name": "PPTX Reader",
|
|
68
|
+
"description": "Extracts text content from Microsoft PowerPoint presentations (.pptx format)",
|
|
69
|
+
}
|
|
70
|
+
config.update(kwargs)
|
|
71
|
+
return PPTXReader(**config)
|
|
72
|
+
|
|
73
|
+
@classmethod
|
|
74
|
+
def _get_json_reader(cls, **kwargs) -> Reader:
|
|
75
|
+
"""Get JSON reader instance."""
|
|
76
|
+
from agno.knowledge.reader.json_reader import JSONReader
|
|
77
|
+
|
|
78
|
+
config: Dict[str, Any] = {
|
|
79
|
+
"name": "JSON Reader",
|
|
80
|
+
"description": "Processes JSON data structures and API responses with nested object handling",
|
|
81
|
+
}
|
|
82
|
+
config.update(kwargs)
|
|
83
|
+
return JSONReader(**config)
|
|
84
|
+
|
|
85
|
+
@classmethod
|
|
86
|
+
def _get_markdown_reader(cls, **kwargs) -> Reader:
|
|
87
|
+
"""Get Markdown reader instance."""
|
|
88
|
+
from agno.knowledge.reader.markdown_reader import MarkdownReader
|
|
89
|
+
|
|
90
|
+
config: Dict[str, Any] = {
|
|
91
|
+
"name": "Markdown Reader",
|
|
92
|
+
"description": "Processes Markdown documentation with header-aware chunking and formatting preservation",
|
|
93
|
+
}
|
|
94
|
+
config.update(kwargs)
|
|
95
|
+
return MarkdownReader(**config)
|
|
96
|
+
|
|
97
|
+
@classmethod
|
|
98
|
+
def _get_text_reader(cls, **kwargs) -> Reader:
|
|
99
|
+
"""Get Text reader instance."""
|
|
100
|
+
from agno.knowledge.reader.text_reader import TextReader
|
|
101
|
+
|
|
102
|
+
config: Dict[str, Any] = {
|
|
103
|
+
"name": "Text Reader",
|
|
104
|
+
"description": "Handles plain text files with customizable chunking strategies and encoding detection",
|
|
105
|
+
}
|
|
106
|
+
config.update(kwargs)
|
|
107
|
+
return TextReader(**config)
|
|
108
|
+
|
|
109
|
+
@classmethod
|
|
110
|
+
def _get_website_reader(cls, **kwargs) -> Reader:
|
|
111
|
+
"""Get Website reader instance."""
|
|
112
|
+
from agno.knowledge.reader.website_reader import WebsiteReader
|
|
113
|
+
|
|
114
|
+
config: Dict[str, Any] = {
|
|
115
|
+
"name": "Website Reader",
|
|
116
|
+
"description": "Scrapes and extracts content from web pages with HTML parsing and text cleaning",
|
|
117
|
+
}
|
|
118
|
+
config.update(kwargs)
|
|
119
|
+
return WebsiteReader(**config)
|
|
120
|
+
|
|
121
|
+
@classmethod
|
|
122
|
+
def _get_firecrawl_reader(cls, **kwargs) -> Reader:
|
|
123
|
+
"""Get Firecrawl reader instance."""
|
|
124
|
+
from agno.knowledge.reader.firecrawl_reader import FirecrawlReader
|
|
125
|
+
|
|
126
|
+
config: Dict[str, Any] = {
|
|
127
|
+
"api_key": kwargs.get("api_key") or os.getenv("FIRECRAWL_API_KEY"),
|
|
128
|
+
"mode": "crawl",
|
|
129
|
+
"name": "Firecrawl Reader",
|
|
130
|
+
"description": "Advanced web scraping and crawling with JavaScript rendering and structured data extraction",
|
|
131
|
+
}
|
|
132
|
+
config.update(kwargs)
|
|
133
|
+
return FirecrawlReader(**config)
|
|
134
|
+
|
|
135
|
+
@classmethod
|
|
136
|
+
def _get_tavily_reader(cls, **kwargs) -> Reader:
|
|
137
|
+
"""Get Tavily reader instance."""
|
|
138
|
+
from agno.knowledge.reader.tavily_reader import TavilyReader
|
|
139
|
+
|
|
140
|
+
config: Dict[str, Any] = {
|
|
141
|
+
"api_key": kwargs.get("api_key") or os.getenv("TAVILY_API_KEY"),
|
|
142
|
+
"extract_format": "markdown",
|
|
143
|
+
"extract_depth": "basic",
|
|
144
|
+
"name": "Tavily Reader",
|
|
145
|
+
"description": "Extracts content from URLs using Tavily's Extract API with markdown or text output",
|
|
146
|
+
}
|
|
147
|
+
config.update(kwargs)
|
|
148
|
+
return TavilyReader(**config)
|
|
149
|
+
|
|
150
|
+
@classmethod
|
|
151
|
+
def _get_youtube_reader(cls, **kwargs) -> Reader:
|
|
152
|
+
"""Get YouTube reader instance."""
|
|
153
|
+
from agno.knowledge.reader.youtube_reader import YouTubeReader
|
|
154
|
+
|
|
155
|
+
config: Dict[str, Any] = {
|
|
156
|
+
"name": "YouTube Reader",
|
|
157
|
+
"description": "Extracts transcripts and metadata from YouTube videos and playlists",
|
|
158
|
+
}
|
|
159
|
+
config.update(kwargs)
|
|
160
|
+
return YouTubeReader(**config)
|
|
161
|
+
|
|
162
|
+
@classmethod
|
|
163
|
+
def _get_arxiv_reader(cls, **kwargs) -> Reader:
|
|
164
|
+
"""Get Arxiv reader instance."""
|
|
165
|
+
from agno.knowledge.reader.arxiv_reader import ArxivReader
|
|
166
|
+
|
|
167
|
+
config: Dict[str, Any] = {
|
|
168
|
+
"name": "Arxiv Reader",
|
|
169
|
+
"description": "Downloads and processes academic papers from ArXiv with PDF parsing and metadata extraction",
|
|
170
|
+
}
|
|
171
|
+
config.update(kwargs)
|
|
172
|
+
return ArxivReader(**config)
|
|
173
|
+
|
|
174
|
+
@classmethod
|
|
175
|
+
def _get_wikipedia_reader(cls, **kwargs) -> Reader:
|
|
176
|
+
"""Get Wikipedia reader instance."""
|
|
177
|
+
from agno.knowledge.reader.wikipedia_reader import WikipediaReader
|
|
178
|
+
|
|
179
|
+
config: Dict[str, Any] = {
|
|
180
|
+
"name": "Wikipedia Reader",
|
|
181
|
+
"description": "Fetches and processes Wikipedia articles with section-aware chunking and link resolution",
|
|
182
|
+
}
|
|
183
|
+
config.update(kwargs)
|
|
184
|
+
return WikipediaReader(**config)
|
|
185
|
+
|
|
186
|
+
@classmethod
|
|
187
|
+
def _get_web_search_reader(cls, **kwargs) -> Reader:
|
|
188
|
+
"""Get Web Search reader instance."""
|
|
189
|
+
from agno.knowledge.reader.web_search_reader import WebSearchReader
|
|
190
|
+
|
|
191
|
+
config: Dict[str, Any] = {
|
|
192
|
+
"name": "Web Search Reader",
|
|
193
|
+
"description": "Executes web searches and processes results with relevance ranking and content extraction",
|
|
194
|
+
}
|
|
195
|
+
config.update(kwargs)
|
|
196
|
+
return WebSearchReader(**config)
|
|
197
|
+
|
|
198
|
+
@classmethod
|
|
199
|
+
def _get_reader_method(cls, reader_key: str) -> Callable[[], Reader]:
|
|
200
|
+
"""Get the appropriate reader method for the given key."""
|
|
201
|
+
method_name = f"_get_{reader_key}_reader"
|
|
202
|
+
if not hasattr(cls, method_name):
|
|
203
|
+
raise ValueError(f"Unknown reader: {reader_key}")
|
|
204
|
+
return getattr(cls, method_name)
|
|
205
|
+
|
|
206
|
+
@classmethod
|
|
207
|
+
def create_reader(cls, reader_key: str, **kwargs) -> Reader:
|
|
208
|
+
"""Create a reader instance with the given key and optional overrides."""
|
|
209
|
+
if reader_key in cls._reader_cache:
|
|
210
|
+
return cls._reader_cache[reader_key]
|
|
211
|
+
|
|
212
|
+
# Get the reader method and create the instance
|
|
213
|
+
reader_method = cls._get_reader_method(reader_key)
|
|
214
|
+
reader = reader_method(**kwargs)
|
|
215
|
+
|
|
216
|
+
# Cache the reader
|
|
217
|
+
cls._reader_cache[reader_key] = reader
|
|
218
|
+
|
|
219
|
+
return reader
|
|
220
|
+
|
|
221
|
+
@classmethod
|
|
222
|
+
def get_reader_for_extension(cls, extension: str) -> Reader:
|
|
223
|
+
"""Get the appropriate reader for a file extension."""
|
|
224
|
+
extension = extension.lower()
|
|
225
|
+
|
|
226
|
+
if extension in [".pdf", "application/pdf"]:
|
|
227
|
+
return cls.create_reader("pdf")
|
|
228
|
+
elif extension in [".csv", "text/csv"]:
|
|
229
|
+
return cls.create_reader("csv")
|
|
230
|
+
elif extension in [".docx", ".doc", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"]:
|
|
231
|
+
return cls.create_reader("docx")
|
|
232
|
+
elif extension == ".pptx":
|
|
233
|
+
return cls.create_reader("pptx")
|
|
234
|
+
elif extension == ".json":
|
|
235
|
+
return cls.create_reader("json")
|
|
236
|
+
elif extension in [".md", ".markdown"]:
|
|
237
|
+
return cls.create_reader("markdown")
|
|
238
|
+
elif extension in [".txt", ".text"]:
|
|
239
|
+
return cls.create_reader("text")
|
|
240
|
+
else:
|
|
241
|
+
# Default to text reader for unknown extensions
|
|
242
|
+
return cls.create_reader("text")
|
|
243
|
+
|
|
244
|
+
@classmethod
|
|
245
|
+
def get_reader_for_url(cls, url: str) -> Reader:
|
|
246
|
+
"""Get the appropriate reader for a URL."""
|
|
247
|
+
url_lower = url.lower()
|
|
248
|
+
|
|
249
|
+
# Check for YouTube URLs
|
|
250
|
+
if any(domain in url_lower for domain in ["youtube.com", "youtu.be"]):
|
|
251
|
+
return cls.create_reader("youtube")
|
|
252
|
+
|
|
253
|
+
# Default to website reader
|
|
254
|
+
return cls.create_reader("website")
|
|
255
|
+
|
|
256
|
+
@classmethod
|
|
257
|
+
def get_all_reader_keys(cls) -> List[str]:
|
|
258
|
+
"""Get all available reader keys in priority order."""
|
|
259
|
+
# Extract reader keys from method names
|
|
260
|
+
|
|
261
|
+
PREFIX = "_get_"
|
|
262
|
+
SUFFIX = "_reader"
|
|
263
|
+
|
|
264
|
+
reader_keys = []
|
|
265
|
+
for attr_name in dir(cls):
|
|
266
|
+
if attr_name.startswith(PREFIX) and attr_name.endswith(SUFFIX):
|
|
267
|
+
reader_key = attr_name[len(PREFIX) : -len(SUFFIX)] # Remove "_get_" prefix and "_reader" suffix
|
|
268
|
+
reader_keys.append(reader_key)
|
|
269
|
+
|
|
270
|
+
# Define priority order for URL readers
|
|
271
|
+
url_reader_priority = [
|
|
272
|
+
"website",
|
|
273
|
+
"firecrawl",
|
|
274
|
+
"tavily",
|
|
275
|
+
"youtube",
|
|
276
|
+
]
|
|
277
|
+
|
|
278
|
+
# Sort with URL readers in priority order, others alphabetically
|
|
279
|
+
def sort_key(reader_key):
|
|
280
|
+
if reader_key in url_reader_priority:
|
|
281
|
+
return (0, url_reader_priority.index(reader_key))
|
|
282
|
+
else:
|
|
283
|
+
return (1, reader_key)
|
|
284
|
+
|
|
285
|
+
reader_keys.sort(key=sort_key)
|
|
286
|
+
return reader_keys
|
|
287
|
+
|
|
288
|
+
@classmethod
|
|
289
|
+
def create_all_readers(cls) -> Dict[str, Reader]:
|
|
290
|
+
"""Create all readers and return them as a dictionary."""
|
|
291
|
+
readers = {}
|
|
292
|
+
for reader_key in cls.get_all_reader_keys():
|
|
293
|
+
readers[reader_key] = cls.create_reader(reader_key)
|
|
294
|
+
return readers
|
|
295
|
+
|
|
296
|
+
@classmethod
|
|
297
|
+
def clear_cache(cls):
|
|
298
|
+
"""Clear the reader cache."""
|
|
299
|
+
cls._reader_cache.clear()
|
|
300
|
+
|
|
301
|
+
@classmethod
|
|
302
|
+
def register_reader(
|
|
303
|
+
cls,
|
|
304
|
+
key: str,
|
|
305
|
+
reader_method,
|
|
306
|
+
name: str,
|
|
307
|
+
description: str,
|
|
308
|
+
extensions: Optional[List[str]] = None,
|
|
309
|
+
):
|
|
310
|
+
"""Register a new reader type."""
|
|
311
|
+
# Add the reader method to the class
|
|
312
|
+
method_name = f"_get_{key}_reader"
|
|
313
|
+
setattr(cls, method_name, classmethod(reader_method))
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from io import BytesIO
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import List, Optional
|
|
5
|
+
|
|
6
|
+
from agno.knowledge.chunking.fixed import FixedSizeChunking
|
|
7
|
+
from agno.knowledge.chunking.strategy import ChunkingStrategy, ChunkingStrategyType
|
|
8
|
+
from agno.knowledge.document.base import Document
|
|
9
|
+
from agno.knowledge.reader.base import Reader
|
|
10
|
+
from agno.knowledge.reader.pdf_reader import PDFReader
|
|
11
|
+
from agno.knowledge.reader.text_reader import TextReader
|
|
12
|
+
from agno.knowledge.types import ContentType
|
|
13
|
+
from agno.utils.log import log_debug, log_error
|
|
14
|
+
|
|
15
|
+
try:
|
|
16
|
+
from agno.aws.resource.s3.object import S3Object # type: ignore
|
|
17
|
+
except (ModuleNotFoundError, ImportError):
|
|
18
|
+
raise ImportError("`agno-aws` not installed. Please install using `pip install agno-aws`")
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
import textract # noqa: F401
|
|
22
|
+
except ImportError:
|
|
23
|
+
raise ImportError("`textract` not installed. Please install it via `pip install textract`.")
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
from pypdf import PdfReader as DocumentReader # noqa: F401
|
|
27
|
+
except ImportError:
|
|
28
|
+
raise ImportError("`pypdf` not installed. Please install it via `pip install pypdf`.")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class S3Reader(Reader):
|
|
32
|
+
"""Reader for S3 files"""
|
|
33
|
+
|
|
34
|
+
def __init__(self, chunking_strategy: Optional[ChunkingStrategy] = FixedSizeChunking(), **kwargs):
|
|
35
|
+
super().__init__(chunking_strategy=chunking_strategy, **kwargs)
|
|
36
|
+
|
|
37
|
+
@classmethod
|
|
38
|
+
def get_supported_chunking_strategies(self) -> List[ChunkingStrategyType]:
|
|
39
|
+
"""Get the list of supported chunking strategies for S3 readers."""
|
|
40
|
+
return [
|
|
41
|
+
ChunkingStrategyType.FIXED_SIZE_CHUNKER,
|
|
42
|
+
ChunkingStrategyType.AGENTIC_CHUNKER,
|
|
43
|
+
ChunkingStrategyType.DOCUMENT_CHUNKER,
|
|
44
|
+
ChunkingStrategyType.RECURSIVE_CHUNKER,
|
|
45
|
+
ChunkingStrategyType.SEMANTIC_CHUNKER,
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
@classmethod
|
|
49
|
+
def get_supported_content_types(self) -> List[ContentType]:
|
|
50
|
+
return [ContentType.FILE, ContentType.URL, ContentType.TEXT]
|
|
51
|
+
|
|
52
|
+
def read(self, name: Optional[str], s3_object: S3Object) -> List[Document]:
|
|
53
|
+
try:
|
|
54
|
+
log_debug(f"Reading S3 file: {s3_object.uri}")
|
|
55
|
+
|
|
56
|
+
# Read PDF files
|
|
57
|
+
if s3_object.uri.endswith(".pdf"):
|
|
58
|
+
object_resource = s3_object.get_resource()
|
|
59
|
+
object_body = object_resource.get()["Body"]
|
|
60
|
+
doc_name = (
|
|
61
|
+
s3_object.name.split("/")[-1].split(".")[0].replace("/", "_").replace(" ", "_")
|
|
62
|
+
if name is None
|
|
63
|
+
else name
|
|
64
|
+
)
|
|
65
|
+
return PDFReader().read(pdf=BytesIO(object_body.read()), name=doc_name)
|
|
66
|
+
|
|
67
|
+
# Read text files
|
|
68
|
+
else:
|
|
69
|
+
doc_name = (
|
|
70
|
+
s3_object.name.split("/")[-1].split(".")[0].replace("/", "_").replace(" ", "_")
|
|
71
|
+
if name is None
|
|
72
|
+
else name
|
|
73
|
+
)
|
|
74
|
+
obj_name = s3_object.name.split("/")[-1]
|
|
75
|
+
temporary_file = Path("storage").joinpath(obj_name)
|
|
76
|
+
s3_object.download(temporary_file)
|
|
77
|
+
documents = TextReader().read(file=temporary_file, name=doc_name)
|
|
78
|
+
|
|
79
|
+
temporary_file.unlink()
|
|
80
|
+
return documents
|
|
81
|
+
|
|
82
|
+
except Exception as e:
|
|
83
|
+
log_error(f"Error reading: {s3_object.uri}: {e}")
|
|
84
|
+
|
|
85
|
+
return []
|
|
86
|
+
|
|
87
|
+
async def async_read(self, name: Optional[str], s3_object: S3Object) -> List[Document]:
|
|
88
|
+
"""Asynchronously read S3 files by running the synchronous read operation in a thread."""
|
|
89
|
+
return await asyncio.to_thread(self.read, name, s3_object)
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from typing import Dict, List, Literal, Optional
|
|
4
|
+
|
|
5
|
+
from agno.knowledge.chunking.semantic import SemanticChunking
|
|
6
|
+
from agno.knowledge.chunking.strategy import ChunkingStrategy, ChunkingStrategyType
|
|
7
|
+
from agno.knowledge.document.base import Document
|
|
8
|
+
from agno.knowledge.reader.base import Reader
|
|
9
|
+
from agno.knowledge.types import ContentType
|
|
10
|
+
from agno.utils.log import log_debug, logger
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
from tavily import TavilyClient # type: ignore[attr-defined]
|
|
14
|
+
except ImportError:
|
|
15
|
+
raise ImportError(
|
|
16
|
+
"The `tavily-python` package is not installed. Please install it via `pip install tavily-python`."
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass
|
|
21
|
+
class TavilyReader(Reader):
|
|
22
|
+
api_key: Optional[str] = None
|
|
23
|
+
params: Optional[Dict] = None
|
|
24
|
+
extract_format: Literal["markdown", "text"] = "markdown"
|
|
25
|
+
extract_depth: Literal["basic", "advanced"] = "basic"
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
api_key: Optional[str] = None,
|
|
30
|
+
params: Optional[Dict] = None,
|
|
31
|
+
extract_format: Literal["markdown", "text"] = "markdown",
|
|
32
|
+
extract_depth: Literal["basic", "advanced"] = "basic",
|
|
33
|
+
chunk: bool = True,
|
|
34
|
+
chunk_size: int = 5000,
|
|
35
|
+
chunking_strategy: Optional[ChunkingStrategy] = SemanticChunking(),
|
|
36
|
+
name: Optional[str] = None,
|
|
37
|
+
description: Optional[str] = None,
|
|
38
|
+
) -> None:
|
|
39
|
+
"""
|
|
40
|
+
Initialize TavilyReader for extracting content from URLs using Tavily's Extract API.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
api_key: Tavily API key (or use TAVILY_API_KEY env var)
|
|
44
|
+
params: Additional parameters to pass to the extract API
|
|
45
|
+
extract_format: Output format - "markdown" or "text"
|
|
46
|
+
extract_depth: Extraction depth - "basic" (1 credit/5 URLs) or "advanced" (2 credits/5 URLs)
|
|
47
|
+
chunk: Whether to chunk the extracted content
|
|
48
|
+
chunk_size: Size of chunks when chunking is enabled
|
|
49
|
+
chunking_strategy: Strategy to use for chunking
|
|
50
|
+
name: Name of the reader
|
|
51
|
+
description: Description of the reader
|
|
52
|
+
"""
|
|
53
|
+
# Initialize base Reader (handles chunk_size / strategy)
|
|
54
|
+
super().__init__(
|
|
55
|
+
chunk=chunk, chunk_size=chunk_size, chunking_strategy=chunking_strategy, name=name, description=description
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# Tavily-specific attributes
|
|
59
|
+
self.api_key = api_key
|
|
60
|
+
self.params = params or {}
|
|
61
|
+
self.extract_format = extract_format
|
|
62
|
+
self.extract_depth = extract_depth
|
|
63
|
+
|
|
64
|
+
@classmethod
|
|
65
|
+
def get_supported_chunking_strategies(self) -> List[ChunkingStrategyType]:
|
|
66
|
+
"""Get the list of supported chunking strategies for Tavily readers."""
|
|
67
|
+
return [
|
|
68
|
+
ChunkingStrategyType.SEMANTIC_CHUNKER,
|
|
69
|
+
ChunkingStrategyType.FIXED_SIZE_CHUNKER,
|
|
70
|
+
ChunkingStrategyType.AGENTIC_CHUNKER,
|
|
71
|
+
ChunkingStrategyType.DOCUMENT_CHUNKER,
|
|
72
|
+
ChunkingStrategyType.RECURSIVE_CHUNKER,
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
@classmethod
|
|
76
|
+
def get_supported_content_types(self) -> List[ContentType]:
|
|
77
|
+
return [ContentType.URL]
|
|
78
|
+
|
|
79
|
+
def _extract(self, url: str, name: Optional[str] = None) -> List[Document]:
|
|
80
|
+
"""
|
|
81
|
+
Internal method to extract content from a URL using Tavily's Extract API.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
url: The URL to extract content from
|
|
85
|
+
name: Optional name for the document (defaults to URL)
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
A list of documents containing the extracted content
|
|
89
|
+
"""
|
|
90
|
+
log_debug(f"Extracting content from: {url}")
|
|
91
|
+
|
|
92
|
+
client = TavilyClient(api_key=self.api_key)
|
|
93
|
+
|
|
94
|
+
# Prepare extract parameters
|
|
95
|
+
extract_params = {
|
|
96
|
+
"urls": [url],
|
|
97
|
+
"depth": self.extract_depth,
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
# Add optional params if provided
|
|
101
|
+
if self.params:
|
|
102
|
+
extract_params.update(self.params)
|
|
103
|
+
|
|
104
|
+
try:
|
|
105
|
+
# Call Tavily Extract API
|
|
106
|
+
response = client.extract(**extract_params)
|
|
107
|
+
|
|
108
|
+
# Extract content from response
|
|
109
|
+
if not response or "results" not in response:
|
|
110
|
+
logger.warning(f"No results received for URL: {url}")
|
|
111
|
+
return [Document(name=name or url, id=url, content="")]
|
|
112
|
+
|
|
113
|
+
results = response.get("results", [])
|
|
114
|
+
if not results:
|
|
115
|
+
logger.warning(f"Empty results for URL: {url}")
|
|
116
|
+
return [Document(name=name or url, id=url, content="")]
|
|
117
|
+
|
|
118
|
+
# Get the first result (since we're extracting a single URL)
|
|
119
|
+
result = results[0]
|
|
120
|
+
|
|
121
|
+
# Check if extraction failed
|
|
122
|
+
if "failed_reason" in result:
|
|
123
|
+
logger.warning(f"Extraction failed for {url}: {result['failed_reason']}")
|
|
124
|
+
return [Document(name=name or url, id=url, content="")]
|
|
125
|
+
|
|
126
|
+
# Get raw content
|
|
127
|
+
content = result.get("raw_content", "")
|
|
128
|
+
|
|
129
|
+
if content is None:
|
|
130
|
+
content = ""
|
|
131
|
+
logger.warning(f"No content received for URL: {url}")
|
|
132
|
+
|
|
133
|
+
# Debug logging
|
|
134
|
+
log_debug(f"Received content type: {type(content)}")
|
|
135
|
+
log_debug(f"Content length: {len(content) if content else 0}")
|
|
136
|
+
|
|
137
|
+
# Create documents
|
|
138
|
+
documents = []
|
|
139
|
+
if self.chunk and content:
|
|
140
|
+
documents.extend(self.chunk_document(Document(name=name or url, id=url, content=content)))
|
|
141
|
+
else:
|
|
142
|
+
documents.append(Document(name=name or url, id=url, content=content))
|
|
143
|
+
return documents
|
|
144
|
+
|
|
145
|
+
except Exception as e:
|
|
146
|
+
logger.error(f"Error extracting content from {url}: {e}")
|
|
147
|
+
return [Document(name=name or url, id=url, content="")]
|
|
148
|
+
|
|
149
|
+
async def _async_extract(self, url: str, name: Optional[str] = None) -> List[Document]:
|
|
150
|
+
"""
|
|
151
|
+
Internal async method to extract content from a URL.
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
url: The URL to extract content from
|
|
155
|
+
name: Optional name for the document
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
A list of documents containing the extracted content
|
|
159
|
+
"""
|
|
160
|
+
log_debug(f"Async extracting content from: {url}")
|
|
161
|
+
|
|
162
|
+
# Use asyncio.to_thread to run the synchronous extract in a thread
|
|
163
|
+
return await asyncio.to_thread(self._extract, url, name)
|
|
164
|
+
|
|
165
|
+
def read(self, url: str, name: Optional[str] = None) -> List[Document]:
|
|
166
|
+
"""
|
|
167
|
+
Reads content from a URL using Tavily Extract API.
|
|
168
|
+
|
|
169
|
+
This is the public API method that users should call.
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
url: The URL to extract content from
|
|
173
|
+
name: Optional name for the document
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
A list of documents containing the extracted content
|
|
177
|
+
"""
|
|
178
|
+
return self._extract(url, name)
|
|
179
|
+
|
|
180
|
+
async def async_read(self, url: str, name: Optional[str] = None) -> List[Document]:
|
|
181
|
+
"""
|
|
182
|
+
Asynchronously reads content from a URL using Tavily Extract API.
|
|
183
|
+
|
|
184
|
+
This is the public API method that users should call for async operations.
|
|
185
|
+
|
|
186
|
+
Args:
|
|
187
|
+
url: The URL to extract content from
|
|
188
|
+
name: Optional name for the document
|
|
189
|
+
|
|
190
|
+
Returns:
|
|
191
|
+
A list of documents containing the extracted content
|
|
192
|
+
"""
|
|
193
|
+
return await self._async_extract(url, name)
|