SlackとElasticsearchを連携し、使いやすい検索システムを作成する
Elasticsearchと対話Botによる対話型の検索システム 第5回
ダウンロード サンプルファイル (2.2 KB)
検索処理部分との連携モジュールについて
前回の記事と異なる部分は以下の通りです。
- 応答の判断部分
- Elasticsearchによる検索処理部分
- Slackへの投稿部分
応答の判断部分
応答は質問かそうでないか判断して返すようにしています。判断基準は「?」(全角)もしくは「?」(半角)を含んでいるかどうか、です。質問の場合はElasticsearchによる検索処理を行います。
if len(self.data) >= 1 and "text" in self.data[0]:
input_text = self.data[0]["text"]
if "search_bot:" in input_text:
if "?" in input_text or "?" in input_text:
word = self.__search_word(input_text)
self.__slack_call(word)
else:
word = self.message
self.__slack_call(word)
検索処理部分
- 改行や判定のためのトリガーワードなど、検索に不要な単語を削除しています
- 検索のモジュールには1.の処理を行った後の、不要な単語を削除した文章を渡しています
- 検索モジュールから返却された結果があれば必要な部分のみを抽出し、返却されなければ「No match」という単語を返しています
注
環境によってはソースコード中に「¥」記号が表示される場合がありますが、実際にはバックスラッシュです。
replace_input = re.sub("search_bot:|\?|\?", "", input_text.strip())
self.elastic_search.search_data(replace_input)
if len(self.elastic_search.search_result) > 0:
hyp_batch = self.elastic_search.search_result[0]
word = hyp_batch["title"] + "\n" + hyp_batch["abstract"] + "\n" + hyp_batch["url"]
else:
word = "No match"
return word
Slackへの投稿部分
前回の記事と同様の内容なので詳細の説明は除きますが、wordに検索された単語が入っています。
print(self.slack_channel.api_call("chat.postMessage", username=self.user_name, channel=self.chan, text=word, \
icon_url=self.icon_url))
検索モジュールについて
- 初期設定
- 検索処理
- 検索クエリ設定
初期設定では以下のように「--link」で連携したコンテナの名前を指定します。この場合はElasticsearchのポート番号である9200番を指定しています。
self.es = Elasticsearch(['elasticsearch_dialogue'], port=9200,)
self.doc = {}
self.elastic_index = "_all"
self.search_result = []
検索結果を初期化して検索クエリを設定し、そのクエリを使用して検索後、ヒットした結果を配列に追加しています。
self.search_result = []
self.setting_search_query(search_key_word)
self.res = self.es.search(index=self.elastic_index, body=self.query)
for hit in self.res['hits']['hits']:
self.search_result.append(hit["_source"])
その下で検索用のクエリを作成しています。検索スコア設定の際に「boost」で値の重み付けを大きくしています。検索スコアの設定については初回の記事をご覧ください。今回のクエリの場合、「title」の方が検索における重要性を増すように作っています。
self.query = {
"query": {
"bool": {
"should": [
{
"match": {
"title": {
"query": "\"" + search_key_word + "\"",
"boost": 10
}
}
},
{
"match": {
"abstract": "\"" + search_key_word + "\""
}
}
]
}
}
}
では、動作確認を行います。前回の記事で設定した、Slack上でBotが反応するチャネルに対して「捕鯨?」と質問文を入力してみましょう。先ほどのスクリプトでSlackのコンテナに入っているため、以下のコマンドを打つと質問応答に対応するBotが立ち上がります。
python app.py
「捕鯨」と調べたかったのですが結果として「反捕鯨」が出ています。なぜこのような結果になったのかというと、「捕鯨」と登録されたデータの「abstract」に「捕鯨」に関係している要素が入っていないためです。そこで、「title」だけで検索してみます。「get_answer.py」の中にコメントアウトしている部分があるので、そのコメントアウトを外し、先ほどの検索クエリはコメントアウトしてください。
self.query = {
"query": {
"bool": {
"should": [
{
"match": {
"title": {
"query": "\"" + search_key_word + "\""
}
}
}]
}
}
}
再度、以下のコマンドを実行してください。
python app.py
この場合、「title」のみにフォーカスして「捕鯨」を検索しているため、欲しい結果を取得できます。本文も考慮して検索するほうが検索の質は向上しそうですが、データの品質によってはそうでない場合もあるため、今回のように確認を行いながら検索することが重要になってきます。
このように検索クエリを変えるだけでも多様な検索を行うことができます。さらに、この変更は検索用のコンテナに対する影響がないので、ここでも疎結合な環境による効果を体感できます。
なお、現状の実装では末尾ではなく文字列内に半角の「?」と全角の「?」が含まれた場合は反応するようになっているため、注意が必要です。
最後に
これでUI部分と検索部分を切り離した構成の、Elasticsearchと対話Botによる対話型の検索システムが作成できました。今回の構成の場合、単純な応答からルールを作成した応答への変更などは既存の検索部分を修正せずに行うことができます。また、UI部分もSlackからFacebook、LINEなどの多様なインターフェースに変更可能で、今回のようにDockerを使用した構成の魅力になっています。本記事の内容を応用していただけると幸いです。
参考
この記事は参考になりましたか?
既に会員の方はを行ってください。
- Elasticsearchと対話Botによる対話型の検索システム連載記事一覧
-
- SlackとElasticsearchを連携し、使いやすい検索システムを作成する
- 使いたくなる検索システムのUIをSlackBotで実現する
- Elasticsearchへの大量データ登録の効率化
- この記事の著者
-
WINGSプロジェクト 大串 正矢(オオグシ マサヤ)
<WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書、記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
-
山田 祥寛(ヤマダ ヨシヒロ)
静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数。
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
この記事は参考になりましたか?
この記事をシェア
