PraisonAI 3.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.
- praisonai/__init__.py +54 -0
- praisonai/__main__.py +15 -0
- praisonai/acp/__init__.py +54 -0
- praisonai/acp/config.py +159 -0
- praisonai/acp/server.py +587 -0
- praisonai/acp/session.py +219 -0
- praisonai/adapters/__init__.py +50 -0
- praisonai/adapters/readers.py +395 -0
- praisonai/adapters/rerankers.py +315 -0
- praisonai/adapters/retrievers.py +394 -0
- praisonai/adapters/vector_stores.py +409 -0
- praisonai/agent_scheduler.py +337 -0
- praisonai/agents_generator.py +903 -0
- praisonai/api/call.py +292 -0
- praisonai/auto.py +1197 -0
- praisonai/capabilities/__init__.py +275 -0
- praisonai/capabilities/a2a.py +140 -0
- praisonai/capabilities/assistants.py +283 -0
- praisonai/capabilities/audio.py +320 -0
- praisonai/capabilities/batches.py +469 -0
- praisonai/capabilities/completions.py +336 -0
- praisonai/capabilities/container_files.py +155 -0
- praisonai/capabilities/containers.py +93 -0
- praisonai/capabilities/embeddings.py +158 -0
- praisonai/capabilities/files.py +467 -0
- praisonai/capabilities/fine_tuning.py +293 -0
- praisonai/capabilities/guardrails.py +182 -0
- praisonai/capabilities/images.py +330 -0
- praisonai/capabilities/mcp.py +190 -0
- praisonai/capabilities/messages.py +270 -0
- praisonai/capabilities/moderations.py +154 -0
- praisonai/capabilities/ocr.py +217 -0
- praisonai/capabilities/passthrough.py +204 -0
- praisonai/capabilities/rag.py +207 -0
- praisonai/capabilities/realtime.py +160 -0
- praisonai/capabilities/rerank.py +165 -0
- praisonai/capabilities/responses.py +266 -0
- praisonai/capabilities/search.py +109 -0
- praisonai/capabilities/skills.py +133 -0
- praisonai/capabilities/vector_store_files.py +334 -0
- praisonai/capabilities/vector_stores.py +304 -0
- praisonai/capabilities/videos.py +141 -0
- praisonai/chainlit_ui.py +304 -0
- praisonai/chat/__init__.py +106 -0
- praisonai/chat/app.py +125 -0
- praisonai/cli/__init__.py +26 -0
- praisonai/cli/app.py +213 -0
- praisonai/cli/commands/__init__.py +75 -0
- praisonai/cli/commands/acp.py +70 -0
- praisonai/cli/commands/completion.py +333 -0
- praisonai/cli/commands/config.py +166 -0
- praisonai/cli/commands/debug.py +142 -0
- praisonai/cli/commands/diag.py +55 -0
- praisonai/cli/commands/doctor.py +166 -0
- praisonai/cli/commands/environment.py +179 -0
- praisonai/cli/commands/lsp.py +112 -0
- praisonai/cli/commands/mcp.py +210 -0
- praisonai/cli/commands/profile.py +457 -0
- praisonai/cli/commands/run.py +228 -0
- praisonai/cli/commands/schedule.py +150 -0
- praisonai/cli/commands/serve.py +97 -0
- praisonai/cli/commands/session.py +212 -0
- praisonai/cli/commands/traces.py +145 -0
- praisonai/cli/commands/version.py +101 -0
- praisonai/cli/configuration/__init__.py +18 -0
- praisonai/cli/configuration/loader.py +353 -0
- praisonai/cli/configuration/paths.py +114 -0
- praisonai/cli/configuration/schema.py +164 -0
- praisonai/cli/features/__init__.py +268 -0
- praisonai/cli/features/acp.py +236 -0
- praisonai/cli/features/action_orchestrator.py +546 -0
- praisonai/cli/features/agent_scheduler.py +773 -0
- praisonai/cli/features/agent_tools.py +474 -0
- praisonai/cli/features/agents.py +375 -0
- praisonai/cli/features/at_mentions.py +471 -0
- praisonai/cli/features/auto_memory.py +182 -0
- praisonai/cli/features/autonomy_mode.py +490 -0
- praisonai/cli/features/background.py +356 -0
- praisonai/cli/features/base.py +168 -0
- praisonai/cli/features/capabilities.py +1326 -0
- praisonai/cli/features/checkpoints.py +338 -0
- praisonai/cli/features/code_intelligence.py +652 -0
- praisonai/cli/features/compaction.py +294 -0
- praisonai/cli/features/compare.py +534 -0
- praisonai/cli/features/cost_tracker.py +514 -0
- praisonai/cli/features/debug.py +810 -0
- praisonai/cli/features/deploy.py +517 -0
- praisonai/cli/features/diag.py +289 -0
- praisonai/cli/features/doctor/__init__.py +63 -0
- praisonai/cli/features/doctor/checks/__init__.py +24 -0
- praisonai/cli/features/doctor/checks/acp_checks.py +240 -0
- praisonai/cli/features/doctor/checks/config_checks.py +366 -0
- praisonai/cli/features/doctor/checks/db_checks.py +366 -0
- praisonai/cli/features/doctor/checks/env_checks.py +543 -0
- praisonai/cli/features/doctor/checks/lsp_checks.py +199 -0
- praisonai/cli/features/doctor/checks/mcp_checks.py +349 -0
- praisonai/cli/features/doctor/checks/memory_checks.py +268 -0
- praisonai/cli/features/doctor/checks/network_checks.py +251 -0
- praisonai/cli/features/doctor/checks/obs_checks.py +328 -0
- praisonai/cli/features/doctor/checks/performance_checks.py +235 -0
- praisonai/cli/features/doctor/checks/permissions_checks.py +259 -0
- praisonai/cli/features/doctor/checks/selftest_checks.py +322 -0
- praisonai/cli/features/doctor/checks/serve_checks.py +426 -0
- praisonai/cli/features/doctor/checks/skills_checks.py +231 -0
- praisonai/cli/features/doctor/checks/tools_checks.py +371 -0
- praisonai/cli/features/doctor/engine.py +266 -0
- praisonai/cli/features/doctor/formatters.py +310 -0
- praisonai/cli/features/doctor/handler.py +397 -0
- praisonai/cli/features/doctor/models.py +264 -0
- praisonai/cli/features/doctor/registry.py +239 -0
- praisonai/cli/features/endpoints.py +1019 -0
- praisonai/cli/features/eval.py +560 -0
- praisonai/cli/features/external_agents.py +231 -0
- praisonai/cli/features/fast_context.py +410 -0
- praisonai/cli/features/flow_display.py +566 -0
- praisonai/cli/features/git_integration.py +651 -0
- praisonai/cli/features/guardrail.py +171 -0
- praisonai/cli/features/handoff.py +185 -0
- praisonai/cli/features/hooks.py +583 -0
- praisonai/cli/features/image.py +384 -0
- praisonai/cli/features/interactive_runtime.py +585 -0
- praisonai/cli/features/interactive_tools.py +380 -0
- praisonai/cli/features/interactive_tui.py +603 -0
- praisonai/cli/features/jobs.py +632 -0
- praisonai/cli/features/knowledge.py +531 -0
- praisonai/cli/features/lite.py +244 -0
- praisonai/cli/features/lsp_cli.py +225 -0
- praisonai/cli/features/mcp.py +169 -0
- praisonai/cli/features/message_queue.py +587 -0
- praisonai/cli/features/metrics.py +211 -0
- praisonai/cli/features/n8n.py +673 -0
- praisonai/cli/features/observability.py +293 -0
- praisonai/cli/features/ollama.py +361 -0
- praisonai/cli/features/output_style.py +273 -0
- praisonai/cli/features/package.py +631 -0
- praisonai/cli/features/performance.py +308 -0
- praisonai/cli/features/persistence.py +636 -0
- praisonai/cli/features/profile.py +226 -0
- praisonai/cli/features/profiler/__init__.py +81 -0
- praisonai/cli/features/profiler/core.py +558 -0
- praisonai/cli/features/profiler/optimizations.py +652 -0
- praisonai/cli/features/profiler/suite.py +386 -0
- praisonai/cli/features/profiling.py +350 -0
- praisonai/cli/features/queue/__init__.py +73 -0
- praisonai/cli/features/queue/manager.py +395 -0
- praisonai/cli/features/queue/models.py +286 -0
- praisonai/cli/features/queue/persistence.py +564 -0
- praisonai/cli/features/queue/scheduler.py +484 -0
- praisonai/cli/features/queue/worker.py +372 -0
- praisonai/cli/features/recipe.py +1723 -0
- praisonai/cli/features/recipes.py +449 -0
- praisonai/cli/features/registry.py +229 -0
- praisonai/cli/features/repo_map.py +860 -0
- praisonai/cli/features/router.py +466 -0
- praisonai/cli/features/sandbox_executor.py +515 -0
- praisonai/cli/features/serve.py +829 -0
- praisonai/cli/features/session.py +222 -0
- praisonai/cli/features/skills.py +856 -0
- praisonai/cli/features/slash_commands.py +650 -0
- praisonai/cli/features/telemetry.py +179 -0
- praisonai/cli/features/templates.py +1384 -0
- praisonai/cli/features/thinking.py +305 -0
- praisonai/cli/features/todo.py +334 -0
- praisonai/cli/features/tools.py +680 -0
- praisonai/cli/features/tui/__init__.py +83 -0
- praisonai/cli/features/tui/app.py +580 -0
- praisonai/cli/features/tui/cli.py +566 -0
- praisonai/cli/features/tui/debug.py +511 -0
- praisonai/cli/features/tui/events.py +99 -0
- praisonai/cli/features/tui/mock_provider.py +328 -0
- praisonai/cli/features/tui/orchestrator.py +652 -0
- praisonai/cli/features/tui/screens/__init__.py +50 -0
- praisonai/cli/features/tui/screens/main.py +245 -0
- praisonai/cli/features/tui/screens/queue.py +174 -0
- praisonai/cli/features/tui/screens/session.py +124 -0
- praisonai/cli/features/tui/screens/settings.py +148 -0
- praisonai/cli/features/tui/widgets/__init__.py +56 -0
- praisonai/cli/features/tui/widgets/chat.py +261 -0
- praisonai/cli/features/tui/widgets/composer.py +224 -0
- praisonai/cli/features/tui/widgets/queue_panel.py +200 -0
- praisonai/cli/features/tui/widgets/status.py +167 -0
- praisonai/cli/features/tui/widgets/tool_panel.py +248 -0
- praisonai/cli/features/workflow.py +720 -0
- praisonai/cli/legacy.py +236 -0
- praisonai/cli/main.py +5559 -0
- praisonai/cli/schedule_cli.py +54 -0
- praisonai/cli/state/__init__.py +31 -0
- praisonai/cli/state/identifiers.py +161 -0
- praisonai/cli/state/sessions.py +313 -0
- praisonai/code/__init__.py +93 -0
- praisonai/code/agent_tools.py +344 -0
- praisonai/code/diff/__init__.py +21 -0
- praisonai/code/diff/diff_strategy.py +432 -0
- praisonai/code/tools/__init__.py +27 -0
- praisonai/code/tools/apply_diff.py +221 -0
- praisonai/code/tools/execute_command.py +275 -0
- praisonai/code/tools/list_files.py +274 -0
- praisonai/code/tools/read_file.py +206 -0
- praisonai/code/tools/search_replace.py +248 -0
- praisonai/code/tools/write_file.py +217 -0
- praisonai/code/utils/__init__.py +46 -0
- praisonai/code/utils/file_utils.py +307 -0
- praisonai/code/utils/ignore_utils.py +308 -0
- praisonai/code/utils/text_utils.py +276 -0
- praisonai/db/__init__.py +64 -0
- praisonai/db/adapter.py +531 -0
- praisonai/deploy/__init__.py +62 -0
- praisonai/deploy/api.py +231 -0
- praisonai/deploy/docker.py +454 -0
- praisonai/deploy/doctor.py +367 -0
- praisonai/deploy/main.py +327 -0
- praisonai/deploy/models.py +179 -0
- praisonai/deploy/providers/__init__.py +33 -0
- praisonai/deploy/providers/aws.py +331 -0
- praisonai/deploy/providers/azure.py +358 -0
- praisonai/deploy/providers/base.py +101 -0
- praisonai/deploy/providers/gcp.py +314 -0
- praisonai/deploy/schema.py +208 -0
- praisonai/deploy.py +185 -0
- praisonai/endpoints/__init__.py +53 -0
- praisonai/endpoints/a2u_server.py +410 -0
- praisonai/endpoints/discovery.py +165 -0
- praisonai/endpoints/providers/__init__.py +28 -0
- praisonai/endpoints/providers/a2a.py +253 -0
- praisonai/endpoints/providers/a2u.py +208 -0
- praisonai/endpoints/providers/agents_api.py +171 -0
- praisonai/endpoints/providers/base.py +231 -0
- praisonai/endpoints/providers/mcp.py +263 -0
- praisonai/endpoints/providers/recipe.py +206 -0
- praisonai/endpoints/providers/tools_mcp.py +150 -0
- praisonai/endpoints/registry.py +131 -0
- praisonai/endpoints/server.py +161 -0
- praisonai/inbuilt_tools/__init__.py +24 -0
- praisonai/inbuilt_tools/autogen_tools.py +117 -0
- praisonai/inc/__init__.py +2 -0
- praisonai/inc/config.py +96 -0
- praisonai/inc/models.py +155 -0
- praisonai/integrations/__init__.py +56 -0
- praisonai/integrations/base.py +303 -0
- praisonai/integrations/claude_code.py +270 -0
- praisonai/integrations/codex_cli.py +255 -0
- praisonai/integrations/cursor_cli.py +195 -0
- praisonai/integrations/gemini_cli.py +222 -0
- praisonai/jobs/__init__.py +67 -0
- praisonai/jobs/executor.py +425 -0
- praisonai/jobs/models.py +230 -0
- praisonai/jobs/router.py +314 -0
- praisonai/jobs/server.py +186 -0
- praisonai/jobs/store.py +203 -0
- praisonai/llm/__init__.py +66 -0
- praisonai/llm/registry.py +382 -0
- praisonai/mcp_server/__init__.py +152 -0
- praisonai/mcp_server/adapters/__init__.py +74 -0
- praisonai/mcp_server/adapters/agents.py +128 -0
- praisonai/mcp_server/adapters/capabilities.py +168 -0
- praisonai/mcp_server/adapters/cli_tools.py +568 -0
- praisonai/mcp_server/adapters/extended_capabilities.py +462 -0
- praisonai/mcp_server/adapters/knowledge.py +93 -0
- praisonai/mcp_server/adapters/memory.py +104 -0
- praisonai/mcp_server/adapters/prompts.py +306 -0
- praisonai/mcp_server/adapters/resources.py +124 -0
- praisonai/mcp_server/adapters/tools_bridge.py +280 -0
- praisonai/mcp_server/auth/__init__.py +48 -0
- praisonai/mcp_server/auth/api_key.py +291 -0
- praisonai/mcp_server/auth/oauth.py +460 -0
- praisonai/mcp_server/auth/oidc.py +289 -0
- praisonai/mcp_server/auth/scopes.py +260 -0
- praisonai/mcp_server/cli.py +852 -0
- praisonai/mcp_server/elicitation.py +445 -0
- praisonai/mcp_server/icons.py +302 -0
- praisonai/mcp_server/recipe_adapter.py +573 -0
- praisonai/mcp_server/recipe_cli.py +824 -0
- praisonai/mcp_server/registry.py +703 -0
- praisonai/mcp_server/sampling.py +422 -0
- praisonai/mcp_server/server.py +490 -0
- praisonai/mcp_server/tasks.py +443 -0
- praisonai/mcp_server/transports/__init__.py +18 -0
- praisonai/mcp_server/transports/http_stream.py +376 -0
- praisonai/mcp_server/transports/stdio.py +132 -0
- praisonai/persistence/__init__.py +84 -0
- praisonai/persistence/config.py +238 -0
- praisonai/persistence/conversation/__init__.py +25 -0
- praisonai/persistence/conversation/async_mysql.py +427 -0
- praisonai/persistence/conversation/async_postgres.py +410 -0
- praisonai/persistence/conversation/async_sqlite.py +371 -0
- praisonai/persistence/conversation/base.py +151 -0
- praisonai/persistence/conversation/json_store.py +250 -0
- praisonai/persistence/conversation/mysql.py +387 -0
- praisonai/persistence/conversation/postgres.py +401 -0
- praisonai/persistence/conversation/singlestore.py +240 -0
- praisonai/persistence/conversation/sqlite.py +341 -0
- praisonai/persistence/conversation/supabase.py +203 -0
- praisonai/persistence/conversation/surrealdb.py +287 -0
- praisonai/persistence/factory.py +301 -0
- praisonai/persistence/hooks/__init__.py +18 -0
- praisonai/persistence/hooks/agent_hooks.py +297 -0
- praisonai/persistence/knowledge/__init__.py +26 -0
- praisonai/persistence/knowledge/base.py +144 -0
- praisonai/persistence/knowledge/cassandra.py +232 -0
- praisonai/persistence/knowledge/chroma.py +295 -0
- praisonai/persistence/knowledge/clickhouse.py +242 -0
- praisonai/persistence/knowledge/cosmosdb_vector.py +438 -0
- praisonai/persistence/knowledge/couchbase.py +286 -0
- praisonai/persistence/knowledge/lancedb.py +216 -0
- praisonai/persistence/knowledge/langchain_adapter.py +291 -0
- praisonai/persistence/knowledge/lightrag_adapter.py +212 -0
- praisonai/persistence/knowledge/llamaindex_adapter.py +256 -0
- praisonai/persistence/knowledge/milvus.py +277 -0
- praisonai/persistence/knowledge/mongodb_vector.py +306 -0
- praisonai/persistence/knowledge/pgvector.py +335 -0
- praisonai/persistence/knowledge/pinecone.py +253 -0
- praisonai/persistence/knowledge/qdrant.py +301 -0
- praisonai/persistence/knowledge/redis_vector.py +291 -0
- praisonai/persistence/knowledge/singlestore_vector.py +299 -0
- praisonai/persistence/knowledge/surrealdb_vector.py +309 -0
- praisonai/persistence/knowledge/upstash_vector.py +266 -0
- praisonai/persistence/knowledge/weaviate.py +223 -0
- praisonai/persistence/migrations/__init__.py +10 -0
- praisonai/persistence/migrations/manager.py +251 -0
- praisonai/persistence/orchestrator.py +406 -0
- praisonai/persistence/state/__init__.py +21 -0
- praisonai/persistence/state/async_mongodb.py +200 -0
- praisonai/persistence/state/base.py +107 -0
- praisonai/persistence/state/dynamodb.py +226 -0
- praisonai/persistence/state/firestore.py +175 -0
- praisonai/persistence/state/gcs.py +155 -0
- praisonai/persistence/state/memory.py +245 -0
- praisonai/persistence/state/mongodb.py +158 -0
- praisonai/persistence/state/redis.py +190 -0
- praisonai/persistence/state/upstash.py +144 -0
- praisonai/persistence/tests/__init__.py +3 -0
- praisonai/persistence/tests/test_all_backends.py +633 -0
- praisonai/profiler.py +1214 -0
- praisonai/recipe/__init__.py +134 -0
- praisonai/recipe/bridge.py +278 -0
- praisonai/recipe/core.py +893 -0
- praisonai/recipe/exceptions.py +54 -0
- praisonai/recipe/history.py +402 -0
- praisonai/recipe/models.py +266 -0
- praisonai/recipe/operations.py +440 -0
- praisonai/recipe/policy.py +422 -0
- praisonai/recipe/registry.py +849 -0
- praisonai/recipe/runtime.py +214 -0
- praisonai/recipe/security.py +711 -0
- praisonai/recipe/serve.py +859 -0
- praisonai/recipe/server.py +613 -0
- praisonai/scheduler/__init__.py +45 -0
- praisonai/scheduler/agent_scheduler.py +552 -0
- praisonai/scheduler/base.py +124 -0
- praisonai/scheduler/daemon_manager.py +225 -0
- praisonai/scheduler/state_manager.py +155 -0
- praisonai/scheduler/yaml_loader.py +193 -0
- praisonai/scheduler.py +194 -0
- praisonai/setup/__init__.py +1 -0
- praisonai/setup/build.py +21 -0
- praisonai/setup/post_install.py +23 -0
- praisonai/setup/setup_conda_env.py +25 -0
- praisonai/setup.py +16 -0
- praisonai/templates/__init__.py +116 -0
- praisonai/templates/cache.py +364 -0
- praisonai/templates/dependency_checker.py +358 -0
- praisonai/templates/discovery.py +391 -0
- praisonai/templates/loader.py +564 -0
- praisonai/templates/registry.py +511 -0
- praisonai/templates/resolver.py +206 -0
- praisonai/templates/security.py +327 -0
- praisonai/templates/tool_override.py +498 -0
- praisonai/templates/tools_doctor.py +256 -0
- praisonai/test.py +105 -0
- praisonai/train.py +562 -0
- praisonai/train_vision.py +306 -0
- praisonai/ui/agents.py +824 -0
- praisonai/ui/callbacks.py +57 -0
- praisonai/ui/chainlit_compat.py +246 -0
- praisonai/ui/chat.py +532 -0
- praisonai/ui/code.py +717 -0
- praisonai/ui/colab.py +474 -0
- praisonai/ui/colab_chainlit.py +81 -0
- praisonai/ui/components/aicoder.py +284 -0
- praisonai/ui/context.py +283 -0
- praisonai/ui/database_config.py +56 -0
- praisonai/ui/db.py +294 -0
- praisonai/ui/realtime.py +488 -0
- praisonai/ui/realtimeclient/__init__.py +756 -0
- praisonai/ui/realtimeclient/tools.py +242 -0
- praisonai/ui/sql_alchemy.py +710 -0
- praisonai/upload_vision.py +140 -0
- praisonai/version.py +1 -0
- praisonai-3.0.0.dist-info/METADATA +3493 -0
- praisonai-3.0.0.dist-info/RECORD +393 -0
- praisonai-3.0.0.dist-info/WHEEL +5 -0
- praisonai-3.0.0.dist-info/entry_points.txt +4 -0
- praisonai-3.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Couchbase implementation of KnowledgeStore.
|
|
3
|
+
|
|
4
|
+
Requires: couchbase
|
|
5
|
+
Install: pip install couchbase
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
from typing import Any, Dict, List, Optional
|
|
10
|
+
|
|
11
|
+
from .base import KnowledgeStore, KnowledgeDocument
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class CouchbaseKnowledgeStore(KnowledgeStore):
|
|
17
|
+
"""
|
|
18
|
+
Couchbase vector store for knowledge/RAG.
|
|
19
|
+
|
|
20
|
+
Uses Couchbase's vector search capabilities.
|
|
21
|
+
|
|
22
|
+
Example:
|
|
23
|
+
store = CouchbaseKnowledgeStore(
|
|
24
|
+
connection_string="couchbase://localhost",
|
|
25
|
+
username="admin",
|
|
26
|
+
password="password",
|
|
27
|
+
bucket_name="praisonai"
|
|
28
|
+
)
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
def __init__(
|
|
32
|
+
self,
|
|
33
|
+
connection_string: str = "couchbase://localhost",
|
|
34
|
+
username: str = "Administrator",
|
|
35
|
+
password: str = "",
|
|
36
|
+
bucket_name: str = "praisonai",
|
|
37
|
+
scope_name: str = "_default",
|
|
38
|
+
collection_name: str = "vectors",
|
|
39
|
+
index_name: str = "vector_index",
|
|
40
|
+
vector_field: str = "embedding",
|
|
41
|
+
text_field: str = "content",
|
|
42
|
+
embedding_dim: int = 1536,
|
|
43
|
+
):
|
|
44
|
+
"""
|
|
45
|
+
Initialize Couchbase knowledge store.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
connection_string: Couchbase connection string
|
|
49
|
+
username: Couchbase username
|
|
50
|
+
password: Couchbase password
|
|
51
|
+
bucket_name: Bucket name
|
|
52
|
+
scope_name: Scope name
|
|
53
|
+
collection_name: Collection name
|
|
54
|
+
index_name: Vector search index name
|
|
55
|
+
vector_field: Field name for embeddings
|
|
56
|
+
text_field: Field name for text content
|
|
57
|
+
embedding_dim: Embedding dimension
|
|
58
|
+
"""
|
|
59
|
+
self.connection_string = connection_string
|
|
60
|
+
self.username = username
|
|
61
|
+
self.password = password
|
|
62
|
+
self.bucket_name = bucket_name
|
|
63
|
+
self.scope_name = scope_name
|
|
64
|
+
self.collection_name = collection_name
|
|
65
|
+
self.index_name = index_name
|
|
66
|
+
self.vector_field = vector_field
|
|
67
|
+
self.text_field = text_field
|
|
68
|
+
self.embedding_dim = embedding_dim
|
|
69
|
+
|
|
70
|
+
self._cluster = None
|
|
71
|
+
self._bucket = None
|
|
72
|
+
self._collection = None
|
|
73
|
+
self._initialized = False
|
|
74
|
+
|
|
75
|
+
def _init_client(self):
|
|
76
|
+
"""Initialize Couchbase client lazily."""
|
|
77
|
+
if self._initialized:
|
|
78
|
+
return
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
from couchbase.cluster import Cluster
|
|
82
|
+
from couchbase.options import ClusterOptions
|
|
83
|
+
from couchbase.auth import PasswordAuthenticator
|
|
84
|
+
from datetime import timedelta
|
|
85
|
+
except ImportError:
|
|
86
|
+
raise ImportError(
|
|
87
|
+
"couchbase is required for Couchbase support. "
|
|
88
|
+
"Install with: pip install couchbase"
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
auth = PasswordAuthenticator(self.username, self.password)
|
|
92
|
+
options = ClusterOptions(auth)
|
|
93
|
+
|
|
94
|
+
self._cluster = Cluster(self.connection_string, options)
|
|
95
|
+
self._cluster.wait_until_ready(timedelta(seconds=10))
|
|
96
|
+
|
|
97
|
+
self._bucket = self._cluster.bucket(self.bucket_name)
|
|
98
|
+
scope = self._bucket.scope(self.scope_name)
|
|
99
|
+
self._collection = scope.collection(self.collection_name)
|
|
100
|
+
|
|
101
|
+
self._initialized = True
|
|
102
|
+
|
|
103
|
+
def insert(
|
|
104
|
+
self,
|
|
105
|
+
collection_name: str,
|
|
106
|
+
documents: List[KnowledgeDocument],
|
|
107
|
+
embeddings: Optional[List[List[float]]] = None,
|
|
108
|
+
) -> List[str]:
|
|
109
|
+
"""Insert documents into the store."""
|
|
110
|
+
self._init_client()
|
|
111
|
+
|
|
112
|
+
ids = []
|
|
113
|
+
for i, doc in enumerate(documents):
|
|
114
|
+
doc_id = doc.id or f"doc_{i}_{hash(doc.content)}"
|
|
115
|
+
|
|
116
|
+
data = {
|
|
117
|
+
self.text_field: doc.content,
|
|
118
|
+
"metadata": doc.metadata or {},
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if embeddings and i < len(embeddings):
|
|
122
|
+
data[self.vector_field] = embeddings[i]
|
|
123
|
+
|
|
124
|
+
self._collection.upsert(doc_id, data)
|
|
125
|
+
ids.append(doc_id)
|
|
126
|
+
|
|
127
|
+
return ids
|
|
128
|
+
|
|
129
|
+
def upsert(
|
|
130
|
+
self,
|
|
131
|
+
collection_name: str,
|
|
132
|
+
documents: List[KnowledgeDocument],
|
|
133
|
+
embeddings: Optional[List[List[float]]] = None,
|
|
134
|
+
) -> List[str]:
|
|
135
|
+
"""Upsert documents (same as insert for Couchbase)."""
|
|
136
|
+
return self.insert(collection_name, documents, embeddings)
|
|
137
|
+
|
|
138
|
+
def search(
|
|
139
|
+
self,
|
|
140
|
+
collection_name: str,
|
|
141
|
+
query_embedding: List[float],
|
|
142
|
+
limit: int = 10,
|
|
143
|
+
filters: Optional[Dict[str, Any]] = None,
|
|
144
|
+
) -> List[KnowledgeDocument]:
|
|
145
|
+
"""Search for similar documents using vector search."""
|
|
146
|
+
self._init_client()
|
|
147
|
+
|
|
148
|
+
try:
|
|
149
|
+
from couchbase.vector_search import VectorQuery, VectorSearch
|
|
150
|
+
except ImportError:
|
|
151
|
+
logger.warning("Vector search not available in this Couchbase version")
|
|
152
|
+
return []
|
|
153
|
+
|
|
154
|
+
vector_query = VectorQuery(
|
|
155
|
+
self.vector_field,
|
|
156
|
+
query_embedding,
|
|
157
|
+
num_candidates=limit * 2
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
search_req = VectorSearch.from_vector_query(vector_query)
|
|
161
|
+
|
|
162
|
+
try:
|
|
163
|
+
scope = self._bucket.scope(self.scope_name)
|
|
164
|
+
result = scope.search(
|
|
165
|
+
self.index_name,
|
|
166
|
+
search_req,
|
|
167
|
+
limit=limit
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
documents = []
|
|
171
|
+
for row in result.rows():
|
|
172
|
+
doc_id = row.id
|
|
173
|
+
try:
|
|
174
|
+
doc_data = self._collection.get(doc_id).content_as[dict]
|
|
175
|
+
documents.append(KnowledgeDocument(
|
|
176
|
+
id=doc_id,
|
|
177
|
+
content=doc_data.get(self.text_field, ""),
|
|
178
|
+
metadata=doc_data.get("metadata", {}),
|
|
179
|
+
score=row.score if hasattr(row, 'score') else None
|
|
180
|
+
))
|
|
181
|
+
except Exception as e:
|
|
182
|
+
logger.warning(f"Failed to fetch document {doc_id}: {e}")
|
|
183
|
+
|
|
184
|
+
return documents
|
|
185
|
+
except Exception as e:
|
|
186
|
+
logger.error(f"Vector search failed: {e}")
|
|
187
|
+
return []
|
|
188
|
+
|
|
189
|
+
def delete(
|
|
190
|
+
self,
|
|
191
|
+
collection_name: str,
|
|
192
|
+
ids: Optional[List[str]] = None,
|
|
193
|
+
filters: Optional[Dict[str, Any]] = None,
|
|
194
|
+
) -> int:
|
|
195
|
+
"""Delete documents by ID."""
|
|
196
|
+
self._init_client()
|
|
197
|
+
|
|
198
|
+
if not ids:
|
|
199
|
+
return 0
|
|
200
|
+
|
|
201
|
+
count = 0
|
|
202
|
+
for doc_id in ids:
|
|
203
|
+
try:
|
|
204
|
+
self._collection.remove(doc_id)
|
|
205
|
+
count += 1
|
|
206
|
+
except Exception as e:
|
|
207
|
+
logger.warning(f"Failed to delete {doc_id}: {e}")
|
|
208
|
+
|
|
209
|
+
return count
|
|
210
|
+
|
|
211
|
+
def get(
|
|
212
|
+
self,
|
|
213
|
+
collection_name: str,
|
|
214
|
+
ids: List[str],
|
|
215
|
+
) -> List[KnowledgeDocument]:
|
|
216
|
+
"""Get documents by ID."""
|
|
217
|
+
self._init_client()
|
|
218
|
+
|
|
219
|
+
documents = []
|
|
220
|
+
for doc_id in ids:
|
|
221
|
+
try:
|
|
222
|
+
doc_data = self._collection.get(doc_id).content_as[dict]
|
|
223
|
+
documents.append(KnowledgeDocument(
|
|
224
|
+
id=doc_id,
|
|
225
|
+
content=doc_data.get(self.text_field, ""),
|
|
226
|
+
metadata=doc_data.get("metadata", {})
|
|
227
|
+
))
|
|
228
|
+
except Exception as e:
|
|
229
|
+
logger.warning(f"Failed to get {doc_id}: {e}")
|
|
230
|
+
|
|
231
|
+
return documents
|
|
232
|
+
|
|
233
|
+
def count(self, collection_name: str) -> int:
|
|
234
|
+
"""Count documents in collection."""
|
|
235
|
+
self._init_client()
|
|
236
|
+
|
|
237
|
+
try:
|
|
238
|
+
query = f"SELECT COUNT(*) as count FROM `{self.bucket_name}`.`{self.scope_name}`.`{self.collection_name}`"
|
|
239
|
+
result = self._cluster.query(query)
|
|
240
|
+
for row in result:
|
|
241
|
+
return row.get("count", 0)
|
|
242
|
+
except Exception as e:
|
|
243
|
+
logger.error(f"Count query failed: {e}")
|
|
244
|
+
|
|
245
|
+
return 0
|
|
246
|
+
|
|
247
|
+
def create_collection(self, collection_name: str, **kwargs) -> bool:
|
|
248
|
+
"""Create collection (Couchbase collections are pre-created)."""
|
|
249
|
+
self._init_client()
|
|
250
|
+
return True
|
|
251
|
+
|
|
252
|
+
def delete_collection(self, collection_name: str) -> bool:
|
|
253
|
+
"""Delete all documents in collection."""
|
|
254
|
+
self._init_client()
|
|
255
|
+
|
|
256
|
+
try:
|
|
257
|
+
query = f"DELETE FROM `{self.bucket_name}`.`{self.scope_name}`.`{self.collection_name}`"
|
|
258
|
+
self._cluster.query(query)
|
|
259
|
+
return True
|
|
260
|
+
except Exception as e:
|
|
261
|
+
logger.error(f"Delete collection failed: {e}")
|
|
262
|
+
return False
|
|
263
|
+
|
|
264
|
+
def list_collections(self) -> List[str]:
|
|
265
|
+
"""List available collections."""
|
|
266
|
+
self._init_client()
|
|
267
|
+
|
|
268
|
+
try:
|
|
269
|
+
collections = self._bucket.collections().get_all_scopes()
|
|
270
|
+
result = []
|
|
271
|
+
for scope in collections:
|
|
272
|
+
for coll in scope.collections:
|
|
273
|
+
result.append(f"{scope.name}.{coll.name}")
|
|
274
|
+
return result
|
|
275
|
+
except Exception as e:
|
|
276
|
+
logger.error(f"List collections failed: {e}")
|
|
277
|
+
return []
|
|
278
|
+
|
|
279
|
+
def close(self) -> None:
|
|
280
|
+
"""Close the connection."""
|
|
281
|
+
if self._cluster:
|
|
282
|
+
self._cluster.close()
|
|
283
|
+
self._cluster = None
|
|
284
|
+
self._bucket = None
|
|
285
|
+
self._collection = None
|
|
286
|
+
self._initialized = False
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"""
|
|
2
|
+
LanceDB implementation of KnowledgeStore.
|
|
3
|
+
|
|
4
|
+
Requires: lancedb
|
|
5
|
+
Install: pip install lancedb
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
from typing import Any, Dict, List, Optional
|
|
10
|
+
|
|
11
|
+
from .base import KnowledgeStore, KnowledgeDocument
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class LanceDBKnowledgeStore(KnowledgeStore):
|
|
17
|
+
"""
|
|
18
|
+
LanceDB-based knowledge store for vector search.
|
|
19
|
+
|
|
20
|
+
Embedded serverless vector database.
|
|
21
|
+
|
|
22
|
+
Example:
|
|
23
|
+
store = LanceDBKnowledgeStore(
|
|
24
|
+
path="./lancedb"
|
|
25
|
+
)
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
path: str = "./lancedb",
|
|
31
|
+
uri: Optional[str] = None,
|
|
32
|
+
):
|
|
33
|
+
try:
|
|
34
|
+
import lancedb
|
|
35
|
+
except ImportError:
|
|
36
|
+
raise ImportError(
|
|
37
|
+
"lancedb is required for LanceDB support. "
|
|
38
|
+
"Install with: pip install lancedb"
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
self._lancedb = lancedb
|
|
42
|
+
self._db = lancedb.connect(uri or path)
|
|
43
|
+
self._tables: Dict[str, Any] = {}
|
|
44
|
+
logger.info(f"Connected to LanceDB at {uri or path}")
|
|
45
|
+
|
|
46
|
+
def create_collection(
|
|
47
|
+
self,
|
|
48
|
+
name: str,
|
|
49
|
+
dimension: int,
|
|
50
|
+
distance: str = "cosine",
|
|
51
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
52
|
+
) -> None:
|
|
53
|
+
"""Create a new table."""
|
|
54
|
+
import pyarrow as pa
|
|
55
|
+
|
|
56
|
+
schema = pa.schema([
|
|
57
|
+
pa.field("id", pa.string()),
|
|
58
|
+
pa.field("content", pa.string()),
|
|
59
|
+
pa.field("content_hash", pa.string()),
|
|
60
|
+
pa.field("created_at", pa.float64()),
|
|
61
|
+
pa.field("vector", pa.list_(pa.float32(), dimension)),
|
|
62
|
+
])
|
|
63
|
+
|
|
64
|
+
self._db.create_table(name, schema=schema)
|
|
65
|
+
logger.info(f"Created LanceDB table: {name}")
|
|
66
|
+
|
|
67
|
+
def delete_collection(self, name: str) -> bool:
|
|
68
|
+
"""Delete a table."""
|
|
69
|
+
try:
|
|
70
|
+
self._db.drop_table(name)
|
|
71
|
+
if name in self._tables:
|
|
72
|
+
del self._tables[name]
|
|
73
|
+
return True
|
|
74
|
+
except Exception as e:
|
|
75
|
+
logger.warning(f"Failed to delete table {name}: {e}")
|
|
76
|
+
return False
|
|
77
|
+
|
|
78
|
+
def collection_exists(self, name: str) -> bool:
|
|
79
|
+
"""Check if a table exists."""
|
|
80
|
+
return name in self._db.table_names()
|
|
81
|
+
|
|
82
|
+
def list_collections(self) -> List[str]:
|
|
83
|
+
"""List all tables."""
|
|
84
|
+
return self._db.table_names()
|
|
85
|
+
|
|
86
|
+
def _get_table(self, name: str):
|
|
87
|
+
"""Get or cache a table."""
|
|
88
|
+
if name not in self._tables:
|
|
89
|
+
self._tables[name] = self._db.open_table(name)
|
|
90
|
+
return self._tables[name]
|
|
91
|
+
|
|
92
|
+
def insert(
|
|
93
|
+
self,
|
|
94
|
+
collection: str,
|
|
95
|
+
documents: List[KnowledgeDocument]
|
|
96
|
+
) -> List[str]:
|
|
97
|
+
"""Insert documents."""
|
|
98
|
+
table = self._get_table(collection)
|
|
99
|
+
|
|
100
|
+
data = []
|
|
101
|
+
ids = []
|
|
102
|
+
for doc in documents:
|
|
103
|
+
if doc.embedding is None:
|
|
104
|
+
raise ValueError(f"Document {doc.id} has no embedding")
|
|
105
|
+
|
|
106
|
+
data.append({
|
|
107
|
+
"id": doc.id,
|
|
108
|
+
"content": doc.content,
|
|
109
|
+
"content_hash": doc.content_hash or "",
|
|
110
|
+
"created_at": doc.created_at,
|
|
111
|
+
"vector": doc.embedding,
|
|
112
|
+
})
|
|
113
|
+
ids.append(doc.id)
|
|
114
|
+
|
|
115
|
+
table.add(data)
|
|
116
|
+
return ids
|
|
117
|
+
|
|
118
|
+
def upsert(
|
|
119
|
+
self,
|
|
120
|
+
collection: str,
|
|
121
|
+
documents: List[KnowledgeDocument]
|
|
122
|
+
) -> List[str]:
|
|
123
|
+
"""Insert or update documents."""
|
|
124
|
+
# LanceDB doesn't have native upsert, delete then insert
|
|
125
|
+
ids = [doc.id for doc in documents]
|
|
126
|
+
self.delete(collection, ids)
|
|
127
|
+
return self.insert(collection, documents)
|
|
128
|
+
|
|
129
|
+
def search(
|
|
130
|
+
self,
|
|
131
|
+
collection: str,
|
|
132
|
+
query_embedding: List[float],
|
|
133
|
+
limit: int = 5,
|
|
134
|
+
filters: Optional[Dict[str, Any]] = None,
|
|
135
|
+
score_threshold: Optional[float] = None
|
|
136
|
+
) -> List[KnowledgeDocument]:
|
|
137
|
+
"""Search for similar documents."""
|
|
138
|
+
table = self._get_table(collection)
|
|
139
|
+
|
|
140
|
+
query = table.search(query_embedding).limit(limit)
|
|
141
|
+
|
|
142
|
+
if filters:
|
|
143
|
+
where_clauses = [f"{k} = '{v}'" for k, v in filters.items()]
|
|
144
|
+
query = query.where(" AND ".join(where_clauses))
|
|
145
|
+
|
|
146
|
+
results = query.to_pandas()
|
|
147
|
+
|
|
148
|
+
documents = []
|
|
149
|
+
for _, row in results.iterrows():
|
|
150
|
+
if score_threshold and row.get("_distance", 1) > (1 - score_threshold):
|
|
151
|
+
continue
|
|
152
|
+
|
|
153
|
+
doc = KnowledgeDocument(
|
|
154
|
+
id=row["id"],
|
|
155
|
+
content=row["content"],
|
|
156
|
+
embedding=None,
|
|
157
|
+
metadata={},
|
|
158
|
+
content_hash=row.get("content_hash"),
|
|
159
|
+
created_at=row.get("created_at", 0),
|
|
160
|
+
)
|
|
161
|
+
documents.append(doc)
|
|
162
|
+
|
|
163
|
+
return documents
|
|
164
|
+
|
|
165
|
+
def get(
|
|
166
|
+
self,
|
|
167
|
+
collection: str,
|
|
168
|
+
ids: List[str]
|
|
169
|
+
) -> List[KnowledgeDocument]:
|
|
170
|
+
"""Get documents by IDs."""
|
|
171
|
+
table = self._get_table(collection)
|
|
172
|
+
|
|
173
|
+
id_list = ", ".join([f"'{i}'" for i in ids])
|
|
174
|
+
results = table.search().where(f"id IN ({id_list})").to_pandas()
|
|
175
|
+
|
|
176
|
+
documents = []
|
|
177
|
+
for _, row in results.iterrows():
|
|
178
|
+
doc = KnowledgeDocument(
|
|
179
|
+
id=row["id"],
|
|
180
|
+
content=row["content"],
|
|
181
|
+
embedding=list(row["vector"]) if "vector" in row else None,
|
|
182
|
+
metadata={},
|
|
183
|
+
content_hash=row.get("content_hash"),
|
|
184
|
+
created_at=row.get("created_at", 0),
|
|
185
|
+
)
|
|
186
|
+
documents.append(doc)
|
|
187
|
+
|
|
188
|
+
return documents
|
|
189
|
+
|
|
190
|
+
def delete(
|
|
191
|
+
self,
|
|
192
|
+
collection: str,
|
|
193
|
+
ids: Optional[List[str]] = None,
|
|
194
|
+
filters: Optional[Dict[str, Any]] = None
|
|
195
|
+
) -> int:
|
|
196
|
+
"""Delete documents."""
|
|
197
|
+
table = self._get_table(collection)
|
|
198
|
+
|
|
199
|
+
if ids:
|
|
200
|
+
id_list = ", ".join([f"'{i}'" for i in ids])
|
|
201
|
+
table.delete(f"id IN ({id_list})")
|
|
202
|
+
return len(ids)
|
|
203
|
+
elif filters:
|
|
204
|
+
where_clauses = [f"{k} = '{v}'" for k, v in filters.items()]
|
|
205
|
+
table.delete(" AND ".join(where_clauses))
|
|
206
|
+
return -1
|
|
207
|
+
return 0
|
|
208
|
+
|
|
209
|
+
def count(self, collection: str) -> int:
|
|
210
|
+
"""Count documents."""
|
|
211
|
+
table = self._get_table(collection)
|
|
212
|
+
return table.count_rows()
|
|
213
|
+
|
|
214
|
+
def close(self) -> None:
|
|
215
|
+
"""Close the store."""
|
|
216
|
+
self._tables.clear()
|