Semantic Kernel：画像のベクトル化

本節はSKと無関係ですが、AIをベースにしているため、このシステムに一時的に配置します。

Azure AI ビジュアルのマルチモーダル埋め込みAPIは、画像とテキストをベクトルへ変換できます。つまり、デジタル表現です。この技術を利用することで、ベクトルベースの画像検索機能を実現できます。このAPIとpgvector（PostgreSQLのベクトルライブラリ）を組み合わせることで、画像を検索可能にし、さらには文字で画像を検索することをサポートします。

> [Semantic Kernel：使用PostgreSQL作为向量化库](https://mp.weixin.qq.com/s?__biz=MzA3NDM1MzIyMQ==&mid=2247488404&idx=1&sn=2989ca6101033d3cdc4dd4b757dc1df9&chksm=9f004cbea877c5a881b73909c6eb252943a284ee692dbcae4c674858fbeaf342aaa98eeb700a&token=1366573873&lang=zh_CN#rd)  
> 作者: 桂素伟、公众号: 桂迹

マルチモーダルの埋め込みとは、画像をその特徴と内容を捉えるベクトルに変換することを指します。このベクトル表現は、テキスト検索で使用するベクトルと互換性があり、画像とテキストを同じ「空間」で検索・一致させることができます。

伝統的な画像検索は、通常、画像から抽出した特徴（タグ、マーク、画像ディスクリプタなど）に依存し、これらの特徴に基づいて画像の類似性を比較します。しかし、ベクトル類似性検索は、従来のキーワード検索と比べて大きな利点があります。それは、画像と文字の類似性をより良く理解でき、現代のコンテンツ検索の重要技術となっています。

以下は、C#で実装されたエンティティクラスとテキストと画像のベクトル化メソッドです：

```csharp
public class VectorResult
{
    public double[] Vector { get; set; }
    public string ModelVersion { get; set; }
}

// TextとImageのベクトル化メソッド
async Task<VectorResult> VectorizeText(string text)
{
    using (var client = new HttpClient())
    {
        client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
        var requestUrl = endpoint + "computervision/retrieval:vectorizeText?api-version=2024-02-01&model-version=2023-04-15";
        var content = new StringContent("{\"text\":\"" + text + "\"}");
        content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
        var response = await client.PostAsync(requestUrl, content);
        var result = await response.Content.ReadAsStringAsync();
        return JsonSerializer.Deserialize<VectorResult>(result, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
    }
}

async Task<VectorResult> VectorizeImageAsync(string imageUrl)
{
    using (var client = new HttpClient())
    {
        client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
        var requestUrl = endpoint + "computervision/retrieval:vectorizeImage?api-version=2024-02-01&model-version=2023-04-15";
        var content = new StringContent("{\"url\":\"" + imageUrl + "\"}");
        content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
        var response = await client.PostAsync(requestUrl, content);
        var result = await response.Content.ReadAsStringAsync();
        return JsonSerializer.Deserialize<VectorResult>(result, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
    }
}
```

以下は、ベクトル化データの保存と対応ベクトルデータのクエリに使用する方法です：

データベースエンティティクラス：

```csharp
class DataVector
{
    public int Id { get; set; }
    public string Name { get; set; }
    public double[] Embedding { get; set; }
}
```

データへの挿入方法：

```csharp
void InsertImageVector(DataVector imageVector)
{
    using (IDbConnection db = new NpgsqlConnection(File.ReadAllText("C://GPT/just-agi-db.txt")))
    {
        string sqlQuery = @"
                INSERT INTO public.imagevector (name, embedding) 
                VALUES (@Name, @Embedding) 
                RETURNING id;";
        var parameters = new
        {
            Name = imageVector.Name,
            Embedding = imageVector.Embedding 
        };
        var id = db.ExecuteScalar<int>(sqlQuery, parameters);
        imageVector.Id = id;
    }
}
```

C#でのベクトルコサイン類似度検索：

```javascript
double GetCosineSimilarity(double[] vector1, double[] vector2)
{
    double dotProduct = 0;
    int length = Math.Min(vector1.Length, vector2.Length);
    for (int i = 0; i < length; i++)
    {
        dotProduct += vector1[i] * vector2[i];
    }
    var magnitude1 = Math.Sqrt(vector1.Select(x => x * x).Sum());
    var magnitude2 = Math.Sqrt(vector2.Select(x => x * x).Sum());
    return dotProduct / (magnitude1 * magnitude2);
}
```

SQLでのベクトルコサイン類似度検索：

```csharp
IEnumerable<QueryVectorResult> QueryImageVector(double[] imageVector)
{
    using (IDbConnection db = new NpgsqlConnection(File.ReadAllText("C://GPT/just-agi-db.txt")))
    {
        string sqlQuery = "select id,name,1-(cast(@embedding as vector) <-> embedding) as result from public.imagevector ";
        return db.Query<QueryVectorResult>(sqlQuery, new { embedding = imageVector });
    }
}
```

(Translated by GPT)