emanuelaboros commited on
Commit
6f7496c
·
verified ·
1 Parent(s): 6cae43f

Upload folder using huggingface_hub

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ tokenizer.json filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,259 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ library_name: transformers
3
+ language:
4
+ - multilingual
5
+ - af
6
+ - am
7
+ - ar
8
+ - as
9
+ - az
10
+ - be
11
+ - bg
12
+ - bm
13
+ - bn
14
+ - br
15
+ - bs
16
+ - ca
17
+ - cs
18
+ - cy
19
+ - da
20
+ - de
21
+ - el
22
+ - en
23
+ - eo
24
+ - es
25
+ - et
26
+ - eu
27
+ - fa
28
+ - ff
29
+ - fi
30
+ - fr
31
+ - fy
32
+ - ga
33
+ - gd
34
+ - gl
35
+ - gn
36
+ - gu
37
+ - ha
38
+ - he
39
+ - hi
40
+ - hr
41
+ - ht
42
+ - hu
43
+ - hy
44
+ - id
45
+ - ig
46
+ - is
47
+ - it
48
+ - ja
49
+ - jv
50
+ - ka
51
+ - kg
52
+ - kk
53
+ - km
54
+ - kn
55
+ - ko
56
+ - ku
57
+ - ky
58
+ - la
59
+ - lg
60
+ - ln
61
+ - lo
62
+ - lt
63
+ - lv
64
+ - mg
65
+ - mk
66
+ - ml
67
+ - mn
68
+ - mr
69
+ - ms
70
+ - my
71
+ - ne
72
+ - nl
73
+ - no
74
+ - om
75
+ - or
76
+ - pa
77
+ - pl
78
+ - ps
79
+ - pt
80
+ - qu
81
+ - ro
82
+ - ru
83
+ - sa
84
+ - sd
85
+ - si
86
+ - sk
87
+ - sl
88
+ - so
89
+ - sq
90
+ - sr
91
+ - ss
92
+ - su
93
+ - sv
94
+ - sw
95
+ - ta
96
+ - te
97
+ - th
98
+ - ti
99
+ - tl
100
+ - tn
101
+ - tr
102
+ - uk
103
+ - ur
104
+ - uz
105
+ - vi
106
+ - wo
107
+ - xh
108
+ - yo
109
+ - zh
110
+
111
+ license: agpl-3.0
112
+ tags:
113
+ - v1.0.0
114
+ - entity-disambiguation
115
+ - named-entity-linking
116
+ - entity-linking
117
+ - text2text-generation
118
+ ---
119
+
120
+ # Model Card for `impresso-project/nel-mgenre-multilingual`
121
+
122
+ The **Impresso multilingual named entity linking (NEL)** model is based on **mGENRE** (multilingual Generative ENtity
123
+ REtrieval) proposed by [De Cao et al](https://arxiv.org/abs/2103.12528), a sequence-to-sequence architecture for entity
124
+ disambiguation based on [mBART](https://arxiv.org/abs/2001.08210). It uses **constrained generation** to output entity
125
+ names mapped to Wikidata/QIDs.
126
+
127
+ This model was adapted for historical texts and fine-tuned on
128
+ the [HIPE-2022 dataset](https://github.com/hipe-eval/HIPE-2022-data), which includes a variety of historical document
129
+ types and languages.
130
+
131
+ ## Model Details
132
+
133
+ ### Model Description
134
+
135
+ - **Developed by:** EPFL from the [Impresso team](https://impresso-project.ch). The project is an interdisciplinary
136
+ project focused on historical media analysis across languages, time, and modalities. Funded by the Swiss National
137
+ Science
138
+ Foundation ([CRSII5_173719](http://p3.snf.ch/project-173719), [CRSII5_213585](https://data.snf.ch/grants/grant/213585))
139
+ and the Luxembourg National Research Fund (grant No. 17498891).
140
+ - **Model type:** mBART-based sequence-to-sequence model with constrained beam search for named entity linking
141
+ - **Languages:** Multilingual (100+ languages, optimized for French, German, and English)
142
+ - **License:** [AGPL v3+](https://github.com/impresso/impresso-pyindexation/blob/master/LICENSE)
143
+ - **Finetuned from:** [`facebook/mgenre-wiki`](https://huggingface.co/facebook/mgenre-wiki)
144
+
145
+ ### Model Architecture
146
+
147
+ - **Architecture:** mBART-based seq2seq with constrained beam search
148
+
149
+ ## Training Details
150
+
151
+ ### Training Data
152
+
153
+ The model was trained on the following datasets:
154
+
155
+ | Dataset alias | README | Document type | Languages | Suitable for | Project | License |
156
+ |---------------|--------------------------------------------|------------------------|----------------|----------------------------|-------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------|
157
+ | ajmc | [link](documentation/README-ajmc.md) | classical commentaries | de, fr, en | NERC-Coarse, NERC-Fine, EL | [AjMC](https://mromanello.github.io/ajax-multi-commentary/) | [![License: CC BY 4.0](https://img.shields.io/badge/License-CC_BY_4.0-lightgrey.svg)](https://creativecommons.org/licenses/by/4.0/) |
158
+ | hipe2020 | [link](documentation/README-hipe2020.md) | historical newspapers | de, fr, en | NERC-Coarse, NERC-Fine, EL | [CLEF-HIPE-2020](https://impresso.github.io/CLEF-HIPE-2020) | [![License: CC BY-NC-SA 4.0](https://img.shields.io/badge/License-CC_BY--NC--SA_4.0-lightgrey.svg)](https://creativecommons.org/licenses/by-nc-sa/4.0/) |
159
+ | topres19th | [link](documentation/README-topres19th.md) | historical newspapers | en | NERC-Coarse, EL | [Living with Machines](https://livingwithmachines.ac.uk/) | [![License: CC BY-NC-SA 4.0](https://img.shields.io/badge/License-CC_BY--NC--SA_4.0-lightgrey.svg)](https://creativecommons.org/licenses/by-nc-sa/4.0/) |
160
+ | newseye | [link](documentation/README-newseye.md) | historical newspapers | de, fi, fr, sv | NERC-Coarse, NERC-Fine, EL | [NewsEye](https://www.newseye.eu/) | [![License: CC BY 4.0](https://img.shields.io/badge/License-CC_BY_4.0-lightgrey.svg)](https://creativecommons.org/licenses/by/4.0/) |
161
+ | sonar | [link](documentation/README-sonar.md) | historical newspapers | de | NERC-Coarse, EL | [SoNAR](https://sonar.fh-potsdam.de/) | [![License: CC BY 4.0](https://img.shields.io/badge/License-CC_BY_4.0-lightgrey.svg)](https://creativecommons.org/licenses/by/4.0/) |
162
+
163
+ ## How to Use
164
+
165
+ ```python
166
+ from transformers import AutoTokenizer, pipeline
167
+
168
+ NEL_MODEL_NAME = "impresso-project/nel-mgenre-multilingual"
169
+ nel_tokenizer = AutoTokenizer.from_pretrained(NEL_MODEL_NAME)
170
+
171
+ nel_pipeline = pipeline("generic-nel", model=NEL_MODEL_NAME,
172
+ tokenizer=nel_tokenizer,
173
+ trust_remote_code=True,
174
+ device='cpu')
175
+
176
+ sentence = "Le 0ctobre 1894, [START] Dreyfvs [END] est arrêté à Paris, accusé d'espionnage pour l'Allemagne — un événement qui déch1ra la société fr4nçaise pendant des années."
177
+ print(nel_pipeline(sentence))
178
+ ```
179
+
180
+ ### Output Format
181
+
182
+ ```python
183
+ [
184
+ {
185
+ 'surface': 'Dreyfvs',
186
+ 'wkd_id': 'Q171826',
187
+ 'wkpedia_pagename': 'Alfred Dreyfus',
188
+ 'wkpedia_url': 'https://fr.wikipedia.org/wiki/Alfred_Dreyfus',
189
+ 'type': 'UNK',
190
+ 'confidence_nel': 99.98,
191
+ 'lOffset': 24,
192
+ 'rOffset': 33}]
193
+ ```
194
+
195
+ ----
196
+
197
+ ### Batched predictions
198
+
199
+ ```python
200
+ from transformers import AutoTokenizer, pipeline
201
+
202
+ NEL_MODEL_NAME = "impresso-project/nel-mgenre-multilingual"
203
+
204
+ nel_tokenizer = AutoTokenizer.from_pretrained(NEL_MODEL_NAME)
205
+
206
+ nel_pipeline = pipeline(
207
+ "generic-nel",
208
+ model=NEL_MODEL_NAME,
209
+ tokenizer=nel_tokenizer,
210
+ trust_remote_code=True,
211
+ device="cpu",
212
+ )
213
+
214
+ sentences = [
215
+ "Le 0ctobre 1894, [START] Dreyfvs [END] est arrêté à Paris.",
216
+ "En 1912, [START] Giollitti [END] était encore au pouvoir en Italie.",
217
+ "La ville de [START] Lpzbourg [END] est importante dans la région."
218
+ ]
219
+
220
+ results = nel_pipeline(sentences)
221
+
222
+ from pprint import pprint
223
+ pprint(results)
224
+ ```
225
+
226
+ The type of the entity is `UNK` because the model was not trained on the entity type. The `confidence_nel` score
227
+ indicates the model's confidence in the prediction.
228
+
229
+ ## Use Cases
230
+
231
+ - Entity disambiguation in noisy OCR settings
232
+ - Linking historical names to modern Wikidata entities
233
+ - Assisting downstream event extraction and biography generation from historical archives
234
+
235
+ > 🐱**Easter Egg**:
236
+ > While the pipeline’s main goal is to link surface forms to QIDs and Wikipedia pages,
237
+ > it sometimes slips in an extra surprise: a coarse Wikidata type label (`pers`, `org`, or `loc`).
238
+ > Not strictly required — but a handy little bonus when it shows up!
239
+
240
+ ## Limitations
241
+
242
+ - Sensitive to tokenisation and malformed spans
243
+ - Accuracy degrades on non-Wikidata entities or in highly ambiguous contexts
244
+ - Focused on historical entity mentions — performance may vary on modern texts
245
+
246
+ ## Environmental Impact
247
+
248
+ - **Hardware:** 1x A100 (80GB) for finetuning
249
+ - **Training time:** ~12 hours
250
+ - **Estimated CO₂ Emissions:** ~2.3 kg CO₂eq
251
+
252
+ ## Contact
253
+
254
+ - Website: [https://impresso-project.ch](https://impresso-project.ch)
255
+
256
+ <p align="center">
257
+ <img src="https://github.com/impresso/impresso.github.io/blob/master/assets/images/3x1--Yellow-Impresso-Black-on-White--transparent.png?raw=true" width="300" alt="Impresso Logo"/>
258
+ </p>
259
+
config.json ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_name_or_path": "facebook/mgenre-wiki",
3
+ "activation_dropout": 0.0,
4
+ "activation_function": "gelu",
5
+ "architectures": [
6
+ "MBartForConditionalGeneration"
7
+ ],
8
+ "custom_pipelines": {
9
+ "generic-nel": {
10
+ "impl": "generic_nel.NelPipeline",
11
+ "pt": [
12
+ "MBartForConditionalGeneration"
13
+ ],
14
+ "tf": []
15
+ }
16
+ },
17
+ "attention_dropout": 0.0,
18
+ "bos_token_id": 0,
19
+ "classifier_dropout": 0.0,
20
+ "d_model": 1024,
21
+ "decoder_attention_heads": 16,
22
+ "decoder_ffn_dim": 4096,
23
+ "decoder_layerdrop": 0.0,
24
+ "decoder_layers": 12,
25
+ "decoder_start_token_id": 2,
26
+ "dropout": 0.1,
27
+ "encoder_attention_heads": 16,
28
+ "encoder_ffn_dim": 4096,
29
+ "encoder_layerdrop": 0.0,
30
+ "encoder_layers": 12,
31
+ "eos_token_id": 2,
32
+ "forced_eos_token_id": 2,
33
+ "init_std": 0.02,
34
+ "is_encoder_decoder": true,
35
+ "max_position_embeddings": 1024,
36
+ "model_type": "mbart",
37
+ "num_hidden_layers": 12,
38
+ "pad_token_id": 1,
39
+ "scale_embedding": true,
40
+ "torch_dtype": "float32",
41
+ "transformers_version": "4.31.0",
42
+ "use_cache": true,
43
+ "vocab_size": 256001
44
+ }
generation_config.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "bos_token_id": 0,
3
+ "decoder_start_token_id": 2,
4
+ "eos_token_id": 2,
5
+ "forced_eos_token_id": 2,
6
+ "pad_token_id": 1,
7
+ "transformers_version": "4.46.0.dev0"
8
+ }
generic_nel.py ADDED
@@ -0,0 +1,590 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import Pipeline
2
+ import requests
3
+ import torch
4
+ import time
5
+ import os
6
+ import random
7
+ import logging
8
+ from filelock import FileLock
9
+ import requests_cache
10
+ from requests.adapters import HTTPAdapter
11
+ from urllib3.util.retry import Retry
12
+
13
+ logger = logging.getLogger("nel_wikidata")
14
+
15
+ NEL_MODEL = "nel-mgenre-multilingual"
16
+
17
+ # Required by Wikimedia: identify your app + contact
18
+ HEADERS = {"User-Agent": "NEL-HF-Space/0.1 (contact: emanuela.boros@epfl.ch)"}
19
+
20
+
21
+ def safe_get(url, params, retries=3, backoff=2):
22
+ """
23
+ Perform a safe HTTP GET request with retry logic.
24
+
25
+ This function wraps `requests.get` and automatically retries the request if it fails
26
+ due to common transient errors such as HTTP 403 (forbidden, often due to missing/blocked
27
+ User-Agent headers) or HTTP 429 (rate-limited). Retries use exponential backoff.
28
+
29
+ Args:
30
+ url (str): The target URL for the request.
31
+ params (dict): Query parameters to send with the GET request.
32
+ retries (int, optional): Maximum number of attempts before giving up. Default is 3.
33
+ backoff (int, optional): Base for exponential backoff in seconds. Default is 2.
34
+ - Example: with retries=3 and backoff=2, wait times will be 1s, 2s, 4s.
35
+
36
+ Returns:
37
+ requests.Response or None:
38
+ - A `Response` object if the request eventually succeeds (status=200).
39
+ - `None` if all retries fail or an unrecoverable error occurs.
40
+
41
+ Notes:
42
+ - Adds `HEADERS` to all requests, which should include a descriptive User-Agent
43
+ as required by Wikimedia APIs.
44
+ - Raises no exceptions; instead prints errors and returns None if the request
45
+ cannot be completed successfully.
46
+ """
47
+ for attempt in range(retries):
48
+ try:
49
+ resp = requests.get(url, params=params, headers=HEADERS, timeout=10)
50
+ if resp.status_code == 200:
51
+ return resp
52
+ elif resp.status_code in (403, 429): # forbidden or rate limited
53
+ wait = backoff**attempt
54
+ print(f"Retrying {url} in {wait}s (status={resp.status_code})")
55
+ time.sleep(wait)
56
+ continue
57
+ else:
58
+ resp.raise_for_status()
59
+ except Exception as e:
60
+ print(f"Request error: {e}")
61
+ time.sleep(backoff**attempt)
62
+ return None
63
+
64
+
65
+ # ---- Persistent cache (shared on disk across processes) ----
66
+ # 30 days is fine for QID/title/type lookups
67
+ requests_cache.install_cache(
68
+ cache_name=os.getenv("WIKIMEDIA_CACHE", "wikimedia_cache"),
69
+ backend="sqlite",
70
+ expire_after=int(os.getenv("WIKIMEDIA_CACHE_TTL", str(60 * 60 * 24 * 30))),
71
+ allowable_methods=("GET",),
72
+ )
73
+
74
+ # ---- One Session per process (connection pooling + retries) ----
75
+ _session = requests.Session()
76
+ _session.headers.update(HEADERS)
77
+
78
+ _retry = Retry(
79
+ total=int(os.getenv("WIKIMEDIA_RETRIES", "5")),
80
+ connect=int(os.getenv("WIKIMEDIA_RETRIES", "5")),
81
+ read=int(os.getenv("WIKIMEDIA_RETRIES", "5")),
82
+ backoff_factor=float(os.getenv("WIKIMEDIA_BACKOFF", "1.5")),
83
+ status_forcelist=(429, 500, 502, 503, 504),
84
+ allowed_methods=frozenset(["GET"]),
85
+ respect_retry_after_header=False, # <-- IMPORTANT
86
+ raise_on_status=False,
87
+ )
88
+
89
+ _adapter = HTTPAdapter(max_retries=_retry, pool_connections=50, pool_maxsize=50)
90
+ _session.mount("https://", _adapter)
91
+ _session.mount("http://", _adapter)
92
+
93
+ # ---- Cross-process rate limit (global QPS across all workers on this machine) ----
94
+ # Choose a conservative QPS; Wikimedia is happier with low QPS.
95
+ WIKIMEDIA_QPS = float(os.getenv("WIKIMEDIA_QPS", "3.0")) # total across ALL processes
96
+ _MIN_INTERVAL = 1.0 / max(WIKIMEDIA_QPS, 0.1)
97
+
98
+ _LOCK = FileLock(os.getenv("WIKIMEDIA_RATELOCK", "/tmp/wikimedia_rate.lock"))
99
+ _TS_FILE = os.getenv("WIKIMEDIA_RATETS", "/tmp/wikimedia_rate.ts")
100
+
101
+
102
+ def _throttle_global():
103
+ """Global rate limiter shared across processes via file lock + timestamp."""
104
+ with _LOCK:
105
+ now = time.time()
106
+ last = 0.0
107
+ try:
108
+ with open(_TS_FILE, "r") as f:
109
+ last = float(f.read().strip() or "0")
110
+ except FileNotFoundError:
111
+ last = 0.0
112
+
113
+ wait = (last + _MIN_INTERVAL) - now
114
+ if wait > 0:
115
+ time.sleep(wait)
116
+
117
+ with open(_TS_FILE, "w") as f:
118
+ f.write(str(time.time()))
119
+
120
+
121
+ def safe_get_old(url, params, timeout=10):
122
+ """
123
+ Cached + globally rate-limited + retrying GET.
124
+ Returns Response or None.
125
+ """
126
+ _throttle_global()
127
+ try:
128
+ resp = _session.get(url, params=params, timeout=timeout)
129
+
130
+ # requests-cache sets this attribute; useful to log
131
+ from_cache = getattr(resp, "from_cache", False)
132
+
133
+ if resp.status_code == 200:
134
+ if from_cache:
135
+ logger.debug(f"[WIKI] 200 (cache) {url} params={_short(params)}")
136
+ return resp
137
+
138
+ if resp.status_code == 429:
139
+ # Even with Retry-After handling, sometimes you still get here.
140
+ ra = resp.headers.get("Retry-After")
141
+ sleep = float(ra) if (ra and ra.isdigit()) else (1.0 + random.random())
142
+ logger.warning(
143
+ f"[WIKI] 429 rate limited. retry-after={ra} sleeping={sleep:.2f}s url={url}"
144
+ )
145
+ time.sleep(sleep)
146
+ return resp # caller may treat as failure; Retry already happened.
147
+
148
+ logger.warning(
149
+ f"[WIKI] HTTP {resp.status_code} url={url} params={_short(params)}"
150
+ )
151
+ return resp
152
+ except Exception as e:
153
+ logger.exception(f"[WIKI] Request error: {e} url={url}")
154
+ return None
155
+
156
+
157
+ def _short(params: dict, maxlen: int = 120) -> str:
158
+ s = str(params)
159
+ return s if len(s) <= maxlen else s[:maxlen] + "..."
160
+
161
+
162
+ def get_wikipedia_page_props(input_str: str):
163
+ """
164
+ Retrieve the Wikidata QID for a given Wikipedia page name.
165
+
166
+ This function attempts to resolve a text prediction (e.g. `"Paris >> fr"`)
167
+ into a Wikidata identifier (`Q90`) and its language code.
168
+
169
+ Resolution happens in two steps:
170
+ 1. Query the specified language Wikipedia API (`prop=pageprops`) to check if
171
+ the page is associated with a `wikibase_item` (QID).
172
+ 2. If that fails, fall back to the Wikidata `wbsearchentities` API, which
173
+ searches for entities matching the page name in the given language.
174
+
175
+ Args:
176
+ input_str (str): A string in the form `"page_name >> language"`.
177
+ - Example: `"Paris >> fr"` → page_name="Paris", language="fr".
178
+ - If no `>>` separator is found, defaults to `"en"` as the language.
179
+
180
+ Returns:
181
+ tuple(str, str):
182
+ - QID of the page (e.g., `"Q90"`) if found, otherwise `"NIL"`.
183
+ - Language code (e.g., `"fr"`, `"en"`).
184
+
185
+ Notes:
186
+ - Uses `safe_get()` internally for API calls, with retry logic and
187
+ a proper User-Agent header (required by Wikimedia).
188
+ - Falls back gracefully to `"NIL"` if both Wikipedia and Wikidata lookups fail.
189
+ - This function does not fetch human-readable titles or URLs;
190
+ use `get_wikipedia_title()` for that.
191
+ """
192
+
193
+ if ">>" in input_str:
194
+ page_name, language = [x.strip() for x in input_str.split(">>", 1)]
195
+ else:
196
+ page_name, language = input_str.strip(), "en"
197
+
198
+ qid = "NIL"
199
+
200
+ # --- Step 1: Try Wikipedia API ---
201
+ wikipedia_url = f"https://{language}.wikipedia.org/w/api.php"
202
+ wikipedia_params = {
203
+ "action": "query",
204
+ "prop": "pageprops",
205
+ "format": "json",
206
+ "titles": page_name,
207
+ }
208
+
209
+ resp = safe_get(wikipedia_url, wikipedia_params)
210
+ if resp:
211
+ data = resp.json()
212
+ if "pages" in data.get("query", {}):
213
+ page_id = list(data["query"]["pages"].keys())[0]
214
+ page_props = data["query"]["pages"][page_id].get("pageprops", {})
215
+ if "wikibase_item" in page_props:
216
+ return page_props["wikibase_item"], language
217
+
218
+ # --- Step 2: Fallback to Wikidata search ---
219
+ wd_url = "https://www.wikidata.org/w/api.php"
220
+ wd_params = {
221
+ "action": "wbsearchentities",
222
+ "search": page_name,
223
+ "language": language,
224
+ "format": "json",
225
+ }
226
+
227
+ resp = safe_get(wd_url, wd_params)
228
+ if resp:
229
+ data = resp.json()
230
+ if data.get("search"):
231
+ first_hit = data["search"][0]
232
+ return first_hit["id"], language
233
+
234
+ return qid, language
235
+
236
+
237
+ def resolve_type_from_wikidata(p31_qids, visited=None, depth=0, max_depth=3):
238
+ """
239
+ Resolve a Wikidata entity's high-level type ("pers", "org", "loc")
240
+ by checking its 'instance of' (P31) values and, if necessary,
241
+ recursively climbing 'subclass of' (P279) relations.
242
+
243
+ Args:
244
+ p31_qids (list[str]): List of QIDs from 'instance of' (P31) claims.
245
+ visited (set, optional): Set of QIDs already checked (to avoid cycles).
246
+ depth (int, optional): Current recursion depth (default=0).
247
+ max_depth (int, optional): Maximum recursion depth for P279 traversal.
248
+
249
+ Returns:
250
+ str: One of {"pers", "org", "loc", "UNK"}.
251
+ "UNK" is returned if no mapping is found within max_depth.
252
+
253
+ Notes:
254
+ - Anchors:
255
+ Q5 → person
256
+ Any in `qid_to_organization_label_keys` or TYPE_MAP=organization → org
257
+ Any in `qid_to_location_label_keys` or TYPE_MAP=location → loc
258
+ - Subclass traversal:
259
+ If P31 is not directly mapped, checks P279 (subclass of)
260
+ recursively up to `max_depth`.
261
+ """
262
+
263
+ if visited is None:
264
+ visited = set()
265
+
266
+ for q in p31_qids:
267
+ if q in visited:
268
+ continue
269
+ visited.add(q)
270
+
271
+ # direct anchors
272
+ if q == "Q5":
273
+ return "pers"
274
+ if (
275
+ q in qid_to_organization_label_keys
276
+ or q in TYPE_MAP
277
+ and TYPE_MAP[q] == "organization"
278
+ ):
279
+ return "org"
280
+ if (
281
+ q in qid_to_location_label_keys
282
+ or q in TYPE_MAP
283
+ and TYPE_MAP[q] == "location"
284
+ ):
285
+ return "loc"
286
+
287
+ # subclass traversal
288
+ if depth < max_depth:
289
+ wd_url = "https://www.wikidata.org/w/api.php"
290
+ params = {
291
+ "action": "wbgetentities",
292
+ "format": "json",
293
+ "ids": q,
294
+ "props": "claims",
295
+ }
296
+ resp = safe_get(wd_url, params)
297
+ if resp:
298
+ data = resp.json()
299
+ entity = data["entities"].get(q, {})
300
+ claims = entity.get("claims", {})
301
+ if "P279" in claims: # subclass of
302
+ parents = [
303
+ c["mainsnak"]["datavalue"]["value"]["id"]
304
+ for c in claims["P279"]
305
+ if "datavalue" in c["mainsnak"]
306
+ ]
307
+ resolved = resolve_type_from_wikidata(
308
+ parents, visited, depth + 1, max_depth
309
+ )
310
+ if resolved != "UNK":
311
+ return resolved
312
+
313
+ return "UNK"
314
+
315
+
316
+ def get_wikipedia_title(qid, language="en"):
317
+ """
318
+ Retrieve a Wikipedia title, URL, and a mapped coarse entity type from a Wikidata QID.
319
+
320
+ This function queries Wikidata to fetch:
321
+ - The title of the corresponding Wikipedia article in the given language.
322
+ - The article URL.
323
+ - A coarse-grained entity type label ("pers", "org", "loc", or "UNK"),
324
+ derived from the entity's "instance of" (P31) and, if necessary,
325
+ recursively from its "subclass of" (P279) hierarchy.
326
+
327
+ Args:
328
+ qid (str): The Wikidata identifier (e.g., "Q90" for Paris).
329
+ If "NIL" or empty, returns ("NIL", "None", "UNK").
330
+ language (str, optional): ISO language code for the Wikipedia site
331
+ (default is "en"). Example: "fr" for French Wikipedia.
332
+
333
+ Returns:
334
+ tuple:
335
+ - title (str): The Wikipedia page title if available, otherwise "NIL".
336
+ - wiki_url (str): The Wikipedia page URL if available, otherwise "None".
337
+ - type_label (str): A mapped entity type:
338
+ * "pers" → person (Q5, or subclass thereof)
339
+ * "org" → organization (Q43229, Q95074, etc. or subclass thereof)
340
+ * "loc" → location (Q515, Q6256, Q484170, etc. or subclass thereof)
341
+ * "UNK" → unknown if not resolved within recursion depth
342
+
343
+ Notes:
344
+ - Uses `safe_get()` internally for robust requests with retries and
345
+ a proper User-Agent header (required by Wikimedia).
346
+ - Calls `resolve_type_from_wikidata()` to map P31/P279 values into
347
+ coarse-grained types.
348
+ - Limits subclass-of (P279) traversal to `max_depth` defined in
349
+ `resolve_type_from_wikidata` (default=3).
350
+ - Returns gracefully with ("NIL", "None", "UNK") if the QID is invalid
351
+ or Wikidata returns no useful data.
352
+ """
353
+
354
+ if not qid or qid == "NIL":
355
+ return "NIL", "None", "UNK"
356
+
357
+ url = "https://www.wikidata.org/w/api.php"
358
+ params = {
359
+ "action": "wbgetentities",
360
+ "format": "json",
361
+ "ids": qid,
362
+ "props": "sitelinks/urls|claims",
363
+ "sitefilter": f"{language}wiki",
364
+ }
365
+
366
+ resp = safe_get(url, params)
367
+ if not resp:
368
+ return "NIL", "None", "UNK"
369
+
370
+ try:
371
+ data = resp.json()
372
+ entity = data["entities"][qid]
373
+
374
+ # --- title + url ---
375
+ sitelinks = entity.get("sitelinks", {})
376
+ if f"{language}wiki" in sitelinks:
377
+ title = sitelinks[f"{language}wiki"]["title"]
378
+ wiki_url = sitelinks[f"{language}wiki"]["url"]
379
+ else:
380
+ title, wiki_url = "NIL", "None"
381
+
382
+ # --- detect type from P31 ---
383
+ claims = entity.get("claims", {})
384
+
385
+ if "P31" in claims:
386
+ p31_qids = [
387
+ c["mainsnak"]["datavalue"]["value"]["id"]
388
+ for c in claims["P31"]
389
+ if "datavalue" in c["mainsnak"]
390
+ ]
391
+ type_label = resolve_type_from_wikidata(p31_qids)
392
+ else:
393
+ type_label = "UNK"
394
+
395
+ return title, wiki_url, type_label
396
+
397
+ except Exception as e:
398
+ print(f"Error parsing Wikidata for {qid}: {e}")
399
+ return "NIL", "None", "UNK"
400
+
401
+
402
+ class NelPipeline(Pipeline):
403
+ """
404
+ Hugging Face Pipeline for NEL that supports:
405
+ - Single input: text with [START] ... [END]
406
+ - Batch input: list of texts, each with one mention
407
+ """
408
+
409
+ def _sanitize_parameters(self, **kwargs):
410
+ preprocess_kwargs = {}
411
+ if "text" in kwargs:
412
+ preprocess_kwargs["text"] = kwargs["text"]
413
+ return preprocess_kwargs, {}, {}
414
+
415
+ def preprocess(self, text, **kwargs):
416
+ """
417
+ Accepts:
418
+ text → string with [START]...[END]
419
+ text → list[str] (batched)
420
+ Returns:
421
+ list of dict items (one per mention)
422
+ """
423
+ if isinstance(text, str):
424
+ text_list = [text]
425
+ else:
426
+ text_list = text
427
+
428
+ batch = []
429
+ for t in text_list:
430
+ start_token = "[START]"
431
+ end_token = "[END]"
432
+
433
+ if start_token in t and end_token in t:
434
+ start_idx = t.index(start_token) + len(start_token)
435
+ end_idx = t.index(end_token)
436
+ enclosed = t[start_idx:end_idx].strip()
437
+ lOffset = start_idx
438
+ rOffset = end_idx
439
+ else:
440
+ enclosed, lOffset, rOffset = None, None, None
441
+
442
+ batch.append(
443
+ {"text": t, "surface": enclosed, "lOffset": lOffset, "rOffset": rOffset}
444
+ )
445
+
446
+ return batch
447
+
448
+ def _forward(self, batch):
449
+ """
450
+ batch is a list of entries from preprocess()
451
+ We batch all texts into one generate() call.
452
+ """
453
+ texts = [b["text"] for b in batch]
454
+
455
+ enc = self.tokenizer(
456
+ texts, return_tensors="pt", padding=True, truncation=True
457
+ ).to(self.device)
458
+
459
+ outputs = self.model.generate(
460
+ **enc,
461
+ num_beams=1,
462
+ num_return_sequences=1,
463
+ max_new_tokens=30,
464
+ return_dict_in_generate=True,
465
+ output_scores=True,
466
+ )
467
+
468
+ # decode predictions
469
+ decoded = self.tokenizer.batch_decode(
470
+ outputs.sequences, skip_special_tokens=True
471
+ )
472
+
473
+ # compute per-sequence confidence
474
+ transition_scores = self.model.compute_transition_scores(
475
+ outputs.sequences, outputs.scores, normalize_logits=True
476
+ )
477
+
478
+ confidences = []
479
+ for i in range(len(decoded)):
480
+ log_prob = sum(transition_scores[i])
481
+ prob = torch.exp(log_prob).cpu().numpy()
482
+ confidences.append(float(prob))
483
+
484
+ # attach outputs to batch
485
+ for i, item in enumerate(batch):
486
+ item["wikipedia_prediction"] = decoded[i]
487
+ item["confidence"] = confidences[i]
488
+
489
+ return batch
490
+
491
+ def postprocess(self, batch, **kwargs):
492
+ """
493
+ N items → N linked entities
494
+ """
495
+
496
+ results = []
497
+ for item in batch:
498
+ pred = item["wikipedia_prediction"]
499
+ surface = item["surface"]
500
+ lOffset = item["lOffset"]
501
+ rOffset = item["rOffset"]
502
+
503
+ # Wikidata resolution
504
+ qid, lang = get_wikipedia_page_props(pred)
505
+ title, url, ent_type = get_wikipedia_title(qid, language=lang)
506
+
507
+ # normalize confidence into [0,1]
508
+ conf = item["confidence"]
509
+ if conf > 1:
510
+ conf = conf / 100
511
+ conf = round(conf, 4)
512
+
513
+ results.append(
514
+ {
515
+ "surface": surface,
516
+ "wkd_id": qid,
517
+ "wkpedia_pagename": title,
518
+ "wkpedia_url": url,
519
+ "type": ent_type,
520
+ "confidence_nel": conf,
521
+ # "lOffset": lOffset,
522
+ # "rOffset": rOffset,
523
+ }
524
+ )
525
+
526
+ return results
527
+
528
+
529
+ qid_to_location_label = {
530
+ "Q82794": "geographical region",
531
+ "Q6256": "country",
532
+ "Q3624078": "sovereign state",
533
+ "Q35657": "U.S. state",
534
+ "Q515": "city",
535
+ "Q532": "village",
536
+ "Q3957": "town",
537
+ "Q2983893": "municipality",
538
+ "Q486972": "human settlement",
539
+ "Q23442": "island",
540
+ "Q8502": "mountain",
541
+ "Q23397": "lake",
542
+ "Q4022": "river",
543
+ "Q123705": "peninsula",
544
+ "Q13221722": "bay",
545
+ "Q165": "sea",
546
+ "Q124714": "ocean",
547
+ "Q42124": "continent",
548
+ "Q23413": "territory",
549
+ "Q1048835": "province",
550
+ "Q107390": "county",
551
+ "Q13220204": "district",
552
+ "Q13218630": "subdistrict",
553
+ "Q618123": "location", # geographical object
554
+ "Q2221906": "location", # geographical location
555
+ "Q17334923": "location", # geographical region
556
+ }
557
+ TYPE_MAP = {
558
+ "Q5": "person", # human
559
+ "Q43229": "organization", # organization
560
+ "Q95074": "organization", # company
561
+ "Q783794": "organization", # non-profit
562
+ "Q618123": "location", # geographical object
563
+ "Q2221906": "location", # geographical location
564
+ "Q17334923": "location", # geographical region
565
+ "Q6256": "location", # country
566
+ "Q515": "location", # city
567
+ }
568
+
569
+ qid_to_location_label_keys = set(qid_to_location_label.keys())
570
+ qid_to_organization_label = {
571
+ "Q43229": "organization", # organization
572
+ "Q95074": "company", # company
573
+ "Q783794": "non-profit", # non-profit organization
574
+ "Q891723": "international organization",
575
+ "Q163740": "political party",
576
+ "Q178706": "trade union",
577
+ "Q189004": "government agency",
578
+ "Q327333": "educational institution",
579
+ "Q31855": "university",
580
+ "Q219885": "research institute",
581
+ "Q12973014": "NGO", # non-governmental organization
582
+ "Q7210356": "television network",
583
+ "Q33231": "military unit",
584
+ "Q15911314": "sports club",
585
+ "Q57660343": "media organization",
586
+ "Q167037": "religious organization",
587
+ "Q4438121": "publishing company",
588
+ "Q2088357": "academic publisher",
589
+ }
590
+ qid_to_organization_label_keys = set(qid_to_organization_label.keys())
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f8cfb5bf9aa521336b586ae37eecac31ed7e86327a1be1802d32551472988633
3
+ size 2468961388
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ torch
2
+ transformers
3
+ requests
4
+ requests-cache
5
+ filelock
scheduler.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:bc00424e1006d8552c992d3bde1acf8d4282909093c4e18a2112a6e6b087b217
3
+ size 1064
sentencepiece.bpe.model ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6ee4dc054a17c18fe81f76c0b1cda00e9fc1cfd9e0f1a16cb6d77009e2076653
3
+ size 4870365
special_tokens_map.json ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "bos_token": {
3
+ "content": "<s>",
4
+ "lstrip": false,
5
+ "normalized": false,
6
+ "rstrip": false,
7
+ "single_word": false
8
+ },
9
+ "cls_token": {
10
+ "content": "<s>",
11
+ "lstrip": false,
12
+ "normalized": false,
13
+ "rstrip": false,
14
+ "single_word": false
15
+ },
16
+ "eos_token": {
17
+ "content": "</s>",
18
+ "lstrip": false,
19
+ "normalized": false,
20
+ "rstrip": false,
21
+ "single_word": false
22
+ },
23
+ "mask_token": {
24
+ "content": "<mask>",
25
+ "lstrip": true,
26
+ "normalized": true,
27
+ "rstrip": false,
28
+ "single_word": false
29
+ },
30
+ "pad_token": {
31
+ "content": "<pad>",
32
+ "lstrip": false,
33
+ "normalized": false,
34
+ "rstrip": false,
35
+ "single_word": false
36
+ },
37
+ "sep_token": {
38
+ "content": "</s>",
39
+ "lstrip": false,
40
+ "normalized": false,
41
+ "rstrip": false,
42
+ "single_word": false
43
+ },
44
+ "unk_token": {
45
+ "content": "<unk>",
46
+ "lstrip": false,
47
+ "normalized": false,
48
+ "rstrip": false,
49
+ "single_word": false
50
+ }
51
+ }
tokenizer_config.json ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "added_tokens_decoder": {
3
+ "0": {
4
+ "content": "<s>",
5
+ "lstrip": false,
6
+ "normalized": false,
7
+ "rstrip": false,
8
+ "single_word": false,
9
+ "special": true
10
+ },
11
+ "1": {
12
+ "content": "<pad>",
13
+ "lstrip": false,
14
+ "normalized": false,
15
+ "rstrip": false,
16
+ "single_word": false,
17
+ "special": true
18
+ },
19
+ "2": {
20
+ "content": "</s>",
21
+ "lstrip": false,
22
+ "normalized": false,
23
+ "rstrip": false,
24
+ "single_word": false,
25
+ "special": true
26
+ },
27
+ "3": {
28
+ "content": "<unk>",
29
+ "lstrip": false,
30
+ "normalized": false,
31
+ "rstrip": false,
32
+ "single_word": false,
33
+ "special": true
34
+ },
35
+ "256001": {
36
+ "content": "<mask>",
37
+ "lstrip": true,
38
+ "normalized": true,
39
+ "rstrip": false,
40
+ "single_word": false,
41
+ "special": true
42
+ }
43
+ },
44
+ "bos_token": "<s>",
45
+ "clean_up_tokenization_spaces": false,
46
+ "cls_token": "<s>",
47
+ "eos_token": "</s>",
48
+ "mask_token": "<mask>",
49
+ "model_max_length": 512,
50
+ "pad_token": "<pad>",
51
+ "sep_token": "</s>",
52
+ "sp_model_kwargs": {},
53
+ "tokenizer_class": "XLMRobertaTokenizer",
54
+ "unk_token": "<unk>"
55
+ }
trainer_state.json ADDED
@@ -0,0 +1,207 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "best_metric": null,
3
+ "best_model_checkpoint": null,
4
+ "epoch": 10.0,
5
+ "eval_steps": 500,
6
+ "global_step": 6480,
7
+ "is_hyper_param_search": false,
8
+ "is_local_process_zero": true,
9
+ "is_world_process_zero": true,
10
+ "log_history": [
11
+ {
12
+ "epoch": 0.7716049382716049,
13
+ "grad_norm": 1.0553990602493286,
14
+ "learning_rate": 1.846913580246914e-05,
15
+ "loss": 0.9346,
16
+ "step": 500
17
+ },
18
+ {
19
+ "epoch": 1.0,
20
+ "eval_bleu": 0.0,
21
+ "eval_gen_len": 10.0959,
22
+ "eval_loss": 0.15309424698352814,
23
+ "eval_runtime": 7.8759,
24
+ "eval_samples_per_second": 154.903,
25
+ "eval_steps_per_second": 2.539,
26
+ "step": 648
27
+ },
28
+ {
29
+ "epoch": 1.5432098765432098,
30
+ "grad_norm": 0.7297214269638062,
31
+ "learning_rate": 1.6925925925925926e-05,
32
+ "loss": 0.0763,
33
+ "step": 1000
34
+ },
35
+ {
36
+ "epoch": 2.0,
37
+ "eval_bleu": 0.0,
38
+ "eval_gen_len": 10.159,
39
+ "eval_loss": 0.16104426980018616,
40
+ "eval_runtime": 7.6405,
41
+ "eval_samples_per_second": 159.674,
42
+ "eval_steps_per_second": 2.618,
43
+ "step": 1296
44
+ },
45
+ {
46
+ "epoch": 2.314814814814815,
47
+ "grad_norm": 0.44237253069877625,
48
+ "learning_rate": 1.5382716049382717e-05,
49
+ "loss": 0.0446,
50
+ "step": 1500
51
+ },
52
+ {
53
+ "epoch": 3.0,
54
+ "eval_bleu": 0.0,
55
+ "eval_gen_len": 10.0426,
56
+ "eval_loss": 0.17489495873451233,
57
+ "eval_runtime": 7.8385,
58
+ "eval_samples_per_second": 155.642,
59
+ "eval_steps_per_second": 2.552,
60
+ "step": 1944
61
+ },
62
+ {
63
+ "epoch": 3.0864197530864197,
64
+ "grad_norm": 0.3801327049732208,
65
+ "learning_rate": 1.3839506172839507e-05,
66
+ "loss": 0.0275,
67
+ "step": 2000
68
+ },
69
+ {
70
+ "epoch": 3.8580246913580245,
71
+ "grad_norm": 0.29495081305503845,
72
+ "learning_rate": 1.2296296296296298e-05,
73
+ "loss": 0.0162,
74
+ "step": 2500
75
+ },
76
+ {
77
+ "epoch": 4.0,
78
+ "eval_bleu": 0.0,
79
+ "eval_gen_len": 10.1139,
80
+ "eval_loss": 0.1843736320734024,
81
+ "eval_runtime": 7.7649,
82
+ "eval_samples_per_second": 157.118,
83
+ "eval_steps_per_second": 2.576,
84
+ "step": 2592
85
+ },
86
+ {
87
+ "epoch": 4.62962962962963,
88
+ "grad_norm": 0.29735738039016724,
89
+ "learning_rate": 1.0753086419753086e-05,
90
+ "loss": 0.0106,
91
+ "step": 3000
92
+ },
93
+ {
94
+ "epoch": 5.0,
95
+ "eval_bleu": 0.0,
96
+ "eval_gen_len": 9.9508,
97
+ "eval_loss": 0.19341909885406494,
98
+ "eval_runtime": 7.6995,
99
+ "eval_samples_per_second": 158.452,
100
+ "eval_steps_per_second": 2.598,
101
+ "step": 3240
102
+ },
103
+ {
104
+ "epoch": 5.401234567901234,
105
+ "grad_norm": 0.07027166336774826,
106
+ "learning_rate": 9.209876543209877e-06,
107
+ "loss": 0.0076,
108
+ "step": 3500
109
+ },
110
+ {
111
+ "epoch": 6.0,
112
+ "eval_bleu": 0.0,
113
+ "eval_gen_len": 9.9377,
114
+ "eval_loss": 0.20017552375793457,
115
+ "eval_runtime": 7.6996,
116
+ "eval_samples_per_second": 158.45,
117
+ "eval_steps_per_second": 2.598,
118
+ "step": 3888
119
+ },
120
+ {
121
+ "epoch": 6.172839506172839,
122
+ "grad_norm": 0.1504916250705719,
123
+ "learning_rate": 7.666666666666667e-06,
124
+ "loss": 0.0059,
125
+ "step": 4000
126
+ },
127
+ {
128
+ "epoch": 6.944444444444445,
129
+ "grad_norm": 0.24264627695083618,
130
+ "learning_rate": 6.123456790123458e-06,
131
+ "loss": 0.0043,
132
+ "step": 4500
133
+ },
134
+ {
135
+ "epoch": 7.0,
136
+ "eval_bleu": 0.0,
137
+ "eval_gen_len": 10.0279,
138
+ "eval_loss": 0.20386986434459686,
139
+ "eval_runtime": 7.7944,
140
+ "eval_samples_per_second": 156.523,
141
+ "eval_steps_per_second": 2.566,
142
+ "step": 4536
143
+ },
144
+ {
145
+ "epoch": 7.716049382716049,
146
+ "grad_norm": 0.08363181352615356,
147
+ "learning_rate": 4.580246913580247e-06,
148
+ "loss": 0.0035,
149
+ "step": 5000
150
+ },
151
+ {
152
+ "epoch": 8.0,
153
+ "eval_bleu": 0.0,
154
+ "eval_gen_len": 10.1566,
155
+ "eval_loss": 0.20531675219535828,
156
+ "eval_runtime": 7.6989,
157
+ "eval_samples_per_second": 158.465,
158
+ "eval_steps_per_second": 2.598,
159
+ "step": 5184
160
+ },
161
+ {
162
+ "epoch": 8.487654320987655,
163
+ "grad_norm": 0.13225023448467255,
164
+ "learning_rate": 3.0370370370370372e-06,
165
+ "loss": 0.0029,
166
+ "step": 5500
167
+ },
168
+ {
169
+ "epoch": 9.0,
170
+ "eval_bleu": 0.0,
171
+ "eval_gen_len": 10.0689,
172
+ "eval_loss": 0.20702147483825684,
173
+ "eval_runtime": 7.6619,
174
+ "eval_samples_per_second": 159.23,
175
+ "eval_steps_per_second": 2.61,
176
+ "step": 5832
177
+ },
178
+ {
179
+ "epoch": 9.25925925925926,
180
+ "grad_norm": 0.022540247067809105,
181
+ "learning_rate": 1.4938271604938272e-06,
182
+ "loss": 0.003,
183
+ "step": 6000
184
+ }
185
+ ],
186
+ "logging_steps": 500,
187
+ "max_steps": 6480,
188
+ "num_input_tokens_seen": 0,
189
+ "num_train_epochs": 10,
190
+ "save_steps": 1000,
191
+ "stateful_callbacks": {
192
+ "TrainerControl": {
193
+ "args": {
194
+ "should_epoch_stop": false,
195
+ "should_evaluate": false,
196
+ "should_log": false,
197
+ "should_save": true,
198
+ "should_training_stop": true
199
+ },
200
+ "attributes": {}
201
+ }
202
+ },
203
+ "total_flos": 4.288315707563704e+17,
204
+ "train_batch_size": 64,
205
+ "trial_name": null,
206
+ "trial_params": null
207
+ }
utils.py ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ qid_to_location_label = {
2
+ "Q82794": "geographical region",
3
+ "Q6256": "country",
4
+ "Q3624078": "sovereign state",
5
+ "Q35657": "U.S. state",
6
+ "Q515": "city",
7
+ "Q532": "village",
8
+ "Q3957": "town",
9
+ "Q2983893": "municipality",
10
+ "Q486972": "human settlement",
11
+ "Q23442": "island",
12
+ "Q8502": "mountain",
13
+ "Q23397": "lake",
14
+ "Q4022": "river",
15
+ "Q123705": "peninsula",
16
+ "Q13221722": "bay",
17
+ "Q165": "sea",
18
+ "Q124714": "ocean",
19
+ "Q42124": "continent",
20
+ "Q23413": "territory",
21
+ "Q1048835": "province",
22
+ "Q107390": "county",
23
+ "Q13220204": "district",
24
+ "Q13218630": "subdistrict",
25
+ "Q618123": "location", # geographical object
26
+ "Q2221906": "location", # geographical location
27
+ "Q17334923": "location", # geographical region
28
+ }
29
+ TYPE_MAP = {
30
+ "Q5": "person", # human
31
+ "Q43229": "organization", # organization
32
+ "Q95074": "organization", # company
33
+ "Q783794": "organization", # non-profit
34
+ "Q618123": "location", # geographical object
35
+ "Q2221906": "location", # geographical location
36
+ "Q17334923": "location", # geographical region
37
+ "Q6256": "location", # country
38
+ "Q515": "location", # city
39
+ }
40
+
41
+ qid_to_location_label_keys = set(qid_to_location_label.keys())
42
+ qid_to_organization_label = {
43
+ "Q43229": "organization", # organization
44
+ "Q95074": "company", # company
45
+ "Q783794": "non-profit", # non-profit organization
46
+ "Q891723": "international organization",
47
+ "Q163740": "political party",
48
+ "Q178706": "trade union",
49
+ "Q189004": "government agency",
50
+ "Q327333": "educational institution",
51
+ "Q31855": "university",
52
+ "Q219885": "research institute",
53
+ "Q12973014": "NGO", # non-governmental organization
54
+ "Q7210356": "television network",
55
+ "Q33231": "military unit",
56
+ "Q15911314": "sports club",
57
+ "Q57660343": "media organization",
58
+ "Q167037": "religious organization",
59
+ "Q4438121": "publishing company",
60
+ "Q2088357": "academic publisher",
61
+ }
62
+ qid_to_organization_label_keys = set(qid_to_organization_label.keys())
Free AI Image Generator No sign-up. Instant results. Open Now