es自2020年的8.x版本以来,就提供了机器学习的能力。我们可以使用es官方提供的工具eland,将hugging face上的NLP模型,上传到es集群中。利用es的机器学习模块,来运维部署管理模型。配合es的管道处理,来更加便捷的处理数据。
但是在国内操作,根据官方文档或者根据官方博客操作,有无穷无尽的坑。看着官方的文档写的很清楚,实际上操作的时候,还是操作不下来。这里写一个闭坑指南。
在你上车体验ES的机器学习之前,看看我这篇文章,肯定是会有收获的。因为我已经花了时间,踩了坑,并解决了它。
上传模型存在的坑
-
第一个坑是,es的机器学习,是收费的功能,白金版才能使用。这里需要开启试用才能用(试用期限为一个月)。如果只是体验,一个月已经足够了。体验效果不错,就可以找老板花钱了。(不过网上也有很多绿色的方案,可以用,不推荐,有法律风险,特别是商用)
-
开启白金试用,需要开启xpack安全认证,开启用户认证,在kibana上登录的时候,要使用elastic用户登录,否则无法开启试用,会告诉你无权限。
-
网络环境问题。如果你能开启科学上网,肯定可以避免问题。但是即使有科学上网,也只是体验一下。并不是生产实践方案,生产环境通常都是在内网环境下,即使能上网,也肯定是在国内网络环境下。这会有各种各样的问题。所以要做我们就做生产环境版本,要做就做离线版本。举一个最简答的例子,国内的网络,很难访问huggingface,去拉取模型。 这里是我直接使用eland,上传模型的时候遇到的错误。
docker run -it -v /u01/isi/.cache/huggingface/hub/:/usr/local/bin/eland_import_hub_model --rm elastic/eland \` `eland_import_hub_model \` `--url http://elastic:123123@10.99.100.49:9200 \` `--hub-model-id sentence-transformers/clip-ViT-B-32-multilingual-v1 \` `--task-type text_embedding \` `--start` `
报错为无法访问huggingface.co 国内域名污染导致的。如果可以挂代理,可以解决。如果没有代理,则看下边离线安装版本
2023-11-22` `09:40:30,738 INFO : Establishing connection to Elasticsearch` `2023-11-22` `09:40:30,751 INFO : Connected to cluster named 'es' (version:` `8.8.0)` `2023-11-22` `09:40:30,752 INFO : Loading HuggingFace transformer tokenizer and model 'sentence-transformers/clip-ViT-B-32-multilingual-v1'` `'HTTPSConnectionPool(host='huggingface.co',` `port=443): Max retries exceeded with url:` `/sentence-transformers/clip-ViT-B-32-multilingual-v1/resolve/main/tokenizer_config.json (Caused by ConnectTimeoutError(<urllib3.connection.HTTPSConnection object at 0x7f50eb16cc10>, 'Connection to huggingface.co timed out.` `(connect timeout=10)'))' thrown while requesting HEAD https://huggingface.co/sentence-transformers/clip-ViT-B-32-multilingual-v1/resolve/main/tokenizer_config.json` `2023-11-22` `09:40:41,125 WARNING : 'HTTPSConnectionPool(host='huggingface.co',` `port=443): Max retries exceeded with url:` `/sentence-transformers/clip-ViT-B-32-multilingual-v1/resolve/main/tokenizer_config.json (Caused by ConnectTimeoutError(<urllib3.connection.HTTPSConnection object at 0x7f50eb16cc10>, 'Connection to huggingface.co timed out.` `(connect timeout=10)'))' thrown while requesting HEAD https://huggingface.co/sentence-transformers/clip-ViT-B-32-multilingual-v1/resolve/main/tokenizer_config.json` `'HTTPSConnectionPool(host='huggingface.co',` `port=443): Max retries exceeded with url:` `/sentence-transformers/clip-ViT-B-32-multilingual-v1/resolve/main/config.json (Caused by ConnectTimeoutError(<urllib3.connection.HTTPSConnection object at 0x7f50eb16cfd0>, 'Connection to huggingface.co timed out.` `(connect timeout=10)'))' thrown while requesting HEAD https://huggingface.co/sentence-transformers/clip-ViT-B-32-multilingual-v1/resolve/main/config.json` `2023-11-22` `09:40:51,583 WARNING : 'HTTPSConnectionPool(host='huggingface.co',` `port=443): Max retries exceeded with url:` `/sentence-transformers/clip-ViT-B-32-multilingual-v1/resolve/main/config.json (Caused by ConnectTimeoutError(<urllib3.connection.HTTPSConnection object at 0x7f50eb16cfd0>, 'Connection to huggingface.co timed out.` `(connect timeout=10)'))' thrown while requesting HEAD https://huggingface.co/sentence-transformers/clip-ViT-B-32-multilingual-v1/resolve/main/config.json` `Traceback (most recent call last):` `File` `"/usr/local/lib/python3.9/dist-packages/transformers/utils/hub.py", line 409,` `in cached_file` ` resolved_file =` `hf_hub_download(` `File` `"/usr/local/lib/python3.9/dist-packages/huggingface_hub/utils/_validators.py", line 118,` `in _inner_fn` `return` `fn(*args,` `**kwargs)` `File` `"/usr/local/lib/python3.9/dist-packages/huggingface_hub/file_download.py", line 1291,` `in hf_hub_download` ` raise LocalEntryNotFoundError(` `huggingface_hub.utils._errors.LocalEntryNotFoundError: Connection error,` `and we cannot find the requested files in the disk cache. Please try again or make sure your Internet connection is` `on.` `During handling of the above exception, another exception occurred:` `Traceback (most recent call last):` `File` `"/usr/local/bin/eland_import_hub_model", line 219,` `in` `<module>` ` tm =` `TransformerModel(model_id=args.hub_model_id, task_type=args.task_type, es_version=cluster_version, quantize=args.quantize)` `File` `"/usr/local/lib/python3.9/dist-packages/eland/ml/pytorch/transformers.py", line 613,` `in __init__` ` self._tokenizer = transformers.AutoTokenizer.from_pretrained(` `File` `"/usr/local/lib/python3.9/dist-packages/transformers/models/auto/tokenization_auto.py", line 634,` `in from_pretrained` ` config = AutoConfig.from_pretrained(` `File` `"/usr/local/lib/python3.9/dist-packages/transformers/models/auto/configuration_auto.py", line 896,` `in from_pretrained` ` config_dict, unused_kwargs = PretrainedConfig.get_config_dict(pretrained_model_name_or_path,` `**kwargs)` `File` `"/usr/local/lib/python3.9/dist-packages/transformers/configuration_utils.py", line 573,` `in get_config_dict` ` config_dict, kwargs = cls._get_config_dict(pretrained_model_name_or_path,` `**kwargs)` `File` `"/usr/local/lib/python3.9/dist-packages/transformers/configuration_utils.py", line 628,` `in _get_config_dict` ` resolved_config_file =` `cached_file(` `File` `"/usr/local/lib/python3.9/dist-packages/transformers/utils/hub.py", line 443,` `in cached_file` ` raise EnvironmentError(` `OSError: We couldn't connect to 'https://huggingface.co' to load this file, couldn't find it in the cached files and it looks like sentence-transformers/clip-ViT-B-32-multilingual-v1 is` `not the path to a directory containing a file named config.json.` `Checkout your internet connection or see how to run the library` `in offline mode at 'https://huggingface.co/docs/transformers/installation#offline-mode'.` `
-
官方指定的向es中导入NLP模型的工具是Eland,下载和构建镜像也是有网络问题,这里需要指定国内的镜像源。
-
关于从hugging face上拉取NLP模型的问题。使用eland,它可以根据我们指定的模型id,去hugging face上拉取模型,但是还是国内的网络环境问题,死活拉不下来。因为无法访问huggingface域名。
-
目前,截止到2023年12月2号为止。es所谓的机器学习能力,仅支持文本类操作的模型。官方一直在说拥有跨模态的能力。实际上es并不支持,将图片转向量的模型导入到es中(例如常用的CLIP多模态模型,其实它是两部分,双塔模型,一个是将图片做embedding,转成向量。另一个模型是将我们的文本内容做embedding转为向量。其中图片转向量的模型,在es中是不支持上传的,文本转向量的模型是可以上传的)。如下所示,上传clip 将图片转为向量的模型。会报错
docker run -it -v /u01/isi/.cache/huggingface/hub/sentence-transformers/clip-vit-base-patch32:/eland/sentence-transformers/clip-vit-base-patch32 --rm elastic/eland
eland_import_hub_model
--url http://elastic:123123@10.99.100.49:9200
--hub-model-id sentence-transformers/clip-vit-base-patch32
--task-type text_embedding
--start
报错如下

准备工作
-
需要搭建一个8.8以上版本的ES集群。默认会开启安全访问认证,不要关它。
-
使用源码构建eland工具
-
从huggingface上,离线下载NLP模型
-
将模型上传到构建eland的服务器上
安装Elasticsearch 和kibana
这里参看以下文章,跟着搭建集群就可以了(其实我整个导入的过程,也是参考的这篇文章,只是在国内安装,遇到了上述的坑)。
Elasticsearch:如何在 Elastic 中实现图片相似度搜索_es 相似度查询_Elastic 中国社区官方博客的博客-CSDN博客
搭建的es版本>=8.8.0 ,一定要开安全认证,不然无法开启机器学习的试用,无法导入模型
需要kibana
开启试用



可以看到模型

安装准备Eland
eland是如何工作的
Eland 可以从huggingFace上,把模型下载下来,并上传导es中。如下图所示

应该如何安装eland
这里提供在线的方式,和离线的方式。
Eland 可以通过 pip 从 PyPI 安装
在安装之前,我们需要安装好自己的 Python。
$ python --version`
`Python 3.10.2`
`
可以使用 Pip 从 PyPI 安装 Eland:
python -m pip install eland
可以使用 Conda 从 Conda Forge 安装 Eland
conda install -c conda-forge eland
Docker容器的方式来使用它
希望在不安装 Eland 的情况下使用它,为了只运行可用的脚本,可以构建 Docker 容器。个人认为这种方式是最符合生产环境的部署方式。易交付。可以移植,不依赖网络环境,可以提前构件好,然后将eland镜像导入。
第一步需要需要在有网的环境下,下载源码。可以将源码上传到有docker环境的服务器上。(如果没有docker环境,可以以最简单的方式来安装docker,这里就不提供方法了,可以网上搜搜文章,是在不行麻烦麻烦运维同事)
# 下载源码
git clone https://github.com/elastic/eland
# 这里可以把源码上传到有docker环境的,且能够访问到es集群的服务器上。`
`cd eland
这里注意,因为是在国内,我们先pass掉挂代理的事情(并不一定每个人都能挂代理)
这里需要先编辑一下dockerFile,添加指定国内的源。添加如下一行
RUN python3 -m pip install --no-cache-dir --disable-pip-version-check .[all] -i https://mirror.baidu.com/pypi/simple
`
#然后构建镜像
`docker build -t elastic/eland .`
`
在huggingface上下载所需的NLP模型
在huggingface上找到该模型。(这里可以根据自己的需求,找到合适的模型)这里我以CLIP的模型为例(这个是clip中做文本embedding的模型),来下载。
https://huggingface.co/sentence-transformers/clip-ViT-B-32-multilingual-v1/tree/main
全部下载下来

然后上传到有eland的服务器上
使用eland 将离线模型导入到es集群中
我是以docker的方式来运行eland的。
这次主要是加里一个数据卷,我把下载后的模型,放在了 /u01/isi/.cache/huggingface/hub/sentence-transformers/clip-ViT-B-32-multilingual-v1 下,然后加了一个数据拒卷。把模型映射到了容器中。这里因为服务器无法访问huggingface去拉取模型。所以用离线的方式。eland,会在运行过程中,检查本地有没有模型,如果有模型,就不用去huggingface上拉取了。
注意eland的挂载目录,docker中映射的是/eland/目录,这样才能读到本地下载好的模型!
docker run -it -v /u01/isi/.cache/huggingface/hub/:/eland/ --rm elastic/eland \`
`eland_import_hub_model \`
`--url http://elastic:123123@10.99.100.49:9200 \`
`--hub-model-id sentence-transformers/clip-ViT-B-32-multilingual-v1 \`
`--task-type text_embedding \`
`--start`
`
可以看到,这里已经成功的导入模型了。

然后在kiabna上,找到模型管理,刷新一下。

已经成功刷新了出来

测试使用模型
对内容进行文本嵌入,在kiban上执行以下内容。点击D旁边的菜单栏,找到 Dev tools

POST _ml/trained_models/sentence-transformers__clip-vit-b-32-multilingual-v1/_infer`
`{`
`"docs"` `:` `[`
`{"text_field":` `"Yellow mountain is the most beautiful mountain in China"}`
`]`
`}
可以看到成功,应用模型,将文本内容,转成了向量。
