agno 2.2.13__py3-none-any.whl → 2.4.3__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 +6 -0
- agno/agent/agent.py +5252 -3145
- agno/agent/remote.py +525 -0
- agno/api/api.py +2 -0
- agno/client/__init__.py +3 -0
- agno/client/a2a/__init__.py +10 -0
- agno/client/a2a/client.py +554 -0
- agno/client/a2a/schemas.py +112 -0
- agno/client/a2a/utils.py +369 -0
- agno/client/os.py +2669 -0
- agno/compression/__init__.py +3 -0
- agno/compression/manager.py +247 -0
- agno/culture/manager.py +2 -2
- agno/db/base.py +927 -6
- agno/db/dynamo/dynamo.py +788 -2
- agno/db/dynamo/schemas.py +128 -0
- agno/db/dynamo/utils.py +26 -3
- agno/db/firestore/firestore.py +674 -50
- agno/db/firestore/schemas.py +41 -0
- agno/db/firestore/utils.py +25 -10
- agno/db/gcs_json/gcs_json_db.py +506 -3
- agno/db/gcs_json/utils.py +14 -2
- agno/db/in_memory/in_memory_db.py +203 -4
- agno/db/in_memory/utils.py +14 -2
- agno/db/json/json_db.py +498 -2
- agno/db/json/utils.py +14 -2
- agno/db/migrations/manager.py +199 -0
- agno/db/migrations/utils.py +19 -0
- agno/db/migrations/v1_to_v2.py +54 -16
- agno/db/migrations/versions/__init__.py +0 -0
- agno/db/migrations/versions/v2_3_0.py +977 -0
- agno/db/mongo/async_mongo.py +1013 -39
- agno/db/mongo/mongo.py +684 -4
- agno/db/mongo/schemas.py +48 -0
- agno/db/mongo/utils.py +17 -0
- agno/db/mysql/__init__.py +2 -1
- agno/db/mysql/async_mysql.py +2958 -0
- agno/db/mysql/mysql.py +722 -53
- agno/db/mysql/schemas.py +77 -11
- agno/db/mysql/utils.py +151 -8
- agno/db/postgres/async_postgres.py +1254 -137
- agno/db/postgres/postgres.py +2316 -93
- agno/db/postgres/schemas.py +153 -21
- agno/db/postgres/utils.py +22 -7
- agno/db/redis/redis.py +531 -3
- agno/db/redis/schemas.py +36 -0
- agno/db/redis/utils.py +31 -15
- agno/db/schemas/evals.py +1 -0
- agno/db/schemas/memory.py +20 -9
- agno/db/singlestore/schemas.py +70 -1
- agno/db/singlestore/singlestore.py +737 -74
- agno/db/singlestore/utils.py +13 -3
- agno/db/sqlite/async_sqlite.py +1069 -89
- agno/db/sqlite/schemas.py +133 -1
- agno/db/sqlite/sqlite.py +2203 -165
- agno/db/sqlite/utils.py +21 -11
- agno/db/surrealdb/models.py +25 -0
- agno/db/surrealdb/surrealdb.py +603 -1
- agno/db/utils.py +60 -0
- agno/eval/__init__.py +26 -3
- agno/eval/accuracy.py +25 -12
- agno/eval/agent_as_judge.py +871 -0
- agno/eval/base.py +29 -0
- agno/eval/performance.py +10 -4
- agno/eval/reliability.py +22 -13
- agno/eval/utils.py +2 -1
- agno/exceptions.py +42 -0
- agno/hooks/__init__.py +3 -0
- agno/hooks/decorator.py +164 -0
- agno/integrations/discord/client.py +13 -2
- agno/knowledge/__init__.py +4 -0
- agno/knowledge/chunking/code.py +90 -0
- agno/knowledge/chunking/document.py +65 -4
- agno/knowledge/chunking/fixed.py +4 -1
- agno/knowledge/chunking/markdown.py +102 -11
- agno/knowledge/chunking/recursive.py +2 -2
- agno/knowledge/chunking/semantic.py +130 -48
- agno/knowledge/chunking/strategy.py +18 -0
- agno/knowledge/embedder/azure_openai.py +0 -1
- agno/knowledge/embedder/google.py +1 -1
- agno/knowledge/embedder/mistral.py +1 -1
- agno/knowledge/embedder/nebius.py +1 -1
- agno/knowledge/embedder/openai.py +16 -12
- agno/knowledge/filesystem.py +412 -0
- agno/knowledge/knowledge.py +4261 -1199
- agno/knowledge/protocol.py +134 -0
- agno/knowledge/reader/arxiv_reader.py +3 -2
- agno/knowledge/reader/base.py +9 -7
- agno/knowledge/reader/csv_reader.py +91 -42
- agno/knowledge/reader/docx_reader.py +9 -10
- agno/knowledge/reader/excel_reader.py +225 -0
- agno/knowledge/reader/field_labeled_csv_reader.py +38 -48
- agno/knowledge/reader/firecrawl_reader.py +3 -2
- agno/knowledge/reader/json_reader.py +16 -22
- agno/knowledge/reader/markdown_reader.py +15 -14
- agno/knowledge/reader/pdf_reader.py +33 -28
- agno/knowledge/reader/pptx_reader.py +9 -10
- agno/knowledge/reader/reader_factory.py +135 -1
- agno/knowledge/reader/s3_reader.py +8 -16
- agno/knowledge/reader/tavily_reader.py +3 -3
- agno/knowledge/reader/text_reader.py +15 -14
- agno/knowledge/reader/utils/__init__.py +17 -0
- agno/knowledge/reader/utils/spreadsheet.py +114 -0
- agno/knowledge/reader/web_search_reader.py +8 -65
- agno/knowledge/reader/website_reader.py +16 -13
- agno/knowledge/reader/wikipedia_reader.py +36 -3
- agno/knowledge/reader/youtube_reader.py +3 -2
- agno/knowledge/remote_content/__init__.py +33 -0
- agno/knowledge/remote_content/config.py +266 -0
- agno/knowledge/remote_content/remote_content.py +105 -17
- agno/knowledge/utils.py +76 -22
- agno/learn/__init__.py +71 -0
- agno/learn/config.py +463 -0
- agno/learn/curate.py +185 -0
- agno/learn/machine.py +725 -0
- agno/learn/schemas.py +1114 -0
- agno/learn/stores/__init__.py +38 -0
- agno/learn/stores/decision_log.py +1156 -0
- agno/learn/stores/entity_memory.py +3275 -0
- agno/learn/stores/learned_knowledge.py +1583 -0
- agno/learn/stores/protocol.py +117 -0
- agno/learn/stores/session_context.py +1217 -0
- agno/learn/stores/user_memory.py +1495 -0
- agno/learn/stores/user_profile.py +1220 -0
- agno/learn/utils.py +209 -0
- agno/media.py +22 -6
- agno/memory/__init__.py +14 -1
- agno/memory/manager.py +223 -8
- agno/memory/strategies/__init__.py +15 -0
- agno/memory/strategies/base.py +66 -0
- agno/memory/strategies/summarize.py +196 -0
- agno/memory/strategies/types.py +37 -0
- agno/models/aimlapi/aimlapi.py +17 -0
- agno/models/anthropic/claude.py +434 -59
- agno/models/aws/bedrock.py +121 -20
- agno/models/aws/claude.py +131 -274
- agno/models/azure/ai_foundry.py +10 -6
- agno/models/azure/openai_chat.py +33 -10
- agno/models/base.py +1162 -561
- agno/models/cerebras/cerebras.py +120 -24
- agno/models/cerebras/cerebras_openai.py +21 -2
- agno/models/cohere/chat.py +65 -6
- agno/models/cometapi/cometapi.py +18 -1
- agno/models/dashscope/dashscope.py +2 -3
- agno/models/deepinfra/deepinfra.py +18 -1
- agno/models/deepseek/deepseek.py +69 -3
- agno/models/fireworks/fireworks.py +18 -1
- agno/models/google/gemini.py +959 -89
- agno/models/google/utils.py +22 -0
- agno/models/groq/groq.py +48 -18
- agno/models/huggingface/huggingface.py +17 -6
- agno/models/ibm/watsonx.py +16 -6
- agno/models/internlm/internlm.py +18 -1
- agno/models/langdb/langdb.py +13 -1
- agno/models/litellm/chat.py +88 -9
- agno/models/litellm/litellm_openai.py +18 -1
- agno/models/message.py +24 -5
- agno/models/meta/llama.py +40 -13
- agno/models/meta/llama_openai.py +22 -21
- agno/models/metrics.py +12 -0
- agno/models/mistral/mistral.py +8 -4
- agno/models/n1n/__init__.py +3 -0
- agno/models/n1n/n1n.py +57 -0
- agno/models/nebius/nebius.py +6 -7
- agno/models/nvidia/nvidia.py +20 -3
- agno/models/ollama/__init__.py +2 -0
- agno/models/ollama/chat.py +17 -6
- agno/models/ollama/responses.py +100 -0
- agno/models/openai/__init__.py +2 -0
- agno/models/openai/chat.py +117 -26
- agno/models/openai/open_responses.py +46 -0
- agno/models/openai/responses.py +110 -32
- agno/models/openrouter/__init__.py +2 -0
- agno/models/openrouter/openrouter.py +67 -2
- agno/models/openrouter/responses.py +146 -0
- agno/models/perplexity/perplexity.py +19 -1
- agno/models/portkey/portkey.py +7 -6
- agno/models/requesty/requesty.py +19 -2
- agno/models/response.py +20 -2
- agno/models/sambanova/sambanova.py +20 -3
- agno/models/siliconflow/siliconflow.py +19 -2
- agno/models/together/together.py +20 -3
- agno/models/vercel/v0.py +20 -3
- agno/models/vertexai/claude.py +124 -4
- agno/models/vllm/vllm.py +19 -14
- agno/models/xai/xai.py +19 -2
- agno/os/app.py +467 -137
- agno/os/auth.py +253 -5
- agno/os/config.py +22 -0
- agno/os/interfaces/a2a/a2a.py +7 -6
- agno/os/interfaces/a2a/router.py +635 -26
- agno/os/interfaces/a2a/utils.py +32 -33
- agno/os/interfaces/agui/agui.py +5 -3
- agno/os/interfaces/agui/router.py +26 -16
- agno/os/interfaces/agui/utils.py +97 -57
- agno/os/interfaces/base.py +7 -7
- agno/os/interfaces/slack/router.py +16 -7
- agno/os/interfaces/slack/slack.py +7 -7
- agno/os/interfaces/whatsapp/router.py +35 -7
- agno/os/interfaces/whatsapp/security.py +3 -1
- agno/os/interfaces/whatsapp/whatsapp.py +11 -8
- agno/os/managers.py +326 -0
- agno/os/mcp.py +652 -79
- agno/os/middleware/__init__.py +4 -0
- agno/os/middleware/jwt.py +718 -115
- agno/os/middleware/trailing_slash.py +27 -0
- agno/os/router.py +105 -1558
- agno/os/routers/agents/__init__.py +3 -0
- agno/os/routers/agents/router.py +655 -0
- agno/os/routers/agents/schema.py +288 -0
- agno/os/routers/components/__init__.py +3 -0
- agno/os/routers/components/components.py +475 -0
- agno/os/routers/database.py +155 -0
- agno/os/routers/evals/evals.py +111 -18
- agno/os/routers/evals/schemas.py +38 -5
- agno/os/routers/evals/utils.py +80 -11
- agno/os/routers/health.py +3 -3
- agno/os/routers/knowledge/knowledge.py +284 -35
- agno/os/routers/knowledge/schemas.py +14 -2
- agno/os/routers/memory/memory.py +274 -11
- agno/os/routers/memory/schemas.py +44 -3
- agno/os/routers/metrics/metrics.py +30 -15
- agno/os/routers/metrics/schemas.py +10 -6
- agno/os/routers/registry/__init__.py +3 -0
- agno/os/routers/registry/registry.py +337 -0
- agno/os/routers/session/session.py +143 -14
- agno/os/routers/teams/__init__.py +3 -0
- agno/os/routers/teams/router.py +550 -0
- agno/os/routers/teams/schema.py +280 -0
- agno/os/routers/traces/__init__.py +3 -0
- agno/os/routers/traces/schemas.py +414 -0
- agno/os/routers/traces/traces.py +549 -0
- agno/os/routers/workflows/__init__.py +3 -0
- agno/os/routers/workflows/router.py +757 -0
- agno/os/routers/workflows/schema.py +139 -0
- agno/os/schema.py +157 -584
- agno/os/scopes.py +469 -0
- agno/os/settings.py +3 -0
- agno/os/utils.py +574 -185
- agno/reasoning/anthropic.py +85 -1
- agno/reasoning/azure_ai_foundry.py +93 -1
- agno/reasoning/deepseek.py +102 -2
- agno/reasoning/default.py +6 -7
- agno/reasoning/gemini.py +87 -3
- agno/reasoning/groq.py +109 -2
- agno/reasoning/helpers.py +6 -7
- agno/reasoning/manager.py +1238 -0
- agno/reasoning/ollama.py +93 -1
- agno/reasoning/openai.py +115 -1
- agno/reasoning/vertexai.py +85 -1
- agno/registry/__init__.py +3 -0
- agno/registry/registry.py +68 -0
- agno/remote/__init__.py +3 -0
- agno/remote/base.py +581 -0
- agno/run/__init__.py +2 -4
- agno/run/agent.py +134 -19
- agno/run/base.py +49 -1
- agno/run/cancel.py +65 -52
- agno/run/cancellation_management/__init__.py +9 -0
- agno/run/cancellation_management/base.py +78 -0
- agno/run/cancellation_management/in_memory_cancellation_manager.py +100 -0
- agno/run/cancellation_management/redis_cancellation_manager.py +236 -0
- agno/run/requirement.py +181 -0
- agno/run/team.py +111 -19
- agno/run/workflow.py +2 -1
- agno/session/agent.py +57 -92
- agno/session/summary.py +1 -1
- agno/session/team.py +62 -115
- agno/session/workflow.py +353 -57
- agno/skills/__init__.py +17 -0
- agno/skills/agent_skills.py +377 -0
- agno/skills/errors.py +32 -0
- agno/skills/loaders/__init__.py +4 -0
- agno/skills/loaders/base.py +27 -0
- agno/skills/loaders/local.py +216 -0
- agno/skills/skill.py +65 -0
- agno/skills/utils.py +107 -0
- agno/skills/validator.py +277 -0
- agno/table.py +10 -0
- agno/team/__init__.py +5 -1
- agno/team/remote.py +447 -0
- agno/team/team.py +3769 -2202
- agno/tools/brandfetch.py +27 -18
- agno/tools/browserbase.py +225 -16
- agno/tools/crawl4ai.py +3 -0
- agno/tools/duckduckgo.py +25 -71
- agno/tools/exa.py +0 -21
- agno/tools/file.py +14 -13
- agno/tools/file_generation.py +12 -6
- agno/tools/firecrawl.py +15 -7
- agno/tools/function.py +94 -113
- agno/tools/google_bigquery.py +11 -2
- agno/tools/google_drive.py +4 -3
- agno/tools/knowledge.py +9 -4
- agno/tools/mcp/mcp.py +301 -18
- agno/tools/mcp/multi_mcp.py +269 -14
- agno/tools/mem0.py +11 -10
- agno/tools/memory.py +47 -46
- agno/tools/mlx_transcribe.py +10 -7
- agno/tools/models/nebius.py +5 -5
- agno/tools/models_labs.py +20 -10
- agno/tools/nano_banana.py +151 -0
- agno/tools/parallel.py +0 -7
- agno/tools/postgres.py +76 -36
- agno/tools/python.py +14 -6
- agno/tools/reasoning.py +30 -23
- agno/tools/redshift.py +406 -0
- agno/tools/shopify.py +1519 -0
- agno/tools/spotify.py +919 -0
- agno/tools/tavily.py +4 -1
- agno/tools/toolkit.py +253 -18
- agno/tools/websearch.py +93 -0
- agno/tools/website.py +1 -1
- agno/tools/wikipedia.py +1 -1
- agno/tools/workflow.py +56 -48
- agno/tools/yfinance.py +12 -11
- agno/tracing/__init__.py +12 -0
- agno/tracing/exporter.py +161 -0
- agno/tracing/schemas.py +276 -0
- agno/tracing/setup.py +112 -0
- agno/utils/agent.py +251 -10
- agno/utils/cryptography.py +22 -0
- agno/utils/dttm.py +33 -0
- agno/utils/events.py +264 -7
- agno/utils/hooks.py +111 -3
- agno/utils/http.py +161 -2
- agno/utils/mcp.py +49 -8
- agno/utils/media.py +22 -1
- agno/utils/models/ai_foundry.py +9 -2
- agno/utils/models/claude.py +20 -5
- agno/utils/models/cohere.py +9 -2
- agno/utils/models/llama.py +9 -2
- agno/utils/models/mistral.py +4 -2
- agno/utils/os.py +0 -0
- agno/utils/print_response/agent.py +99 -16
- agno/utils/print_response/team.py +223 -24
- agno/utils/print_response/workflow.py +0 -2
- agno/utils/prompts.py +8 -6
- agno/utils/remote.py +23 -0
- agno/utils/response.py +1 -13
- agno/utils/string.py +91 -2
- agno/utils/team.py +62 -12
- agno/utils/tokens.py +657 -0
- agno/vectordb/base.py +15 -2
- agno/vectordb/cassandra/cassandra.py +1 -1
- agno/vectordb/chroma/__init__.py +2 -1
- agno/vectordb/chroma/chromadb.py +468 -23
- agno/vectordb/clickhouse/clickhousedb.py +1 -1
- agno/vectordb/couchbase/couchbase.py +6 -2
- agno/vectordb/lancedb/lance_db.py +7 -38
- agno/vectordb/lightrag/lightrag.py +7 -6
- agno/vectordb/milvus/milvus.py +118 -84
- agno/vectordb/mongodb/__init__.py +2 -1
- agno/vectordb/mongodb/mongodb.py +14 -31
- agno/vectordb/pgvector/pgvector.py +120 -66
- agno/vectordb/pineconedb/pineconedb.py +2 -19
- agno/vectordb/qdrant/__init__.py +2 -1
- agno/vectordb/qdrant/qdrant.py +33 -56
- agno/vectordb/redis/__init__.py +2 -1
- agno/vectordb/redis/redisdb.py +19 -31
- agno/vectordb/singlestore/singlestore.py +17 -9
- agno/vectordb/surrealdb/surrealdb.py +2 -38
- agno/vectordb/weaviate/__init__.py +2 -1
- agno/vectordb/weaviate/weaviate.py +7 -3
- agno/workflow/__init__.py +5 -1
- agno/workflow/agent.py +2 -2
- agno/workflow/condition.py +12 -10
- agno/workflow/loop.py +28 -9
- agno/workflow/parallel.py +21 -13
- agno/workflow/remote.py +362 -0
- agno/workflow/router.py +12 -9
- agno/workflow/step.py +261 -36
- agno/workflow/steps.py +12 -8
- agno/workflow/types.py +40 -77
- agno/workflow/workflow.py +939 -213
- {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/METADATA +134 -181
- agno-2.4.3.dist-info/RECORD +677 -0
- {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/WHEEL +1 -1
- agno/tools/googlesearch.py +0 -98
- agno/tools/memori.py +0 -339
- agno-2.2.13.dist-info/RECORD +0 -575
- {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/licenses/LICENSE +0 -0
- {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/top_level.txt +0 -0
|
@@ -260,39 +260,6 @@ class LanceDb(VectorDb):
|
|
|
260
260
|
tbl = self.connection.create_table(name=self.table_name, schema=schema, mode="overwrite", exist_ok=True) # type: ignore
|
|
261
261
|
return tbl # type: ignore
|
|
262
262
|
|
|
263
|
-
def doc_exists(self, document: Document) -> bool:
|
|
264
|
-
"""
|
|
265
|
-
Validating if the document exists or not
|
|
266
|
-
|
|
267
|
-
Args:
|
|
268
|
-
document (Document): Document to validate
|
|
269
|
-
"""
|
|
270
|
-
try:
|
|
271
|
-
if self.table is not None:
|
|
272
|
-
cleaned_content = document.content.replace("\x00", "\ufffd")
|
|
273
|
-
doc_id = md5(cleaned_content.encode()).hexdigest()
|
|
274
|
-
result = self.table.search().where(f"{self._id}='{doc_id}'").to_arrow()
|
|
275
|
-
return len(result) > 0
|
|
276
|
-
except Exception:
|
|
277
|
-
# Search sometimes fails with stale cache data, it means the doc doesn't exist
|
|
278
|
-
return False
|
|
279
|
-
|
|
280
|
-
return False
|
|
281
|
-
|
|
282
|
-
async def async_doc_exists(self, document: Document) -> bool:
|
|
283
|
-
"""
|
|
284
|
-
Asynchronously validate if the document exists
|
|
285
|
-
|
|
286
|
-
Args:
|
|
287
|
-
document (Document): Document to validate
|
|
288
|
-
|
|
289
|
-
Returns:
|
|
290
|
-
bool: True if document exists, False otherwise
|
|
291
|
-
"""
|
|
292
|
-
if self.connection:
|
|
293
|
-
self.table = self.connection.open_table(name=self.table_name)
|
|
294
|
-
return self.doc_exists(document)
|
|
295
|
-
|
|
296
263
|
def insert(self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
|
|
297
264
|
"""
|
|
298
265
|
Insert documents into the database.
|
|
@@ -309,18 +276,20 @@ class LanceDb(VectorDb):
|
|
|
309
276
|
data = []
|
|
310
277
|
|
|
311
278
|
for document in documents:
|
|
312
|
-
if self.doc_exists(document):
|
|
313
|
-
continue
|
|
314
|
-
|
|
315
279
|
# Add filters to document metadata if provided
|
|
316
280
|
if filters:
|
|
317
281
|
meta_data = document.meta_data.copy() if document.meta_data else {}
|
|
318
282
|
meta_data.update(filters)
|
|
319
283
|
document.meta_data = meta_data
|
|
320
284
|
|
|
321
|
-
document
|
|
285
|
+
# Only embed if the document doesn't already have an embedding
|
|
286
|
+
# This prevents duplicate embedding when called from async_insert or async_upsert
|
|
287
|
+
if document.embedding is None:
|
|
288
|
+
document.embed(embedder=self.embedder)
|
|
322
289
|
cleaned_content = document.content.replace("\x00", "\ufffd")
|
|
323
|
-
|
|
290
|
+
# Include content_hash in ID to ensure uniqueness across different content hashes
|
|
291
|
+
base_id = document.id or md5(cleaned_content.encode()).hexdigest()
|
|
292
|
+
doc_id = str(md5(f"{base_id}_{content_hash}".encode()).hexdigest())
|
|
324
293
|
payload = {
|
|
325
294
|
"name": document.name,
|
|
326
295
|
"meta_data": document.meta_data,
|
|
@@ -109,7 +109,7 @@ class LightRag(VectorDb):
|
|
|
109
109
|
async with httpx.AsyncClient(timeout=30.0) as client:
|
|
110
110
|
response = await client.post(
|
|
111
111
|
f"{self.server_url}/query",
|
|
112
|
-
json={"query": query, "mode": "hybrid"},
|
|
112
|
+
json={"query": query, "mode": "hybrid", "include_references": True},
|
|
113
113
|
headers=self._get_headers(),
|
|
114
114
|
)
|
|
115
115
|
|
|
@@ -322,7 +322,7 @@ class LightRag(VectorDb):
|
|
|
322
322
|
async with httpx.AsyncClient(timeout=30.0) as client:
|
|
323
323
|
response = await client.post(
|
|
324
324
|
f"{self.server_url}/query",
|
|
325
|
-
json={"query": query, "mode": "hybrid"},
|
|
325
|
+
json={"query": query, "mode": "hybrid", "include_references": True},
|
|
326
326
|
headers=self._get_headers(),
|
|
327
327
|
)
|
|
328
328
|
|
|
@@ -349,10 +349,11 @@ class LightRag(VectorDb):
|
|
|
349
349
|
# LightRAG server returns a dict with 'response' key, but we expect a list of documents
|
|
350
350
|
# Convert the response to the expected format
|
|
351
351
|
if isinstance(result, dict) and "response" in result:
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
352
|
+
meta_data = {"source": "lightrag", "query": query, "mode": mode}
|
|
353
|
+
# Preserve references from LightRAG response for document citations
|
|
354
|
+
if "references" in result:
|
|
355
|
+
meta_data["references"] = result["references"]
|
|
356
|
+
return [Document(content=result["response"], meta_data=meta_data)]
|
|
356
357
|
elif isinstance(result, list):
|
|
357
358
|
# Convert list items to Document objects
|
|
358
359
|
documents = []
|
agno/vectordb/milvus/milvus.py
CHANGED
|
@@ -89,7 +89,7 @@ class Milvus(VectorDb):
|
|
|
89
89
|
from agno.knowledge.embedder.openai import OpenAIEmbedder
|
|
90
90
|
|
|
91
91
|
embedder = OpenAIEmbedder()
|
|
92
|
-
|
|
92
|
+
log_debug("Embedder not provided, using OpenAIEmbedder as default.")
|
|
93
93
|
self.embedder: Embedder = embedder
|
|
94
94
|
self.dimensions: Optional[int] = self.embedder.dimensions
|
|
95
95
|
|
|
@@ -229,7 +229,9 @@ class Milvus(VectorDb):
|
|
|
229
229
|
"""
|
|
230
230
|
|
|
231
231
|
cleaned_content = document.content.replace("\x00", "\ufffd")
|
|
232
|
-
|
|
232
|
+
# Include content_hash in ID to ensure uniqueness across different content hashes
|
|
233
|
+
base_id = document.id or md5(cleaned_content.encode()).hexdigest()
|
|
234
|
+
doc_id = md5(f"{base_id}_{content_hash}".encode()).hexdigest()
|
|
233
235
|
|
|
234
236
|
# Convert dictionary fields to JSON strings
|
|
235
237
|
meta_data_str = json.dumps(document.meta_data) if document.meta_data else "{}"
|
|
@@ -239,7 +241,7 @@ class Milvus(VectorDb):
|
|
|
239
241
|
"id": doc_id,
|
|
240
242
|
"text": cleaned_content,
|
|
241
243
|
"name": document.name,
|
|
242
|
-
"content_id": document.content_id,
|
|
244
|
+
"content_id": document.content_id or "",
|
|
243
245
|
"meta_data": meta_data_str,
|
|
244
246
|
"content": cleaned_content,
|
|
245
247
|
"usage": usage_str,
|
|
@@ -317,36 +319,6 @@ class Milvus(VectorDb):
|
|
|
317
319
|
max_length=65_535,
|
|
318
320
|
)
|
|
319
321
|
|
|
320
|
-
def doc_exists(self, document: Document) -> bool:
|
|
321
|
-
"""
|
|
322
|
-
Validating if the document exists or not
|
|
323
|
-
|
|
324
|
-
Args:
|
|
325
|
-
document (Document): Document to validate
|
|
326
|
-
"""
|
|
327
|
-
if self.client:
|
|
328
|
-
cleaned_content = document.content.replace("\x00", "\ufffd")
|
|
329
|
-
doc_id = md5(cleaned_content.encode()).hexdigest()
|
|
330
|
-
collection_points = self.client.get(
|
|
331
|
-
collection_name=self.collection,
|
|
332
|
-
ids=[doc_id],
|
|
333
|
-
)
|
|
334
|
-
return len(collection_points) > 0
|
|
335
|
-
return False
|
|
336
|
-
|
|
337
|
-
async def async_doc_exists(self, document: Document) -> bool:
|
|
338
|
-
"""
|
|
339
|
-
Check if document exists asynchronously.
|
|
340
|
-
AsyncMilvusClient supports get().
|
|
341
|
-
"""
|
|
342
|
-
cleaned_content = document.content.replace("\x00", "\ufffd")
|
|
343
|
-
doc_id = md5(cleaned_content.encode()).hexdigest()
|
|
344
|
-
collection_points = await self.async_client.get(
|
|
345
|
-
collection_name=self.collection,
|
|
346
|
-
ids=[doc_id],
|
|
347
|
-
)
|
|
348
|
-
return len(collection_points) > 0
|
|
349
|
-
|
|
350
322
|
def name_exists(self, name: str) -> bool:
|
|
351
323
|
"""
|
|
352
324
|
Validates if a document with the given name exists in the collection.
|
|
@@ -362,6 +334,7 @@ class Milvus(VectorDb):
|
|
|
362
334
|
scroll_result = self.client.query(
|
|
363
335
|
collection_name=self.collection,
|
|
364
336
|
filter=expr,
|
|
337
|
+
output_fields=["id"],
|
|
365
338
|
limit=1,
|
|
366
339
|
)
|
|
367
340
|
return len(scroll_result) > 0 and len(scroll_result[0]) > 0
|
|
@@ -391,6 +364,7 @@ class Milvus(VectorDb):
|
|
|
391
364
|
scroll_result = self.client.query(
|
|
392
365
|
collection_name=self.collection,
|
|
393
366
|
filter=expr,
|
|
367
|
+
output_fields=["id"],
|
|
394
368
|
limit=1,
|
|
395
369
|
)
|
|
396
370
|
return len(scroll_result) > 0 and len(scroll_result[0]) > 0
|
|
@@ -457,7 +431,7 @@ class Milvus(VectorDb):
|
|
|
457
431
|
"id": doc_id,
|
|
458
432
|
"vector": document.embedding,
|
|
459
433
|
"name": document.name,
|
|
460
|
-
"content_id": document.content_id,
|
|
434
|
+
"content_id": document.content_id or "",
|
|
461
435
|
"meta_data": meta_data,
|
|
462
436
|
"content": cleaned_content,
|
|
463
437
|
"usage": document.usage,
|
|
@@ -528,7 +502,9 @@ class Milvus(VectorDb):
|
|
|
528
502
|
log_debug(f"Skipping document without embedding: {document.name} ({document.meta_data})")
|
|
529
503
|
return None
|
|
530
504
|
cleaned_content = document.content.replace("\x00", "\ufffd")
|
|
531
|
-
|
|
505
|
+
# Include content_hash in ID to ensure uniqueness across different content hashes
|
|
506
|
+
base_id = document.id or md5(cleaned_content.encode()).hexdigest()
|
|
507
|
+
doc_id = md5(f"{base_id}_{content_hash}".encode()).hexdigest()
|
|
532
508
|
|
|
533
509
|
meta_data = document.meta_data or {}
|
|
534
510
|
if filters:
|
|
@@ -538,7 +514,7 @@ class Milvus(VectorDb):
|
|
|
538
514
|
"id": doc_id,
|
|
539
515
|
"vector": document.embedding,
|
|
540
516
|
"name": document.name,
|
|
541
|
-
"content_id": document.content_id,
|
|
517
|
+
"content_id": document.content_id or "",
|
|
542
518
|
"meta_data": meta_data,
|
|
543
519
|
"content": cleaned_content,
|
|
544
520
|
"usage": document.usage,
|
|
@@ -573,30 +549,41 @@ class Milvus(VectorDb):
|
|
|
573
549
|
filters (Optional[Dict[str, Any]]): Filters to apply while upserting
|
|
574
550
|
"""
|
|
575
551
|
log_debug(f"Upserting {len(documents)} documents")
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
552
|
+
|
|
553
|
+
if self.search_type == SearchType.hybrid:
|
|
554
|
+
for document in documents:
|
|
555
|
+
document.embed(embedder=self.embedder)
|
|
556
|
+
data = self._prepare_document_data(content_hash=content_hash, document=document, include_vectors=True)
|
|
557
|
+
self.client.upsert(
|
|
558
|
+
collection_name=self.collection,
|
|
559
|
+
data=data,
|
|
560
|
+
)
|
|
561
|
+
log_debug(f"Upserted hybrid document: {document.name} ({document.meta_data})")
|
|
562
|
+
else:
|
|
563
|
+
for document in documents:
|
|
564
|
+
document.embed(embedder=self.embedder)
|
|
565
|
+
cleaned_content = document.content.replace("\x00", "\ufffd")
|
|
566
|
+
doc_id = md5(cleaned_content.encode()).hexdigest()
|
|
567
|
+
|
|
568
|
+
meta_data = document.meta_data or {}
|
|
569
|
+
if filters:
|
|
570
|
+
meta_data.update(filters)
|
|
571
|
+
|
|
572
|
+
data = {
|
|
573
|
+
"id": doc_id,
|
|
574
|
+
"vector": document.embedding,
|
|
575
|
+
"name": document.name,
|
|
576
|
+
"content_id": document.content_id or "",
|
|
577
|
+
"meta_data": meta_data, # type: ignore[dict-item]
|
|
578
|
+
"content": cleaned_content,
|
|
579
|
+
"usage": document.usage, # type: ignore[dict-item]
|
|
580
|
+
"content_hash": content_hash,
|
|
581
|
+
}
|
|
582
|
+
self.client.upsert(
|
|
583
|
+
collection_name=self.collection,
|
|
584
|
+
data=data,
|
|
585
|
+
)
|
|
586
|
+
log_debug(f"Upserted document: {document.name} ({document.meta_data})")
|
|
600
587
|
|
|
601
588
|
async def async_upsert(
|
|
602
589
|
self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
|
|
@@ -642,28 +629,46 @@ class Milvus(VectorDb):
|
|
|
642
629
|
embed_tasks = [document.async_embed(embedder=self.embedder) for document in documents]
|
|
643
630
|
await asyncio.gather(*embed_tasks, return_exceptions=True)
|
|
644
631
|
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
"
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
632
|
+
if self.search_type == SearchType.hybrid:
|
|
633
|
+
|
|
634
|
+
async def process_hybrid_document(document):
|
|
635
|
+
data = self._prepare_document_data(content_hash=content_hash, document=document, include_vectors=True)
|
|
636
|
+
await self.async_client.upsert(
|
|
637
|
+
collection_name=self.collection,
|
|
638
|
+
data=data,
|
|
639
|
+
)
|
|
640
|
+
log_debug(f"Upserted hybrid document asynchronously: {document.name} ({document.meta_data})")
|
|
641
|
+
return data
|
|
642
|
+
|
|
643
|
+
await asyncio.gather(*[process_hybrid_document(doc) for doc in documents])
|
|
644
|
+
else:
|
|
645
|
+
|
|
646
|
+
async def process_document(document):
|
|
647
|
+
cleaned_content = document.content.replace("\x00", "\ufffd")
|
|
648
|
+
doc_id = md5(cleaned_content.encode()).hexdigest()
|
|
649
|
+
|
|
650
|
+
meta_data = document.meta_data or {}
|
|
651
|
+
if filters:
|
|
652
|
+
meta_data.update(filters)
|
|
653
|
+
|
|
654
|
+
data = {
|
|
655
|
+
"id": doc_id,
|
|
656
|
+
"vector": document.embedding,
|
|
657
|
+
"name": document.name,
|
|
658
|
+
"content_id": document.content_id or "",
|
|
659
|
+
"meta_data": meta_data, # type: ignore[dict-item]
|
|
660
|
+
"content": cleaned_content,
|
|
661
|
+
"usage": document.usage, # type: ignore[dict-item]
|
|
662
|
+
"content_hash": content_hash,
|
|
663
|
+
}
|
|
664
|
+
await self.async_client.upsert(
|
|
665
|
+
collection_name=self.collection,
|
|
666
|
+
data=data,
|
|
667
|
+
)
|
|
668
|
+
log_debug(f"Upserted document asynchronously: {document.name} ({document.meta_data})")
|
|
669
|
+
return data
|
|
664
670
|
|
|
665
|
-
|
|
666
|
-
await asyncio.gather(*[process_document(doc) for doc in documents])
|
|
671
|
+
await asyncio.gather(*[process_document(doc) for doc in documents])
|
|
667
672
|
|
|
668
673
|
log_debug(f"Upserted {len(documents)} documents asynchronously in parallel")
|
|
669
674
|
|
|
@@ -677,7 +682,11 @@ class Milvus(VectorDb):
|
|
|
677
682
|
return MILVUS_DISTANCE_MAP.get(self.distance, "COSINE")
|
|
678
683
|
|
|
679
684
|
def search(
|
|
680
|
-
self,
|
|
685
|
+
self,
|
|
686
|
+
query: str,
|
|
687
|
+
limit: int = 5,
|
|
688
|
+
filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
|
|
689
|
+
search_params: Optional[Dict[str, Any]] = None,
|
|
681
690
|
) -> List[Document]:
|
|
682
691
|
"""
|
|
683
692
|
Search for documents matching the query.
|
|
@@ -686,6 +695,10 @@ class Milvus(VectorDb):
|
|
|
686
695
|
query (str): Query string to search for
|
|
687
696
|
limit (int): Maximum number of results to return
|
|
688
697
|
filters (Optional[Dict[str, Any]]): Filters to apply to the search
|
|
698
|
+
search_params (Optional[Dict[str, Any]]): Milvus search parameters including:
|
|
699
|
+
- radius (float): Minimum similarity threshold for range search
|
|
700
|
+
- range_filter (float): Maximum similarity threshold for range search
|
|
701
|
+
- params (dict): Index-specific search params (e.g., nprobe, ef)
|
|
689
702
|
|
|
690
703
|
Returns:
|
|
691
704
|
List[Document]: List of matching documents
|
|
@@ -707,6 +720,7 @@ class Milvus(VectorDb):
|
|
|
707
720
|
filter=self._build_expr(filters),
|
|
708
721
|
output_fields=["*"],
|
|
709
722
|
limit=limit,
|
|
723
|
+
search_params=search_params,
|
|
710
724
|
)
|
|
711
725
|
|
|
712
726
|
# Build search results
|
|
@@ -734,8 +748,27 @@ class Milvus(VectorDb):
|
|
|
734
748
|
return search_results
|
|
735
749
|
|
|
736
750
|
async def async_search(
|
|
737
|
-
self,
|
|
751
|
+
self,
|
|
752
|
+
query: str,
|
|
753
|
+
limit: int = 5,
|
|
754
|
+
filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
|
|
755
|
+
search_params: Optional[Dict[str, Any]] = None,
|
|
738
756
|
) -> List[Document]:
|
|
757
|
+
"""
|
|
758
|
+
Asynchronously search for documents matching the query.
|
|
759
|
+
|
|
760
|
+
Args:
|
|
761
|
+
query (str): Query string to search for
|
|
762
|
+
limit (int): Maximum number of results to return
|
|
763
|
+
filters (Optional[Dict[str, Any]]): Filters to apply to the search
|
|
764
|
+
search_params (Optional[Dict[str, Any]]): Milvus search parameters including:
|
|
765
|
+
- radius (float): Minimum similarity threshold for range search
|
|
766
|
+
- range_filter (float): Maximum similarity threshold for range search
|
|
767
|
+
- params (dict): Index-specific search params (e.g., nprobe, ef)
|
|
768
|
+
|
|
769
|
+
Returns:
|
|
770
|
+
List[Document]: List of matching documents
|
|
771
|
+
"""
|
|
739
772
|
if isinstance(filters, List):
|
|
740
773
|
log_warning("Filters Expressions are not supported in Milvus. No filters will be applied.")
|
|
741
774
|
filters = None
|
|
@@ -753,6 +786,7 @@ class Milvus(VectorDb):
|
|
|
753
786
|
filter=self._build_expr(filters),
|
|
754
787
|
output_fields=["*"],
|
|
755
788
|
limit=limit,
|
|
789
|
+
search_params=search_params,
|
|
756
790
|
)
|
|
757
791
|
|
|
758
792
|
# Build search results
|
|
@@ -1099,7 +1133,7 @@ class Milvus(VectorDb):
|
|
|
1099
1133
|
if isinstance(v, (list, tuple)):
|
|
1100
1134
|
# For array values, use json_contains_any
|
|
1101
1135
|
values_str = json.dumps(v)
|
|
1102
|
-
expr = f'json_contains_any(meta_data
|
|
1136
|
+
expr = f'json_contains_any(meta_data["{k}"], {values_str})'
|
|
1103
1137
|
elif isinstance(v, str):
|
|
1104
1138
|
# For string values
|
|
1105
1139
|
expr = f'meta_data["{k}"] == "{v}"'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from agno.vectordb.mongodb.mongodb import MongoDb
|
|
1
|
+
from agno.vectordb.mongodb.mongodb import MongoDb, SearchType
|
|
2
2
|
|
|
3
3
|
# Alias to avoid name collision with the main MongoDb class
|
|
4
4
|
MongoVectorDb = MongoDb
|
|
@@ -6,4 +6,5 @@ MongoVectorDb = MongoDb
|
|
|
6
6
|
__all__ = [
|
|
7
7
|
"MongoVectorDb",
|
|
8
8
|
"MongoDb",
|
|
9
|
+
"SearchType",
|
|
9
10
|
]
|
agno/vectordb/mongodb/mongodb.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import time
|
|
3
|
+
from importlib import metadata
|
|
3
4
|
from typing import Any, Dict, List, Optional, Union
|
|
4
5
|
|
|
5
6
|
from bson import ObjectId
|
|
@@ -20,11 +21,14 @@ except ImportError:
|
|
|
20
21
|
try:
|
|
21
22
|
from pymongo import AsyncMongoClient, MongoClient, errors
|
|
22
23
|
from pymongo.collection import Collection
|
|
24
|
+
from pymongo.driver_info import DriverInfo
|
|
23
25
|
from pymongo.operations import SearchIndexModel
|
|
24
26
|
|
|
25
27
|
except ImportError:
|
|
26
28
|
raise ImportError("`pymongo` not installed. Please install using `pip install pymongo`")
|
|
27
29
|
|
|
30
|
+
DRIVER_METADATA = DriverInfo(name="Agno", version=metadata.version("agno"))
|
|
31
|
+
|
|
28
32
|
|
|
29
33
|
class MongoDb(VectorDb):
|
|
30
34
|
"""
|
|
@@ -110,7 +114,7 @@ class MongoDb(VectorDb):
|
|
|
110
114
|
from agno.knowledge.embedder.openai import OpenAIEmbedder
|
|
111
115
|
|
|
112
116
|
embedder = OpenAIEmbedder()
|
|
113
|
-
|
|
117
|
+
log_debug("Embedder not provided, using OpenAIEmbedder as default.")
|
|
114
118
|
self.embedder = embedder
|
|
115
119
|
|
|
116
120
|
self.distance_metric = distance_metric
|
|
@@ -135,6 +139,11 @@ class MongoDb(VectorDb):
|
|
|
135
139
|
self._async_db = None
|
|
136
140
|
self._async_collection: Optional[Collection] = None
|
|
137
141
|
|
|
142
|
+
if self._client is not None:
|
|
143
|
+
# append_metadata was added in PyMongo 4.14.0, but is a valid database name on earlier versions
|
|
144
|
+
if callable(self._client.append_metadata):
|
|
145
|
+
self._client.append_metadata(DRIVER_METADATA)
|
|
146
|
+
|
|
138
147
|
def _get_client(self) -> MongoClient:
|
|
139
148
|
"""Create or retrieve the MongoDB client."""
|
|
140
149
|
if self._client is None:
|
|
@@ -157,7 +166,7 @@ class MongoDb(VectorDb):
|
|
|
157
166
|
warnings.filterwarnings(
|
|
158
167
|
"ignore", category=UserWarning, message=".*connected to a CosmosDB cluster.*"
|
|
159
168
|
)
|
|
160
|
-
self._client = MongoClient(self.connection_string, **cosmos_kwargs) # type: ignore
|
|
169
|
+
self._client = MongoClient(self.connection_string, **cosmos_kwargs, driver=DRIVER_METADATA) # type: ignore
|
|
161
170
|
|
|
162
171
|
self._client.admin.command("ping")
|
|
163
172
|
|
|
@@ -173,7 +182,7 @@ class MongoDb(VectorDb):
|
|
|
173
182
|
else:
|
|
174
183
|
try:
|
|
175
184
|
log_debug("Creating MongoDB Client")
|
|
176
|
-
self._client = MongoClient(self.connection_string, **self.kwargs)
|
|
185
|
+
self._client = MongoClient(self.connection_string, **self.kwargs, driver=DRIVER_METADATA) # type: ignore
|
|
177
186
|
# Trigger a connection to verify the client
|
|
178
187
|
self._client.admin.command("ping")
|
|
179
188
|
log_info("Connected to MongoDB successfully.")
|
|
@@ -195,6 +204,7 @@ class MongoDb(VectorDb):
|
|
|
195
204
|
maxPoolSize=self.kwargs.get("maxPoolSize", 100),
|
|
196
205
|
retryWrites=self.kwargs.get("retryWrites", True),
|
|
197
206
|
serverSelectionTimeoutMS=5000,
|
|
207
|
+
driver=DRIVER_METADATA,
|
|
198
208
|
)
|
|
199
209
|
# Verify connection
|
|
200
210
|
try:
|
|
@@ -471,20 +481,6 @@ class MongoDb(VectorDb):
|
|
|
471
481
|
if self.wait_until_index_ready_in_seconds:
|
|
472
482
|
await self._wait_for_index_ready_async()
|
|
473
483
|
|
|
474
|
-
def doc_exists(self, document: Document) -> bool:
|
|
475
|
-
"""Check if a document exists in the MongoDB collection based on its content."""
|
|
476
|
-
try:
|
|
477
|
-
collection = self._get_collection()
|
|
478
|
-
# Use content hash as document ID
|
|
479
|
-
doc_id = md5(document.content.encode("utf-8")).hexdigest()
|
|
480
|
-
result = collection.find_one({"_id": doc_id})
|
|
481
|
-
exists = result is not None
|
|
482
|
-
log_debug(f"Document {'exists' if exists else 'does not exist'}: {doc_id}")
|
|
483
|
-
return exists
|
|
484
|
-
except Exception as e:
|
|
485
|
-
logger.error(f"Error checking document existence: {e}")
|
|
486
|
-
return False
|
|
487
|
-
|
|
488
484
|
def name_exists(self, name: str) -> bool:
|
|
489
485
|
"""Check if a document with a given name exists in the collection."""
|
|
490
486
|
try:
|
|
@@ -1024,19 +1020,6 @@ class MongoDb(VectorDb):
|
|
|
1024
1020
|
logger.error(f"Error getting document count: {e}")
|
|
1025
1021
|
return 0
|
|
1026
1022
|
|
|
1027
|
-
async def async_doc_exists(self, document: Document) -> bool:
|
|
1028
|
-
"""Check if a document exists asynchronously."""
|
|
1029
|
-
try:
|
|
1030
|
-
collection = await self._get_async_collection()
|
|
1031
|
-
doc_id = md5(document.content.encode("utf-8")).hexdigest()
|
|
1032
|
-
result = await collection.find_one({"_id": doc_id})
|
|
1033
|
-
exists = result is not None
|
|
1034
|
-
log_debug(f"Document {'exists' if exists else 'does not exist'}: {doc_id}")
|
|
1035
|
-
return exists
|
|
1036
|
-
except Exception as e:
|
|
1037
|
-
logger.error(f"Error checking document existence asynchronously: {e}")
|
|
1038
|
-
return False
|
|
1039
|
-
|
|
1040
1023
|
async def async_insert(
|
|
1041
1024
|
self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
|
|
1042
1025
|
) -> None:
|
|
@@ -1167,7 +1150,7 @@ class MongoDb(VectorDb):
|
|
|
1167
1150
|
if isinstance(filters, List):
|
|
1168
1151
|
log_warning("Filters Expressions are not supported in MongoDB. No filters will be applied.")
|
|
1169
1152
|
filters = None
|
|
1170
|
-
query_embedding = self.embedder.
|
|
1153
|
+
query_embedding = await self.embedder.async_get_embedding(query)
|
|
1171
1154
|
if query_embedding is None:
|
|
1172
1155
|
logger.error(f"Failed to generate embedding for query: {query}")
|
|
1173
1156
|
return []
|