Elasticsearch 向量搜索:余弦相似度匹配
实现向量实时生成,保持数据与向量的一致性。:实际部署时建议结合。
·
Elasticsearch 向量搜索:余弦相似度匹配实现
1. 核心概念
- 余弦相似度:衡量两个向量方向的相似性,计算公式: $$\cos(\theta) = \frac{\mathbf{A} \cdot \mathbf{B}}{|\mathbf{A}| |\mathbf{B}|}$$ 其中 $\mathbf{A} \cdot \mathbf{B}$ 是点积,$|\mathbf{A}|$ 是向量模长。
- 在 Elasticsearch 中:需使用
dense_vector类型字段存储向量,通过脚本计算相似度。
2. 实现步骤
(1) 创建索引映射
PUT /vector_index
{
"mappings": {
"properties": {
"text": { "type": "text" }, // 原始文本
"embedding": { // 向量字段
"type": "dense_vector",
"dims": 768, // 向量维度 (如BERT输出)
"index": true, // 启用索引
"similarity": "cosine" // 指定余弦相似度
}
}
}
}
(2) 插入文档(含向量)
POST /vector_index/_doc/1
{
"text": "机器学习教程",
"embedding": [0.12, -0.05, 0.87, ...] // 768维向量
}
(3) 执行余弦相似度查询
GET /vector_index/_search
{
"query": {
"script_score": {
"query": { "match_all": {} },
"script": {
"source": """
// 计算余弦相似度
double dot = 0.0;
double normA = 0.0;
double normB = 0.0;
for (int i = 0; i < params.query_vector.length; ++i) {
dot += params.query_vector[i] * doc['embedding'].get(i);
normA += params.query_vector[i] * params.query_vector[i];
normB += doc['embedding'].get(i) * doc['embedding'].get(i);
}
return dot / (Math.sqrt(normA) * Math.sqrt(normB));
""",
"params": {
"query_vector": [0.15, -0.02, 0.91, ...] // 查询向量
}
}
}
}
}
3. 关键参数说明
| 参数 | 作用 | 示例值 |
|---|---|---|
dense_vector |
向量字段类型 | 必填 |
dims |
向量维度 | 768 (BERT) / 512 (其他模型) |
similarity |
相似度算法 | cosine |
script_score |
自定义评分查询 | 用于计算相似度 |
4. 优化建议
- 归一化预处理:存储前将向量归一化(模长为1),可简化为点积计算: $$\cos(\theta) = \mathbf{A} \cdot \mathbf{B}$$
- 使用
knn查询(Elasticsearch 8.0+):{ "knn": { "field": "embedding", "query_vector": [0.15, -0.02, 0.91, ...], "k": 10, "num_candidates": 100 } } - 性能注意:超过1000维时需调整
index_options参数
5. 典型应用场景
- 语义搜索(如:用BERT生成文本向量)
- 推荐系统(物品/用户向量匹配)
- 图像/音视频内容检索
提示:实际部署时建议结合Ingest Pipeline实现向量实时生成,保持数据与向量的一致性。
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)