agno 1.8.1__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/__init__.py +8 -0
- 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 +15 -11
- 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 +131 -131
- agno/models/aws/bedrock.py +110 -182
- 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 +77 -33
- 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 +22 -22
- 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 +19 -34
- 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 +32 -2
- 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 +47 -4
- 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 -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 -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 -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.1.dist-info/METADATA +0 -982
- agno-1.8.1.dist-info/RECORD +0 -566
- agno-1.8.1.dist-info/entry_points.txt +0 -3
- agno-1.8.1.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.1.dist-info → agno-2.0.0.dist-info}/WHEEL +0 -0
- {agno-1.8.1.dist-info → agno-2.0.0.dist-info}/top_level.txt +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import asyncio
|
|
1
2
|
from hashlib import md5
|
|
2
3
|
from typing import Any, Dict, List, Optional
|
|
3
4
|
|
|
@@ -10,8 +11,8 @@ try:
|
|
|
10
11
|
except ImportError:
|
|
11
12
|
raise ImportError("`clickhouse-connect` not installed. Use `pip install clickhouse-connect` to install it")
|
|
12
13
|
|
|
13
|
-
from agno.document import Document
|
|
14
|
-
from agno.embedder import Embedder
|
|
14
|
+
from agno.knowledge.document import Document
|
|
15
|
+
from agno.knowledge.embedder import Embedder
|
|
15
16
|
from agno.utils.log import log_debug, log_info, logger
|
|
16
17
|
from agno.vectordb.base import VectorDb
|
|
17
18
|
from agno.vectordb.distance import Distance
|
|
@@ -62,7 +63,7 @@ class Clickhouse(VectorDb):
|
|
|
62
63
|
# Embedder for embedding the document contents
|
|
63
64
|
_embedder = embedder
|
|
64
65
|
if _embedder is None:
|
|
65
|
-
from agno.embedder.openai import OpenAIEmbedder
|
|
66
|
+
from agno.knowledge.embedder.openai import OpenAIEmbedder
|
|
66
67
|
|
|
67
68
|
_embedder = OpenAIEmbedder()
|
|
68
69
|
log_info("Embedder not provided, using OpenAIEmbedder as default.")
|
|
@@ -157,6 +158,7 @@ class Clickhouse(VectorDb):
|
|
|
157
158
|
meta_data JSON DEFAULT '{{}}',
|
|
158
159
|
filters JSON DEFAULT '{{}}',
|
|
159
160
|
content String,
|
|
161
|
+
content_id String,
|
|
160
162
|
embedding Array(Float32),
|
|
161
163
|
usage JSON,
|
|
162
164
|
created_at DateTime('UTC') DEFAULT now(),
|
|
@@ -201,6 +203,7 @@ class Clickhouse(VectorDb):
|
|
|
201
203
|
meta_data JSON DEFAULT '{{}}',
|
|
202
204
|
filters JSON DEFAULT '{{}}',
|
|
203
205
|
content String,
|
|
206
|
+
content_id String,
|
|
204
207
|
embedding Array(Float32),
|
|
205
208
|
usage JSON,
|
|
206
209
|
created_at DateTime('UTC') DEFAULT now(),
|
|
@@ -211,37 +214,6 @@ class Clickhouse(VectorDb):
|
|
|
211
214
|
parameters=parameters,
|
|
212
215
|
)
|
|
213
216
|
|
|
214
|
-
def doc_exists(self, document: Document) -> bool:
|
|
215
|
-
"""
|
|
216
|
-
Validating if the document exists or not
|
|
217
|
-
|
|
218
|
-
Args:
|
|
219
|
-
document (Document): Document to validate
|
|
220
|
-
"""
|
|
221
|
-
cleaned_content = document.content.replace("\x00", "\ufffd")
|
|
222
|
-
parameters = self._get_base_parameters()
|
|
223
|
-
parameters["content_hash"] = md5(cleaned_content.encode()).hexdigest()
|
|
224
|
-
|
|
225
|
-
result = self.client.query(
|
|
226
|
-
"SELECT content_hash FROM {database_name:Identifier}.{table_name:Identifier} WHERE content_hash = {content_hash:String}",
|
|
227
|
-
parameters=parameters,
|
|
228
|
-
)
|
|
229
|
-
return bool(result.result_rows)
|
|
230
|
-
|
|
231
|
-
async def async_doc_exists(self, document: Document) -> bool:
|
|
232
|
-
"""Check if a document exists asynchronously."""
|
|
233
|
-
cleaned_content = document.content.replace("\x00", "\ufffd")
|
|
234
|
-
async_client = await self._ensure_async_client()
|
|
235
|
-
|
|
236
|
-
parameters = self._get_base_parameters()
|
|
237
|
-
parameters["content_hash"] = md5(cleaned_content.encode()).hexdigest()
|
|
238
|
-
|
|
239
|
-
result = await async_client.query(
|
|
240
|
-
"SELECT content_hash FROM {database_name:Identifier}.{table_name:Identifier} WHERE content_hash = {content_hash:String}",
|
|
241
|
-
parameters=parameters,
|
|
242
|
-
)
|
|
243
|
-
return bool(result.result_rows)
|
|
244
|
-
|
|
245
217
|
def name_exists(self, name: str) -> bool:
|
|
246
218
|
"""
|
|
247
219
|
Validate if a row with this name exists or not
|
|
@@ -289,6 +261,7 @@ class Clickhouse(VectorDb):
|
|
|
289
261
|
|
|
290
262
|
def insert(
|
|
291
263
|
self,
|
|
264
|
+
content_hash: str,
|
|
292
265
|
documents: List[Document],
|
|
293
266
|
filters: Optional[Dict[str, Any]] = None,
|
|
294
267
|
) -> None:
|
|
@@ -296,8 +269,7 @@ class Clickhouse(VectorDb):
|
|
|
296
269
|
for document in documents:
|
|
297
270
|
document.embed(embedder=self.embedder)
|
|
298
271
|
cleaned_content = document.content.replace("\x00", "\ufffd")
|
|
299
|
-
|
|
300
|
-
_id = document.id or content_hash
|
|
272
|
+
_id = md5(cleaned_content.encode()).hexdigest()
|
|
301
273
|
|
|
302
274
|
row: List[Any] = [
|
|
303
275
|
_id,
|
|
@@ -305,6 +277,7 @@ class Clickhouse(VectorDb):
|
|
|
305
277
|
document.meta_data,
|
|
306
278
|
filters,
|
|
307
279
|
cleaned_content,
|
|
280
|
+
document.content_id,
|
|
308
281
|
document.embedding,
|
|
309
282
|
document.usage,
|
|
310
283
|
content_hash,
|
|
@@ -320,6 +293,7 @@ class Clickhouse(VectorDb):
|
|
|
320
293
|
"meta_data",
|
|
321
294
|
"filters",
|
|
322
295
|
"content",
|
|
296
|
+
"content_id",
|
|
323
297
|
"embedding",
|
|
324
298
|
"usage",
|
|
325
299
|
"content_hash",
|
|
@@ -327,16 +301,19 @@ class Clickhouse(VectorDb):
|
|
|
327
301
|
)
|
|
328
302
|
log_debug(f"Inserted {len(documents)} documents")
|
|
329
303
|
|
|
330
|
-
async def async_insert(
|
|
304
|
+
async def async_insert(
|
|
305
|
+
self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
|
|
306
|
+
) -> None:
|
|
331
307
|
"""Insert documents asynchronously."""
|
|
332
308
|
rows: List[List[Any]] = []
|
|
333
309
|
async_client = await self._ensure_async_client()
|
|
334
310
|
|
|
311
|
+
embed_tasks = [document.async_embed(embedder=self.embedder) for document in documents]
|
|
312
|
+
await asyncio.gather(*embed_tasks, return_exceptions=True)
|
|
313
|
+
|
|
335
314
|
for document in documents:
|
|
336
|
-
document.embed(embedder=self.embedder)
|
|
337
315
|
cleaned_content = document.content.replace("\x00", "\ufffd")
|
|
338
|
-
|
|
339
|
-
_id = document.id or content_hash
|
|
316
|
+
_id = md5(cleaned_content.encode()).hexdigest()
|
|
340
317
|
|
|
341
318
|
row: List[Any] = [
|
|
342
319
|
_id,
|
|
@@ -344,6 +321,7 @@ class Clickhouse(VectorDb):
|
|
|
344
321
|
document.meta_data,
|
|
345
322
|
filters,
|
|
346
323
|
cleaned_content,
|
|
324
|
+
document.content_id,
|
|
347
325
|
document.embedding,
|
|
348
326
|
document.usage,
|
|
349
327
|
content_hash,
|
|
@@ -359,6 +337,7 @@ class Clickhouse(VectorDb):
|
|
|
359
337
|
"meta_data",
|
|
360
338
|
"filters",
|
|
361
339
|
"content",
|
|
340
|
+
"content_id",
|
|
362
341
|
"embedding",
|
|
363
342
|
"usage",
|
|
364
343
|
"content_hash",
|
|
@@ -371,6 +350,20 @@ class Clickhouse(VectorDb):
|
|
|
371
350
|
|
|
372
351
|
def upsert(
|
|
373
352
|
self,
|
|
353
|
+
content_hash: str,
|
|
354
|
+
documents: List[Document],
|
|
355
|
+
filters: Optional[Dict[str, Any]] = None,
|
|
356
|
+
) -> None:
|
|
357
|
+
"""
|
|
358
|
+
Upsert documents into the database.
|
|
359
|
+
"""
|
|
360
|
+
if self.content_hash_exists(content_hash):
|
|
361
|
+
self._delete_by_content_hash(content_hash)
|
|
362
|
+
self.insert(content_hash=content_hash, documents=documents, filters=filters)
|
|
363
|
+
|
|
364
|
+
def _upsert(
|
|
365
|
+
self,
|
|
366
|
+
content_hash: str,
|
|
374
367
|
documents: List[Document],
|
|
375
368
|
filters: Optional[Dict[str, Any]] = None,
|
|
376
369
|
) -> None:
|
|
@@ -384,7 +377,7 @@ class Clickhouse(VectorDb):
|
|
|
384
377
|
"""
|
|
385
378
|
# We are using ReplacingMergeTree engine in our table, so we need to insert the documents,
|
|
386
379
|
# then call SELECT with FINAL
|
|
387
|
-
self.insert(documents=documents, filters=filters)
|
|
380
|
+
self.insert(content_hash=content_hash, documents=documents, filters=filters)
|
|
388
381
|
|
|
389
382
|
parameters = self._get_base_parameters()
|
|
390
383
|
self.client.query(
|
|
@@ -392,11 +385,21 @@ class Clickhouse(VectorDb):
|
|
|
392
385
|
parameters=parameters,
|
|
393
386
|
)
|
|
394
387
|
|
|
395
|
-
async def async_upsert(
|
|
388
|
+
async def async_upsert(
|
|
389
|
+
self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
|
|
390
|
+
) -> None:
|
|
391
|
+
"""Upsert documents asynchronously."""
|
|
392
|
+
if self.content_hash_exists(content_hash):
|
|
393
|
+
self._delete_by_content_hash(content_hash)
|
|
394
|
+
await self._async_upsert(content_hash=content_hash, documents=documents, filters=filters)
|
|
395
|
+
|
|
396
|
+
async def _async_upsert(
|
|
397
|
+
self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
|
|
398
|
+
) -> None:
|
|
396
399
|
"""Upsert documents asynchronously."""
|
|
397
400
|
# We are using ReplacingMergeTree engine in our table, so we need to insert the documents,
|
|
398
401
|
# then call SELECT with FINAL
|
|
399
|
-
await self.async_insert(documents=documents, filters=filters)
|
|
402
|
+
await self.async_insert(content_hash=content_hash, documents=documents, filters=filters)
|
|
400
403
|
|
|
401
404
|
parameters = self._get_base_parameters()
|
|
402
405
|
await self.async_client.query( # type: ignore
|
|
@@ -412,13 +415,6 @@ class Clickhouse(VectorDb):
|
|
|
412
415
|
|
|
413
416
|
parameters = self._get_base_parameters()
|
|
414
417
|
where_query = ""
|
|
415
|
-
# if filters:
|
|
416
|
-
# query_filters: List[str] = []
|
|
417
|
-
# for key, value in filters.values():
|
|
418
|
-
# query_filters.append(f"{{{key}_key:String}} = {{{key}_value:String}}")
|
|
419
|
-
# parameters[f"{key}_key"] = key
|
|
420
|
-
# parameters[f"{key}_value"] = value
|
|
421
|
-
# where_query = f"WHERE {' AND '.join(query_filters)}"
|
|
422
418
|
|
|
423
419
|
order_by_query = ""
|
|
424
420
|
if self.distance == Distance.l2 or self.distance == Distance.max_inner_product:
|
|
@@ -429,7 +425,7 @@ class Clickhouse(VectorDb):
|
|
|
429
425
|
parameters["query_embedding"] = query_embedding
|
|
430
426
|
|
|
431
427
|
clickhouse_query = (
|
|
432
|
-
"SELECT name, meta_data, content, embedding, usage FROM "
|
|
428
|
+
"SELECT name, meta_data, content, content_id, embedding, usage FROM "
|
|
433
429
|
"{database_name:Identifier}.{table_name:Identifier} "
|
|
434
430
|
f"{where_query} {order_by_query} LIMIT {limit}"
|
|
435
431
|
)
|
|
@@ -455,9 +451,10 @@ class Clickhouse(VectorDb):
|
|
|
455
451
|
name=result[0],
|
|
456
452
|
meta_data=result[1],
|
|
457
453
|
content=result[2],
|
|
454
|
+
content_id=result[3],
|
|
458
455
|
embedder=self.embedder,
|
|
459
|
-
embedding=result[
|
|
460
|
-
usage=result[
|
|
456
|
+
embedding=result[4],
|
|
457
|
+
usage=result[5],
|
|
461
458
|
)
|
|
462
459
|
)
|
|
463
460
|
|
|
@@ -476,13 +473,6 @@ class Clickhouse(VectorDb):
|
|
|
476
473
|
|
|
477
474
|
parameters = self._get_base_parameters()
|
|
478
475
|
where_query = ""
|
|
479
|
-
# if filters:
|
|
480
|
-
# query_filters: List[str] = []
|
|
481
|
-
# for key, value in filters.values():
|
|
482
|
-
# query_filters.append(f"{{{key}_key:String}} = {{{key}_value:String}}")
|
|
483
|
-
# parameters[f"{key}_key"] = key
|
|
484
|
-
# parameters[f"{key}_value"] = value
|
|
485
|
-
# where_query = f"WHERE {' AND '.join(query_filters)}"
|
|
486
476
|
|
|
487
477
|
order_by_query = ""
|
|
488
478
|
if self.distance == Distance.l2 or self.distance == Distance.max_inner_product:
|
|
@@ -493,7 +483,7 @@ class Clickhouse(VectorDb):
|
|
|
493
483
|
parameters["query_embedding"] = query_embedding
|
|
494
484
|
|
|
495
485
|
clickhouse_query = (
|
|
496
|
-
"SELECT name, meta_data, content, embedding, usage FROM "
|
|
486
|
+
"SELECT name, meta_data, content, content_id, embedding, usage FROM "
|
|
497
487
|
"{database_name:Identifier}.{table_name:Identifier} "
|
|
498
488
|
f"{where_query} {order_by_query} LIMIT {limit}"
|
|
499
489
|
)
|
|
@@ -519,9 +509,10 @@ class Clickhouse(VectorDb):
|
|
|
519
509
|
name=result[0],
|
|
520
510
|
meta_data=result[1],
|
|
521
511
|
content=result[2],
|
|
512
|
+
content_id=result[3],
|
|
522
513
|
embedder=self.embedder,
|
|
523
|
-
embedding=result[
|
|
524
|
-
usage=result[
|
|
514
|
+
embedding=result[4],
|
|
515
|
+
usage=result[5],
|
|
525
516
|
)
|
|
526
517
|
)
|
|
527
518
|
|
|
@@ -573,3 +564,219 @@ class Clickhouse(VectorDb):
|
|
|
573
564
|
parameters=parameters,
|
|
574
565
|
)
|
|
575
566
|
return True
|
|
567
|
+
|
|
568
|
+
def delete_by_id(self, id: str) -> bool:
|
|
569
|
+
"""
|
|
570
|
+
|
|
571
|
+
Delete a document by its ID.
|
|
572
|
+
|
|
573
|
+
Args:
|
|
574
|
+
id (str): The document ID to delete
|
|
575
|
+
|
|
576
|
+
Returns:
|
|
577
|
+
bool: True if document was deleted, False otherwise
|
|
578
|
+
"""
|
|
579
|
+
try:
|
|
580
|
+
log_debug(f"ClickHouse VectorDB : Deleting document with ID {id}")
|
|
581
|
+
if not self.id_exists(id):
|
|
582
|
+
return False
|
|
583
|
+
|
|
584
|
+
parameters = self._get_base_parameters()
|
|
585
|
+
parameters["id"] = id
|
|
586
|
+
|
|
587
|
+
self.client.command(
|
|
588
|
+
"DELETE FROM {database_name:Identifier}.{table_name:Identifier} WHERE id = {id:String}",
|
|
589
|
+
parameters=parameters,
|
|
590
|
+
)
|
|
591
|
+
return True
|
|
592
|
+
except Exception as e:
|
|
593
|
+
log_info(f"Error deleting document with ID {id}: {e}")
|
|
594
|
+
return False
|
|
595
|
+
|
|
596
|
+
def delete_by_name(self, name: str) -> bool:
|
|
597
|
+
"""
|
|
598
|
+
Delete documents by name.
|
|
599
|
+
|
|
600
|
+
Args:
|
|
601
|
+
name (str): The document name to delete
|
|
602
|
+
|
|
603
|
+
Returns:
|
|
604
|
+
bool: True if documents were deleted, False otherwise
|
|
605
|
+
"""
|
|
606
|
+
try:
|
|
607
|
+
log_debug(f"ClickHouse VectorDB : Deleting documents with name {name}")
|
|
608
|
+
if not self.name_exists(name):
|
|
609
|
+
return False
|
|
610
|
+
|
|
611
|
+
parameters = self._get_base_parameters()
|
|
612
|
+
parameters["name"] = name
|
|
613
|
+
|
|
614
|
+
self.client.command(
|
|
615
|
+
"DELETE FROM {database_name:Identifier}.{table_name:Identifier} WHERE name = {name:String}",
|
|
616
|
+
parameters=parameters,
|
|
617
|
+
)
|
|
618
|
+
return True
|
|
619
|
+
except Exception as e:
|
|
620
|
+
log_info(f"Error deleting documents with name {name}: {e}")
|
|
621
|
+
return False
|
|
622
|
+
|
|
623
|
+
def delete_by_metadata(self, metadata: Dict[str, Any]) -> bool:
|
|
624
|
+
"""
|
|
625
|
+
Delete documents by metadata.
|
|
626
|
+
|
|
627
|
+
Args:
|
|
628
|
+
metadata (Dict[str, Any]): The metadata to match for deletion
|
|
629
|
+
|
|
630
|
+
Returns:
|
|
631
|
+
bool: True if documents were deleted, False otherwise
|
|
632
|
+
"""
|
|
633
|
+
try:
|
|
634
|
+
log_debug(f"ClickHouse VectorDB : Deleting documents with metadata {metadata}")
|
|
635
|
+
parameters = self._get_base_parameters()
|
|
636
|
+
|
|
637
|
+
# Build WHERE clause for metadata matching using proper ClickHouse JSON syntax
|
|
638
|
+
where_conditions = []
|
|
639
|
+
for key, value in metadata.items():
|
|
640
|
+
if isinstance(value, bool):
|
|
641
|
+
where_conditions.append(f"JSONExtractBool(toString(filters), '{key}') = {str(value).lower()}")
|
|
642
|
+
elif isinstance(value, (int, float)):
|
|
643
|
+
where_conditions.append(f"JSONExtractFloat(toString(filters), '{key}') = {value}")
|
|
644
|
+
else:
|
|
645
|
+
where_conditions.append(f"JSONExtractString(toString(filters), '{key}') = '{value}'")
|
|
646
|
+
|
|
647
|
+
if not where_conditions:
|
|
648
|
+
return False
|
|
649
|
+
|
|
650
|
+
where_clause = " AND ".join(where_conditions)
|
|
651
|
+
|
|
652
|
+
self.client.command(
|
|
653
|
+
f"DELETE FROM {{database_name:Identifier}}.{{table_name:Identifier}} WHERE {where_clause}",
|
|
654
|
+
parameters=parameters,
|
|
655
|
+
)
|
|
656
|
+
return True
|
|
657
|
+
except Exception as e:
|
|
658
|
+
log_info(f"Error deleting documents with metadata {metadata}: {e}")
|
|
659
|
+
return False
|
|
660
|
+
|
|
661
|
+
def delete_by_content_id(self, content_id: str) -> bool:
|
|
662
|
+
"""
|
|
663
|
+
Delete documents by content ID.
|
|
664
|
+
|
|
665
|
+
Args:
|
|
666
|
+
content_id (str): The content ID to delete
|
|
667
|
+
|
|
668
|
+
Returns:
|
|
669
|
+
bool: True if documents were deleted, False otherwise
|
|
670
|
+
"""
|
|
671
|
+
try:
|
|
672
|
+
log_debug(f"ClickHouse VectorDB : Deleting documents with content_id {content_id}")
|
|
673
|
+
parameters = self._get_base_parameters()
|
|
674
|
+
parameters["content_id"] = content_id
|
|
675
|
+
|
|
676
|
+
self.client.command(
|
|
677
|
+
"DELETE FROM {database_name:Identifier}.{table_name:Identifier} WHERE content_id = {content_id:String}",
|
|
678
|
+
parameters=parameters,
|
|
679
|
+
)
|
|
680
|
+
return True
|
|
681
|
+
except Exception as e:
|
|
682
|
+
log_info(f"Error deleting documents with content_id {content_id}: {e}")
|
|
683
|
+
return False
|
|
684
|
+
|
|
685
|
+
def content_hash_exists(self, content_hash: str) -> bool:
|
|
686
|
+
"""
|
|
687
|
+
Validate if a row with this content_hash exists or not
|
|
688
|
+
|
|
689
|
+
Args:
|
|
690
|
+
content_hash (str): Content hash to check
|
|
691
|
+
"""
|
|
692
|
+
parameters = self._get_base_parameters()
|
|
693
|
+
parameters["content_hash"] = content_hash
|
|
694
|
+
|
|
695
|
+
result = self.client.query(
|
|
696
|
+
"SELECT content_hash FROM {database_name:Identifier}.{table_name:Identifier} WHERE content_hash = {content_hash:String}",
|
|
697
|
+
parameters=parameters,
|
|
698
|
+
)
|
|
699
|
+
return bool(result)
|
|
700
|
+
|
|
701
|
+
def _delete_by_content_hash(self, content_hash: str) -> bool:
|
|
702
|
+
"""
|
|
703
|
+
Delete documents by content hash.
|
|
704
|
+
"""
|
|
705
|
+
try:
|
|
706
|
+
parameters = self._get_base_parameters()
|
|
707
|
+
parameters["content_hash"] = content_hash
|
|
708
|
+
|
|
709
|
+
self.client.command(
|
|
710
|
+
"DELETE FROM {database_name:Identifier}.{table_name:Identifier} WHERE content_hash = {content_hash:String}",
|
|
711
|
+
parameters=parameters,
|
|
712
|
+
)
|
|
713
|
+
return True
|
|
714
|
+
except Exception:
|
|
715
|
+
return False
|
|
716
|
+
|
|
717
|
+
def update_metadata(self, content_id: str, metadata: Dict[str, Any]) -> None:
|
|
718
|
+
"""
|
|
719
|
+
Update the metadata for documents with the given content_id.
|
|
720
|
+
|
|
721
|
+
Args:
|
|
722
|
+
content_id (str): The content ID to update
|
|
723
|
+
metadata (Dict[str, Any]): The metadata to update
|
|
724
|
+
"""
|
|
725
|
+
import json
|
|
726
|
+
|
|
727
|
+
try:
|
|
728
|
+
parameters = self._get_base_parameters()
|
|
729
|
+
parameters["content_id"] = content_id
|
|
730
|
+
|
|
731
|
+
# First, get existing documents with their current metadata and filters
|
|
732
|
+
result = self.client.query(
|
|
733
|
+
"SELECT id, meta_data, filters FROM {database_name:Identifier}.{table_name:Identifier} WHERE content_id = {content_id:String}",
|
|
734
|
+
parameters=parameters,
|
|
735
|
+
)
|
|
736
|
+
|
|
737
|
+
if not result.result_rows:
|
|
738
|
+
logger.debug(f"No documents found with content_id: {content_id}")
|
|
739
|
+
return
|
|
740
|
+
|
|
741
|
+
# Update each document
|
|
742
|
+
updated_count = 0
|
|
743
|
+
for row in result.result_rows:
|
|
744
|
+
doc_id, current_meta_json, current_filters_json = row
|
|
745
|
+
|
|
746
|
+
# Parse existing metadata
|
|
747
|
+
try:
|
|
748
|
+
current_metadata = json.loads(current_meta_json) if current_meta_json else {}
|
|
749
|
+
except (json.JSONDecodeError, TypeError):
|
|
750
|
+
current_metadata = {}
|
|
751
|
+
|
|
752
|
+
# Parse existing filters
|
|
753
|
+
try:
|
|
754
|
+
current_filters = json.loads(current_filters_json) if current_filters_json else {}
|
|
755
|
+
except (json.JSONDecodeError, TypeError):
|
|
756
|
+
current_filters = {}
|
|
757
|
+
|
|
758
|
+
# Merge existing metadata with new metadata
|
|
759
|
+
updated_metadata = current_metadata.copy()
|
|
760
|
+
updated_metadata.update(metadata)
|
|
761
|
+
|
|
762
|
+
# Merge existing filters with new metadata
|
|
763
|
+
updated_filters = current_filters.copy()
|
|
764
|
+
updated_filters.update(metadata)
|
|
765
|
+
|
|
766
|
+
# Update the document
|
|
767
|
+
update_params = parameters.copy()
|
|
768
|
+
update_params["doc_id"] = doc_id
|
|
769
|
+
update_params["metadata_json"] = json.dumps(updated_metadata)
|
|
770
|
+
update_params["filters_json"] = json.dumps(updated_filters)
|
|
771
|
+
|
|
772
|
+
self.client.command(
|
|
773
|
+
"ALTER TABLE {database_name:Identifier}.{table_name:Identifier} UPDATE meta_data = {metadata_json:String}, filters = {filters_json:String} WHERE id = {doc_id:String}",
|
|
774
|
+
parameters=update_params,
|
|
775
|
+
)
|
|
776
|
+
updated_count += 1
|
|
777
|
+
|
|
778
|
+
logger.debug(f"Updated metadata for {updated_count} documents with content_id: {content_id}")
|
|
779
|
+
|
|
780
|
+
except Exception as e:
|
|
781
|
+
logger.error(f"Error updating metadata for content_id '{content_id}': {e}")
|
|
782
|
+
raise
|