File size: 8,118 Bytes
7b1fddc
 
 
 
dcec8fc
 
 
12d284c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7b1fddc
 
 
 
 
 
 
 
 
55ea1a3
 
7b1fddc
 
dcec8fc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7b1fddc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12d284c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
---
license: mit
datasets:
- rokn/slovlo-dataset-v1
language:
- sl
library_name: sentence-transformers
pipeline_tag: sentence-similarity
widget:
- source_sentence: Kam na pohod iz glavnega mesta Slovenije?
  sentences:
  - >-
    Triglav je najvišja gora v Sloveniji (2864 m) in simbol slovenske narodne
    identitete. Pohod je zahteven in običajno traja dva dni. Potrebna je dobra
    fizična pripravljenost in osnovno znanje plezanja. Priporočena je tudi
    uporaba vodnika za manj izkušene pohodnike.
  - >-
    Velika Planina je zelo priljubljena pohodniška destinacija z značilnimi
    pastirskimi kočami. Pohod je primeren za vse starosti in ponuja čudovite
    razglede na okoliške gore. Na vrh se lahko povzpnete peš ali z nihalko iz
    Kamniške Bistrice.
  - >-
    Bled je znan po kremnih rezinah. Če vas zanima pohod, so pa zraven še
    Ojstrica, ter Mala in Velika Osojnica.
  - >-
    Golica je znana po neskončnih poljih narcis v maju. Pohod se začne iz vasi
    Planina pod Golico in traja približno 2-3 ure. Pot je primerna za vse
    pohodnike in ponuja lepe razglede na Julijske Alpe in Avstrijo.
  - >-
    Šmarna Gora je najbolj priljubljena pohodniška destinacija v bližini
    Ljubljane. Pohod traja približno 1 uro iz Tacna. Na vrhu je koča, kjer lahko
    uživate v tradicionalni slovenski hrani in lepih razgledih na Ljubljansko
    kotlino.
  - >-
    Pohorje je pohodniško območje z različnimi potmi, primernimi za vse starosti
    in pripravljenosti. Posebej priljubljena je pot do Črnega jezera in
    Slivniškega jezera. Pozimi je Pohorje tudi priljubljena smučarska
    destinacija.
---

The SloVlo (**Slo**venske **Vlo**žitve) project brings purposefully built embeddings and semantic search capabilities to the Slovenian language.
The `slovlo-v1` model can be used to implement semantic search applications over Slovenian documents. See an example in the [usage](#usage) section below.

The base model is the [e5-multilingual-base](https://huggingface.co/intfloat/multilingual-e5-base) model. The model has 12 layers and the embedding size is 768. 

The model was trained and evaluated on the [slovlo-dataset-v1](https://huggingface.co/datasets/rokn/slovlo-dataset-v1) dataset.

The code is released in the [slovlo](https://github.com/novoselrok/slovlo) repository on Github.

## Usage

### Via Sentence Transformers

```py
from sentence_transformers import SentenceTransformer
import torch

model = SentenceTransformer("rokn/slovlo-v1")

query = "Kam na pohod iz glavnega mesta Slovenije?"

# First, we define the documents we want to search over.
# In our case, that is a list of destination descriptions.
documents = [
    "Triglav je najvišja gora v Sloveniji (2864 m) in simbol slovenske narodne identitete. Pohod je zahteven in običajno traja dva dni. Potrebna je dobra fizična pripravljenost in osnovno znanje plezanja. Priporočena je tudi uporaba vodnika za manj izkušene pohodnike.",
    "Velika Planina je zelo priljubljena pohodniška destinacija z značilnimi pastirskimi kočami. Pohod je primeren za vse starosti in ponuja čudovite razglede na okoliške gore. Na vrh se lahko povzpnete peš ali z nihalko iz Kamniške Bistrice.",
    "Bled je znan po kremnih rezinah. Če vas zanima pohod, so pa zraven še Ojstrica, ter Mala in Velika Osojnica.",
    "Golica je znana po neskončnih poljih narcis v maju. Pohod se začne iz vasi Planina pod Golico in traja približno 2-3 ure. Pot je primerna za vse pohodnike in ponuja lepe razglede na Julijske Alpe in Avstrijo.",
    "Šmarna Gora je najbolj priljubljena pohodniška destinacija v bližini Ljubljane. Pohod traja približno 1 uro iz Tacna. Na vrhu je koča, kjer lahko uživate v tradicionalni slovenski hrani in lepih razgledih na Ljubljansko kotlino.",
    "Pohorje je pohodniško območje z različnimi potmi, primernimi za vse starosti in pripravljenosti. Posebej priljubljena je pot do Črnega jezera in Slivniškega jezera. Pozimi je Pohorje tudi priljubljena smučarska destinacija.",
]

# Embed the documents (destinations).
document_embeddings = model.encode(documents, prompt_name="document")

# Embed the user query.
query_embedding = model.encode(query, prompt_name="query")

# Compute dot product between the query and each document.
similarities = model.similarity(query_embedding, document_embeddings)

# Find the nearest neighbor.
nearest_index = torch.argmax(similarities).item()

print("Predlog za tvojo naslednjo avanturo:", documents[nearest_index])
```

### Via Transformers

```py
import sys
from typing import List

import torch
from transformers import AutoModel, AutoTokenizer

device = "cuda" if torch.cuda.is_available() else "cpu"

query = "Kam na pohod iz glavnega mesta Slovenije?"

# First, we define the documents we want to search over.
# In our case, that is a list of destination descriptions.
documents = [
    "Triglav je najvišja gora v Sloveniji (2864 m) in simbol slovenske narodne identitete. Pohod je zahteven in običajno traja dva dni. Potrebna je dobra fizična pripravljenost in osnovno znanje plezanja. Priporočena je tudi uporaba vodnika za manj izkušene pohodnike.",
    "Velika Planina je zelo priljubljena pohodniška destinacija z značilnimi pastirskimi kočami. Pohod je primeren za vse starosti in ponuja čudovite razglede na okoliške gore. Na vrh se lahko povzpnete peš ali z nihalko iz Kamniške Bistrice.",
    "Bled je znan po kremnih rezinah. Če vas zanima pohod, so pa zraven še Ojstrica, ter Mala in Velika Osojnica.",
    "Golica je znana po neskončnih poljih narcis v maju. Pohod se začne iz vasi Planina pod Golico in traja približno 2-3 ure. Pot je primerna za vse pohodnike in ponuja lepe razglede na Julijske Alpe in Avstrijo.",
    "Šmarna Gora je najbolj priljubljena pohodniška destinacija v bližini Ljubljane. Pohod traja približno 1 uro iz Tacna. Na vrhu je koča, kjer lahko uživate v tradicionalni slovenski hrani in lepih razgledih na Ljubljansko kotlino.",
    "Pohorje je pohodniško območje z različnimi potmi, primernimi za vse starosti in pripravljenosti. Posebej priljubljena je pot do Črnega jezera in Slivniškega jezera. Pozimi je Pohorje tudi priljubljena smučarska destinacija.",
]

# Load the model and the tokenizer.
slovlo_model = AutoModel.from_pretrained("rokn/slovlo-v1").eval().to(device)
slovlo_tokenizer = AutoTokenizer.from_pretrained("rokn/slovlo-v1")


def get_embeddings(texts: List[str], prefix: str):
    def mean_pool(
        last_hidden_states: torch.Tensor, attention_mask: torch.Tensor
    ) -> torch.Tensor:
        last_hidden = last_hidden_states.masked_fill(
            ~attention_mask[..., None].bool(), 0.0
        )
        return last_hidden.sum(dim=1) / attention_mask.sum(dim=1)[..., None]

    prefixed_texts = [f"{prefix}{text}" for text in texts]
    inputs = slovlo_tokenizer(
        prefixed_texts, return_tensors="pt", truncation=True, padding=True
    ).to(device)

    with torch.no_grad():
        model_output = slovlo_model(**inputs)

    embeddings = mean_pool(model_output.last_hidden_state, inputs["attention_mask"])
    return torch.nn.functional.normalize(embeddings, p=2, dim=1)


# Embed the documents (destinations).
document_embeddings = get_embeddings(documents, "document: ")

# Embed the user query.
query_embedding = get_embeddings([query], "query: ")

# Compute dot product between the query and each document.
similarities = torch.matmul(document_embeddings, query_embedding.T).squeeze()

# Find the nearest neighbor.
nearest_index = torch.argmax(similarities).item()

print("Predlog za tvojo naslednjo avanturo:", documents[nearest_index])
```

## Evaluation

MRR@k on the `slovlo-dataset-v1` test split:

| Model                | MRR@1    | MRR@5    | MRR@10   |
| -------------------- | -------- | -------- | -------- |
| Elasticsearch (BM25) | 31.7     | 45.2     | 45.8     |
| e5-base-v2           | 25.1     | 36.5     | 37.2     |
| multilingual-e5-base | 37.2     | 53.9     | 54.5     |
| bge-m3               | 38.1     | 54.1     | 54.7     |
| slovlo-v1            | **43.6** | **60.4** | **61.0** |