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
|
@@ -3,10 +3,10 @@ import time
|
|
|
3
3
|
from datetime import timedelta
|
|
4
4
|
from typing import Any, Dict, List, Optional, Union
|
|
5
5
|
|
|
6
|
-
from agno.document import Document
|
|
7
|
-
from agno.embedder import Embedder
|
|
8
|
-
from agno.embedder.openai import OpenAIEmbedder
|
|
9
|
-
from agno.utils.log import log_debug, logger
|
|
6
|
+
from agno.knowledge.document import Document
|
|
7
|
+
from agno.knowledge.embedder import Embedder
|
|
8
|
+
from agno.knowledge.embedder.openai import OpenAIEmbedder
|
|
9
|
+
from agno.utils.log import log_debug, log_info, logger
|
|
10
10
|
from agno.vectordb.base import VectorDb
|
|
11
11
|
|
|
12
12
|
try:
|
|
@@ -287,12 +287,7 @@ class CouchbaseSearch(VectorDb):
|
|
|
287
287
|
self._create_collection_and_scope()
|
|
288
288
|
self._create_fts_index()
|
|
289
289
|
|
|
290
|
-
def
|
|
291
|
-
"""Check if a document exists in the bucket based on its content."""
|
|
292
|
-
doc_id = md5(document.content.encode("utf-8")).hexdigest()
|
|
293
|
-
return self.id_exists(doc_id)
|
|
294
|
-
|
|
295
|
-
def insert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
|
|
290
|
+
def insert(self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
|
|
296
291
|
"""
|
|
297
292
|
Insert documents into the Couchbase bucket. Fails if any document already exists.
|
|
298
293
|
|
|
@@ -304,8 +299,13 @@ class CouchbaseSearch(VectorDb):
|
|
|
304
299
|
|
|
305
300
|
docs_to_insert: Dict[str, Any] = {}
|
|
306
301
|
for document in documents:
|
|
302
|
+
if document.embedding is None:
|
|
303
|
+
document.embed(embedder=self.embedder)
|
|
304
|
+
|
|
305
|
+
if document.embedding is None:
|
|
306
|
+
raise ValueError(f"Failed to generate embedding for document: {document.name}")
|
|
307
307
|
try:
|
|
308
|
-
doc_data = self.prepare_doc(document)
|
|
308
|
+
doc_data = self.prepare_doc(content_hash, document)
|
|
309
309
|
if filters:
|
|
310
310
|
doc_data["filters"] = filters
|
|
311
311
|
# For insert_multi, the key of the dict is the document ID,
|
|
@@ -367,7 +367,19 @@ class CouchbaseSearch(VectorDb):
|
|
|
367
367
|
if errors_occurred:
|
|
368
368
|
logger.warning("Some errors occurred during the insert operation. Please check logs for details.")
|
|
369
369
|
|
|
370
|
-
def
|
|
370
|
+
def upsert_available(self) -> bool:
|
|
371
|
+
"""Check if upsert is available in Couchbase."""
|
|
372
|
+
return True
|
|
373
|
+
|
|
374
|
+
def _upsert(self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
|
|
375
|
+
"""
|
|
376
|
+
Update existing documents or insert new ones into the Couchbase bucket.
|
|
377
|
+
"""
|
|
378
|
+
if self.content_hash_exists(content_hash):
|
|
379
|
+
self._delete_by_content_hash(content_hash)
|
|
380
|
+
self.insert(content_hash=content_hash, documents=documents, filters=filters)
|
|
381
|
+
|
|
382
|
+
def upsert(self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
|
|
371
383
|
"""
|
|
372
384
|
Update existing documents or insert new ones into the Couchbase bucket.
|
|
373
385
|
|
|
@@ -380,7 +392,13 @@ class CouchbaseSearch(VectorDb):
|
|
|
380
392
|
docs_to_upsert: Dict[str, Any] = {}
|
|
381
393
|
for document in documents:
|
|
382
394
|
try:
|
|
383
|
-
|
|
395
|
+
if document.embedding is None:
|
|
396
|
+
document.embed(embedder=self.embedder)
|
|
397
|
+
|
|
398
|
+
if document.embedding is None:
|
|
399
|
+
raise ValueError(f"Failed to generate embedding for document: {document.name}")
|
|
400
|
+
|
|
401
|
+
doc_data = self.prepare_doc(content_hash, document)
|
|
384
402
|
if filters:
|
|
385
403
|
doc_data["filters"] = filters
|
|
386
404
|
# For upsert_multi, the key of the dict is the document ID,
|
|
@@ -506,6 +524,7 @@ class CouchbaseSearch(VectorDb):
|
|
|
506
524
|
content=value["content"],
|
|
507
525
|
meta_data=value["meta_data"],
|
|
508
526
|
embedding=value["embedding"],
|
|
527
|
+
content_id=value.get("content_id"),
|
|
509
528
|
)
|
|
510
529
|
)
|
|
511
530
|
|
|
@@ -543,7 +562,7 @@ class CouchbaseSearch(VectorDb):
|
|
|
543
562
|
except Exception:
|
|
544
563
|
return False
|
|
545
564
|
|
|
546
|
-
def prepare_doc(self, document: Document) -> Dict[str, Any]:
|
|
565
|
+
def prepare_doc(self, content_hash: str, document: Document) -> Dict[str, Any]:
|
|
547
566
|
"""
|
|
548
567
|
Prepare a document for insertion into Couchbase.
|
|
549
568
|
|
|
@@ -561,13 +580,6 @@ class CouchbaseSearch(VectorDb):
|
|
|
561
580
|
|
|
562
581
|
logger.debug(f"Preparing document: {document.name}")
|
|
563
582
|
|
|
564
|
-
# Generate embedding if needed
|
|
565
|
-
if document.embedding is None:
|
|
566
|
-
document.embed(embedder=self.embedder)
|
|
567
|
-
|
|
568
|
-
if document.embedding is None:
|
|
569
|
-
raise ValueError(f"Failed to generate embedding for document: {document.name}")
|
|
570
|
-
|
|
571
583
|
# Clean content and generate ID
|
|
572
584
|
cleaned_content = document.content.replace("\x00", "\ufffd")
|
|
573
585
|
doc_id = md5(cleaned_content.encode("utf-8")).hexdigest()
|
|
@@ -578,6 +590,8 @@ class CouchbaseSearch(VectorDb):
|
|
|
578
590
|
"content": cleaned_content,
|
|
579
591
|
"meta_data": document.meta_data, # Ensure meta_data is never None
|
|
580
592
|
"embedding": document.embedding,
|
|
593
|
+
"content_id": document.content_id,
|
|
594
|
+
"content_hash": content_hash,
|
|
581
595
|
}
|
|
582
596
|
|
|
583
597
|
def get_count(self) -> int:
|
|
@@ -617,6 +631,24 @@ class CouchbaseSearch(VectorDb):
|
|
|
617
631
|
logger.error(f"Error checking document existence: {e}")
|
|
618
632
|
return False
|
|
619
633
|
|
|
634
|
+
def content_hash_exists(self, content_hash: str) -> bool:
|
|
635
|
+
"""Check if a document exists in the bucket based on its content hash."""
|
|
636
|
+
try:
|
|
637
|
+
# Use N1QL query to check if document with given content_hash exists
|
|
638
|
+
query = f"SELECT content_hash FROM {self.bucket_name}.{self.scope_name}.{self.collection_name} WHERE content_hash = $content_hash LIMIT 1"
|
|
639
|
+
result = self.scope.query(
|
|
640
|
+
query,
|
|
641
|
+
QueryOptions(
|
|
642
|
+
named_parameters={"content_hash": content_hash}, scan_consistency=QueryScanConsistency.REQUEST_PLUS
|
|
643
|
+
),
|
|
644
|
+
)
|
|
645
|
+
for row in result.rows():
|
|
646
|
+
return True
|
|
647
|
+
return False
|
|
648
|
+
except Exception as e:
|
|
649
|
+
logger.error(f"Error checking document content_hash existence: {e}")
|
|
650
|
+
return False
|
|
651
|
+
|
|
620
652
|
# === ASYNC SUPPORT USING acouchbase ===
|
|
621
653
|
|
|
622
654
|
async def _create_async_cluster_instance(self) -> AsyncCluster:
|
|
@@ -806,10 +838,6 @@ class CouchbaseSearch(VectorDb):
|
|
|
806
838
|
raise TimeoutError("Timeout waiting for FTS index to become ready")
|
|
807
839
|
await asyncio.sleep(1)
|
|
808
840
|
|
|
809
|
-
async def async_doc_exists(self, document: Document) -> bool:
|
|
810
|
-
doc_id = md5(document.content.encode("utf-8")).hexdigest()
|
|
811
|
-
return await self.async_id_exists(doc_id)
|
|
812
|
-
|
|
813
841
|
async def async_id_exists(self, id: str) -> bool:
|
|
814
842
|
try:
|
|
815
843
|
async_collection_instance = await self.get_async_collection()
|
|
@@ -835,16 +863,21 @@ class CouchbaseSearch(VectorDb):
|
|
|
835
863
|
logger.error(f"[async] Error checking document name existence: {e}")
|
|
836
864
|
return False
|
|
837
865
|
|
|
838
|
-
async def async_insert(
|
|
866
|
+
async def async_insert(
|
|
867
|
+
self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
|
|
868
|
+
) -> None:
|
|
839
869
|
logger.info(f"[async] Inserting {len(documents)} documents")
|
|
840
870
|
|
|
841
871
|
async_collection_instance = await self.get_async_collection()
|
|
842
872
|
all_docs_to_insert: Dict[str, Any] = {}
|
|
843
873
|
|
|
874
|
+
embed_tasks = [document.async_embed(embedder=self.embedder) for document in documents]
|
|
875
|
+
await asyncio.gather(*embed_tasks, return_exceptions=True)
|
|
876
|
+
|
|
844
877
|
for document in documents:
|
|
845
878
|
try:
|
|
846
879
|
# User edit: self.prepare_doc is no longer awaited with to_thread
|
|
847
|
-
doc_data = self.prepare_doc(document)
|
|
880
|
+
doc_data = self.prepare_doc(content_hash, document)
|
|
848
881
|
if filters:
|
|
849
882
|
doc_data["filters"] = filters
|
|
850
883
|
doc_id = doc_data.pop("_id") # Remove _id as it's used as key
|
|
@@ -888,16 +921,29 @@ class CouchbaseSearch(VectorDb):
|
|
|
888
921
|
logger.info(f"[async] Finished processing {processed_doc_count} documents.")
|
|
889
922
|
logger.info(f"[async] Total successfully inserted: {total_inserted_count}, Total failed: {total_failed_count}.")
|
|
890
923
|
|
|
891
|
-
async def async_upsert(
|
|
924
|
+
async def async_upsert(
|
|
925
|
+
self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
|
|
926
|
+
) -> None:
|
|
927
|
+
"""Upsert documents asynchronously."""
|
|
928
|
+
if self.content_hash_exists(content_hash):
|
|
929
|
+
self._delete_by_content_hash(content_hash)
|
|
930
|
+
await self._async_upsert(content_hash=content_hash, documents=documents, filters=filters)
|
|
931
|
+
|
|
932
|
+
async def _async_upsert(
|
|
933
|
+
self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
|
|
934
|
+
) -> None:
|
|
892
935
|
logger.info(f"[async] Upserting {len(documents)} documents")
|
|
893
936
|
|
|
894
937
|
async_collection_instance = await self.get_async_collection()
|
|
895
938
|
all_docs_to_upsert: Dict[str, Any] = {}
|
|
896
939
|
|
|
940
|
+
embed_tasks = [document.async_embed(embedder=self.embedder) for document in documents]
|
|
941
|
+
await asyncio.gather(*embed_tasks, return_exceptions=True)
|
|
942
|
+
|
|
897
943
|
for document in documents:
|
|
898
944
|
try:
|
|
899
945
|
# Consistent with async_insert, prepare_doc is not awaited with to_thread based on prior user edits
|
|
900
|
-
doc_data = self.prepare_doc(document)
|
|
946
|
+
doc_data = self.prepare_doc(content_hash, document)
|
|
901
947
|
if filters:
|
|
902
948
|
doc_data["filters"] = filters
|
|
903
949
|
doc_id = doc_data.pop("_id") # _id is used as key for upsert
|
|
@@ -1069,3 +1115,237 @@ class CouchbaseSearch(VectorDb):
|
|
|
1069
1115
|
continue
|
|
1070
1116
|
|
|
1071
1117
|
return documents
|
|
1118
|
+
|
|
1119
|
+
def delete_by_id(self, id: str) -> bool:
|
|
1120
|
+
"""
|
|
1121
|
+
Delete a document by its ID.
|
|
1122
|
+
|
|
1123
|
+
Args:
|
|
1124
|
+
id (str): The document ID to delete
|
|
1125
|
+
|
|
1126
|
+
Returns:
|
|
1127
|
+
bool: True if document was deleted, False otherwise
|
|
1128
|
+
"""
|
|
1129
|
+
try:
|
|
1130
|
+
log_debug(f"Couchbase VectorDB : Deleting document with ID {id}")
|
|
1131
|
+
if not self.id_exists(id):
|
|
1132
|
+
return False
|
|
1133
|
+
|
|
1134
|
+
# Delete by ID using Couchbase collection.delete()
|
|
1135
|
+
self.collection.remove(id)
|
|
1136
|
+
log_info(f"Successfully deleted document with ID {id}")
|
|
1137
|
+
return True
|
|
1138
|
+
except Exception as e:
|
|
1139
|
+
log_info(f"Error deleting document with ID {id}: {e}")
|
|
1140
|
+
return False
|
|
1141
|
+
|
|
1142
|
+
def delete_by_name(self, name: str) -> bool:
|
|
1143
|
+
"""
|
|
1144
|
+
Delete documents by name.
|
|
1145
|
+
|
|
1146
|
+
Args:
|
|
1147
|
+
name (str): The document name to delete
|
|
1148
|
+
|
|
1149
|
+
Returns:
|
|
1150
|
+
bool: True if documents were deleted, False otherwise
|
|
1151
|
+
"""
|
|
1152
|
+
try:
|
|
1153
|
+
log_debug(f"Couchbase VectorDB : Deleting documents with name {name}")
|
|
1154
|
+
|
|
1155
|
+
query = f"SELECT META().id as doc_id, * FROM {self.bucket_name}.{self.scope_name}.{self.collection_name} WHERE name = $name"
|
|
1156
|
+
result = self.scope.query(
|
|
1157
|
+
query, QueryOptions(named_parameters={"name": name}, scan_consistency=QueryScanConsistency.REQUEST_PLUS)
|
|
1158
|
+
)
|
|
1159
|
+
rows = list(result.rows()) # Collect once
|
|
1160
|
+
|
|
1161
|
+
for row in rows:
|
|
1162
|
+
self.collection.remove(row.get("doc_id"))
|
|
1163
|
+
log_info(f"Deleted {len(rows)} documents with name {name}")
|
|
1164
|
+
return True
|
|
1165
|
+
|
|
1166
|
+
except Exception as e:
|
|
1167
|
+
log_info(f"Error deleting documents with name {name}: {e}")
|
|
1168
|
+
return False
|
|
1169
|
+
|
|
1170
|
+
def delete_by_metadata(self, metadata: Dict[str, Any]) -> bool:
|
|
1171
|
+
"""
|
|
1172
|
+
Delete documents by metadata.
|
|
1173
|
+
|
|
1174
|
+
Args:
|
|
1175
|
+
metadata (Dict[str, Any]): The metadata to match for deletion
|
|
1176
|
+
|
|
1177
|
+
Returns:
|
|
1178
|
+
bool: True if documents were deleted, False otherwise
|
|
1179
|
+
"""
|
|
1180
|
+
try:
|
|
1181
|
+
log_debug(f"Couchbase VectorDB : Deleting documents with metadata {metadata}")
|
|
1182
|
+
|
|
1183
|
+
if not metadata:
|
|
1184
|
+
log_info("No metadata provided for deletion")
|
|
1185
|
+
return False
|
|
1186
|
+
|
|
1187
|
+
# Build WHERE clause for metadata matching
|
|
1188
|
+
where_conditions = []
|
|
1189
|
+
named_parameters: Dict[str, Any] = {}
|
|
1190
|
+
|
|
1191
|
+
for key, value in metadata.items():
|
|
1192
|
+
if isinstance(value, (list, tuple)):
|
|
1193
|
+
# For array values, use ARRAY_CONTAINS
|
|
1194
|
+
where_conditions.append(
|
|
1195
|
+
f"(ARRAY_CONTAINS(filters.{key}, $value_{key}) OR ARRAY_CONTAINS(recipes.filters.{key}, $value_{key}))"
|
|
1196
|
+
)
|
|
1197
|
+
named_parameters[f"value_{key}"] = value
|
|
1198
|
+
elif isinstance(value, str):
|
|
1199
|
+
where_conditions.append(f"(filters.{key} = $value_{key} OR recipes.filters.{key} = $value_{key})")
|
|
1200
|
+
named_parameters[f"value_{key}"] = value
|
|
1201
|
+
elif isinstance(value, bool):
|
|
1202
|
+
where_conditions.append(f"(filters.{key} = $value_{key} OR recipes.filters.{key} = $value_{key})")
|
|
1203
|
+
named_parameters[f"value_{key}"] = value
|
|
1204
|
+
elif isinstance(value, (int, float)):
|
|
1205
|
+
where_conditions.append(f"(filters.{key} = $value_{key} OR recipes.filters.{key} = $value_{key})")
|
|
1206
|
+
named_parameters[f"value_{key}"] = value
|
|
1207
|
+
elif value is None:
|
|
1208
|
+
where_conditions.append(f"(filters.{key} IS NULL OR recipes.filters.{key} IS NULL)")
|
|
1209
|
+
else:
|
|
1210
|
+
# For other types, convert to string
|
|
1211
|
+
where_conditions.append(f"(filters.{key} = $value_{key} OR recipes.filters.{key} = $value_{key})")
|
|
1212
|
+
named_parameters[f"value_{key}"] = str(value)
|
|
1213
|
+
|
|
1214
|
+
if not where_conditions:
|
|
1215
|
+
log_info("No valid metadata conditions for deletion")
|
|
1216
|
+
return False
|
|
1217
|
+
|
|
1218
|
+
where_clause = " AND ".join(where_conditions)
|
|
1219
|
+
query = f"SELECT META().id as doc_id, * FROM {self.bucket_name}.{self.scope_name}.{self.collection_name} WHERE {where_clause}"
|
|
1220
|
+
|
|
1221
|
+
result = self.scope.query(
|
|
1222
|
+
query,
|
|
1223
|
+
QueryOptions(named_parameters=named_parameters, scan_consistency=QueryScanConsistency.REQUEST_PLUS),
|
|
1224
|
+
)
|
|
1225
|
+
rows = list(result.rows()) # Collect once
|
|
1226
|
+
|
|
1227
|
+
for row in rows:
|
|
1228
|
+
print(row)
|
|
1229
|
+
self.collection.remove(row.get("doc_id"))
|
|
1230
|
+
log_info(f"Deleted {len(rows)} documents with metadata {metadata}")
|
|
1231
|
+
return True
|
|
1232
|
+
|
|
1233
|
+
except Exception as e:
|
|
1234
|
+
log_info(f"Error deleting documents with metadata {metadata}: {e}")
|
|
1235
|
+
return False
|
|
1236
|
+
|
|
1237
|
+
def delete_by_content_id(self, content_id: str) -> bool:
|
|
1238
|
+
"""
|
|
1239
|
+
Delete documents by content ID.
|
|
1240
|
+
|
|
1241
|
+
Args:
|
|
1242
|
+
content_id (str): The content ID to delete
|
|
1243
|
+
|
|
1244
|
+
Returns:
|
|
1245
|
+
bool: True if documents were deleted, False otherwise
|
|
1246
|
+
"""
|
|
1247
|
+
try:
|
|
1248
|
+
log_debug(f"Couchbase VectorDB : Deleting documents with content_id {content_id}")
|
|
1249
|
+
|
|
1250
|
+
query = f"SELECT META().id as doc_id, * FROM {self.bucket_name}.{self.scope_name}.{self.collection_name} WHERE content_id = $content_id OR recipes.content_id = $content_id"
|
|
1251
|
+
result = self.scope.query(
|
|
1252
|
+
query,
|
|
1253
|
+
QueryOptions(
|
|
1254
|
+
named_parameters={"content_id": content_id}, scan_consistency=QueryScanConsistency.REQUEST_PLUS
|
|
1255
|
+
),
|
|
1256
|
+
)
|
|
1257
|
+
rows = list(result.rows()) # Collect once
|
|
1258
|
+
|
|
1259
|
+
for row in rows:
|
|
1260
|
+
self.collection.remove(row.get("doc_id"))
|
|
1261
|
+
log_info(f"Deleted {len(rows)} documents with content_id {content_id}")
|
|
1262
|
+
return True
|
|
1263
|
+
|
|
1264
|
+
except Exception as e:
|
|
1265
|
+
log_info(f"Error deleting documents with content_id {content_id}: {e}")
|
|
1266
|
+
return False
|
|
1267
|
+
|
|
1268
|
+
def _delete_by_content_hash(self, content_hash: str) -> bool:
|
|
1269
|
+
"""
|
|
1270
|
+
Delete documents by content hash.
|
|
1271
|
+
|
|
1272
|
+
Args:
|
|
1273
|
+
content_hash (str): The content hash to delete
|
|
1274
|
+
|
|
1275
|
+
Returns:
|
|
1276
|
+
bool: True if documents were deleted, False otherwise
|
|
1277
|
+
"""
|
|
1278
|
+
try:
|
|
1279
|
+
log_debug(f"Couchbase VectorDB : Deleting documents with content_hash {content_hash}")
|
|
1280
|
+
|
|
1281
|
+
query = f"SELECT META().id as doc_id, * FROM {self.bucket_name}.{self.scope_name}.{self.collection_name} WHERE content_hash = $content_hash"
|
|
1282
|
+
result = self.scope.query(
|
|
1283
|
+
query,
|
|
1284
|
+
QueryOptions(
|
|
1285
|
+
named_parameters={"content_hash": content_hash}, scan_consistency=QueryScanConsistency.REQUEST_PLUS
|
|
1286
|
+
),
|
|
1287
|
+
)
|
|
1288
|
+
rows = list(result.rows()) # Collect once
|
|
1289
|
+
|
|
1290
|
+
for row in rows:
|
|
1291
|
+
self.collection.remove(row.get("doc_id"))
|
|
1292
|
+
log_info(f"Deleted {len(rows)} documents with content_hash {content_hash}")
|
|
1293
|
+
return True
|
|
1294
|
+
|
|
1295
|
+
except Exception as e:
|
|
1296
|
+
log_info(f"Error deleting documents with content_hash {content_hash}: {e}")
|
|
1297
|
+
return False
|
|
1298
|
+
|
|
1299
|
+
def update_metadata(self, content_id: str, metadata: Dict[str, Any]) -> None:
|
|
1300
|
+
"""
|
|
1301
|
+
Update the metadata for documents with the given content_id.
|
|
1302
|
+
|
|
1303
|
+
Args:
|
|
1304
|
+
content_id (str): The content ID to update
|
|
1305
|
+
metadata (Dict[str, Any]): The metadata to update
|
|
1306
|
+
"""
|
|
1307
|
+
try:
|
|
1308
|
+
# Query for documents with the given content_id
|
|
1309
|
+
query = f"SELECT META().id as doc_id, meta_data, filters FROM `{self.bucket_name}` WHERE content_id = $content_id"
|
|
1310
|
+
result = self.cluster.query(query, content_id=content_id)
|
|
1311
|
+
|
|
1312
|
+
updated_count = 0
|
|
1313
|
+
for row in result:
|
|
1314
|
+
doc_id = row.get("doc_id")
|
|
1315
|
+
current_metadata = row.get("meta_data", {})
|
|
1316
|
+
current_filters = row.get("filters", {})
|
|
1317
|
+
|
|
1318
|
+
# Merge existing metadata with new metadata
|
|
1319
|
+
if isinstance(current_metadata, dict):
|
|
1320
|
+
updated_metadata = current_metadata.copy()
|
|
1321
|
+
updated_metadata.update(metadata)
|
|
1322
|
+
else:
|
|
1323
|
+
updated_metadata = metadata
|
|
1324
|
+
|
|
1325
|
+
# Merge existing filters with new metadata
|
|
1326
|
+
if isinstance(current_filters, dict):
|
|
1327
|
+
updated_filters = current_filters.copy()
|
|
1328
|
+
updated_filters.update(metadata)
|
|
1329
|
+
else:
|
|
1330
|
+
updated_filters = metadata
|
|
1331
|
+
|
|
1332
|
+
# Update the document
|
|
1333
|
+
try:
|
|
1334
|
+
doc = self.collection.get(doc_id)
|
|
1335
|
+
doc_content = doc.content_as[dict]
|
|
1336
|
+
doc_content["meta_data"] = updated_metadata
|
|
1337
|
+
doc_content["filters"] = updated_filters
|
|
1338
|
+
|
|
1339
|
+
self.collection.upsert(doc_id, doc_content)
|
|
1340
|
+
updated_count += 1
|
|
1341
|
+
except Exception as doc_error:
|
|
1342
|
+
logger.warning(f"Failed to update document {doc_id}: {doc_error}")
|
|
1343
|
+
|
|
1344
|
+
if updated_count == 0:
|
|
1345
|
+
logger.debug(f"No documents found with content_id: {content_id}")
|
|
1346
|
+
else:
|
|
1347
|
+
logger.debug(f"Updated metadata for {updated_count} documents with content_id: {content_id}")
|
|
1348
|
+
|
|
1349
|
+
except Exception as e:
|
|
1350
|
+
logger.error(f"Error updating metadata for content_id '{content_id}': {e}")
|
|
1351
|
+
raise
|