/ Модель

Характеристики

Контекст
512 токенов
Параметры
195 млн
Лицензия
Apache 2.0
Архитектура
bert · dense
Библиотека
sentence-transformers
Опубликована
21 фев 2025

opensearch-neural-sparse-encoding-multilingual-v1

ЭмбеддингиТекст → embedding4 профессии

Многоязычная разреженная BERT-модель OpenSearch для кодирования документов и запросов в поиске по текстам.

24 770скачиваний за 30 дней24лайкавеса обновлены30 июн 2025

Бенчмарки

Как модель справилась с задачами пользователей ailist и что о ней публикуют открытые лидерборды

Публичные оценки

Из открытых лидербордов. Сравнивайте результаты одного теста при одинаковых условиях — отсутствие оценки не значит, что модель хуже.

В подключённых источниках результатов для этой модели пока нет.

Что умеет модель

Описание составлено по карточке модели и метаданным Hugging Face

Многоязычная модель OpenSearch для разреженного поиска по текстам. Она построена на архитектуре BERT и содержит 194,6 млн параметров; репозиторий опубликован в формате safetensors. Модель обучена выдавать разреженные векторы размерности 105 879: при кодировании документов веса отражают важность токенов, а запросы можно представить разреженными векторами с помощью токенизатора и таблицы весов. Релевантность оценивается скалярным произведением векторов.

Модель предназначена для поиска документов и пассажей, расширения документов и семантического поиска с разреженным индексом OpenSearch на основе инвертированного индекса Lucene. В карточке приведены результаты на MIRACL для 15 языков, включая русский; для сокращения размера представления рекомендуется прореживание max_ratio. Контекст модели — до 512 токенов. В бенчмарке исключён тайский язык, поскольку uncased-основа не может его кодировать.

Модель выпущена участниками проекта OpenSearch по лицензии Apache-2.0. Её применение особенно связано с поисковой инфраструктурой OpenSearch; показатели бенчмарка относятся к MIRACL и сами по себе не гарантируют качество на других наборах данных и сценариях.

Сценарии применения

  • семантический поиск документов в OpenSearch
  • поиск по пассажам в многоязычных коллекциях
  • расширение документов для повышения полноты поиска
  • ранжирование документов по разреженным векторам

Ограничения

Контекст ограничен 512 токенами; в README отмечено, что uncased-основа не кодирует тайский язык. Результаты бенчмарка MIRACL могут не отражать качество на других коллекциях и задачах.

Для каких профессий подходит4

Разделы каталога профессий, в задачах которых используется эта модель

Все профессии

Карточка модели

README от автора на Hugging Face, как он его опубликовал

Открыть на Hugging Face

opensearch-neural-sparse-encoding-multilingual-v1

Select the model

The model should be selected considering search relevance, model inference and retrieval efficiency(FLOPS). We benchmark models' performance on MIRACL benchmark (we exclude th since the uncased backbone can not encode it). We recommend to use it with max_ratio pruning.

ModelInference-free for RetrievalModel ParametersAVG NDCG@10AVG FLOPSAVG EMB SIZE
opensearch-neural-sparse-encoding-multilingual-v1✔️160M0.6291.3138
opensearch-neural-sparse-encoding-multilingual-v1; prune_ratio 0.1✔️160M0.6260.875

Overview

This is a learned sparse retrieval model. It encodes the documents to 105879 dimensional sparse vectors. For queries, it just use a tokenizer and a weight look-up table to generate sparse vectors. The non-zero dimension index means the corresponding token in the vocabulary, and the weight means the importance of the token. And the similarity score is the inner product of query/document sparse vectors.

OpenSearch neural sparse feature supports learned sparse retrieval with lucene inverted index. Link: https://opensearch.org/docs/latest/query-dsl/specialized/neural-sparse/. The indexing and search can be performed with OpenSearch high-level API.

Usage (Sentence Transformers)

First install the Sentence Transformers library:

pip install -U sentence-transformers

Then you can load this model and run inference.

from sentence_transformers.sparse_encoder import SparseEncoder

# Download from the 🤗 Hub
model = SparseEncoder("opensearch-project/opensearch-neural-sparse-encoding-multilingual-v1")

query = "What's the weather in ny now?"
document = "Currently New York is rainy."

query_embed = model.encode_query(query)
document_embed = model.encode_document(document)

sim = model.similarity(query_embed, document_embed)
print(f"Similarity: {sim}")
# Similarity: tensor([[7.7400]])

decoded_query = model.decode(query_embed)
decoded_document = model.decode(document_embed)

for i in range(len(decoded_query)):
    query_token, query_score = decoded_query[i]
    doc_score = next((score for token, score in decoded_document if token == query_token), 0)
    if doc_score != 0:
        print(f"Token: {query_token}, Query score: {query_score:.4f}, Document score: {doc_score:.4f}")

# Token: weather, Query score: 3.0699, Document score: 1.2821
# Token: now, Query score: 1.6406, Document score: 0.9018
# Token: ?, Query score: 1.6108, Document score: 0.3141
# Token: ny, Query score: 1.2721, Document score: 1.3446
# Token: in, Query score: 0.6005, Document score: 0.1804

Usage (HuggingFace)

This model is supposed to run inside OpenSearch cluster. But you can also use it outside the cluster, with HuggingFace models API.

import json
import itertools
import torch

from transformers import AutoModelForMaskedLM, AutoTokenizer


# get sparse vector from dense vectors with shape batch_size * seq_len * vocab_size
def get_sparse_vector(feature, output, prune_ratio=0.1):
    values, _ = torch.max(output*feature["attention_mask"].unsqueeze(-1), dim=1)
    values = torch.log(1 + torch.relu(values))
    values[:,special_token_ids] = 0
    max_values = values.max(dim=-1)[0].unsqueeze(1) * prune_ratio
    return values * (values > max_values)
    
# transform the sparse vector to a dict of (token, weight)
def transform_sparse_vector_to_dict(sparse_vector):
    sample_indices,token_indices=torch.nonzero(sparse_vector,as_tuple=True)
    non_zero_values = sparse_vector[(sample_indices,token_indices)].tolist()
    number_of_tokens_for_each_sample = torch.bincount(sample_indices).cpu().tolist()
    tokens = [transform_sparse_vector_to_dict.id_to_token[_id] for _id in token_indices.tolist()]

    output = []
    end_idxs = list(itertools.accumulate([0]+number_of_tokens_for_each_sample))
    for i in range(len(end_idxs)-1):
        token_strings = tokens[end_idxs[i]:end_idxs[i+1]]
        weights = non_zero_values[end_idxs[i]:end_idxs[i+1]]
        output.append(dict(zip(token_strings, weights)))
    return output
    
# download the idf file from model hub. idf is used to give weights for query tokens
def get_tokenizer_idf(tokenizer):
    from huggingface_hub import hf_hub_download
    local_cached_path = hf_hub_download(repo_id="opensearch-project/opensearch-neural-sparse-encoding-multilingual-v1", filename="idf.json")
    with open(local_cached_path) as f:
        idf = json.load(f)
    idf_vector = [0]*tokenizer.vocab_size
    for token,weight in idf.items():
        _id = tokenizer._convert_token_to_id_with_added_voc(token)
        idf_vector[_id]=weight
    return torch.tensor(idf_vector)

# load the model
model = AutoModelForMaskedLM.from_pretrained("opensearch-project/opensearch-neural-sparse-encoding-multilingual-v1")
tokenizer = AutoTokenizer.from_pretrained("opensearch-project/opensearch-neural-sparse-encoding-multilingual-v1")
idf = get_tokenizer_idf(tokenizer)

# set the special tokens and id_to_token transform for post-process
special_token_ids = [tokenizer.vocab[token] for token in tokenizer.special_tokens_map.values()]
get_sparse_vector.special_token_ids = special_token_ids
id_to_token = ["" for i in range(tokenizer.vocab_size)]
for token, _id in tokenizer.vocab.items():
    id_to_token[_id] = token
transform_sparse_vector_to_dict.id_to_token = id_to_token



query = "What's the weather in ny now?"
document = "Currently New York is rainy."

# encode the query
feature_query = tokenizer([query], padding=True, truncation=True, return_tensors='pt', return_token_type_ids=False)
input_ids = feature_query["input_ids"]
batch_size = input_ids.shape[0]
query_vector = torch.zeros(batch_size, tokenizer.vocab_size)
query_vector[torch.arange(batch_size).unsqueeze(-1), input_ids] = 1
query_sparse_vector = query_vector*idf

# encode the document
feature_document = tokenizer([document], padding=True, truncation=True, return_tensors='pt', return_token_type_ids=False)
output = model(**feature_document)[0]
document_sparse_vector = get_sparse_vector(feature_document, output)


# get similarity score
sim_score = torch.matmul(query_sparse_vector[0],document_sparse_vector[0])
print(sim_score)   # tensor(7.6317, grad_fn=<DotBackward0>)


query_token_weight = transform_sparse_vector_to_dict(query_sparse_vector)[0]
document_query_token_weight = transform_sparse_vector_to_dict(document_sparse_vector)[0]
for token in sorted(query_token_weight, key=lambda x:query_token_weight[x], reverse=True):
    if token in document_query_token_weight:
        print("score in query: %.4f, score in document: %.4f, token: %s"%(query_token_weight[token],document_query_token_weight[token],token))
        

        
# result:
# score in query: 3.0699, score in document: 1.2821, token: weather
# score in query: 1.6406, score in document: 0.9018, token: now
# score in query: 1.6108, score in document: 0.3141, token: ?
# score in query: 1.2721, score in document: 1.3446, token: ny

The above code sample shows an example of neural sparse search. Although there is no overlap token in original query and document, but this model performs a good match.

Detailed Search Relevance

ModelAveragebnteesfridhiruarzhfajafiswkoen
BM250.3050.4820.3830.0770.1150.2970.3500.2560.3950.1750.2870.3120.4580.3510.3710.267
opensearch-neural-sparse-encoding-multilingual-v10.6290.6700.7400.5420.5580.5820.4860.6580.7400.5620.5140.6690.7670.7680.6070.575
opensearch-neural-sparse-encoding-multilingual-v1; prune_ratio 0.10.6260.6670.7400.5370.5550.5760.4810.6550.7370.5580.5110.6640.7610.7660.6040.572

License

This project is licensed under the Apache v2.0 License.

Copyright

Copyright OpenSearch Contributors. See NOTICE for details.

Как запустить

На своей GPU в ailist. Цена — по текущим предложениям провайдеров

GPU в ailist

Универсальный рантайм · sentence-transformers

Нельзя запустить

Первый модуль sentence-transformers (sentence_transformers.models.Router) рантайм не поддерживает.

Класс архитектуры
BertForMaskedLM
Ревизия весов
1e0f096

0 моделей