跳转至

Store#

nlql.store —— Store 接口、StoreCaps 能力描述,以及内置的 LocalStore(基于 numpy 的精确检索)。各后端实现 Store 接口;引擎将过滤等操作尽量交给后端的原生能力处理,其余在内存中完成。

store #

Store protocol and the built-in LocalStore (numpy flat index).

__all__ module-attribute #

__all__ = ['Store', 'StoreCaps', 'LocalStore', 'matches_filter']

Store #

Bases: Protocol

The storage + retrieval interface the executor runs against.

upsert #

upsert(units: Sequence[Unit]) -> None
源代码位于: src/nlql/store/base.py
def upsert(self, units: Sequence[Unit]) -> None: ...

add_documents #

add_documents(documents: Iterable[Document]) -> None
源代码位于: src/nlql/store/base.py
def add_documents(self, documents: Iterable[Document]) -> None: ...

get_document #

get_document(doc_id: str) -> Document | None
源代码位于: src/nlql/store/base.py
def get_document(self, doc_id: str) -> Document | None: ...
ann_search(vector: ndarray, k: int | None = None, *, filter: Expr | None = None) -> list[tuple[Unit, float]]

Return up to k (unit, cosine) pairs matching filter, best first.

源代码位于: src/nlql/store/base.py
def ann_search(
    self,
    vector: np.ndarray,
    k: int | None = None,
    *,
    filter: Expr | None = None,
) -> list[tuple[Unit, float]]:
    """Return up to ``k`` ``(unit, cosine)`` pairs matching ``filter``, best first."""
    ...

scan #

scan(filter: Expr | None = None) -> list[Unit]

Return all units matching filter (non-vector path).

源代码位于: src/nlql/store/base.py
def scan(self, filter: Expr | None = None) -> list[Unit]:
    """Return all units matching ``filter`` (non-vector path)."""
    ...

all_units #

all_units() -> list[Unit]
源代码位于: src/nlql/store/base.py
def all_units(self) -> list[Unit]: ...

neighbors #

neighbors(doc_id: str, ordinal: int, window: int) -> list[Unit]

Units of the same document within ±window ordinals, ordinal-ordered.

源代码位于: src/nlql/store/base.py
def neighbors(self, doc_id: str, ordinal: int, window: int) -> list[Unit]:
    """Units of the same document within ``±window`` ordinals, ordinal-ordered."""
    ...

capabilities #

capabilities() -> StoreCaps
源代码位于: src/nlql/store/base.py
def capabilities(self) -> StoreCaps: ...

__len__ #

__len__() -> int
源代码位于: src/nlql/store/base.py
def __len__(self) -> int: ...

StoreCaps dataclass #

StoreCaps(name: str = 'local', vector_search: bool = True, exact: bool = True, metadata_pushdown: bool = False, text_pushdown: bool = False)

What a store can do natively.

name class-attribute instance-attribute #

name: str = 'local'
vector_search: bool = True

exact class-attribute instance-attribute #

exact: bool = True

metadata_pushdown class-attribute instance-attribute #

metadata_pushdown: bool = False

text_pushdown class-attribute instance-attribute #

text_pushdown: bool = False

LocalStore #

LocalStore()

Bases: BaseUnitStore

Process-local unit store with an exact flat vector index.

源代码位于: src/nlql/store/local.py
def __init__(self) -> None:
    super().__init__()
    self._ids: list[str] = []
    self._matrix: np.ndarray = np.empty((0, 0), dtype=np.float32)
    self._columns = MetadataColumns()
ann_search(vector: ndarray, k: int | None = None, *, filter: Expr | None = None) -> list[tuple[Unit, float]]
源代码位于: src/nlql/store/local.py
def ann_search(
    self,
    vector: np.ndarray,
    k: int | None = None,
    *,
    filter: Expr | None = None,
) -> list[tuple[Unit, float]]:
    self._ensure_index()
    n = self._matrix.shape[0]
    if n == 0:
        return []
    query = normalize(vector)
    if query.shape[0] != self._matrix.shape[1]:
        raise NLQLExecutionError(
            f"query dim {query.shape[0]} != index dim {self._matrix.shape[1]}"
        )
    scores = self._matrix @ query  # cosine, since both sides are unit-normalized

    if filter is not None:
        candidate_idx = np.nonzero(self._columns.mask(filter))[0]
    else:
        candidate_idx = np.arange(n)
    if candidate_idx.size == 0:
        return []

    cand_scores = scores[candidate_idx]
    order = np.argsort(-cand_scores)
    if k is not None:
        order = order[:k]
    return [
        (self._units[self._ids[int(candidate_idx[o])]], float(cand_scores[o])) for o in order
    ]

scan #

scan(filter: Expr | None = None) -> list[Unit]
源代码位于: src/nlql/store/local.py
def scan(self, filter: Expr | None = None) -> list[Unit]:
    if filter is None:
        return list(self._units.values())
    self._ensure_index()
    keep = self._columns.mask(filter)
    return [self._units[self._ids[i]] for i in np.nonzero(keep)[0]]

capabilities #

capabilities() -> StoreCaps
源代码位于: src/nlql/store/local.py
def capabilities(self) -> StoreCaps:
    return StoreCaps(name="local", vector_search=True, exact=True, metadata_pushdown=True)

matches_filter #

matches_filter(expr: Expr | None, metadata: dict[str, Any]) -> bool

Whether metadata satisfies a pushed metadata filter (None matches all).

源代码位于: src/nlql/store/filter.py
def matches_filter(expr: Expr | None, metadata: dict[str, Any]) -> bool:
    """Whether ``metadata`` satisfies a pushed metadata filter (``None`` matches all)."""
    if expr is None:
        return True
    if isinstance(expr, Compare):
        return compare_values(
            expr.op, _operand(expr.left, metadata), _operand(expr.right, metadata)
        )
    if isinstance(expr, And):
        return all(matches_filter(o, metadata) for o in expr.operands)
    if isinstance(expr, Or):
        return any(matches_filter(o, metadata) for o in expr.operands)
    if isinstance(expr, Not):
        return not matches_filter(expr.operand, metadata)
    return False

后端适配器#

以下适配器实现 Store 接口,需安装对应 extras:

适配器 模块 extras
LocalStore nlql.store.local 内置
FaissStore nlql.store.faiss_store nlql[faiss]
HnswStore nlql.store.hnsw_store nlql[hnsw]
QdrantStore nlql.store.qdrant_store nlql[qdrant]
ChromaStore nlql.store.chroma_store nlql[chroma]
PgVectorStore nlql.store.pgvector_store nlql[pgvector]

各后端的能力差异(向量检索类型、元数据与全文过滤)见 混合后端