メタ検索エンジン「SearXNG」を試す
検索+生成AIサービスである「Perplexity」のOSSクローンをいくつか試していた。
その中で、検索部分にSearXNGというものがよく使われていた。
SearXNGは、70以上の検索サービスからの結果を集約した無料のインターネット・メタ検索エンジンである。ユーザーは追跡もプロファイリングもされない。さらに、SearXNGはオンライン匿名性のためにTor上で使用することができる。
少し気になったので試してみようと思う。
インストール
3つの方法がある。
- Docker
- インストールスクリプト
- 手動
今回はDockerを使うのだけど、ドキュメントとGitHubのREADMEでは書いてあることが少しだけ違う。
ドキュメントの方はSearXNGのDockerイメージをそのままpullして使う感じ。
それに対して、GitHubのDockerインストールのリンク先は以下のレポジトリになっていて、SearXNGだけでなく、Let's Encrypt・リバースプロキシ・インメモリデータベースなどもまとめてdocker composeで動かすような感じになっている。外部に公開するとかだとこちらのほうがいいかもしれない。
今回なシンプルにドキュメントの方に従って進めることとする。LAN内のUbuntuサーバにセットアップする。
作業ディレクトリを作る。
$ mkdir searxng-test && cd searxng-test
SearXNGのイメージをpullする。
$ docker pull searxng/searxng
コンテナを起動する。ポート番号は適当に設定。今回のようにリモートサーバで動かす場合にはBASE_URL
を書き換える必要がある。ローカルホストで動かす場合にはドキュメントどおりで良い。
$ export PORT=8080
$ docker run --rm \
-d -p ${PORT}:8080 \
-v "${PWD}/searxng:/etc/searxng" \
-e "BASE_URL=http://XXX.XXX.XXX.XXX:$PORT/" \
-e "INSTANCE_NAME=my-searxng-instance" \
searxng/searxng
ちょっと余談。
自分の環境だけなのかもしれないけども、上記で起動した後、検索を行うと「DuckDuckGoの検索が10秒ぐらいかかってタイムアウトしてしまう」という事象があった。で、SearXNGの正しい挙動なのかまだわかってないけども、この場合、複数の検索エンジンのうち1つでもタイムアウトすると全部の検索が失敗として扱われてしまうように見えた。
ローカルのMac上で同じように動かしても特に問題ないので、何かしら環境依存ではないかと思ってはいるのだけども、これに対しての対策は2つ。
- 初回起動時にバインドマウントしている領域に作成されるsettings.yamlの以下の箇所を修正してタイムアウトを伸ばす
(snip)
outgoing:
# default timeout in seconds, can be override by engine
request_timeout: 3.0
(snip)
設定を変更してコンテナを再起動すればOK。20秒ぐらいに設定するとタイムアウトは起きなくなった、が当然ながら遅い。
- ホストモード(
--net=host
)を使う
コンテナ起動時に--net=host
をつけてホストモードネットワークで起動する。ブリッジやiptablesのポートマッピング等を経由せずにそのままホスト側ネットワークを使用することになるので、当然ながら速い。ただしポートマッピングができなくなり、コンテナのポートがそのままホストのポートで使用されることになる。
$ docker run --rm \
--net=host \
-v "${PWD}/searxng:/etc/searxng" \
-e "BASE_URL=http://XXX.XXX.XXX.XXX:8080/" \
-e "INSTANCE_NAME=my-searxng-instance" \
searxng/searxng
今回はこちらで進めた。
参考)https://qiita.com/MetricFire/items/b731c84975bd9894748d
起動したらブラウザでアクセスする。こんな感じの画面が表示される。
検索してみる。
検索結果は以下のような感じ。複数の検索エンジンから取得されていることがわかる。
画像や動画などでも検索できるし、あと設定も非常に豊富。
このあたりはドキュメントを確認するなり実際に試してみるなりするのが良いと思う。
SearXNGにはSearch APIがあり、API経由で検索を行うことができる。
デフォルトだと出力はHTMLで返ってくるのだけど、JSONでも返すことができる。JSONでの出力を有効化するにはsettings.ymlを修正する。
$ sudo vi searxng/settings.yml
(snip)
search:
(snip)
# remove format to deny access, use lower case.
# formats: [html, csv, json, rss]
formats:
- html
- json # 追加
(snip)
コンテナを再起動する。
$ docker container restart [コンテナID or コンテナ名]
ではcurlで実行してみる。
$ curl -L -X GET http://localhost:8080 --data-urlencode q='オグリキャップ' -d format=json -d language=ja | jq -r .
{
"query": "オグリキャップ",
"number_of_results": 0,
"results": [
{
"url": "https://db.netkeiba.com/horse/1985102167/",
"title": "オグリキャップ (Oguri Cap) | 競走馬データ - netkeiba",
"content": "オグリキャップ (Oguri Cap)の競走馬データです。競走成績、血統情報、産駒情報などをはじめ、50万頭以上の競走馬・騎手・調教師・馬主・生産者・レースの全データがご覧いただけます。",
"publishedDate": null,
"thumbnail": "",
"engine": "brave",
"parsed_url": [
"https",
"db.netkeiba.com",
"/horse/1985102167/",
"",
"",
""
],
"template": "default.html",
"engines": [
"brave",
"duckduckgo"
],
"positions": [
1,
2
],
"score": 3,
"category": "general"
},
{
"url": "https://ja.wikipedia.org/wiki/オグリキャップ",
"title": "オグリキャップ",
"content": "2 週間前 - オグリキャップ(欧字名:Oguri Cap、1985年3月27日 - 2010年7月3日)は、日本の競走馬、種牡馬。 · 1987年5月に岐阜県の地方競馬・笠松競馬場でデビュー。8連勝、重賞5勝を含む12戦10勝を記録した後、1988年1月に中央競馬へ移...",
"publishedDate": null,
"thumbnail": "",
"engine": "brave",
"parsed_url": [
"https",
"ja.wikipedia.org",
"/wiki/オグリキャップ",
"",
"",
""
],
"template": "default.html",
"engines": [
"brave",
"duckduckgo"
],
"positions": [
2,
1
],
"score": 3,
"category": "general"
},
{
"url": "https://www.jra.go.jp/gallery/3minmeiba/horse13/",
"title": "オグリキャップ3分でわかった気になる名馬",
"content": "オグリキャップは地方・笠松競馬場でデビューし、重賞6連勝で中央・瀬戸口厩舎に移籍した。ジャパンカップや安田記念などの重賞を制したが、1990年の有馬記念で奇跡の復活を果たした。JRAの公式サイトでオグリキャップのプロフィールやレース映像、フォトギャラリーなどを見ることができる。",
(snip)
なるほど、広告も出ないし、プライバシーにも配慮されているならば、使いやすい。無料で使える?っぽいのでそのあたりも良いところ。
ただ、一応Google検索も使えるようなのだけども、Googleって広告が出なくなるのは規約的にいいんだっけ?というところは気になった。
参考)
とはいえ有料の検索サービスを否定するものではない。TavilyあたりはLLMで使いやすい出力にしてくれるというメリットがあるはずだし、そのへんはユースケースに合わせて。
LangChainだと公式にインテグレーションされている