/ Модель

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

Контекст
512 токенов
Параметры
25,9 млн
Лицензия
Apache 2.0
Архитектура
bert · dense
Базовая модель
all-MiniLM-L6-v2
Библиотека
sentence-transformers
Опубликована
2 сен 2026

sbert-legal-v1-legacy

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

Англоязычный энкодер для поиска релевантных абзацев в судебных решениях Индии по юридическому запросу.

84скачиваний за 30 дней0лайковвеса обновлены2 сен 2026

Бенчмарки

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

Тесты пользователейпока нет

Никто ещё не опубликовал тест этой модели. Соберите бенчмарк из своих задач — результат появится здесь.

  1. Добавьте модель в бенчмарк

    Вместе с другими моделями категории «Эмбеддинги» — сравнение идёт внутри одной категории.

  2. Опишите свои задачи

    Напишите запросы, при необходимости приложите файлы и эталонные ответы.

  3. Запустите и опубликуйте

    Модели ответят на каждую задачу, судья оценит ответы. Опубликованный результат появится на этой странице.

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

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

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

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

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

SBERT Legal Paragraph Retrieval — англоязычный энкодер предложений, разработанный для поиска релевантных абзацев в корпусе судебных решений Индии. Модель создана дообучением sentence-transformers/all-MiniLM-L6-v2 и использует архитектуру Sentence Transformer с энкодером BERT, усреднением токенов и нормализацией векторов. Она преобразует запросы и абзацы в векторы размерности 384; косинусное сходство отражает юридическую релевантность. Максимальная длина последовательности в карточке README — 256 токенов; метаданные указывают контекст 512 токенов.

Модель предназначена для первого этапа поиска по судебной практике: она сопоставляет естественно-языковой запрос юриста с оригинальными абзацами решений и соответствующими краткими резюме. Обучение на 90 142 парах из 693 индийских судебных решений включало запросы разного стиля и примеры как с оригинальным текстом, так и с LLM-резюме. На отложенной выборке точность cosine_accuracy@1 составила 0,5051, @3 — 0,7408, @5 — 0,8375.

Модель рассчитана на английский язык и индийские судебные решения. Она не предназначена для генерации юридических советов, прогнозирования исхода дела или самостоятельного принятия решений; качество зависит от разбиения документов на абзацы. Тексты длиннее 256 токенов обрезаются, а модель не проверена на других юрисдикциях, законах, договорах и текстах общего назначения. README также сообщает о некотором преимуществе при поиске по LLM-резюме перед оригинальным текстом. Лицензия — Apache 2.0.

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

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

Ограничения

Модель обучена и оценена на английских судебных решениях Индии; её качество не подтверждено для других юрисдикций, законов, договоров или общих текстов. Последовательности длиннее 256 токенов обрезаются, а качество поиска зависит от разбиения документов на абзацы.

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

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

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

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

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

Открыть на Hugging Face

SBERT Legal Paragraph Retrieval (Indian Court Judgments)

This is a sentence-transformers bi-encoder finetuned from sentence-transformers/all-MiniLM-L6-v2 for legal paragraph retrieval: given a lawyer's natural-language query, retrieve the most relevant paragraph from a corpus of Indian court judgments. It maps sentences and paragraphs into a 384-dimensional vector space where cosine similarity reflects legal relevance.

Training data pairs each piece of legal content with two parallel representations — the original verbatim judgment text and an LLM-generated case-summary sentence — so the model is trained to retrieve either representation with comparable confidence for the same query, rather than learning a shortcut tied to one source's writing style.

A companion variant trained with chunk-and-pool encoding (for documents whose individual paragraphs exceed 256 tokens) is available at sbert-legal-v1-chunkpoolmean.

Model Details

  • Model type: Sentence Transformer (bi-encoder)
  • Base model: sentence-transformers/all-MiniLM-L6-v2
  • Maximum sequence length: 256 tokens (longer paragraphs are truncated — see "Splitting a judgment into paragraphs" below for why this is rarely an issue in practice)
  • Output dimensionality: 384
  • Similarity function: Cosine similarity
  • Language: English
  • Domain: Indian court judgments
  • License: Apache 2.0

Full Model Architecture

SentenceTransformer(
  (0): Transformer({'transformer_task': 'feature-extraction', 'architecture': 'BertModel'})
  (1): Pooling({'embedding_dimension': 384, 'pooling_mode': 'mean', 'include_prompt': True})
  (2): Normalize({})
)

Usage

Install the library first:

pip install -U sentence-transformers pdfplumber

If you're in Google Colab and hit an error like AttributeError: 'SentenceTransformer' object has no attribute 'encode_query': that method needs a very recent sentence-transformers version, and Colab often keeps the old version loaded in memory even after pip install -U until you restart the runtime (Runtime → Restart session). The example below avoids the issue entirely by using the standard .encode() method, which works on every version.

If loading raises TypeError: Pooling.__init__() missing 1 required positional argument: 'embedding_dimension': this model's saved config uses an older key name for the pooling module than the very newest sentence-transformers releases expect, so the one-line SentenceTransformer("vishnuprabha72/sbert-legal-v1-legacy") loader can fail to auto-infer that argument depending on which library version you have installed. Load it by explicitly constructing the modules instead — this always works regardless of version, and is what both examples below do.

Quick start (sanity check)

Confirms the model loads and encodes correctly before you build a full retrieval pipeline:

from sentence_transformers import SentenceTransformer, models

# Load explicitly via modules rather than the one-line loader — this sidesteps
# the Pooling config mismatch some sentence-transformers versions hit when
# auto-inferring embedding_dimension from an older saved config.
word_embedding_model = models.Transformer(
    model_name_or_path="vishnuprabha72/sbert-legal-v1-legacy"
)
embedding_dimension = word_embedding_model.get_word_embedding_dimension()
pooling_model = models.Pooling(embedding_dimension, pooling_mode="mean")
model = SentenceTransformer(modules=[word_embedding_model, pooling_model])

sentences = [
    "What are the essential conditions for granting a temporary injunction?",
    "The cardinal principles for grant of temporary injunction require a strong "
    "prima facie case, that non-interference would cause irreparable injury with "
    "no other remedy available, and that the balance of convenience favours the "
    "party seeking relief.",
    "The plaintiff filed suits for declaration and specific performance against "
    "the defendant companies regarding a total area of 19,685 square metres of "
    "land, contending a concluded contract existed after negotiations for a "
    "total sum running into several crores of rupees.",
    "The appeals are allowed and the orders of injunction granted by the trial "
    "court and affirmed by the High Court are set aside.",
]
embeddings = model.encode(sentences)

similarities = model.similarity(embeddings, embeddings)
print(similarities.shape)
# [4, 4]

The query (sentence 1) and the injunction-principles paragraph (sentence 2) should score noticeably higher against each other than either scores against the unrelated background-facts or disposition sentences — that's the retrieval behavior the rest of this section builds on.

Full example: retrieving a paragraph from a real judgment

This example uses excerpts from Ambalal Sarabhai Enterprise Ltd. v. K.S. Infraspace LLP (Supreme Court of India, Civil Appeal No. 9346/2019) — a specific-performance and injunction dispute — as a stand-in for "a judgment you've split into paragraphs."

from sentence_transformers import SentenceTransformer, util, models

# Load explicitly via modules rather than the one-line loader — this sidesteps
# the Pooling config mismatch some sentence-transformers versions hit when
# auto-inferring embedding_dimension from an older saved config.
word_embedding_model = models.Transformer(
    model_name_or_path="vishnuprabha72/sbert-legal-v1-legacy"
)
pooling_model = models.Pooling(
    word_embedding_model.get_word_embedding_dimension(),
    pooling_mode="mean",
)
model = SentenceTransformer(modules=[word_embedding_model, pooling_model])

# Paragraphs from one judgment (already split — see next section for how to
# do this automatically from a PDF).
paragraphs = [
    "The plaintiff filed suits for declaration and specific performance "
    "against the defendant companies regarding land measuring 19,685 square "
    "metres, contending that a concluded contract existed after negotiations "
    "for a total sum running into several crores of rupees.",

    "The Principal Civil Judge held that the terms and conditions for sale "
    "stood finalised by e-mail, that a token amount had already been paid, "
    "and restrained the defendants from executing any further documents or "
    "creating third-party rights in the suit lands.",

    "Section 36 of the Specific Relief Act, 1963 provides for grant of "
    "preventive relief, and Section 37 provides that temporary injunction in "
    "a suit shall be regulated by the Code of Civil Procedure. The grant of "
    "relief in a suit for specific performance is itself a discretionary "
    "remedy.",

    "The cardinal principles for grant of temporary injunction were "
    "considered in Dalpat Kumar v. Prahlad Singh: the court must be "
    "satisfied there is a prima facie case, that non-interference would "
    "result in irreparable injury with no other remedy available, and that "
    "the balance of convenience favours granting the injunction.",

    "The plaintiff was aware from the very inception that the defendant was "
    "negotiating for sale of the lands simultaneously with two others, and "
    "was further aware that the deal with it had fallen through before the "
    "registered agreement for sale was executed with defendant no. 2.",

    "The suit was filed seven months after the plaintiff acknowledged "
    "receiving a refund of its advance payment; in commercial dealings "
    "involving high-stake matters, such delay is a vital consideration "
    "against the grant of equitable relief.",

    "The appeals are allowed and the orders of injunction are set aside; "
    "nothing in this order shall be construed as an expression of opinion on "
    "the merits of the suit, which will be decided on its own merits at "
    "trial.",
]

query = "What are the essential conditions for granting a temporary injunction?"

query_embedding = model.encode(query, convert_to_tensor=True)
paragraph_embeddings = model.encode(paragraphs, convert_to_tensor=True)

scores = util.cos_sim(query_embedding, paragraph_embeddings)[0]
ranked = scores.argsort(descending=True)

for rank, idx in enumerate(ranked, start=1):
    print(f"[{rank}] score={scores[idx]:.4f}\n{paragraphs[idx]}\n")

This should rank the Dalpat Kumar / Section 36–37 passages at the top — those are the paragraphs that actually answer "what are the conditions for granting a temporary injunction," as opposed to the case's background facts or procedural history.

Splitting a judgment into paragraphs (from a PDF)

For a real workflow, you'll extract text from a judgment PDF and split it into paragraphs before encoding. Indian judgments are almost always numbered ("1. ...", "2. ...", etc.), so a simple regex on that pattern is a reasonable default:

import re
import pdfplumber
from sentence_transformers import SentenceTransformer, util, models

def extract_paragraphs(pdf_path, min_words=15):
    """Extract numbered paragraphs from a judgment PDF."""
    with pdfplumber.open(pdf_path) as pdf:
        full_text = "\n".join(page.extract_text() or "" for page in pdf.pages)

    # Split right before a numbered paragraph marker at the start of a line,
    # e.g. "\n15. The cardinal principles..."
    raw_chunks = re.split(r"\n(?=\d{1,3}\.\s+[A-Z])", full_text)

    paragraphs = []
    for chunk in raw_chunks:
        chunk = re.sub(r"\s+", " ", chunk).strip()
        if len(chunk.split()) >= min_words:
            paragraphs.append(chunk)
    return paragraphs

# See the loading note above — constructed explicitly to avoid the Pooling
# config mismatch.
word_embedding_model = models.Transformer(
    model_name_or_path="vishnuprabha72/sbert-legal-v1-legacy"
)
pooling_model = models.Pooling(
    word_embedding_model.get_word_embedding_dimension(),
    pooling_mode="mean",
)
model = SentenceTransformer(modules=[word_embedding_model, pooling_model])

paragraphs = extract_paragraphs("your_judgment.pdf")
print(f"Extracted {len(paragraphs)} paragraphs")

query = "your search query here"
query_embedding = model.encode(query, convert_to_tensor=True)
paragraph_embeddings = model.encode(paragraphs, convert_to_tensor=True)

scores = util.cos_sim(query_embedding, paragraph_embeddings)[0]
top_k = scores.topk(min(5, len(paragraphs)))

for score, idx in zip(top_k.values, top_k.indices):
    print(f"score={score:.4f}\n{paragraphs[idx]}\n")

This regex-based splitter is intentionally simple. Real judgments contain numbers inside citations (e.g. "33 Cal. 789") and quoted passages from other judgments, which can occasionally get mis-split as paragraph boundaries — always spot-check the extracted list on a document before trusting it fully, especially for footnote-heavy judgments. If most of your paragraphs are short (a few sentences), 256 tokens is comfortably enough and truncation rarely matters; if you're regularly working with very long paragraphs (dense LAW/REASON sections, 200+ words), use the chunk-pool variant instead, which was trained specifically to avoid truncating those.


Evaluation

Evaluated with InformationRetrievalEvaluator on the held-out validation split.

MetricValue
cosine_accuracy@10.5051
cosine_accuracy@30.7408
cosine_accuracy@50.8375
cosine_accuracy@100.925
cosine_precision@10.5051
cosine_precision@30.3231
cosine_precision@50.2406
cosine_precision@100.1484
cosine_recall@10.2525
cosine_recall@30.4836
cosine_recall@50.5998
cosine_recall@100.7393
cosine_ndcg@100.5889
cosine_mrr@100.6441
cosine_map@1000.4949

Training Details

Training Dataset

  • Size: 90,142 training pairs (sentence_0 = query, sentence_1 = positive paragraph/summary)
  • Source: 693 raw Indian court judgments, rhetorical-role-tagged (FACT, ISSUE, ARG_P, ARG_R, REASON, HOLDING, ORDER, LAW)
  • Dual-positive design: for every aligned (query, content) pair, two training rows are emitted from the same alignment — one against the original judgment paragraph, one against an LLM-generated summary sentence covering the same content. This is what teaches the model cross-source semantic equivalence rather than a stylistic shortcut.
  • Queries: three styles per aligned pair — short bare-keyword queries, natural one-line questions, and detailed multi-clause questions — approximating how a lawyer might actually search, generated via meta-llama-3-3-70b-instruct (Meta Llama 3.3) on IBM watsonx.ai.
  • Statistics (first 100 samples): query length averages 22.3 tokens (7–70 range); paragraph length averages 126.9 tokens (7–256 range, capped by max_seq_length).

Loss Function

MultipleNegativesRankingLoss — for each (query, positive) pair in a batch, every other positive in the batch serves as an in-batch negative; the loss encourages the correct pairing to score highest among all in-batch alternatives.

{
    "scale": 20.0,
    "similarity_fct": "cos_sim"
}

Training Hyperparameters

ParameterValue
Epochs4
Learning rate5e-05
LR schedulerlinear
Batch size (train/eval)32
Optimizeradamw_torch_fused
Max grad norm1.0
Seed42

Training Logs

EpochStepTraining Lossval NDCG@10
0.185000.6311–
0.3610000.4600–
0.7120000.3694–
1.02817–0.5814
1.4240000.2425–
2.05634–0.5886
2.6675000.1785–
3.08451–0.5887
3.55100000.1482–
4.011268–0.5889

Validation performance plateaus after epoch 1 (0.5814 → 0.5889 over the remaining three epochs) while training loss continues to fall — the saved checkpoint is the epoch-4 model, which is also the best-on-validation model for this run.

Training time: 1.0 hours.

Framework Versions

  • Python 3.12.13 · Sentence Transformers 5.6.0 · Transformers 5.13.1 · PyTorch 2.11.0+cu128 · Accelerate 1.14.0 · Datasets 4.0.0 · Tokenizers 0.22.2

Known Limitations

  • 256-token truncation: any single paragraph or query longer than 256 tokens is silently truncated. This is rarely an issue for individual judgment paragraphs (median well under the limit) but can matter for very dense LAW/REASON sections — use the chunk-pool variant for those.
  • Domain-specific: trained and evaluated only on Indian court judgments; not validated on other jurisdictions, statutes, contracts, or general-domain text.
  • English only.
  • Source bias: the model retrieves LLM-generated summary text somewhat more easily than original judgment text (style-parity mean gap around −0.07 in full-scale evaluation); this gap narrows with more training data but individual query/paragraph pairs can still differ substantially.
  • Paragraph splitting is not solved by this model. How you split a judgment into candidate paragraphs (numbering-based regex, page layout, rhetorical-role tagging) directly affects retrieval quality — this model only ranks whatever candidate paragraphs you give it.
  • Single training run: hyperparameters and results reflect one seed, not an average over multiple runs.

Intended Use

Retrieval of relevant paragraphs from a corpus of Indian court judgments given a natural-language legal query — e.g. as the first-stage retriever in a legal research or case-law search tool. Not intended for legal advice generation, outcome prediction, or use as a standalone decision-making system.


Citation

This model

@misc{sbert-legal-v1-legacy,
  title  = {SBERT Legal Paragraph Retrieval for Indian Court Judgments},
  author = {Vishnuprabha V},
  year   = {2026},
  note   = {Fine-tuned from sentence-transformers/all-MiniLM-L6-v2}
}

Sentence Transformers

@inproceedings{reimers-2019-sentence-bert,
    title = "Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks",
    author = "Reimers, Nils and Gurevych, Iryna",
    booktitle = "Proceedings of the 2019 Conference on Empirical Methods in Natural Language Processing",
    month = "11",
    year = "2019",
    publisher = "Association for Computational Linguistics",
    url = "https://arxiv.org/abs/1908.10084",
}

MultipleNegativesRankingLoss

@misc{oord2019representationlearningcontrastivepredictive,
      title={Representation Learning with Contrastive Predictive Coding},
      author={Aaron van den Oord and Yazhe Li and Oriol Vinyals},
      year={2019},
      eprint={1807.03748},
      archivePrefix={arXiv},
      primaryClass={cs.LG},
      url={https://arxiv.org/abs/1807.03748},
}

Acknowledgements

Built on sentence-transformers/all-MiniLM-L6-v2 (Apache 2.0). Built with Llama — training queries were generated with Meta's Llama-3.3-70B-Instruct via IBM watsonx.ai.

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

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

GPU в ailist

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

Можно запустить

Подбираем GPU…

Класс архитектуры
BertModel
Ревизия весов
16bd8ea

0 моделей