PaddleNLP:Docker下搭建基于ES的语义检索系统
什么是语义检索?
语义检索(也称基于向量的检索):指检索系统不再拘泥于用户 Query 字面本身(例如:sql查询的like),而是能精准 捕捉到用户 Query 后面的真正意图 并以此来搜索,从而更准确地向用户返回最符合的结果。
原理是通过使用最先进的 语义索引模型找到文本的向量 表示,在高维向量空间中对它们进行索引,并度量查询向量与索引文档的相似程度,从而解决了关键词索引带来的缺陷。
目前有一个很火的国内开源项目( pp飞桨的PaddleNLP),我们可以基于它的源码示例,搭建一套基于ES的语义检索系统。
项目地址: https://github.com/PaddlePaddle/PaddleNLP
本文主要是参照官网的示例来操作的: https://github.com/PaddlePaddle/PaddleNLP/tree/develop/pipelines/examples/semantic-search
但是由于按照教程去部署,遇到了很多问题,所以我把源码下载下来,在服务器直接使用docker去安装了
本文准备了如下内容:
- Linux系统(本文使用的是CentOS 7,8核CPU:x86_64)
- Docker(本文使用的版本为:20.10.17,docker-compose版本为1.29.2)
- PaddleNLP源码(使用稳定的2.6.0版本)
安装部署
2.1 下载源码包
首先下载源码包到本地(官方也推荐的2.6.0版本版本): https://codeload.github.com/PaddlePaddle/PaddleNLP/tar.gz/refs/tags/v2.6.0
上传到服务器目录,并解压:
tar -zxvf PaddleNLP-2.6.0.tar.gz
2.2 配置解释
进入解压后的docker目录(/PaddleNLP-2.6.0/pipelines/docker),使用ls命令并可以看到如下内容:
cd {当前解压目录}/PaddleNLP-2.6.0/pipelines/docker
docker-compose的内容如下,主要是启动Elasticsearch和pipelines-cpu-serving这两个服务,里面已经做了注释:
version: "3"
services:
elasticsearch: #定义服务名
# This will start an empty Elasticsearch instance (so you have to add your documents yourself)
#image: "elasticsearch:8.3.3" # Docker镜像的版本 8.3.3 ,注释表示不使用该配置
image: "docker.elastic.co/elasticsearch/elasticsearch:8.3.3" # Docker镜像的地址
container_name: es01 # Docker容器的名称
ports:
- 9200:9200 # 映射到主机的端口
restart: on-failure # 当程序运行失败时自动重启容器
environment: # 对容器添加环境变量
- discovery.type=single-node
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- cluster.routing.allocation.disk.threshold_enabled=false
- xpack.security.enabled=false
pipelines-cpu-serving: # 定义服务名
image: paddlepaddle/paddlenlp:pipelines-cpu-1.0 # Docker镜像的地址
build: # 构建Docker镜像的相关设置
context: . # Docker的构建上下文路径
dockerfile: Dockerfile # Dockerfile的文件名
container_name: pip01 # Docker容器的名称
network_mode: host # 网络模式设置为host
restart: on-failure # 当程序运行失败时自动重启容器
volumes: # 数据卷,将主机的目录挂载至容器
- .:/paddle
environment: # 对容器添加环境变量
- API_ENDPOINT=http://127.0.0.1:8891
- PIPELINE_YAML_PATH=rest_api/pipeline/semantic_search.yaml
depends_on: # 定义容器启动顺序
- elasticsearch
command: /bin/bash -c "sleep 15 && cd /paddle && sh start_compose.sh && tail -f /dev/null" # 容器启动后执行的命令
networks:
default: # 默认的网络配置
name: elastic # 网络的名称
继续看看启动pipelines-cpu-serving服务里面的配置start_compose.sh配置:
#!/bin/bash
cd /root/PaddleNLP/pipelines/
# linux
python utils/offline_ann.py --index_name dureader_robust_query_encoder \
--doc_dir data/dureader_dev \
--query_embedding_model rocketqa-zh-nano-query-encoder \
--passage_embedding_model rocketqa-zh-nano-para-encoder \
--port 9200 \
--host localhost \
--embedding_dim 312 \
--delete_index
# 使用端口号 8891 启动模型服务
nohup python rest_api/application.py 8891 > server.log 2>&1 &
# 在指定端口 8502 启动 WebUI
nohup python -m streamlit run ui/webapp_semantic_search.py --server.port 8502 > client.log 2>&1 &
可以看出,这个docker-compose的配置,已经帮我完成了官方文档里面的所有操作(包括一些示例数据的生成等): westworld加速官网https://github.com/PaddlePaddle/PaddleNLP/tree/develop/pipelines/examples/semantic-search
2.3 开始安装
使用docker-compse启动es(网络较好的情况下,不用等太久):
docker-compose -f docker-compose.yml up -d elasticsearch
继续使用docker-compose启动paddle(网络较好的情况下,也需要等很久,镜像包超过8个G):
docker-compose -f docker-compose.yml up -d pipelines-cpu-serving
查看是否已经安装成功:
docker ps -a | grep -E 'paddle|es'
可以看到已经安装成功了,继续查看paddle的日志,可以看到日志显示正在下载示例数据:
docker logs -f pip01
日志内容大致如下:
[root@xx docker]# docker logs -f pip01 > logs.txt
INFO - pipelines.utils.import_utils - Fetching from https://paddlenlp.bj.bcebos.com/applications/dureader_dev.zip to `data/dureader_dev`
/bin/sh: 1: docker: not found
WARNING - pipelines.utils.doc_store - Tried to start Elasticsearch through Docker but this failed. It is likely that there is already an existing Elasticsearch instance running.
INFO - pipelines.utils.preprocessing - Converting data/dureader_dev/dureader_dev/dev537.txt
INFO - pipelines.utils.preprocessing - Converting data/dureader_dev/dureader_dev/dev251.txt
INFO - pipelines.utils.common_utils - Using devices: PLACE(CPU)
INFO - pipelines.utils.common_utils - Number of GPUs: 0
[2024-03-15 09:12:26,049] [ INFO] - Already cached /root/.paddlenlp/models/rocketqa-zh-nano-query-encoder/rocketqa-zh-nano-query-encoder.pdparams
[2024-03-15 09:12:28,896] [ INFO] - Already cached /root/.paddlenlp/models/rocketqa-zh-nano-para-encoder/rocketqa-zh-nano-para-encoder.pdparams
[2024-03-15 09:12:31,342] [ INFO] - We are using <class 'paddlenlp.transformers.ernie.tokenizer.ErnieTokenizer'> to load 'rocketqa-zh-nano-query-encoder'.
[2024-03-15 09:12:31,343] [ INFO] - Already cached /root/.paddlenlp/models/rocketqa-zh-nano-query-encoder/ernie_3.0_nano_zh_vocab.txt
[2024-03-15 09:12:31,395] [ INFO] - tokenizer config file saved in /root/.paddlenlp/models/rocketqa-zh-nano-query-encoder/tokenizer_config.json
[2024-03-15 09:12:31,396] [ INFO] - Special tokens file saved in /root/.paddlenlp/models/rocketqa-zh-nano-query-encoder/special_tokens_map.json
[2024-03-15 09:12:31,397] [ INFO] - We are using <class 'paddlenlp.transformers.ernie.tokenizer.ErnieTokenizer'> to load 'rocketqa-zh-nano-para-encoder'.
[2024-03-15 09:12:31,398] [ INFO] - Already cached /root/.paddlenlp/models/rocketqa-zh-nano-para-encoder/ernie_3.0_nano_zh_vocab.txt
[2024-03-15 09:12:31,446] [ INFO] - tokenizer config file saved in /root/.paddlenlp/models/rocketqa-zh-nano-para-encoder/tokenizer_config.json
[2024-03-15 09:12:31,447] [ INFO] - Special tokens file saved in /root/.paddlenlp/models/rocketqa-zh-nano-para-encoder/special_tokens_map.json
INFO - pipelines.utils.logger - Logged parameters:
{'processor': 'TextSimilarityProcessor', 'tokenizer': 'NoneType', 'max_seq_len': '0', 'dev_split': '0.1'}
INFO - pipelines.document_stores.elasticsearch - Updating embeddings for all 1398 docs ...
Updating embeddings: 10000 Docs [05:15, 31.74 Docs/s]
至此,安装已经成功了,接下来我们使用下。
使用
浏览器访问:http://服务器地址:8502,可以看到检索系统运行正常,我们可以输入内容进行语义搜索,这里就使用了默认的提示搜索
同时也可以查询这个界面的API接口:http://服务器地址:8891/docs
调试query接口:
我们使用postman查询es的内容:http://服务器地址:9200/dureader_robust_query_encoder/_search
经过前面的步骤,博主理解它的整个流程应该如下:
-
首先,输入一段查询的文字,然后通过模型计算出这段文字的特征值(或者说是该文字在向量空间中的位置)。
-
接着,利用计算出的特征值与存储在Elasticsearch(ES)中其他文本的特征值进行比对和计算,以找出最匹配的结果。
-
最后,返回匹配的内容。
这其中涉及到的是信息检索(Information Retrieval)和自然语言处理(NLP)的知识。
文末
最终,我们成功地在Docker环境下搭建了基于ES的语义检索系统。全过程的整体来看并非易事,出现了各种问题,我们现在看到的是一个成功的版本。
一个常见的问题就是:出现提示"[Paddle]Error: Your machine doesn‘t support AVX, but the installed PaddlePaddle is avx core, you…"。
之前我是在使用装有M2芯片的Mac笔记本并通过使用Docker Desktop进行安装。这里的错误提示的原因可能是与我笔记本的CPU架构不匹配,我的笔记本的硬件并不支持这种架构的PaddlePaddle。
我尝试使用命令 “docker buildx build --load --platform linux/amd64 -t” 来声明为X86架构进行操作,且在容器内下载不需支持AVX指令集的paddlepaddle版本,但是依然未能解决问题。
最终我选择在满足环境需求的服务器(CentOS 7)上进行操作。当然,用户也可以在自己 GPU 硬件环境进行,速度更快。
标签:INFO,pipelines,nano,encoder,PaddleNLP,zh,Docker,docker,ES From: https://www.cnblogs.com/xibujichang/p/18095115