pauhmolins commited on
Commit
1200d57
·
1 Parent(s): c8fb72b

Upload app

Browse files
Files changed (11) hide show
  1. .gitignore +180 -0
  2. README.md +5 -13
  3. app.py +86 -52
  4. datasets/prompts.json +322 -0
  5. datasets/proverbs.json +1655 -0
  6. requirements.txt +6 -1
  7. src/commons.py +67 -0
  8. src/customlogger.py +68 -0
  9. src/datasets.py +107 -0
  10. src/indexes.py +52 -0
  11. src/models.py +76 -0
.gitignore ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py,cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ #uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ #poetry.lock
109
+
110
+ # pdm
111
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
112
+ #pdm.lock
113
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
114
+ # in version control.
115
+ # https://pdm.fming.dev/latest/usage/project/#working-with-version-control
116
+ .pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
121
+ __pypackages__/
122
+
123
+ # Celery stuff
124
+ celerybeat-schedule
125
+ celerybeat.pid
126
+
127
+ # SageMath parsed files
128
+ *.sage.py
129
+
130
+ # Environments
131
+ .env
132
+ .venv
133
+ env/
134
+ venv/
135
+ ENV/
136
+ env.bak/
137
+ venv.bak/
138
+
139
+ # Spyder project settings
140
+ .spyderproject
141
+ .spyproject
142
+
143
+ # Rope project settings
144
+ .ropeproject
145
+
146
+ # mkdocs documentation
147
+ /site
148
+
149
+ # mypy
150
+ .mypy_cache/
151
+ .dmypy.json
152
+ dmypy.json
153
+
154
+ # Pyre type checker
155
+ .pyre/
156
+
157
+ # pytype static type analyzer
158
+ .pytype/
159
+
160
+ # Cython debug symbols
161
+ cython_debug/
162
+
163
+ # PyCharm
164
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
165
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
166
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
167
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
168
+ #.idea/
169
+
170
+ # Ruff stuff:
171
+ .ruff_cache/
172
+
173
+ # PyPI configuration file
174
+ .pypirc
175
+
176
+ # Gradio stuff
177
+ .gradio
178
+
179
+ # Test runs
180
+ tests_runs/
README.md CHANGED
@@ -1,14 +1,6 @@
1
- ---
2
- title: Virtual Catalan Grandparent
3
- emoji: 💬
4
- colorFrom: yellow
5
- colorTo: purple
6
- sdk: gradio
7
- sdk_version: 5.0.1
8
- app_file: app.py
9
- pinned: false
10
- license: mit
11
- short_description: A virtual Catalan grandparent
12
- ---
13
 
14
- An example chatbot using [Gradio](https://gradio.app), [`huggingface_hub`](https://huggingface.co/docs/huggingface_hub/v0.22.2/en/index), and the [Hugging Face Inference API](https://huggingface.co/docs/api-inference/index).
 
 
 
 
1
+ # A virtual Catalan grandparent
 
 
 
 
 
 
 
 
 
 
 
2
 
3
+ This is the repository for the project "A virtual Catalan grandparent",
4
+ created as part of the course "Natural Language Processing" of the
5
+ "Master's degree in Machine Learning and Cybersecurity for Internet Connected Systems"
6
+ at UPC-EPSEM.
app.py CHANGED
@@ -1,64 +1,98 @@
 
 
1
  import gradio as gr
2
- from huggingface_hub import InferenceClient
 
 
 
3
 
4
- """
5
- For more information on `huggingface_hub` Inference API support, please check the docs: https://huggingface.co/docs/huggingface_hub/v0.22.2/en/guides/inference
6
- """
7
- client = InferenceClient("HuggingFaceH4/zephyr-7b-beta")
8
 
 
 
 
 
 
 
 
9
 
10
- def respond(
11
- message,
12
- history: list[tuple[str, str]],
13
- system_message,
14
- max_tokens,
15
- temperature,
16
- top_p,
17
- ):
18
- messages = [{"role": "system", "content": system_message}]
19
 
20
- for val in history:
21
- if val[0]:
22
- messages.append({"role": "user", "content": val[0]})
23
- if val[1]:
24
- messages.append({"role": "assistant", "content": val[1]})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
- messages.append({"role": "user", "content": message})
27
 
28
- response = ""
 
 
 
 
 
29
 
30
- for message in client.chat_completion(
31
- messages,
32
- max_tokens=max_tokens,
33
- stream=True,
34
- temperature=temperature,
35
- top_p=top_p,
36
- ):
37
- token = message.choices[0].delta.content
38
-
39
- response += token
40
- yield response
41
 
 
 
42
 
43
- """
44
- For information on how to customize the ChatInterface, peruse the gradio docs: https://www.gradio.app/docs/chatinterface
45
- """
46
- demo = gr.ChatInterface(
47
- respond,
48
- additional_inputs=[
49
- gr.Textbox(value="You are a friendly Chatbot.", label="System message"),
50
- gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
51
- gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
52
- gr.Slider(
53
- minimum=0.1,
54
- maximum=1.0,
55
- value=0.95,
56
- step=0.05,
57
- label="Top-p (nucleus sampling)",
58
- ),
59
- ],
60
- )
61
 
 
 
 
 
 
 
 
 
 
 
62
 
63
- if __name__ == "__main__":
64
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pprint
2
+ import numpy as np
3
  import gradio as gr
4
+ import src.datasets as datasets
5
+ import src.models as models
6
+ import src.commons as commons
7
+ from src.customlogger import logger
8
 
9
+ SHARE = True
10
+ TOP_K = 5
 
 
11
 
12
+ def setup():
13
+ """Set up the environment by loading the model, tokenizer, and dataset."""
14
+ tokenizer = models.load_tokenizer()
15
+ model = models.load_model()
16
+ proverbs = datasets.load_proverbs()
17
+ index = commons.load_or_create_index(tokenizer, model, proverbs)
18
+ return index, tokenizer, model, proverbs
19
 
 
 
 
 
 
 
 
 
 
20
 
21
+ def sample_inference_results(inference_results: list[dict]) -> list[dict]:
22
+ """Sample one match per input from inference results, with probability inversely proportional to distance."""
23
+ sampled = []
24
+ for result in inference_results:
25
+ matches = result['matches']
26
+ distances = np.array([m['distance'] for m in matches])
27
+ # Convert distances to probabilities using softmax
28
+ # over negative distances (closer = higher prob)
29
+ alpha = 1000
30
+ exp_scores = np.exp(-alpha * distances)
31
+ probs = exp_scores / exp_scores.sum()
32
+ sample = np.random.choice(len(result['matches']), p=probs)
33
+ sampled.append({
34
+ 'input': result['input'],
35
+ 'matches': [match | {"prob": float(probs[i])} for i, match in enumerate(matches)],
36
+ 'sample': result['matches'][sample],
37
+ "prob": float(probs[sample]),
38
+ })
39
+ return sampled
40
 
 
41
 
42
+ def build_response_from_result(result: dict) -> str:
43
+ response = f"**Top {len(result['matches'])} matches:**\n"
44
+ matches = sorted(result["matches"], key=lambda x: x["rank"])
45
+ for match in matches:
46
+ response += f"{match['rank']}. \"{match['proverb']}\" *(distance = {match['distance']:.6f}, probability = {match['prob']*100:.2f}%)*\n"
47
+ return response
48
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
+ if __name__ == "__main__":
51
+ index, tokenizer, model, proverbs = setup()
52
 
53
+ def run(message, history, detailed_response):
54
+ # Run inference on the input message
55
+ logger.info(f"Running inference for message \"{message}\"...")
56
+ results = commons.inference(
57
+ [message], index, tokenizer, model, proverbs, k=TOP_K
58
+ )
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
+ # Sample one match per input from inference results
61
+ sampled = sample_inference_results(results)
62
+ logger.info(f"Inference result:\n{pprint.pformat(sampled[0])}")
63
+
64
+ # Build the final response with the details or just the proverb
65
+ if detailed_response:
66
+ response = build_response_from_result(sampled[0])
67
+ else:
68
+ response = sampled[0]["sample"]["proverb"]
69
+ return response
70
 
71
+ # Create the Gradio interface
72
+ with gr.Blocks() as demo:
73
+ with gr.Row():
74
+ gr.Markdown(
75
+ "# A virtual Catalan grandparent"
76
+ )
77
+ with gr.Row():
78
+ with gr.Column(scale=1):
79
+ gr.Markdown(
80
+ "This is the demo of \"A virtual Catalan grandparent\", a project built as part of a Natural Language Processing course.\n\n"
81
+ "You can write anything and you will get a fitting proverb as the response.\n\n"
82
+ "> The application is based on a pre-trained transformer model, " +
83
+ "[projecte-aina/roberta-base-ca-v2-cased-sts](https://huggingface.co/projecte-aina/roberta-base-ca-v2-cased-sts) " +
84
+ "and uses normalized L2 distance between embedding to select the most appropriate proverb in the database, " +
85
+ "available [here](https://huggingface.co/datasets/pauhmolins/catalan-proverbs).\n\n"
86
+ )
87
+ with gr.Column(scale=2):
88
+ detailed_response_checkbox = gr.Checkbox(
89
+ label="Show detailed response", render=False, value=False)
90
+ accordion = gr.Accordion(
91
+ label="Options", render=False, open=False)
92
+ chat = gr.ChatInterface(
93
+ fn=run,
94
+ type="messages",
95
+ additional_inputs = [detailed_response_checkbox],
96
+ additional_inputs_accordion=accordion,
97
+ )
98
+ demo.launch(share=SHARE)
datasets/prompts.json ADDED
@@ -0,0 +1,322 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "prompt": "Un any més, m'han tornat a pujar el preu del lloguer.",
4
+ "proverb": "A cada bugada es perd un llençol."
5
+ },
6
+ {
7
+ "prompt": "Avui m'ha arribat una multa per excés de velocitat que em van posar fa un any.",
8
+ "proverb": "A cada porc li arriba el seu Sant Martí."
9
+ },
10
+ {
11
+ "prompt": "El meu metge m'ha cancelat la visita, diu que s'ha posat malalt.",
12
+ "proverb": "A cal sabater, sabates de paper."
13
+ },
14
+ {
15
+ "prompt": "Es nota que s'acosta l'estiu, les terrasses estan ben plenes!",
16
+ "proverb": "A l'estiu, tota cuca viu."
17
+ },
18
+ {
19
+ "prompt": "Vaig marxar del concert just abans que toquessin la seva millor cançó.",
20
+ "proverb": "A la taula d'en Bernat, qui no hi és, no hi és comptat."
21
+ },
22
+ {
23
+ "prompt": "Va arribar a darrera hora, però noi, quan van cridar a dinar, va ser el primer a parar el plat.",
24
+ "proverb": "A la taula i al llit, al primer crit."
25
+ },
26
+ {
27
+ "prompt": "Ho va fer assegurant-se de no equivocar-se.",
28
+ "proverb": "A poc a poc i bona lletra."
29
+ },
30
+ {
31
+ "prompt": "El van enganyar amb tot de regles i normes que només coneixien ells.",
32
+ "proverb": "Advocats i procuradors, a l'infern de dos en dos."
33
+ },
34
+ {
35
+ "prompt": "Les nevades de l'hivern asseguren una bona collita pels pagesos.",
36
+ "proverb": "Any de neu, any de Déu."
37
+ },
38
+ {
39
+ "prompt": "El van marejar a metges quan només necessitava tranquil·litat.",
40
+ "proverb": "Aquest mal no vol soroll."
41
+ },
42
+ {
43
+ "prompt": "Semblava que s’havia de menjar el món però a la primera dificultat ja va plegar.",
44
+ "proverb": "Arrancada de cavall, parada de rossí."
45
+ },
46
+ {
47
+ "prompt": "No va poder entrar anar de festa enlloc, tot era caríssim.",
48
+ "proverb": "Barcelona és bona si la bossa sona."
49
+ },
50
+ {
51
+ "prompt": "No s’en sortia i va plegar, va començar de nou.",
52
+ "proverb": "Bon vent i barca nova."
53
+ },
54
+ {
55
+ "prompt": "Criticava tot i a tothom, però mentrestant feia el que li deien.",
56
+ "proverb": "Brams d'ase no arriben al cel."
57
+ },
58
+ {
59
+ "prompt": "Nosaltres demanant que plogui i els hotelers que faci sol.",
60
+ "proverb": "Cada terra fa sa guerra."
61
+ },
62
+ {
63
+ "prompt": "Abans no era així, però què vols, s'hi ha anat tornant.",
64
+ "proverb": "Caldera vella, bony o forat."
65
+ },
66
+ {
67
+ "prompt": "Va dir que no i d'allí no el treies, no va haver-hi manera. Tremendo!",
68
+ "proverb": "Canalla neixem i canalla tornem."
69
+ },
70
+ {
71
+ "prompt": "Es queixa de l’ordre, i si veiéssis com té la casa...",
72
+ "proverb": "Cap geperut no es veu el gep."
73
+ },
74
+ {
75
+ "prompt": "Els botiguers lamenten que el temps hagi espantat a la clientela.",
76
+ "proverb": "Carrers molls, calaixos eixuts."
77
+ },
78
+ {
79
+ "prompt": "Ja no ve d'aquí, havíem de ser deu i ja som trenta.",
80
+ "proverb": "Com més serem, més riurem."
81
+ },
82
+ {
83
+ "prompt": "Aquest matí ha estat marejat tot el dia, fins ara que ho ha vomitat",
84
+ "proverb": "Cosa dolenta, fora del ventre."
85
+ },
86
+ {
87
+ "prompt": "Ho va encertar només una vegada però sempre més li han demanat consell.",
88
+ "proverb": "Cria fama i posa't a jeure."
89
+ },
90
+ {
91
+ "prompt": "El seu pis vell ha millorat molt només repintant-ne les parets.",
92
+ "proverb": "Cànter nou fa l'aigua fresca."
93
+ },
94
+ {
95
+ "prompt": "Per més que li explicaven no ho entenia i ell, tossut, que tenia raó.",
96
+ "proverb": "D'on no n'hi ha, no en pot rajar."
97
+ },
98
+ {
99
+ "prompt": "Els va sorprendre que també els passés a ells.",
100
+ "proverb": "De Joans, Joseps i ases, n'hi ha a totes les cases."
101
+ },
102
+ {
103
+ "prompt": "Els havia ajudat a fer el dinar i no van ser bons per convidar-lo.",
104
+ "proverb": "De desagraïts, l'infern n'és ple."
105
+ },
106
+ {
107
+ "prompt": "Jugant, jugant van acabar caient pel marge",
108
+ "proverb": "De les rialles vénen les ploralles."
109
+ },
110
+ {
111
+ "prompt": "Cada dia hi posava un euro fins que s’ha pogut comprar el tren que volia",
112
+ "proverb": "De mica en mica s'omple la pica."
113
+ },
114
+ {
115
+ "prompt": "Era qüestió d’esperar, només es podia resoldre d’aquella manera.",
116
+ "proverb": "De més verdes en maduren."
117
+ },
118
+ {
119
+ "prompt": "No diries mai qui li ha vingut a donar les gràcies…",
120
+ "proverb": "De porc i de senyor, se n'ha de venir de mena."
121
+ },
122
+ {
123
+ "prompt": "Va agafar una llibreta nova per fer-ne blocs de notes.",
124
+ "proverb": "De qui pa en fa rosegons."
125
+ },
126
+ {
127
+ "prompt": "Era inevitable, ja feia temps que la salut li fallava.",
128
+ "proverb": "De vell, ningú no passa."
129
+ },
130
+ {
131
+ "prompt": "Tu demana la beca, mai se sap.",
132
+ "proverb": "Demanar no fa pobre."
133
+ },
134
+ {
135
+ "prompt": "Els convidats arribaven i encara no havia ni encès el foc…",
136
+ "proverb": "El més calent és a l'aigüera."
137
+ },
138
+ {
139
+ "prompt": "Semblava que era una afició i n’ha fet una empresa.",
140
+ "proverb": "Els catalans de les pedres en fem pans."
141
+ },
142
+ {
143
+ "prompt": "No va voler posar aïllant a les finestres i la factura de calefacció ha estat monumental.",
144
+ "proverb": "Els estalvis es mengen les estovalles."
145
+ },
146
+ {
147
+ "prompt": "Què vols, a casa seva ja eren tibats de mena.",
148
+ "proverb": "Els testos s'assemblen a les olles."
149
+ },
150
+ {
151
+ "prompt": "Tota la tarda li va riure les gràcies, i no va ser fins al vespre que li va demanar el gran favor.",
152
+ "proverb": "Em fas festes i no me'n solies fer, és que em vols fotre o m'has de menester."
153
+ },
154
+ {
155
+ "prompt": "Ell va poder anar de festa, ja tenia el treball enllestit.",
156
+ "proverb": "Feina feta no fa destorb."
157
+ },
158
+ {
159
+ "prompt": "Aquestes vacances no penso fer altra cosa que jaure al sofà.",
160
+ "proverb": "Feina fuig, mandra no em deixis."
161
+ },
162
+ {
163
+ "prompt": "No volia que el tornéssin a enredar per preparar una festa. Quina feinada.",
164
+ "proverb": "Gat escaldat, de l'aigua tèbia fuig."
165
+ },
166
+ {
167
+ "prompt": "D’ença que viu amb la Maria, només fa el que ella li diu.",
168
+ "proverb": "Home casat, burro espatllat."
169
+ },
170
+ {
171
+ "prompt": "Tot ho començava però res ho arreglava bé.",
172
+ "proverb": "Home de molts oficis, pobre segur."
173
+ },
174
+ {
175
+ "prompt": "Van anar a dormir a la Fonda perque els convidats estiguessin còmodes a casa seva.",
176
+ "proverb": "Hostes vingueren que de casa ens tragueren."
177
+ },
178
+ {
179
+ "prompt": "Just acabaven d’arreglar una cadira que es va trencar la taula.",
180
+ "proverb": "L'alegria dura poc a casa del pobre."
181
+ },
182
+ {
183
+ "prompt": "Ja fa molts dies que està costipada, i mira que es cuida.",
184
+ "proverb": "Març, marçot, mata la vella a la vora del foc i la jove si pot."
185
+ },
186
+ {
187
+ "prompt": "Es va passar l’estona amb una caixa a la mà amunt i avall, però la resta, pendent.",
188
+ "proverb": "Molta fressa i poca endreça."
189
+ },
190
+ {
191
+ "prompt": "Si deia el que havia vist, encara en sortiria malparat.",
192
+ "proverb": "Muts i a la gàbia."
193
+ },
194
+ {
195
+ "prompt": "Va sortir de casa sense agafar una jaqueta perquè deia que no feia tan fred, i s'ha passat la setmana malalt al llit.",
196
+ "proverb": "Més viu el qui piula que el qui xiula."
197
+ },
198
+ {
199
+ "prompt": "Quan van haver cobrat pel transport li van deixar les caixes de qualsevol manera.",
200
+ "proverb": "Músic pagat no fa bon so."
201
+ },
202
+ {
203
+ "prompt": "No et creuràs com va acabar.",
204
+ "proverb": "N'hi ha per llogar-hi cadires."
205
+ },
206
+ {
207
+ "prompt": "Els va avisar que ja havia passat abans, però no se’l van voler escoltar.",
208
+ "proverb": "Ningú és profeta en la seva terra."
209
+ },
210
+ {
211
+ "prompt": "Semblava fet però a l’ultim minut els van marcar un gol que els va deixar fora.",
212
+ "proverb": "No diguis blat que no sigui al sac i ben lligat."
213
+ },
214
+ {
215
+ "prompt": "Sempre havia dit que ell no ho faria.",
216
+ "proverb": "No diguis mai d'aquesta aigua no en beuré."
217
+ },
218
+ {
219
+ "prompt": "Enmig d’aquells disbarats, cal dir que alguna idea era molt bona.",
220
+ "proverb": "No es pot pas matar tot el que és gras."
221
+ },
222
+ {
223
+ "prompt": "Semblava que la sequera no s’acabaria mai.",
224
+ "proverb": "No hi ha mal que cent anys duri ni cos que resistir el pugui."
225
+ },
226
+ {
227
+ "prompt": "No només es va adormir sinó que encara es va perdre quan hi anava",
228
+ "proverb": "No vols caldo? Dues tasses!"
229
+ },
230
+ {
231
+ "prompt": "Tot anava bé fins que li va criticar al germà.",
232
+ "proverb": "On no hi ha sang, butifarra no s'hi fa."
233
+ },
234
+ {
235
+ "prompt": "Semblava impossible fins que va dir que els pagaria un dinar.",
236
+ "proverb": "Pagant, Sant Pere canta."
237
+ },
238
+ {
239
+ "prompt": "Es va comprar tota una vaixella quan només se li havia trencat un plat.",
240
+ "proverb": "Preu per preu, sabates grosses."
241
+ },
242
+ {
243
+ "prompt": "Quan va veure el preu de la tele, li va trobar totes les pegues.",
244
+ "proverb": "Quan la guineu no les pot haver diu que són verdes."
245
+ },
246
+ {
247
+ "prompt": "Per un cantó feien la guerra bruta mentre deien que respectaven l’ordre establert.",
248
+ "proverb": "Que la mà esquerra no sàpiga el que fa la mà dreta."
249
+ },
250
+ {
251
+ "prompt": "Va travessar el bosc a mitjanit, cantant com un boig.",
252
+ "proverb": "Qui canta els seus mals espanta."
253
+ },
254
+ {
255
+ "prompt": "No va començar a cotitzar fins passats els trenta, i li ha quedat una pensió força minsa.",
256
+ "proverb": "Qui de jove no treballa, de vell dorm a la palla."
257
+ },
258
+ {
259
+ "prompt": "Semblava que no havien de durar ni dos dies, i guaita’ls.",
260
+ "proverb": "Qui dia passa, any empeny."
261
+ },
262
+ {
263
+ "prompt": "De jove ja havia fet teatre, ara fa les millors presentacions a la feina.",
264
+ "proverb": "Qui fa un cove fa un cistell."
265
+ },
266
+ {
267
+ "prompt": "Després que es fes públic el cas de corrupció, se'l va expulsar dels càrrecs de govern i se'l va acabar condemant a presó.",
268
+ "proverb": "Qui la fa, la paga."
269
+ },
270
+ {
271
+ "prompt": "No va parar de queixar-se fins que tothom li va fer cas.",
272
+ "proverb": "Qui no plora no mama."
273
+ },
274
+ {
275
+ "prompt": "No he pensat a agafar el moneder, així que he hagut de tornar a buscar-lo.",
276
+ "proverb": "Qui no té cap, ha de tenir cames."
277
+ },
278
+ {
279
+ "prompt": "Ell té molt bona vista però molt mal d'esquena, en canvi l'altre no s'hi veu però camina ben dret.",
280
+ "proverb": "Qui no té un all, té una ceba."
281
+ },
282
+ {
283
+ "prompt": "Tothom apartava la vista, al final van ser les seves amistats més properes qui li van haver de fer veure el seu error.",
284
+ "proverb": "Qui vol bé et farà plorar i qui et vol mal et farà riure."
285
+ },
286
+ {
287
+ "prompt": "Les sabates eren precioses, i la llaga que li van fer també.",
288
+ "proverb": "Qui vol lluir ha de patir."
289
+ },
290
+ {
291
+ "prompt": "Si vols veure el concert des de primera fila, hauràs de posar-te a la cua moltes hores abans que comenci.",
292
+ "proverb": "Qui vulgui peix que es mulli el cul."
293
+ },
294
+ {
295
+ "prompt": "Fins ara les hi haviem deixat passar totes, però a partir d'ara això canviarà.",
296
+ "proverb": "S'ha acabat el bròquil."
297
+ },
298
+ {
299
+ "prompt": "Els millors amics són aquells que saben escoltar.",
300
+ "proverb": "Si vols ben parlar, aprèn de callar."
301
+ },
302
+ {
303
+ "prompt": "D'ençà del dia que van acabar de pintar, no hi han fet res més.",
304
+ "proverb": "Tal dia farà l'any."
305
+ },
306
+ {
307
+ "prompt": "Al final, no en va sobrar cap...",
308
+ "proverb": "Tants caps, tants barrets."
309
+ },
310
+ {
311
+ "prompt": "Aquella mala notícia va ser només la primera de totes.",
312
+ "proverb": "Un mal no ve tot sol."
313
+ },
314
+ {
315
+ "prompt": "Ell presumeix de la feina que fa, però li fan els seus col·laboradors.",
316
+ "proverb": "Uns tenen la fama i altres carden la llana."
317
+ },
318
+ {
319
+ "prompt": "D'ell, si més no, ja en sabia els defectes. Del nou només eren referències.",
320
+ "proverb": "Val més boig conegut que savi per conèixer."
321
+ }
322
+ ]
datasets/proverbs.json ADDED
@@ -0,0 +1,1655 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "proverb": "A cada bugada es perd un llençol.",
4
+ "themes": [
5
+ "pèrdua",
6
+ "inevitabilitat",
7
+ "experiència"
8
+ ],
9
+ "sentiment": "resignació",
10
+ "explanation": "Aquest refrany expressa que en cada acció o procés, per molt rutinari que sigui, sempre hi ha la possibilitat de perdre alguna cosa. És una manera de dir que les pèrdues petites són inevitables en la vida quotidiana.",
11
+ "usage": "S'utilitza quan es vol expressar que les petites pèrdues o inconvenients són part natural de qualsevol activitat o procés."
12
+ },
13
+ {
14
+ "proverb": "A cada porc li arriba el seu Sant Martí.",
15
+ "themes": [
16
+ "justícia",
17
+ "conseqüències",
18
+ "karma"
19
+ ],
20
+ "sentiment": "esperança",
21
+ "explanation": "Aquest refrany indica que tothom rep el que es mereix, tard o d'hora. Fa referència al fet que per Sant Martí es mata el porc, simbolitzant que les accions tenen conseqüències.",
22
+ "usage": "S'utilitza per expressar que les persones que actuen malament acabaran rebent el càstig o les conseqüències dels seus actes."
23
+ },
24
+ {
25
+ "proverb": "A cal sabater, sabates de paper.",
26
+ "themes": [
27
+ "ironia",
28
+ "incoherència",
29
+ "paradoxa"
30
+ ],
31
+ "sentiment": "sornegueria",
32
+ "explanation": "Aquest refrany ressalta la paradoxa que sovint les persones que tenen una professió o habilitat no l'apliquen a si mateixes. El sabater, tot i fer sabates, en té de mala qualitat per a ell mateix.",
33
+ "usage": "S'utilitza per comentar situacions on algú no aplica els seus coneixements o habilitats en benefici propi."
34
+ },
35
+ {
36
+ "proverb": "A l'estiu, tota cuca viu.",
37
+ "themes": [
38
+ "abundància",
39
+ "cicle vital",
40
+ "temporada"
41
+ ],
42
+ "sentiment": "alegria",
43
+ "explanation": "Aquest refrany fa referència a la vitalitat i l'activitat que es produeix durant l'estiu, quan les condicions són favorables per a la vida.",
44
+ "usage": "S'utilitza per destacar l'activitat i l'energia que es percep durant l'estiu, tant en la natura com en les persones."
45
+ },
46
+ {
47
+ "proverb": "A la taula d'en Bernat, qui no hi és, no hi és comptat.",
48
+ "themes": [
49
+ "presència",
50
+ "importància",
51
+ "exclusió"
52
+ ],
53
+ "sentiment": "advertència",
54
+ "explanation": "Aquest refrany indica que si no estàs present en un moment o lloc determinat, no seràs tingut en compte. Fa referència a la importància de ser present per ser considerat.",
55
+ "usage": "S'utilitza per remarcar que la presència és necessària per participar o ser considerat en decisions o esdeveniments."
56
+ },
57
+ {
58
+ "proverb": "A la taula i al llit, al primer crit.",
59
+ "themes": [
60
+ "celeritat",
61
+ "atenció",
62
+ "reacció"
63
+ ],
64
+ "sentiment": "picardia",
65
+ "explanation": "Aquest refrany recomana ser ràpid a l'hora de seure a taula o anar al llit, especialment si es fa en companyia, per aprofitar l'ocasió sense perdre temps.",
66
+ "usage": "S'utilitza sovint amb to humorístic per indicar que cal actuar ràpidament quan se't presenta una bona oportunitat."
67
+ },
68
+ {
69
+ "proverb": "A la vora del riu no t'hi facis el niu.",
70
+ "themes": [
71
+ "precaució",
72
+ "saviesa popular",
73
+ "naturalesa"
74
+ ],
75
+ "sentiment": "prudència",
76
+ "explanation": "Refrany que adverteix de no establir-se en llocs que poden ser perillosos o inestables, com la vora d'un riu que pot desbordar-se.",
77
+ "usage": "S'utilitza per aconsellar a algú que eviti situacions que poden ser arriscades o poc fiables."
78
+ },
79
+ {
80
+ "proverb": "A més de pregar, cal treballar.",
81
+ "themes": [
82
+ "esforç",
83
+ "religió",
84
+ "pragmatisme"
85
+ ],
86
+ "sentiment": "consell",
87
+ "explanation": "Vol dir que no només cal confiar en la sort o en l'ajuda divina, sinó també posar-hi el teu propi esforç.",
88
+ "usage": "S'utilitza per dir que la feina i l'esforç personal són essencials per aconseguir els resultats."
89
+ },
90
+ {
91
+ "proverb": "A poc a poc i bona lletra.",
92
+ "themes": [
93
+ "despaci",
94
+ "precisió",
95
+ "perseverança"
96
+ ],
97
+ "sentiment": "consell",
98
+ "explanation": "Vol dir que cal fer les coses amb calma i amb cura per obtenir bons resultats.",
99
+ "usage": "S’utilitza per animar a fer les coses amb paciència i de manera meticulosa."
100
+ },
101
+ {
102
+ "proverb": "A sants i a minyons no els prometis si no els dons.",
103
+ "themes": [
104
+ "promeses",
105
+ "compromís",
106
+ "veracitat"
107
+ ],
108
+ "sentiment": "avís",
109
+ "explanation": "Aquest refrany ensenya que no s'han de fer promeses si no tens la intenció de complir-les, especialment a persones que s'hi agafen amb il·lusió o fe.",
110
+ "usage": "S'utilitza per advertir algú que no prometi res que no pugui o vulgui complir."
111
+ },
112
+ {
113
+ "proverb": "A so de timbals no s'agafen llebres.",
114
+ "themes": [
115
+ "eficàcia",
116
+ "estratègia",
117
+ "discreció"
118
+ ],
119
+ "sentiment": "realisme",
120
+ "explanation": "Vol dir que amb molt de rebombori no s'aconsegueixen coses delicades o difícils. La caça de la llebre necessita silenci, no soroll.",
121
+ "usage": "S'utilitza per criticar accions espectaculars o molt visibles que no porten resultats reals."
122
+ },
123
+ {
124
+ "proverb": "Advocats i procuradors, a l'infern de dos en dos.",
125
+ "themes": [
126
+ "justícia",
127
+ "crítica social",
128
+ "professions"
129
+ ],
130
+ "sentiment": "sarcasme",
131
+ "explanation": "Refrany popular que reflecteix la desconfiança o mala fama tradicional cap a aquests professionals, considerats sovint poc honestos o interessats.",
132
+ "usage": "S'utilitza quan es vol expressar frustració o cinisme respecte al món judicial o legal."
133
+ },
134
+ {
135
+ "proverb": "Al pot petit hi ha la bona confitura.",
136
+ "themes": [
137
+ "valor",
138
+ "aparences",
139
+ "qualitat"
140
+ ],
141
+ "sentiment": "apreciació",
142
+ "explanation": "Vol dir que les coses petites poden tenir molt de valor o ser excel·lents, com la confitura concentrada en un pot petit.",
143
+ "usage": "S'utilitza per defensar o valorar persones o coses petites però valuoses."
144
+ },
145
+ {
146
+ "proverb": "Amb una cama no es camina.",
147
+ "themes": [
148
+ "equilibri",
149
+ "col·laboració",
150
+ "funcionalitat"
151
+ ],
152
+ "sentiment": "realisme",
153
+ "explanation": "Indica que per funcionar correctament o avançar, calen més d'un recurs, eina o persona.",
154
+ "usage": "S'utilitza per expressar que no es pot fer una tasca completament amb només una part dels recursos necessaris."
155
+ },
156
+ {
157
+ "proverb": "Any de neu, any de Déu.",
158
+ "themes": [
159
+ "cicles naturals",
160
+ "bona collita",
161
+ "optimisme"
162
+ ],
163
+ "sentiment": "esperança",
164
+ "explanation": "Aquest refrany expressa que un any amb molta neu és auguri d'una bona collita i prosperitat.",
165
+ "usage": "S'utilitza per veure de manera positiva un hivern nevat o unes condicions que aparentment poden semblar dures."
166
+ },
167
+ {
168
+ "proverb": "Aquest mal no vol soroll.",
169
+ "themes": [
170
+ "prudència",
171
+ "discreció",
172
+ "precaució"
173
+ ],
174
+ "sentiment": "cautelós",
175
+ "explanation": "És millor no fer-ne massa esment d'alguns problemes delicats.",
176
+ "usage": "S'utilitza per tractar assumptes que no convé divulgar."
177
+ },
178
+ {
179
+ "proverb": "Arrancada de cavall, parada de rossí.",
180
+ "themes": [
181
+ "constància",
182
+ "impulsivitat",
183
+ "esforç"
184
+ ],
185
+ "sentiment": "crítica",
186
+ "explanation": "Vol dir que algú comença amb molt entusiasme o força, però es desinfla ràpidament i no acaba la feina.",
187
+ "usage": "S'utilitza per descriure persones o projectes que tenen un gran inici però no continuen amb la mateixa energia."
188
+ },
189
+ {
190
+ "proverb": "Barcelona és bona si la bossa sona.",
191
+ "themes": [
192
+ "riquesa",
193
+ "vida urbana",
194
+ "desigualtat"
195
+ ],
196
+ "sentiment": "ironia",
197
+ "explanation": "Aquest refrany ironitza sobre el fet que per gaudir de Barcelona (i de qualsevol ciutat gran) cal tenir diners.",
198
+ "usage": "S'utilitza per comentar que l'accés a certs llocs o plaers depèn del poder adquisitiu."
199
+ },
200
+ {
201
+ "proverb": "Bon vent i barca nova.",
202
+ "themes": [
203
+ "comiat",
204
+ "despit",
205
+ "canvi"
206
+ ],
207
+ "sentiment": "desdeny",
208
+ "explanation": "S'utilitza per acomiadar algú de manera poc afectuosa, desitjant-li que se'n vagi lluny.",
209
+ "usage": "S'empra quan algú se'n va i no se'l troba a faltar, o fins i tot se n'alegra."
210
+ },
211
+ {
212
+ "proverb": "Brams d'ase no arriben al cel.",
213
+ "themes": [
214
+ "ignorància",
215
+ "ofenses",
216
+ "indiferència"
217
+ ],
218
+ "sentiment": "menyspreu",
219
+ "explanation": "Vol dir que els insults o comentaris d'ignorants no tenen importància ni transcendència.",
220
+ "usage": "S'utilitza per restar importància a crítiques o comentaris ofensius de gent poc respectada."
221
+ },
222
+ {
223
+ "proverb": "Cada terra fa sa guerra.",
224
+ "themes": [
225
+ "diversitat",
226
+ "cultura",
227
+ "costums"
228
+ ],
229
+ "sentiment": "reflexiu",
230
+ "explanation": "Indica que cada lloc té els seus costums i maneres de fer diferents.",
231
+ "usage": "S'empra per justificar diferències entre regions o tradicions locals."
232
+ },
233
+ {
234
+ "proverb": "Caldera vella, bony o forat.",
235
+ "themes": [
236
+ "experiència",
237
+ "envelliment",
238
+ "imperfecció"
239
+ ],
240
+ "sentiment": "comprensiu",
241
+ "explanation": "Vol dir que amb el temps tot s'espatlla o té defectes.",
242
+ "usage": "S'utilitza per excusar errors o defectes en persones o coses velles."
243
+ },
244
+ {
245
+ "proverb": "Canalla neixem i canalla tornem.",
246
+ "themes": [
247
+ "vida",
248
+ "vellesa",
249
+ "cicle vital"
250
+ ],
251
+ "sentiment": "melancòlic",
252
+ "explanation": "Expressa que tal com naixem dèbils i dependents, així ens tornem amb la vellesa.",
253
+ "usage": "S'utilitza parlant del pas del temps i la pèrdua d'autonomia en fer-se gran."
254
+ },
255
+ {
256
+ "proverb": "Cap geperut no es veu el gep.",
257
+ "themes": [
258
+ "hipocresia",
259
+ "autocrítica",
260
+ "defectes"
261
+ ],
262
+ "sentiment": "crític",
263
+ "explanation": "Vol dir que la gent sovint no veu els seus propis defectes però sí els dels altres.",
264
+ "usage": "S'utilitza per retreure a algú que critica però no veu les seves pròpies mancances."
265
+ },
266
+ {
267
+ "proverb": "Carrers molls, calaixos eixuts.",
268
+ "themes": [
269
+ "clima",
270
+ "economia",
271
+ "pagesia"
272
+ ],
273
+ "sentiment": "preocupació",
274
+ "explanation": "Expressa que quan plou massa, els pagesos no poden vendre i no guanyen diners.",
275
+ "usage": "S'empra en contextos agrícoles per parlar dels efectes econòmics del mal temps."
276
+ },
277
+ {
278
+ "proverb": "Com més serem, més riurem.",
279
+ "themes": [
280
+ "companyonia",
281
+ "diversió",
282
+ "optimisme"
283
+ ],
284
+ "sentiment": "alegria",
285
+ "explanation": "Vol dir que com més gent hi hagi, millor s'ho passa tothom.",
286
+ "usage": "S'utilitza per convidar més gent a unir-se a una activitat o celebració."
287
+ },
288
+ {
289
+ "proverb": "Cosa dolenta, fora del ventre.",
290
+ "themes": [
291
+ "nadalitat",
292
+ "alliberament",
293
+ "família"
294
+ ],
295
+ "sentiment": "alleujament",
296
+ "explanation": "Es diu després de donar a llum, celebrant que el part ha acabat bé.",
297
+ "usage": "S'utilitza tradicionalment en contextos rurals o familiars després del naixement d'un infant."
298
+ },
299
+ {
300
+ "proverb": "Cria fama i posa't a jeure.",
301
+ "themes": [
302
+ "reputació",
303
+ "comoditat",
304
+ "aparences"
305
+ ],
306
+ "sentiment": "cínic",
307
+ "explanation": "Quan tens una bona reputació, pots aprofitar-te'n i no esforçar-te gaire.",
308
+ "usage": "S'utilitza per referir-se a qui viu de la seva fama sense fer gaire res."
309
+ },
310
+ {
311
+ "proverb": "Cànter nou fa l'aigua fresca.",
312
+ "themes": [
313
+ "novetat",
314
+ "atractiu",
315
+ "aparences"
316
+ ],
317
+ "sentiment": "positiu",
318
+ "explanation": "Indica que allò nou o recent sempre sembla millor o més atractiu.",
319
+ "usage": "S'empra per valorar la novetat o justificar un canvi per coses noves."
320
+ },
321
+ {
322
+ "proverb": "D'on no n'hi ha, no en pot rajar.",
323
+ "themes": [
324
+ "limitacions",
325
+ "realitat",
326
+ "expectatives"
327
+ ],
328
+ "sentiment": "realista",
329
+ "explanation": "No es pot treure res d'on no hi ha recursos o capacitat.",
330
+ "usage": "S'empra per indicar que no es poden exigir coses impossibles."
331
+ },
332
+ {
333
+ "proverb": "De Joans, Joseps i ases, n'hi ha a totes les cases.",
334
+ "themes": [
335
+ "popularitat",
336
+ "quotidianitat",
337
+ "persones"
338
+ ],
339
+ "sentiment": "irònic",
340
+ "explanation": "Indica que hi ha noms o persones molt comunes, a vegades amb sentit despectiu.",
341
+ "usage": "S'utilitza per parlar de coses o persones corrents, sense singularitat."
342
+ },
343
+ {
344
+ "proverb": "De desagraïts, l'infern n'és ple.",
345
+ "themes": [
346
+ "agraïment",
347
+ "moral",
348
+ "valors"
349
+ ],
350
+ "sentiment": "reprotxa",
351
+ "explanation": "Critica les persones que no són agraïdes quan reben ajuda.",
352
+ "usage": "S'utilitza per retreure la manca d'agraïment."
353
+ },
354
+ {
355
+ "proverb": "De les rialles vénen les ploralles.",
356
+ "themes": [
357
+ "canvi",
358
+ "advertència",
359
+ "equilibri"
360
+ ],
361
+ "sentiment": "preventiu",
362
+ "explanation": "Recorda que darrere la diversió pot venir el plor o una situació negativa.",
363
+ "usage": "S'empra per advertir de no perdre el seny en l'alegria."
364
+ },
365
+ {
366
+ "proverb": "De mica en mica s'omple la pica.",
367
+ "themes": [
368
+ "paciència",
369
+ "constància",
370
+ "progrés"
371
+ ],
372
+ "sentiment": "positiu",
373
+ "explanation": "Amb esforç constant, encara que lent, s'aconsegueixen grans coses.",
374
+ "usage": "S'utilitza per encoratjar a seguir treballant pas a pas."
375
+ },
376
+ {
377
+ "proverb": "De moliner mudaràs i de lladre no t'escaparàs.",
378
+ "themes": [
379
+ "justícia",
380
+ "naturalesa humana",
381
+ "canvi"
382
+ ],
383
+ "sentiment": "pessimista",
384
+ "explanation": "Vol dir que pots evitar certes coses, però no sempre el mal.",
385
+ "usage": "S'utilitza per indicar que hi ha mals inevitables."
386
+ },
387
+ {
388
+ "proverb": "De més verdes en maduren.",
389
+ "themes": [
390
+ "esperança",
391
+ "temps",
392
+ "canvi"
393
+ ],
394
+ "sentiment": "esperançador",
395
+ "explanation": "Encara que ara sembli difícil, tot pot canviar amb el temps.",
396
+ "usage": "S'utilitza per expressar que les coses poden evolucionar favorablement."
397
+ },
398
+ {
399
+ "proverb": "De ponent, ni vent ni gent.",
400
+ "themes": [
401
+ "clima",
402
+ "caràcter",
403
+ "territori"
404
+ ],
405
+ "sentiment": "despectiu",
406
+ "explanation": "Fa referència a la mala fama del vent i la gent que ve de ponent.",
407
+ "usage": "S'empra per criticar el mal temps o la gent d'un lloc determinat."
408
+ },
409
+ {
410
+ "proverb": "De porc i de senyor, se n'ha de venir de mena.",
411
+ "themes": [
412
+ "origen",
413
+ "educació",
414
+ "naturalesa"
415
+ ],
416
+ "sentiment": "conservador",
417
+ "explanation": "Indica que certes qualitats no s'aprenen, sinó que es tenen de naixement.",
418
+ "usage": "S'utilitza per valorar el llinatge o l'educació heretada."
419
+ },
420
+ {
421
+ "proverb": "De qui pa en fa rosegons.",
422
+ "themes": [
423
+ "repartiment",
424
+ "enveja",
425
+ "economia"
426
+ ],
427
+ "sentiment": "desconfiat",
428
+ "explanation": "El que en té, sempre en guarda o en fa profit pels seus interessos.",
429
+ "usage": "S'utilitza per assenyalar qui sap aprofitar-se de tot."
430
+ },
431
+ {
432
+ "proverb": "De vell, ningú no passa.",
433
+ "themes": [
434
+ "vellesa",
435
+ "destí",
436
+ "vida"
437
+ ],
438
+ "sentiment": "resignat",
439
+ "explanation": "Tots envellim si no morim abans.",
440
+ "usage": "S'empra per recordar que ningú s'escapa del pas del temps."
441
+ },
442
+ {
443
+ "proverb": "Demanar no fa pobre.",
444
+ "themes": [
445
+ "dignitat",
446
+ "necessitat",
447
+ "humilitat"
448
+ ],
449
+ "sentiment": "neutral",
450
+ "explanation": "No passa res per demanar ajuda si es necessita.",
451
+ "usage": "S'utilitza per encoratjar algú a demanar sense vergonya."
452
+ },
453
+ {
454
+ "proverb": "Diu el mort al degollat: qui t'ha fet eixe forat?.",
455
+ "themes": [
456
+ "cinisme",
457
+ "ironia",
458
+ "hipocresia"
459
+ ],
460
+ "sentiment": "burleta",
461
+ "explanation": "Es diu quan algú en mal estat es burla o critica algú que està pitjor.",
462
+ "usage": "S'utilitza per posar en evidència la hipocresia."
463
+ },
464
+ {
465
+ "proverb": "Déu dona faves a qui no té queixals.",
466
+ "themes": [
467
+ "injustícia",
468
+ "destí",
469
+ "desigualtat"
470
+ ],
471
+ "sentiment": "crític",
472
+ "explanation": "La vida dona coses valuoses a qui no les pot aprofitar.",
473
+ "usage": "S'empra per lamentar-se de la mala sort o les injustícies de la vida."
474
+ },
475
+ {
476
+ "proverb": "El fill de la gata, rates mata.",
477
+ "themes": [
478
+ "naturalesa",
479
+ "herència",
480
+ "instint"
481
+ ],
482
+ "sentiment": "afirmatiu",
483
+ "explanation": "Indica que els fills s'assemblen als pares en actitud o caràcter.",
484
+ "usage": "S'utilitza quan algú segueix les passes familiars."
485
+ },
486
+ {
487
+ "proverb": "El mal fuster molts encenalls sol fer.",
488
+ "themes": [
489
+ "errors",
490
+ "habilitat",
491
+ "resultats"
492
+ ],
493
+ "sentiment": "advertència",
494
+ "explanation": "Vol dir que aquells que no fan bé les coses solen generar més problemes o mal resultat.",
495
+ "usage": "S'utilitza per advertir sobre els perills d'un treball mal fet o descurat."
496
+ },
497
+ {
498
+ "proverb": "El més calent és a l'aigüera.",
499
+ "themes": [
500
+ "tasques inacabades",
501
+ "imprevistos",
502
+ "desordre"
503
+ ],
504
+ "sentiment": "frustració",
505
+ "explanation": "Vol dir que encara no s'ha acabat allò que s'estava fent.",
506
+ "usage": "S'utilitza per indicar que queda feina pendent."
507
+ },
508
+ {
509
+ "proverb": "El nom no fa la cosa.",
510
+ "themes": [
511
+ "aparences",
512
+ "essència",
513
+ "veritat"
514
+ ],
515
+ "sentiment": "reflexiu",
516
+ "explanation": "No es pot jutjar una cosa només pel seu nom o aparença.",
517
+ "usage": "S'empra per recordar que l'essència importa més que la forma."
518
+ },
519
+ {
520
+ "proverb": "El prometre no fa pobre.",
521
+ "themes": [
522
+ "paraules",
523
+ "compromís",
524
+ "engany"
525
+ ],
526
+ "sentiment": "escèptic",
527
+ "explanation": "Prometre no costa res, però complir és diferent.",
528
+ "usage": "S'utilitza per desconfiar de les promeses buides."
529
+ },
530
+ {
531
+ "proverb": "El que no vulguis per a tu, no ho vulguis per a ningú.",
532
+ "themes": [
533
+ "ètica",
534
+ "empatia",
535
+ "respecte"
536
+ ],
537
+ "sentiment": "moralitzador",
538
+ "explanation": "Tracta els altres com voldries ser tractat.",
539
+ "usage": "S'utilitza per promoure el respecte i la justícia en les accions personals."
540
+ },
541
+ {
542
+ "proverb": "Els catalans de les pedres en fem pans.",
543
+ "themes": [
544
+ "recursivitat",
545
+ "identitat",
546
+ "resiliència"
547
+ ],
548
+ "sentiment": "orgullós",
549
+ "explanation": "Els catalans sabem aprofitar qualsevol recurs, per escàs que sigui.",
550
+ "usage": "S'utilitza per expressar l'enginy i capacitat de sortir-se'n amb poc."
551
+ },
552
+ {
553
+ "proverb": "Els estalvis es mengen les estovalles.",
554
+ "themes": [
555
+ "avarícia",
556
+ "mesura",
557
+ "conseqüències"
558
+ ],
559
+ "sentiment": "crític",
560
+ "explanation": "L'estalvi excessiu pot fer perdre més del que es guanya.",
561
+ "usage": "S'utilitza per advertir sobre els efectes negatius de l'estalvi extrem."
562
+ },
563
+ {
564
+ "proverb": "Els testos s'assemblen a les olles.",
565
+ "themes": [
566
+ "família",
567
+ "semblança",
568
+ "educació"
569
+ ],
570
+ "sentiment": "reflexiu",
571
+ "explanation": "Els fills acostumen a assemblar-se als pares.",
572
+ "usage": "S'utilitza per indicar la transmissió de caràcters o costums familiars."
573
+ },
574
+ {
575
+ "proverb": "Em fas festes i no me'n solies fer, és que em vols fotre o m'has de menester.",
576
+ "themes": [
577
+ "desconfiança",
578
+ "interès",
579
+ "relacions"
580
+ ],
581
+ "sentiment": "sospitós",
582
+ "explanation": "Quan algú sobtadament és amable, pot ser que tingui un interès ocult.",
583
+ "usage": "S'utilitza per expressar recel davant una actitud inusualment simpàtica."
584
+ },
585
+ {
586
+ "proverb": "Feina feta no fa destorb.",
587
+ "themes": [
588
+ "ordre",
589
+ "eficiència",
590
+ "treball"
591
+ ],
592
+ "sentiment": "positiu",
593
+ "explanation": "Quan les coses es fan al seu temps, deixen de ser un problema.",
594
+ "usage": "S'utilitza per fomentar la previsió i el compliment de les tasques."
595
+ },
596
+ {
597
+ "proverb": "Feina fuig, mandra no em deixis.",
598
+ "themes": [
599
+ "peresa",
600
+ "procrastinació",
601
+ "sàtira"
602
+ ],
603
+ "sentiment": "irònic",
604
+ "explanation": "Fa broma sobre la mandra i la tendència a evitar la feina.",
605
+ "usage": "S'empra en to humorístic quan no es vol treballar."
606
+ },
607
+ {
608
+ "proverb": "Feta la llei, feta la trampa.",
609
+ "themes": [
610
+ "legalitat",
611
+ "enginy",
612
+ "corruptela"
613
+ ],
614
+ "sentiment": "escèptic",
615
+ "explanation": "Sempre hi ha qui troba la manera de saltar-se les normes.",
616
+ "usage": "S'utilitza per assenyalar la facilitat amb què es poden esquivar les lleis."
617
+ },
618
+ {
619
+ "proverb": "Gallina vella fa bon caldo.",
620
+ "themes": [
621
+ "experiència",
622
+ "edat",
623
+ "valor"
624
+ ],
625
+ "sentiment": "positiu",
626
+ "explanation": "Les persones grans poden aportar molt, com una gallina vella fa un bon brou.",
627
+ "usage": "S'utilitza per defensar el valor de l'experiència."
628
+ },
629
+ {
630
+ "proverb": "Gat escaldat, de l'aigua tèbia fuig.",
631
+ "themes": [
632
+ "trauma",
633
+ "prudència",
634
+ "experiència"
635
+ ],
636
+ "sentiment": "cautelós",
637
+ "explanation": "Qui ha tingut una mala experiència, evita fins i tot riscos petits.",
638
+ "usage": "S'utilitza per justificar una actitud temerosa o reservada."
639
+ },
640
+ {
641
+ "proverb": "Gent jove, pa tou.",
642
+ "themes": [
643
+ "joventut",
644
+ "fragilitat",
645
+ "inexperiència"
646
+ ],
647
+ "sentiment": "despectiu",
648
+ "explanation": "Els joves poden ser tous o no tenir prou resistència.",
649
+ "usage": "S'utilitza de manera crítica per referir-se a la manca de fermesa dels joves."
650
+ },
651
+ {
652
+ "proverb": "Hi ha més dies que llonganisses.",
653
+ "themes": [
654
+ "paciència",
655
+ "temps",
656
+ "esperança"
657
+ ],
658
+ "sentiment": "tranquil·litzador",
659
+ "explanation": "Encara hi ha molt de temps per fer les coses.",
660
+ "usage": "S'utilitza per calmar algú que té pressa o angoixa."
661
+ },
662
+ {
663
+ "proverb": "Home casat, burro espatllat.",
664
+ "themes": [
665
+ "matrimoni",
666
+ "experiència",
667
+ "ironia"
668
+ ],
669
+ "sentiment": "burleta",
670
+ "explanation": "El matrimoni pot desgastar o limitar l'home.",
671
+ "usage": "S'empra de manera humorística o crítica sobre els efectes del matrimoni."
672
+ },
673
+ {
674
+ "proverb": "Home de molts oficis, pobre segur.",
675
+ "themes": [
676
+ "especialització",
677
+ "treball",
678
+ "riquesa"
679
+ ],
680
+ "sentiment": "escèptic",
681
+ "explanation": "Qui fa moltes coses diferents, sovint no domina cap i no prospera.",
682
+ "usage": "S'utilitza per valorar la importància de centrar-se en un ofici."
683
+ },
684
+ {
685
+ "proverb": "Home roig i gos pelut, primer mort que conegut.",
686
+ "themes": [
687
+ "aparences",
688
+ "desconfiança",
689
+ "prejudicis"
690
+ ],
691
+ "sentiment": "refrany tradicional",
692
+ "explanation": "Desconfiança envers allò que es veu com estrany o fora del comú.",
693
+ "usage": "S'utilitza (de manera ja molt antiquada o crítica) per referir-se a la desconfiança basada en aparença."
694
+ },
695
+ {
696
+ "proverb": "Hostes vingueren que de casa ens tragueren.",
697
+ "themes": [
698
+ "hospitalitat",
699
+ "abusos",
700
+ "conseqüències"
701
+ ],
702
+ "sentiment": "negatiu",
703
+ "explanation": "Els convidats es van imposar tant que van fer fora els amfitrions.",
704
+ "usage": "S'utilitza per advertir del perill de ser massa acollidor."
705
+ },
706
+ {
707
+ "proverb": "Ja pots xiular, si l'ase no vol beure.",
708
+ "themes": [
709
+ "voluntat",
710
+ "ineficiència",
711
+ "força de voluntat"
712
+ ],
713
+ "sentiment": "resignat",
714
+ "explanation": "No serveix de res insistir si l'altre no vol cooperar.",
715
+ "usage": "S'utilitza quan algú és tossut o intractable."
716
+ },
717
+ {
718
+ "proverb": "L'alegria dura poc a casa del pobre.",
719
+ "themes": [
720
+ "classe social",
721
+ "tristesa",
722
+ "realitat"
723
+ ],
724
+ "sentiment": "trist",
725
+ "explanation": "Les bones notícies duren poc quan es tenen pocs recursos.",
726
+ "usage": "S'utilitza per expressar una realitat dura i injusta."
727
+ },
728
+ {
729
+ "proverb": "L'ase d'en Mora, de tot se n'enamora.",
730
+ "themes": [
731
+ "frivolitat",
732
+ "tendències",
733
+ "canvi d'opinió"
734
+ ],
735
+ "sentiment": "burleta",
736
+ "explanation": "Fa referència a qui canvia de preferències sovint o s'entusiasma fàcilment.",
737
+ "usage": "S'utilitza per descriure persones inconstants o massa entusiastes."
738
+ },
739
+ {
740
+ "proverb": "L'enciam és l'escombreta de la panxa.",
741
+ "themes": [
742
+ "salut",
743
+ "alimentació",
744
+ "digestió"
745
+ ],
746
+ "sentiment": "positiu",
747
+ "explanation": "L'enciam ajuda a fer neteja a l'estómac i afavoreix la digestió.",
748
+ "usage": "S'utilitza per promoure una dieta saludable."
749
+ },
750
+ {
751
+ "proverb": "L'ull del amo engreixa el cavall",
752
+ "themes": [
753
+ "vigilància",
754
+ "responsabilitat",
755
+ "cura",
756
+ "gestió"
757
+ ],
758
+ "sentiment": "consell",
759
+ "explanation": "Vol dir que quan el propietari o responsable està pendent de les seves coses, aquestes funcionen millor o prosperen.",
760
+ "usage": "S’utilitza per destacar la importància de supervisar personalment allò que és teu si vols que vagi bé."
761
+ },
762
+ {
763
+ "proverb": "Les cabres, pels seus pecats, porten els genolls pelats.",
764
+ "themes": [
765
+ "conseqüències",
766
+ "culpa",
767
+ "accions"
768
+ ],
769
+ "sentiment": "advertència",
770
+ "explanation": "Indica que els errors o mals actes sovint deixen rastres visibles o conseqüències.",
771
+ "usage": "S'utilitza per remarcar que les males accions no passen desapercebudes."
772
+ },
773
+ {
774
+ "proverb": "Lo món no fou fet en un dia",
775
+ "themes": [
776
+ "temps",
777
+ "paciència",
778
+ "procés",
779
+ "esforç"
780
+ ],
781
+ "sentiment": "reflexió",
782
+ "explanation": "Vol dir que les grans obres o els bons resultats necessiten temps per aconseguir-se, i no es poden fer de pressa.",
783
+ "usage": "S’utilitza per recordar que cal tenir paciència i constància per assolir objectius importants."
784
+ },
785
+ {
786
+ "proverb": "Març, marçot, mata la vella a la vora del foc i la jove si pot.",
787
+ "themes": [
788
+ "clima",
789
+ "duresa",
790
+ "inestabilitat"
791
+ ],
792
+ "sentiment": "precaució",
793
+ "explanation": "Fa referència a la duresa i inestabilitat del mes de març, que pot afectar tothom.",
794
+ "usage": "S'utilitza per avisar del fred tardà o el temps traïdorenc de març."
795
+ },
796
+ {
797
+ "proverb": "Molta fressa i poca endreça.",
798
+ "themes": [
799
+ "aparences",
800
+ "eficiència",
801
+ "crítica"
802
+ ],
803
+ "sentiment": "desaprovació",
804
+ "explanation": "Descriu situacions on es fa molt soroll però poca feina real.",
805
+ "usage": "S'utilitza per criticar la manca de productivitat malgrat l'activitat aparent."
806
+ },
807
+ {
808
+ "proverb": "Muts i a la gàbia.",
809
+ "themes": [
810
+ "silenci",
811
+ "autoritat",
812
+ "obediència"
813
+ ],
814
+ "sentiment": "imperatiu",
815
+ "explanation": "És una expressió que ordena callar i sotmetre's.",
816
+ "usage": "S'utilitza per exigir silenci o aturar qualsevol protesta o comentari."
817
+ },
818
+ {
819
+ "proverb": "Més viu el qui piula que el qui xiula.",
820
+ "themes": [
821
+ "vivacitat",
822
+ "astúcia",
823
+ "expressió"
824
+ ],
825
+ "sentiment": "afirmació",
826
+ "explanation": "Indica que qui s'expressa o actua amb intel·ligència sol sortir-se'n millor.",
827
+ "usage": "S'utilitza per valorar l'enginy o la capacitat de fer-se notar amb habilitat."
828
+ },
829
+ {
830
+ "proverb": "Músic pagat no fa bon so.",
831
+ "themes": [
832
+ "interès",
833
+ "motivació",
834
+ "qualitat"
835
+ ],
836
+ "sentiment": "cínic",
837
+ "explanation": "Suggerix que quan algú ja ha cobrat, potser no treballa amb la mateixa qualitat.",
838
+ "usage": "S'utilitza per expressar desconfiança en el rendiment un cop s'ha cobrat per endavant."
839
+ },
840
+ {
841
+ "proverb": "N'hi ha per llogar-hi cadires.",
842
+ "themes": [
843
+ "sorpresa",
844
+ "exageració",
845
+ "crítica social"
846
+ ],
847
+ "sentiment": "sorpresa",
848
+ "explanation": "Expressa que una situació és tan extravagant o conflictiva que val la pena seure a mirar-la.",
849
+ "usage": "S'utilitza davant d'una escena ridícula, absurda o d'alt dramatisme."
850
+ },
851
+ {
852
+ "proverb": "Ningú és profeta en la seva terra.",
853
+ "themes": [
854
+ "reconeixement",
855
+ "injustícia",
856
+ "societat"
857
+ ],
858
+ "sentiment": "resignació",
859
+ "explanation": "Expressa que sovint no es reconeix el valor d'algú en el seu propi entorn.",
860
+ "usage": "S'utilitza quan una persona no rep valoració al seu lloc d'origen."
861
+ },
862
+ {
863
+ "proverb": "No deixes les sendes velles per les novelles.",
864
+ "themes": [
865
+ "prudència",
866
+ "experiència",
867
+ "tradició"
868
+ ],
869
+ "sentiment": "conservador",
870
+ "explanation": "Recomana no abandonar allò conegut i segur per opcions noves i incertes.",
871
+ "usage": "S'utilitza per advertir contra els canvis innecessaris o arriscats."
872
+ },
873
+ {
874
+ "proverb": "No diguis blat que no sigui al sac i ben lligat.",
875
+ "themes": [
876
+ "precaució",
877
+ "expectatives",
878
+ "realitat"
879
+ ],
880
+ "sentiment": "advertència",
881
+ "explanation": "Adverteix de no donar res per segur fins que no es té completament assolit.",
882
+ "usage": "S'utilitza per recomanar prudència abans de celebrar l'èxit."
883
+ },
884
+ {
885
+ "proverb": "No diguis mai d'aquesta aigua no en beuré.",
886
+ "themes": [
887
+ "humilitat",
888
+ "canvis",
889
+ "incertesa"
890
+ ],
891
+ "sentiment": "advertència",
892
+ "explanation": "Fes referència a la incertesa del futur, i com les circumstàncies poden canviar.",
893
+ "usage": "S'utilitza per advertir que mai es pot estar segur de tot, ja que les opinions o accions poden canviar."
894
+ },
895
+ {
896
+ "proverb": "No es pot pas matar tot el que és gras.",
897
+ "themes": [
898
+ "incapacitat",
899
+ "limitacions",
900
+ "realisme"
901
+ ],
902
+ "sentiment": "realista",
903
+ "explanation": "Indica que no tot es pot canviar o eliminar, hi ha coses que són difícils d'afectar.",
904
+ "usage": "S'utilitza per reconèixer les limitacions davant situacions complicades."
905
+ },
906
+ {
907
+ "proverb": "No hi ha mal dinar per qui es fa convidar.",
908
+ "themes": [
909
+ "convides",
910
+ "comer",
911
+ "despesa"
912
+ ],
913
+ "sentiment": "ironia",
914
+ "explanation": "Vol dir que el menjar d'un convidat sempre és millor perquè no ha de pagar.",
915
+ "usage": "S'utilitza per referir-se als avantatges d'algú que gaudeix de serveis sense haver de pagar."
916
+ },
917
+ {
918
+ "proverb": "No hi ha mal que cent anys duri ni cos que resistir el pugui.",
919
+ "themes": [
920
+ "temps",
921
+ "resiliència",
922
+ "esperança",
923
+ "patiment"
924
+ ],
925
+ "sentiment": "consol",
926
+ "explanation": "Vol dir que cap mal dura per sempre, i que fins i tot els pitjors moments acaben passant, ja que ningú pot suportar un patiment etern.",
927
+ "usage": "S’utilitza per consolar algú que està passant per una mala època, recordant-li que tot acaba passant."
928
+ },
929
+ {
930
+ "proverb": "No vols caldo? Dues tasses!",
931
+ "themes": [
932
+ "desafiaments",
933
+ "conseqüències",
934
+ "ironia"
935
+ ],
936
+ "sentiment": "irònic",
937
+ "explanation": "Suggerix que si rebutges una situació, en pots rebre encara més.",
938
+ "usage": "S'utilitza per evidenciar que rebutjar una opció pot portar a una situació encara més difícil."
939
+ },
940
+ {
941
+ "proverb": "No és carn ni peix i piula quan neix.",
942
+ "themes": [
943
+ "ambigüitat",
944
+ "incertesa",
945
+ "caràcter"
946
+ ],
947
+ "sentiment": "desaprovació",
948
+ "explanation": "Descriu algú que no té una postura clara o definida, essent indecís.",
949
+ "usage": "S'utilitza per criticar aquells que no tenen una posició decidida o clara."
950
+ },
951
+ {
952
+ "proverb": "On no hi ha sang, butifarra no s'hi fa.",
953
+ "themes": [
954
+ "esforç",
955
+ "resultat",
956
+ "relacions"
957
+ ],
958
+ "sentiment": "realista",
959
+ "explanation": "Indica que els bons resultats requereixen esforç i implicació.",
960
+ "usage": "S'utilitza per dir que les coses bones no es poden aconseguir sense treball dur."
961
+ },
962
+ {
963
+ "proverb": "Pagant, Sant Pere canta.",
964
+ "themes": [
965
+ "diners",
966
+ "interessos",
967
+ "motivació"
968
+ ],
969
+ "sentiment": "cínic",
970
+ "explanation": "Indica que les persones actuen de manera diferent quan hi ha un interès econòmic involucrat.",
971
+ "usage": "S'utilitza per mostrar que les accions estan sovint motivades per interessos econòmics."
972
+ },
973
+ {
974
+ "proverb": "Panxa plena no té pena.",
975
+ "themes": [
976
+ "satisfacció",
977
+ "necessitats bàsiques",
978
+ "comoditat"
979
+ ],
980
+ "sentiment": "afirmació",
981
+ "explanation": "Aquesta expressió subratlla com la satisfacció de les necessitats bàsiques porta tranquil·litat.",
982
+ "usage": "S'utilitza per dir que quan algú està satisfet, sol estar més content i tranquil."
983
+ },
984
+ {
985
+ "proverb": "Preu per preu, sabates grosses.",
986
+ "themes": [
987
+ "costos",
988
+ "valor",
989
+ "eficiència"
990
+ ],
991
+ "sentiment": "pragmatisme",
992
+ "explanation": "Suggerix que si s'ha de pagar el mateix, és millor optar per una opció millor.",
993
+ "usage": "S'utilitza per advocar per obtenir el millor valor possible en qualsevol situació."
994
+ },
995
+ {
996
+ "proverb": "Quan el dia creix, el fred neix.",
997
+ "themes": [
998
+ "temps",
999
+ "cicles",
1000
+ "relacions naturals"
1001
+ ],
1002
+ "sentiment": "observacional",
1003
+ "explanation": "Fa referència al comportament del temps en relació a la llargada dels dies.",
1004
+ "usage": "S'utilitza per descriure les variacions de temperatura segons les estacions."
1005
+ },
1006
+ {
1007
+ "proverb": "Quan la guineu no les pot haver diu que són verdes.",
1008
+ "themes": [
1009
+ "excuses",
1010
+ "frustració",
1011
+ "justificacions"
1012
+ ],
1013
+ "sentiment": "crítica",
1014
+ "explanation": "Descrit a qui es nega a reconèixer una cosa tot i que és evident, justificant-se amb excuses.",
1015
+ "usage": "S'utilitza per criticar aquells que donen excuses per justificar la seva incapacitat o fracàs."
1016
+ },
1017
+ {
1018
+ "proverb": "Quan un no vol, dos no es barallen.",
1019
+ "themes": [
1020
+ "conflictes",
1021
+ "responsabilitat",
1022
+ "relacions"
1023
+ ],
1024
+ "sentiment": "reflexió",
1025
+ "explanation": "Indica que en un conflicte, si una de les parts no vol discutir, no pot haver-hi baralla.",
1026
+ "usage": "S'utilitza per dir que la resolució de conflictes depèn també de la voluntat de les dues parts."
1027
+ },
1028
+ {
1029
+ "proverb": "Que la mà esquerra no sàpiga el que fa la mà dreta.",
1030
+ "themes": [
1031
+ "discreció",
1032
+ "privacitat",
1033
+ "accions"
1034
+ ],
1035
+ "sentiment": "prudència",
1036
+ "explanation": "Suggerix que cal mantenir les accions en secret i no deixar que altres sàpiguen els nostres moviments.",
1037
+ "usage": "S'utilitza per instar a la discreció i la privacitat en les accions importants."
1038
+ },
1039
+ {
1040
+ "proverb": "Qui canta a la taula i xiula al llit, no té el seny complit.",
1041
+ "themes": [
1042
+ "conducta",
1043
+ "coherència",
1044
+ "caràcter"
1045
+ ],
1046
+ "sentiment": "crítica",
1047
+ "explanation": "Indica que qui no és coherent en les seves accions i comportaments no és completament savi.",
1048
+ "usage": "S'utilitza per criticar qui té actituds contradictòries."
1049
+ },
1050
+ {
1051
+ "proverb": "Qui canta els seus mals espanta.",
1052
+ "themes": [
1053
+ "expressió",
1054
+ "emocions",
1055
+ "cataracta"
1056
+ ],
1057
+ "sentiment": "cautela",
1058
+ "explanation": "Indica que parlar dels problemes pot alleujar però també pot causar reaccions negatives.",
1059
+ "usage": "S'utilitza per alertar de les conseqüències de compartir massa les pròpies dificultats."
1060
+ },
1061
+ {
1062
+ "proverb": "Qui de jove no treballa, de vell dorm a la palla.",
1063
+ "themes": [
1064
+ "esforç",
1065
+ "futur",
1066
+ "responsabilitat"
1067
+ ],
1068
+ "sentiment": "advertència",
1069
+ "explanation": "Aquesta dita fa referència al fet que no treballar de jove porta problemes econòmics o de salut a l'edat avançada.",
1070
+ "usage": "S'utilitza per advertir els joves de la importància de l'esforç a la vida laboral."
1071
+ },
1072
+ {
1073
+ "proverb": "Qui dia passa, any empeny.",
1074
+ "themes": [
1075
+ "temps",
1076
+ "persistència",
1077
+ "futur"
1078
+ ],
1079
+ "sentiment": "optimisme",
1080
+ "explanation": "Indica que el temps passarà i que les dificultats es superaran amb el temps.",
1081
+ "usage": "S'utilitza per dir que la paciència i la persistència ens portaran a superar les dificultats."
1082
+ },
1083
+ {
1084
+ "proverb": "Qui fa un cove fa un cistell.",
1085
+ "themes": [
1086
+ "treball",
1087
+ "resultats",
1088
+ "acció"
1089
+ ],
1090
+ "sentiment": "optimisme",
1091
+ "explanation": "Indica que les petites accions o esforços porten a resultats més grans si es mantenen.",
1092
+ "usage": "S'utilitza per motivar a perseverar en qualsevol tasca, ja que els petits esforços s'acumulen."
1093
+ },
1094
+ {
1095
+ "proverb": "Qui guanya primer, s'escanya darrer.",
1096
+ "themes": [
1097
+ "competència",
1098
+ "temps",
1099
+ "resultats"
1100
+ ],
1101
+ "sentiment": "advertència",
1102
+ "explanation": "Expressa que en competicions o desafiaments, qui corre massa al principi pot acabar fatigat o en desavantatge a la fi.",
1103
+ "usage": "S'utilitza per advertir que cal equilibrar l'esforç i no precipitar-se massa."
1104
+ },
1105
+ {
1106
+ "proverb": "Qui guarda quan té, menja quan vol.",
1107
+ "themes": [
1108
+ "estalvi",
1109
+ "previsió",
1110
+ "seguretat"
1111
+ ],
1112
+ "sentiment": "conservador",
1113
+ "explanation": "Diu que qui estalvia o guarda en els moments bons tindrà seguretat en els moments difícils.",
1114
+ "usage": "S'utilitza per animar a ser prudent i estalviar per al futur."
1115
+ },
1116
+ {
1117
+ "proverb": "Qui la fa, la paga.",
1118
+ "themes": [
1119
+ "responsabilitat",
1120
+ "justícia",
1121
+ "acció"
1122
+ ],
1123
+ "sentiment": "equitat",
1124
+ "explanation": "Expressa que qui comet un error o una acció negativa en serà responsable.",
1125
+ "usage": "S'utilitza per recordar que cada acció té una conseqüència."
1126
+ },
1127
+ {
1128
+ "proverb": "Qui mal no fa, mal no pensa.",
1129
+ "themes": [
1130
+ "intencions",
1131
+ "puresa",
1132
+ "moralitat"
1133
+ ],
1134
+ "sentiment": "ètica",
1135
+ "explanation": "Indica que qui actua de manera correcta no té males intencions.",
1136
+ "usage": "S'utilitza per justificar o defensar una persona que no té intencions malicioses."
1137
+ },
1138
+ {
1139
+ "proverb": "Qui menja sopes, se les pensa totes.",
1140
+ "themes": [
1141
+ "experiència",
1142
+ "reflexió",
1143
+ "prudència"
1144
+ ],
1145
+ "sentiment": "sabiesa",
1146
+ "explanation": "Fes referència a qui té experiència o qui pensa molt abans d'actuar.",
1147
+ "usage": "S'utilitza per dir que les persones que reflexionen abans de fer alguna cosa solen ser més astutes."
1148
+ },
1149
+ {
1150
+ "proverb": "Qui molt xerra, algunes n'erra.",
1151
+ "themes": [
1152
+ "paraula",
1153
+ "precaució",
1154
+ "comunicació"
1155
+ ],
1156
+ "sentiment": "advertència",
1157
+ "explanation": "Indica que parlar massa pot portar a equivocar-se.",
1158
+ "usage": "S'utilitza per advertir que parlar excessivament pot causar errors."
1159
+ },
1160
+ {
1161
+ "proverb": "Qui no en passa no en conta.",
1162
+ "themes": [
1163
+ "experiència",
1164
+ "comprensió",
1165
+ "empatia"
1166
+ ],
1167
+ "sentiment": "comprensió",
1168
+ "explanation": "Indica que només qui ha passat per una determinada experiència pot entendre realment les seves dificultats.",
1169
+ "usage": "S'utilitza per mostrar comprensió envers algú que no entén una situació si no l'ha viscuda."
1170
+ },
1171
+ {
1172
+ "proverb": "Qui no menja davant de vós, menja per dos.",
1173
+ "themes": [
1174
+ "generositat",
1175
+ "regals",
1176
+ "ingratitud"
1177
+ ],
1178
+ "sentiment": "ironia",
1179
+ "explanation": "Fa referència a aquells que mengen el que no els pertany o aprofiten oportunitats sense agrair-les.",
1180
+ "usage": "S'utilitza per criticar aquells que aprofiten els altres sense donar res a canvi."
1181
+ },
1182
+ {
1183
+ "proverb": "Qui no plora no mama.",
1184
+ "themes": [
1185
+ "necessitats",
1186
+ "esforç",
1187
+ "iniciativa"
1188
+ ],
1189
+ "sentiment": "realista",
1190
+ "explanation": "Vol dir que si no es demana el que es vol o es necessita, no s'obté res.",
1191
+ "usage": "S'utilitza per dir que cal demanar o lluitar per aconseguir el que es vol."
1192
+ },
1193
+ {
1194
+ "proverb": "Qui no pot segar, espigola.",
1195
+ "themes": [
1196
+ "adaptació",
1197
+ "capacitats",
1198
+ "futur"
1199
+ ],
1200
+ "sentiment": "pragmatisme",
1201
+ "explanation": "Fa referència a qui no pot fer una cosa gran, però s'adapta i fa el millor possible.",
1202
+ "usage": "S'utilitza per animar a buscar solucions adaptades a les pròpies capacitats."
1203
+ },
1204
+ {
1205
+ "proverb": "Qui no s'arrisca, no pisca.",
1206
+ "themes": [
1207
+ "coratge",
1208
+ "iniciativa",
1209
+ "resultat"
1210
+ ],
1211
+ "sentiment": "motivació",
1212
+ "explanation": "Indica que qui no es pren riscos no aconseguirà resultats significatius.",
1213
+ "usage": "S'utilitza per encoratjar a prendre riscos o decisions valentes."
1214
+ },
1215
+ {
1216
+ "proverb": "Qui no té cap, ha de tenir cames.",
1217
+ "themes": [
1218
+ "responsabilitat",
1219
+ "solucions",
1220
+ "adaptació"
1221
+ ],
1222
+ "sentiment": "pragmatisme",
1223
+ "explanation": "Diu que si no tens un recurs, has de trobar una altra manera de solucionar el problema.",
1224
+ "usage": "S'utilitza per suggerir que, si no tens una opció, has de buscar una alternativa."
1225
+ },
1226
+ {
1227
+ "proverb": "Qui no té feina, el gat pentina.",
1228
+ "themes": [
1229
+ "ocupació",
1230
+ "procrastinació",
1231
+ "oci"
1232
+ ],
1233
+ "sentiment": "ironia",
1234
+ "explanation": "Fa referència a qui no té res a fer i es dedica a tasques innecessàries o absurdament petites.",
1235
+ "usage": "S'utilitza per referir-se a aquells que es dediquen a feines sense importància per manca d'activitat."
1236
+ },
1237
+ {
1238
+ "proverb": "Qui no té un all, té una ceba.",
1239
+ "themes": [
1240
+ "alternatives",
1241
+ "recursos",
1242
+ "vida quotidiana"
1243
+ ],
1244
+ "sentiment": "humilitat",
1245
+ "explanation": "Indica que sempre hi ha solucions alternatives, encara que no siguin exactament el que es volia.",
1246
+ "usage": "S'utilitza per dir que encara que no es tingui el que es vol, sempre es pot fer servir una altra cosa."
1247
+ },
1248
+ {
1249
+ "proverb": "Qui oli remena, els dits se n'unta.",
1250
+ "themes": [
1251
+ "responsabilitat",
1252
+ "conseqüències",
1253
+ "accions"
1254
+ ],
1255
+ "sentiment": "advertència",
1256
+ "explanation": "Fes referència a que les accions d'un mateix comporten conseqüències, sovint inesperades.",
1257
+ "usage": "S'utilitza per recordar que quan t'implicaries en alguna cosa, les conseqüències et poden afectar."
1258
+ },
1259
+ {
1260
+ "proverb": "Qui paga, mana.",
1261
+ "themes": [
1262
+ "poder",
1263
+ "diners",
1264
+ "autoritat"
1265
+ ],
1266
+ "sentiment": "pragmatisme",
1267
+ "explanation": "Indica que qui té els recursos o el control econòmic té poder per influir en les decisions.",
1268
+ "usage": "S'utilitza per descriure com el poder econòmic pot determinar qui té l'autoritat en una situació."
1269
+ },
1270
+ {
1271
+ "proverb": "Qui tot ho vol, tot ho perd.",
1272
+ "themes": [
1273
+ "desig",
1274
+ "conseqüències",
1275
+ "modestia"
1276
+ ],
1277
+ "sentiment": "consell",
1278
+ "explanation": "Diu que voler-ho tot pot portar a perdre-ho tot.",
1279
+ "usage": "S'utilitza per advertir que cal ser conscient dels límits i no desitjar més del que es pot obtenir."
1280
+ },
1281
+ {
1282
+ "proverb": "Qui té boca s'equivoca.",
1283
+ "themes": [
1284
+ "errores",
1285
+ "imperfecció",
1286
+ "humilitat"
1287
+ ],
1288
+ "sentiment": "comprensió",
1289
+ "explanation": "Vol dir que tothom pot equivocar-se, ja que no existeix ningú perfecte.",
1290
+ "usage": "S'utilitza per mostrar comprensió quan algú comet un error verbal o en opinió."
1291
+ },
1292
+ {
1293
+ "proverb": "Qui té cua de palla, s'encén.",
1294
+ "themes": [
1295
+ "culpabilitat",
1296
+ "sospita",
1297
+ "consciència"
1298
+ ],
1299
+ "sentiment": "crítica",
1300
+ "explanation": "Fes referència a qui té un passat o accions sospitoses que el fan vulnerables a la crítica o la desconfiança.",
1301
+ "usage": "S'utilitza per indicar que aquells que tenen secrets o culpabilitat s'exposen a la sospita."
1302
+ },
1303
+ {
1304
+ "proverb": "Qui té el cul llogat no seu quan vol.",
1305
+ "themes": [
1306
+ "responsabilitat",
1307
+ "llibertat",
1308
+ "compromís"
1309
+ ],
1310
+ "sentiment": "realista",
1311
+ "explanation": "Fes referència a la falta de llibertat d'acció per aquells que tenen compromisos o deutes.",
1312
+ "usage": "S'utilitza per dir que qui té deures o responsabilitats no pot fer el que vol tot el temps."
1313
+ },
1314
+ {
1315
+ "proverb": "Qui té gana somia pa.",
1316
+ "themes": [
1317
+ "desig",
1318
+ "necessitats",
1319
+ "esperança"
1320
+ ],
1321
+ "sentiment": "nostàlgia",
1322
+ "explanation": "Indica que aquells que tenen necessitats somien amb resoldre-les.",
1323
+ "usage": "S'utilitza per dir que qui està mancat d'una cosa desitjada tendeix a pensar-hi constantment."
1324
+ },
1325
+ {
1326
+ "proverb": "Qui va amb un coix, al cap de l'any ho són tots dos.",
1327
+ "themes": [
1328
+ "influència",
1329
+ "relacions",
1330
+ "adaptació"
1331
+ ],
1332
+ "sentiment": "advertència",
1333
+ "explanation": "Fes referència a la influència de l'entorn, que pot afectar la persona que està al voltant d'algú amb alguna característica o comportament.",
1334
+ "usage": "S'utilitza per advertir que l'entorn pot influir negativament en una persona que se sent còmoda amb ell."
1335
+ },
1336
+ {
1337
+ "proverb": "Qui vol bé et farà plorar i qui et vol mal et farà riure.",
1338
+ "themes": [
1339
+ "relacions",
1340
+ "amor",
1341
+ "interessos"
1342
+ ],
1343
+ "sentiment": "ironia",
1344
+ "explanation": "Indica que a vegades les accions de les persones properes poden tenir efectes inesperats, a vegades dolorosos, altre cops humorístics.",
1345
+ "usage": "S'utilitza per reflexionar sobre com les relacions poden ser complexes i no sempre transparents."
1346
+ },
1347
+ {
1348
+ "proverb": "Qui vol lluir ha de patir.",
1349
+ "themes": [
1350
+ "esforç",
1351
+ "resultats",
1352
+ "aparences"
1353
+ ],
1354
+ "sentiment": "motivació",
1355
+ "explanation": "Vol dir que aquells que volen aconseguir èxit o reconeixement han de passar per dificultats o sacrificis.",
1356
+ "usage": "S'utilitza per dir que el camí cap a l'èxit no és fàcil i requereix esforç."
1357
+ },
1358
+ {
1359
+ "proverb": "Qui vulgui peix que es mulli el cul.",
1360
+ "themes": [
1361
+ "esforç",
1362
+ "acció",
1363
+ "resultats"
1364
+ ],
1365
+ "sentiment": "pragmatisme",
1366
+ "explanation": "Indica que per aconseguir el que es vol, cal actuar i afrontar les dificultats.",
1367
+ "usage": "S'utilitza per suggerir que per aconseguir alguna cosa s'ha de prendre la iniciativa i superar els obstacles."
1368
+ },
1369
+ {
1370
+ "proverb": "Què sap el gat de fer culleres?.",
1371
+ "themes": [
1372
+ "incapacitat",
1373
+ "ignorància",
1374
+ "sorpresa"
1375
+ ],
1376
+ "sentiment": "irònic",
1377
+ "explanation": "Descriu la falta d'habilitat o coneixement d'algú sobre un tema.",
1378
+ "usage": "S'utilitza per fer burla de la ignorància d'algú en un camp específic."
1379
+ },
1380
+ {
1381
+ "proverb": "S'atrapa abans un mentider que un coix.",
1382
+ "themes": [
1383
+ "mentides",
1384
+ "veritat",
1385
+ "engany"
1386
+ ],
1387
+ "sentiment": "desconfiança",
1388
+ "explanation": "Vol dir que és més fàcil agafar algú que menteix que algú que no pot fer el que promet.",
1389
+ "usage": "S'utilitza per ressaltar la facilitat amb què es poden detectar les mentides."
1390
+ },
1391
+ {
1392
+ "proverb": "S'ha acabat el bròquil.",
1393
+ "themes": [
1394
+ "final",
1395
+ "conclusió",
1396
+ "desistència"
1397
+ ],
1398
+ "sentiment": "frustració",
1399
+ "explanation": "Indica que una situació ha arribat al seu fi, sovint de manera definitiva.",
1400
+ "usage": "S'utilitza per expressar que una situació s'ha acabat o que una oportunitat s'ha perdut."
1401
+ },
1402
+ {
1403
+ "proverb": "Sempre han tingut bec les oques.",
1404
+ "themes": [
1405
+ "tradició",
1406
+ "costums",
1407
+ "experiència"
1408
+ ],
1409
+ "sentiment": "nostàlgia",
1410
+ "explanation": "Vol dir que les coses que es fan habitualment han estat sempre així.",
1411
+ "usage": "S'utilitza per fer referència a tradicions o pràctiques que han estat presents durant molt de temps."
1412
+ },
1413
+ {
1414
+ "proverb": "Sempre plou sobre mullat.",
1415
+ "themes": [
1416
+ "dificultats",
1417
+ "desafiaments",
1418
+ "complicacions"
1419
+ ],
1420
+ "sentiment": "desesperança",
1421
+ "explanation": "Expressa que quan una situació ja és difícil, sembla que sempre apareixen més problemes.",
1422
+ "usage": "S'utilitza per referir-se a una situació que es complica encara més després d'haver-se enfrontat a dificultats."
1423
+ },
1424
+ {
1425
+ "proverb": "Si ets al ball, has de ballar.",
1426
+ "themes": [
1427
+ "adaptació",
1428
+ "situació",
1429
+ "responsabilitat"
1430
+ ],
1431
+ "sentiment": "acceptació",
1432
+ "explanation": "Indica que si t'has implicat en alguna situació, cal afrontar-la i fer-te'n responsable.",
1433
+ "usage": "S'utilitza per dir que un cop estàs en una situació, cal afrontar-la sense queixar-se."
1434
+ },
1435
+ {
1436
+ "proverb": "Si no vols pols, no vagis a l'era.",
1437
+ "themes": [
1438
+ "evitar problemes",
1439
+ "precaució",
1440
+ "responsabilitat"
1441
+ ],
1442
+ "sentiment": "consell",
1443
+ "explanation": "Vol dir que si no vols afrontar dificultats, no t'hi impliquis des d'un principi.",
1444
+ "usage": "S'utilitza per dir que si no vols enfrontar-te a un problema, millor que no t'hi involucris."
1445
+ },
1446
+ {
1447
+ "proverb": "Si veus una aranya, fot-li castanya.",
1448
+ "themes": [
1449
+ "acció",
1450
+ "immediatesa",
1451
+ "resposta"
1452
+ ],
1453
+ "sentiment": "determinat",
1454
+ "explanation": "Diu que quan et trobes amb un problema, cal actuar de manera decidida i ràpida.",
1455
+ "usage": "S'utilitza per motivar a fer front immediatament a un problema sense dubtar."
1456
+ },
1457
+ {
1458
+ "proverb": "Si vols ben parlar, aprèn de callar.",
1459
+ "themes": [
1460
+ "sabiduría",
1461
+ "comunicació",
1462
+ "prudència"
1463
+ ],
1464
+ "sentiment": "consell",
1465
+ "explanation": "Indica que per ser un bon parlant, cal saber escoltar i saber quan callar.",
1466
+ "usage": "S'utilitza per fer entendre que la comunicació efectiva requereix saber callar quan és necessari."
1467
+ },
1468
+ {
1469
+ "proverb": "Si vols estar ben servit, fes-te tu mateix el llit.",
1470
+ "themes": [
1471
+ "independència",
1472
+ "autonomia",
1473
+ "esforç"
1474
+ ],
1475
+ "sentiment": "motivació",
1476
+ "explanation": "Expressa que per aconseguir els millors resultats, cal prendre la iniciativa i responsabilitzar-se de les pròpies tasques.",
1477
+ "usage": "S'utilitza per animar a ser independent i no dependre dels altres."
1478
+ },
1479
+ {
1480
+ "proverb": "Si vols saber, pregunta.",
1481
+ "themes": [
1482
+ "curiositat",
1483
+ "coneixement",
1484
+ "aprenentatge"
1485
+ ],
1486
+ "sentiment": "invitació",
1487
+ "explanation": "Suggerix que la millor manera d'aprendre és preguntar quan no es té la informació.",
1488
+ "usage": "S'utilitza per fomentar la curiositat i l'aprenentatge actiu."
1489
+ },
1490
+ {
1491
+ "proverb": "Tal dia farà l'any.",
1492
+ "themes": [
1493
+ "temps",
1494
+ "record",
1495
+ "període"
1496
+ ],
1497
+ "sentiment": "nostàlgia",
1498
+ "explanation": "Expressa que un any després, la situació tornarà o es recordarà.",
1499
+ "usage": "S'utilitza per dir que el temps passarà i es recordarà aquell moment o es reviurà."
1500
+ },
1501
+ {
1502
+ "proverb": "Tal faràs, tal trobaràs.",
1503
+ "themes": [
1504
+ "acció",
1505
+ "resultat",
1506
+ "causa-efecte"
1507
+ ],
1508
+ "sentiment": "advertència",
1509
+ "explanation": "Indica que els resultats d'una acció depenen directament de com es faci aquella acció.",
1510
+ "usage": "S’utilitza per advertir que el que es fa tindrà una reacció proporcional."
1511
+ },
1512
+ {
1513
+ "proverb": "Tal mesura com fareu us serà feta.",
1514
+ "themes": [
1515
+ "acció",
1516
+ "conseqüències",
1517
+ "justícia"
1518
+ ],
1519
+ "sentiment": "injustícia",
1520
+ "explanation": "Vol dir que el tractament que donis als altres serà el que rebràs.",
1521
+ "usage": "S'utilitza per indicar que el que fas als altres t'arribarà a tu."
1522
+ },
1523
+ {
1524
+ "proverb": "Tant te vull, que et trac un ull.",
1525
+ "themes": [
1526
+ "relacions",
1527
+ "sacrifici",
1528
+ "desig"
1529
+ ],
1530
+ "sentiment": "ironia",
1531
+ "explanation": "Vol dir que el desig o l'amor per algú pot portar a fer sacrificis, a vegades excessius o irracionals.",
1532
+ "usage": "S'utilitza per expressar un amor o una estima exagerada o fins i tot una acció impulsiva."
1533
+ },
1534
+ {
1535
+ "proverb": "Tanta roba i tan poc sabó!",
1536
+ "themes": [
1537
+ "aparences",
1538
+ "eficàcia",
1539
+ "pragmatisme"
1540
+ ],
1541
+ "sentiment": "crítica",
1542
+ "explanation": "Fa referència a una situació en què hi ha molt de material o recurs però poc rendiment o eficàcia.",
1543
+ "usage": "S'utilitza per descriure una situació en què les expectatives són grans però els resultats són minúsculs."
1544
+ },
1545
+ {
1546
+ "proverb": "Tants caps, tants barrets.",
1547
+ "themes": [
1548
+ "diversitat",
1549
+ "opinions",
1550
+ "opinió pública"
1551
+ ],
1552
+ "sentiment": "acceptació",
1553
+ "explanation": "Vol dir que hi ha tantes opinions o punts de vista com persones, i cadascú té la seva manera de pensar.",
1554
+ "usage": "S'utilitza per expressar la idea que no hi ha una sola manera de veure les coses, sinó moltes."
1555
+ },
1556
+ {
1557
+ "proverb": "Tota pedra fa paret.",
1558
+ "themes": [
1559
+ "petits esforços",
1560
+ "construcció",
1561
+ "persistència"
1562
+ ],
1563
+ "sentiment": "motivació",
1564
+ "explanation": "Vol dir que amb petites aportacions o esforços, es poden aconseguir grans resultats a llarg termini.",
1565
+ "usage": "S'utilitza per animar a continuar amb petites tasques que, a la llarga, sumaran molt."
1566
+ },
1567
+ {
1568
+ "proverb": "Tots els camins van a Roma.",
1569
+ "themes": [
1570
+ "alternatives",
1571
+ "objectius",
1572
+ "camí"
1573
+ ],
1574
+ "sentiment": "optimisme",
1575
+ "explanation": "Expressa la idea que hi ha moltes maneres d'arribar a un mateix objectiu, i totes són vàlides.",
1576
+ "usage": "S'utilitza per tranquil·litzar algú, mostrant-li que no importa el camí que esculli per arribar a un fi."
1577
+ },
1578
+ {
1579
+ "proverb": "Un mal no ve tot sol.",
1580
+ "themes": [
1581
+ "desafiaments",
1582
+ "problemes",
1583
+ "dificultats"
1584
+ ],
1585
+ "sentiment": "desesperança",
1586
+ "explanation": "Indica que un problema sol portar-ne altres després.",
1587
+ "usage": "S'utilitza per expressar la idea que les dificultats tendeixen a aparèixer en grup."
1588
+ },
1589
+ {
1590
+ "proverb": "Una flor no fa estiu, ni dues primavera.",
1591
+ "themes": [
1592
+ "temps",
1593
+ "realitat",
1594
+ "expectatives"
1595
+ ],
1596
+ "sentiment": "prudència",
1597
+ "explanation": "Indica que una sola acció o esdeveniment no és suficient per establir una tendència o resultat durador.",
1598
+ "usage": "S'utilitza per avisar que no cal fer conclusions precipitadament a partir d'un únic esdeveniment."
1599
+ },
1600
+ {
1601
+ "proverb": "Una gota fa vessar un got.",
1602
+ "themes": [
1603
+ "mides",
1604
+ "desbordament",
1605
+ "límits"
1606
+ ],
1607
+ "sentiment": "frustració",
1608
+ "explanation": "Vol dir que un petit detall o una petita acció pot ser l'últim en provocar una reacció gran.",
1609
+ "usage": "S'utilitza per mostrar com el mínim en excés pot causar una situació insostenible."
1610
+ },
1611
+ {
1612
+ "proverb": "Uns tenen la fama i altres carden la llana.",
1613
+ "themes": [
1614
+ "reconeixement",
1615
+ "justícia",
1616
+ "injustícia"
1617
+ ],
1618
+ "sentiment": "ironia",
1619
+ "explanation": "Vol dir que algú rep el reconeixement pels èxits dels altres, o que els qui treballen no sempre són reconeguts.",
1620
+ "usage": "S'utilitza per criticar la falta de reconeixement a qui realment fa el treball dur."
1621
+ },
1622
+ {
1623
+ "proverb": "Val més anar sol que mal acompanyat.",
1624
+ "themes": [
1625
+ "relacions",
1626
+ "companyia",
1627
+ "independència"
1628
+ ],
1629
+ "sentiment": "consell",
1630
+ "explanation": "Diu que és millor estar sol que estar mal acompanyat, com a manera de preservar la qualitat de les relacions.",
1631
+ "usage": "S'utilitza per suggerir que la qualitat de les companyies és més important que la quantitat."
1632
+ },
1633
+ {
1634
+ "proverb": "Val més boig conegut que savi per conèixer.",
1635
+ "themes": [
1636
+ "incertesa",
1637
+ "relacions",
1638
+ "desconfiança"
1639
+ ],
1640
+ "sentiment": "prudència",
1641
+ "explanation": "Diu que és millor mantenir-se amb el que ja es coneix, encara que no sigui ideal, que arriscar-se amb el desconegut.",
1642
+ "usage": "S'utilitza per argumentar que les coses familiars, per dolentes que siguin, poden semblar més segures que les noves."
1643
+ },
1644
+ {
1645
+ "proverb": "Val més caure amb gràcia que ser graciós.",
1646
+ "themes": [
1647
+ "aparences",
1648
+ "distingir-se",
1649
+ "impressió"
1650
+ ],
1651
+ "sentiment": "reflexió",
1652
+ "explanation": "Vol dir que és millor ser autèntic en els teus actes, fins i tot si no són perfectes, que intentar ser simpàtic de manera artificial.",
1653
+ "usage": "S'utilitza per dir que és millor ser un mateix i actuar amb naturalitat."
1654
+ }
1655
+ ]
requirements.txt CHANGED
@@ -1 +1,6 @@
1
- huggingface_hub==0.25.2
 
 
 
 
 
 
1
+ transformers
2
+ torch
3
+ faiss-cpu
4
+ numpy
5
+ gradio
6
+ colorlog
src/commons.py ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import src.datasets
2
+ import src.models as models
3
+ import src.indexes as indexes
4
+ import numpy as np
5
+
6
+
7
+ def load_or_create_index(tokenizer: models.Tokenizer, model: models.Model, dataset: list[dict]) -> indexes.Index:
8
+ """Load an existing index or create a new one with default values if it doesn't exist."""
9
+ if indexes.index_exists():
10
+ # Load existing index
11
+ index = indexes.load_index()
12
+ else:
13
+ # Create a new index with default values
14
+ embeddings = embed_dataset(dataset, tokenizer, model)
15
+ index = indexes.create_index(embeddings)
16
+ return index
17
+
18
+
19
+ def embed_dataset(
20
+ dataset: list[dict],
21
+ tokenizer: models.Tokenizer,
22
+ model: models.Model,
23
+ map: callable = None,
24
+ pooling_method: str = models.DEFAULT_POOLING_METHOD
25
+ ) -> np.ndarray:
26
+ """Create a FAISS index from the given dataset."""
27
+ texts = datasets.build_text_representations(dataset, map)
28
+ embeddings = models.embed_texts(texts, tokenizer, model, pooling_method)
29
+ return embeddings
30
+
31
+
32
+ def inference(
33
+ inputs: list[str],
34
+ index,
35
+ tokenizer: models.Tokenizer,
36
+ model: models.Model,
37
+ dataset: list[dict],
38
+ pooling_method: str = models.DEFAULT_POOLING_METHOD,
39
+ k: int = 1
40
+ ) -> list[dict]:
41
+ """Perform inference on the input text and return top matches from the index."""
42
+ embeddings = models.embed_texts(inputs, tokenizer, model, pooling_method)
43
+ distances, indices = indexes.find_closest(embeddings, index, k=k)
44
+ return build_inference_results(inputs, embeddings, dataset, distances, indices)
45
+
46
+
47
+ def build_inference_results(inputs: list[str], embeddings: np.ndarray, dataset: list[dict], distances: np.ndarray, indices: np.ndarray) -> list[dict]:
48
+ """Build the inference results from the distances and indices."""
49
+ results = []
50
+ for i in range(len(distances)):
51
+ indices_list = [idx for idx in indices[i]]
52
+
53
+ # Create a list of matches with distances and proverbs
54
+ matches = {
55
+ "input": inputs[i],
56
+ "embedding": embeddings[i],
57
+ "matches": [
58
+ {
59
+ "rank": j + 1,
60
+ "proverb": dataset[indices_list[j]]["proverb"],
61
+ "distance": float(distances[i][j])
62
+ }
63
+ for j in range(len(indices_list))
64
+ ]
65
+ }
66
+ results.append(matches)
67
+ return results
src/customlogger.py ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ import logging
3
+ import time
4
+ import colorlog
5
+
6
+ # A module is only ever loaded once, so we can set up the logger here
7
+ logger = logging.getLogger("custom")
8
+
9
+ # Set the default logging level once at the module level
10
+ TRACE = 5
11
+ logger.setLevel(TRACE)
12
+
13
+
14
+ def trace(self, message, *args, **kwargs):
15
+ """Log a message with severity TRACE."""
16
+ if self.isEnabledFor(TRACE):
17
+ self._log(TRACE, message, args, **kwargs)
18
+
19
+
20
+ def setup_logger():
21
+ """Set up the logger with a custom format and color scheme."""
22
+ # Set the log record to include padding for the origin
23
+ old_factory = logging.getLogRecordFactory()
24
+
25
+ def record_factory(*args, **kwargs):
26
+ record = old_factory(*args, **kwargs)
27
+ record.origin = f'{record.filename}:{record.lineno}'
28
+ return record
29
+ logging.setLogRecordFactory(record_factory)
30
+
31
+ # Create a new log level
32
+ logging.Logger.trace = trace
33
+ logging.addLevelName(TRACE, "TRACE")
34
+
35
+ # Set formatting for the custom logger
36
+ fmt = colorlog.ColoredFormatter(
37
+ "%(asctime)s | %(log_color)s%(levelname)-5s%(reset)s | %(blue)s%(origin)-20s%(reset)s | %(log_color)s%(message)s%(reset)s",
38
+ datefmt="%H:%M:%S",
39
+ log_colors={
40
+ 'TRACE': 'yellow',
41
+ 'DEBUG': 'white',
42
+ 'INFO': 'green',
43
+ 'WARNING': 'yellow',
44
+ 'ERROR': 'red',
45
+ }
46
+ )
47
+
48
+ stdout = colorlog.StreamHandler(stream=sys.stdout)
49
+ stdout.setFormatter(fmt)
50
+ logger.addHandler(stdout)
51
+
52
+ # Disable the default logging handler
53
+ logger.propagate = False
54
+
55
+
56
+ def log_time(func):
57
+ """Decorator to log the time taken by a function."""
58
+ def wrapper(*args, **kwargs):
59
+ start = time.time()
60
+ result = func(*args, **kwargs)
61
+ logger.trace(
62
+ f"{func.__name__} completed in {time.time() - start:.2f} seconds")
63
+ return result
64
+ return wrapper
65
+
66
+
67
+ # Actually set up the logger for all modules that import this one
68
+ setup_logger()
src/datasets.py ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+ import random
4
+ import re
5
+ from src.customlogger import log_time, logger
6
+
7
+ PROVERBS_FILE = os.path.join("datasets", "proverbs.json")
8
+ PROMPTS_FILE = os.path.join("datasets", "prompts.json")
9
+ PROMPTS_TRAIN_FILE = os.path.join("datasets", "prompts_train.json")
10
+ PROMPTS_TEST_FILE = os.path.join("datasets", "prompts_test.json")
11
+ PROVERB_FIELDS = ["proverb", "themes", "sentiment", "explanation", "usage"]
12
+
13
+
14
+ @log_time
15
+ def load_proverbs(proverbs_file: str = PROVERBS_FILE) -> list[dict]:
16
+ logger.debug(f"Loading proverb dataset from '{proverbs_file}'...")
17
+ proverbs = load_dataset(proverbs_file)
18
+ logger.debug(f"Loaded {len(proverbs)} proverb entries")
19
+ return proverbs
20
+
21
+
22
+ @log_time
23
+ def load_prompts(prompts_file: str = PROMPTS_FILE) -> list[dict]:
24
+ logger.debug(f"Loading prompts dataset from '{prompts_file}'...")
25
+ prompts = load_dataset(prompts_file)
26
+ logger.debug(f"Loaded {len(prompts)} prompt entries")
27
+ return prompts
28
+
29
+
30
+ def load_dataset(file):
31
+ with open(file, "r", encoding="utf-8") as f:
32
+ data = json.load(f)
33
+ return data
34
+
35
+
36
+ def default_proverb_fields_selection(proverb):
37
+ """Select fields from the proverb for text representation (proverb, sentiment, usage)."""
38
+ return [proverb["proverb"]] + proverb["themes"]
39
+
40
+
41
+ @log_time
42
+ def build_text_representations(proverbs: list[dict], map: callable = None) -> list[str]:
43
+ if not map:
44
+ map = default_proverb_fields_selection
45
+
46
+ """Build text representations of proverbs for embedding."""
47
+ # Remove duplicate periods (some fields already have them)
48
+ text_representations = [
49
+ re.sub(r"\.+", ".", ". ".join(map(proverb))) for proverb in proverbs]
50
+
51
+ return text_representations
52
+
53
+
54
+ def prompts_dataset_splits_exists(train_file: str = PROMPTS_TRAIN_FILE, test_file: str = PROMPTS_TEST_FILE) -> bool:
55
+ """Check if the prompt dataset splits exist."""
56
+ return os.path.exists(train_file) and os.path.exists(test_file)
57
+
58
+
59
+ @log_time
60
+ def load_prompt_dataset_splits(train_file: str = PROMPTS_TRAIN_FILE, test_file: str = PROMPTS_TEST_FILE) -> tuple[list[dict], list[dict]]:
61
+ """Load the prompt dataset splits."""
62
+ with open(train_file, "r", encoding="utf-8") as f:
63
+ train_set = json.load(f)
64
+
65
+ with open(test_file, "r", encoding="utf-8") as f:
66
+ test_set = json.load(f)
67
+
68
+ return train_set, test_set
69
+
70
+
71
+ @log_time
72
+ def split_dataset(dataset: list[dict], train_ratio: float = 0, seed: int = 42,
73
+ train_file: str = PROMPTS_TRAIN_FILE, test_file: str = PROMPTS_TEST_FILE) -> tuple[list[dict], list[dict]]:
74
+ """Split a dataset into train and test sets and save them to JSON files.
75
+
76
+ Args:
77
+ dataset (list[dict]): The dataset to split.
78
+ train_ratio (float): The ratio of the dataset to use for training.
79
+ seed (int): The random seed for reproducibility.
80
+ train_file (str): Path to save the training dataset.
81
+ test_file (str): Path to save the testing dataset.
82
+ """
83
+ logger.debug(
84
+ f"Splitting dataset into train and test with train_ratio={train_ratio}, seed={seed}")
85
+ random.seed(seed)
86
+ # Copy the dataset to avoid modifying the original
87
+ # (it's okay since it's a small dataset)
88
+ dataset = dataset.copy()
89
+ random.shuffle(dataset)
90
+
91
+ split_index = int(len(dataset) * train_ratio)
92
+ train_set = dataset[:split_index]
93
+ test_set = dataset[split_index:]
94
+
95
+ logger.debug(
96
+ f"Train set size: {len(train_set)}, Test set size: {len(test_set)}")
97
+
98
+ with open(train_file, "w", encoding="utf-8") as f:
99
+ json.dump(train_set, f, ensure_ascii=False, indent=2)
100
+
101
+ with open(test_file, "w", encoding="utf-8") as f:
102
+ json.dump(test_set, f, ensure_ascii=False, indent=2)
103
+
104
+ logger.info(f"Train dataset saved to '{train_file}'")
105
+ logger.info(f"Test dataset saved to '{test_file}'")
106
+
107
+ return train_set, test_set
src/indexes.py ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import faiss
3
+ import numpy as np
4
+ from src.customlogger import log_time, logger
5
+
6
+ # Type alias to decouple from FAISS
7
+ Index = faiss.IndexFlat
8
+
9
+ INDEX_FILE = "proverbs.index"
10
+
11
+ # This were the index types tested
12
+ INDEX_TYPES = [faiss.IndexFlatL2, faiss.IndexFlatIP]
13
+ # This is the pooling method used in the final iteration
14
+ DEFAULT_INDEX_TYPE = faiss.IndexFlatL2
15
+
16
+
17
+ def index_exists(index_file: str = INDEX_FILE) -> bool:
18
+ """Check if the index file exists."""
19
+ return os.path.exists(index_file)
20
+
21
+
22
+ @log_time
23
+ def create_index(embeddings: np.ndarray, index_type: type = None, index_file: str = INDEX_FILE) -> Index:
24
+ """Create a FAISS index and store the given embeddings."""
25
+ if not index_type:
26
+ index_type = DEFAULT_INDEX_TYPE
27
+
28
+ dimension = embeddings.shape[1]
29
+ logger.debug(
30
+ f"Creating FAISS index with {len(embeddings)} {embeddings.shape[1]}-dimensional embeddings...")
31
+ index = index_type(dimension)
32
+ index.add(embeddings)
33
+ logger.debug(f"Saving FAISS index to '{index_file}'...")
34
+ faiss.write_index(index, index_file)
35
+ return index
36
+
37
+
38
+ @log_time
39
+ def load_index(index_file: str = INDEX_FILE) -> Index:
40
+ """Load the FAISS index from the specified file."""
41
+ logger.debug(f"Loading FAISS index from '{index_file}'...")
42
+ index = faiss.read_index(index_file)
43
+ return index
44
+
45
+
46
+ @log_time
47
+ def find_closest(embeddings, index: Index, k=5) -> tuple[np.ndarray, np.ndarray]:
48
+ """Find the closest k vectors in the index for the given embeddings."""
49
+ logger.debug(
50
+ f"Performing search for the top {k} matches of {len(embeddings)} embedding...")
51
+ distances, indices = index.search(embeddings, k)
52
+ return distances, indices
src/models.py ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import AutoTokenizer, AutoModel
2
+ import torch
3
+ import numpy as np
4
+ from src.customlogger import log_time, logger
5
+
6
+ # Type alias to decouple from transformers
7
+ Tokenizer = AutoTokenizer
8
+ Model = AutoModel
9
+
10
+ # This were the models tested
11
+ MODELS = [
12
+ "projecte-aina/roberta-base-ca-v2",
13
+ "projecte-aina/roberta-base-ca-v2-cased-sts",
14
+ "projecte-aina/roberta-base-ca-v2-cased-te",
15
+ "projecte-aina/roberta-base-ca-v2-cased-tc",
16
+ "projecte-aina/roberta-large-ca-v2"
17
+ ]
18
+ # This is the model used in the final iteration
19
+ DEFAULT_MODEL = "projecte-aina/roberta-base-ca-v2"
20
+
21
+ # This were the pooling methods tested
22
+ POOLING_METHODS = ["mean", "max", "cls"]
23
+ # This is the pooling method used in the final iteration
24
+ DEFAULT_POOLING_METHOD = "cls"
25
+
26
+
27
+ @log_time
28
+ def load_model(model_name: str = DEFAULT_MODEL) -> Model:
29
+ """Load the model for the specified model name."""
30
+ logger.debug(f"Loading model {model_name}...")
31
+ model = AutoModel.from_pretrained(model_name)
32
+ # Set model to evaluation mode
33
+ model.eval()
34
+ return model
35
+
36
+
37
+ @log_time
38
+ def load_tokenizer(model_name: str = DEFAULT_MODEL) -> Tokenizer:
39
+ """Load the tokenizer for the specified model."""
40
+ logger.debug(f"Loading tokenizer {model_name}...")
41
+ tokenizer = AutoTokenizer.from_pretrained(model_name)
42
+ return tokenizer
43
+
44
+
45
+ @log_time
46
+ def embed_texts(texts: list[str], tokenizer: Tokenizer, model: Model, pooling_metod: str = DEFAULT_POOLING_METHOD, batch_size: int = 32) -> np.ndarray:
47
+ """Get sentence embeddings using mean pooling."""
48
+ logger.debug(f"Computing {len(texts)} embeddings...")
49
+ embeddings = []
50
+ # Do not use gradient tracking, as we are only doing inference
51
+ with torch.no_grad():
52
+ for i in range(0, len(texts), batch_size):
53
+ # Tokenize the batch of texts
54
+ batch = texts[i:i+batch_size]
55
+ encoded = tokenizer(batch, padding=True,
56
+ truncation=True, return_tensors="pt")
57
+ # Run the model on the input batch and get the last hidden state
58
+ outputs = model(**encoded)
59
+ last_hidden = outputs.last_hidden_state
60
+ # Recover the attention mask to avoid padding tokens and compute the pooling
61
+ mask = encoded["attention_mask"].unsqueeze(-1)\
62
+ .expand(last_hidden.size()).float()
63
+ # Apply the pooling method
64
+ if pooling_metod == "mean":
65
+ pooled = (last_hidden * mask).sum(1) / mask.sum(1)
66
+ elif pooling_metod == "max":
67
+ pooled = (last_hidden * mask).max(1)[0]
68
+ elif pooling_metod == "cls":
69
+ pooled = last_hidden[:, 0, :]
70
+ else:
71
+ raise ValueError(f"Unknown pooling method: {pooling_metod}")
72
+ # Normalize the pooled embeddings to unit length (L2 norm)
73
+ pooled = torch.nn.functional.normalize(pooled, p=2, dim=1)
74
+ # Append the normalized embeddings to the list
75
+ embeddings.append(pooled.cpu().numpy())
76
+ return np.vstack(embeddings)