agno 1.8.2__py3-none-any.whl → 2.0.0__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/agent/__init__.py +19 -27
- agno/agent/agent.py +3143 -4170
- agno/api/agent.py +11 -67
- agno/api/api.py +5 -46
- agno/api/evals.py +8 -19
- 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 +11 -66
- 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 +1743 -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 +1432 -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 +882 -0
- agno/db/in_memory/utils.py +172 -0
- agno/db/json/__init__.py +3 -0
- agno/db/json/json_db.py +1045 -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 +1416 -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 +297 -0
- agno/db/postgres/__init__.py +3 -0
- agno/db/postgres/postgres.py +1710 -0
- agno/db/postgres/schemas.py +124 -0
- agno/db/postgres/utils.py +280 -0
- agno/db/redis/__init__.py +3 -0
- agno/db/redis/redis.py +1367 -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 +1712 -0
- agno/db/singlestore/utils.py +326 -0
- agno/db/sqlite/__init__.py +3 -0
- agno/db/sqlite/schemas.py +119 -0
- agno/db/sqlite/sqlite.py +1676 -0
- agno/db/sqlite/utils.py +268 -0
- agno/db/utils.py +88 -0
- agno/eval/__init__.py +14 -0
- agno/eval/accuracy.py +154 -48
- 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 +1551 -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 +47 -65
- agno/knowledge/reader/docx_reader.py +83 -0
- agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
- agno/{document → knowledge}/reader/json_reader.py +30 -9
- agno/{document → knowledge}/reader/markdown_reader.py +58 -9
- agno/{document → knowledge}/reader/pdf_reader.py +71 -126
- agno/knowledge/reader/reader_factory.py +268 -0
- agno/knowledge/reader/s3_reader.py +101 -0
- agno/{document → knowledge}/reader/text_reader.py +31 -10
- agno/knowledge/reader/url_reader.py +128 -0
- agno/knowledge/reader/web_search_reader.py +366 -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 +269 -268
- 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 +128 -72
- 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 +346 -290
- agno/models/cerebras/cerebras.py +84 -27
- agno/models/cohere/chat.py +106 -98
- agno/models/google/gemini.py +105 -46
- 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 +46 -151
- 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 +85 -47
- agno/models/openai/chat.py +154 -37
- agno/models/openai/responses.py +178 -105
- agno/models/perplexity/perplexity.py +26 -2
- agno/models/portkey/portkey.py +0 -7
- agno/models/response.py +15 -9
- 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 +497 -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 +32 -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 +29 -0
- agno/os/mcp.py +235 -0
- agno/os/router.py +1400 -0
- agno/os/routers/__init__.py +3 -0
- agno/os/routers/evals/__init__.py +3 -0
- agno/os/routers/evals/evals.py +393 -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 +850 -0
- agno/os/routers/knowledge/schemas.py +118 -0
- agno/os/routers/memory/__init__.py +3 -0
- agno/os/routers/memory/memory.py +410 -0
- agno/os/routers/memory/schemas.py +58 -0
- agno/os/routers/metrics/__init__.py +3 -0
- agno/os/routers/metrics/metrics.py +178 -0
- agno/os/routers/metrics/schemas.py +47 -0
- agno/os/routers/session/__init__.py +3 -0
- agno/os/routers/session/session.py +536 -0
- agno/os/schema.py +945 -0
- agno/{app/playground → os}/settings.py +7 -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/agent.py +633 -0
- agno/run/base.py +53 -77
- agno/run/cancel.py +81 -0
- agno/run/team.py +243 -96
- agno/run/workflow.py +550 -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 +3260 -4824
- 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 +43 -23
- agno/tools/browserbase.py +13 -4
- agno/tools/calcom.py +12 -10
- agno/tools/calculator.py +10 -27
- agno/tools/cartesia.py +20 -17
- agno/tools/{clickup_tool.py → clickup.py} +12 -25
- agno/tools/confluence.py +8 -8
- agno/tools/crawl4ai.py +7 -1
- agno/tools/csv_toolkit.py +9 -8
- agno/tools/dalle.py +22 -12
- agno/tools/daytona.py +13 -16
- agno/tools/decorator.py +6 -3
- agno/tools/desi_vocal.py +17 -8
- 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 +36 -29
- agno/tools/email.py +4 -1
- agno/tools/evm.py +7 -1
- agno/tools/exa.py +19 -14
- agno/tools/fal.py +30 -30
- agno/tools/file.py +9 -8
- agno/tools/financial_datasets.py +25 -44
- agno/tools/firecrawl.py +17 -18
- agno/tools/function.py +127 -18
- agno/tools/giphy.py +23 -11
- agno/tools/github.py +48 -126
- agno/tools/gmail.py +45 -61
- 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 +32 -20
- agno/tools/mcp.py +1 -2
- 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 +33 -15
- agno/tools/models/gemini.py +59 -32
- agno/tools/models/groq.py +30 -23
- agno/tools/models/nebius.py +28 -12
- agno/tools/models_labs.py +40 -16
- agno/tools/moviepy_video.py +7 -6
- agno/tools/neo4j.py +10 -8
- agno/tools/newspaper.py +7 -2
- agno/tools/newspaper4k.py +8 -3
- agno/tools/openai.py +58 -32
- agno/tools/openbb.py +12 -11
- agno/tools/opencv.py +63 -47
- 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 +55 -42
- 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 +100 -123
- agno/utils/gemini.py +1 -1
- agno/utils/knowledge.py +29 -0
- agno/utils/log.py +54 -4
- agno/utils/mcp.py +68 -10
- agno/utils/media.py +39 -0
- agno/utils/message.py +12 -1
- agno/utils/models/aws_claude.py +1 -1
- agno/utils/models/claude.py +6 -12
- agno/utils/models/cohere.py +1 -1
- agno/utils/models/mistral.py +8 -7
- agno/utils/models/schema_utils.py +3 -3
- agno/utils/models/watsonx.py +1 -1
- agno/utils/openai.py +1 -1
- agno/utils/pprint.py +33 -32
- agno/utils/print_response/agent.py +779 -0
- agno/utils/print_response/team.py +1669 -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/streamlit.py +481 -0
- 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 +334 -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} +207 -49
- agno/workflow/{v2/steps.py → steps.py} +147 -66
- agno/workflow/types.py +482 -0
- agno/workflow/workflow.py +2410 -696
- agno-2.0.0.dist-info/METADATA +494 -0
- agno-2.0.0.dist-info/RECORD +515 -0
- agno-2.0.0.dist-info/licenses/LICENSE +201 -0
- agno/agent/metrics.py +0 -110
- 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 -1053
- agno/app/playground/deploy.py +0 -249
- agno/app/playground/operator.py +0 -183
- agno/app/playground/schemas.py +0 -223
- agno/app/playground/serve.py +0 -55
- agno/app/playground/sync_router.py +0 -1045
- 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 -702
- 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/response.py +0 -467
- 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 -3313
- 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.2.dist-info/METADATA +0 -982
- agno-1.8.2.dist-info/RECORD +0 -566
- agno-1.8.2.dist-info/entry_points.txt +0 -3
- agno-1.8.2.dist-info/licenses/LICENSE +0 -375
- /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.2.dist-info → agno-2.0.0.dist-info}/WHEEL +0 -0
- {agno-1.8.2.dist-info → agno-2.0.0.dist-info}/top_level.txt +0 -0
agno/eval/reliability.py
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
from dataclasses import asdict, dataclass, field
|
|
2
2
|
from os import getenv
|
|
3
|
-
from typing import TYPE_CHECKING, List, Optional
|
|
3
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional
|
|
4
4
|
from uuid import uuid4
|
|
5
5
|
|
|
6
|
+
from agno.db.base import BaseDb
|
|
7
|
+
|
|
6
8
|
if TYPE_CHECKING:
|
|
7
9
|
from rich.console import Console
|
|
8
10
|
|
|
9
|
-
from agno.agent import
|
|
10
|
-
from agno.
|
|
11
|
-
from agno.eval.utils import
|
|
12
|
-
from agno.run.team import
|
|
11
|
+
from agno.agent import RunOutput
|
|
12
|
+
from agno.db.schemas.evals import EvalType
|
|
13
|
+
from agno.eval.utils import async_log_eval, log_eval_run, store_result_in_file
|
|
14
|
+
from agno.run.team import TeamRunOutput
|
|
13
15
|
from agno.utils.log import logger
|
|
14
16
|
|
|
15
17
|
|
|
@@ -46,9 +48,9 @@ class ReliabilityEval:
|
|
|
46
48
|
eval_id: str = field(default_factory=lambda: str(uuid4()))
|
|
47
49
|
|
|
48
50
|
# Agent response
|
|
49
|
-
agent_response: Optional[
|
|
51
|
+
agent_response: Optional[RunOutput] = None
|
|
50
52
|
# Team response
|
|
51
|
-
team_response: Optional[
|
|
53
|
+
team_response: Optional[TeamRunOutput] = None
|
|
52
54
|
# Expected tool calls
|
|
53
55
|
expected_tool_calls: Optional[List[str]] = None
|
|
54
56
|
# Result of the evaluation
|
|
@@ -60,8 +62,13 @@ class ReliabilityEval:
|
|
|
60
62
|
file_path_to_save_results: Optional[str] = None
|
|
61
63
|
# Enable debug logs
|
|
62
64
|
debug_mode: bool = getenv("AGNO_DEBUG", "false").lower() == "true"
|
|
63
|
-
#
|
|
64
|
-
|
|
65
|
+
# The database to store Evaluation results
|
|
66
|
+
db: Optional[BaseDb] = None
|
|
67
|
+
|
|
68
|
+
# Telemetry settings
|
|
69
|
+
# telemetry=True logs minimal telemetry for analytics
|
|
70
|
+
# This helps us improve our Evals and provide better support
|
|
71
|
+
telemetry: bool = True
|
|
65
72
|
|
|
66
73
|
def run(self, *, print_results: bool = False) -> Optional[ReliabilityResult]:
|
|
67
74
|
if self.agent_response is None and self.team_response is None:
|
|
@@ -100,15 +107,18 @@ class ReliabilityEval:
|
|
|
100
107
|
|
|
101
108
|
failed_tool_calls = []
|
|
102
109
|
passed_tool_calls = []
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
if
|
|
109
|
-
|
|
110
|
+
if not actual_tool_calls:
|
|
111
|
+
failed_tool_calls = self.expected_tool_calls or []
|
|
112
|
+
else:
|
|
113
|
+
for tool_call in actual_tool_calls: # type: ignore
|
|
114
|
+
tool_name = tool_call.get("function", {}).get("name")
|
|
115
|
+
if not tool_name:
|
|
116
|
+
continue
|
|
110
117
|
else:
|
|
111
|
-
|
|
118
|
+
if tool_name not in self.expected_tool_calls: # type: ignore
|
|
119
|
+
failed_tool_calls.append(tool_call.get("function", {}).get("name"))
|
|
120
|
+
else:
|
|
121
|
+
passed_tool_calls.append(tool_call.get("function", {}).get("name"))
|
|
112
122
|
|
|
113
123
|
self.result = ReliabilityResult(
|
|
114
124
|
eval_status="PASSED" if len(failed_tool_calls) == 0 else "FAILED",
|
|
@@ -130,7 +140,7 @@ class ReliabilityEval:
|
|
|
130
140
|
self.result.print_eval(console)
|
|
131
141
|
|
|
132
142
|
# Log results to the Agno platform if requested
|
|
133
|
-
if self.
|
|
143
|
+
if self.db:
|
|
134
144
|
if self.agent_response is not None:
|
|
135
145
|
agent_id = self.agent_response.agent_id
|
|
136
146
|
team_id = None
|
|
@@ -142,7 +152,12 @@ class ReliabilityEval:
|
|
|
142
152
|
model_id = self.team_response.model
|
|
143
153
|
model_provider = self.team_response.model_provider
|
|
144
154
|
|
|
155
|
+
eval_input = {
|
|
156
|
+
"expected_tool_calls": self.expected_tool_calls,
|
|
157
|
+
}
|
|
158
|
+
|
|
145
159
|
log_eval_run(
|
|
160
|
+
db=self.db,
|
|
146
161
|
run_id=self.eval_id, # type: ignore
|
|
147
162
|
run_data=asdict(self.result),
|
|
148
163
|
eval_type=EvalType.RELIABILITY,
|
|
@@ -151,6 +166,18 @@ class ReliabilityEval:
|
|
|
151
166
|
team_id=team_id,
|
|
152
167
|
model_id=model_id,
|
|
153
168
|
model_provider=model_provider,
|
|
169
|
+
eval_input=eval_input,
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
if self.telemetry:
|
|
173
|
+
from agno.api.evals import EvalRunCreate, create_eval_run_telemetry
|
|
174
|
+
|
|
175
|
+
create_eval_run_telemetry(
|
|
176
|
+
eval_run=EvalRunCreate(
|
|
177
|
+
run_id=self.eval_id,
|
|
178
|
+
eval_type=EvalType.RELIABILITY,
|
|
179
|
+
data=self._get_telemetry_data(),
|
|
180
|
+
),
|
|
154
181
|
)
|
|
155
182
|
|
|
156
183
|
logger.debug(f"*********** Evaluation End: {self.eval_id} ***********")
|
|
@@ -223,7 +250,7 @@ class ReliabilityEval:
|
|
|
223
250
|
self.result.print_eval(console)
|
|
224
251
|
|
|
225
252
|
# Log results to the Agno platform if requested
|
|
226
|
-
if self.
|
|
253
|
+
if self.db:
|
|
227
254
|
if self.agent_response is not None:
|
|
228
255
|
agent_id = self.agent_response.agent_id
|
|
229
256
|
team_id = None
|
|
@@ -235,7 +262,12 @@ class ReliabilityEval:
|
|
|
235
262
|
model_id = self.team_response.model
|
|
236
263
|
model_provider = self.team_response.model_provider
|
|
237
264
|
|
|
238
|
-
|
|
265
|
+
eval_input = {
|
|
266
|
+
"expected_tool_calls": self.expected_tool_calls,
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
await async_log_eval(
|
|
270
|
+
db=self.db,
|
|
239
271
|
run_id=self.eval_id, # type: ignore
|
|
240
272
|
run_data=asdict(self.result),
|
|
241
273
|
eval_type=EvalType.RELIABILITY,
|
|
@@ -244,7 +276,28 @@ class ReliabilityEval:
|
|
|
244
276
|
team_id=team_id,
|
|
245
277
|
model_id=model_id,
|
|
246
278
|
model_provider=model_provider,
|
|
279
|
+
eval_input=eval_input,
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
if self.telemetry:
|
|
283
|
+
from agno.api.evals import EvalRunCreate, async_create_eval_run_telemetry
|
|
284
|
+
|
|
285
|
+
await async_create_eval_run_telemetry(
|
|
286
|
+
eval_run=EvalRunCreate(
|
|
287
|
+
run_id=self.eval_id,
|
|
288
|
+
eval_type=EvalType.RELIABILITY,
|
|
289
|
+
data=self._get_telemetry_data(),
|
|
290
|
+
),
|
|
247
291
|
)
|
|
248
292
|
|
|
249
293
|
logger.debug(f"*********** Evaluation End: {self.eval_id} ***********")
|
|
250
294
|
return self.result
|
|
295
|
+
|
|
296
|
+
def _get_telemetry_data(self) -> Dict[str, Any]:
|
|
297
|
+
"""Get the telemetry data for the evaluation"""
|
|
298
|
+
return {
|
|
299
|
+
"team_id": self.team_response.team_id if self.team_response else None,
|
|
300
|
+
"agent_id": self.agent_response.agent_id if self.agent_response else None,
|
|
301
|
+
"model_id": self.agent_response.model if self.agent_response else None,
|
|
302
|
+
"model_provider": self.agent_response.model_provider if self.agent_response else None,
|
|
303
|
+
}
|
agno/eval/utils.py
CHANGED
|
@@ -2,8 +2,8 @@ from dataclasses import asdict
|
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
from typing import TYPE_CHECKING, Optional, Union
|
|
4
4
|
|
|
5
|
-
from agno.
|
|
6
|
-
from agno.
|
|
5
|
+
from agno.db.base import BaseDb
|
|
6
|
+
from agno.db.schemas.evals import EvalRunRecord, EvalType
|
|
7
7
|
from agno.utils.log import log_debug, logger
|
|
8
8
|
|
|
9
9
|
if TYPE_CHECKING:
|
|
@@ -13,61 +13,71 @@ if TYPE_CHECKING:
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
def log_eval_run(
|
|
16
|
+
db: BaseDb,
|
|
16
17
|
run_id: str,
|
|
17
18
|
run_data: dict,
|
|
18
19
|
eval_type: EvalType,
|
|
20
|
+
eval_input: dict,
|
|
19
21
|
agent_id: Optional[str] = None,
|
|
20
22
|
model_id: Optional[str] = None,
|
|
21
23
|
model_provider: Optional[str] = None,
|
|
22
24
|
name: Optional[str] = None,
|
|
23
|
-
|
|
25
|
+
evaluated_component_name: Optional[str] = None,
|
|
24
26
|
team_id: Optional[str] = None,
|
|
27
|
+
workflow_id: Optional[str] = None,
|
|
25
28
|
) -> None:
|
|
26
29
|
"""Call the API to create an evaluation run."""
|
|
27
30
|
|
|
28
31
|
try:
|
|
29
|
-
create_eval_run(
|
|
30
|
-
|
|
32
|
+
db.create_eval_run(
|
|
33
|
+
EvalRunRecord(
|
|
31
34
|
run_id=run_id,
|
|
32
35
|
eval_type=eval_type,
|
|
33
36
|
eval_data=run_data,
|
|
37
|
+
eval_input=eval_input,
|
|
34
38
|
agent_id=agent_id,
|
|
35
39
|
model_id=model_id,
|
|
36
40
|
model_provider=model_provider,
|
|
37
41
|
name=name,
|
|
38
|
-
|
|
42
|
+
evaluated_component_name=evaluated_component_name,
|
|
39
43
|
team_id=team_id,
|
|
44
|
+
workflow_id=workflow_id,
|
|
40
45
|
)
|
|
41
46
|
)
|
|
42
47
|
except Exception as e:
|
|
43
48
|
log_debug(f"Could not create agent event: {e}")
|
|
44
49
|
|
|
45
50
|
|
|
46
|
-
async def
|
|
51
|
+
async def async_log_eval(
|
|
52
|
+
db: BaseDb,
|
|
47
53
|
run_id: str,
|
|
48
54
|
run_data: dict,
|
|
49
55
|
eval_type: EvalType,
|
|
56
|
+
eval_input: dict,
|
|
50
57
|
agent_id: Optional[str] = None,
|
|
51
58
|
model_id: Optional[str] = None,
|
|
52
59
|
model_provider: Optional[str] = None,
|
|
53
60
|
name: Optional[str] = None,
|
|
54
|
-
|
|
61
|
+
evaluated_component_name: Optional[str] = None,
|
|
55
62
|
team_id: Optional[str] = None,
|
|
63
|
+
workflow_id: Optional[str] = None,
|
|
56
64
|
) -> None:
|
|
57
|
-
"""
|
|
65
|
+
"""Call the API to create an evaluation run."""
|
|
58
66
|
|
|
59
67
|
try:
|
|
60
|
-
|
|
61
|
-
|
|
68
|
+
db.create_eval_run(
|
|
69
|
+
EvalRunRecord(
|
|
62
70
|
run_id=run_id,
|
|
63
71
|
eval_type=eval_type,
|
|
64
72
|
eval_data=run_data,
|
|
73
|
+
eval_input=eval_input,
|
|
65
74
|
agent_id=agent_id,
|
|
66
75
|
model_id=model_id,
|
|
67
76
|
model_provider=model_provider,
|
|
68
|
-
team_id=team_id,
|
|
69
77
|
name=name,
|
|
70
|
-
|
|
78
|
+
evaluated_component_name=evaluated_component_name,
|
|
79
|
+
team_id=team_id,
|
|
80
|
+
workflow_id=workflow_id,
|
|
71
81
|
)
|
|
72
82
|
)
|
|
73
83
|
except Exception as e:
|
|
@@ -4,9 +4,9 @@ from typing import Optional, Union
|
|
|
4
4
|
|
|
5
5
|
import requests
|
|
6
6
|
|
|
7
|
-
from agno.agent.agent import Agent,
|
|
7
|
+
from agno.agent.agent import Agent, RunOutput
|
|
8
8
|
from agno.media import Audio, File, Image, Video
|
|
9
|
-
from agno.team.team import Team,
|
|
9
|
+
from agno.team.team import Team, TeamRunOutput
|
|
10
10
|
from agno.utils.log import log_info, log_warning
|
|
11
11
|
from agno.utils.message import get_text_from_message
|
|
12
12
|
|
|
@@ -116,8 +116,8 @@ class DiscordClient:
|
|
|
116
116
|
""")
|
|
117
117
|
if self.agent:
|
|
118
118
|
self.agent.additional_context = additional_context
|
|
119
|
-
agent_response:
|
|
120
|
-
message_text,
|
|
119
|
+
agent_response: RunOutput = await self.agent.arun(
|
|
120
|
+
input=message_text,
|
|
121
121
|
user_id=message_user_id,
|
|
122
122
|
session_id=str(thread.id),
|
|
123
123
|
images=[Image(url=message_image)] if message_image else None,
|
|
@@ -128,8 +128,8 @@ class DiscordClient:
|
|
|
128
128
|
await self._handle_response_in_thread(agent_response, thread)
|
|
129
129
|
elif self.team:
|
|
130
130
|
self.team.additional_context = additional_context
|
|
131
|
-
team_response:
|
|
132
|
-
message_text,
|
|
131
|
+
team_response: TeamRunOutput = await self.team.arun(
|
|
132
|
+
input=message_text,
|
|
133
133
|
user_id=message_user_id,
|
|
134
134
|
session_id=str(thread.id),
|
|
135
135
|
images=[Image(url=message_image)] if message_image else None,
|
|
@@ -140,8 +140,8 @@ class DiscordClient:
|
|
|
140
140
|
await self._handle_response_in_thread(team_response, thread)
|
|
141
141
|
|
|
142
142
|
async def handle_hitl(
|
|
143
|
-
self, run_response:
|
|
144
|
-
) ->
|
|
143
|
+
self, run_response: RunOutput, thread: Union[discord.Thread, discord.TextChannel]
|
|
144
|
+
) -> RunOutput:
|
|
145
145
|
"""Handles optional Human-In-The-Loop interaction."""
|
|
146
146
|
if run_response.is_paused:
|
|
147
147
|
for tool in run_response.tools_requiring_confirmation:
|
|
@@ -158,9 +158,9 @@ class DiscordClient:
|
|
|
158
158
|
return run_response
|
|
159
159
|
|
|
160
160
|
async def _handle_response_in_thread(
|
|
161
|
-
self, response: Union[
|
|
161
|
+
self, response: Union[RunOutput, TeamRunOutput], thread: Union[discord.TextChannel, discord.Thread]
|
|
162
162
|
):
|
|
163
|
-
if isinstance(response,
|
|
163
|
+
if isinstance(response, RunOutput):
|
|
164
164
|
response = await self.handle_hitl(response, thread)
|
|
165
165
|
|
|
166
166
|
if response.reasoning_content:
|
agno/knowledge/__init__.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from typing import List, Optional
|
|
2
2
|
|
|
3
|
-
from agno.
|
|
4
|
-
from agno.document.
|
|
3
|
+
from agno.knowledge.chunking.strategy import ChunkingStrategy
|
|
4
|
+
from agno.knowledge.document.base import Document
|
|
5
5
|
from agno.models.base import Model
|
|
6
6
|
from agno.models.defaults import DEFAULT_OPENAI_MODEL_ID
|
|
7
7
|
from agno.models.message import Message
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from typing import List
|
|
2
2
|
|
|
3
|
-
from agno.
|
|
4
|
-
from agno.document.
|
|
3
|
+
from agno.knowledge.chunking.strategy import ChunkingStrategy
|
|
4
|
+
from agno.knowledge.document.base import Document
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class DocumentChunking(ChunkingStrategy):
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
from typing import List
|
|
2
2
|
|
|
3
|
-
from agno.
|
|
4
|
-
from agno.document.
|
|
3
|
+
from agno.knowledge.chunking.strategy import ChunkingStrategy
|
|
4
|
+
from agno.knowledge.document.base import Document
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class FixedSizeChunking(ChunkingStrategy):
|
|
8
8
|
"""Chunking strategy that splits text into fixed-size chunks with optional overlap"""
|
|
9
9
|
|
|
10
|
-
def __init__(self, chunk_size: int =
|
|
10
|
+
def __init__(self, chunk_size: int = 100, overlap: int = 0):
|
|
11
11
|
# overlap must be less than chunk size
|
|
12
12
|
if overlap >= chunk_size:
|
|
13
13
|
raise ValueError(f"Invalid parameters: overlap ({overlap}) must be less than chunk size ({chunk_size}).")
|
|
@@ -8,8 +8,8 @@ try:
|
|
|
8
8
|
except ImportError:
|
|
9
9
|
raise ImportError("`unstructured` not installed. Please install it using `pip install unstructured markdown`")
|
|
10
10
|
|
|
11
|
-
from agno.
|
|
12
|
-
from agno.document.
|
|
11
|
+
from agno.knowledge.chunking.strategy import ChunkingStrategy
|
|
12
|
+
from agno.knowledge.document.base import Document
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class MarkdownChunking(ChunkingStrategy):
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import warnings
|
|
2
2
|
from typing import List
|
|
3
3
|
|
|
4
|
-
from agno.
|
|
5
|
-
from agno.document.
|
|
4
|
+
from agno.knowledge.chunking.strategy import ChunkingStrategy
|
|
5
|
+
from agno.knowledge.document.base import Document
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class RecursiveChunking(ChunkingStrategy):
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from typing import List
|
|
2
2
|
|
|
3
|
-
from agno.
|
|
4
|
-
from agno.document.
|
|
3
|
+
from agno.knowledge.chunking.strategy import ChunkingStrategy
|
|
4
|
+
from agno.knowledge.document.base import Document
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class RowChunking(ChunkingStrategy):
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from typing import List, Optional
|
|
2
|
+
|
|
3
|
+
from agno.knowledge.chunking.strategy import ChunkingStrategy
|
|
4
|
+
from agno.knowledge.document.base import Document
|
|
5
|
+
from agno.knowledge.embedder.base import Embedder
|
|
6
|
+
from agno.knowledge.embedder.openai import OpenAIEmbedder
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SemanticChunking(ChunkingStrategy):
|
|
10
|
+
"""Chunking strategy that splits text into semantic chunks using chonkie"""
|
|
11
|
+
|
|
12
|
+
def __init__(self, embedder: Optional[Embedder] = None, chunk_size: int = 5000, similarity_threshold: float = 0.5):
|
|
13
|
+
self.embedder = embedder or OpenAIEmbedder(id="text-embedding-3-small") # type: ignore
|
|
14
|
+
self.chunk_size = chunk_size
|
|
15
|
+
self.similarity_threshold = similarity_threshold
|
|
16
|
+
self.chunker = None # Will be initialized lazily when needed
|
|
17
|
+
|
|
18
|
+
def _initialize_chunker(self):
|
|
19
|
+
"""Lazily initialize the chunker with chonkie dependency."""
|
|
20
|
+
if self.chunker is None:
|
|
21
|
+
try:
|
|
22
|
+
from chonkie import SemanticChunker
|
|
23
|
+
except ImportError:
|
|
24
|
+
raise ImportError(
|
|
25
|
+
"`chonkie` is required for semantic chunking. "
|
|
26
|
+
"Please install it using `pip install chonkie` to use SemanticChunking."
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
self.chunker = SemanticChunker(
|
|
30
|
+
embedding_model=self.embedder.id, # type: ignore
|
|
31
|
+
chunk_size=self.chunk_size,
|
|
32
|
+
threshold=self.similarity_threshold,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
def chunk(self, document: Document) -> List[Document]:
|
|
36
|
+
"""Split document into semantic chunks using chonkie"""
|
|
37
|
+
if not document.content:
|
|
38
|
+
return [document]
|
|
39
|
+
|
|
40
|
+
# Ensure chunker is initialized (will raise ImportError if chonkie is missing)
|
|
41
|
+
self._initialize_chunker()
|
|
42
|
+
|
|
43
|
+
# Use chonkie to split into semantic chunks
|
|
44
|
+
if self.chunker is None:
|
|
45
|
+
raise RuntimeError("Chunker failed to initialize")
|
|
46
|
+
|
|
47
|
+
chunks = self.chunker.chunk(self.clean_text(document.content))
|
|
48
|
+
|
|
49
|
+
# Convert chunks to Documents
|
|
50
|
+
chunked_documents: List[Document] = []
|
|
51
|
+
for i, chunk in enumerate(chunks, 1):
|
|
52
|
+
meta_data = document.meta_data.copy()
|
|
53
|
+
meta_data["chunk"] = i
|
|
54
|
+
chunk_id = f"{document.id}_{i}" if document.id else None
|
|
55
|
+
meta_data["chunk_size"] = len(chunk.text)
|
|
56
|
+
|
|
57
|
+
chunked_documents.append(Document(id=chunk_id, name=document.name, meta_data=meta_data, content=chunk.text))
|
|
58
|
+
|
|
59
|
+
return chunked_documents
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from typing import List
|
|
4
|
+
|
|
5
|
+
from agno.knowledge.document.base import Document
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ChunkingStrategy(ABC):
|
|
9
|
+
"""Base class for chunking strategies"""
|
|
10
|
+
|
|
11
|
+
@abstractmethod
|
|
12
|
+
def chunk(self, document: Document) -> List[Document]:
|
|
13
|
+
raise NotImplementedError
|
|
14
|
+
|
|
15
|
+
def clean_text(self, text: str) -> str:
|
|
16
|
+
"""Clean the text by replacing multiple newlines with a single newline"""
|
|
17
|
+
import re
|
|
18
|
+
|
|
19
|
+
# Replace multiple newlines with a single newline
|
|
20
|
+
cleaned_text = re.sub(r"\n+", "\n", text)
|
|
21
|
+
# Replace multiple spaces with a single space
|
|
22
|
+
cleaned_text = re.sub(r"\s+", " ", cleaned_text)
|
|
23
|
+
# Replace multiple tabs with a single tab
|
|
24
|
+
cleaned_text = re.sub(r"\t+", "\t", cleaned_text)
|
|
25
|
+
# Replace multiple carriage returns with a single carriage return
|
|
26
|
+
cleaned_text = re.sub(r"\r+", "\r", cleaned_text)
|
|
27
|
+
# Replace multiple form feeds with a single form feed
|
|
28
|
+
cleaned_text = re.sub(r"\f+", "\f", cleaned_text)
|
|
29
|
+
# Replace multiple vertical tabs with a single vertical tab
|
|
30
|
+
cleaned_text = re.sub(r"\v+", "\v", cleaned_text)
|
|
31
|
+
|
|
32
|
+
return cleaned_text
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class ChunkingStrategyType(str, Enum):
|
|
36
|
+
"""Enumeration of available chunking strategies."""
|
|
37
|
+
|
|
38
|
+
AGENTIC_CHUNKER = "AgenticChunker"
|
|
39
|
+
DOCUMENT_CHUNKER = "DocumentChunker"
|
|
40
|
+
RECURSIVE_CHUNKER = "RecursiveChunker"
|
|
41
|
+
SEMANTIC_CHUNKER = "SemanticChunker"
|
|
42
|
+
FIXED_SIZE_CHUNKER = "FixedSizeChunker"
|
|
43
|
+
ROW_CHUNKER = "RowChunker"
|
|
44
|
+
MARKDOWN_CHUNKER = "MarkdownChunker"
|
|
45
|
+
|
|
46
|
+
@classmethod
|
|
47
|
+
def from_string(cls, strategy_name: str) -> "ChunkingStrategyType":
|
|
48
|
+
"""Convert a string to a ChunkingStrategyType."""
|
|
49
|
+
strategy_name_clean = strategy_name.strip()
|
|
50
|
+
|
|
51
|
+
# Try exact enum value match first
|
|
52
|
+
for enum_member in cls:
|
|
53
|
+
if enum_member.value == strategy_name_clean:
|
|
54
|
+
return enum_member
|
|
55
|
+
|
|
56
|
+
raise ValueError(f"Unsupported chunking strategy: {strategy_name}. Valid options: {[e.value for e in cls]}")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class ChunkingStrategyFactory:
|
|
60
|
+
"""Factory for creating chunking strategy instances."""
|
|
61
|
+
|
|
62
|
+
@classmethod
|
|
63
|
+
def create_strategy(cls, strategy_type: ChunkingStrategyType, **kwargs) -> ChunkingStrategy:
|
|
64
|
+
"""Create an instance of the chunking strategy with the given parameters."""
|
|
65
|
+
strategy_map = {
|
|
66
|
+
ChunkingStrategyType.AGENTIC_CHUNKER: cls._create_agentic_chunking,
|
|
67
|
+
ChunkingStrategyType.DOCUMENT_CHUNKER: cls._create_document_chunking,
|
|
68
|
+
ChunkingStrategyType.RECURSIVE_CHUNKER: cls._create_recursive_chunking,
|
|
69
|
+
ChunkingStrategyType.SEMANTIC_CHUNKER: cls._create_semantic_chunking,
|
|
70
|
+
ChunkingStrategyType.FIXED_SIZE_CHUNKER: cls._create_fixed_chunking,
|
|
71
|
+
ChunkingStrategyType.ROW_CHUNKER: cls._create_row_chunking,
|
|
72
|
+
ChunkingStrategyType.MARKDOWN_CHUNKER: cls._create_markdown_chunking,
|
|
73
|
+
}
|
|
74
|
+
return strategy_map[strategy_type](**kwargs)
|
|
75
|
+
|
|
76
|
+
@classmethod
|
|
77
|
+
def _create_agentic_chunking(cls, **kwargs) -> ChunkingStrategy:
|
|
78
|
+
from agno.knowledge.chunking.agentic import AgenticChunking
|
|
79
|
+
|
|
80
|
+
# Map chunk_size to max_chunk_size for AgenticChunking
|
|
81
|
+
if "chunk_size" in kwargs and "max_chunk_size" not in kwargs:
|
|
82
|
+
kwargs["max_chunk_size"] = kwargs.pop("chunk_size")
|
|
83
|
+
return AgenticChunking(**kwargs)
|
|
84
|
+
|
|
85
|
+
@classmethod
|
|
86
|
+
def _create_document_chunking(cls, **kwargs) -> ChunkingStrategy:
|
|
87
|
+
from agno.knowledge.chunking.document import DocumentChunking
|
|
88
|
+
|
|
89
|
+
return DocumentChunking(**kwargs)
|
|
90
|
+
|
|
91
|
+
@classmethod
|
|
92
|
+
def _create_recursive_chunking(cls, **kwargs) -> ChunkingStrategy:
|
|
93
|
+
from agno.knowledge.chunking.recursive import RecursiveChunking
|
|
94
|
+
|
|
95
|
+
return RecursiveChunking(**kwargs)
|
|
96
|
+
|
|
97
|
+
@classmethod
|
|
98
|
+
def _create_semantic_chunking(cls, **kwargs) -> ChunkingStrategy:
|
|
99
|
+
from agno.knowledge.chunking.semantic import SemanticChunking
|
|
100
|
+
|
|
101
|
+
return SemanticChunking(**kwargs)
|
|
102
|
+
|
|
103
|
+
@classmethod
|
|
104
|
+
def _create_fixed_chunking(cls, **kwargs) -> ChunkingStrategy:
|
|
105
|
+
from agno.knowledge.chunking.fixed import FixedSizeChunking
|
|
106
|
+
|
|
107
|
+
return FixedSizeChunking(**kwargs)
|
|
108
|
+
|
|
109
|
+
@classmethod
|
|
110
|
+
def _create_row_chunking(cls, **kwargs) -> ChunkingStrategy:
|
|
111
|
+
from agno.knowledge.chunking.row import RowChunking
|
|
112
|
+
|
|
113
|
+
# Remove chunk_size if present since RowChunking doesn't use it
|
|
114
|
+
kwargs.pop("chunk_size", None)
|
|
115
|
+
return RowChunking(**kwargs)
|
|
116
|
+
|
|
117
|
+
@classmethod
|
|
118
|
+
def _create_markdown_chunking(cls, **kwargs) -> ChunkingStrategy:
|
|
119
|
+
from agno.knowledge.chunking.markdown import MarkdownChunking
|
|
120
|
+
|
|
121
|
+
return MarkdownChunking(**kwargs)
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from typing import Any, Dict, List, Optional, Union
|
|
4
|
+
|
|
5
|
+
from agno.knowledge.reader import Reader
|
|
6
|
+
from agno.knowledge.remote_content.remote_content import RemoteContent
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ContentStatus(str, Enum):
|
|
10
|
+
"""Enumeration of possible content processing statuses."""
|
|
11
|
+
|
|
12
|
+
PROCESSING = "processing"
|
|
13
|
+
COMPLETED = "completed"
|
|
14
|
+
FAILED = "failed"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class FileData:
|
|
19
|
+
content: Optional[Union[str, bytes]] = None
|
|
20
|
+
type: Optional[str] = None
|
|
21
|
+
filename: Optional[str] = None
|
|
22
|
+
size: Optional[int] = None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
class ContentAuth:
|
|
27
|
+
password: Optional[str] = None
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
class Content:
|
|
32
|
+
id: Optional[str] = None
|
|
33
|
+
name: Optional[str] = None
|
|
34
|
+
description: Optional[str] = None
|
|
35
|
+
path: Optional[str] = None
|
|
36
|
+
url: Optional[str] = None
|
|
37
|
+
auth: Optional[ContentAuth] = None
|
|
38
|
+
file_data: Optional[FileData] = None
|
|
39
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
40
|
+
topics: Optional[List[str]] = None
|
|
41
|
+
remote_content: Optional[RemoteContent] = None
|
|
42
|
+
reader: Optional[Reader] = None
|
|
43
|
+
size: Optional[int] = None
|
|
44
|
+
file_type: Optional[str] = None
|
|
45
|
+
content_hash: Optional[str] = None
|
|
46
|
+
status: Optional[ContentStatus] = None
|
|
47
|
+
status_message: Optional[str] = None
|
|
48
|
+
created_at: Optional[int] = None
|
|
49
|
+
updated_at: Optional[int] = None
|
|
50
|
+
external_id: Optional[str] = None
|
|
51
|
+
|
|
52
|
+
@classmethod
|
|
53
|
+
def from_dict(cls, data: Dict[str, Any]) -> "Content":
|
|
54
|
+
return cls(
|
|
55
|
+
id=data.get("id"),
|
|
56
|
+
name=data.get("name"),
|
|
57
|
+
description=data.get("description"),
|
|
58
|
+
path=data.get("path"),
|
|
59
|
+
url=data.get("url"),
|
|
60
|
+
auth=data.get("auth"),
|
|
61
|
+
file_data=data.get("file_data"),
|
|
62
|
+
metadata=data.get("metadata"),
|
|
63
|
+
topics=data.get("topics"),
|
|
64
|
+
remote_content=data.get("remote_content"),
|
|
65
|
+
reader=data.get("reader"),
|
|
66
|
+
size=data.get("size"),
|
|
67
|
+
file_type=data.get("file_type"),
|
|
68
|
+
content_hash=data.get("content_hash"),
|
|
69
|
+
status=data.get("status"),
|
|
70
|
+
status_message=data.get("status_message"),
|
|
71
|
+
created_at=data.get("created_at"),
|
|
72
|
+
updated_at=data.get("updated_at"),
|
|
73
|
+
external_id=data.get("external_id"),
|
|
74
|
+
)
|