在 Elasticsearch 中使用日语语言的自然语言处理 (NLP) 模型来实现语义搜索

原文约600字,阅读约需2分钟。发表于:

从每天产生的大量内部文档和产品信息中快速查找所需的文档,是工作和日常生活中的一项极为重要的任务。然而,如果要搜索的文档数量庞大,即使是计算机实时重新读取所有文档并找到目标文件,也会是一个耗时的过程。在这种情况下,Elasticsearch® 和其他搜索引擎软件应运而生。在使用搜索引擎时,首先要创建搜索索引数据,以便使用文档中包含的关键搜索词来快速查找这些文档。不过,即使用户大致知道自己要搜索什么类型的信息,他们也可能想不起合适的关键词,或者可能会搜索具有相同含义的另一种措辞。借助 Elasticsearch,可以定义同义词和相似术语来处理这种情况,但在某些情况下,仅仅使用对应表将搜索查询转换为更合适的查询,可能没那么容易。为了解决这个问题,Elasticsearch 8.0 版发布了能够通过短语的语义内容进行搜索的矢量搜索功能。与此同时,我们还发布了一系列的博客文章,介绍如何使用 Elasticsearch 执行矢量搜索和其他 NLP 任务。不过,在发布 8.8 版之前,它都无法正确分析除英语以外的其他语言文本。在发布的 8.9 版中,Elastic 增加了可在文本分析处理中正确分析日语的功能。通过这项功能,Elasticsearch 能够对日语文本执行矢量搜索等语义搜索以及日语情感分析等自然语言处理任务。本文将提供具体的分步说明,介绍如何使用这些功能。!pip install torch==1.13 !pip install transformers !pip install sentence_transformers !pip install fugashi !pip install ipadic !pip install unidic_lite要使用日语模型,必须要安装 fugashi、ipadic 和 unidic_lite 库。在安装这些库之后,还可以安装 Eland。要使用日语模型,需要 Eland 8.9.0 或更高版本,因此请务必注意版本号。!pip install eland安装完成后,请使用下面的命令确认已安装的 Eland 可用。!eland_import_hub_model -h 导入 NLP 模型启用矢量搜索的主要方法与这篇文章中用于英语语言的方法相同。我们在这里简要回顾一下相同的过程。如上所述,必须将适当的 Machine Learning 模型导入 Elasticsearch 中,才能在 Elasticsearch 中实现 NLP 处理。您可以使用 PyTorch 自行实现一个 Machine Learning 模型,但这也需要具备足够的机器学习和自然语言处理专业知识,以及机器学习所需的计算能力。不过,现在有一个名为 Hugging Face 的在线存储库,被机器学习和自然语言处理领域的研究人员和开发人员广泛使用,而且有许多模型都发布到这个存储库中。在这个例中,我们将使用发布到 Hugging Face 的模型来实现语义搜索功能。首先,选取 Hugging Face 上的一个模型,将日语句子嵌入(矢量化为)数值矢量中。在本文中,我们将使用下面链接的模型。cl-tohoku/bert-base-japanese-v2下面我们来介绍一下在 8.9 版中选择日语模型时,需要注意的一些事项。首先,只支持 BERT 模型算法。查看 Hugging Face 上的标签和其他信息,确认所需的 NLP 模型是经过 BERT 训练的模型。此外,对于 BERT 和其他 NLP 任务,输入的文本都要经过“预分词”处理,也就是会在单词级别上将文本分割为多个单元。在本例中,我们使用了日语语言的形态分析引擎对日语文本进行预分词。Elasticsearch 8.9 版支持使用 MeCab 进行形态分析。在 Hugging Face 的模型页面上,打开“Files and versions”(文件和版本)选项卡,查看 tokenizer_config.json 文件的内容。确认 word_tokenizer_type 的值为 mecab。{ "do_lower_case": false, "word_tokenizer_type": "mecab", "subword_tokenizer_type": "wordpiece", "mecab_kwargs": { "mecab_dic": "unidic_lite" } } 如果您想使用的模型的 word_tokenizer_type 值不是 mecab,非常遗憾,Elasticsearch 目前不支持其他模型。对于需要支持的任何具体单词分词器类型 (word_tokenizer_type),我们欢迎大家提供反馈意见。在确定要导入的模型后,导入所需的步骤就与英语模型相同了。首先,使用 eland_import_hub_model 将模型导入 Elasticsearch 中。若要了解如何使用 eland_import_hub_model,请参考本页面。!eland_import_hub_model \ --url "https://your.elasticserach" \ --es-api-key "your_api_key" \ --hub-model-id cl-tohoku/bert-base-japanese-v2 \ --task-type text_embedding \ --start 成功导入模型后,可以在 Kibana 的“Machine Learning”>“Model Management”(模型管理)>“Trained Models”(已训练模型)下找到它。打开模型的“Config”(配置)选项卡,确认使用“bert_ja”进行分词,并且模型已经过正确设置,可以处理日语。https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb5ba7e76eeef113e/64ef8bb662b319b59185e3bc/elastic-blog-1-inference-configuration.png,elastic-blog-1-inference-configuration.png模型上传完成后,让我们来测试一下。单击“Actions”(操作)列中的按钮以打开菜单。https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt22cdfe7a7ac13b15/64ef8bf9cd0f23e475cb6df7/elastic-blog-2-actions.png,elastic-blog-2-actions.png选择“Test model”(测试模型),然后在“Input text”(输入文本)下输入任何日语短语,单击“Test”(测试)按钮。https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt02af60e9ff04ec71/64ef8c06185e8c2e2a21ecdb/elastic-blog-3-test-trained-model.png,elastic-blog-3-test-trained-model.png然后,您就可以看到这个模型将输入的日语文本矢量化为了一个数值字符串,如下所示。模型看起来运行正常。PUT _ingest/pipeline/japanese-text-embeddings { "description": "Text embedding pipeline", "processors": [ { "inference": { "model_id": "cl-tohoku__bert-base-japanese-v2", "target_field": "text_embedding", "field_map": { "title": "text_field" } } } ], "on_failure": [ { "set": { "description": "Index document to 'failed-'", "field": "_index", "value": "failed-{{{_index}}}" } }, { "set": { "description": "Set error message", "field": "ingest.failure", "value": "{{_ingest.on_failure_message}}" } } ] } 在使用推理处理器时,model_id 中指定的模型将应用于目标字段(在本例中是 title)中保存的文本,因此,输出会存储在 target_field 中。此外,每个模型都需要不同的字段(在本例中是 text_field)作为过程的输入值。因此,field_map 用于指定过程目标的实际输入字段与 ML 模型所需的字段名称之间的对应关系。设置好管道后,就可以用它来创建索引了。由于索引中需要有字段来存储矢量,因此我们需要定义适当的映射。在下面的示例中,text_embedding.predicted_value 字段被设置为存储 768 维度的 dense_vector 数据。请注意,维度的数量因模型而异。查看 Hugging Face 上的模型页面(模型的 config.json 中的 hidden_size 值)或其他位置,然后设置一个适当的数量。PUT japanese-text-with-embeddings { "mappings": { "properties": { "text_embedding.predicted_value": { "type": "dense_vector", "dims": 768, "index": true, "similarity": "cosine" } } } } 如果已经存在包含用于搜索的日语文本数据的索引,就可以使用重新索引 API。在本例中,原始文本数据位于 japanese-text 索引中。包含这些文本矢量化内容的文档将注册到 japanese-text-embeddings 索引中。POST _reindex?wait_for_completion=false { "source": { "index": "japanese-text" }, "dest": { "index": "japanese-text-with-embeddings", "pipeline": "japanese-text-embeddings" } } 另外,也可以通过指定一个如下所示创建的管道并将其存储在索引中,直接注册文档来进行测试。POST japanese-text-with-embeddings/_doc?pipeline=japanese-text-embeddings { "title": "日本語のドキュメントをベクトル化してインデックスに登録する。" } 注册完矢量化的文档后,此时就可以执行搜索了。kNN(k-最近邻)搜索是一种利用矢量的可用方法。我们现在将使用标准 _search API 中的 query_vector_builder 选项来执行 kNN 矢量搜索。使用 query_vector_builder 时,可以使用 model_id 中指定的模型,将 model_text 中的文本转换为包含嵌入该文本的矢量的查询。GET japanese-text-with-embeddings/_search { "knn": { "field": "text_embedding.predicted_value", "k": 10, "num_candidates": 100, "query_vector_builder": { "text_embedding": { "model_id": "cl-tohoku__bert-base-japanese-v2", "model_text": "日本語でElasticsearchを検索したい" } } } } 在执行这个搜索查询后,会收到以下类型的响应。 "hits": [ { "_index": "japanese-text-with-embeddings", "_id": "vOD6MIoBdRdLZd7EKaBy", "_score": 0.82438844, "_source": { "title": "日本語のドキュメントをベクトル化してインデックスに登録する。", "text_embedding": { "predicted_value": [ -0.13586345314979553, -0.6291824579238892, 0.32779985666275024, 0.36690405011177063, (略、768次元のベクトルが表示される) ], "model_id": "cl-tohoku__bert-base-japanese-v2" } } } ] 搜索成功!搜索还包含了已嵌入日语的字段。在大多数实际用例中,不需要将这些文本包含在响应中。在这类情况下,可以使用 _source 参数或其他方法,从响应中排除这些信息(或采取其他操作)。为了对搜索排名进行微调,可以使用已发布的倒数排序融合 (RRF) 功能,巧妙地将矢量搜索和标准关键字搜索的结果融合在一起。请务必也了解一下这项功能。关于如何使用矢量搜索来实现语义搜索的讨论先到这里。虽然设置这项功能可能需要完成比标准搜索更多的工作,而且还可能会遇到一些独特的机器学习词汇,但在完成设置阶段后,您就能够以几乎与正常搜索相同的方式执行搜索,所以请尝试一下。!eland_import_hub_model \ --url "https://your.elasticserach" \ --es-api-key "your_api_key" \ --hub-model-id koheiduck/bert-japanese-finetuned-sentiment \ --task-type text_classification \ --start 成功导入模型后,可以在 Kibana 的“Machine Learning”>“Model Management”(模型管理)>“Trained Models”(已训练模型)下找到它。https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt85fb6d7c0c749e81/64ef8c1f8c8fe9601b98b711/elastic-blog-4-inference-configuration2.png,elastic-blog-4-inference-configuration2.png在本例中,也是单击“Actions”(操作)菜单中的“Test model”(测试模型)。https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt400b9b6ac70557de/64ef8c4d185e8c078221ecdf/elastic-blog-5-actions2.png,elastic-blog-5-actions2.png与之前一样,这将显示一个用于测试的对话框。在此处输入要分类的文本,然后文本将被分类为“积极”、“中立”或“消极”。作为测试,我们输入:“我很高兴现在能够使用 Elasticsearch 执行 NLP 任务。” 如下所示,这条输入生成的结果是 99.2% 为积极情感。https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5706e88c8d5b777f/64ef8c6177e0cc6e7d9db8a1/elastic-blog-6-test-trained-model2.png,elastic-blog-6-test-trained-model2.png下面是通过 API 执行的相同过程。POST _ml/trained_models/koheiduck__bert-japanese-finetuned-sentiment/_infer { "docs": [{"text_field": "ElasticsearchでNLPのタスクが実行できるようになって嬉しい。"}], "inference_config": { "text_classification": { "num_top_classes": 3 } } } 响应如下:{ "inference_results": [ { "predicted_value": "POSITIVE", "top_classes": [ { "class_name": "POSITIVE", "class_probability": 0.9921651090124636, "class_score": 0.9921651090124636 }, { "class_name": "NEUTRAL", "class_probability": 0.006682728902566756, "class_score": 0.006682728902566756 }, { "class_name": "NEGATIVE", "class_probability": 0.0011521620849697567, "class_score": 0.0011521620849697567 } ], "prediction_probability": 0.9921651090124636 } ] }由于这个过程也可以使用推理处理器执行,因此在对日语文本建立索引之前,可附加上这些分析结果。例如,将这个过程应用于特定产品评论的文本,有助于将用户对这些产品的评级转换为数值。本博文所描述的任何特性或功能的发布及上市时间均由 Elastic 自行决定。当前尚未发布的任何特性或功能可能无法按时提供或根本不会提供。在本博文中,我们可能使用或提到了第三方生成式 AI 工具,这些工具由其各自所有者拥有和运营。Elastic 对第三方工具没有任何控制权,对其内容、操作或使用不承担任何责任或义务,对您使用此类工具可能造成的任何损失或损害也不承担任何责任或义务。在 AI 工具中使用个人、敏感或机密信息时,请务必谨慎。您提交的任何数据都可能用于 AI 训练或其他目的。Elastic 不保证您所提供信息的安全性或保密性。在使用任何生成式 AI 工具之前,您都应自行熟悉其隐私惯例和使用条款。Elastic、Elasticsearch、ESRE、Elasticsearch Relevance Engine 及相关标志为 Elasticsearch N.V. 在美国和其他国家/地区的商标、徽标或注册商标。所有其他公司和产品名称均为其相应所有者的商标、徽标或注册商标。

Elasticsearch 8.9版本新增了对日语文本的正确分析能力,可进行语义搜索和自然语言处理任务,如日语情感分析。文章提供了使用这些功能的逐步说明。

在 Elasticsearch 中使用日语语言的自然语言处理 (NLP) 模型来实现语义搜索
相关推荐 去reddit讨论