agno 1.8.0__py3-none-any.whl → 2.0.0a1__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 +19 -27
- agno/agent/agent.py +2781 -4126
- agno/api/agent.py +9 -65
- agno/api/api.py +5 -46
- agno/api/evals.py +6 -17
- agno/api/os.py +17 -0
- agno/api/routes.py +6 -41
- agno/api/schemas/__init__.py +9 -0
- agno/api/schemas/agent.py +5 -21
- agno/api/schemas/evals.py +7 -16
- agno/api/schemas/os.py +14 -0
- agno/api/schemas/team.py +5 -21
- agno/api/schemas/utils.py +21 -0
- agno/api/schemas/workflows.py +11 -7
- agno/api/settings.py +53 -0
- agno/api/team.py +9 -64
- 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/db/__init__.py +24 -0
- agno/db/base.py +245 -0
- agno/db/dynamo/__init__.py +3 -0
- agno/db/dynamo/dynamo.py +1749 -0
- agno/db/dynamo/schemas.py +278 -0
- agno/db/dynamo/utils.py +684 -0
- agno/db/firestore/__init__.py +3 -0
- agno/db/firestore/firestore.py +1438 -0
- agno/db/firestore/schemas.py +130 -0
- agno/db/firestore/utils.py +278 -0
- agno/db/gcs_json/__init__.py +3 -0
- agno/db/gcs_json/gcs_json_db.py +1001 -0
- agno/db/gcs_json/utils.py +194 -0
- agno/db/in_memory/__init__.py +3 -0
- agno/db/in_memory/in_memory_db.py +888 -0
- agno/db/in_memory/utils.py +172 -0
- agno/db/json/__init__.py +3 -0
- agno/db/json/json_db.py +1051 -0
- agno/db/json/utils.py +196 -0
- agno/db/migrations/v1_to_v2.py +162 -0
- agno/db/mongo/__init__.py +3 -0
- agno/db/mongo/mongo.py +1417 -0
- agno/db/mongo/schemas.py +77 -0
- agno/db/mongo/utils.py +204 -0
- agno/db/mysql/__init__.py +3 -0
- agno/db/mysql/mysql.py +1719 -0
- agno/db/mysql/schemas.py +124 -0
- agno/db/mysql/utils.py +298 -0
- agno/db/postgres/__init__.py +3 -0
- agno/db/postgres/postgres.py +1720 -0
- agno/db/postgres/schemas.py +124 -0
- agno/db/postgres/utils.py +281 -0
- agno/db/redis/__init__.py +3 -0
- agno/db/redis/redis.py +1371 -0
- agno/db/redis/schemas.py +109 -0
- agno/db/redis/utils.py +288 -0
- agno/db/schemas/__init__.py +3 -0
- agno/db/schemas/evals.py +33 -0
- agno/db/schemas/knowledge.py +40 -0
- agno/db/schemas/memory.py +46 -0
- agno/db/singlestore/__init__.py +3 -0
- agno/db/singlestore/schemas.py +116 -0
- agno/db/singlestore/singlestore.py +1722 -0
- agno/db/singlestore/utils.py +327 -0
- agno/db/sqlite/__init__.py +3 -0
- agno/db/sqlite/schemas.py +119 -0
- agno/db/sqlite/sqlite.py +1680 -0
- agno/db/sqlite/utils.py +269 -0
- agno/db/utils.py +88 -0
- agno/eval/__init__.py +14 -0
- agno/eval/accuracy.py +142 -43
- agno/eval/performance.py +88 -23
- agno/eval/reliability.py +73 -20
- agno/eval/utils.py +23 -13
- agno/integrations/discord/__init__.py +3 -0
- agno/{app → integrations}/discord/client.py +10 -10
- agno/knowledge/__init__.py +2 -2
- agno/{document → knowledge}/chunking/agentic.py +2 -2
- agno/{document → knowledge}/chunking/document.py +2 -2
- agno/{document → knowledge}/chunking/fixed.py +3 -3
- agno/{document → knowledge}/chunking/markdown.py +2 -2
- agno/{document → knowledge}/chunking/recursive.py +2 -2
- agno/{document → knowledge}/chunking/row.py +2 -2
- agno/knowledge/chunking/semantic.py +59 -0
- agno/knowledge/chunking/strategy.py +121 -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/{embedder → knowledge/embedder}/aws_bedrock.py +127 -1
- agno/{embedder → knowledge/embedder}/azure_openai.py +65 -1
- agno/{embedder → knowledge/embedder}/base.py +6 -0
- agno/{embedder → knowledge/embedder}/cohere.py +72 -1
- agno/{embedder → knowledge/embedder}/fastembed.py +17 -1
- agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
- agno/{embedder → knowledge/embedder}/google.py +74 -1
- agno/{embedder → knowledge/embedder}/huggingface.py +36 -2
- agno/{embedder → knowledge/embedder}/jina.py +48 -2
- agno/knowledge/embedder/langdb.py +22 -0
- agno/knowledge/embedder/mistral.py +139 -0
- agno/{embedder → knowledge/embedder}/nebius.py +1 -1
- agno/{embedder → knowledge/embedder}/ollama.py +54 -3
- agno/knowledge/embedder/openai.py +223 -0
- agno/{embedder → knowledge/embedder}/sentence_transformer.py +16 -1
- agno/{embedder → knowledge/embedder}/together.py +1 -1
- agno/{embedder → knowledge/embedder}/voyageai.py +49 -1
- agno/knowledge/knowledge.py +1515 -0
- agno/knowledge/reader/__init__.py +7 -0
- agno/{document → knowledge}/reader/arxiv_reader.py +32 -4
- agno/knowledge/reader/base.py +88 -0
- agno/{document → knowledge}/reader/csv_reader.py +68 -15
- agno/knowledge/reader/docx_reader.py +83 -0
- agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
- agno/knowledge/reader/gcs_reader.py +67 -0
- agno/{document → knowledge}/reader/json_reader.py +30 -9
- agno/{document → knowledge}/reader/markdown_reader.py +36 -9
- agno/{document → knowledge}/reader/pdf_reader.py +79 -21
- agno/knowledge/reader/reader_factory.py +275 -0
- agno/knowledge/reader/s3_reader.py +171 -0
- agno/{document → knowledge}/reader/text_reader.py +31 -10
- agno/knowledge/reader/url_reader.py +84 -0
- agno/knowledge/reader/web_search_reader.py +389 -0
- agno/{document → knowledge}/reader/website_reader.py +37 -10
- agno/knowledge/reader/wikipedia_reader.py +59 -0
- agno/knowledge/reader/youtube_reader.py +78 -0
- agno/knowledge/remote_content/remote_content.py +88 -0
- agno/{reranker → knowledge/reranker}/base.py +1 -1
- agno/{reranker → knowledge/reranker}/cohere.py +2 -2
- agno/{reranker → knowledge/reranker}/infinity.py +2 -2
- agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
- agno/knowledge/types.py +30 -0
- agno/knowledge/utils.py +169 -0
- agno/media.py +2 -2
- agno/memory/__init__.py +2 -10
- agno/memory/manager.py +1003 -148
- agno/models/aimlapi/__init__.py +2 -2
- agno/models/aimlapi/aimlapi.py +6 -6
- agno/models/anthropic/claude.py +129 -82
- agno/models/aws/bedrock.py +107 -175
- agno/models/aws/claude.py +64 -18
- agno/models/azure/ai_foundry.py +73 -23
- agno/models/base.py +347 -287
- agno/models/cerebras/cerebras.py +84 -27
- agno/models/cohere/chat.py +106 -98
- agno/models/dashscope/dashscope.py +14 -5
- agno/models/google/gemini.py +123 -53
- agno/models/groq/groq.py +97 -35
- agno/models/huggingface/huggingface.py +92 -27
- agno/models/ibm/watsonx.py +72 -13
- agno/models/litellm/chat.py +85 -13
- agno/models/message.py +38 -144
- agno/models/meta/llama.py +85 -49
- agno/models/metrics.py +120 -0
- agno/models/mistral/mistral.py +90 -21
- agno/models/ollama/__init__.py +0 -2
- agno/models/ollama/chat.py +84 -46
- agno/models/openai/chat.py +135 -27
- agno/models/openai/responses.py +233 -115
- agno/models/perplexity/perplexity.py +26 -2
- agno/models/portkey/portkey.py +0 -7
- agno/models/response.py +14 -8
- agno/models/utils.py +20 -0
- agno/models/vercel/__init__.py +2 -2
- agno/models/vercel/v0.py +1 -1
- agno/models/vllm/__init__.py +2 -2
- agno/models/vllm/vllm.py +3 -3
- agno/models/xai/xai.py +10 -10
- agno/os/__init__.py +3 -0
- agno/os/app.py +393 -0
- agno/os/auth.py +47 -0
- agno/os/config.py +103 -0
- agno/os/interfaces/agui/__init__.py +3 -0
- agno/os/interfaces/agui/agui.py +31 -0
- agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
- agno/{app → os/interfaces}/agui/utils.py +65 -28
- agno/os/interfaces/base.py +21 -0
- agno/os/interfaces/slack/__init__.py +3 -0
- agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
- agno/os/interfaces/slack/slack.py +33 -0
- agno/os/interfaces/whatsapp/__init__.py +3 -0
- agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
- agno/os/interfaces/whatsapp/whatsapp.py +30 -0
- agno/os/router.py +843 -0
- agno/os/routers/__init__.py +3 -0
- agno/os/routers/evals/__init__.py +3 -0
- agno/os/routers/evals/evals.py +204 -0
- agno/os/routers/evals/schemas.py +142 -0
- agno/os/routers/evals/utils.py +161 -0
- agno/os/routers/knowledge/__init__.py +3 -0
- agno/os/routers/knowledge/knowledge.py +413 -0
- agno/os/routers/knowledge/schemas.py +118 -0
- agno/os/routers/memory/__init__.py +3 -0
- agno/os/routers/memory/memory.py +179 -0
- agno/os/routers/memory/schemas.py +58 -0
- agno/os/routers/metrics/__init__.py +3 -0
- agno/os/routers/metrics/metrics.py +58 -0
- agno/os/routers/metrics/schemas.py +47 -0
- agno/os/routers/session/__init__.py +3 -0
- agno/os/routers/session/session.py +163 -0
- agno/os/schema.py +892 -0
- agno/{app/playground → os}/settings.py +8 -15
- agno/os/utils.py +270 -0
- agno/reasoning/azure_ai_foundry.py +4 -4
- agno/reasoning/deepseek.py +4 -4
- agno/reasoning/default.py +6 -11
- agno/reasoning/groq.py +4 -4
- agno/reasoning/helpers.py +4 -6
- agno/reasoning/ollama.py +4 -4
- agno/reasoning/openai.py +4 -4
- agno/run/{response.py → agent.py} +144 -72
- agno/run/base.py +44 -58
- agno/run/cancel.py +83 -0
- agno/run/team.py +133 -77
- agno/run/workflow.py +537 -12
- agno/session/__init__.py +10 -0
- agno/session/agent.py +244 -0
- agno/session/summary.py +225 -0
- agno/session/team.py +262 -0
- agno/{storage/session/v2 → session}/workflow.py +47 -24
- agno/team/__init__.py +15 -16
- agno/team/team.py +2967 -4243
- agno/tools/agentql.py +14 -5
- agno/tools/airflow.py +9 -4
- agno/tools/api.py +7 -3
- agno/tools/apify.py +2 -46
- agno/tools/arxiv.py +8 -3
- agno/tools/aws_lambda.py +7 -5
- agno/tools/aws_ses.py +7 -1
- agno/tools/baidusearch.py +4 -1
- agno/tools/bitbucket.py +4 -4
- agno/tools/brandfetch.py +14 -11
- agno/tools/bravesearch.py +4 -1
- agno/tools/brightdata.py +42 -22
- agno/tools/browserbase.py +13 -4
- agno/tools/calcom.py +12 -10
- agno/tools/calculator.py +10 -27
- agno/tools/cartesia.py +18 -13
- agno/tools/{clickup_tool.py → clickup.py} +12 -25
- agno/tools/confluence.py +71 -18
- agno/tools/crawl4ai.py +7 -1
- agno/tools/csv_toolkit.py +9 -8
- agno/tools/dalle.py +18 -11
- agno/tools/daytona.py +13 -16
- agno/tools/decorator.py +6 -3
- agno/tools/desi_vocal.py +16 -7
- agno/tools/discord.py +11 -8
- agno/tools/docker.py +30 -42
- agno/tools/duckdb.py +34 -53
- agno/tools/duckduckgo.py +8 -7
- agno/tools/e2b.py +62 -62
- agno/tools/eleven_labs.py +35 -28
- agno/tools/email.py +4 -1
- agno/tools/evm.py +7 -1
- agno/tools/exa.py +19 -14
- agno/tools/fal.py +29 -29
- agno/tools/file.py +9 -8
- agno/tools/financial_datasets.py +25 -44
- agno/tools/firecrawl.py +22 -22
- agno/tools/function.py +68 -17
- agno/tools/giphy.py +22 -10
- agno/tools/github.py +48 -126
- agno/tools/gmail.py +46 -62
- agno/tools/google_bigquery.py +7 -6
- agno/tools/google_maps.py +11 -26
- agno/tools/googlesearch.py +7 -2
- agno/tools/googlesheets.py +21 -17
- agno/tools/hackernews.py +9 -5
- agno/tools/jina.py +5 -4
- agno/tools/jira.py +18 -9
- agno/tools/knowledge.py +31 -32
- agno/tools/linear.py +18 -33
- agno/tools/linkup.py +5 -1
- agno/tools/local_file_system.py +8 -5
- agno/tools/lumalab.py +31 -19
- agno/tools/mem0.py +18 -12
- agno/tools/memori.py +14 -10
- agno/tools/mlx_transcribe.py +3 -2
- agno/tools/models/azure_openai.py +32 -14
- agno/tools/models/gemini.py +58 -31
- agno/tools/models/groq.py +29 -20
- agno/tools/models/nebius.py +27 -11
- agno/tools/models_labs.py +39 -15
- agno/tools/moviepy_video.py +7 -6
- agno/tools/neo4j.py +134 -0
- agno/tools/newspaper.py +7 -2
- agno/tools/newspaper4k.py +8 -3
- agno/tools/openai.py +57 -26
- agno/tools/openbb.py +12 -11
- agno/tools/opencv.py +62 -46
- agno/tools/openweather.py +14 -12
- agno/tools/pandas.py +11 -3
- agno/tools/postgres.py +4 -12
- agno/tools/pubmed.py +4 -1
- agno/tools/python.py +9 -22
- agno/tools/reasoning.py +35 -27
- agno/tools/reddit.py +11 -26
- agno/tools/replicate.py +54 -41
- agno/tools/resend.py +4 -1
- agno/tools/scrapegraph.py +15 -14
- agno/tools/searxng.py +10 -23
- agno/tools/serpapi.py +6 -3
- agno/tools/serper.py +13 -4
- agno/tools/shell.py +9 -2
- agno/tools/slack.py +12 -11
- agno/tools/sleep.py +3 -2
- agno/tools/spider.py +24 -4
- agno/tools/sql.py +7 -6
- agno/tools/tavily.py +6 -4
- agno/tools/telegram.py +12 -4
- agno/tools/todoist.py +11 -31
- agno/tools/toolkit.py +1 -1
- agno/tools/trafilatura.py +22 -6
- agno/tools/trello.py +9 -22
- agno/tools/twilio.py +10 -3
- agno/tools/user_control_flow.py +6 -1
- agno/tools/valyu.py +34 -5
- agno/tools/visualization.py +19 -28
- agno/tools/webbrowser.py +4 -3
- agno/tools/webex.py +11 -7
- agno/tools/website.py +15 -46
- agno/tools/webtools.py +12 -4
- agno/tools/whatsapp.py +5 -9
- agno/tools/wikipedia.py +20 -13
- agno/tools/x.py +14 -13
- agno/tools/yfinance.py +13 -40
- agno/tools/youtube.py +26 -20
- agno/tools/zendesk.py +7 -2
- agno/tools/zep.py +10 -7
- agno/tools/zoom.py +10 -9
- agno/utils/common.py +1 -19
- agno/utils/events.py +95 -118
- agno/utils/knowledge.py +29 -0
- agno/utils/location.py +2 -2
- agno/utils/log.py +2 -2
- agno/utils/mcp.py +11 -5
- agno/utils/media.py +39 -0
- agno/utils/message.py +12 -1
- agno/utils/models/claude.py +6 -4
- agno/utils/models/mistral.py +8 -7
- agno/utils/models/schema_utils.py +3 -3
- agno/utils/pprint.py +33 -32
- agno/utils/print_response/agent.py +779 -0
- agno/utils/print_response/team.py +1565 -0
- agno/utils/print_response/workflow.py +1451 -0
- agno/utils/prompts.py +14 -14
- agno/utils/reasoning.py +87 -0
- agno/utils/response.py +42 -42
- agno/utils/string.py +8 -22
- agno/utils/team.py +50 -0
- agno/utils/timer.py +2 -2
- agno/vectordb/base.py +33 -21
- agno/vectordb/cassandra/cassandra.py +287 -23
- agno/vectordb/chroma/chromadb.py +482 -59
- agno/vectordb/clickhouse/clickhousedb.py +270 -63
- agno/vectordb/couchbase/couchbase.py +309 -29
- agno/vectordb/lancedb/lance_db.py +360 -21
- agno/vectordb/langchaindb/__init__.py +5 -0
- agno/vectordb/langchaindb/langchaindb.py +145 -0
- agno/vectordb/lightrag/__init__.py +5 -0
- agno/vectordb/lightrag/lightrag.py +374 -0
- agno/vectordb/llamaindex/llamaindexdb.py +127 -0
- agno/vectordb/milvus/milvus.py +242 -32
- agno/vectordb/mongodb/mongodb.py +200 -24
- agno/vectordb/pgvector/pgvector.py +319 -37
- agno/vectordb/pineconedb/pineconedb.py +221 -27
- agno/vectordb/qdrant/qdrant.py +356 -14
- agno/vectordb/singlestore/singlestore.py +286 -29
- agno/vectordb/surrealdb/surrealdb.py +187 -7
- agno/vectordb/upstashdb/upstashdb.py +342 -26
- agno/vectordb/weaviate/weaviate.py +227 -165
- agno/workflow/__init__.py +17 -13
- agno/workflow/{v2/condition.py → condition.py} +135 -32
- agno/workflow/{v2/loop.py → loop.py} +115 -28
- agno/workflow/{v2/parallel.py → parallel.py} +138 -108
- agno/workflow/{v2/router.py → router.py} +133 -32
- agno/workflow/{v2/step.py → step.py} +200 -42
- agno/workflow/{v2/steps.py → steps.py} +147 -66
- agno/workflow/types.py +482 -0
- agno/workflow/workflow.py +2394 -696
- agno-2.0.0a1.dist-info/METADATA +355 -0
- agno-2.0.0a1.dist-info/RECORD +514 -0
- agno/agent/metrics.py +0 -107
- agno/api/app.py +0 -35
- agno/api/playground.py +0 -92
- agno/api/schemas/app.py +0 -12
- agno/api/schemas/playground.py +0 -22
- agno/api/schemas/user.py +0 -35
- agno/api/schemas/workspace.py +0 -46
- agno/api/user.py +0 -160
- agno/api/workflows.py +0 -33
- agno/api/workspace.py +0 -175
- agno/app/agui/__init__.py +0 -3
- agno/app/agui/app.py +0 -17
- agno/app/agui/sync_router.py +0 -120
- agno/app/base.py +0 -186
- agno/app/discord/__init__.py +0 -3
- agno/app/fastapi/__init__.py +0 -3
- agno/app/fastapi/app.py +0 -107
- agno/app/fastapi/async_router.py +0 -457
- agno/app/fastapi/sync_router.py +0 -448
- agno/app/playground/app.py +0 -228
- agno/app/playground/async_router.py +0 -1050
- agno/app/playground/deploy.py +0 -249
- agno/app/playground/operator.py +0 -183
- agno/app/playground/schemas.py +0 -220
- agno/app/playground/serve.py +0 -55
- agno/app/playground/sync_router.py +0 -1042
- agno/app/playground/utils.py +0 -46
- agno/app/settings.py +0 -15
- agno/app/slack/__init__.py +0 -3
- agno/app/slack/app.py +0 -19
- agno/app/slack/sync_router.py +0 -92
- agno/app/utils.py +0 -54
- agno/app/whatsapp/__init__.py +0 -3
- agno/app/whatsapp/app.py +0 -15
- agno/app/whatsapp/sync_router.py +0 -197
- agno/cli/auth_server.py +0 -249
- agno/cli/config.py +0 -274
- agno/cli/console.py +0 -88
- agno/cli/credentials.py +0 -23
- agno/cli/entrypoint.py +0 -571
- agno/cli/operator.py +0 -357
- agno/cli/settings.py +0 -96
- agno/cli/ws/ws_cli.py +0 -817
- agno/constants.py +0 -13
- agno/document/__init__.py +0 -5
- agno/document/chunking/semantic.py +0 -45
- agno/document/chunking/strategy.py +0 -31
- agno/document/reader/__init__.py +0 -5
- agno/document/reader/base.py +0 -47
- agno/document/reader/docx_reader.py +0 -60
- agno/document/reader/gcs/pdf_reader.py +0 -44
- agno/document/reader/s3/pdf_reader.py +0 -59
- agno/document/reader/s3/text_reader.py +0 -63
- agno/document/reader/url_reader.py +0 -59
- agno/document/reader/youtube_reader.py +0 -58
- agno/embedder/__init__.py +0 -5
- agno/embedder/langdb.py +0 -80
- agno/embedder/mistral.py +0 -82
- agno/embedder/openai.py +0 -78
- agno/file/__init__.py +0 -5
- 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 -698
- agno/knowledge/arxiv.py +0 -33
- agno/knowledge/combined.py +0 -36
- agno/knowledge/csv.py +0 -144
- agno/knowledge/csv_url.py +0 -124
- agno/knowledge/document.py +0 -223
- agno/knowledge/docx.py +0 -137
- agno/knowledge/firecrawl.py +0 -34
- agno/knowledge/gcs/__init__.py +0 -0
- agno/knowledge/gcs/base.py +0 -39
- agno/knowledge/gcs/pdf.py +0 -125
- agno/knowledge/json.py +0 -137
- agno/knowledge/langchain.py +0 -71
- agno/knowledge/light_rag.py +0 -273
- agno/knowledge/llamaindex.py +0 -66
- agno/knowledge/markdown.py +0 -154
- agno/knowledge/pdf.py +0 -164
- agno/knowledge/pdf_bytes.py +0 -42
- agno/knowledge/pdf_url.py +0 -148
- agno/knowledge/s3/__init__.py +0 -0
- agno/knowledge/s3/base.py +0 -64
- agno/knowledge/s3/pdf.py +0 -33
- agno/knowledge/s3/text.py +0 -34
- agno/knowledge/text.py +0 -141
- agno/knowledge/url.py +0 -46
- agno/knowledge/website.py +0 -179
- agno/knowledge/wikipedia.py +0 -32
- agno/knowledge/youtube.py +0 -35
- agno/memory/agent.py +0 -423
- agno/memory/classifier.py +0 -104
- agno/memory/db/__init__.py +0 -5
- 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 -22
- agno/memory/row.py +0 -36
- agno/memory/summarizer.py +0 -201
- agno/memory/summary.py +0 -19
- agno/memory/team.py +0 -415
- agno/memory/v2/__init__.py +0 -2
- agno/memory/v2/db/__init__.py +0 -1
- agno/memory/v2/db/base.py +0 -42
- agno/memory/v2/db/firestore.py +0 -339
- agno/memory/v2/db/mongodb.py +0 -196
- agno/memory/v2/db/postgres.py +0 -214
- agno/memory/v2/db/redis.py +0 -187
- agno/memory/v2/db/schema.py +0 -54
- agno/memory/v2/db/sqlite.py +0 -209
- agno/memory/v2/manager.py +0 -437
- agno/memory/v2/memory.py +0 -1097
- agno/memory/v2/schema.py +0 -55
- agno/memory/v2/summarizer.py +0 -215
- agno/memory/workflow.py +0 -38
- agno/models/ollama/tools.py +0 -430
- agno/models/qwen/__init__.py +0 -5
- agno/playground/__init__.py +0 -10
- agno/playground/deploy.py +0 -3
- agno/playground/playground.py +0 -3
- agno/playground/serve.py +0 -3
- agno/playground/settings.py +0 -3
- agno/reranker/__init__.py +0 -0
- agno/run/v2/__init__.py +0 -0
- agno/run/v2/workflow.py +0 -567
- agno/storage/__init__.py +0 -0
- agno/storage/agent/__init__.py +0 -0
- agno/storage/agent/dynamodb.py +0 -1
- agno/storage/agent/json.py +0 -1
- agno/storage/agent/mongodb.py +0 -1
- agno/storage/agent/postgres.py +0 -1
- agno/storage/agent/singlestore.py +0 -1
- agno/storage/agent/sqlite.py +0 -1
- agno/storage/agent/yaml.py +0 -1
- agno/storage/base.py +0 -60
- agno/storage/dynamodb.py +0 -673
- agno/storage/firestore.py +0 -297
- agno/storage/gcs_json.py +0 -261
- agno/storage/in_memory.py +0 -234
- agno/storage/json.py +0 -237
- agno/storage/mongodb.py +0 -328
- agno/storage/mysql.py +0 -685
- agno/storage/postgres.py +0 -682
- agno/storage/redis.py +0 -336
- agno/storage/session/__init__.py +0 -16
- agno/storage/session/agent.py +0 -64
- agno/storage/session/team.py +0 -63
- agno/storage/session/v2/__init__.py +0 -5
- agno/storage/session/workflow.py +0 -61
- agno/storage/singlestore.py +0 -606
- agno/storage/sqlite.py +0 -646
- agno/storage/workflow/__init__.py +0 -0
- agno/storage/workflow/mongodb.py +0 -1
- agno/storage/workflow/postgres.py +0 -1
- agno/storage/workflow/sqlite.py +0 -1
- agno/storage/yaml.py +0 -241
- agno/tools/thinking.py +0 -73
- 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/workflow/v2/__init__.py +0 -21
- agno/workflow/v2/types.py +0 -357
- agno/workflow/v2/workflow.py +0 -3312
- agno/workspace/__init__.py +0 -0
- agno/workspace/config.py +0 -325
- agno/workspace/enums.py +0 -6
- agno/workspace/helpers.py +0 -52
- agno/workspace/operator.py +0 -757
- agno/workspace/settings.py +0 -158
- agno-1.8.0.dist-info/METADATA +0 -979
- agno-1.8.0.dist-info/RECORD +0 -565
- agno-1.8.0.dist-info/entry_points.txt +0 -3
- /agno/{app → db/migrations}/__init__.py +0 -0
- /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
- /agno/{cli → integrations}/__init__.py +0 -0
- /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
- /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
- /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
- /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
- /agno/{app → os/interfaces}/slack/security.py +0 -0
- /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
- /agno/{file/local → utils/print_response}/__init__.py +0 -0
- /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
- {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/WHEEL +0 -0
- {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/licenses/LICENSE +0 -0
- {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/top_level.txt +0 -0
|
@@ -1,27 +1,54 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import uuid
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import IO, Any, List, Union
|
|
4
|
+
from typing import IO, Any, List, Optional, Union
|
|
5
5
|
|
|
6
|
-
from agno.
|
|
7
|
-
from agno.
|
|
6
|
+
from agno.knowledge.chunking.markdown import MarkdownChunking
|
|
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.types import ContentType
|
|
8
11
|
from agno.utils.log import log_info, logger
|
|
9
12
|
|
|
10
13
|
|
|
11
14
|
class MarkdownReader(Reader):
|
|
12
15
|
"""Reader for Markdown files"""
|
|
13
16
|
|
|
14
|
-
|
|
17
|
+
@classmethod
|
|
18
|
+
def get_supported_chunking_strategies(self) -> List[ChunkingStrategyType]:
|
|
19
|
+
"""Get the list of supported chunking strategies for Markdown readers."""
|
|
20
|
+
return [
|
|
21
|
+
ChunkingStrategyType.MARKDOWN_CHUNKING,
|
|
22
|
+
ChunkingStrategyType.AGENTIC_CHUNKING,
|
|
23
|
+
ChunkingStrategyType.DOCUMENT_CHUNKING,
|
|
24
|
+
ChunkingStrategyType.RECURSIVE_CHUNKING,
|
|
25
|
+
ChunkingStrategyType.SEMANTIC_CHUNKING,
|
|
26
|
+
ChunkingStrategyType.FIXED_SIZE_CHUNKING,
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
@classmethod
|
|
30
|
+
def get_supported_content_types(self) -> List[ContentType]:
|
|
31
|
+
return [ContentType.MARKDOWN]
|
|
32
|
+
|
|
33
|
+
def __init__(
|
|
34
|
+
self,
|
|
35
|
+
chunking_strategy: Optional[ChunkingStrategy] = MarkdownChunking(),
|
|
36
|
+
name: Optional[str] = None,
|
|
37
|
+
description: Optional[str] = None,
|
|
38
|
+
) -> None:
|
|
39
|
+
super().__init__(chunking_strategy=chunking_strategy, name=name, description=description)
|
|
40
|
+
|
|
41
|
+
def read(self, file: Union[Path, IO[Any]], name: Optional[str] = None) -> List[Document]:
|
|
15
42
|
try:
|
|
16
43
|
if isinstance(file, Path):
|
|
17
44
|
if not file.exists():
|
|
18
45
|
raise FileNotFoundError(f"Could not find file: {file}")
|
|
19
46
|
log_info(f"Reading: {file}")
|
|
20
|
-
file_name = file.stem
|
|
47
|
+
file_name = name or file.stem
|
|
21
48
|
file_contents = file.read_text("utf-8")
|
|
22
49
|
else:
|
|
23
50
|
log_info(f"Reading uploaded file: {file.name}")
|
|
24
|
-
file_name = file.name.split(".")[0]
|
|
51
|
+
file_name = name or file.name.split(".")[0]
|
|
25
52
|
file.seek(0)
|
|
26
53
|
file_contents = file.read().decode("utf-8")
|
|
27
54
|
|
|
@@ -36,14 +63,14 @@ class MarkdownReader(Reader):
|
|
|
36
63
|
logger.error(f"Error reading: {file}: {e}")
|
|
37
64
|
return []
|
|
38
65
|
|
|
39
|
-
async def async_read(self, file: Union[Path, IO[Any]]) -> List[Document]:
|
|
66
|
+
async def async_read(self, file: Union[Path, IO[Any]], name: Optional[str] = None) -> List[Document]:
|
|
40
67
|
try:
|
|
41
68
|
if isinstance(file, Path):
|
|
42
69
|
if not file.exists():
|
|
43
70
|
raise FileNotFoundError(f"Could not find file: {file}")
|
|
44
71
|
|
|
45
72
|
log_info(f"Reading asynchronously: {file}")
|
|
46
|
-
file_name = file.stem
|
|
73
|
+
file_name = name or file.stem
|
|
47
74
|
|
|
48
75
|
try:
|
|
49
76
|
import aiofiles
|
|
@@ -55,7 +82,7 @@ class MarkdownReader(Reader):
|
|
|
55
82
|
file_contents = file.read_text("utf-8")
|
|
56
83
|
else:
|
|
57
84
|
log_info(f"Reading uploaded file asynchronously: {file.name}")
|
|
58
|
-
file_name = file.name.split(".")[0]
|
|
85
|
+
file_name = name or file.name.split(".")[0]
|
|
59
86
|
file.seek(0)
|
|
60
87
|
file_contents = file.read().decode("utf-8")
|
|
61
88
|
|
|
@@ -4,8 +4,10 @@ from pathlib import Path
|
|
|
4
4
|
from typing import IO, Any, List, Optional, Tuple, Union
|
|
5
5
|
from uuid import uuid4
|
|
6
6
|
|
|
7
|
-
from agno.
|
|
8
|
-
from agno.document.
|
|
7
|
+
from agno.knowledge.chunking.strategy import ChunkingStrategyType
|
|
8
|
+
from agno.knowledge.document.base import Document
|
|
9
|
+
from agno.knowledge.reader.base import Reader
|
|
10
|
+
from agno.knowledge.types import ContentType
|
|
9
11
|
from agno.utils.http import async_fetch_with_retry, fetch_with_retry
|
|
10
12
|
from agno.utils.log import log_error, log_info, logger
|
|
11
13
|
|
|
@@ -95,9 +97,9 @@ def _clean_page_numbers(
|
|
|
95
97
|
Notes:
|
|
96
98
|
- The function scans for page numbers using a regular expression that matches digits at the start or end of a string.
|
|
97
99
|
- It evaluates several potential starting points for numbering (-2, -1, 0, 1, 2 shifts) to determine the most consistent sequence.
|
|
98
|
-
- If at least a specified ratio of pages (defined by `PAGE_NUMBERING_CORRECTNESS_RATIO_FOR_REMOVAL`) has correct sequential numbering,
|
|
100
|
+
- If at least a specified ratio of pages (defined by `PAGE_NUMBERING_CORRECTNESS_RATIO_FOR_REMOVAL`) has correct sequential numbering,
|
|
99
101
|
the page numbers are processed.
|
|
100
|
-
- If page numbers are found, the function will add formatted page numbers to each page's content if `page_start_numbering_format` or
|
|
102
|
+
- If page numbers are found, the function will add formatted page numbers to each page's content if `page_start_numbering_format` or
|
|
101
103
|
`page_end_numbering_format` is provided.
|
|
102
104
|
"""
|
|
103
105
|
assert len(extra_content) == 0 or len(extra_content) == len(page_content_list), (
|
|
@@ -190,8 +192,23 @@ class BasePDFReader(Reader):
|
|
|
190
192
|
self.page_end_numbering_format = page_end_numbering_format
|
|
191
193
|
self.password = password
|
|
192
194
|
|
|
195
|
+
if self.chunking_strategy is None:
|
|
196
|
+
from agno.knowledge.chunking.document import DocumentChunking
|
|
197
|
+
|
|
198
|
+
self.chunking_strategy = DocumentChunking(chunk_size=5000)
|
|
193
199
|
super().__init__(**kwargs)
|
|
194
200
|
|
|
201
|
+
@classmethod
|
|
202
|
+
def get_supported_chunking_strategies(self) -> List[ChunkingStrategyType]:
|
|
203
|
+
"""Get the list of supported chunking strategies for PDF readers."""
|
|
204
|
+
return [
|
|
205
|
+
ChunkingStrategyType.DOCUMENT_CHUNKING,
|
|
206
|
+
ChunkingStrategyType.FIXED_SIZE_CHUNKING,
|
|
207
|
+
ChunkingStrategyType.AGENTIC_CHUNKING,
|
|
208
|
+
ChunkingStrategyType.SEMANTIC_CHUNKING,
|
|
209
|
+
ChunkingStrategyType.RECURSIVE_CHUNKING,
|
|
210
|
+
]
|
|
211
|
+
|
|
195
212
|
def _build_chunked_documents(self, documents: List[Document]) -> List[Document]:
|
|
196
213
|
chunked_documents: List[Document] = []
|
|
197
214
|
for document in documents:
|
|
@@ -306,9 +323,17 @@ class BasePDFReader(Reader):
|
|
|
306
323
|
class PDFReader(BasePDFReader):
|
|
307
324
|
"""Reader for PDF files"""
|
|
308
325
|
|
|
309
|
-
|
|
326
|
+
@classmethod
|
|
327
|
+
def get_supported_content_types(self) -> List[ContentType]:
|
|
328
|
+
return [ContentType.PDF]
|
|
329
|
+
|
|
330
|
+
def read(
|
|
331
|
+
self, pdf: Union[str, Path, IO[Any]], name: Optional[str] = None, password: Optional[str] = None
|
|
332
|
+
) -> List[Document]:
|
|
310
333
|
try:
|
|
311
|
-
if
|
|
334
|
+
if name:
|
|
335
|
+
doc_name = name
|
|
336
|
+
elif isinstance(pdf, str):
|
|
312
337
|
doc_name = pdf.split("/")[-1].split(".")[0].replace(" ", "_")
|
|
313
338
|
else:
|
|
314
339
|
doc_name = pdf.name.split(".")[0]
|
|
@@ -317,6 +342,22 @@ class PDFReader(BasePDFReader):
|
|
|
317
342
|
|
|
318
343
|
log_info(f"Reading: {doc_name}")
|
|
319
344
|
|
|
345
|
+
try:
|
|
346
|
+
DocumentReader(pdf)
|
|
347
|
+
except PdfStreamError as e:
|
|
348
|
+
logger.error(f"Error reading PDF: {e}")
|
|
349
|
+
return []
|
|
350
|
+
|
|
351
|
+
try:
|
|
352
|
+
if isinstance(pdf, str):
|
|
353
|
+
doc_name = name or pdf.split("/")[-1].split(".")[0].replace(" ", "_")
|
|
354
|
+
else:
|
|
355
|
+
doc_name = name or pdf.name.split(".")[0]
|
|
356
|
+
except Exception:
|
|
357
|
+
doc_name = name or "pdf"
|
|
358
|
+
|
|
359
|
+
log_info(f"Reading: {doc_name}")
|
|
360
|
+
|
|
320
361
|
try:
|
|
321
362
|
pdf_reader = DocumentReader(pdf)
|
|
322
363
|
except PdfStreamError as e:
|
|
@@ -330,14 +371,23 @@ class PDFReader(BasePDFReader):
|
|
|
330
371
|
# Read and chunk.
|
|
331
372
|
return self._pdf_reader_to_documents(pdf_reader, doc_name, use_uuid_for_id=True)
|
|
332
373
|
|
|
333
|
-
async def async_read(
|
|
374
|
+
async def async_read(
|
|
375
|
+
self,
|
|
376
|
+
pdf: Optional[Union[str, Path, IO[Any]]] = None,
|
|
377
|
+
name: Optional[str] = None,
|
|
378
|
+
password: Optional[str] = None,
|
|
379
|
+
) -> List[Document]:
|
|
380
|
+
if pdf is None:
|
|
381
|
+
log_error("No pdf provided")
|
|
382
|
+
return []
|
|
383
|
+
|
|
334
384
|
try:
|
|
335
385
|
if isinstance(pdf, str):
|
|
336
|
-
doc_name = pdf.split("/")[-1].split(".")[0].replace(" ", "_")
|
|
386
|
+
doc_name = name or pdf.split("/")[-1].split(".")[0].replace(" ", "_")
|
|
337
387
|
else:
|
|
338
388
|
doc_name = pdf.name.split(".")[0]
|
|
339
389
|
except Exception:
|
|
340
|
-
doc_name = "pdf"
|
|
390
|
+
doc_name = name or "pdf"
|
|
341
391
|
|
|
342
392
|
log_info(f"Reading: {doc_name}")
|
|
343
393
|
|
|
@@ -362,7 +412,11 @@ class PDFUrlReader(BasePDFReader):
|
|
|
362
412
|
super().__init__(password=password, **kwargs)
|
|
363
413
|
self.proxy = proxy
|
|
364
414
|
|
|
365
|
-
|
|
415
|
+
@classmethod
|
|
416
|
+
def get_supported_content_types(self) -> List[ContentType]:
|
|
417
|
+
return [ContentType.URL]
|
|
418
|
+
|
|
419
|
+
def read(self, url: str, name: Optional[str] = None, password: Optional[str] = None) -> List[Document]:
|
|
366
420
|
if not url:
|
|
367
421
|
raise ValueError("No url provided")
|
|
368
422
|
|
|
@@ -373,7 +427,7 @@ class PDFUrlReader(BasePDFReader):
|
|
|
373
427
|
# Retry the request up to 3 times with exponential backoff
|
|
374
428
|
response = fetch_with_retry(url, proxy=self.proxy)
|
|
375
429
|
|
|
376
|
-
doc_name = url.split("/")[-1].split(".")[0].replace("/", "_").replace(" ", "_")
|
|
430
|
+
doc_name = name or url.split("/")[-1].split(".")[0].replace("/", "_").replace(" ", "_")
|
|
377
431
|
pdf_reader = DocumentReader(BytesIO(response.content))
|
|
378
432
|
|
|
379
433
|
# Handle PDF decryption
|
|
@@ -383,7 +437,7 @@ class PDFUrlReader(BasePDFReader):
|
|
|
383
437
|
# Read and chunk.
|
|
384
438
|
return self._pdf_reader_to_documents(pdf_reader, doc_name, use_uuid_for_id=False)
|
|
385
439
|
|
|
386
|
-
async def async_read(self, url: str, password: Optional[str] = None) -> List[Document]:
|
|
440
|
+
async def async_read(self, url: str, name: Optional[str] = None, password: Optional[str] = None) -> List[Document]:
|
|
387
441
|
if not url:
|
|
388
442
|
raise ValueError("No url provided")
|
|
389
443
|
|
|
@@ -397,7 +451,7 @@ class PDFUrlReader(BasePDFReader):
|
|
|
397
451
|
async with httpx.AsyncClient(**client_args) as client: # type: ignore
|
|
398
452
|
response = await async_fetch_with_retry(url, client=client)
|
|
399
453
|
|
|
400
|
-
doc_name = url.split("/")[-1].split(".")[0].replace("/", "_").replace(" ", "_")
|
|
454
|
+
doc_name = name or url.split("/")[-1].split(".")[0].replace("/", "_").replace(" ", "_")
|
|
401
455
|
pdf_reader = DocumentReader(BytesIO(response.content))
|
|
402
456
|
|
|
403
457
|
# Handle PDF decryption
|
|
@@ -411,13 +465,15 @@ class PDFUrlReader(BasePDFReader):
|
|
|
411
465
|
class PDFImageReader(BasePDFReader):
|
|
412
466
|
"""Reader for PDF files with text and images extraction"""
|
|
413
467
|
|
|
414
|
-
def read(
|
|
468
|
+
def read(
|
|
469
|
+
self, pdf: Union[str, Path, IO[Any]], name: Optional[str] = None, password: Optional[str] = None
|
|
470
|
+
) -> List[Document]:
|
|
415
471
|
if not pdf:
|
|
416
472
|
raise ValueError("No pdf provided")
|
|
417
473
|
|
|
418
474
|
try:
|
|
419
475
|
if isinstance(pdf, str):
|
|
420
|
-
doc_name = pdf.split("/")[-1].split(".")[0].replace(" ", "_")
|
|
476
|
+
doc_name = name or pdf.split("/")[-1].split(".")[0].replace(" ", "_")
|
|
421
477
|
else:
|
|
422
478
|
doc_name = pdf.name.split(".")[0]
|
|
423
479
|
except Exception:
|
|
@@ -433,13 +489,15 @@ class PDFImageReader(BasePDFReader):
|
|
|
433
489
|
# Read and chunk.
|
|
434
490
|
return self._pdf_reader_to_documents(pdf_reader, doc_name, read_images=True, use_uuid_for_id=False)
|
|
435
491
|
|
|
436
|
-
async def async_read(
|
|
492
|
+
async def async_read(
|
|
493
|
+
self, pdf: Union[str, Path, IO[Any]], name: Optional[str] = None, password: Optional[str] = None
|
|
494
|
+
) -> List[Document]:
|
|
437
495
|
if not pdf:
|
|
438
496
|
raise ValueError("No pdf provided")
|
|
439
497
|
|
|
440
498
|
try:
|
|
441
499
|
if isinstance(pdf, str):
|
|
442
|
-
doc_name = pdf.split("/")[-1].split(".")[0].replace(" ", "_")
|
|
500
|
+
doc_name = name or pdf.split("/")[-1].split(".")[0].replace(" ", "_")
|
|
443
501
|
else:
|
|
444
502
|
doc_name = pdf.name.split(".")[0]
|
|
445
503
|
except Exception:
|
|
@@ -463,7 +521,7 @@ class PDFUrlImageReader(BasePDFReader):
|
|
|
463
521
|
super().__init__(password=password, **kwargs)
|
|
464
522
|
self.proxy = proxy
|
|
465
523
|
|
|
466
|
-
def read(self, url: str, password: Optional[str] = None) -> List[Document]:
|
|
524
|
+
def read(self, url: str, name: Optional[str] = None, password: Optional[str] = None) -> List[Document]:
|
|
467
525
|
if not url:
|
|
468
526
|
raise ValueError("No url provided")
|
|
469
527
|
|
|
@@ -475,7 +533,7 @@ class PDFUrlImageReader(BasePDFReader):
|
|
|
475
533
|
log_info(f"Reading: {url}")
|
|
476
534
|
response = httpx.get(url, proxy=self.proxy) if self.proxy else httpx.get(url)
|
|
477
535
|
|
|
478
|
-
doc_name = url.split("/")[-1].split(".")[0].replace(" ", "_")
|
|
536
|
+
doc_name = name or url.split("/")[-1].split(".")[0].replace(" ", "_")
|
|
479
537
|
pdf_reader = DocumentReader(BytesIO(response.content))
|
|
480
538
|
|
|
481
539
|
# Handle PDF decryption
|
|
@@ -485,7 +543,7 @@ class PDFUrlImageReader(BasePDFReader):
|
|
|
485
543
|
# Read and chunk.
|
|
486
544
|
return self._pdf_reader_to_documents(pdf_reader, doc_name, read_images=True, use_uuid_for_id=False)
|
|
487
545
|
|
|
488
|
-
async def async_read(self, url: str, password: Optional[str] = None) -> List[Document]:
|
|
546
|
+
async def async_read(self, url: str, name: Optional[str] = None, password: Optional[str] = None) -> List[Document]:
|
|
489
547
|
if not url:
|
|
490
548
|
raise ValueError("No url provided")
|
|
491
549
|
|
|
@@ -500,7 +558,7 @@ class PDFUrlImageReader(BasePDFReader):
|
|
|
500
558
|
response = await client.get(url)
|
|
501
559
|
response.raise_for_status()
|
|
502
560
|
|
|
503
|
-
doc_name = url.split("/")[-1].split(".")[0].replace(" ", "_")
|
|
561
|
+
doc_name = name or url.split("/")[-1].split(".")[0].replace(" ", "_")
|
|
504
562
|
pdf_reader = DocumentReader(BytesIO(response.content))
|
|
505
563
|
|
|
506
564
|
# Handle PDF decryption
|
|
@@ -0,0 +1,275 @@
|
|
|
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] = {"chunk": True, "chunk_size": 100}
|
|
19
|
+
config.update(kwargs)
|
|
20
|
+
return PDFReader(**config)
|
|
21
|
+
|
|
22
|
+
@classmethod
|
|
23
|
+
def _get_csv_reader(cls, **kwargs) -> Reader:
|
|
24
|
+
"""Get CSV reader instance."""
|
|
25
|
+
from agno.knowledge.reader.csv_reader import CSVReader
|
|
26
|
+
|
|
27
|
+
config: Dict[str, Any] = {"name": "CSV Reader", "description": "Reads CSV files"}
|
|
28
|
+
config.update(kwargs)
|
|
29
|
+
return CSVReader(**config)
|
|
30
|
+
|
|
31
|
+
@classmethod
|
|
32
|
+
def _get_docx_reader(cls, **kwargs) -> Reader:
|
|
33
|
+
"""Get Docx reader instance."""
|
|
34
|
+
from agno.knowledge.reader.docx_reader import DocxReader
|
|
35
|
+
|
|
36
|
+
config: Dict[str, Any] = {"name": "Docx Reader", "description": "Reads Docx files"}
|
|
37
|
+
config.update(kwargs)
|
|
38
|
+
return DocxReader(**config)
|
|
39
|
+
|
|
40
|
+
@classmethod
|
|
41
|
+
def _get_json_reader(cls, **kwargs) -> Reader:
|
|
42
|
+
"""Get JSON reader instance."""
|
|
43
|
+
from agno.knowledge.reader.json_reader import JSONReader
|
|
44
|
+
|
|
45
|
+
config: Dict[str, Any] = {"name": "JSON Reader", "description": "Reads JSON files"}
|
|
46
|
+
config.update(kwargs)
|
|
47
|
+
return JSONReader(**config)
|
|
48
|
+
|
|
49
|
+
@classmethod
|
|
50
|
+
def _get_markdown_reader(cls, **kwargs) -> Reader:
|
|
51
|
+
"""Get Markdown reader instance."""
|
|
52
|
+
from agno.knowledge.reader.markdown_reader import MarkdownReader
|
|
53
|
+
|
|
54
|
+
config: Dict[str, Any] = {"name": "Markdown Reader", "description": "Reads Markdown files"}
|
|
55
|
+
config.update(kwargs)
|
|
56
|
+
return MarkdownReader(**config)
|
|
57
|
+
|
|
58
|
+
@classmethod
|
|
59
|
+
def _get_text_reader(cls, **kwargs) -> Reader:
|
|
60
|
+
"""Get Text reader instance."""
|
|
61
|
+
from agno.knowledge.reader.text_reader import TextReader
|
|
62
|
+
|
|
63
|
+
config: Dict[str, Any] = {"name": "Text Reader", "description": "Reads Text files"}
|
|
64
|
+
config.update(kwargs)
|
|
65
|
+
return TextReader(**config)
|
|
66
|
+
|
|
67
|
+
@classmethod
|
|
68
|
+
def _get_url_reader(cls, **kwargs) -> Reader:
|
|
69
|
+
"""Get URL reader instance."""
|
|
70
|
+
from agno.knowledge.reader.url_reader import URLReader
|
|
71
|
+
|
|
72
|
+
config: Dict[str, Any] = {"name": "URL Reader", "description": "Reads URLs"}
|
|
73
|
+
config.update(kwargs)
|
|
74
|
+
return URLReader(**config)
|
|
75
|
+
|
|
76
|
+
@classmethod
|
|
77
|
+
def _get_website_reader(cls, **kwargs) -> Reader:
|
|
78
|
+
"""Get Website reader instance."""
|
|
79
|
+
from agno.knowledge.reader.website_reader import WebsiteReader
|
|
80
|
+
|
|
81
|
+
config: Dict[str, Any] = {"name": "Website Reader", "description": "Reads Website files"}
|
|
82
|
+
config.update(kwargs)
|
|
83
|
+
return WebsiteReader(**config)
|
|
84
|
+
|
|
85
|
+
@classmethod
|
|
86
|
+
def _get_firecrawl_reader(cls, **kwargs) -> Reader:
|
|
87
|
+
"""Get Firecrawl reader instance."""
|
|
88
|
+
from agno.knowledge.reader.firecrawl_reader import FirecrawlReader
|
|
89
|
+
|
|
90
|
+
config: Dict[str, Any] = {
|
|
91
|
+
"api_key": kwargs.get("api_key") or os.getenv("FIRECRAWL_API_KEY"),
|
|
92
|
+
"mode": "crawl",
|
|
93
|
+
"name": "Firecrawl Reader",
|
|
94
|
+
"description": "Crawls websites",
|
|
95
|
+
}
|
|
96
|
+
config.update(kwargs)
|
|
97
|
+
return FirecrawlReader(**config)
|
|
98
|
+
|
|
99
|
+
@classmethod
|
|
100
|
+
def _get_youtube_reader(cls, **kwargs) -> Reader:
|
|
101
|
+
"""Get YouTube reader instance."""
|
|
102
|
+
from agno.knowledge.reader.youtube_reader import YouTubeReader
|
|
103
|
+
|
|
104
|
+
config: Dict[str, Any] = {"name": "YouTube Reader", "description": "Reads YouTube videos"}
|
|
105
|
+
config.update(kwargs)
|
|
106
|
+
return YouTubeReader(**config)
|
|
107
|
+
|
|
108
|
+
@classmethod
|
|
109
|
+
def _get_pdf_url_reader(cls, **kwargs) -> Reader:
|
|
110
|
+
"""Get PDF URL reader instance."""
|
|
111
|
+
from agno.knowledge.reader.pdf_reader import PDFUrlReader
|
|
112
|
+
|
|
113
|
+
config: Dict[str, Any] = {"name": "PDF URL Reader", "description": "Reads PDF URLs"}
|
|
114
|
+
config.update(kwargs)
|
|
115
|
+
return PDFUrlReader(**config)
|
|
116
|
+
|
|
117
|
+
@classmethod
|
|
118
|
+
def _get_csv_url_reader(cls, **kwargs) -> Reader:
|
|
119
|
+
"""Get CSV URL reader instance."""
|
|
120
|
+
from agno.knowledge.reader.csv_reader import CSVUrlReader
|
|
121
|
+
|
|
122
|
+
config: Dict[str, Any] = {"name": "CSV URL Reader", "description": "Reads CSV URLs"}
|
|
123
|
+
config.update(kwargs)
|
|
124
|
+
return CSVUrlReader(**config)
|
|
125
|
+
|
|
126
|
+
@classmethod
|
|
127
|
+
def _get_s3_reader(cls, **kwargs) -> Reader:
|
|
128
|
+
"""Get S3 reader instance."""
|
|
129
|
+
from agno.knowledge.reader.s3_reader import S3Reader
|
|
130
|
+
|
|
131
|
+
config: Dict[str, Any] = {"name": "S3 Reader", "description": "Reads S3 files"}
|
|
132
|
+
config.update(kwargs)
|
|
133
|
+
return S3Reader(**config)
|
|
134
|
+
|
|
135
|
+
@classmethod
|
|
136
|
+
def _get_gcs_reader(cls, **kwargs) -> Reader:
|
|
137
|
+
"""Get GCS reader instance."""
|
|
138
|
+
from agno.knowledge.reader.gcs_reader import GCSReader
|
|
139
|
+
|
|
140
|
+
config: Dict[str, Any] = {"name": "GCS Reader", "description": "Reads GCS files"}
|
|
141
|
+
config.update(kwargs)
|
|
142
|
+
return GCSReader(**config)
|
|
143
|
+
|
|
144
|
+
@classmethod
|
|
145
|
+
def _get_arxiv_reader(cls, **kwargs) -> Reader:
|
|
146
|
+
"""Get Arxiv reader instance."""
|
|
147
|
+
from agno.knowledge.reader.arxiv_reader import ArxivReader
|
|
148
|
+
|
|
149
|
+
config: Dict[str, Any] = {"name": "Arxiv Reader", "description": "Reads Arxiv papers"}
|
|
150
|
+
config.update(kwargs)
|
|
151
|
+
return ArxivReader(**config)
|
|
152
|
+
|
|
153
|
+
@classmethod
|
|
154
|
+
def _get_wikipedia_reader(cls, **kwargs) -> Reader:
|
|
155
|
+
"""Get Wikipedia reader instance."""
|
|
156
|
+
from agno.knowledge.reader.wikipedia_reader import WikipediaReader
|
|
157
|
+
|
|
158
|
+
config: Dict[str, Any] = {"name": "Wikipedia Reader", "description": "Reads Wikipedia articles"}
|
|
159
|
+
config.update(kwargs)
|
|
160
|
+
return WikipediaReader(**config)
|
|
161
|
+
|
|
162
|
+
@classmethod
|
|
163
|
+
def _get_web_search_reader(cls, **kwargs) -> Reader:
|
|
164
|
+
"""Get Web Search reader instance."""
|
|
165
|
+
from agno.knowledge.reader.web_search_reader import WebSearchReader
|
|
166
|
+
|
|
167
|
+
config: Dict[str, Any] = {"name": "Web Search Reader", "description": "Performs web searches"}
|
|
168
|
+
config.update(kwargs)
|
|
169
|
+
return WebSearchReader(**config)
|
|
170
|
+
|
|
171
|
+
@classmethod
|
|
172
|
+
def _get_reader_method(cls, reader_key: str) -> Callable[[], Reader]:
|
|
173
|
+
"""Get the appropriate reader method for the given key."""
|
|
174
|
+
method_name = f"_get_{reader_key}_reader"
|
|
175
|
+
if not hasattr(cls, method_name):
|
|
176
|
+
raise ValueError(f"Unknown reader: {reader_key}")
|
|
177
|
+
return getattr(cls, method_name)
|
|
178
|
+
|
|
179
|
+
@classmethod
|
|
180
|
+
def create_reader(cls, reader_key: str, **kwargs) -> Reader:
|
|
181
|
+
"""Create a reader instance with the given key and optional overrides."""
|
|
182
|
+
if reader_key in cls._reader_cache:
|
|
183
|
+
return cls._reader_cache[reader_key]
|
|
184
|
+
|
|
185
|
+
# Get the reader method and create the instance
|
|
186
|
+
reader_method = cls._get_reader_method(reader_key)
|
|
187
|
+
reader = reader_method(**kwargs)
|
|
188
|
+
|
|
189
|
+
# Cache the reader
|
|
190
|
+
cls._reader_cache[reader_key] = reader
|
|
191
|
+
|
|
192
|
+
return reader
|
|
193
|
+
|
|
194
|
+
@classmethod
|
|
195
|
+
def get_reader_for_extension(cls, extension: str) -> Reader:
|
|
196
|
+
"""Get the appropriate reader for a file extension."""
|
|
197
|
+
extension = extension.lower()
|
|
198
|
+
|
|
199
|
+
if extension in [".pdf", "application/pdf"]:
|
|
200
|
+
return cls.create_reader("pdf")
|
|
201
|
+
elif extension in [".csv", "text/csv"]:
|
|
202
|
+
return cls.create_reader("csv")
|
|
203
|
+
elif extension in [".docx", ".doc"]:
|
|
204
|
+
return cls.create_reader("docx")
|
|
205
|
+
elif extension == ".json":
|
|
206
|
+
return cls.create_reader("json")
|
|
207
|
+
elif extension in [".md", ".markdown"]:
|
|
208
|
+
return cls.create_reader("markdown")
|
|
209
|
+
elif extension in [".txt", ".text"]:
|
|
210
|
+
return cls.create_reader("text")
|
|
211
|
+
else:
|
|
212
|
+
# Default to text reader for unknown extensions
|
|
213
|
+
return cls.create_reader("text")
|
|
214
|
+
|
|
215
|
+
@classmethod
|
|
216
|
+
def get_reader_for_url(cls, url: str) -> Reader:
|
|
217
|
+
"""Get the appropriate reader for a URL."""
|
|
218
|
+
url_lower = url.lower()
|
|
219
|
+
|
|
220
|
+
# Check for YouTube URLs
|
|
221
|
+
if any(domain in url_lower for domain in ["youtube.com", "youtu.be"]):
|
|
222
|
+
return cls.create_reader("youtube")
|
|
223
|
+
|
|
224
|
+
# Default to URL reader
|
|
225
|
+
return cls.create_reader("url")
|
|
226
|
+
|
|
227
|
+
@classmethod
|
|
228
|
+
def get_reader_for_url_file(cls, extension: str) -> Reader:
|
|
229
|
+
"""Get the appropriate reader for a URL file extension."""
|
|
230
|
+
extension = extension.lower()
|
|
231
|
+
|
|
232
|
+
if extension == ".pdf":
|
|
233
|
+
return cls.create_reader("pdf_url")
|
|
234
|
+
elif extension == ".csv":
|
|
235
|
+
return cls.create_reader("csv_url")
|
|
236
|
+
else:
|
|
237
|
+
return cls.create_reader("url")
|
|
238
|
+
|
|
239
|
+
@classmethod
|
|
240
|
+
def get_all_reader_keys(cls) -> List[str]:
|
|
241
|
+
"""Get all available reader keys."""
|
|
242
|
+
# Extract reader keys from method names
|
|
243
|
+
reader_keys = []
|
|
244
|
+
for attr_name in dir(cls):
|
|
245
|
+
if attr_name.startswith("_get_") and attr_name.endswith("_reader"):
|
|
246
|
+
reader_key = attr_name[5:-7] # Remove "_get_" prefix and "_reader" suffix
|
|
247
|
+
reader_keys.append(reader_key)
|
|
248
|
+
return reader_keys
|
|
249
|
+
|
|
250
|
+
@classmethod
|
|
251
|
+
def create_all_readers(cls) -> Dict[str, Reader]:
|
|
252
|
+
"""Create all readers and return them as a dictionary."""
|
|
253
|
+
readers = {}
|
|
254
|
+
for reader_key in cls.get_all_reader_keys():
|
|
255
|
+
readers[reader_key] = cls.create_reader(reader_key)
|
|
256
|
+
return readers
|
|
257
|
+
|
|
258
|
+
@classmethod
|
|
259
|
+
def clear_cache(cls):
|
|
260
|
+
"""Clear the reader cache."""
|
|
261
|
+
cls._reader_cache.clear()
|
|
262
|
+
|
|
263
|
+
@classmethod
|
|
264
|
+
def register_reader(
|
|
265
|
+
cls,
|
|
266
|
+
key: str,
|
|
267
|
+
reader_method,
|
|
268
|
+
name: str,
|
|
269
|
+
description: str,
|
|
270
|
+
extensions: Optional[List[str]] = None,
|
|
271
|
+
):
|
|
272
|
+
"""Register a new reader type."""
|
|
273
|
+
# Add the reader method to the class
|
|
274
|
+
method_name = f"_get_{key}_reader"
|
|
275
|
+
setattr(cls, method_name, classmethod(reader_method))
|