Open5

multipassでOpenSearch/OpenSearch Dashboardsを立てて遊んでみる

kun432kun432

ローカルのテスト用ということで、セキュリティ等はあまり気にしない方針で。

$ brew install multipass

以下の内容でcloud-initのコンフィグを作成する。恥ずかしながらJVMの設定はさっぱりわからない。メモリ4GB割り当てるとすれば半分でいっか、というだけ。適宜変更のこと。

cloud-config.yaml
#cloud-config

locale: ja_JP.UTF-8
timezone: Asia/Tokyo

users:
  - name: ubuntu
    plain_text_passwd: ubuntu
    sudo: ALL=(ALL) NOPASSWD:ALL

package_update: true
package_upgrade: true

packages:
  - sudo
  - wget
  - curl
  - tzdata
  - vim
  - git
  - jq
  - lsb-release
  - ca-certificates
  - gnupg2
  - unzip

runcmd:
  - echo "vm.max_map_count=262144" >> /etc/sysctl.conf
  - sysctl -p
  - curl -o- https://artifacts.opensearch.org/publickeys/opensearch.pgp | gpg --dearmor --batch --yes -o /usr/share/keyrings/opensearch-keyring
  - echo "deb [signed-by=/usr/share/keyrings/opensearch-keyring] https://artifacts.opensearch.org/releases/bundle/opensearch/2.x/apt stable main" > /etc/apt/sources.list.d/opensearch-2.x.list
  - echo "deb [signed-by=/usr/share/keyrings/opensearch-keyring] https://artifacts.opensearch.org/releases/bundle/opensearch-dashboards/2.x/apt stable main" > /etc/apt/sources.list.d/opensearch-dashboards-2.x.list
  - apt update
  - apt install -y opensearch opensearch-dashboards
  - |
    echo "network.host: 0.0.0.0" >> /etc/opensearch/opensearch.yml
  - |
    echo "discovery.type: single-node" >> /etc/opensearch/opensearch.yml
  - |
    echo "server.host: 0.0.0.0" >> /etc/opensearch-dashboards/opensearch_dashboards.yml
  - sed -i -e 's/-Xms1g/-Xms2g/' -e 's/-Xmx1g/-Xmx2g/' /etc/opensearch/jvm.options
  - systemctl enable opensearch
  - systemctl start opensearch
  - systemctl enable opensearch-dashboards
  - systemctl start opensearch-dashboards

VM起動。 CPU・メモリ・ディスクは適宜設定。

$ multipass launch 22.04 --name opensearch -c 4 -m 4g -d 50g --cloud-init cloud-config.yaml

なお、multipassはcloud-initで5分以上かかった場合に起動がタイムアウトする。ただし、実際はそのまま継続しているらしいので、もしタイムアウトした場合はログインしてcloud-initのログを確認すれば良い。

ログイン

$ multipass shell opensearch

OpenSearchの確認

$ systemctl status opensearch --no-pager
(snip)
     Active: active (running) since Tue 2023-11-21 04:58:20 JST; 4min 24s ago
(snip)

$ systemctl status opensearch-dashboards.service --no-pager
(snip)
     Active: active (running) since Tue 2023-11-21 04:58:21 JST; 3min 52s ago
(snip)

$ curl https://localhost:9200 -ku admin:admin
{
  "name" : "opensearch",
  "cluster_name" : "opensearch",
  "cluster_uuid" : "eF64GM-VSf6VOGRuSTO48A",
  "version" : {
    "distribution" : "opensearch",
    "number" : "2.11.0",
    "build_type" : "deb",
    "build_hash" : "4dcad6dd1fd45b6bd91f041a041829c8687278fa",
    "build_date" : "2023-10-13T02:56:27.374317074Z",
    "build_snapshot" : false,
    "lucene_version" : "9.7.0",
    "minimum_wire_compatibility_version" : "7.10.0",
    "minimum_index_compatibility_version" : "7.0.0"
  },
  "tagline" : "The OpenSearch Project: https://opensearch.org/"
}

$ curl -X GET https://localhost:9200/_cat/plugins?v -u 'admin:admin' --insecure
name       component                            version
opensearch opensearch-alerting                  2.11.0.0
opensearch opensearch-anomaly-detection         2.11.0.0
opensearch opensearch-asynchronous-search       2.11.0.0
opensearch opensearch-cross-cluster-replication 2.11.0.0
opensearch opensearch-custom-codecs             2.11.0.0
opensearch opensearch-geospatial                2.11.0.0
opensearch opensearch-index-management          2.11.0.0
opensearch opensearch-job-scheduler             2.11.0.0
opensearch opensearch-knn                       2.11.0.0
opensearch opensearch-ml                        2.11.0.0
opensearch opensearch-neural-search             2.11.0.0
opensearch opensearch-notifications             2.11.0.0
opensearch opensearch-notifications-core        2.11.0.0
opensearch opensearch-observability             2.11.0.0
opensearch opensearch-performance-analyzer      2.11.0.0
opensearch opensearch-reports-scheduler         2.11.0.0
opensearch opensearch-security                  2.11.0.0
opensearch opensearch-security-analytics        2.11.0.0
opensearch opensearch-sql                       2.11.0.0

ホスト側からもアクセスできることを確認する。まずVMのIPを確認。

$ multipass list
Name                    State             IPv4             Image
opensearch              Running           192.168.64.26    Ubuntu 22.04 LTS

上記IPに対して、先ほどと同じようにAPIを叩いてレスポンスが変えればOK。

$ curl https://192.168.64.26:9200 -ku admin:admin
$ curl -X GET https://192.168.64.26:9200/_cat/plugins?v -u 'admin:admin' --insecure

OpenSearch Dashboardsにもアクセスしてみる。ブラウザから同じIPのポート5601番にアクセスして以下のようなログイン画面が出てきたら、ID: admin、PW: adminでログインできればOK。

削除

$ multipass delete opensearch && multipass purge
kun432kun432

以下に従ってまずはsudachiを有効化する

https://zenn.dev/kun432/scraps/bbf3ffdf8da1c8

ダッシュボードのDevToolsから。

GET _cat/plugins?v
name       component                            version
opensearch opensearch-alerting                  2.11.0.0
opensearch opensearch-anomaly-detection         2.11.0.0
opensearch opensearch-asynchronous-search       2.11.0.0
opensearch opensearch-cross-cluster-replication 2.11.0.0
opensearch opensearch-custom-codecs             2.11.0.0
opensearch opensearch-geospatial                2.11.0.0
opensearch opensearch-index-management          2.11.0.0
opensearch opensearch-job-scheduler             2.11.0.0
opensearch opensearch-knn                       2.11.0.0
opensearch opensearch-ml                        2.11.0.0
opensearch opensearch-neural-search             2.11.0.0
opensearch opensearch-notifications             2.11.0.0
opensearch opensearch-notifications-core        2.11.0.0
opensearch opensearch-observability             2.11.0.0
opensearch opensearch-performance-analyzer      2.11.0.0
opensearch opensearch-reports-scheduler         2.11.0.0
opensearch opensearch-security                  2.11.0.0
opensearch opensearch-security-analytics        2.11.0.0
opensearch opensearch-sql                       2.11.0.0

プラグインのインストール

https://opensearch.org/docs/latest/install-and-configure/plugins/

OpenSearchのコマンドは/usr/share/opensearch/binにある。

$ /usr/share/opensearch/bin/opensearch-plugin list
opensearch-alerting
opensearch-anomaly-detection
opensearch-asynchronous-search
opensearch-cross-cluster-replication
opensearch-custom-codecs
opensearch-geospatial
opensearch-index-management
opensearch-job-scheduler
opensearch-knn
opensearch-ml
opensearch-neural-search
opensearch-notifications
opensearch-notifications-core
opensearch-observability
opensearch-performance-analyzer
opensearch-reports-scheduler
opensearch-security
opensearch-security-analytics
opensearch-sql

sudachiプラグインは以下。

https://github.com/WorksApplications/elasticsearch-sudachi

OpenSearch-2.8.0より上のバージョン向けがない。最も近い2.8.0用のものをインストールしてみる。

$ sudo /usr/share/opensearch/bin/opensearch-plugin install https://github.com/WorksApplications/elasticsearch-sudachi/releases/download/v3.1.0/opensearch-2.8.0-analysis-sudachi-3.1.0.zip

怒られた。やっぱりだめかー。

Exception in thread "main" java.lang.IllegalArgumentException: Plugin [analysis-sudachi] was built for OpenSearch version 2.8.0 but version 2.11.0 is running
	at org.opensearch.plugins.PluginsService.verifyCompatibility(PluginsService.java:395)
	at org.opensearch.plugins.InstallPluginCommand.loadPluginInfo(InstallPluginCommand.java:820)
	at org.opensearch.plugins.InstallPluginCommand.installPlugin(InstallPluginCommand.java:875)
	at org.opensearch.plugins.InstallPluginCommand.execute(InstallPluginCommand.java:276)
	at org.opensearch.plugins.InstallPluginCommand.execute(InstallPluginCommand.java:250)
	at org.opensearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:104)
	at org.opensearch.cli.Command.mainWithoutErrorHandling(Command.java:138)
	at org.opensearch.cli.MultiCommand.execute(MultiCommand.java:104)
	at org.opensearch.cli.Command.mainWithoutErrorHandling(Command.java:138)
	at org.opensearch.cli.Command.main(Command.java:101)
	at org.opensearch.plugins.PluginCli.main(PluginCli.java:60)
kun432kun432

いろいろやってみたが、javaよくわからん、新しいバージョン向けのsudachiプラグインが出てくることを祈りつつ、kuromojiプラグインをインストールすることとする。

opensearchのコマンドは/usr/share/opensearch/bin以下にインストールされていた。kuromojiプラグインをインストール。

$ sudo /usr/share/opensearch/bin/opensearch-plugin install analysis-kuromoji
$ sudo /usr/share/opensearch/bin/opensearch-plugin install analysis-icu
$ sudo systemctl restart opensearch

インストールされている

$ curl -X GET https://localhost:9200/_cat/plugins?v -u 'admin:admin' --insecure
name       component                            version
opensearch analysis-icu                         2.11.0
opensearch analysis-kuromoji                    2.11.0
(snip)

動作OK

$ curl -X GET https://localhost:9200/_analyze -u 'admin:admin' --insecure -H 'Content-Type:Application/json' -d '{"analyzer": "kuromoji","text": "我が家には柴犬とクロネコ、うさぎがいます。"}' | jq
{
  "tokens": [
    {
      "token": "我が家",
      "start_offset": 0,
      "end_offset": 3,
      "type": "word",
      "position": 0
    },
    {
      "token": "柴犬",
      "start_offset": 5,
      "end_offset": 7,
      "type": "word",
      "position": 3
    },
    {
      "token": "クロ",
      "start_offset": 8,
      "end_offset": 10,
      "type": "word",
      "position": 5
    },
    {
      "token": "ネコ",
      "start_offset": 10,
      "end_offset": 12,
      "type": "word",
      "position": 6
    },
    {
      "token": "うさぎ",
      "start_offset": 13,
      "end_offset": 16,
      "type": "word",
      "position": 7
    }
  ]
}

以前に作ったTMDBのデータを日本語化したものを使ってインデックスを作成する。

https://zenn.dev/kun432/scraps/e88eb6cb9eaab4

movie_jp_mapping.json
{
  "mappings": {
    "properties": {
      "id": {
        "type": "keyword"
      },
      "title": {
        "type": "text",
        "analyzer": "kuromoji"
      },
      "overview": {
        "type": "text",
        "analyzer": "kuromoji"
      },
      "genres": {
        "type": "keyword"
      },
      "poster": {
        "type": "keyword"
      },
      "release_date": {
        "type": "date",
        "format": "epoch_millis"
      }
    }
  }
}
$ curl -X PUT https://localhost:9200/movies_jp  -u 'admin:admin'  -H 'Content-Type:Application/json'  --insecure  -d @movie_jp_mapping.json | jq -r
{
  "acknowledged": true,
  "shards_acknowledged": true,
  "index": "movies_jp"
}

データを登録する

$ curl -X POST https://localhost:9200/_bulk -u 'admin:admin' --insecure -H 'Content-Type: Application/x-ndjson' --data-binary @movie_jp.jsonl | jq -r

検索

$ SEARCH_STR=$(cat <<EOS
{
    "size": 25,
    "query": {
        "multi_match": {
            "query": "シンケンジャー",
            "fields": ["title^2", "overview"]
        }
    }
}
EOS
)

$ curl -X GET https://localhost:9200/movies_jp/_search -u 'admin:admin' --insecure -H 'Content-Type: Application/json' -d "$SEARCH_STR" | jq -r

結果

{
  "took": 5,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 117,
      "relation": "eq"
    },
    "max_score": 29.145908,
    "hits": [
      {
        "_index": "movies_jp",
        "_id": "XXXXXX",
        "_score": 29.145908,
        "_source": {
          "id": "XXXXXX",
          "title": "天装戦隊ゴセイジャーVSシンケンジャー エピックon銀幕",
          "overview": "シンケンジャーに倒された(snip)",
          "genres": [
            (snip)
          ],
          "poster": "https://image.tmdb.org/t/p/w500/XXXXXXXXXX.jpg",
          "release_date": XXXXXXXXXX
        }
      },
      {
        "_index": "movies_jp",
        "_id": "XXXXXX",
        "_score": 26.722607,
        "_source": {
          "id": "XXXXXX",
          "title": "侍戦隊シンケンジャーVSゴーオンジャー銀幕BANG!!",
          "overview": "折神が舞い、炎神が駆け、(snip)",
          "genres": [
            (snip)
          ],
(snip)
kun432kun432

ここからやりたいこと。

  • データ検索時にベクトル検索を行う。
    • そのためには検索したいプロパティをベクトル化する必要がある
      • 事前にベクトル化したデータを登録するか
      • データ登録時にベクトル変換もセットで行うか→多分パイプラインを使う
  • キーワード検索とベクトル検索をセットで行うハイブリッド検索
    • 通常ハイブリッドは複数の検索結果をリランキングする必要があるが、これはどう行うのか?
  • RAGパイプライン
    • クエリを投げるだけでRAGの検索および生成を行い、その結果を返す