一、原理简介

Elasticsearch 8.x+(OpenSearch 2.x+ 同理)内置了向量字段(dense_vectorknn_vector),支持如下功能:

  • 存储高维向量(如 128/256/768 维 embedding)
  • 支持向量相似度检索(如 KNN、余弦距离、欧氏距离)
  • 可与结构化/全文检索混合查询

底层实现常用 HNSW(Hierarchical Navigable Small World)等 ANN 算法。


二、索引设计与数据写入

1. 映射定义(Mapping)

以 knn_vector 为例(Elasticsearch 8.0+):

PUT my-index
{
  "mappings": {
    "properties": {
      "embedding": {
        "type": "knn_vector",
        "dimension": 768
      },
      "title": { "type": "text" },
      "category": { "type": "keyword" }
    }
  }
}
  • dimension:向量维度(必须与实际向量长度一致)

2. 数据写入

POST my-index/_doc
{
  "embedding": [0.12, -0.98, ..., 0.56],
  "title": "AI技术详解",
  "category": "tech"
}

向量通常由模型生成(如 BERT、CLIP、ResNet),前端或 ETL 提供。


三、向量检索查询

1. KNN 查询(最近邻搜索)

POST my-index/_search
{
  "knn": {
    "embedding": {
      "vector": [0.13, -0.95, ..., 0.54],
      "k": 5
    }
  }
}
  • vector:待检索的目标向量
  • k:返回最近的 K 个文档

2. 混合过滤检索

POST my-index/_search
{
  "knn": {
    "embedding": {
      "vector": [0.13, -0.95, ..., 0.54],
      "k": 10
    }
  },
  "query": {
    "bool": {
      "filter": [
        { "term": { "category": "tech" } }
      ]
    }
  }
}

支持结构化过滤、全文检索与向量检索结合。

3. 余弦相似度/欧氏距离

  • 默认使用 HNSW+余弦距离。
  • 可在 mapping 设置 method,如:
    "embedding": {
      "type": "knn_vector",
      "dimension": 768,
      "method": {
        "name": "hnsw",
        "space_type": "cosinesimil"
      }
    }
    

四、性能与架构建议

  • 向量维度建议不超过 1024,常见为 128~768。
  • 向量字段不能参与全文检索,只能用于 ANN 检索。
  • KNN 查询适合少量高频检索,批量场景建议用专用向量数据库(如 Milvus)。
  • 集群需分配足够内存,HNSW 索引会占用大量堆空间。
  • 向量检索可与结构化/全文检索混合,提升业务相关性。

五、应用场景

  • AI 语义搜索(文本、图片、音频 embedding 检索)
  • 推荐系统(用户/物品 embedding 最近邻查找)
  • 问答系统(知识库语义匹配)
  • RAG(检索增强生成,LLM知识库)

六、代码示例(Python)

使用官方 elasticsearch Python SDK:

from elasticsearch import Elasticsearch

es = Elasticsearch("http://localhost:9200")

# 向量检索
query = {
    "knn": {
        "embedding": {
            "vector": [0.13, -0.95, ..., 0.54],
            "k": 5
        }
    }
}
res = es.search(index="my-index", body=query)
for hit in res['hits']['hits']:
    print(hit['_score'], hit['_source']['title'])

七、向量生成方法

向量(embedding)是将文本、图片、音频、视频等内容转换为定长的高维数值数组,常见方法如下:

1. 文本向量生成

  • BERT/Transformer 系列
    使用 HuggingFace Transformers 等库,获得句子/段落 embedding。

    from transformers import AutoTokenizer, AutoModel
    import torch
    
    tokenizer = AutoTokenizer.from_pretrained("sentence-transformers/all-MiniLM-L6-v2")
    model = AutoModel.from_pretrained("sentence-transformers/all-MiniLM-L6-v2")
    
    text = "Elasticsearch 向量检索原理"
    inputs = tokenizer(text, return_tensors="pt")
    with torch.no_grad():
        outputs = model(**inputs)
        # 取 [CLS] 向量或平均池化
        embedding = outputs.last_hidden_state.mean(dim=1).squeeze().numpy()
    
  • word2vec/fastText
    适合词级别 embedding,句子可平均池化。

  • OpenAI Embedding API
    GPT/CLIP/embedding-ada-002 等模型,直接返回 embedding。

    import openai
    resp = openai.Embedding.create(model="text-embedding-ada-002", input="你的文本")
    embedding = resp["data"][0]["embedding"]
    

2. 图片/音频/视频向量

  • CLIP、ResNet、ViT
    用于图片、文本跨模态 embedding。
  • VGGish、wav2vec
    用于音频 embedding。
  • 自监督/迁移学习模型
    适合领域定制。

3. 向量归一化

  • 检索时建议归一化(如 L2),提升相似度精度。
    import numpy as np
    embedding = embedding / np.linalg.norm(embedding)
    

八、混合检索实战(向量+结构化/全文)

混合检索是指:先用向量查找语义相近的候选,再用结构化过滤或全文检索提升相关性。

1. Elasticsearch 混合检索示例

POST my-index/_search
{
  "knn": {
    "embedding": {
      "vector": [0.13, -0.95, ..., 0.54],
      "k": 20
    }
  },
  "query": {
    "bool": {
      "filter": [
        { "term": { "category": "tech" } },
        { "range": { "ts": { "gte": 1680000000 } } }
      ],
      "must": [
        { "match": { "title": "向量检索" } }
      ]
    }
  }
}
  • 先用向量检索获取最近邻,再用 filter/must 精确筛选。
  • 可以设置排序权重,综合向量分数与文本分数。

2. Milvus/Weaviate 混合检索

  • 支持 SQL-like 或 REST API,表达向量+属性过滤。
  • 例如 Milvus:
    results = collection.search(
        [query_vector],
        "embedding",
        limit=10,
        expr="category == 'tech' and ts > 1680000000"
    )
    

九、性能调优方案

1. 向量维度选择

  • 128~768 维为主流,维度越高检索越慢。
  • 选用合适模型和降维算法(如 PCA)。

2. 索引类型优化

  • Elasticsearch:优先用 HNSW,设置合理参数(如 M、ef_search)。
  • Milvus/Qdrant:选 HNSW、IVF_FLAT、IVF_PQ,调优参数。

3. 批量写入与并发

  • 数据入库建议批量,提升吞吐。
  • 检索端多线程/异步,提高 QPS。

4. 热点数据预热

  • 对热门向量提前缓存,减少延迟。

5. 资源配置

  • 分配足够内存和 CPU,向量索引依赖堆空间。
  • 分布式部署,横向扩展节点。

6. 混合检索分阶段

  • 先用向量召回大候选集,再用结构化/全文排序,分阶段减少无关数据。

7. 索引重建与维护

  • 定期重建索引,清理无效数据,保证检索精度和速度。

十、与大模型(LLM)集成案例

向量数据库是 RAG(Retrieval Augmented Generation,检索增强生成)等大模型知识库的核心。

1. 典型流程

  1. 知识入库:文本/文档分段,生成 embedding,存入向量数据库。
  2. 用户提问:用 LLM 将问题生成 embedding。
  3. 向量检索:在向量数据库查找语义最相关的知识片段。
  4. 结果拼接:将检索结果作为上下文,喂给大模型进行生成/问答。

2. 示例代码(OpenAI + Milvus)

import openai
from pymilvus import Collection

# 1. 用户提问
question = "什么是向量数据库?"
q_emb = openai.Embedding.create(model="text-embedding-ada-002", input=question)["data"][0]["embedding"]

# 2. 检索相关知识
collection = Collection("knowledge")
results = collection.search([q_emb], "embedding", limit=5)
context = "\n".join([hit.entity.get("content") for hit in results[0]])

# 3. 拼接并生成答案
prompt = f"已知知识:{context}\n请回答:{question}"
answer = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=[{"role": "user", "content": prompt}])
print(answer["choices"][0]["message"]["content"])

3. 实战应用

  • 企业知识库智能问答
  • 智能客服/Agent
  • 医疗/法律/金融检索增强
  • 代码搜索、图像搜索

知识传递,互通有无,创作不易,点点关注!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐