Rustで実装されたSearXNG

2026/08/04 1:41

Rustで実装されたSearXNG

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

metadata-search-engine-rs
は、SearXNG に着想を得たオープンソースの Rust 製検索アグリゲーターであり、ユーザーがプライベートな検索エンジンをセルフホストすることを可能にします。複数のプロバイダー(DuckDuckGo、Brave、Startpage、Yahoo など)に対して同時クエリを実行することで単一情報源へのバイアスを排除し、結果を結合する際に見返しランク融合(Reciprocal Rank Fusion, RRF)という数学的ランキング手法
score = Σ 1/(60 + rank)
を使用します。システムは追跡パラメータの削除、URL の正規化、エントリの重複排除などによりクリーンなデータを確保し、ヘルスチェック用エンドポイント(
/health
)と検索用エンドポイント(
/search
)を含むセキュアな JSON API を通じて結果を提示します。インストールは Cargo またはソースから行うことが容易で、ライブラリ統合とサーバー展開の両方をサポートしています(例:
cargo run --release
でポートと結果制限を設定可能)。ローカル利用のためには、
ratatui
によって支えられた専用ターミナルインターフェースがインタラクティブな体験を提供します。開発者はプロジェクトの
SearchEngine
トレイトを実装した新しいエンジンを追加することで機能拡張を容易に行い、タイムアウト管理も含まれています。このツールは組織に検索メタデータに対する完全な制御を可能にし、堅牢なエラーハンドリング(すべてのエンジン障害時などの 503 レスポンスを含む)と、自らのサーバーからのカスタマイズ可能なクエリ処理を搭載しています。

本文

SearXNG スタイルのメタデータ検索エンジン(Rust)

Rust で記述された、SearXNG スタイルのメタデータ検索エンジンです。複数の検索エンジンにクエリを同時並列で送信し、HTML をスクレイピングして結果を返します。

仕組み

  1. リクエスト受付:
    GET /search?q=<query>
    に検索リクエストが到達します。
  2. 並列処理: クエリは
    reqwest
    を使用して、DuckDuckGo、Brave、Startpage、Yahoo へのクエリを同時並列で送信します。
  3. HTML パース: Mozilla の
    html5ever
    を基盤とする CSS セレクトルの仕組み(
    scraper
    ライブラリ)を用いて HTML レスポンスを解析します。
  4. 重複排除: URL 正規化(パラメータ追跡、ロケールプレフィックス除去、クエリパラメータソート)により結果を重複排除します。
  5. スコアリング:
    • 重複した URL は統合され、**相互順位フュージョン(Reciprocal Rank Fusion, RRF)**でスコアリングされます。
    • スコア計算式:
      score = Σ 1/(60 + rank)
    • 複数のエンジンから返されたページほど、高いスコアを獲得します。
  6. レスポンス: 上位の結果が JSON 形式で返却されます。

要件

  • Rust 1.75 以降
  • Cargo

インストール

ライブラリとして利用する場合

Cargo.toml
に以下の記述を追加します:

[dependencies]
metadata-search-engine-rs = "0.1"

または、

cargo add
を使用することも可能です:

cargo add metadata-search-engine-rs

サーバーとして利用する場合(ソースコードから)

git clone https://github.com/MikeLuu99/searxng-rust
cd metadata-search-engine-rs
cargo build --release

実行方法

環境変数を指定して実行します:

PORT=8080 MAX_RESULTS=20 cargo run --release

デバッグログを有効にするには、適切な環境変数または設定ファイルを指定してください。

使用例

単一のエンジンを実行する場合

Cargo.toml
に以下の依存関係を追加します:

[dependencies]
metadata-search-engine-rs = "0.1"
tokio = { version = "1", features = ["full"] }

コード例:

use std::sync::Arc;
use metadata_search_engine_rs::engines::{DuckDuckGoEngine, SearchEngine, build_http_client};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let client = Arc::new(build_http_client()?);
    let engine = DuckDuckGoEngine::new(client);

    let results = engine.search("rust programming", 5).await?;
    for r in results {
        println!("{}\n  {}", r.title, r.url);
    }
    Ok(())
}

すべてのエンジンにクエリを広げ、RRF ランキングを取得する場合

複数のエンジン(DuckDuckGo、Brave、Startpage、Yahoo)を使用し、スコア付きの結果を統合します。

コード例:

use std::sync::Arc;
use metadata_search_engine_rs::{
    aggregator::{aggregate, query_all_engines},
    engines::{BraveEngine, DuckDuckGoEngine, SearchEngine, StartpageEngine, YahooEngine, build_http_client},
};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let client = Arc::new(build_http_client()?);
    let engines: Vec<Arc<dyn SearchEngine>> = vec![
        Arc::new(DuckDuckGoEngine::new(Arc::clone(&client))),
        Arc::new(BraveEngine::new(Arc::clone(&client))),
        Arc::new(StartpageEngine::new(Arc::clone(&client))),
        Arc::new(YahooEngine::new(Arc::clone(&client))),
    ];

    let (successes, failures) = query_all_engines(&engines, "rust programming", 10).await;
    
    // エラー処理
    for (name, err) in &failures {
        eprintln!("engine {name} failed: {err}");
    }

    let results = aggregate(successes, 10);
    for r in &results {
        println!("[{:.3}] ({}) {}", r.score, r.engines.join(", "), r.title);
        println!("        {}", r.url);
    }
    Ok(())
}

特定のエンジンのみを使用する場合

指定したエンジン(例:DuckDuckGo と Brave)のみを使用し、スニペットを含む結果を出力します。

コード例:

use std::sync::Arc;
use metadata_search_engine_rs::{
    aggregator::{aggregate, query_all_engines},
    engines::{BraveEngine, DuckDuckGoEngine, SearchEngine, build_http_client},
};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let client = Arc::new(build_http_client()?);
    let engines: Vec<Arc<dyn SearchEngine>> = vec![
        Arc::new(DuckDuckGoEngine::new(Arc::clone(&client))),
        Arc::new(BraveEngine::new(Arc::clone(&client))),
    ];

    let (successes, _) = query_all_engines(&engines, "tokio async rust", 5).await;
    
    for r in aggregate(successes, 5) {
        println!("{} — {}", r.title, r.url);
        if let Some(snippet) = r.snippet {
            println!("  {snippet}");
        }
    }
    Ok(())
}

API

  • GET /health
    : サーバーの状態確認
    例:
    curl http://localhost:3000/health
  • GET /search?q=<query>
    : 検索実行
    例:
    curl "http://localhost:3000/search?q=rust"

レスポンス例:

{
  "query": "rust",
  "results": [
    {
      "title": "Rust Programming Language",
      "url": "https://rust-lang.org/",
      "snippet": "A language empowering everyone to build reliable and efficient software.",
      "engines": ["duckduckgo", "brave", "startpage", "yahoo"],
      "score": 0.049
    }
  ],
  "engines_queried": ["duckduckgo", "brave", "startpage", "yahoo"],
  "engines_failed": []
}

エラーレスポンス

状況ステータスコードボディ
q
パラメータの欠落
400
{"error": "query parameter 'q' is required"}
q
が空である
400
{"error": "query parameter 'q' cannot be empty"}
すべてのエンジンでエラーが発生した場合503
{"error": "all engines failed to respond"}

テスト

全単位テスト

cargo test

特定のモジュールのみをテストする場合

cargo test normalizer
cargo test aggregator
cargo test engines::duckduckgo
cargo test engines::brave
cargo test engines::startpage
cargo test engines::yahoo
cargo test server::handlers

リアル環境でのテスト(インターネット接続が必要)

cargo test -- --ignored test_live

※注意: リアル環境テストは

#[ignore]
でマークされているため、デフォルトでは CI には実行されません。手動で実行して、HTML セレクトが実際のサイト上で正しく動作するか確認してください。

ターミナルユーザーインターフェース(TUI)

ratatui
ベースの TUI クレイトも利用可能です。GitHub からコードにアクセスできます。

新しい検索エンジンの追加方法

  1. src/engines/<name>.rs
    を作成します。

  2. Arc<reqwest::Client>
    を保持する構造体を実装します。

  3. SearchEngine
    トレイトを実装します:

    impl SearchEngine for MyEngine {
        fn name(&self) -> &'static str { "myengine" }
    
        fn search<'a>(
            &'a self,
            query: &'a str,
            max_results: usize,
        ) -> BoxFuture<'a, Result<Vec<SearchResult>, EngineError>> {
            Box::pin(async move {
                // HTML を取得し、scraper で解析して Vec<SearchResult> を返す
            })
        }
    }
    
  4. engines/mod.rs
    に追加し、
    main.rs
    で連携します。

  5. 構造体に

    timeout: Duration
    フィールドと、既存のエンジンと同様の
    new()/with_timeout()
    コンストラクタペアを追加し、タイムアウトをモジュール内の検索関数に渡すことを忘れないでください。

同じ日のほかのニュース

一覧に戻る →

2026/08/04 6:13

LLM は専門性を報酬とする

## 日本語翻訳: 大規模言語モデル(LLM)は、CSS など基本的なデジタルタスクへの参入障壁を下げていますが、深いドメイン知識の必要性を排除するものではありません。一般的に応用提示技術(generalist prompting techniques)を習得すれば真の価値を引き出せるという一般的な誤解がありますが、複雑な問題解決には特定の分野の知識が不可欠であり、それによって AI を効果的に導く必要があります。数学者のテレンス・ tao の LLM に関する研究に示されるように、専門的な成果は簡潔であるといったスタイル上のヒントではなく、真の理解から生じます。分野に対する親和性がない場合、ユーザーは出力を検証したり、モデルを高度な解決策へと導いたりすることができず、質問の工夫がいくら手巧くてもその限りではありません。著者は、トークンが無限にあっても、非専門家は Tao 氏のような複雑な数学問題においては彼のレベルには達できないと指摘しており、分野知識こそが決定的な要因であることを強調しています。したがって、モデルがさらに強くなるにつれて、人間が正確な要件を伝達し結果を検証するという役割がボトルネックとなります。そのためには、組織は平均的な成果を超えようとする場合、特別な訓練への投資や専門家を採用することが必要であり、AI 統合の未来は汎用的なインターネット検索スキルよりも、制約を定義し高品質な結果を確保するために特定分野での卓越した知識を育成することによって支えられるでしょう。

2026/08/03 23:15

デベロッパーツールのオープンソース化が必須です。

## 日本語翻訳: 人工知能(AI)エージェントは、大規模なユーザーコミュニティや複雑な設定ファイルに依存せずに個々の作成者がパーソナライズされたアプリケーションを構築することを可能にするため、ソフトウェア開発を変革しています。VS Code の拡張機能や vimdiff といった従来の API はリアルタイムでのファイル変更やバックグラウンド処理で苦戦するのに対し、Shelley とような AI エージェントは、上流リリースとの nightly スインジングや人間のレビュー前のコードのプリプロセスなどの複雑なタスクを自動的に処理します。これは、過去 5 年の間にエンジニアが高い維持コストと疑わしい投資対効果のためにカスタムツールを廃棄することが多かった時代から、現在、かつて高価なプラグインシステムを必要としたか多くのユーザーにアモルタイズされた機能が単一ユーザーのために瞬時に組み立てられることへの大きなシフトを示しています。著者は "meat.dev" というツールを作成することでこれを例示しました。このツールは大規模言語モデル(LLM)を使用して、差分からインポートやボイラープレートなど重要なコードを取り除き、開発者がコアアーキテクチャとエッジケース(「the meat」)に集中できるようにします。Shelley 内の発見可能なスキルとして構築されたこのエージェントは、単一のプロンプトでバックグラウンドスインジングなどの複雑なロジックを統合することを可能にし、手動のコマンドライン実行の必要性を排除します。さらに、エージェントによるパーソナライゼーションは学習曲線を劇的に削減し、ソリューションが「機能しているように見える」場合、大規模なレビューなしに小規模チームや個人開発者向けのカスタムソフトウェア(例:セルフホストされたブログ)を可能にします。Claude Code などのクローズドソースツールはソースコードへのアクセスを欠いているのに対し、オープンソースのエージェントはハードコーディングされた値の直接修正や Monobit を通じたビットマップフォントのようなカスタムアセットの統合、またはオンデマンドでの固有リソースの生成を可能にします。このシフトは、開発をレガシーなプラグインエコシステムと設定中心のワークフローから遠ざけ、自動化が効率的に日常運用を管理する一方で人間がコアアーキテクチャに完全に集中する未来へと導きます。

2026/08/04 2:08

より小さく、高速で、安全に:Kim i と G L M を大規模に展開するための実行方法

## Japanese Translation: Workers AI は、Cloudflare のインフラストラクチャ上で大規模な AI モデルの提供を進めており、NVIDIA Blackwell GPU と SGLang フレームワークを活用することでコストを大幅に削減するとともに速度を向上させながら精度を維持しています。本ソリューションは、モデル重みの圧縮、KV キャッシュメモリへの量子化、共有メモリの保護を実現するための整合性チェックという 3 つの中核技術を採用しています。 モデル重みについては、Workers AI がハイブリッド戦略を採用しており、応答のデコードには低精度の INT4 形式を使用します(GLM モデルでは約 60% のメモリ使用量削減を実現しながら、全精度重みから機能的不可能区別性 を維持)。一方、初期処理には高精度な形式を留保しています。KV キャッシュについては、BF16 から 8 ビット FP8 への量子化によりメモリサイズが半分になり、コンテキスト容量が倍増します(例えば、約 137 万トークンの対応が可能になり、従来の約 686 千トークンから)。MMLU や GSM8K などの主要なベンチマークにおける精度劣化はありません。 莫大な同時接続下での安定性を確保するため、Workers AI は共有 KV キャッシュに対して汎用整合性チェックを実装しており、数百件のリクエストが物理メモリページを共有する際のエラーを防いでいます。これにより、スループットおよびレイテンシに対するオーバーヘッドは 1% も未満です。これらの最適化により、同時接続制限が倍増し(例えば、64 つの同時リクエストへの対応が可能になり、従来の 32 から)、運用コストを約 30% 削減するとともに、モデルの信頼性を損なうことなくデコード速度を大幅に向上させることが可能になりました。技術が進化するにつれ、Workers AI は効率的なグローバル展開を実現するために新たな精度形式の検証を継続しています。

Rustで実装されたSearXNG | そっか~ニュース