Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

API リファレンス

Index

Laurus 検索エンジンをラップするメインクラスです。

class Index:
    def __init__(
        self,
        path: str | None = None,
        schema: Schema | None = None,
        wal_sync_policy: WalSyncPolicy | None = None,
        commit_policy: CommitPolicy | None = None,
    ) -> None: ...

コンストラクタ

パラメータ型デフォルト説明
pathstr | NoneNone永続ストレージのディレクトリパス。None の場合はインメモリインデックスを作成します。指定した場合、そのディレクトリは laurus-cli create index/--index-dir と同じ <path>/schema.toml + <path>/store/ というレイアウトに従うため、ここで作成したインデックスは CLI からも開けます(逆も同様)。詳細は下記を参照してください。
schemaSchema | NoneNoneスキーマ定義。新規にファイルベース(またはインメモリ)インデックスを作成する場合のみ意味を持ちます。既存のファイルベースインデックスを再オープンする場合は省略(None)する必要があり、永続化済みのスキーマが代わりに読み込まれます。新規インデックスで省略した場合は空のスキーマが使用されます。
wal_sync_policyWalSyncPolicy | NoneNoneWAL の永続性ポリシー。None の場合はデフォルトのレコードごとの fsync を使用します。WAL 同期ポリシー / 永続性を参照してください。
commit_policyCommitPolicy | NoneNone自動コミットポリシー。None の場合はデフォルトの手動コミット(自動コミットなし)を使用します。コミットポリシー / 自動コミットを参照してください。

ファイルベースインデックスの作成 vs 再オープン(path を指定した場合): <path>/schema.toml がまだ存在しない場合、この呼び出しは新規インデックスを作成し、schema(省略時は空のスキーマ)をそこに永続化します。<path>/schema.toml が既に存在する場合、この呼び出しは既存インデックスを再オープンします – schema は省略しなければならず、指定すると ValueError になります(どちらのスキーマを優先すべきか曖昧になるため)。path がこの規約導入以前のレイアウト(schema.toml が無く、セグメントファイルが path 直下にある)のインデックスを含んでいる場合も ValueError になります。

メソッド

メソッド説明
put_document(id, doc)ドキュメントをアップサート(upsert)します。同じ ID の既存バージョンをすべて置換します。
add_document(id, doc)既存バージョンを削除せずにドキュメントチャンクを追記します。
put_documents(docs)バッチ upsert。docs は (id, dict) ペアのイテラブルで、バッチごとに WAL fsync 1 回で順に適用します(重複 ID はデデュープ、最後が勝ち)。最初の不正エントリで fail-fast し、適用済みの prefix はロールバックされません。
add_documents(docs)バッチチャンク追記。put_documents と同様ですが、繰り返した ID は別バージョンとして蓄積されます。
get_documents(id) -> list[dict]指定 ID の全保存バージョンを返します。
delete_documents(id)指定 ID の全バージョンを削除します。
commit()バッファリングされた書き込みをフラッシュし、すべての保留中の変更を検索可能にします。
flush_wal()WAL の永続性バリアを強制します。WAL 同期ポリシー / 永続性を参照してください。
search(query, *, limit=10, offset=0, highlight=None, rescore=None) -> list[SearchResult]検索クエリを実行します。rescore には、MultiVector フィールドに対する late interaction で上位の結果を並べ替える LateInteractionRescore を渡します(Issue #1351)。query が SearchRequest の場合はリクエスト自身の rescore を使い、このキーワードは無視されます。
search_batch(queries, *, limit=10, offset=0, highlight=None) -> list[list[SearchResult]]独立した複数の検索を 1 回の呼び出しで実行します。各クエリは内部の tokio ランタイム上で並列に dispatch されます。results[i] は queries[i] に対応し、入力が空のリストの場合は [] を返します。highlight はバッチ内のすべてのクエリに同一に適用されます。rescore キーワードはありません。再採点が必要なクエリには、rescore= を指定した SearchRequest を渡してください。
stats() -> dictインデックス統計(document_count、vector_fields)を返します。

search の query 引数

query パラメータは以下のいずれかを受け付けます:

  • DSL 文字列(例: "title:hello"、"content:\"memory safety\"")
  • Lexical クエリオブジェクト(TermQuery、PhraseQuery、BooleanQuery など)
  • Vector クエリオブジェクト(VectorQuery、VectorTextQuery)
  • SearchRequest(完全な制御が必要な場合)

search_batch の queries リストの各要素も同じ種類の値を受け付けます。DSL 文字列・クエリオブジェクト・SearchRequest を 1 つのバッチ内で混在させることもできます。

ハイライト

search/search_batch の highlight パラメータ(Issue #1134)は、各ヒットの SearchResult.highlights にフィールドごとのハイライト済みフラグメントを要求します。以下のいずれかを受け付けます。

  • フィールド名のリスト: highlight=["body"]
  • 辞書: 必須の "fields" キーに加えて、HighlightConfig の任意の設定(max_fragments、fragment_size、tag、css_class、require_field_match、max_analyzed_chars、return_entire_field_if_no_highlight)を指定 — 例: highlight={"fields": ["body"], "tag": "em", "max_fragments": 2}
results = index.search("body:rust", highlight=["body"])
print(results[0].highlights)  # {"body": ["<mark>Rust</mark> is a systems programming language."]}

ハイライトは search/search_batch に渡したクエリ(または SearchRequest.query/lexical_query、下記参照)に従い、stored: true のテキストフィールドのみハイライト可能です。存在しない、保存されていない、テキスト型でないフィールドは黙ってスキップされます。highlight を省略すると、すべての結果の highlights は空のままになります。同じ highlight= キーワードは SearchRequest でも使用できます。

WAL 同期ポリシー / 永続性

永続インデックスでは、すべての書き込みが先行書き込みログ(WAL)に追記されます。 デフォルトでは WAL はすべてのレコードごとに fsync されるため、呼び出しが 返った時点で各書き込みは完全に永続化されます。コンストラクタはオプションの wal_sync_policy を受け付け、永続性を一部犠牲にして書き込みスループットを 向上させることができます。また flush_wal() で必要なときに永続性バリアを 強制できます。

class WalSyncPolicy:
    @staticmethod
    def per_record() -> WalSyncPolicy: ...
    @staticmethod
    def group(
        max_records: int | None = None,
        max_bytes: int | None = None,
        max_interval_ms: int | None = None,
    ) -> WalSyncPolicy: ...
コンストラクタ説明
WalSyncPolicy.per_record()デフォルト。WAL レコードごとに fsync し、書き込みごとに完全に永続化します。
WalSyncPolicy.group(...)グループコミット。複数の書き込みにまたがって fsync をまとめます。

group() のパラメータ(いずれもキーワード指定可。None はデフォルトを維持):

パラメータデフォルト説明
max_records1024この件数のレコードが蓄積されたらフラッシュします。
max_bytes1048576(1 MiB)この量の未同期バイトが蓄積されたらフラッシュします。
max_interval_msNone任意の定期フラッシュタイマー(ミリ秒)。None でタイマー無効。

グループコミットでは、max_records または max_bytes のいずれかに達した 時点で WAL がフラッシュされ、commit() 時にも必ずフラッシュされます。 クラッシュ時には最後の未同期バッチまでを失う可能性があります — これは SQLite の synchronous = NORMAL と同じトレードオフです。完全な commit() を 行わずにこれまで書き込んだ内容をディスクへ強制するには flush_wal() を 呼び出します。

メソッド説明
flush_wal()今すぐ WAL の永続性バリアを強制します。同期メソッドで None を返します。
import laurus

# 1 秒の定期フラッシュタイマー付きでグループコミットを有効化します。
policy = laurus.WalSyncPolicy.group(max_records=4096, max_interval_ms=1000)
index = laurus.Index(path="./myindex", wal_sync_policy=policy)

for i in range(10_000):
    index.put_document(f"doc{i}", {"title": f"Document {i}"})

# まだコミットせずに永続性バリアを強制します。
index.flush_wal()

index.commit()  # WAL もフラッシュされます

wal_sync_policy を省略する(または WalSyncPolicy.per_record() を渡す)と、 デフォルトの完全に永続的な動作が維持されます。

コミットポリシー / 自動コミット

コミットはバッファリングされた書き込みをストアへ materialize し、すべての 保留中の変更を検索可能にします。デフォルトでは Index は自動コミットを 行わないため、呼び出し側がすべての commit() を明示的に実行します。 コンストラクタはオプションの commit_policy を受け付け、一定件数の ドキュメントを適用するごと、または一定時間ごとにエンジンが自動的に コミットするようにできます。

class CommitPolicy:
    @staticmethod
    def manual() -> CommitPolicy: ...
    @staticmethod
    def every_docs(n: int) -> CommitPolicy: ...
    @staticmethod
    def interval_ms(ms: int) -> CommitPolicy: ...
コンストラクタ説明
CommitPolicy.manual()デフォルト。自動コミットなし。呼び出し側がすべての commit() を実行します。
CommitPolicy.every_docs(n)n 件のドキュメントを適用するごとに自動コミットします。
CommitPolicy.interval_ms(ms)バックグラウンドタイマーにより、少なくとも ms ミリ秒ごとに自動コミットします(デフォルト: なし)。ネイティブ専用で、wasm では no-op です。

every_docs(n) は、単体(put_document、add_document)とバッチ (put_documents、add_documents)の両方の取り込みにまたがって適用済み ドキュメントを数え、n 件ごとに自動コミットします — 1 つのバッチの 内部でも同様です。every_docs(0) も有効で、自動コミットを無効化するため manual() と等価になります。

interval_ms(ms) は every_docs(n) の時間ベースの対応版です。 バックグラウンドタイマーが少なくとも ms ミリ秒ごとにコミットするため、 取り込みがアイドル状態でも末尾の部分バッチがコミットされます。この ファクトリは ネイティブ専用 です — wasm にはバックグラウンドスレッドが 存在しないため、エンジンはこれを no-op として扱います。値の構築は できますが、WebAssembly 上ではタイマーによるコミットは発生しません。

commit_policy は wal_sync_policy と直交します。wal_sync_policy は WAL の fsync 永続性を制御するのに対し、commit_policy はストアが保留中の変更を 検索可能な状態へ materialize するタイミングを制御します。一方を設定しても 他方には影響しません。

import laurus

# 100 件のドキュメントを適用するごとに自動コミットします。
index = laurus.Index(
    path="./myindex",
    commit_policy=laurus.CommitPolicy.every_docs(100),
)

for i in range(1_000):
    index.put_document(f"doc{i}", {"title": f"Document {i}"})
# エンジンはすでに 10 回コミットしています(100 件ごとに 1 回)。

commit_policy を省略する(または CommitPolicy.manual() を渡す)と、 デフォルトの手動コミットの動作が維持されます。


Schema

Index のフィールドとインデックスタイプを定義します。

class Schema:
    def __init__(self) -> None: ...

フィールドメソッド

メソッド説明
add_text_field(name, *, stored=True, indexed=True, term_vectors=True, doc_values=True, multi_valued=False, position_increment_gap=100, analyzer=None)全文フィールド(転置インデックス、BM25)。term_vectors はタームの位置を保存するかどうかを制御し、フレーズクエリ・スパンクエリが読み取ります。doc_values は値を DocValues(ソート・ファセット・集計が読み取る列指向ストア)にもコピーするかどうかを制御します(Issue #1047)。stored=True の場合のみ有効です。multi_valued=True で list[str] を受け付けます(Issue #1175): term クエリはいずれかの要素がタームを含めばマッチし、フレーズクエリは slop が position_increment_gap(デフォルト 100。0 にすると要素を連結したものとして付番)に達しない限り 2 つの要素をまたぎません。値は list[str] として読み戻されます。analyzer には組込名("standard" / "english" / "keyword" / "simple" / "noop"、または add_analyzer で登録したカスタム名)か、{"language": "japanese", "mode": "normal", "dict": "/var/lib/lindera/ipadic"} のようなパラメータ付きプリセットの dict を渡せます。文字列単独の "japanese" は Lindera 辞書パスが必須なため拒否されます。
add_integer_field(name, *, stored=True, indexed=True, multi_valued=False, doc_values=True)64 ビット整数フィールド。multi_valued=True で整数配列を受け付け(範囲クエリは “any match”)。doc_values は上記を参照。
add_float_field(name, *, stored=True, indexed=True, multi_valued=False, doc_values=True)64 ビット浮動小数点フィールド。multi_valued=True で浮動小数点配列を受け付け(範囲クエリは “any match”)。doc_values は上記を参照。
add_boolean_field(name, *, stored=True, indexed=True, multi_valued=False, doc_values=True)ブールフィールド。multi_valued=True で list[bool] を受け付け(flags:true のような term クエリはいずれかの要素が値と等しければマッチ。値は list[bool] として読み戻されます)。doc_values は上記を参照。
add_bytes_field(name, *, stored=True, multi_valued=False)生バイトフィールド。doc_values オプションはありません —— Bytes の値は設定にかかわらず DocValues に一切書き込まれないためです。multi_valued=True で list[bytes] を受け付けます(Issue #1176)。Bytes はそもそもインデックスされないため、他の multi_valued オプションと異なりクエリ一致の意味論はなく、保存時の形と取り込み時の許容個数を変えるだけです。値は list[bytes] として読み戻されます(MIME は保持されません)。
add_geo_field(name, *, stored=True, indexed=True, multi_valued=False, doc_values=True)地理座標フィールド(緯度/経度)。multi_valued=True で (lat, lon) タプルのリストを受け付け(距離 / バウンディングボックスクエリはいずれかのポイントが条件を満たせばマッチ。値はタプルのリストとして読み戻されます)。doc_values は上記を参照。
add_geo3d_field(name, *, stored=True, indexed=True, multi_valued=False, doc_values=True)3D ECEF カルテシアン座標フィールド(x, y, z はメートル)。multi_valued=True で (x, y, z) タプルのリストを受け付け(距離 / バウンディングボックス / nearest クエリはいずれかのポイントが条件を満たせばマッチ。値はタプルのリストとして読み戻されます)。詳細は Geo3d の概念。doc_values は上記を参照。
add_datetime_field(name, *, stored=True, indexed=True, multi_valued=False, doc_values=True)UTC 日時フィールド。multi_valued=True で datetime.datetime / str のリストを受け付け(範囲クエリはいずれかの時刻が条件を満たせばマッチ。値は UTC の RFC 3339 文字列の list[str] として読み戻されます)。doc_values は上記を参照。
add_hnsw_field(name, dimension, *, distance="cosine", m=16, ef_construction=200, quantizer=None, subvector_count=None, rerank_storage=None, embedder=None, pq_codebook_path=None, base_weight=1.0)HNSW 近似最近傍ベクトルフィールド。base_weight は他の vector フィールドと同時に検索されたときの相対的なスコアリング優先度(Issue #1084)。ウェイトを参照。
add_flat_field(name, dimension, *, distance="cosine", embedder=None, base_weight=1.0)Flat(総当たり)ベクトルフィールド。
add_ivf_field(name, dimension, *, distance="cosine", n_clusters=100, n_probe=1, embedder=None, base_weight=1.0)IVF 近似最近傍ベクトルフィールド。
add_multi_vector_field(name, dimension, *, distance="cosine", storage="f32", embedder=None)文書ごとに可変個のトークンベクトル(ColBERT の埋め込みなど)を保持する MultiVector フィールド。late interaction による再採点だけが読み取ります(Issue #1351)。ANN 索引は持たず、ベクトル検索の対象にはなりません。distance は "cosine"(デフォルト。書き込み時にベクトルを L2 正規化)か "dot_product" のどちらかで、dimension は 0 より大きい必要があります。どちらもこのメソッドの呼び出し時に検査し、不正なら ValueError を送出します。storage は各トークンベクトルのディスク上の要素種別を指定します — "f32"(デフォルト、正確)、"f16"(2倍小さい)、"int8"(約4倍小さいが非可逆圧縮)のいずれかで、認識できない値も ValueError を送出します。embedder にはトークン単位のエンベダー("candle_colbert"。エンベダータイプを参照)の名前を指定し、テキストの値と再採点のテキストクエリを埋め込みます。文書はこのフィールドに float のリストのリスト(フィールド値の型マッピングを参照)か、embedder がある場合はテキストを与えます。トークンベクトルはベクトルストアにだけ保持されるため、get_documents や検索結果には含まれません。詳細は MultiVector フィールドを参照。

ベクトル量子化とリランクストレージ(HNSW フィールド):

  • quantizer — "scalar_8bit"(デフォルト、4 倍圧縮)または高圧縮率の "product_quantization"。Product quantization では subvector_count(dimension を割り切れる値)が必須です。
  • rerank_storage — "f32" を指定すると完全精度の *.hnsw.f32 サイドカーを書き出し、厳密な Stage-2 リランクを有効化します。省略すると int8 のみのセグメントを維持します。
  • pq_codebook_path — 共有 PQ codebook のストレージ相対ファイル名(Issue #631)。laurus train pq-codebook CLI コマンドで一度だけ学習します。quantizer="product_quantization" との組み合わせでのみ意味を持ち、以後の commit は segment ごとの k-means 再学習の代わりに学習済み codebook で encode します。省略すると segment ごとの学習を維持します。

上記のどの add_*_field メソッドも、name が _(_id を除く)で始まる場合は ValueError を送出し、フィールドを追加しない。from_toml / from_toml_file で読み込むスキーマは引き続きそのようなフィールドを受け付けるため、永続化済みのスキーマは読み込めるが、そのスキーマから新しい Index を作成すると ValueError になる。詳細はフィールド命名規則を参照。

その他のメソッド

メソッド説明
add_embedder(name, config)名前付きエンベダー定義を登録します。config は "type" キーを持つ辞書で(下記参照)、スキーマ TOML の [embedders] テーブルと同じ規則で読み取ります。config が辞書でない場合、"type" が無いか未知の場合、必須キーが無い場合は ValueError(invalid embedder config: ...)を送出します。
add_analyzer(name, tokenizer, *, char_filters=None, token_filters=None)カスタムアナライザ定義を登録します。tokenizer は必須、char_filters/token_filters は省略可能な辞書のリストです。各辞書はスキーマ TOML/JSON 形式と同じ {"type": "..."} 形式です(下記参照)。組み込みアナライザ用に予約された名前(standard、keyword、english、simple、noop)は ValueError になり、その名前を定義したスキーマ(from_toml で読み込んだものなど)から新しい Index を作る場合も同じです。正規表現の妥当性など意味的な検証は、このメソッド呼び出し時点ではなく Index 構築時に行われます。
analyzer_names()add_analyzer で登録された、または TOML から読み込まれたカスタムアナライザの名前一覧を返します。
Schema.from_toml(toml_str) (静的メソッド)laurus-cli create index --schema と同じ形式の TOML 文字列からスキーマを読み込みます。
Schema.from_toml_file(path) (静的メソッド)TOML ファイルからスキーマを読み込みます(path は str または os.PathLike を受け付けます)。
to_toml()このスキーマを laurus-cli と同じ形式の TOML 文字列にシリアライズします。
to_toml_file(path)このスキーマを TOML ファイルに書き込みます。
set_default_fields(fields)デフォルト検索フィールドを設定(文字列のリスト)。
set_dynamic_field_policy(policy)未宣言フィールドの扱いを設定。policy は "strict" / "dynamic"(デフォルト)/ "ignore"。詳細は下記を参照。
dynamic_field_policy()現在のポリシーを小文字の文字列で返す。
field_names()全フィールド名を返す。

Dynamic field policy(動的フィールドポリシー)

ドキュメントに含まれるがスキーマに宣言されていないフィールドの扱いを制御します:

  • "strict" — ドキュメントを拒否
  • "dynamic"(デフォルト)— 各未宣言フィールドの型を推論してスキーマに追加。警告: integer フィールドに入ってきた float 値は静かに切り捨てられます(3.14 → 3)。厳密さが必要なら "strict" を使用してください
  • "ignore" — 未宣言フィールドを静かに破棄

詳細な挙動マトリクスは スキーマとフィールド を参照してください。

エンベダータイプ

各型の説明を含む正規のリファレンスは スキーマフォーマットリファレンス → エンベダー を参照してください。

"type"必須キーFeature Flag
"precomputed"–(常に利用可能)
"candle_bert""model"embeddings-candle
"candle_clip""model"embeddings-multimodal
"openai""model"embeddings-openai
"candle_colbert""model"embeddings-candle

"candle_colbert" はトークン単位のエンベダーです。トークンごとに 1 本のベクトルを生成し、MultiVector フィールド(add_multi_vector_field)でだけ使えます。省略可能なキーとして "revision"(モデルリポジトリのブランチ・タグ・コミット)、"query_maxlen"、"doc_maxlen" も受け付けます。各キーのデフォルトは スキーマフォーマットリファレンス → エンベダー を参照してください。

schema = laurus.Schema()
schema.add_text_field("body")
schema.add_embedder("colbert", {"type": "candle_colbert", "model": "colbert-ir/colbertv2.0"})
schema.add_multi_vector_field("body_colbert", dimension=128, embedder="colbert")

アナライザコンポーネント

add_analyzer(name, tokenizer, *, char_filters=None, token_filters=None) と [analyzers.<name>] TOML セクションで使用します。tokenizer は単一の辞書、 char_filters/token_filters は辞書のリストで、リストの順序どおりに適用されます。

各コンポーネントの説明を含む正規のリファレンスは スキーマフォーマットリファレンス → アナライザ を参照してください。

トークナイザ(tokenizer、必ず1つ):

"type"必須キー省略可能キー
"whitespace"––
"unicode_word"––
"regex"–"pattern"(デフォルト \w+)、"gaps"(デフォルト false)
"ngram""min_gram"、"max_gram"–
"lindera""mode"、"dict""user_dict"
"whole"––

文字フィルタ(char_filters、トークン化前の生テキストに適用):

"type"必須キー省略可能キー
"unicode_normalization""form"("nfc"/"nfd"/"nfkc"/"nfkd")–
"pattern_replace""pattern"、"replacement"–
"mapping""mapping"(文字列置換の辞書)–
"japanese_iteration_mark"–"kanji"(デフォルト true)、"kana"(デフォルト true)

トークンフィルタ(token_filters、トークン化後のトークン列に適用):

"type"必須キー省略可能キー
"lowercase"––
"stop"–"words"(デフォルト: 英語のストップワード)
"stem"–"stem_type"("porter"/"simple"/"identity")
"boost""boost"–
"limit""limit"–
"strip"––
"remove_empty"––
"flatten_graph"––
schema = laurus.Schema()
schema.add_analyzer(
    "ja_ipadic",
    {"type": "lindera", "mode": "normal", "dict": "/var/lib/lindera/ipadic"},
    char_filters=[
        {"type": "unicode_normalization", "form": "nfkc"},
        {"type": "japanese_iteration_mark"},
    ],
    token_filters=[{"type": "lowercase"}],
)
schema.add_text_field("title", analyzer="ja_ipadic")

距離メトリクス

値説明
"cosine"コサイン類似度(デフォルト)
"euclidean"ユークリッド距離
"dot_product"内積
"manhattan"マンハッタン距離
"angular"角度距離

クエリクラス

TermQuery

TermQuery(field: str, term: str)

指定フィールドに完全一致する語句を含むドキュメントを検索します。

PhraseQuery

PhraseQuery(field: str, terms: list[str])

指定した語句が順序どおりに含まれるドキュメントを検索します。

FuzzyQuery

FuzzyQuery(field: str, term: str, *, max_edits: int = 2)

編集距離が max_edits 以内の近似一致を検索します。max_edits はキーワード専用引数です。

WildcardQuery

WildcardQuery(field: str, pattern: str)

ワイルドカードパターン検索。* は任意の文字列、? は任意の1文字に一致します。

NumericRangeQuery

NumericRangeQuery(field: str, *, min: int | float | None = None, max: int | float | None = None)

[min, max] の範囲内の数値を検索します。開いた境界には None を指定する (または省略する)と開放されます。min と max はキーワード専用引数です。 数値型(整数または浮動小数点)は min/max の Python 型から推論されます。

DateTimeRangeQuery

DateTimeRangeQuery(
    field: str, *,
    min: str | datetime.datetime | datetime.date | None = None,
    max: str | datetime.datetime | datetime.date | None = None,
)

[min, max] の範囲内(両端を含む)の DateTime 値を検索します。開いた境界には None を指定する(または省略する)と開放されます。min と max はキーワード 専用引数です。境界は Query DSL が受け付ける任意の形式の str リテラル(RFC 3339 の "2024-01-01T09:00:00+09:00"(UTC に正規化)、オフセットなしの "YYYY-MM-DDTHH:MM:SS[.fff]"(UTC)、"YYYY-MM-DD"(その日の 0 時 UTC))、 または datetime.datetime / datetime.date(isoformat() で変換。naive な datetime は UTC として扱われます)です。不正な境界は構築時に ValueError を 送出します。クエリオブジェクトを受け付ける場所(Index.search、BooleanQuery、 SearchRequest)ならどこでも使用できます。例: index.search(laurus.DateTimeRangeQuery("created_at", min="2024-01-01", max="2024-12-31"))

GeoDistanceQuery

GeoDistanceQuery.within_radius(
    field: str, lat: float, lon: float, distance_m: float,
)

地理的距離検索(半径指定)。指定した地点から distance_m メートル以内の (lat, lon) 座標を持つドキュメントを返します。

GeoBoundingBoxQuery

GeoBoundingBoxQuery.within_bounding_box(
    field: str,
    min_lat: float, min_lon: float,
    max_lat: float, max_lon: float,
)

地理的範囲(バウンディングボックス)検索。軸並行 [min_lat, max_lat] × [min_lon, max_lon] 内の (lat, lon) 座標を持つドキュメントを返します。

Geo3dDistanceQuery

Geo3dDistanceQuery.within_sphere(
    field: str, x: float, y: float, z: float, distance_m: float,
)

3D ECEF 座標フィールドへの球距離検索。中心 (x, y, z) から distance_m メートル以内 の座標を持つドキュメントを返します。ECEF の理論については Geo3d の概念 を参照。

Geo3dBoundingBoxQuery

Geo3dBoundingBoxQuery.within_box(
    field: str,
    min_x: float, min_y: float, min_z: float,
    max_x: float, max_y: float, max_z: float,
)

軸並行 3D 範囲(AABB)検索。[min_x, max_x] × [min_y, max_y] × [min_z, max_z] 内 にある ECEF 座標を持つドキュメントを返します。

Geo3dNearestQuery

Geo3dNearestQuery.k_nearest(
    field: str,
    x: float, y: float, z: float,
    k: int,
    *,
    initial_radius_m: float | None = None,
    max_radius_m: float | None = None,
)

3D ECEF 座標フィールドへの k 最近傍検索。(x, y, z) から最も近い k 件のドキュ メントを返します。initial_radius_m / max_radius_m は反復拡張サーチの探索コーン を調整します。

BooleanQuery

bq = BooleanQuery()
bq.must(query)
bq.should(query)
bq.must_not(query)

複合ブールクエリ。引数なしでコンストラクタを呼び出し、must / should / must_not メソッドで節を一つずつ追加します。各メソッドは任意のクエリ オブジェクト(ネストされた BooleanQuery も含む)を受け付けます。

must 節はすべて一致する必要があり、must_not 節は一致してはなりません。 should 節はスコアリングに寄与し、must 節が無い場合は少なくとも1つが 一致する必要があります。

SpanQuery

# 単一語句
SpanQuery.term(field: str, term: str)

# Near: slop 位置以内の語句
SpanQuery.near(field: str, terms: list[str], *, slop: int = 0, ordered: bool = True)

# ネストされた SpanQuery 句を使った Near
SpanQuery.near_spans(field: str, clauses: list[SpanQuery], *, slop: int = 0, ordered: bool = True)

# Containing: big スパンが little スパンを含む
SpanQuery.containing(field: str, big: SpanQuery, little: SpanQuery)

# Within: 最大距離での include スパンと exclude スパン
SpanQuery.within(field: str, include: SpanQuery, exclude: SpanQuery, distance: int)

位置・近接スパンクエリ。静的ファクトリメソッドで構築します。near は語句 文字列のリストを受け取り、near_spans はネスト式のために SpanQuery オブジェクトのリストを受け取ります。slop と ordered はキーワード専用 引数です。

VectorQuery

VectorQuery(field: str, vector: list[float])

事前計算済みエンベディングベクトルを使った近似最近傍検索を行います。

VectorTextQuery

VectorTextQuery(field: str, text: str)

クエリ時に text をエンベディングに変換してベクトル検索を行います。インデックスにエンベダーの設定が必要です。


SearchRequest

高度な制御が必要な場合の完全なリクエストクラスです。

class SearchRequest:
    def __init__(
        self,
        *,
        query=None,
        lexical_query=None,
        vector_query=None,
        filter_query=None,
        fusion=None,
        limit: int = 10,
        offset: int = 0,
        highlight=None,
        rescore: LateInteractionRescore | None = None,
    ) -> None: ...
パラメータ説明
queryDSL 文字列または単一クエリオブジェクト。lexical_query / vector_query と排他的。
lexical_query明示的なハイブリッド検索の Lexical コンポーネント。
vector_query明示的なハイブリッド検索の Vector コンポーネント。
filter_queryスコアリング後に適用する Lexical フィルター。
fusionフュージョンアルゴリズム(RRF または WeightedSum)。両コンポーネント指定時のデフォルトは RRF(k=60)。
limit最大結果件数(デフォルト 10)。
offsetページネーションオフセット(デフォルト 0)。
highlightIndex.search の highlight パラメータと同じリストまたは辞書の形式(Issue #1134)。ハイライトを参照。
rescoreこのリクエストの上位の結果に適用する LateInteractionRescore(Issue #1351)。どのクエリの形を指定した場合でも適用されます。SearchRequest を渡すと Index.search の rescore キーワードは無視され、こちらが使われます。

LateInteractionRescore

検索の上位の結果を late interaction(ColBERT の MaxSim)で再採点します(Issue #1351)。Index.search または SearchRequest の rescore= に渡します。

class LateInteractionRescore:
    def __init__(
        self,
        field: str,
        query: str | list[list[float]],
        *,
        window_size: int | None = None,
    ) -> None: ...

    @property
    def window_size(self) -> int: ...
パラメータ型デフォルト説明
fieldstr–MultiVector フィールド(add_multi_vector_field を参照)。
querystr | list[list[float]]–クエリのテキスト、またはクエリのトークンベクトル。テキストはフィールドのトークン単位のエンベダー("candle_colbert")が埋め込みます。トークンベクトルは、文書のトークンベクトルと同じモデルで計算したものを渡します。ベクトルの要素には整数も使えます。
window_sizeint | NoneNone(100)再採点する 1 段目の上位の結果の件数。1..=10,000。キーワード専用引数です。

window_size プロパティは、再採点で使う window の件数を返します(省略時は 100)。

1 段目(lexical・vector・ハイブリッド)の上位 window_size 件を、フィールドに対する MaxSim の降順に並べ替えます。再採点した結果の score は MaxSim の値です。フィールドにトークンベクトルを持たない window 内の結果は 1 段目の順で続き、window の外の結果は 1 段目の順とスコアのまま最後に続きます。offset と limit は、この再採点済みの順位から切り出されます。並び順・類似度・コストの詳細は ベクトル検索 → Late Interaction による再採点 を参照してください。

エラー:

  • query が str でもリストのリストでもない場合、またはトークンベクトルに bool か str が含まれる場合は、構築時に TypeError を送出します。
  • それ以外の不正な値は、Index.search が検索を始める前に検査し、ValueError(Invalid argument: rescore: ...)を送出します。対象は、field が MultiVector フィールドでない場合、クエリがフィールドの次元で有限値のベクトルを 1〜1,024 本持たない場合、window_size が 1..=10,000 の範囲外の場合、テキストのクエリが空かフィールドにトークン単位のエンベダーがない場合です。
import laurus

schema = laurus.Schema()
schema.add_text_field("title")
schema.add_multi_vector_field("tokens", dimension=2, distance="dot_product")

index = laurus.Index(schema=schema)
index.put_document("a", {"title": "rust", "tokens": [[0.1, 0.0]]})
index.put_document("b", {"title": "rust language", "tokens": [[0.9, 0.2]]})
index.commit()

rescore = laurus.LateInteractionRescore("tokens", [[1.0, 0.0], [0.0, 1.0]], window_size=50)
results = index.search("title:rust", rescore=rescore)  # "b"(MaxSim 1.1)が "a"(0.1)より先

# 同じ再採点を SearchRequest で指定する(search_batch でも使える)
request = laurus.SearchRequest(query="title:rust", rescore=rescore, limit=5)
results = index.search(request)

フィールドに "candle_colbert" のエンベダーがあれば、文書はフィールドにテキストを与えられ、クエリもテキストで渡せます: laurus.LateInteractionRescore("body_colbert", "how do lifetimes work")。


SearchResult

Index.search() が返すクラスです。

class SearchResult:
    id: str          # 外部ドキュメント識別子
    score: float     # 関連性スコア
    document: dict | None  # 取得されたフィールド値。stored=False の場合は None
    highlights: dict[str, list[str]]  # 要求したフィールドごとのハイライト済みフラグメント

highlights は highlight で指定した各フィールドをハイライト済みフラグメント(最も良いものが先頭)にマッピングします。ハイライトされなかったフィールドは辞書に現れず、highlight を要求しなかった場合 highlights は {} になります。詳細はハイライトを参照してください。

rescore を指定した場合、再採点した結果の score は MaxSim の値になり、再採点の window の外の結果は 1 段目のスコアのままです。詳細は LateInteractionRescore を参照してください。


フュージョンアルゴリズム

RRF

RRF(k: float = 60.0)

逆順位フュージョン(Reciprocal Rank Fusion)。Lexical と Vector の結果リストを順位位置によってマージします。k は平滑化定数で、値が大きいほど上位ランクの影響が小さくなります。

WeightedSum

WeightedSum(lexical_weight: float = 0.5, vector_weight: float = 0.5)

両スコアリストをそれぞれ正規化した後、lexical_weight * lexical_score + vector_weight * vector_score として結合します。


テキスト解析

SynonymDictionary

class SynonymDictionary:
    def __init__(self) -> None: ...
    def add_synonym_group(self, synonyms: list[str]) -> None: ...

WhitespaceTokenizer

class WhitespaceTokenizer:
    def __init__(self) -> None: ...
    def tokenize(self, text: str) -> list[Token]: ...

SynonymGraphFilter

class SynonymGraphFilter:
    def __init__(
        self,
        dictionary: SynonymDictionary,
        keep_original: bool = True,
        boost: float = 1.0,
    ) -> None: ...
    def apply(self, tokens: list[Token]) -> list[Token]: ...

Token

class Token:
    text: str
    position: int
    start_offset: int
    end_offset: int
    boost: float
    stopped: bool
    position_increment: int
    position_length: int
    token_type: str | None

start_offset と end_offset は、元テキストの UTF-8 バイトオフセットです。非 ASCII のテキストでは str の添字と一致しないため、エンコードしたバイト列を切り出します: text.encode()[tok.start_offset:tok.end_offset].decode()。

token_type は "alphanum"、"num"、"cjk"、"katakana"、"hiragana"、"hangul"、"punctuation"、"whitespace"、"synonym"、"email"、"url"、"other" のいずれか、または None です。SynonymGraphFilter.apply は各トークンのオフセットと種別を保ち、挿入する同義語には種別 "synonym" と、置き換える語のオフセットを付けます。


フィールド値の型マッピング

Python の値は自動的に Laurus の DataValue 型に変換されます:

Python 型Laurus 型備考
NoneNull
boolBoolint より先にチェック
intInt64
floatFloat64
strText
bytesBytes
list[bool]BoolArray多値ブールフィールド。bool は int のサブクラスのため list[int] の規則より先にチェック。フィールドに multi_valued=True が必要
list[bytes]BytesArray多値バイトフィールド(Issue #1176)。各要素は単一の bytes 値と同じ直接バイト経路をたどるため、MIME は常に None。Bytes はそもそもインデックスされないため、クエリ一致の意味論はなく保存時の形を変えるだけ。フィールドに multi_valued=True が必要
list[int]Int64Array多値整数フィールド(bool のリストは代わりに BoolArray になり、多値の Float / Integer フィールドではコアが 0/1 に拡張する)。ベクトルフィールドではリストを f32 にキャスト。空リストは空の Int64Array
list[float | int]Float64Array多値浮動小数点フィールド(整数は拡張)。ベクトルフィールドではリストを f32 にキャスト
list[list[float | int]]VectorArrayMultiVector フィールドのトークンベクトル(Issue #1351)。内側のリストが 1 トークンに対応する(例: {"tokens": [[0.1, 0.2], [0.3, 0.4]]})。整数は拡張し、bool や str の要素は TypeError。ベクトルの本数と次元はドキュメントの書き込み時にフィールドと照合する(長さの揃わないリストなどは ValueError)。get_documents や検索結果には含まれない
(lat, lon) タプルGeo2 つの float 値
(x, y, z) タプルGeo3d3 つの float 値(ECEF 直交座標系、メートル単位)
list[(lat, lon)]GeoArray(lat, lon) タプルのリスト。フィールドに multi_valued=True が必要
list[(x, y, z)]GeoEcefArray(x, y, z) タプルのリスト。フィールドに multi_valued=True が必要
datetime.datetimeDateTimeisoformat() 経由で変換
list[datetime.datetime | str](datetime を 1 つ以上含む)DateTimeArray各要素を単一の日時と同じ規則でパース(オフセット付き RFC 3339 / ISO 8601、または naive な YYYY-MM-DDTHH:MM:SS を UTC として扱う。isoformat() を持つオブジェクトは先に変換)。日時でない要素は ValueError。フィールドに multi_valued=True が必要
list[str]DateTimeArray または TextArray全要素が日時としてパースできれば(上記と同じ形式)DateTimeArray、そうでなければ TextArray(Issue #1175。list[str] として読み戻される)。フィールドに multi_valued=True が必要