Mint the training data your retriever never had

    Generate verified (query, passage) pairs from your own corpus in 25 languages, and fine-tune retrievers and rerankers on data that matches your domain.

    ML & data teamsRAG platformsSearch infrastructure
    0.955
    ROUND-TRIP KEEP-RATE
    ~150K
    QUESTIONS MINTED THIS WAY
    25
    LANGUAGES SUPPORTED
    / The problem

    Why this breaks today

    Off-the-shelf embedding models are trained on English web text. Point one at your domain corpus (legal filings, medical guidance, product docs, Yorùbá news) and recall drops in ways no amount of prompt engineering fixes.

    The fix is fine-tuning, and fine-tuning needs (query, positive passage) pairs. Nobody has those for their own corpus, and hand-labelling them is the reason most teams never do it.

    / How it works

    The pipeline, step by step

    01

    Label the corpus by language

    lid-lite-608 tags every document on CPU. Map its label (yor_Latn) to the language code (yor) and keep only the 25 languages the generator covers, so generation happens in the right language and your eval splits stay honest.

    lid-lite-608
    02

    Generate candidate queries

    mist-qg-1.5b turns each passage into search-style questions in that language. This is the pipeline that built Olaverse's own qg-passages-multi dataset: roughly 50k passages and 150k questions.

    mist-qg-1.5b
    03

    Keep only what survives round-trip retrieval

    Embed each generated question and check that it retrieves its own source passage out of [source + distractors]. Discard the rest. What is left is a clean pair set you can train on.

    04

    Fine-tune, then measure

    Train your embedder or cross-encoder on the surviving pairs and evaluate on a held-out slice of your own corpus, not on a public benchmark that looks nothing like your data.

    / The code

    Running in about ten lines

    The Olaverse SDK wraps the models with sane defaults. If you would rather not add a dependency, the second tab is the same pipeline in plain transformers.

    $pip install "olaverse[deeplearning,lid]"
    mint_pairs.py
    from olaverse import LIDLite608, MISTQuestionGenerator
    from sentence_transformers import SentenceTransformer, util
    
    lid = LIDLite608()                       # coverage mode, for corpus labelling
    qg = MISTQuestionGenerator()             # mist-qg-1.5b, 25 languages
    qg.load()
    embedder = SentenceTransformer("Qwen/Qwen3-Embedding-0.6B")
    QG_LANGS = {"afr", "amh", "deu", "eng", "fra", "hau", "hin", "ibo", "ind", "ita", "jpn", "kor", "nld",
                "pol", "por", "rus", "sna", "som", "spa", "swh", "tur", "vie", "xho", "yor", "zul"}
    
    def survives_round_trip(question, source, distractors):
        pool = [source] + distractors
        q = embedder.encode(question, convert_to_tensor=True)
        p = embedder.encode(pool, convert_to_tensor=True)
        return int(util.cos_sim(q, p).argmax()) == 0   # the source ranks first
    
    pairs = []
    for doc in corpus:
        lang = lid.predict(doc["text"]).split("_")[0]   # 'yor_Latn' → 'yor'
        if lang not in QG_LANGS:
            continue
        for q in qg.generate(doc["text"], n=3, language=lang):
            if survives_round_trip(q, doc["text"], sample_distractors(corpus, doc)):
                pairs.append((q, doc["text"]))
    
    # pairs → fine-tune your embedder or cross-encoder on your own domain

    Language coverage

    / 25 LANGUAGES

    Every language the models in this pipeline were trained on, with the codes you pass and the codes you get back.

    Afrikaans
    af · afr
    Amharic
    am · amh
    German
    de · deu
    English
    en · eng
    French
    fr · fra
    Hausa
    ha · hau
    Hindi
    hi · hin
    Igbo
    ig · ibo
    Indonesian
    id · ind
    Italian
    it · ita
    Japanese
    ja · jpn
    Korean
    ko · kor
    Dutch
    nl · nld
    Polish
    pl · pol
    Portuguese
    pt · por
    Russian
    ru · rus
    Shona
    sn · sna
    Somali
    so · som
    Spanish
    es · spa
    Swahili
    sw · swh
    Turkish
    tr · tur
    Vietnamese
    vi · vie
    Xhosa
    xh · xho
    Yorùbá
    yo · yor
    Zulu
    zu · zul

    Generation covers these 25. Language ID covers 608, so documents in any other language are labelled and skipped rather than sent to the generator.

    / This is you if
    • Your RAG system retrieves the wrong passages and you have run out of prompt-level fixes.
    • Your corpus is domain-specific, non-English, or both.
    • You have engineers who can fine-tune, and no labelled retrieval data to fine-tune on.

    Every figure on this page comes from the published model cards. Download the weights and check us.

    Want this on your data?

    The weights are open, so you can build it yourself this afternoon. If you would rather we tuned it to your domain, evaluated it properly, and handed it over, tell us what you are working on.