セマンティッククエリ

インデックスに ELSER 埋め込みが装備されたので、 app.pyhandle_search()関数を変更してこれらの埋め込みを検索できます。現時点では、ELSER のみを使用して検索する方法を説明します。後で、以前の検索方法を組み込んで、複合ソリューションを作成します。

検索時に ELSER 推論を使用するには、 text_expansionクエリ タイプが使用されます。以下に、このクエリで更新されたhandle_search()関数を示します。

@app.post('/')
def handle_search():
    query = request.form.get('query', '')
    filters, parsed_query = extract_filters(query)
    from_ = request.form.get('from_', type=int, default=0)

    results = es.search(
        query={
            'text_expansion': {
                'elser_embedding': {
                    'model_id': '.elser_model_2',
                    'model_text': parsed_query,
                }
            },
        },
        size=5,
        from_=from_,
    )
    return render_template('index.html', results=results['hits']['hits'],
                           query=query, from_=from_,
                           total=results['hits']['total']['value'])

text_expansionクエリは、検索するフィールドの名前を持つキーを受け取ります。このキーの下で、 model_id検索で使用するモデルを構成し、 model_text検索対象を定義します。この場合、Elasticsearch がモデルを管理し、それを処理できるため、検索テキストの埋め込みを生成する必要がないことに注意してください。

上記のバージョンのhandle_search()では、 filtersは未使用のままになっており、集計は省略されています。これらは、フルテキスト検索ソリューションに組み込まれたときと同じ方法で再度追加できます。以下は、 text_expansionクエリをbool.mustセクション内に移動する更新されたhandle_search()関数です。フィルターはbool.filterに含まれ、集計は以前と同じように追加されています。

@app.post('/')
def handle_search():
    query = request.form.get('query', '')
    filters, parsed_query = extract_filters(query)
    from_ = request.form.get('from_', type=int, default=0)

    results = es.search(
        query={
            'bool': {
                'must': [
                    {
                        'text_expansion': {
                            'elser_embedding': {
                                'model_id': '.elser_model_2',
                                'model_text': parsed_query,
                            }
                        },
                    }
                ],
                **filters,
            }
        },
        aggs={
            'category-agg': {
                'terms': {
                    'field': 'category.keyword',
                }
            },
            'year-agg': {
                'date_histogram': {
                    'field': 'updated_at',
                    'calendar_interval': 'year',
                    'format': 'yyyy',
                },
            },
        },
        size=5,
        from_=from_,
    )
    aggs = {
        'Category': {
            bucket['key']: bucket['doc_count']
            for bucket in results['aggregations']['category-agg']['buckets']
        },
        'Year': {
            bucket['key_as_string']: bucket['doc_count']
            for bucket in results['aggregations']['year-agg']['buckets']
            if bucket['doc_count'] > 0
        },
    }
    return render_template('index.html', results=results['hits']['hits'],
                           query=query, from_=from_,
                           total=results['hits']['total']['value'], aggs=aggs)

時間をかけてさまざまな検索を試してみてください。高密度ベクトル埋め込みと同様に、インデックス付けされたドキュメントに正確な単語が表示されない場合は、ELSER モデルによる検索の方が全文検索よりも効果的であることがわかります。

最先端の検索体験を構築する準備はできましたか?

十分に高度な検索は 1 人の努力だけでは実現できません。Elasticsearch は、データ サイエンティスト、ML オペレーター、エンジニアなど、あなたと同じように検索に情熱を傾ける多くの人々によって支えられています。ぜひつながり、協力して、希望する結果が得られる魔法の検索エクスペリエンスを構築しましょう。

はじめましょう