From 36a5512fc89bc43b2eec07a3adc3e9dce03af7fe Mon Sep 17 00:00:00 2001 From: jinliyl <6469360+jinliyl@users.noreply.github.com> Date: Wed, 3 Jun 2026 17:28:30 +0800 Subject: [PATCH] refactor(vector_store): make obvec and zvec vector stores optional dependencies (#273) * refactor(vector_store): make obvec and zvec vector stores optional dependencies - Removed direct imports of ObVecVectorStore and ZvecVectorStore from init file - Added try-except blocks for conditional importing of optional vector stores - Updated error handling to check for both pyobvector and sqlalchemy in ObVecVectorStore - Renamed _OBVECTOR_IMPORT_ERROR to _OBVEC_IMPORT_ERROR for consistency - Moved pyobvector and related dependencies to optional 'obvec' extra - Added separate 'zvec' optional dependency group - Updated package configuration to exclude reme4 module patterns - Removed reme4 entry point from console scripts - Bumped version from 0.3.1.9 to 0.3.1.10 * refactor(dependencies): reorganize project dependencies and add optional seekdb support - Move sqlite-vec, prompt_toolkit, and rich to earlier in dependencies list - Remove pyseekdb from main dependencies and create separate seekdb optional dependency group - Reorder pyyaml to later in the dependencies list - Maintain all existing dependency versions while improving organization * chore(deps): remove faiss-cpu dependency from pyproject.toml - Removed faiss-cpu>=1.7.4 from the faiss dependency group - Cleaned up unused faiss dependency configuration - Updated project dependencies to exclude faiss-cpu package --- pyproject.toml | 47 +++++++++----------- reme/__init__.py | 2 +- reme/core/vector_store/__init__.py | 22 ++++++--- reme/core/vector_store/obvec_vector_store.py | 22 ++++++--- 4 files changed, 52 insertions(+), 41 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3636193a..7f4d7352 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,33 +33,23 @@ classifiers = [ keywords = ["llm", "memory", "experience", "memoryscope", "ai", "mcp", "http", "reme", "personal"] dependencies = [ - "aiofiles>=24.1.0", + "sqlite-vec>=0.1.6", + "prompt_toolkit>=3.0.52", + "rich>=14.2.0", "asyncpg>=0.31.0", "chromadb>=1.3.5", - # pyseekdb 1.2+ requires Python >=3.11 (no wheels on 3.10) - "pyseekdb>=1.2.0; python_version >= '3.11'", "dashscope>=1.25.1", "elasticsearch>=9.2.0", "fastapi>=0.121.3", "fastmcp>=2.14.1", "httpx>=0.28.1", - "jieba>=0.42.1", - "rjieba>=0.1.11", "loguru>=0.7.3", "mcp>=1.25.0", - "networkx>=3.4", "numpy>=2.2.6", "openai>=2.8.1", "pandas>=2.3.3", - "prompt_toolkit>=3.0.52", "pydantic>=2.12.4", - "pyobvector>=0.1.20", - "pyyaml>=6.0.3", "qdrant-client>=1.16.0", - "rich>=14.2.0", - "sqlite-vec>=0.1.6", - # pyobvector imports Expression from sqlglot; removed from sqlglot 30+ top-level API - "sqlglot>=25,<30", "tavily-python>=0.7.13", "tiktoken>=0.12.0", "tqdm>=4.67.1", @@ -67,17 +57,27 @@ dependencies = [ "uvicorn>=0.40.0", "watchfiles>=1.1.1", "pyyaml>=6.0.3", - "mistletoe", - "neo4j", ] [project.optional-dependencies] -ray = [ - "ray", +obvec = [ + "pyobvector>=0.1.20", + "sqlalchemy>=2.0", + # pyobvector imports Expression from sqlglot; removed from sqlglot 30+ top-level API + "sqlglot>=25,<30", ] -faiss = [ - "faiss-cpu>=1.7.4", +seekdb = [ + # pyseekdb 1.2+ requires Python >=3.11 (no wheels on 3.10) + "pyseekdb>=1.2.0; python_version >= '3.11'", +] + +zvec = [ + "zvec", +] + +ray = [ + "ray", ] dev = [ @@ -111,7 +111,7 @@ core = [ [tool.setuptools.packages.find] where = ["."] -include = ["reme_ai*", "reme*", "reme4*"] +include = ["reme_ai*", "reme*"] exclude = ["test*", "cookbook*", "doc*", "library*", "dist*"] [tool.setuptools.package-data] @@ -127,12 +127,6 @@ reme = [ "**/*.json", ] -reme4 = [ - "**/*.yaml", - "**/*.py", - "**/*.json", -] - [tool.setuptools.dynamic] version = { attr = "reme.__version__" } @@ -145,7 +139,6 @@ Repository = "https://github.com/agentscope-ai/ReMe" reme = "reme_ai.main:main" reme2 = "reme.reme:main" remecli = "reme.reme_cli:main" -reme4 = "reme4.reme:main" [tool.pytest.ini_options] asyncio_default_fixture_loop_scope = "function" diff --git a/reme/__init__.py b/reme/__init__.py index 01261acd..604c0014 100644 --- a/reme/__init__.py +++ b/reme/__init__.py @@ -6,7 +6,7 @@ from . import extension from . import memory from .reme import ReMe -__version__ = "0.3.1.9" +__version__ = "0.3.1.10" __all__ = [ "config", diff --git a/reme/core/vector_store/__init__.py b/reme/core/vector_store/__init__.py index 8ea58d76..4c01c748 100644 --- a/reme/core/vector_store/__init__.py +++ b/reme/core/vector_store/__init__.py @@ -5,10 +5,8 @@ from .chroma_vector_store import ChromaVectorStore from .es_vector_store import ESVectorStore from .hologres_store import HologresVectorStore from .local_vector_store import LocalVectorStore -from .obvec_vector_store import ObVecVectorStore from .pgvector_store import PGVectorStore from .qdrant_vector_store import QdrantVectorStore -from .zvec_vector_store import ZvecVectorStore from ..registry_factory import R __all__ = [ @@ -17,20 +15,32 @@ __all__ = [ "ESVectorStore", "HologresVectorStore", "LocalVectorStore", - "ObVecVectorStore", "PGVectorStore", "QdrantVectorStore", - "ZvecVectorStore", ] R.vector_stores.register("chroma")(ChromaVectorStore) R.vector_stores.register("es")(ESVectorStore) R.vector_stores.register("hologres")(HologresVectorStore) R.vector_stores.register("local")(LocalVectorStore) -R.vector_stores.register("obvec")(ObVecVectorStore) R.vector_stores.register("pgvector")(PGVectorStore) R.vector_stores.register("qdrant")(QdrantVectorStore) -R.vector_stores.register("zvec")(ZvecVectorStore) + +try: + from .obvec_vector_store import ObVecVectorStore + + R.vector_stores.register("obvec")(ObVecVectorStore) + __all__.append("ObVecVectorStore") +except ImportError: + pass + +try: + from .zvec_vector_store import ZvecVectorStore + + R.vector_stores.register("zvec")(ZvecVectorStore) + __all__.append("ZvecVectorStore") +except ImportError: + pass try: from .seekdb_vector_store import SeekdbVectorStore diff --git a/reme/core/vector_store/obvec_vector_store.py b/reme/core/vector_store/obvec_vector_store.py index c8ad17c5..74231343 100644 --- a/reme/core/vector_store/obvec_vector_store.py +++ b/reme/core/vector_store/obvec_vector_store.py @@ -7,24 +7,31 @@ from pathlib import Path from typing import Any from loguru import logger -from sqlalchemy import Column, JSON, String, text as sa_text -from sqlalchemy.dialects.mysql import LONGTEXT from .base_vector_store import BaseVectorStore from ..embedding import BaseEmbeddingModel from ..schema import VectorNode -_OBVECTOR_IMPORT_ERROR: Exception | None = None +_OBVEC_IMPORT_ERROR: Exception | None = None try: + from sqlalchemy import Column, JSON, String, text as sa_text + from sqlalchemy.dialects.mysql import LONGTEXT from pyobvector import IndexParams, ObVecClient, VecIndexType, VECTOR from pyobvector import cosine_distance, inner_product except Exception as e: - _OBVECTOR_IMPORT_ERROR = e + _OBVEC_IMPORT_ERROR = e + Column = None # type: ignore[misc, assignment] + JSON = None # type: ignore[misc, assignment] + String = None # type: ignore[misc, assignment] + sa_text = None # type: ignore[misc, assignment] + LONGTEXT = None # type: ignore[misc, assignment] IndexParams = None # type: ignore[misc, assignment] ObVecClient = None # type: ignore[misc, assignment] VecIndexType = None # type: ignore[misc, assignment] VECTOR = None # type: ignore[misc, assignment] + cosine_distance = None # type: ignore[misc, assignment] + inner_product = None # type: ignore[misc, assignment] _COL_SELECT = "id, content, vector, metadata" @@ -139,10 +146,11 @@ class ObVecVectorStore(BaseVectorStore): index_ef_search: int = 100, **kwargs, ): - if _OBVECTOR_IMPORT_ERROR is not None: + if _OBVEC_IMPORT_ERROR is not None: raise ImportError( - "ObVecVectorStore requires pyobvector. Install with `pip install pyobvector`", - ) from _OBVECTOR_IMPORT_ERROR + "ObVecVectorStore requires pyobvector and sqlalchemy. " + "Install with `pip install pyobvector sqlalchemy`", + ) from _OBVEC_IMPORT_ERROR super().__init__( collection_name=collection_name,