Azure AI Search のベクトル最適化を Cohere-embed-v3-multilingual モデルで検証する

[前回](https://qiita.com/nohanaga/items/fd04e2223b8a237cf335)は Azure Machine Learning/Azure AI Studio の[モデルカタログ](https://learn.microsoft.com/azure/ai-studio/how-to/model-catalog-overview)を使用して **Cohere-embed-v3-multilingual** をデプロイして Azure AI Search でベクトル検索を実施しました。ところで Azure AI Search は 4月4日、ベクトルストレージを最適化する以下のような新しいベクトル検索機能を追加しています。

https://qiita.com/nohanaga/items/d0922a812a41af2c7f64#%E3%83%99%E3%82%AF%E3%83%88%E3%83%AB%E6%A4%9C%E7%B4%A2%E6%9C%80%E9%81%A9%E5%8C%96%E6%A9%9F%E8%83%BD
1. より小さいプリミティブデータ型の追加（float16, int16, int8）
1. `stored` パラメータの追加によりクエリ応答に不要なベクトル領域を削減
1. 組み込みのスカラー量子化機能を追加

今回はこれらの機能を検証します。

# 1. より小さいプリミティブデータ型の追加（float16, int16, int8）
**Cohere-embed-v3-multilingual** モデルには `embedding_types` パラメータで `float`, `int8`, `uint8`, `binary`, `ubinary` が指定できるため、通常使用する `float` 以外のプリミティブデータ型を使用して Embeddings を生成・格納します。

## Cohere SDK
1 つ以上の `embedding_types` を配列で指定できます。
```python
response = co.embed(
    texts=[text], 
    input_type=input_type,
    embedding_types=["int8"]
)
response.embeddings.int8[0] 
```

```python
[
    -3,
    20,
    -25,
    ...
]
```

## インデックス定義
`int8` プリミティブデータ型を格納するためには、インデックスフィールドの型を `Collection(Edm.SByte)` に設定します。

```json
{
    "name": "cohere_v3",
    "type": "Collection(Edm.SByte)",
    ...
}
```
参考までに、Azure AI Search に新たに追加された型は以下となります。

|EDM データ型| 説明|サイズ|
|:-:|:-:|:-:|
|Collection(Edm.Single)|32 ビット浮動小数点|4 byte
|Collection(Edm.Half)|16 ビット浮動小数点|2 byte
|Collection(Edm.Int16)|16 ビット符号付き整数|2 byte
|Collection(Edm.SByte)|8 ビット符号付き整数|1 byte

https://learn.microsoft.com/azure/search/vector-search-how-to-configure-compression-storage#option-1-assign-narrow-data-types-to-vector-fields

# 2. `stored` パラメータの追加
ベクトルインデックス作成時にベクトルフィールドに新たに追加された `stored` パラメータを `false` に設定すると、クエリ時にベクトルデータを返却するために用意されているストレージ領域が削減されます。フィールドごとの全体的なストレージを最大 1/2 削減できます。

```json
{
  "name": "cohere_v3",
  "type": "Collection(Edm.Single)",
  "retrievable": false,
  "stored": false,
  ...
}
```
後段処理などでベクトルデータ実体を使用せず、ベクトル検索処理のみが実行できればよいというユースケースにおいては、この機能が有効です。

# 3. 組み込みのスカラー量子化機能
自動的に `float32` を `int8` に圧縮します。これによりベクトルデータストレージを圧縮および最適化します。検索インデックス定義に `vectorSearch.compressions` を追加します。Pubic Preview でサポートされている圧縮アルゴリズムは `int8` へのスカラー量子化です。

```json
"compressions": [
    {
        "name": "vector-1716124629799-compressor",
        "kind": "scalarQuantization",
        "rerankWithOriginalVectors": true,
        "defaultOversampling": 4,
        "scalarQuantizationParameters": {
            "quantizedDataType": "int8"
        }
    }
]
```

https://learn.microsoft.com/azure/search/vector-search-how-to-configure-compression-storage#option-3-configure-scalar-quantization

# インデックスサイズ比較
| | インデックス数|ベクトルインデックス|ストレージ|
|:-:|:-:|:-:|:-:|
|float32 |8,066|31.93 MB|139.09 MB
|float32(no-stored) |8,066|31.93 MB|73.73 MB (≈1/2)
|int8    |8,066|8.3 MB (≈1/4)|45.88 MB
|int8(compressions)|8,066|8.3 MB (≈1/4)|114.18 MB

## ベクトル最適化の図解
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674344/0b0eef70-cc4f-1e8f-aedd-82df1c0022fc.png)

# パフォーマンス比較
https://qiita.com/nohanaga/items/07236a87b6bc72ca83ee

# 精度比較
比較方法は[以前](https://qiita.com/nohanaga/items/e159712acbf80e40ca1a#%E7%B5%90%E6%9E%9C)と同様。
| | float32|int8|uint8|compressions(float32->int8)
|:-:|:-:|:-:|:-:|:-:|
|#1 Recall@3 avg|0.652|**0.668**|0.663|0.652
|#1 Recall@5 avg|0.786|0.786|**0.790**|0.781
|#2 Recall@3 avg|0.686|**0.696**|**0.696**|0.686
|#2 Recall@5 avg|0.817|0.813|**0.819**|0.817

**Cohere-embed-v3-multilingual** モデルの場合、`compressions` で `float32->int8` にスカラー量子化するよりも、直接 `embedding_types=["int8"]` で生成したほうが精度が高くなっています。ただし、ここでは `rerankWithOriginalVectors` 機能も併用しています。

データセットで精度比較を実施して `float32` と `int8` であまり変わらないようであれば、`int8` にすることでベクトルインデックスサイズを約 1/4 に削減できます。