Token Classification
Transformers
Safetensors
German
bert
ner
german
contact-information
imprint
web-extraction
Instructions to use andyP/gbert-base-contact-ner with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use andyP/gbert-base-contact-ner with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("token-classification", model="andyP/gbert-base-contact-ner")# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForTokenClassification tokenizer = AutoTokenizer.from_pretrained("andyP/gbert-base-contact-ner") model = AutoModelForTokenClassification.from_pretrained("andyP/gbert-base-contact-ner", device_map="auto") - Notebooks
- Google Colab
- Kaggle
Upload gbert-base-contact-ner (company_research.contact gpu model)
Browse files- README.md +126 -0
- config.json +78 -0
- impressum.json +1 -0
- model.safetensors +3 -0
- tokenizer.json +0 -0
- tokenizer_config.json +16 -0
README.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: mit
|
| 3 |
+
language: de
|
| 4 |
+
base_model: deepset/gbert-base
|
| 5 |
+
pipeline_tag: token-classification
|
| 6 |
+
library_name: transformers
|
| 7 |
+
tags:
|
| 8 |
+
- token-classification
|
| 9 |
+
- ner
|
| 10 |
+
- german
|
| 11 |
+
- contact-information
|
| 12 |
+
- imprint
|
| 13 |
+
- web-extraction
|
| 14 |
+
---
|
| 15 |
+
|
| 16 |
+
# gbert-base-contact-ner
|
| 17 |
+
|
| 18 |
+
A German token-classification model that finds contact details in the text of company web pages: street, postal
|
| 19 |
+
code, city, country, phone, fax, email, opening hours, location label, department and contact person. It is
|
| 20 |
+
[`deepset/gbert-base`](https://huggingface.co/deepset/gbert-base) fine-tuned on LLM-labeled contact pages. It is the
|
| 21 |
+
`gpu` extraction model of the `company_research.contact` package.
|
| 22 |
+
|
| 23 |
+
## Labels
|
| 24 |
+
|
| 25 |
+
11 fields in BIO format, 23 labels in total (`O` plus `B-`/`I-` for each field):
|
| 26 |
+
|
| 27 |
+
`street`, `plz` (postal code), `city`, `country`, `phone`, `fax`, `email`, `opening_hours`, `location_label`,
|
| 28 |
+
`department`, `person`.
|
| 29 |
+
|
| 30 |
+
The model outputs character spans of the input text only. It never rewrites or normalizes a value.
|
| 31 |
+
|
| 32 |
+
## Training data
|
| 33 |
+
|
| 34 |
+
- Pages of 800 German-language company websites, labeled by LLM agents (Claude Opus) against a written labeling
|
| 35 |
+
guide. Every labeled value appears verbatim on its page. The labels were not verified by humans; one clean-up pass
|
| 36 |
+
covered flagged sites only.
|
| 37 |
+
- The sites are German (399), Swiss (346) and Austrian (55), split by domain: 480 train, 160 dev, 160 test.
|
| 38 |
+
This model was trained on the train split (565 labeled pages) and tuned on dev. The 55 Austrian sites are all in
|
| 39 |
+
the test split, so the model never saw AT data during training.
|
| 40 |
+
- Input is the page as markdown text (not raw HTML).
|
| 41 |
+
|
| 42 |
+
## Training
|
| 43 |
+
|
| 44 |
+
- Base model `deepset/gbert-base`, token classification head with 23 labels.
|
| 45 |
+
- Pages are cut into windows of 512 tokens (510 plus `[CLS]` and `[SEP]`) with an overlap of 128 tokens. Training
|
| 46 |
+
uses the windows that contain a labeled value plus an equal number of randomly drawn windows without any.
|
| 47 |
+
- AdamW, learning rate 3e-5, weight decay 0.01, batch size 4 with 4 gradient-accumulation steps, up to 8 epochs
|
| 48 |
+
with early stopping (patience 2) on dev seqeval F1.
|
| 49 |
+
|
| 50 |
+
## Evaluation
|
| 51 |
+
|
| 52 |
+
All numbers are agreement with the LLM-made labels on the 160 held-out test sites (153 of them have contact data),
|
| 53 |
+
from the experiments report of the Impressum project (section 12). Scores are set-based: per site, the predicted
|
| 54 |
+
values are compared with the labeled values after normalization (phones to E.164, emails lowercased, PLZ digits only,
|
| 55 |
+
text casefolded with whitespace and punctuation cleaned). Micro F1 pools all fields. The differences under about 3
|
| 56 |
+
points between rows of the report are noise at this test size.
|
| 57 |
+
|
| 58 |
+
**Extraction on the right pages** (labeled contact pages given; this model alone, F1):
|
| 59 |
+
|
| 60 |
+
| micro | street | plz | phone | fax | email | opening hours | person |
|
| 61 |
+
|---|---|---|---|---|---|---|---|
|
| 62 |
+
| 70.2 | 64.9 | 88.0 | 88.9 | 80.6 | 70.7 | 48.9 | 80.5 |
|
| 63 |
+
|
| 64 |
+
The report does not list per-field scores for city, country, location label or department for this model alone.
|
| 65 |
+
Street and email are its weaker fields among those listed (a regex and a CRF do better there; the pipeline routes those
|
| 66 |
+
fields to them), and opening hours are hard for every method tried.
|
| 67 |
+
|
| 68 |
+
**End to end** (report section 12.7). These numbers are for the whole `company_research.contact` `gpu` pipeline,
|
| 69 |
+
not for this model alone: contact-page detection, hybrid extraction (this model for PLZ, city, phone, hours,
|
| 70 |
+
department and person; a CRF for street and label; regex for fax, email and country), grouping into locations and
|
| 71 |
+
departments, structured-data parsing and social links. Micro F1 over all site fields: **73.6** overall;
|
| 72 |
+
71.0 on DE, 80.0 on CH, 72.9 on AT.
|
| 73 |
+
|
| 74 |
+
## How to use
|
| 75 |
+
|
| 76 |
+
### With `company_research.contact`
|
| 77 |
+
|
| 78 |
+
```python
|
| 79 |
+
from company_research import contact
|
| 80 |
+
|
| 81 |
+
result = contact.from_site("https://www.example.de", device="gpu")
|
| 82 |
+
```
|
| 83 |
+
|
| 84 |
+
`device="gpu"` needs the package's `gpu` extra (torch and transformers); the package is not on PyPI.
|
| 85 |
+
It downloads this model on first use and runs on CUDA when available (otherwise on the CPU, much slower). The `cpu` device uses a different, smaller
|
| 86 |
+
set of models without a transformer.
|
| 87 |
+
|
| 88 |
+
### With `transformers`
|
| 89 |
+
|
| 90 |
+
The model was trained on windows, so long pages must be windowed at inference as well. The reference implementation
|
| 91 |
+
is `company_research/contact/gbert.py` (`windows`, `decode`, `predict`). In short:
|
| 92 |
+
|
| 93 |
+
1. Tokenize the page text without special tokens, keeping character offsets
|
| 94 |
+
(`tok(text, add_special_tokens=False, return_offsets_mapping=True)`).
|
| 95 |
+
2. Make windows of 510 tokens whose starts are 382 tokens apart (overlap 128); add `[CLS]` and `[SEP]` to each.
|
| 96 |
+
3. Run the model, apply softmax, and average the probabilities of tokens that are covered by several windows.
|
| 97 |
+
4. Take the argmax per token and merge `B-x`/`I-x` runs into character spans using the offsets.
|
| 98 |
+
|
| 99 |
+
```python
|
| 100 |
+
from transformers import AutoModelForTokenClassification, AutoTokenizer
|
| 101 |
+
|
| 102 |
+
tok = AutoTokenizer.from_pretrained("andyP/gbert-base-contact-ner")
|
| 103 |
+
model = AutoModelForTokenClassification.from_pretrained("andyP/gbert-base-contact-ner").eval()
|
| 104 |
+
```
|
| 105 |
+
|
| 106 |
+
## Limitations
|
| 107 |
+
|
| 108 |
+
- German-language company pages (imprint, contact and similar pages). Other languages and page types are untested.
|
| 109 |
+
- The labels come from an LLM and were not verified by humans, so the scores measure agreement with those labels,
|
| 110 |
+
not with human judgment.
|
| 111 |
+
- Weaker fields: street (64.9) and email (70.7) in the scores above; opening hours (48.9) are the hardest.
|
| 112 |
+
Typical errors in the project's spot-check of the full pipeline were missed values, values of third parties (for
|
| 113 |
+
example the web agency named in the imprint), spans cut inside words and navigation text.
|
| 114 |
+
- The model does not group values into locations or departments, and it does not tell contact pages from other
|
| 115 |
+
pages. The pipeline does that.
|
| 116 |
+
- Input must be the page text as markdown, as the training data was. Raw HTML will perform worse.
|
| 117 |
+
|
| 118 |
+
## Privacy
|
| 119 |
+
|
| 120 |
+
The training pages are public company websites. They contain names and business contact details of contact persons,
|
| 121 |
+
so the training data includes personal data of that kind. The model outputs spans copied from the text you give it
|
| 122 |
+
and does not generate text.
|
| 123 |
+
|
| 124 |
+
## License
|
| 125 |
+
|
| 126 |
+
MIT, as the base model.
|
config.json
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"add_cross_attention": false,
|
| 3 |
+
"architectures": [
|
| 4 |
+
"BertForTokenClassification"
|
| 5 |
+
],
|
| 6 |
+
"attention_probs_dropout_prob": 0.1,
|
| 7 |
+
"bos_token_id": null,
|
| 8 |
+
"classifier_dropout": null,
|
| 9 |
+
"dtype": "float32",
|
| 10 |
+
"eos_token_id": null,
|
| 11 |
+
"hidden_act": "gelu",
|
| 12 |
+
"hidden_dropout_prob": 0.1,
|
| 13 |
+
"hidden_size": 768,
|
| 14 |
+
"id2label": {
|
| 15 |
+
"0": "O",
|
| 16 |
+
"1": "B-street",
|
| 17 |
+
"2": "I-street",
|
| 18 |
+
"3": "B-plz",
|
| 19 |
+
"4": "I-plz",
|
| 20 |
+
"5": "B-city",
|
| 21 |
+
"6": "I-city",
|
| 22 |
+
"7": "B-country",
|
| 23 |
+
"8": "I-country",
|
| 24 |
+
"9": "B-phone",
|
| 25 |
+
"10": "I-phone",
|
| 26 |
+
"11": "B-fax",
|
| 27 |
+
"12": "I-fax",
|
| 28 |
+
"13": "B-email",
|
| 29 |
+
"14": "I-email",
|
| 30 |
+
"15": "B-opening_hours",
|
| 31 |
+
"16": "I-opening_hours",
|
| 32 |
+
"17": "B-location_label",
|
| 33 |
+
"18": "I-location_label",
|
| 34 |
+
"19": "B-department",
|
| 35 |
+
"20": "I-department",
|
| 36 |
+
"21": "B-person",
|
| 37 |
+
"22": "I-person"
|
| 38 |
+
},
|
| 39 |
+
"initializer_range": 0.02,
|
| 40 |
+
"intermediate_size": 3072,
|
| 41 |
+
"is_decoder": false,
|
| 42 |
+
"label2id": {
|
| 43 |
+
"B-city": 5,
|
| 44 |
+
"B-country": 7,
|
| 45 |
+
"B-department": 19,
|
| 46 |
+
"B-email": 13,
|
| 47 |
+
"B-fax": 11,
|
| 48 |
+
"B-location_label": 17,
|
| 49 |
+
"B-opening_hours": 15,
|
| 50 |
+
"B-person": 21,
|
| 51 |
+
"B-phone": 9,
|
| 52 |
+
"B-plz": 3,
|
| 53 |
+
"B-street": 1,
|
| 54 |
+
"I-city": 6,
|
| 55 |
+
"I-country": 8,
|
| 56 |
+
"I-department": 20,
|
| 57 |
+
"I-email": 14,
|
| 58 |
+
"I-fax": 12,
|
| 59 |
+
"I-location_label": 18,
|
| 60 |
+
"I-opening_hours": 16,
|
| 61 |
+
"I-person": 22,
|
| 62 |
+
"I-phone": 10,
|
| 63 |
+
"I-plz": 4,
|
| 64 |
+
"I-street": 2,
|
| 65 |
+
"O": 0
|
| 66 |
+
},
|
| 67 |
+
"layer_norm_eps": 1e-12,
|
| 68 |
+
"max_position_embeddings": 512,
|
| 69 |
+
"model_type": "bert",
|
| 70 |
+
"num_attention_heads": 12,
|
| 71 |
+
"num_hidden_layers": 12,
|
| 72 |
+
"pad_token_id": 0,
|
| 73 |
+
"tie_word_embeddings": true,
|
| 74 |
+
"transformers_version": "5.16.1",
|
| 75 |
+
"type_vocab_size": 2,
|
| 76 |
+
"use_cache": true,
|
| 77 |
+
"vocab_size": 31102
|
| 78 |
+
}
|
impressum.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"name": "gbert_ner", "hf_id": "deepset/gbert-base", "max_len": 512, "stride": 128, "fields": ["street", "plz", "city", "country", "phone", "fax", "email", "opening_hours", "location_label", "department", "person"]}
|
model.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:66f501c8644499d84d80e2848c6843f02b3f08a56ceada192a4f0256c4fccb36
|
| 3 |
+
size 437442444
|
tokenizer.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
tokenizer_config.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"backend": "tokenizers",
|
| 3 |
+
"cls_token": "[CLS]",
|
| 4 |
+
"do_lower_case": false,
|
| 5 |
+
"is_local": false,
|
| 6 |
+
"local_files_only": false,
|
| 7 |
+
"mask_token": "[MASK]",
|
| 8 |
+
"max_len": 512,
|
| 9 |
+
"model_max_length": 512,
|
| 10 |
+
"pad_token": "[PAD]",
|
| 11 |
+
"sep_token": "[SEP]",
|
| 12 |
+
"strip_accents": false,
|
| 13 |
+
"tokenize_chinese_chars": true,
|
| 14 |
+
"tokenizer_class": "BertTokenizer",
|
| 15 |
+
"unk_token": "[UNK]"
|
| 16 |
+
}
|