虽然本节与SK无关,但都是基于AI,所以暂且放在这个系统中
Azure AI 视觉的多模式嵌入 API 可以将图像和文本转换为向量,也就是一种数字化的表示方式。这种技术可以让我们实现基于向量的图片搜索功能。通过结合这个 API 和 pgvector(PostgreSQL 中的向量库),我们可以让图片变得可搜索,甚至支持用文字来找图片。
使用PostgreSQL作为向量化库
桂素伟,公众号:桂迹Semantic Kernel:使用PostgreSQL作为向量化库
多模式嵌入是指把图像转换成可以捕捉其特征和内容的向量。这个向量表示能和文本搜索使用的向量兼容,意味着你可以用图像和文本在同一个“空间”里做搜索匹配。
传统的图像搜索通常依赖于从图像中提取的特征,比如标签、标记或图像描述符,再通过这些特征来比较图片相似度。但向量相似性搜索相比传统的关键字搜索有很大优势。它能更好地理解图片和文字的相似性,成为现代内容搜索的关键技术。
public class VectorResult
{
public double[] Vector { get; set; }
public string ModelVersion { get; set; }
}
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 });
}
}
下面用向量化数据保存和查询对应向量数据:
数据库实体类:
class DataVector
{
public int Id { get; set; }
public string Name { get; set; }
public double[] Embedding { get; set; }
}
向数据写入的方法:
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#向量余弦相似度查
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实现向量余弦相似度查
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 });
}
}