
# 使用Elasticsearch AI搜索实现语义检索
CSS服务结合搜索大模型的知识搜索能力，在传统字符搜索的基础上集成语义搜索能力，通过向量化技术提升搜索结果相关性。本方案兼容开源Elasticsearch生态，业务仅需适配multi_match查询语句即可实现语义检索。
#### 应用场景
Elasticsearch AI语义搜索适用于以下场景：
- 知识库检索：企业知识库、FAQ系统等需要理解用户查询意图的场景。
- 内容推荐：基于语义相似度的内容推荐系统。
 
#### 方案架构
图1语义检索架构图   
![](https://support.huaweicloud.com/usermanual-css/figure/zh-cn_image_0000002322772105.png "点击放大")
数据写入：使用Elasticsearch原生Bulk接口写入数据，搜索大模型插件自动调用Embedding模型将文本转换为向量，生成的语义向量存储在CSS向量数据库中。
语义查询：使用Elasticsearch原生multi_match查询语句，搜索大模型插件自动转换查询语句为语义向量查询，执行多路召回（关键词+向量相似度），调用精排模型对结果进行二次排序，返回最终结果。
#### 方案优势
- 提升搜索精度：通过语义理解与精排实现多路召回与重排序，提升结果相关性。
- 兼容开源生态：兼容开源Elasticsearch，适配multi_match语句。
- 易用性高：通过插件方式实现，仅需配置模型服务和索引，无需改造业务代码。
 
#### 约束限制
Elasticsearch AI搜索功能依赖Embedding节点，该节点的配置采用白名单机制，如需试用，请提交[工单](https://console.huaweicloud.com/ticket/?locale=zh-cn#/ticketindex/serviceTickets)申请权限。
#### 前提条件
- 确认Elasticsearch集群满足以下条件。
  - 集群状态：可用
  
  - 集群版本：7.10.2（在集群列表查看"集群版本"）
  
  - 配置要求：已配置Embedding节点（在依赖服务页面查看是否存在"可用"状态的独享版集群）
   
- 获取独享版集群的访问地址。
  1. 登录[云搜索服务管理控制台](https://console.huaweicloud.com/elasticsearch/)。
  
  2. 在左侧导航栏，选择"搜索大模型 \> 独享版集群"。
  
  3. 在集群列表，选择目标集群，在"内网访问地址"列获取并记录集群的内网IP地址，后续配置模型服务需要使用。 一般是"\<host\>:\<port\>"或"\<host\>:\<port\>,\<host\>:\<port\>"样式。
     图2获取集群访问地址   
     ![](https://support.huaweicloud.com/usermanual-css/figure/zh-cn_image_0000002477835644.png "点击放大") 
   
 
#### 步骤一：登录Kibana
登录Kibana进入命令执行页面。Elasticsearch集群支持多种客户端访问，本文仅以CSS服务集成的Kibana为例介绍配置指导。
1. 登录[云搜索服务管理控制台](https://console.huaweicloud.com/elasticsearch/)。
2. 在左侧导航栏，选择"集群管理 \> Elasticsearch"。
3. 在集群列表，选择目标集群，单击操作列的"Kibana"，登录Kibana。
4. 在Kibana左侧导航栏选择"Dev Tools"，进入操作页面。 控制台左侧是命令输入框，其右侧的三角形图标为执行按钮，右侧区域则显示执行结果。
   
 
#### 步骤二：启用搜索大模型插件
在Kibana中执行以下命令，启用搜索大模型插件。
```
PUT _cluster/settings
{
  "persistent": {
    "pg_search.inference.enable": true
  }
}
```
返回如下信息，表示成功启用搜索大模型插件。
```
{
  "acknowledged" : true,
  "persistent" : {
    "pg_search" : {
      "inference" : {
        "enable" : "true"
      }
    }
  },
  "transient" : { }
}
```
#### 步骤三：配置模型服务
1. 在Kibana中执行以下命令，配置Embedding模型服务。
   ```
   PUT _inference/model_service/pangu_vector  // pangu_vector为模型服务名称，支持自定义
   {
     "description": "搜索大模型-语义向量化模型", // 服务描述信息
     "service_config": {
       "semantic_vector": {          // 模型类型
         "service_urls": [           // Embedding模型服务的访问地址列表（数组格式）
           "http://{endpoint}/app/search/v1/vector" // 替换{endpoint}为独享版集群的访问地址，例如访问地址为10.20.30.40:18088，则此处应填写"http://10.20.30.40:18088/app/search/v1/vector"
         ],
         "algorithm": "GRAPH",      // 使用图算法进行近似最近邻搜索
         "metric": "inner_product", // 相似度度量方式：内积
         "dimension": "768"        // 向量维度768
       }
     }
   }
   ```
   
2. 在Kibana中执行以下命令，配置Rerank模型服务。
   ```
   PUT _inference/model_service/pangu_ranking  // pangu_ranking为模型服务名称，支持自定义
   {
     "description": "搜索大模型-精排模型", // 服务描述信息
     "service_config": {
        "reorder": {                 // 模型类型
         "service_urls": [           // Rerank模型服务的访问地址列表（数组格式）
           "http://{endpoint}/app/search/v1/rerank" // 替换{endpoint}为独享版集群的访问地址，例如访问地址为10.20.30.40:18088，则此处应填写"http://10.20.30.40:18088/app/search/v1/rerank"
         ]
       }
     }
   }
   ```
   
更多配置参数及说明请参见[配置模型服务](https://support.huaweicloud.com/usermanual-css/css_01_0282.html)。
#### 步骤四：创建向量索引
在Kibana中执行以下命令，创建向量索引，如pangu_index，并将上一步配置的Embedding和Rerank模型服务关联到索引中。
```
PUT pangu_index
{
  "aliases": {                    // 定义索引别名
    "pangu_wiki": {}              // 通过pangu_wiki别名访问索引
  },
  "mappings": {                   // 字段映射定义
    "properties": {
      "title": {                  // 文档标题字段
        "type": "text"            // 全文检索类型
      },
      "desc": {                   // 描述字段
        "type": "text"            // 全文检索类型
      },
      "content": {                // 正文内容字段
        "type": "text"            // 全文检索类型
      },
      "author": {                 // 作者字段
        "type": "keyword"         // 精确值类型，适合过滤和聚合
      }
    }
  },
  "settings": {                   // 索引设置
    "index.vector": true,         // 启用向量索引功能
    "index.inference.semantic_search_enabled": true, // 启用语义搜索
    "index.inference.field": [    // 参与向量化的字段及权重
      "title:100",               // 标题字段，权重100
      "desc:80",                 // 描述字段，权重80
      "content:30"               // 内容字段，权重30
    ],
    "index.inference.embedding_model": "pangu_vector", // Embedding模型服务的名称
    "index.inference.reorder_enabled": true, // 启用结果重排序
    "index.inference.reorder_model": "pangu_ranking", // 重排序模型服务的名称
    "index.inference.semantic_search_type": "vector", // 语义搜索类型为向量搜索
    "number_of_shards": 3         // 索引分片数为3（根据数据量调整）
  }
}
```
#### 步骤五：导入数据
在Kibana中，使用Bulk API批量导入数据到上一步创建的索引pangu_index。
```
// 操作类型为index(创建/更新文档)，并指定文档ID为1
// title字段值（文本类型，将被向量化），desc字段值（文本类型，将被向量化），content字段值（文本类型，将被向量化），author字段值（关键字类型，用于精确匹配）
PUT pangu_index/_bulk
{"index":{"_id":"1"}}
{"title":"热带雨林","desc":"丰富的热带植物世界","content":"生态系统","author":"李雷"}
```
批量导入说明：
- 向量生成过程：系统会自动将title(权重100)、desc(权重80)、content(权重30)拼接，调用pangu_vector模型生成768维的语义向量，向量数据存储在_inference.semantic_vector字段。
- 如果某条文档失败，不会影响其他文档的导入，Bulk API的详细使用说明请参见[Bulk API](https://www.elastic.co/guide/en/elasticsearch/reference/7.7/docs-bulk.html)。
- 性能建议：大批量导入时建议每批次500\~1000个文档。
- 数据格式建议：
  - 文本字段建议做基础清洗，去除特殊字符等。
  
  - 关键业务字段建议设置非空校验。
  
  - 中文文本不需要预先分词，大模型会自动处理。
   
 
#### 步骤六：语义检索
在Kibana中执行以下命令，使用multi_match语句在pangu_index索引中执行语义检索。
```
GET pangu_index/_search
{
  // 控制返回结果的字段内容
  "_source": {
    "excludes": [ 
      "_inference"  // 排除返回结果中可能包含敏感或冗余信息的字段
    ]
  },
  // 查询主体部分
  "query": {
    // 布尔查询
    "bool": {
      // 必须满足的条件列表（逻辑AND）
      "must": [
        {
          // 多字段匹配查询，目标字段匹配时会自动转换为语义向量搜索
          "multi_match": {
            "query": "橡胶树在哪里",  // 用户输入的搜索关键词/句
            "fields": ["title","content","desc"]  // 搜索的目标字段列表,必须和索引配置的index.inference.field字段对应
          }
        }
      ]
      // 可选添加其他逻辑条件:
      // "filter": [...]    // 不影响评分的过滤条件
      // "should": [...]    // 逻辑OR条件
      // "must_not": [...]  // 排除条件
    }
  }
  // 可选添加搜索优化参数:
  // "size": 20,            // 返回结果数量
  // "explain": true,       // 显示相关性评分计算细节
  // "highlight": { ... }   // 关键词高亮配置
}
```
检索说明：
- 该查询同时搜索title、content、desc三个字段，寻找与"橡胶树在哪里"相关的内容。
- 通过bool查询结构确保结果必须满足multi_match条件。
- 排除_inference字段可减少网络传输数据量并保护内部处理细节。
 
