DashText は、DashVector で推奨される疎ベクトルエンコーダーです。セマンティック検索は意味を捉えることができますが、キーワードの完全一致を見逃すことがあります。ドメイン固有の用語、製品名、またはエラーコードなどがその例です。DashText は、BM25 アルゴリズムを使用してテキストを疎ベクトルに変換することで、このギャップを埋めます。これらの疎ベクトルを DashVector の密ベクトルと組み合わせることで、キーワードを意識したセマンティック検索、つまりセマンティックな関連性とキーワードの正確性を両立させた取得を実行できます。
主要な例
以下の Python スニペットは、コレクションの作成、ドキュメントのエンコードと挿入、ハイブリッドクエリの実行という、最小限のエンドツーエンドのフローを示しています。
import dashvector
from dashtext import SparseVectorEncoder
from dashvector import Doc
# Connect to DashVector
client = dashvector.Client(
api_key='YOUR_API_KEY',
endpoint='YOUR_CLUSTER_ENDPOINT'
)
# Create a collection with dot product metric (required for sparse vectors)
client.create('hybrid_collection', dimension=4, metric='dotproduct')
collection = client.get('hybrid_collection')
# Build a sparse vector encoder and encode a document
encoder = SparseVectorEncoder.default()
doc_sparse = encoder.encode_documents("Your document text here.")
# Insert the document with both dense and sparse vectors
collection.insert(Doc(
id='doc1',
vector=[0.1, 0.2, 0.3, 0.4],
sparse_vector=doc_sparse
))
# Search with both dense and sparse vectors
query_sparse = encoder.encode_queries("Your search query here.")
results = collection.query(
vector=[0.1, 0.1, 0.1, 0.1],
sparse_vector=query_sparse
)以下のセクションでは、Python と Java の両方の例を用いて、各ステップを詳しく説明します。
前提条件
開始する前に、以下をご確認ください。
利用可能な API キーとエンドポイントを持つ DashVector クラスター。詳細については、「ベクターの概要」をご参照ください。
Python または Java SDK がインストール済みであること (Python の場合は
dashvectorおよびdashtextパッケージ)
このガイドのすべての例では、簡潔にするために 4 次元の密ベクトルを使用しています。本番環境では、ご利用の埋め込みモデルの出力に合わせてディメンションを設定してください。
ステップ 1:疎ベクトルをサポートするコレクションの作成
疎ベクトルには、ドット積距離メトリックが必要です。疎ベクトルのサポートを有効化するには、metric='dotproduct' を指定してコレクションを作成します。
Python
import dashvector
client = dashvector.Client(
api_key='YOUR_API_KEY',
endpoint='YOUR_CLUSTER_ENDPOINT'
)
assert client
# Create a collection with dot product metric (required for sparse vectors)
ret = client.create('hybrid_collection', dimension=4, metric='dotproduct')
assert ret
collection = client.get('hybrid_collection')
assert collectionJava
import com.aliyun.dashvector.DashVectorClient;
import com.aliyun.dashvector.DashVectorCollection;
import com.aliyun.dashvector.models.requests.CreateCollectionRequest;
import com.aliyun.dashvector.models.responses.Response;
import com.aliyun.dashvector.proto.CollectionInfo;
DashVectorClient client =
new DashVectorClient("YOUR_API_KEY", "YOUR_CLUSTER_ENDPOINT");
CreateCollectionRequest request = CreateCollectionRequest.builder()
.name("hybrid_collection")
.dimension(4)
.metric(CollectionInfo.Metric.dotproduct)
.dataType(CollectionInfo.DataType.FLOAT)
.build();
Response<Void> response = client.create(request);
System.out.println(response);
DashVectorCollection collection = client.get("hybrid_collection");疎ベクトルは、ドット プロダクト メトリック (metric='dotproduct') を使用するコレクションでのみサポートされます。
コードが正しく実行されるように、YOUR_API_KEY をご自身の API キーに、YOUR_CLUSTER_ENDPOINT をご自身のクラスターのエンドポイントに置き換えてください。
ステップ 2:疎ベクトルエンコーダーの構築
DashText では、SparseVectorEncoder を作成するための 2 つのアプローチを提供しています:汎用テキスト向けの組み込みエンコーダー、およびドメイン固有の用語に対するより高い精度を実現するための独自のコーパスでトレーニングされたカスタムエンコーダーです。
組み込みエンコーダーの使用
組み込みエンコーダーは、中国語版 Wikipedia コーパスで事前学習されており、中国語のテキスト分割には Jieba を使用します。追加のトレーニングは不要です。
Python
from dashtext import SparseVectorEncoder
encoder = SparseVectorEncoder.default()Java
import com.aliyun.dashtext.encoder.SparseVectorEncoder;
SparseVectorEncoder encoder = SparseVectorEncoder.getDefaultInstance();独自のコーパスでのカスタムエンコーダーのトレーニング
ドメイン固有の用語が多いデータの場合は、コーパス全体でエンコーダーをトレーニングして精度を向上させます。詳細については、「高度な使用法」をご参照ください。
Python
from dashtext import SparseVectorEncoder
encoder = SparseVectorEncoder()
# Your own corpus
corpus = [
"向量检索服务DashVector基于阿里云自研的高效向量引擎Proxima内核,提供具备水平拓展能力的云原生、全托管的向量检索服务",
"DashVector将其强大的向量管理、向量查询等多样化能力,通过简洁易用的SDK/API接口透出,方便被上层AI应用迅速集成",
"从而为包括大模型生态、多模态AI搜索、分子结构分析在内的多种应用场景,提供所需的高效向量检索能力",
"简单灵活、开箱即用的SDK,使用极简代码即可实现向量管理",
"自研向量相似性比对算法,快速高效稳定服务",
"Schema-free设计,通过Schema实现任意条件下的组合过滤查询"
]
# Train the encoder on the full corpus
encoder.train(corpus)Java
import com.aliyun.dashtext.encoder.SparseVectorEncoder;
import java.util.*;
SparseVectorEncoder encoder = new SparseVectorEncoder();
// Your own corpus
List<String> corpus = Arrays.asList(
"向量检索服务DashVector基于阿里云自研的高效向量引擎Proxima内核,提供具备水平拓展能力的云原生、全托管的向量检索服务",
"DashVector将其强大的向量管理、向量查询等多样化能力,通过简洁易用的SDK/API接口透出,方便被上层AI应用迅速集成",
"从而为包括大模型生态、多模态AI搜索、分子结构分析在内的多种应用场景,提供所需的高效向量检索能力",
"简单灵活、开箱即用的SDK,使用极简代码即可实现向量管理",
"自研向量相似性比对算法,快速高效稳定服务",
"Schema-free设计,通过Schema实现任意条件下的组合过滤查询"
);
// Train the encoder on the full corpus
encoder.train(corpus);適切なエンコーダーの選択
| エンコーダー | 長所 | 制限事項 | 最適な用途 |
|---|---|---|---|
| 組み込み | すぐに使用可能、優れた汎化能力 | 専門用語に対する精度が低い | 汎用テキスト、迅速なプロトタイピング |
| カスタムコーパス | 専門的な語彙に対する精度が高い | コーパス全体での事前のトレーニングが必要 | フィールド固有の用語を含むドメイン固有のデータ |
ビジネス要件に基づいてエンコーダーを選択してください。特定のフィールドに固有の用語が多数含まれるビジネスの場合は、独自のコーパスに基づいてエンコーダーを作成することを推奨します。
ステップ 3:ドキュメントのエンコードと挿入
ドキュメントテキストを encode_documents で疎ベクトルにエンコードし、密ベクトルとともにコレクションに挿入します。
Python
from dashvector import Doc
document = "向量检索服务DashVector基于阿里云自研的高效向量引擎Proxima内核,提供具备水平拓展能力的云原生、全托管的向量检索服务。"
doc_sparse_vector = encoder.encode_documents(document)
print(doc_sparse_vector)
# Output based on the built-in encoder:
# {380823393: 0.7262431704356519, 414191989: 0.7262431704356519, 565176162: 0.7262431704356519, 904594806: 0.7262431704356519, 1005505802: 0.7262431704356519, 1169440797: 0.8883757984694465, 1240922502: 0.7262431704356519, 1313971048: 0.7262431704356519, 1317077351: 0.7262431704356519, 1490140460: 0.7262431704356519, 1574737055: 0.7262431704356519, 1760434515: 0.7262431704356519, 2045788977: 0.8414146776926797, 2141666983: 0.7262431704356519, 2509543087: 0.7262431704356519, 3180265193: 0.7262431704356519, 3845702398: 0.7262431704356519, 4106887295: 0.7262431704356519}
collection.insert(Doc(
id='A',
vector=[0.1, 0.2, 0.3, 0.4],
sparse_vector=doc_sparse_vector
))Java
String document = "向量检索服务DashVector基于达摩院自研的高效向量引擎Proxima内核,提供具备水平拓展能力的云原生、全托管的向量检索服务。";
Map<Long, Float> sparseVector = encoder.encodeDocuments(document);
System.out.println(sparseVector);
// Output based on the built-in encoder:
// {380823393: 0.7262431704356519, 414191989: 0.7262431704356519, 565176162: 0.7262431704356519, 904594806: 0.7262431704356519, 1005505802: 0.7262431704356519, 1169440797: 0.8883757984694465, 1240922502: 0.7262431704356519, 1313971048: 0.7262431704356519, 1317077351: 0.7262431704356519, 1490140460: 0.7262431704356519, 1574737055: 0.7262431704356519, 1760434515: 0.7262431704356519, 2045788977: 0.8414146776926797, 2141666983: 0.7262431704356519, 2509543087: 0.7262431704356519, 3180265193: 0.7262431704356519, 3845702398: 0.7262431704356519, 4106887295: 0.7262431704356519}
Vector vector = Vector.builder().value(Arrays.asList(0.1f, 0.2f, 0.3f, 0.4f)).build();
// Build a Doc with both dense and sparse vectors
Doc doc = Doc.builder()
.id("28")
.sparseVector(sparseVector)
.vector(vector)
.build();
// Insert the document
Response<Void> response = collection.insert(InsertDocRequest.builder().doc(doc).build());各疎ベクトルは、トークンハッシュ ID から BM25 の重みへのマップです。重みが大きいほど、ドキュメント内でより特徴的な用語であることを示します。
ステップ 4:キーワードを意識したセマンティック検索の実行
クエリを encode_queries で疎ベクトルにエンコードし、密ベクトルと疎ベクトルの両方を query に渡します。
Python
query = "什么是向量检索服务?"
sparse_vector = encoder.encode_queries(query)
print(sparse_vector)
# Output based on the built-in encoder:
# {1169440797: 0.2947158712590364, 2045788977: 0.7052841287409635}
docs = collection.query(
vector=[0.1, 0.1, 0.1, 0.1],
sparse_vector=sparse_vector
)Java
String query = "什么是向量检索服务?";
Map<Long, Float> sparseVector = encoder.encodeQueries(query);
System.out.println(sparseVector);
// Output based on the built-in encoder:
// {1169440797: 0.2947158712590364, 2045788977: 0.7052841287409635}
Vector vector = Vector.builder().value(Arrays.asList(0.1f, 0.2f, 0.3f, 0.4f)).build();
// Build a query with both dense and sparse vectors
QueryDocRequest request = QueryDocRequest.builder()
.vector(vector)
.sparse_ector(sparseVector)
.topk(100)
.includeVector(true)
.build();
Response<List<Doc>> response = collection.query(request);
System.out.println(response);ステップ 5:重み付きベクトルによる結果の調整
alpha パラメーターを使用して、セマンティックな類似性 (密ベクトル) とキーワード一致 (疎ベクトル) のバランスを調整します。
| Alpha 値 | 動作 |
|---|---|
0.0 | 距離測定には疎ベクトルのみが使用されます (純粋なキーワード検索) |
1.0 | 距離測定には密ベクトルのみが使用されます (純粋なセマンティック検索) |
クエリを実行する前に、combine_dense_and_sparse を適用して、両方のベクターをスケーリングします。
Python
from dashtext import combine_dense_and_sparse
query = "什么是向量检索服务?"
sparse_vector = encoder.encode_queries(query)
# Set alpha to control the balance: 0.0 = keywords only, 1.0 = semantics only
alpha = 0.7
dense_vector = [0.1, 0.1, 0.1, 0.1]
scaled_dense_vector, scaled_sparse_vector = combine_dense_and_sparse(dense_vector, sparse_vector, alpha)
docs = collection.query(
vector=scaled_dense_vector,
sparse_vector=scaled_sparse_vector
)Java
String query = "什么是向量检索服务?";
Map<Long, Float> sparseVector = encoder.encodeQueries(query);
System.out.println(sparseVector);
// Output based on the built-in encoder:
// {1169440797: 0.2947158712590364, 2045788977: 0.7052841287409635}
Vector denseVector = Vector.builder().value(Arrays.asList(0.1f, 0.2f, 0.3f, 0.4f)).build();
// Scale dense and sparse vectors by the alpha weight factor
float alpha = 0.1f;
sparseVector.forEach((key, value) -> sparseVector.put(key, value * alpha));
denseVector = Vector.builder().value(
denseVector.getValue().stream().map(number -> number.floatValue() * alpha).collect(Collectors.toList())
).build();
// Query with weighted vectors
QueryDocRequest request = QueryDocRequest.builder()
.vector(denseVector)
.sparse_ector(sparseVector)
.topk(100)
.includeVector(true)
.build();
Response<List<Doc>> response = collection.query(request);
System.out.println(response);API リファレンス
完全な DashText API については、「DashText SDK for Python」をご参照ください。