コンテンツにスキップ

DocumentStore と VectorIndex

エンコードした文書を保存しチャンクを検索する 2 つのポート。オーナーで区切られ、失効で区切られる。

英語版が原文です。

ポート: DocumentStore と VectorIndex。 indx_interfaces.protocols で、 indx_interfaces.store のモデルの上に宣言されています(ADR-0071)。

DocumentStore はエンコードした文書を保存します。StoredDocument は StoredDocumentSummary と EncodeResult 全体を並べたものです。VectorIndex はチャンクごとに 1 つの ChunkPoint(テキスト、 ページ、枠と、埋め込まれた空間ごとの BlockEmbedding。0 個のこともある)を保存し、ChunkQuery に ChunkHit で答えます。どちらもオーナーとソースダイジェストをキーとします。

class DocumentStore(Protocol):
def put(self, owner: OwnerId, document: StoredDocument) -> None: ...
def get(self, owner: OwnerId, digest: SourceDigest) -> StoredDocument | None: ...
def list(self, owner: OwnerId) -> tuple[StoredDocumentSummary, ...]: ...
def delete(self, owner: OwnerId, digest: SourceDigest) -> bool: ...
def purge(self, now: datetime) -> int: ...
class VectorIndex(Protocol):
def upsert(
self,
owner: OwnerId,
digest: SourceDigest,
points: tuple[ChunkPoint, ...],
spaces: tuple[EmbeddingSpace, ...],
expires_at: datetime,
) -> None: ...
def delete(self, owner: OwnerId, digest: SourceDigest) -> None: ...
def search(self, owner: OwnerId, query: ChunkQuery) -> tuple[ChunkHit, ...]: ...
def purge(self, now: datetime) -> int: ...

ポートが 2 つなのは、バックエンドがそこで分かれるからです。pgvector 付きの pgsql は両方を、qdrant の ようなベクトルデータベースは VectorIndex だけを、インメモリストアは両方を実装します。ポイントを持つ バックエンドがレコードストアを偽装することはありません。同梱するのは memory(indx-store-memory)、 sqlite(indx-store-sqlite。INDX_STORE_SQLITE_PATH が名指す 1 つのファイルで、保存したものが再起動を 越えて残る)、postgres(indx-store-postgres。INDX_STORE_POSTGRES_URL が名指すデータベースで、すべての インスタンスが共有する)の 3 つです。どれも indx-ranking で脚を順位づけるので、同じポイントからは、どれが 保持していても同じヒットが同じ順に返ります。

ChunkQuery が 1 本の脚(名指した空間のベクトル、またはテキスト)なのは、どちらのバックエンドも両方に ネイティブに答え、後から足す語彙のポートは 2 つ目のポートになるからです。両方を同時に運ばないのは、 類似度と語のスコアが尺度を共有しないからで、呼び出し元が脚を順位で融合し、それぞれのスコアを保ちます。

  • オーナー. purge 以外のすべてのメソッドは最初に OwnerId を受け取ります。オーナーをまたぐものは ありません。別のオーナーが保存したダイジェストは、このオーナーにとって保存されたことのない ダイジェストです。オーナーはモデルのフィールドにならないので、ワイヤー上のものが別のオーナーを 名指すことはできません。
  • 同一性. オーナーの中で、文書はそのソースダイジェストです。StoredDocument は、ダイジェストが 結果の plan.source_digest と異なるサマリーを拒否します。
  • 置き換え. put は同じダイジェストの文書を置き換え、upsert はそのダイジェストが持っていた すべてのポイントを置き換えます。
  • 冪等性. 存在しないダイジェストの delete は False(レコード)または何もしない(ポイント)です。
  • 読み取り時の失効. get、list、search は、expires_at が現在時刻以前のものを決して返しません。 purge(now) はすべてのオーナーの領域を回収し、消えた文書の数を返します。正しさがそれを待つことは ありません。
  • 両方のポートでの失効. インデックスはレコードと結合して知ることができないので、upsert には文書の expires_at が渡されます。
  • 空間. ベクトル列やコレクションは次元とメトリックで作られるので、upsert にはポイントのすべての ベクトルの EmbeddingSpace が渡されます。ベクトルの脚は空間のメトリックで、近いほど高く採点します。
  • 順序. list は最近更新されたものから返します。search は最大 top_k 件を良い順に返します。 ベクトルの脚は名指した空間のベクトルを持つポイントだけ、テキストの脚はテキストを持つすべてのポイント、 digests が設定されていればそれらの文書からだけです。スコアは バックエンド固有の尺度で、1 つの応答の中でだけ比較できます。
  • 同期. ファサードと同じです(ADR-0024)。呼び出し元はイベントループの 外で実行します。

バックエンドは indx.document_stores または indx.vector_indexes のエントリポイントで、その値は引数の ないファクトリーです。ファクトリーは自身の設定を読みます。デプロイはそれぞれ 1 つを名指し、2 つは別の ディストリビューションから来ても構いません。どちらも indx.capabilities には加わりません。ストアは計画 されることがなく、機能スナップショットのハッシュをそのために動かしてはならないからです。