temsa commited on
Commit
6631226
·
verified ·
1 Parent(s): 3bc044c

Publish rc15 release

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +0 -30
  2. .gitignore +3 -0
  3. LICENSE +73 -0
  4. NOTICE +13 -0
  5. PORTFOLIO_COMPARISON.md +77 -0
  6. README.md +182 -0
  7. common.py +2142 -0
  8. config.json +318 -0
  9. eval/benchmark_summary.json +215 -0
  10. eval/benchmark_summary.md +25 -0
  11. eval/full_diffmask_fresh_holdout_v1.json +85 -0
  12. eval/full_diffmask_gap_uat_exact_v1.json +53 -0
  13. eval/full_globalpointer_context_redteam_v1.json +109 -0
  14. eval/full_globalpointer_context_redteam_v2.json +69 -0
  15. eval/full_globalpointer_context_redteam_v3.json +77 -0
  16. eval/full_globalpointer_context_redteam_v4.json +101 -0
  17. eval/full_globalpointer_context_redteam_v5.json +100 -0
  18. eval/full_globalpointer_context_redteam_v6.json +100 -0
  19. eval/full_globalpointer_context_redteam_v7.json +100 -0
  20. eval/full_globalpointer_context_redteam_v8.json +100 -0
  21. eval/full_globalpointer_demographic_patch_v2_test.json +108 -0
  22. eval/full_globalpointer_location_coverage_v1.json +61 -0
  23. eval/full_globalpointer_location_coverage_v2.json +61 -0
  24. eval/full_globalpointer_location_coverage_v3.json +61 -0
  25. eval/full_irish_core_pii_v1.json +108 -0
  26. eval/full_irish_dllm_hardening_exact_v1.json +101 -0
  27. eval/full_irish_extended_pii_v1.json +108 -0
  28. eval/full_irish_gov_chatbot_gap_holdout_v1.json +258 -0
  29. eval/full_irish_gov_chatbot_gap_holdout_v2.json +92 -0
  30. eval/full_irish_gov_chatbot_redteam_assistant_v2.json +84 -0
  31. eval/full_irish_gov_chatbot_redteam_user_v2.json +108 -0
  32. eval/full_irish_gov_chatbot_redteam_v1.json +362 -0
  33. eval/full_irish_gov_chatbot_redteam_v2.json +108 -0
  34. eval/full_irish_gov_contact_policy_v1.json +76 -0
  35. eval/full_irish_numeric_qafix_v2.json +45 -0
  36. eval/full_irish_ppsn_phone_edge_v1.json +37 -0
  37. eval/full_irish_remaining_gaps_v2.json +36 -0
  38. eval/full_multilingual_ppsn_v1_all.json +28 -0
  39. eval/full_runtime_profile_source.json +29 -0
  40. eval/label_inventory.json +20 -0
  41. eval/q8_diffmask_fresh_holdout_v1.json +85 -0
  42. eval/q8_diffmask_gap_uat_exact_v1.json +53 -0
  43. eval/q8_globalpointer_context_redteam_v1.json +109 -0
  44. eval/q8_globalpointer_context_redteam_v2.json +69 -0
  45. eval/q8_globalpointer_context_redteam_v3.json +77 -0
  46. eval/q8_globalpointer_context_redteam_v4.json +101 -0
  47. eval/q8_globalpointer_context_redteam_v5.json +100 -0
  48. eval/q8_globalpointer_context_redteam_v6.json +100 -0
  49. eval/q8_globalpointer_context_redteam_v7.json +100 -0
  50. eval/q8_globalpointer_context_redteam_v8.json +100 -0
.gitattributes CHANGED
@@ -1,35 +1,5 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
  *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
  *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
  *.pt filter=lfs diff=lfs merge=lfs -text
23
  *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
  *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz 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
 
 
 
1
  *.bin filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
2
  *.onnx filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
3
  *.pt filter=lfs diff=lfs merge=lfs -text
4
  *.pth filter=lfs diff=lfs merge=lfs -text
 
5
  *.safetensors filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
.gitignore ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ __pycache__/
2
+ *.pyc
3
+ .venv/
LICENSE ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
10
+
11
+ "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
12
+
13
+ "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
14
+
15
+ "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
16
+
17
+ "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
18
+
19
+ "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
20
+
21
+ "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
22
+
23
+ "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
24
+
25
+ "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
26
+
27
+ "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
28
+
29
+ 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
30
+
31
+ 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
32
+
33
+ 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
34
+
35
+ (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
36
+
37
+ (b) You must cause any modified files to carry prominent notices stating that You changed the files; and
38
+
39
+ (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
40
+
41
+ (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
42
+
43
+ You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
44
+
45
+ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
46
+
47
+ 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
48
+
49
+ 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
50
+
51
+ 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
52
+
53
+ 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
54
+
55
+ END OF TERMS AND CONDITIONS
56
+
57
+ APPENDIX: How to apply the Apache License to your work.
58
+
59
+ To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
60
+
61
+ Copyright [yyyy] [name of copyright owner]
62
+
63
+ Licensed under the Apache License, Version 2.0 (the "License");
64
+ you may not use this file except in compliance with the License.
65
+ You may obtain a copy of the License at
66
+
67
+ http://www.apache.org/licenses/LICENSE-2.0
68
+
69
+ Unless required by applicable law or agreed to in writing, software
70
+ distributed under the License is distributed on an "AS IS" BASIS,
71
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
72
+ See the License for the specific language governing permissions and
73
+ limitations under the License.
NOTICE ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ IrishCore-GlobalPointer-ContextPII-135M-v1-rc15
2
+
3
+ This release is derived from:
4
+ - OpenMed/OpenMed-PII-mLiteClinical-Base-135M-v1 (Apache-2.0)
5
+
6
+ Training and evaluation data used for this derivative included:
7
+ - temsa/OpenMed-Irish-CorePII-TrainMix-v1
8
+ - temsa/OpenMed-Irish-PPSN-Eircode-Spec-v1
9
+ - joelniklaus/mapa (CC-BY-4.0)
10
+ - gretelai/synthetic_pii_finance_multilingual (Apache-2.0)
11
+
12
+ Additional local synthetic hardening, UAT replay, and holdout sets were used during model selection.
13
+ Please review upstream licenses and dataset cards before redistributing derivative datasets.
PORTFOLIO_COMPARISON.md ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Portfolio Comparison
2
+
3
+ Updated: `2026-03-15`.
4
+
5
+ Use this section for the fastest public comparison across the `temsa` PII masking portfolio.
6
+
7
+ - The first core table only includes public checkpoints that ship both comparable q8 accuracy and q8 CPU throughput.
8
+ - The first PPSN table only includes public artifacts that ship comparable PPSN accuracy and CPU throughput.
9
+ - Missing cells in the archive tables mean the older release did not ship that metric in its public bundle.
10
+ - DiffMask rows use the reconciled `clean_single_pass` harness that matches the deployed runtime.
11
+ - GlobalPointer rows use the public raw-only span-matrix release bundle and its packaged q8 ONNX artifact.
12
+ - The same content is shipped as `PORTFOLIO_COMPARISON.md` inside each public model repo.
13
+
14
+ ### Irish Core PII: Comparable Public Checkpoints
15
+
16
+ | Repo | Stack | Full Core F1 | Q8 Core F1 | Q8 Multilingual PPSN F1 | Q8 Core ex/s |
17
+ |---|---|---:|---:|---:|---:|
18
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc15`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc15) | GlobalPointer raw-only + context labels | 1.0000 | 1.0000 | 0.9333 | 125.5 |
19
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc14`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc14) | GlobalPointer raw-only + context labels | 1.0000 | 1.0000 | 0.9333 | 119.2 |
20
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc13`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc13) | GlobalPointer raw-only + context labels | 1.0000 | 1.0000 | 0.9333 | 126.1 |
21
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc12`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc12) | GlobalPointer raw-only + context labels | 1.0000 | 1.0000 | 0.9333 | 73.6 |
22
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc11`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc11) | GlobalPointer raw-only + context labels | 1.0000 | 1.0000 | 0.9333 | 94.1 |
23
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc10`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc10) | GlobalPointer raw-only + context labels | 1.0000 | 1.0000 | 0.9333 | 125.8 |
24
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc9`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc9) | GlobalPointer raw-only + context labels | 1.0000 | 1.0000 | 0.9333 | 119.8 |
25
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc8`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc8) | GlobalPointer raw-only + context labels | 1.0000 | 1.0000 | 0.9333 | 128.9 |
26
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc7`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc7) | GlobalPointer raw-only + context labels | 1.0000 | 1.0000 | 0.9333 | 89.0 |
27
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc6`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc6) | GlobalPointer raw-only + context labels | 1.0000 | 1.0000 | 0.9333 | 89.0 |
28
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc5`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc5) | GlobalPointer raw-only + context labels | 1.0000 | 1.0000 | 0.9333 | 84.5 |
29
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc4`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc4) | GlobalPointer raw-only + context labels | 0.9935 | 0.9935 | 0.9333 | 61.5 |
30
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc3`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc3) | GlobalPointer raw-only + context labels | 0.9935 | 0.9935 | 0.9333 | 61.5 |
31
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc2`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc2) | GlobalPointer raw-only + context labels | 0.9935 | 0.9935 | 0.9222 | 61.5 |
32
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc1`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc1) | GlobalPointer raw-only + context labels | 0.9935 | 0.9935 | 0.9222 | 61.5 |
33
+ | [`temsa/IrishCore-GlobalPointer-135M-v1-rc4`](https://huggingface.co/temsa/IrishCore-GlobalPointer-135M-v1-rc4) | GlobalPointer raw-only span-matrix | 1.0000 | 1.0000 | 0.9333 | 221.6 |
34
+ | [`temsa/IrishCore-GlobalPointer-135M-v1-rc3`](https://huggingface.co/temsa/IrishCore-GlobalPointer-135M-v1-rc3) | GlobalPointer raw-only span-matrix | 1.0000 | 1.0000 | 0.9213 | 204.9 |
35
+ | [`temsa/IrishCore-GlobalPointer-135M-v1-rc2`](https://huggingface.co/temsa/IrishCore-GlobalPointer-135M-v1-rc2) | GlobalPointer raw-only span-matrix | 0.9934 | 0.9934 | 0.9326 | 231.2 |
36
+ | [`temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc8`](https://huggingface.co/temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc8) | Raw-only token-span | 0.9737 | 0.9737 | 0.9176 | 46.1 |
37
+ | [`temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc7`](https://huggingface.co/temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc7) | Hybrid classifier + generated scanner spec | 1.0000 | 0.9934 | 1.0000 | 30.0 |
38
+ | [`temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc6`](https://huggingface.co/temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc6) | Hybrid classifier + repair decoders | 1.0000 | 0.9934 | 1.0000 | 29.5 |
39
+ | [`temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc5`](https://huggingface.co/temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc5) | Hybrid classifier + repair decoders | 0.9737 | 0.9669 | 0.9333 | 34.4 |
40
+ | [`temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc4`](https://huggingface.co/temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc4) | Hybrid classifier + repair decoders | 0.9870 | 0.9740 | 0.9600 | 114.2 |
41
+ | [`temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc3`](https://huggingface.co/temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc3) | Hybrid classifier + repair decoders | 0.9806 | 0.9677 | 0.9333 | 44.9 |
42
+ | [`temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc2`](https://huggingface.co/temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc2) | Hybrid classifier + repair decoders | 0.9554 | 0.9615 | 0.7887 | 119.1 |
43
+ | [`temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v1`](https://huggingface.co/temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v1) | Hybrid classifier baseline | 0.9530 | 0.9333 | 0.9882 | 103.3 |
44
+ | [`temsa/IrishCore-DiffMask-135M-v1-rc6`](https://huggingface.co/temsa/IrishCore-DiffMask-135M-v1-rc6) | DiffMask token-span, scanner-free | 0.9801 | 0.9733 | 0.9274 | 130.3 |
45
+ | [`temsa/IrishCore-DiffMask-135M-v1-rc5`](https://huggingface.co/temsa/IrishCore-DiffMask-135M-v1-rc5) | DiffMask token-span, scanner-free | 0.9733 | 0.9733 | 0.9379 | 249.2 |
46
+ | [`temsa/IrishCore-DiffMask-135M-v1-rc4`](https://huggingface.co/temsa/IrishCore-DiffMask-135M-v1-rc4) | DiffMask token-span, scanner-free | 0.9733 | 0.9733 | 0.9371 | 29.5 |
47
+ | [`temsa/IrishCore-DiffMask-135M-v1-rc3`](https://huggingface.co/temsa/IrishCore-DiffMask-135M-v1-rc3) | DiffMask token-span, scanner-free | 0.9664 | 0.9664 | 0.9591 | 30.0 |
48
+ | [`temsa/IrishCore-DiffMask-135M-v1-rc2`](https://huggingface.co/temsa/IrishCore-DiffMask-135M-v1-rc2) | DiffMask token-span, scanner-free | 0.9664 | 0.9664 | 0.9212 | 247.1 |
49
+ | [`temsa/IrishCore-DiffMask-135M-v1-rc1`](https://huggingface.co/temsa/IrishCore-DiffMask-135M-v1-rc1) | DiffMask token-span, scanner-free | 0.9801 | 0.9934 | 0.9412 | 251.2 |
50
+
51
+ ### Irish Core PII: Other Public Checkpoints
52
+
53
+ | Repo | Stack | Full Core F1 | Q8 Core F1 | Q8 Multilingual PPSN F1 | Notes |
54
+ |---|---|---:|---:|---:|---|
55
+ | [`temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc1`](https://huggingface.co/temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc1) | Hybrid classifier prototype | 0.9487 | — | — | Predates the public q8 artifact. |
56
+
57
+ Finance-boundary q8 F1 is `1.0000` for `OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc6`, `OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc7`, `OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc8`, and all public `IrishCore-DiffMask` releases from `rc1` to `rc6`. `OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc5` ships `0.8750` on that public q8 suite.
58
+
59
+ ### PPSN-Only: Comparable Public Artifacts
60
+
61
+ | Repo | Artifact | Irish Large F1 | Multilingual PPSN F1 | User Raw F1 | QA v8 F1 | CPU ex/s |
62
+ |---|---|---:|---:|---:|---:|---:|
63
+ | [`temsa/OpenMed-mLiteClinical-IrishPPSN-135M-v1`](https://huggingface.co/temsa/OpenMed-mLiteClinical-IrishPPSN-135M-v1) | fp32 canonical checkpoint | 0.8979 | 0.9704 | 0.8000 | 0.7385 | 57.4 |
64
+ | [`temsa/OpenMed-mLiteClinical-IrishPPSN-135M-v1-fp16`](https://huggingface.co/temsa/OpenMed-mLiteClinical-IrishPPSN-135M-v1-fp16) | fp16 CPU/GPU artifact | — | 0.9704 | 0.8000 | 0.7385 | 45.8 |
65
+ | [`temsa/OpenMed-mLiteClinical-IrishPPSN-135M-v1-q8`](https://huggingface.co/temsa/OpenMed-mLiteClinical-IrishPPSN-135M-v1-q8) | dynamic int8 CPU artifact | — | 0.9040 | — | — | 132.1 |
66
+
67
+ ### PPSN-Only: Historical Public Checkpoints
68
+
69
+ | Repo | Main Published Metrics | Notes |
70
+ |---|---|---|
71
+ | [`temsa/OpenMed-PPSN-mLiteClinical-v1`](https://huggingface.co/temsa/OpenMed-PPSN-mLiteClinical-v1) | same as canonical fp32 repo: multilingual 0.9704, user raw 0.8000 | Legacy alias; prefer `temsa/OpenMed-mLiteClinical-IrishPPSN-135M-v1`. |
72
+ | [`temsa/OpenMed-PPSN-v6-raw-rc2`](https://huggingface.co/temsa/OpenMed-PPSN-v6-raw-rc2) | irish_reg_v5 0.8750; user_raw 0.8000; qa_v8 0.7385 | Raw PPSN-only research checkpoint; no packaged multilingual CPU benchmark row. |
73
+ | [`temsa/OpenMed-PPSN-v5_1`](https://huggingface.co/temsa/OpenMed-PPSN-v5_1) | irish_large_v2 raw 0.9285; qa_v6 hybrid strict 1.0000 | Hybrid PPSN-only checkpoint; predates the canonical multilingual suite packaging. |
74
+ | [`temsa/OpenMed-PPSN-v5`](https://huggingface.co/temsa/OpenMed-PPSN-v5) | irish_reg_v5 raw 0.8235; irish_reg_v5 hybrid strict 1.0000 | Hybrid PPSN-only checkpoint; predates the canonical multilingual suite packaging. |
75
+ | [`temsa/OpenMed-PPSN-v4`](https://huggingface.co/temsa/OpenMed-PPSN-v4) | synthetic non-PPSN drift check only | Predates the current PPSN eval suite; no packaged apples-to-apples multilingual CPU row. |
76
+
77
+ If you need the strongest current raw-only Irish core model, start with `IrishCore-GlobalPointer-135M-v1-rc4`. If you need the fastest CPU-first raw-only line, compare it against `IrishCore-DiffMask-135M-v1-rc6`. If you need a PPSN-only artifact, compare the canonical `fp32`, `fp16`, and `q8` variants of `OpenMed-mLiteClinical-IrishPPSN-135M-v1` directly in the table above.
README.md ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language:
3
+ - en
4
+ - ga
5
+ license: apache-2.0
6
+ pipeline_tag: token-classification
7
+ tags:
8
+ - pii-masking
9
+ - token-classification
10
+ - globalpointer
11
+ - onnx
12
+ - dynamic-quantization
13
+ - ireland
14
+ - irish
15
+ - gaelic
16
+ ---
17
+ # IrishCore-GlobalPointer-ContextPII-135M-v1-rc15
18
+
19
+ `IrishCore-GlobalPointer-ContextPII-135M-v1-rc15` is the current expanded-label raw-only PII masking release for Irish public-sector, HSE, and citizen-support flows.
20
+
21
+ It keeps the same DistilBERT-size GlobalPointer span extractor family as `temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc14`, but ships a stronger bundled decoder for contextual Irish/English address, location, and name recovery while preserving the broader contextual masking behavior from rc14.
22
+
23
+ Context labels served by this line:
24
+
25
+ - `STREET_ADDRESS`
26
+ - `CITY`
27
+ - `COUNTY`
28
+ - `DATE_OF_BIRTH`
29
+ - `AGE`
30
+
31
+ Core labels retained:
32
+
33
+ - `PPSN`
34
+ - `POSTCODE`
35
+ - `PHONE_NUMBER`
36
+ - `EMAIL`
37
+ - `PASSPORT_NUMBER`
38
+ - `ACCOUNT_NUMBER`
39
+ - `BANK_ROUTING_NUMBER`
40
+ - `SWIFT_BIC`
41
+ - `CREDIT_DEBIT_CARD`
42
+ - `FIRST_NAME`
43
+ - `LAST_NAME`
44
+
45
+ ## Positioning
46
+
47
+ `rc15` is a decoder-hardening release over `rc14`.
48
+
49
+ - weights unchanged
50
+ - ONNX graph unchanged
51
+ - no external scanner or validator added
52
+ - deployment path still single-pass span extraction plus deterministic `[PII:LABEL]` replacement
53
+
54
+ What changed in `rc15`:
55
+
56
+ - lenited Gaelic address cues now recover full unit-plus-street spans like `Árasán 4, Cedar Court`
57
+ - city recovery now handles city-before-county cases such as `Clonakilty, Co. Cork` and `Kildare Town, Co. Kildare`
58
+ - county recovery now accepts generic `Co.` forms while avoiding the earlier `Contae na Mí` regression from field-style rescue
59
+ - the decoder now recovers business-centre style address blocks like `Unit 5, Riverpark Business Centre`
60
+ - structured-cue name recovery now handles prose forms like `Anne-Marie O'Connor-Smyth, PPSN ...`
61
+ - `globalpointer_context_redteam_v8` is `1.0000` at both IoU 0.5 and exact-boundary matching on full and q8 paths while `globalpointer_context_redteam_v7` remains `1.0000`
62
+
63
+ If you only need the narrower Irish-core structured label set and want maximum CPU throughput, `temsa/IrishCore-GlobalPointer-135M-v1-rc4` remains the faster option.
64
+
65
+ ## Benchmarks
66
+
67
+ ### ONNX q8
68
+
69
+ | Suite | F1 | Examples/s |
70
+ | --- | ---: | ---: |
71
+ | Irish core | 1.0000 | 125.5054 |
72
+ | Gov contact policy v1 | 1.0000 | 74.3676 |
73
+ | Gov chatbot red-team v2 | 0.9861 | 74.9871 |
74
+ | Context red-team v8 | 1.0000 | 102.1626 |
75
+ | Context red-team v7 | 1.0000 | 115.8655 |
76
+ | Multilingual PPSN overall | 0.9333 | 120.6708 |
77
+ | Multilingual PPSN label-only | 1.0000 | — |
78
+ | Multilingual PPSN label-only | 1.0000 | — |
79
+
80
+ ### Comparison
81
+
82
+ | Model | Core F1 | Gov Contact Policy v1 F1 | Context Red-team v8 F1 | Multilingual F1 | Core examples/s |
83
+ | --- | ---: | ---: | ---: | ---: | ---: |
84
+ | ContextPII rc15 q8 | 1.0000 | 1.0000 | 1.0000 | 0.9333 | 125.5054 |
85
+ | ContextPII rc14 q8 | 1.0000 | 1.0000 | — | 0.9333 | 119.2240 |
86
+ | ContextPII rc13 q8 | 1.0000 | 1.0000 | — | 0.9333 | 126.0878 |
87
+
88
+ ## Evaluation Notes
89
+
90
+ Additional q8 release checks shipped in this repo:
91
+
92
+ - `eval/q8_globalpointer_context_redteam_v8.json`: contextual regression suite for lenited Gaelic address cues, business-centre address blocks, generic city/county field cues, city-before-county recovery, and structured-cue hyphenated names, `1.0000` F1 in `rc15`
93
+ - `eval/q8_globalpointer_context_redteam_v7.json`: contextual regression suite for generic county forms inside Irish address blocks, retained at `1.0000` F1 in `rc15`
94
+ - `eval/q8_globalpointer_context_redteam_v6.json`: contextual regression suite for address cue variants, hyphenated DOBs, first-person bare age statements, role-cued lowercase names, and surname fields, retained from `rc12`
95
+ - `eval/q8_globalpointer_context_redteam_v5.json`: contextual regression suite for slash-separated phones and 1-digit dotted/slashed DOB formats, retained from `rc11`
96
+ - `eval/q8_globalpointer_location_coverage_v1.json`, `v2`, `v3`: Irish location coverage suites retained from `rc9`
97
+
98
+ ## Usage
99
+
100
+ ```bash
101
+ python3 inference_mask_onnx.py --model temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc15 --text "My surname is de Búrca, my PPSN is 1234567T, and my address is Árasán 4, Cedar Court, mBaile Átha Cliath, D08 XY12."
102
+ ```
103
+
104
+ <!-- portfolio-comparison:start -->
105
+ ## Portfolio Comparison
106
+
107
+ Updated: `2026-03-15`.
108
+
109
+ Use this section for the fastest public comparison across the `temsa` PII masking portfolio.
110
+
111
+ - The first core table only includes public checkpoints that ship both comparable q8 accuracy and q8 CPU throughput.
112
+ - The first PPSN table only includes public artifacts that ship comparable PPSN accuracy and CPU throughput.
113
+ - Missing cells in the archive tables mean the older release did not ship that metric in its public bundle.
114
+ - DiffMask rows use the reconciled `clean_single_pass` harness that matches the deployed runtime.
115
+ - GlobalPointer rows use the public raw-only span-matrix release bundle and its packaged q8 ONNX artifact.
116
+ - The same content is shipped as `PORTFOLIO_COMPARISON.md` inside each public model repo.
117
+
118
+ ### Irish Core PII: Comparable Public Checkpoints
119
+
120
+ | Repo | Stack | Full Core F1 | Q8 Core F1 | Q8 Multilingual PPSN F1 | Q8 Core ex/s |
121
+ |---|---|---:|---:|---:|---:|
122
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc15`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc15) | GlobalPointer raw-only + context labels | 1.0000 | 1.0000 | 0.9333 | 125.5 |
123
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc14`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc14) | GlobalPointer raw-only + context labels | 1.0000 | 1.0000 | 0.9333 | 119.2 |
124
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc13`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc13) | GlobalPointer raw-only + context labels | 1.0000 | 1.0000 | 0.9333 | 126.1 |
125
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc12`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc12) | GlobalPointer raw-only + context labels | 1.0000 | 1.0000 | 0.9333 | 73.6 |
126
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc11`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc11) | GlobalPointer raw-only + context labels | 1.0000 | 1.0000 | 0.9333 | 94.1 |
127
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc10`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc10) | GlobalPointer raw-only + context labels | 1.0000 | 1.0000 | 0.9333 | 125.8 |
128
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc9`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc9) | GlobalPointer raw-only + context labels | 1.0000 | 1.0000 | 0.9333 | 119.8 |
129
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc8`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc8) | GlobalPointer raw-only + context labels | 1.0000 | 1.0000 | 0.9333 | 128.9 |
130
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc7`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc7) | GlobalPointer raw-only + context labels | 1.0000 | 1.0000 | 0.9333 | 89.0 |
131
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc6`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc6) | GlobalPointer raw-only + context labels | 1.0000 | 1.0000 | 0.9333 | 89.0 |
132
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc5`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc5) | GlobalPointer raw-only + context labels | 1.0000 | 1.0000 | 0.9333 | 84.5 |
133
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc4`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc4) | GlobalPointer raw-only + context labels | 0.9935 | 0.9935 | 0.9333 | 61.5 |
134
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc3`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc3) | GlobalPointer raw-only + context labels | 0.9935 | 0.9935 | 0.9333 | 61.5 |
135
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc2`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc2) | GlobalPointer raw-only + context labels | 0.9935 | 0.9935 | 0.9222 | 61.5 |
136
+ | [`temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc1`](https://huggingface.co/temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc1) | GlobalPointer raw-only + context labels | 0.9935 | 0.9935 | 0.9222 | 61.5 |
137
+ | [`temsa/IrishCore-GlobalPointer-135M-v1-rc4`](https://huggingface.co/temsa/IrishCore-GlobalPointer-135M-v1-rc4) | GlobalPointer raw-only span-matrix | 1.0000 | 1.0000 | 0.9333 | 221.6 |
138
+ | [`temsa/IrishCore-GlobalPointer-135M-v1-rc3`](https://huggingface.co/temsa/IrishCore-GlobalPointer-135M-v1-rc3) | GlobalPointer raw-only span-matrix | 1.0000 | 1.0000 | 0.9213 | 204.9 |
139
+ | [`temsa/IrishCore-GlobalPointer-135M-v1-rc2`](https://huggingface.co/temsa/IrishCore-GlobalPointer-135M-v1-rc2) | GlobalPointer raw-only span-matrix | 0.9934 | 0.9934 | 0.9326 | 231.2 |
140
+ | [`temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc8`](https://huggingface.co/temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc8) | Raw-only token-span | 0.9737 | 0.9737 | 0.9176 | 46.1 |
141
+ | [`temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc7`](https://huggingface.co/temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc7) | Hybrid classifier + generated scanner spec | 1.0000 | 0.9934 | 1.0000 | 30.0 |
142
+ | [`temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc6`](https://huggingface.co/temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc6) | Hybrid classifier + repair decoders | 1.0000 | 0.9934 | 1.0000 | 29.5 |
143
+ | [`temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc5`](https://huggingface.co/temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc5) | Hybrid classifier + repair decoders | 0.9737 | 0.9669 | 0.9333 | 34.4 |
144
+ | [`temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc4`](https://huggingface.co/temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc4) | Hybrid classifier + repair decoders | 0.9870 | 0.9740 | 0.9600 | 114.2 |
145
+ | [`temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc3`](https://huggingface.co/temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc3) | Hybrid classifier + repair decoders | 0.9806 | 0.9677 | 0.9333 | 44.9 |
146
+ | [`temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc2`](https://huggingface.co/temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc2) | Hybrid classifier + repair decoders | 0.9554 | 0.9615 | 0.7887 | 119.1 |
147
+ | [`temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v1`](https://huggingface.co/temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v1) | Hybrid classifier baseline | 0.9530 | 0.9333 | 0.9882 | 103.3 |
148
+ | [`temsa/IrishCore-DiffMask-135M-v1-rc6`](https://huggingface.co/temsa/IrishCore-DiffMask-135M-v1-rc6) | DiffMask token-span, scanner-free | 0.9801 | 0.9733 | 0.9274 | 130.3 |
149
+ | [`temsa/IrishCore-DiffMask-135M-v1-rc5`](https://huggingface.co/temsa/IrishCore-DiffMask-135M-v1-rc5) | DiffMask token-span, scanner-free | 0.9733 | 0.9733 | 0.9379 | 249.2 |
150
+ | [`temsa/IrishCore-DiffMask-135M-v1-rc4`](https://huggingface.co/temsa/IrishCore-DiffMask-135M-v1-rc4) | DiffMask token-span, scanner-free | 0.9733 | 0.9733 | 0.9371 | 29.5 |
151
+ | [`temsa/IrishCore-DiffMask-135M-v1-rc3`](https://huggingface.co/temsa/IrishCore-DiffMask-135M-v1-rc3) | DiffMask token-span, scanner-free | 0.9664 | 0.9664 | 0.9591 | 30.0 |
152
+ | [`temsa/IrishCore-DiffMask-135M-v1-rc2`](https://huggingface.co/temsa/IrishCore-DiffMask-135M-v1-rc2) | DiffMask token-span, scanner-free | 0.9664 | 0.9664 | 0.9212 | 247.1 |
153
+ | [`temsa/IrishCore-DiffMask-135M-v1-rc1`](https://huggingface.co/temsa/IrishCore-DiffMask-135M-v1-rc1) | DiffMask token-span, scanner-free | 0.9801 | 0.9934 | 0.9412 | 251.2 |
154
+
155
+ ### Irish Core PII: Other Public Checkpoints
156
+
157
+ | Repo | Stack | Full Core F1 | Q8 Core F1 | Q8 Multilingual PPSN F1 | Notes |
158
+ |---|---|---:|---:|---:|---|
159
+ | [`temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc1`](https://huggingface.co/temsa/OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc1) | Hybrid classifier prototype | 0.9487 | — | — | Predates the public q8 artifact. |
160
+
161
+ Finance-boundary q8 F1 is `1.0000` for `OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc6`, `OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc7`, `OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc8`, and all public `IrishCore-DiffMask` releases from `rc1` to `rc6`. `OpenMed-mLiteClinical-IrishCorePII-135M-v2-rc5` ships `0.8750` on that public q8 suite.
162
+
163
+ ### PPSN-Only: Comparable Public Artifacts
164
+
165
+ | Repo | Artifact | Irish Large F1 | Multilingual PPSN F1 | User Raw F1 | QA v8 F1 | CPU ex/s |
166
+ |---|---|---:|---:|---:|---:|---:|
167
+ | [`temsa/OpenMed-mLiteClinical-IrishPPSN-135M-v1`](https://huggingface.co/temsa/OpenMed-mLiteClinical-IrishPPSN-135M-v1) | fp32 canonical checkpoint | 0.8979 | 0.9704 | 0.8000 | 0.7385 | 57.4 |
168
+ | [`temsa/OpenMed-mLiteClinical-IrishPPSN-135M-v1-fp16`](https://huggingface.co/temsa/OpenMed-mLiteClinical-IrishPPSN-135M-v1-fp16) | fp16 CPU/GPU artifact | — | 0.9704 | 0.8000 | 0.7385 | 45.8 |
169
+ | [`temsa/OpenMed-mLiteClinical-IrishPPSN-135M-v1-q8`](https://huggingface.co/temsa/OpenMed-mLiteClinical-IrishPPSN-135M-v1-q8) | dynamic int8 CPU artifact | — | 0.9040 | — | — | 132.1 |
170
+
171
+ ### PPSN-Only: Historical Public Checkpoints
172
+
173
+ | Repo | Main Published Metrics | Notes |
174
+ |---|---|---|
175
+ | [`temsa/OpenMed-PPSN-mLiteClinical-v1`](https://huggingface.co/temsa/OpenMed-PPSN-mLiteClinical-v1) | same as canonical fp32 repo: multilingual 0.9704, user raw 0.8000 | Legacy alias; prefer `temsa/OpenMed-mLiteClinical-IrishPPSN-135M-v1`. |
176
+ | [`temsa/OpenMed-PPSN-v6-raw-rc2`](https://huggingface.co/temsa/OpenMed-PPSN-v6-raw-rc2) | irish_reg_v5 0.8750; user_raw 0.8000; qa_v8 0.7385 | Raw PPSN-only research checkpoint; no packaged multilingual CPU benchmark row. |
177
+ | [`temsa/OpenMed-PPSN-v5_1`](https://huggingface.co/temsa/OpenMed-PPSN-v5_1) | irish_large_v2 raw 0.9285; qa_v6 hybrid strict 1.0000 | Hybrid PPSN-only checkpoint; predates the canonical multilingual suite packaging. |
178
+ | [`temsa/OpenMed-PPSN-v5`](https://huggingface.co/temsa/OpenMed-PPSN-v5) | irish_reg_v5 raw 0.8235; irish_reg_v5 hybrid strict 1.0000 | Hybrid PPSN-only checkpoint; predates the canonical multilingual suite packaging. |
179
+ | [`temsa/OpenMed-PPSN-v4`](https://huggingface.co/temsa/OpenMed-PPSN-v4) | synthetic non-PPSN drift check only | Predates the current PPSN eval suite; no packaged apples-to-apples multilingual CPU row. |
180
+
181
+ If you need the strongest current raw-only Irish core model, start with `IrishCore-GlobalPointer-135M-v1-rc4`. If you need the fastest CPU-first raw-only line, compare it against `IrishCore-DiffMask-135M-v1-rc6`. If you need a PPSN-only artifact, compare the canonical `fp32`, `fp16`, and `q8` variants of `OpenMed-mLiteClinical-IrishPPSN-135M-v1` directly in the table above.
182
+ <!-- portfolio-comparison:end -->
common.py ADDED
@@ -0,0 +1,2142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ from __future__ import annotations
3
+
4
+ import math
5
+ import re
6
+ from pathlib import Path
7
+ import sys
8
+ from typing import Any
9
+ import unicodedata
10
+
11
+ import numpy as np
12
+
13
+ ROOT_DIR = Path(__file__).resolve().parents[2]
14
+ if str(ROOT_DIR) not in sys.path:
15
+ sys.path.insert(0, str(ROOT_DIR))
16
+
17
+ try:
18
+ from ..irish_core_span_raw_only.common import (
19
+ dedupe_spans,
20
+ label_max_span_tokens_from_config,
21
+ label_min_nonspace_chars_from_config,
22
+ label_names_from_config,
23
+ load_onnx_session,
24
+ normalize_entity_name,
25
+ safe_auto_tokenizer,
26
+ )
27
+ except ImportError:
28
+ from experiments.irish_core_span_raw_only.common import (
29
+ dedupe_spans,
30
+ label_max_span_tokens_from_config,
31
+ label_min_nonspace_chars_from_config,
32
+ label_names_from_config,
33
+ load_onnx_session,
34
+ normalize_entity_name,
35
+ safe_auto_tokenizer,
36
+ )
37
+
38
+
39
+ def label_thresholds_from_config(config, default_threshold: float) -> dict[str, float]:
40
+ raw = getattr(config, "span_label_thresholds", None) or {}
41
+ out = {normalize_entity_name(key): float(value) for key, value in raw.items()}
42
+ for label in label_names_from_config(config):
43
+ out.setdefault(label, float(default_threshold))
44
+ return out
45
+
46
+
47
+ def valid_offset(offset: tuple[int, int]) -> bool:
48
+ return bool(offset) and int(offset[1]) > int(offset[0])
49
+
50
+
51
+ def nonspace_length(text: str, start: int, end: int) -> int:
52
+ return sum(0 if ch.isspace() else 1 for ch in text[int(start) : int(end)])
53
+
54
+
55
+ def alnum_upper(text: str) -> str:
56
+ return "".join(ch for ch in text.upper() if ch.isalnum())
57
+
58
+
59
+ def normalize_surface(text: str) -> str:
60
+ value = unicodedata.normalize("NFKD", text)
61
+ value = "".join(ch for ch in value if not unicodedata.combining(ch))
62
+ value = value.replace("\u00A0", " ").replace("\u202F", " ")
63
+ value = re.sub(r"\s+", " ", value.strip().lower())
64
+ return value
65
+
66
+
67
+ IRISH_CITY_FORMS = (
68
+ "Dublin",
69
+ "Baile Átha Cliath",
70
+ "mBaile Átha Cliath",
71
+ "mBaile Atha Cliath",
72
+ "Galway",
73
+ "Gaillimh",
74
+ "Cork",
75
+ "Cork City",
76
+ "Corcaigh",
77
+ "Limerick",
78
+ "Luimneach",
79
+ "Waterford",
80
+ "Port Láirge",
81
+ "Kilkenny",
82
+ "Cill Chainnigh",
83
+ "Carlow",
84
+ "Ceatharlach",
85
+ "Sligo",
86
+ "Sligeach",
87
+ "Tralee",
88
+ "Trá Lí",
89
+ "Ennis",
90
+ "Inis",
91
+ "Letterkenny",
92
+ "Leitir Ceanainn",
93
+ "Castlebar",
94
+ "Caisleán an Bharraigh",
95
+ "Caislean an Bharraigh",
96
+ "gCaisleán an Bharraigh",
97
+ "gCaislean an Bharraigh",
98
+ "Wexford",
99
+ "Loch Garman",
100
+ "Navan",
101
+ "Uaimh",
102
+ "An Uaimh",
103
+ "hUaimh",
104
+ "nUaimh",
105
+ "Dundalk",
106
+ "Dún Dealgan",
107
+ "Dun Dealgan",
108
+ "Mullingar",
109
+ "Muileann gCearr",
110
+ "An Muileann gCearr",
111
+ "Tullamore",
112
+ "Tulach Mhór",
113
+ "Tulach Mhor",
114
+ "dTulach Mhór",
115
+ "dTulach Mhor",
116
+ "Portlaoise",
117
+ "Port Laoise",
118
+ "bPort Laoise",
119
+ "Bray",
120
+ "Bré",
121
+ "Bre",
122
+ "mBré",
123
+ "mBre",
124
+ "Athlone",
125
+ "Baile Átha Luain",
126
+ "Baile Atha Luain",
127
+ "mBaile Átha Luain",
128
+ "mBaile Atha Luain",
129
+ )
130
+ IRISH_CITY_SURFACES = {normalize_surface(value) for value in IRISH_CITY_FORMS}
131
+
132
+ IRISH_COUNTY_FORMS = (
133
+ "Co. Dublin",
134
+ "County Dublin",
135
+ "Co. Bhaile Átha Cliath",
136
+ "Contae Bhaile Átha Cliath",
137
+ "gContae Bhaile Átha Cliath",
138
+ "Co. Galway",
139
+ "County Galway",
140
+ "Co. na Gaillimhe",
141
+ "Contae na Gaillimhe",
142
+ "gContae na Gaillimhe",
143
+ "Co. Cork",
144
+ "County Cork",
145
+ "Co. Chorcaí",
146
+ "Contae Chorcaí",
147
+ "gContae Chorcaí",
148
+ "Co. Limerick",
149
+ "County Limerick",
150
+ "Co. Luimnigh",
151
+ "Contae Luimnigh",
152
+ "gContae Luimnigh",
153
+ "Co. Waterford",
154
+ "County Waterford",
155
+ "Co. Phort Láirge",
156
+ "Contae Phort Láirge",
157
+ "gContae Phort Láirge",
158
+ "Co. Kilkenny",
159
+ "County Kilkenny",
160
+ "Co. Chill Chainnigh",
161
+ "Contae Chill Chainnigh",
162
+ "gContae Chill Chainnigh",
163
+ "Co. Carlow",
164
+ "County Carlow",
165
+ "Co. Cheatharlach",
166
+ "Contae Cheatharlach",
167
+ "gContae Cheatharlach",
168
+ "Co. Sligo",
169
+ "County Sligo",
170
+ "Co. Shligigh",
171
+ "Contae Shligigh",
172
+ "gContae Shligigh",
173
+ "Co. Kerry",
174
+ "County Kerry",
175
+ "Co. Chiarraí",
176
+ "Contae Chiarraí",
177
+ "gContae Chiarraí",
178
+ "Co. Clare",
179
+ "County Clare",
180
+ "Co. an Chláir",
181
+ "Contae an Chláir",
182
+ "gContae an Chláir",
183
+ "Co. Donegal",
184
+ "County Donegal",
185
+ "Co. Dhún na nGall",
186
+ "Co. Dhun na nGall",
187
+ "Contae Dhún na nGall",
188
+ "Contae Dhun na nGall",
189
+ "gContae Dhún na nGall",
190
+ "gContae Dhun na nGall",
191
+ "Co. Mayo",
192
+ "County Mayo",
193
+ "Co. Mhaigh Eo",
194
+ "Contae Mhaigh Eo",
195
+ "gContae Mhaigh Eo",
196
+ "Co. Wexford",
197
+ "County Wexford",
198
+ "Co. Loch Garman",
199
+ "Contae Loch Garman",
200
+ "gContae Loch Garman",
201
+ "Co. Meath",
202
+ "County Meath",
203
+ "Co. na Mí",
204
+ "Co. na Mi",
205
+ "Contae na Mí",
206
+ "Contae na Mi",
207
+ "gContae na Mí",
208
+ "gContae na Mi",
209
+ "Co. Louth",
210
+ "County Louth",
211
+ "Co. Lú",
212
+ "Co. Lu",
213
+ "Contae Lú",
214
+ "Contae Lu",
215
+ "gContae Lú",
216
+ "gContae Lu",
217
+ "Co. Westmeath",
218
+ "County Westmeath",
219
+ "Co. na hIarmhí",
220
+ "Co. na hIarmhi",
221
+ "Contae na hIarmhí",
222
+ "Contae na hIarmhi",
223
+ "gContae na hIarmhí",
224
+ "gContae na hIarmhi",
225
+ "Co. Offaly",
226
+ "County Offaly",
227
+ "Co. Uíbh Fhailí",
228
+ "Co. Uibh Fhaili",
229
+ "Contae Uíbh Fhailí",
230
+ "Contae Uibh Fhaili",
231
+ "gContae Uíbh Fhailí",
232
+ "gContae Uibh Fhaili",
233
+ "Co. Laois",
234
+ "County Laois",
235
+ "Contae Laoise",
236
+ "gContae Laoise",
237
+ "Co. Wicklow",
238
+ "County Wicklow",
239
+ "Co. Chill Mhantáin",
240
+ "Co. Chill Mhantain",
241
+ "Contae Chill Mhantáin",
242
+ "Contae Chill Mhantain",
243
+ "gContae Chill Mhantáin",
244
+ "gContae Chill Mhantain",
245
+ )
246
+ IRISH_COUNTY_SURFACES = {normalize_surface(value) for value in IRISH_COUNTY_FORMS}
247
+ IRISH_CITY_PREFIX_CHARS = {"n", "g", "m", "b", "d", "h"}
248
+
249
+ STREET_SUFFIX_RE = re.compile(
250
+ r"(?i)\b(street|road|avenue|lane|park|view|square|terrace|drive|close|way|place|crescent|grove|green|court|manor|mews|gardens?|heights|quay|bóthar|bothar|sráid|sraid|lána|lana)\b"
251
+ )
252
+ PHONE_SURFACE_RE = re.compile(r"^[+().\d][+().\d \-/\u00A0\u202F]*\d$")
253
+ ACCOUNT_DIGIT_SURFACE_RE = re.compile(r"^[\d \-\u00A0\u202F]+$")
254
+ DATE_OF_BIRTH_RE = re.compile(
255
+ r"(?i)^(?:\d{1,2}[./-]\d{1,2}[./-]\d{4}|\d{4}-\d{2}-\d{2}|(?:an\s+)?\d{1,2}(?:st|nd|rd|th|ú)?\s+[A-Za-zÁÉÍÓÚáéíóú]+(?:\s+[A-Za-zÁÉÍÓÚáéíóú]+)?\s+\d{4}|[A-Za-zÁÉÍÓÚáéíóú]+(?:\s+[A-Za-zÁÉÍÓÚáéíóú]+)?\s+\d{1,2},\s+\d{4})$"
256
+ )
257
+ DATE_OF_BIRTH_VALUE_RE = re.compile(
258
+ r"(?<![A-Za-z0-9])(\d{1,2}[./-]\d{1,2}[./-]\d{4}|\d{4}-\d{2}-\d{2}|(?:an\s+)?\d{1,2}(?:st|nd|rd|th|ú)?\s+[A-Za-zÁÉÍÓÚáéíóú]+(?:\s+[A-Za-zÁÉÍÓÚáéíóú]+)?\s+\d{4}|[A-Za-zÁÉÍÓÚáéíóú]+(?:\s+[A-Za-zÁÉÍÓÚáéíóú]+)?\s+\d{1,2},\s+\d{4})(?![A-Za-z0-9])"
259
+ )
260
+ AGE_CONTEXT_RE = re.compile(r"(?i)\b(age|aged|years?\s+old|year\s+old|year-old|yrs?\s+old|y/?o|yo|aois|bliana\s+d['’]aois|mbliana\s+d['’]aois)\b")
261
+ AGE_INLINE_SUFFIX_RE = re.compile(r"(?i)^(?:-year-old\b|yo\b|y/o\b|yrs?\b)")
262
+ AGE_VALUE_RE = re.compile(r"(?<![A-Za-z0-9])(\d{1,3})(?![A-Za-z0-9])")
263
+ AGE_SELF_PREFIX_RE = re.compile(r"(?i)(?:^|.*\b)(?:i\s+am|i['’]?m|im|t[áa]\s+m[ée]|t[áa]im)\s*$")
264
+ DOB_CONTEXT_RE = re.compile(
265
+ r"(?i)\b(dob|date\s+of\s+birth|born(?:\s+on)?|data\s+breithe|dáta\s+breithe|dhata\s+breithe|dháta\s+breithe|rugadh)\b"
266
+ )
267
+ ADDRESS_CUE_RE = re.compile(
268
+ r"(?i)\b(address(?:\s+is)?|my\s+address\s+is|seoladh|sheoladh|allocation\s+centre|intreo\s+centre|ionad\s+leithdh[aá]ilte|ionad\s+intreo|live\s+at|lives\s+at|living\s+at|located\s+at|is\s+[ée]\s+mo\s+sheoladh|i\s+mo\s+ch[oó]na[ií]\s+ag|t[áa]\s+m[ée]\s+i\s+mo\s+ch[oó]na[ií]\s+ag|t[áa]im\s+i\s+mo\s+ch[oó]na[ií]\s+ag|cónai\s+ag|chónai\s+ag|conai\s+ag|chonai\s+ag)\b"
269
+ )
270
+ CITY_COUNTY_PREFIX_RE = re.compile(r"(?i)(?:county|co\.|contae|gcontae)(?:\s+na)?\s*$")
271
+ PPSN_CUE_RE = re.compile(
272
+ r"(?i)\b(ppsn|upsp|personal public service(?:\s+number)?|uimhir\s+(?:mo\s+)?upsp|uimhir\s+(?:mo\s+)?ppsn)\b"
273
+ )
274
+ NAME_STOP_SURFACES = {
275
+ normalize_surface(value)
276
+ for value in {
277
+ "Address",
278
+ "Name",
279
+ "Phone",
280
+ "Email",
281
+ "Seoladh",
282
+ "Ainm",
283
+ "Teagmháil",
284
+ "Teagmhail",
285
+ "Ríomhphost",
286
+ "Riomhphost",
287
+ "PPSN",
288
+ "UPSP",
289
+ "Call",
290
+ "Glao",
291
+ "Glaoigh",
292
+ "Rugadh",
293
+ "Ionad",
294
+ "Intreo",
295
+ "Cill",
296
+ "Sampla",
297
+ "Leithdháilte",
298
+ "Leithdhailte",
299
+ "Leithdháil",
300
+ "Leithdhail",
301
+ "Leithdh",
302
+ "Apartment",
303
+ "Flat",
304
+ "Unit",
305
+ "Suite",
306
+ "Árasán",
307
+ "Arasan",
308
+ "Aonad",
309
+ "County",
310
+ "Contae",
311
+ "Fón",
312
+ "Fon",
313
+ "January",
314
+ "February",
315
+ "March",
316
+ "April",
317
+ "May",
318
+ "June",
319
+ "July",
320
+ "August",
321
+ "September",
322
+ "October",
323
+ "November",
324
+ "December",
325
+ "Monday",
326
+ "Tuesday",
327
+ "Wednesday",
328
+ "Thursday",
329
+ "Friday",
330
+ "Saturday",
331
+ "Sunday",
332
+ "Eanáir",
333
+ "Feabhra",
334
+ "Márta",
335
+ "Aibreán",
336
+ "Aibrean",
337
+ "Bealtaine",
338
+ "Meitheamh",
339
+ "Iúil",
340
+ "Iuil",
341
+ "Lúnasa",
342
+ "Lunasa",
343
+ "Meán Fómhair",
344
+ "Mean Fomhair",
345
+ "Deireadh Fómhair",
346
+ "Deireadh Fomhair",
347
+ "Samhain",
348
+ "Nollaig",
349
+ "Luan",
350
+ "Máirt",
351
+ "Mairt",
352
+ "Céadaoin",
353
+ "Ceadaoin",
354
+ "Déardaoin",
355
+ "Deardaoin",
356
+ "Aoine",
357
+ "Satharn",
358
+ "Domhnach",
359
+ }
360
+ }
361
+ NAME_PARTICLE_SURFACES = {
362
+ normalize_surface(value)
363
+ for value in {"Ó", "O", "Ní", "Ni", "Nic", "Mac", "Mc", "de", "van", "von"}
364
+ }
365
+ STREET_TRAILING_BLOCK_SURFACES = {
366
+ normalize_surface(value)
367
+ for value in {
368
+ "are",
369
+ "public",
370
+ "contact",
371
+ "details",
372
+ "website",
373
+ "open",
374
+ "before",
375
+ "visiting",
376
+ "roimh",
377
+ "chuairt",
378
+ "agus",
379
+ "and",
380
+ "the",
381
+ "is",
382
+ "ta",
383
+ }
384
+ }
385
+ ADDRESS_UNIT_PREFIX_RE = re.compile(r"(?i)^(?:apartment|apt\.?|flat|unit|suite|[AaÁá]ras[aá]n|aonad)\b")
386
+ HOUSE_NAME_PREFIX_RE = re.compile(
387
+ r"(?i)^(?:[A-ZÁÉÍÓÚ][\w'’.-]+(?:\s+[A-ZÁÉÍÓÚ][\w'’.-]+){0,2}\s+(?:house|cottage|lodge|villa)|teach(?:ín|in)?(?:\s+na\s+[A-ZÁÉÍÓÚ][\w'’.-]+)?)$"
388
+ )
389
+ STREET_ADDRESS_VALUE_RE = re.compile(
390
+ r"(?i)(?<![\w@])("
391
+ r"(?:(?:apartment|apt\.?|flat|unit|suite|[AaÁá]ras[aá]n|aonad)\s+[A-Za-z0-9-]+,\s+)?"
392
+ r"(?:(?:[A-ZÁÉÍÓÚ][\w'’.-]+(?:\s+[A-ZÁÉÍÓÚ][\w'’.-]+){0,2}\s+(?:house|cottage|lodge|villa)|teach(?:ín|in)?(?:\s+na\s+[A-ZÁÉÍÓÚ][\w'’.-]+)?),\s+)?"
393
+ r"(?:\d{1,4}\s+)?(?:[A-ZÁÉÍÓÚa-záéíóú][\w'’.-]*\s+){0,5}(?:street|road|avenue|lane|park|view|square|terrace|drive|close|way|place|crescent|grove|green|court|manor|mews|gardens?|heights|quay|bóthar|bothar|sráid|sraid|lána|lana)(?:\s+[A-ZÁÉÍÓÚa-záéíóú][\w'’.-]*){0,2}"
394
+ r")"
395
+ )
396
+
397
+
398
+ def is_plausible_last_name_sequence(value: str) -> bool:
399
+ tokens = [token for token in re.split(r"\s+", value.strip()) if token]
400
+ if not tokens:
401
+ return False
402
+ for token in tokens:
403
+ if not any(ch.isalpha() for ch in token):
404
+ return False
405
+ if not all(is_name_token_char(ch) for ch in token):
406
+ return False
407
+ alpha_chars = [ch for ch in token if ch.isalpha()]
408
+ first_alpha = alpha_chars[0] if alpha_chars else ""
409
+ if first_alpha.isupper():
410
+ continue
411
+ if len(alpha_chars) >= 2 and alpha_chars[0].islower() and alpha_chars[1].isupper():
412
+ continue
413
+ if normalize_surface(token) in NAME_PARTICLE_SURFACES:
414
+ continue
415
+ return False
416
+ return True
417
+
418
+
419
+ def is_reasonable_span_text(label: str, text: str, start: int, end: int) -> bool:
420
+ value = text[int(start) : int(end)].strip()
421
+ if not value:
422
+ return False
423
+ upper = alnum_upper(value)
424
+
425
+ if label in {"FIRST_NAME", "LAST_NAME"}:
426
+ if not any(ch.isalpha() for ch in value):
427
+ return False
428
+ if any(ch.isdigit() for ch in value):
429
+ return False
430
+ if int(start) > 0 and text[int(start) - 1].isalpha():
431
+ return False
432
+ if int(end) < len(text) and text[int(end)].isalpha():
433
+ return False
434
+ if normalize_surface(value) in NAME_STOP_SURFACES:
435
+ return False
436
+ if label == "FIRST_NAME" and any(ch.isspace() for ch in value):
437
+ return False
438
+ if any(ch in ".,;:/@()" for ch in value):
439
+ return False
440
+ if label == "FIRST_NAME":
441
+ first_alpha = next((ch for ch in value if ch.isalpha()), "")
442
+ if not first_alpha or not first_alpha.isupper():
443
+ return False
444
+ if label == "LAST_NAME" and not is_plausible_last_name_sequence(value):
445
+ return False
446
+ if start > 0 and text[int(start) - 1].isdigit():
447
+ return False
448
+ return True
449
+
450
+ if label == "EMAIL":
451
+ if "@" not in value:
452
+ return False
453
+ local, _, domain = value.partition("@")
454
+ return bool(local) and "." in domain
455
+
456
+ if label == "PHONE_NUMBER":
457
+ normalized = value.replace("\u00A0", " ").replace("\u202F", " ").strip()
458
+ if any(ch.isalpha() for ch in normalized):
459
+ return False
460
+ if "@" in normalized:
461
+ return False
462
+ if int(start) > 0 and text[int(start) - 1].isalnum():
463
+ return False
464
+ if int(end) < len(text) and text[int(end)].isalnum():
465
+ return False
466
+ if not PHONE_SURFACE_RE.match(normalized):
467
+ return False
468
+ digits = "".join(ch for ch in value if ch.isdigit())
469
+ if normalized.startswith("+353"):
470
+ tail = digits[3:]
471
+ if tail.startswith("0"):
472
+ tail = tail[1:]
473
+ return 8 <= len(tail) <= 9
474
+ if not digits.startswith("0"):
475
+ return False
476
+ if digits.startswith("0818") or digits.startswith("1800"):
477
+ return len(digits) == 10
478
+ if digits.startswith("08"):
479
+ return len(digits) == 10
480
+ if digits.startswith("01"):
481
+ return len(digits) == 9
482
+ return 9 <= len(digits) <= 10
483
+
484
+ if label == "PPSN":
485
+ return bool(len(upper) in {8, 9} and upper[:7].isdigit() and upper[7:].isalpha())
486
+
487
+ if label == "POSTCODE":
488
+ compact = value.replace(" ", "").replace("\u00A0", "").replace("\u202F", "")
489
+ if any(not (ch.isalnum() or ch.isspace()) for ch in value):
490
+ return False
491
+ if len(compact) != 7:
492
+ return False
493
+ routing = compact[:3]
494
+ unique = compact[3:]
495
+ routing_ok = bool(
496
+ (routing[0].isalpha() and routing[1:].isdigit())
497
+ or routing == "D6W"
498
+ )
499
+ unique_ok = bool(
500
+ len(unique) == 4
501
+ and unique[0].isalpha()
502
+ and unique[1:].isalnum()
503
+ )
504
+ return routing_ok and unique_ok
505
+
506
+ if label == "PASSPORT_NUMBER":
507
+ return bool(re.fullmatch(r"[A-Z]{1,2}\s?\d{7}", value.strip()))
508
+
509
+ if label == "BANK_ROUTING_NUMBER":
510
+ digits = "".join(ch for ch in value if ch.isdigit())
511
+ if len(digits) != 6:
512
+ return False
513
+ context = text[max(0, int(start) - 32) : min(len(text), int(end) + 24)]
514
+ return bool(BANK_ROUTING_CONTEXT_RE.search(context))
515
+
516
+ if label == "SWIFT_BIC":
517
+ return len(upper) in {8, 11} and upper.isalnum()
518
+
519
+ if label == "CREDIT_DEBIT_CARD":
520
+ digits = "".join(ch for ch in value if ch.isdigit())
521
+ return 12 <= len(digits) <= 19
522
+
523
+ if label == "ACCOUNT_NUMBER":
524
+ if upper.startswith("IE"):
525
+ return bool(re.fullmatch(r"IE\d{2}[A-Z0-9]{18}", upper))
526
+ if not ACCOUNT_DIGIT_SURFACE_RE.fullmatch(value.strip()):
527
+ return False
528
+ digits = "".join(ch for ch in value if ch.isdigit())
529
+ return 6 <= len(digits) <= 34
530
+
531
+ if label == "AGE":
532
+ digits = "".join(ch for ch in value if ch.isdigit())
533
+ if digits != value.strip():
534
+ return False
535
+ if not digits:
536
+ return False
537
+ if int(start) > 0 and text[int(start) - 1].isalnum():
538
+ return False
539
+ trailing = text[int(end) : min(len(text), int(end) + 12)]
540
+ if int(end) < len(text) and text[int(end)].isalnum() and not AGE_INLINE_SUFFIX_RE.match(trailing):
541
+ return False
542
+ if int(start) > 0 and text[int(start) - 1] in "/-":
543
+ return False
544
+ if int(end) < len(text) and text[int(end)] in "/-" and not AGE_INLINE_SUFFIX_RE.match(trailing):
545
+ return False
546
+ age = int(digits)
547
+ if not (0 < age <= 120):
548
+ return False
549
+ context = text[max(0, int(start) - 12) : min(len(text), int(end) + 16)]
550
+ prefix = text[max(0, int(start) - 12) : int(start)]
551
+ return bool(AGE_CONTEXT_RE.search(context) or AGE_SELF_PREFIX_RE.search(prefix))
552
+
553
+ if label == "DATE_OF_BIRTH":
554
+ if not any(ch.isdigit() for ch in value):
555
+ return False
556
+ if not DATE_OF_BIRTH_RE.match(value.strip()):
557
+ return False
558
+ context = text[max(0, int(start) - 32) : min(len(text), int(end) + 32)]
559
+ return bool(DOB_CONTEXT_RE.search(context))
560
+
561
+ if label == "CITY":
562
+ if any(ch.isdigit() for ch in value):
563
+ return False
564
+ prefix = text[max(0, int(start) - 20) : int(start)]
565
+ if CITY_COUNTY_PREFIX_RE.search(prefix):
566
+ return False
567
+ return normalize_surface(value) in IRISH_CITY_SURFACES
568
+
569
+ if label == "COUNTY":
570
+ if any(ch.isdigit() for ch in value):
571
+ return False
572
+ normalized = normalize_surface(value)
573
+ return normalized in IRISH_COUNTY_SURFACES or normalized.startswith(("county ", "contae ", "gcontae ", "co. "))
574
+
575
+ if label == "STREET_ADDRESS":
576
+ cleaned = value.strip()
577
+ address_parts = [part.strip() for part in cleaned.split(",")]
578
+ if len(address_parts) > 2:
579
+ return False
580
+ prefix_part = ""
581
+ street_part = cleaned
582
+ if len(address_parts) == 2:
583
+ prefix_part, street_part = address_parts
584
+ if not prefix_part or not street_part:
585
+ return False
586
+ if not (
587
+ ADDRESS_UNIT_PREFIX_RE.match(prefix_part)
588
+ or HOUSE_NAME_PREFIX_RE.match(prefix_part)
589
+ ):
590
+ return False
591
+ suffix_match = STREET_SUFFIX_RE.search(street_part)
592
+ if not suffix_match:
593
+ return False
594
+ if any(ch in "@:;" for ch in cleaned):
595
+ return False
596
+ trailing = street_part[int(suffix_match.end()) :].strip()
597
+ trailing_tokens = [token for token in re.split(r"\s+", trailing) if token]
598
+ if len(trailing_tokens) > 3:
599
+ return False
600
+ if any(normalize_surface(token) in STREET_TRAILING_BLOCK_SURFACES for token in trailing_tokens):
601
+ return False
602
+ has_digit = any(ch.isdigit() for ch in street_part)
603
+ if has_digit and not re.match(r"^\s*\d{1,4}\b", street_part):
604
+ return False
605
+ title_tokens = [token for token in re.split(r"\s+", street_part) if token]
606
+ if not has_digit and not prefix_part:
607
+ context = text[max(0, int(start) - 24) : min(len(text), int(end) + 12)]
608
+ if not ADDRESS_CUE_RE.search(context):
609
+ return False
610
+ return has_digit or len(title_tokens) >= 2
611
+
612
+ return True
613
+
614
+
615
+ def spans_overlap(a: dict, b: dict) -> bool:
616
+ return int(a["start"]) < int(b["end"]) and int(b["start"]) < int(a["end"])
617
+
618
+
619
+ def is_name_token_char(ch: str) -> bool:
620
+ return ch.isalpha() or ch in {"-", "'", "’"}
621
+
622
+
623
+ def is_plausible_first_name(value: str) -> bool:
624
+ if not value:
625
+ return False
626
+ if any(ch.isspace() for ch in value):
627
+ return False
628
+ if any(ch.isdigit() for ch in value):
629
+ return False
630
+ if any(ch in ",;:/@()" for ch in value):
631
+ return False
632
+ if not any(ch.isalpha() for ch in value):
633
+ return False
634
+ first_alpha = next((ch for ch in value if ch.isalpha()), "")
635
+ if not first_alpha or not first_alpha.isupper():
636
+ return False
637
+ return all(is_name_token_char(ch) for ch in value)
638
+
639
+
640
+ def is_plausible_cued_first_name(value: str) -> bool:
641
+ if not value:
642
+ return False
643
+ if any(ch.isspace() for ch in value):
644
+ return False
645
+ if any(ch.isdigit() for ch in value):
646
+ return False
647
+ if any(ch in ",;:/@()" for ch in value):
648
+ return False
649
+ if not any(ch.isalpha() for ch in value):
650
+ return False
651
+ return all(is_name_token_char(ch) for ch in value)
652
+
653
+
654
+ def is_plausible_cued_last_name_sequence(value: str) -> bool:
655
+ tokens = [token for token in re.split(r"\s+", value.strip()) if token]
656
+ if not tokens:
657
+ return False
658
+ for token in tokens:
659
+ if not any(ch.isalpha() for ch in token):
660
+ return False
661
+ if not all(is_name_token_char(ch) for ch in token):
662
+ return False
663
+ alpha_chars = [ch for ch in token if ch.isalpha()]
664
+ first_alpha = alpha_chars[0] if alpha_chars else ""
665
+ if first_alpha.isupper() or first_alpha.islower():
666
+ continue
667
+ if normalize_surface(token) in NAME_PARTICLE_SURFACES:
668
+ continue
669
+ return False
670
+ return True
671
+
672
+
673
+ def extract_name_tokens_after_cue(text: str, cue_end: int, max_tokens: int = 4) -> list[tuple[int, int, str]]:
674
+ cursor = cue_end
675
+ while cursor < len(text) and text[cursor].isspace():
676
+ cursor += 1
677
+ tokens: list[tuple[int, int, str]] = []
678
+ while cursor < len(text):
679
+ while cursor < len(text) and text[cursor].isspace():
680
+ cursor += 1
681
+ if cursor >= len(text) or text[cursor] in ",.;:\n":
682
+ break
683
+ token_start = cursor
684
+ while cursor < len(text) and is_name_token_char(text[cursor]):
685
+ cursor += 1
686
+ if token_start == cursor:
687
+ break
688
+ token = text[token_start:cursor]
689
+ normalized = normalize_surface(token)
690
+ if tokens and normalized in NAME_CUE_STOP_SURFACES:
691
+ break
692
+ if not all(is_name_token_char(ch) for ch in token):
693
+ break
694
+ tokens.append((token_start, cursor, token))
695
+ if len(tokens) >= max_tokens:
696
+ break
697
+ if cursor < len(text) and text[cursor] in ",.;:\n":
698
+ break
699
+ if cursor < len(text) and not text[cursor].isspace():
700
+ break
701
+ return tokens
702
+
703
+
704
+ def repair_first_name_from_last_name(text: str, spans: list[dict]) -> list[dict]:
705
+ repaired = list(spans)
706
+ for last_name in [span for span in repaired if span["label"] == "LAST_NAME"]:
707
+ if any(
708
+ span["label"] == "FIRST_NAME"
709
+ and int(span["end"]) <= int(last_name["start"])
710
+ and int(last_name["start"]) - int(span["end"]) <= 2
711
+ for span in repaired
712
+ ):
713
+ continue
714
+
715
+ cursor = int(last_name["start"]) - 1
716
+ if cursor < 0 or not text[cursor].isspace():
717
+ continue
718
+ while cursor >= 0 and text[cursor].isspace():
719
+ cursor -= 1
720
+ token_end = cursor + 1
721
+ while cursor >= 0 and is_name_token_char(text[cursor]):
722
+ cursor -= 1
723
+ token_start = cursor + 1
724
+ if token_end <= token_start:
725
+ continue
726
+ candidate = text[token_start:token_end]
727
+ if not is_plausible_first_name(candidate):
728
+ continue
729
+ candidate_span = {
730
+ "start": token_start,
731
+ "end": token_end,
732
+ "label": "FIRST_NAME",
733
+ "score": float(last_name.get("score", 0.5)) * 0.6,
734
+ "text": candidate,
735
+ }
736
+ if any(spans_overlap(candidate_span, other) for other in repaired if other["label"] == "FIRST_NAME"):
737
+ continue
738
+ repaired.append(candidate_span)
739
+ return repaired
740
+
741
+
742
+ def repair_contextual_name_cues(text: str, spans: list[dict]) -> list[dict]:
743
+ repaired = list(spans)
744
+ for match in NAME_SELF_CUE_RE.finditer(text):
745
+ if any(
746
+ other["label"] == "FIRST_NAME"
747
+ and 0 <= int(other["start"]) - match.end() <= 4
748
+ for other in repaired
749
+ ) and any(
750
+ other["label"] == "LAST_NAME"
751
+ and 0 <= int(other["start"]) - match.end() <= 16
752
+ for other in repaired
753
+ ):
754
+ continue
755
+ cursor = match.end()
756
+ while cursor < len(text) and text[cursor].isspace():
757
+ cursor += 1
758
+ start = cursor
759
+ while cursor < len(text) and (is_name_token_char(text[cursor]) or text[cursor].isspace()):
760
+ cursor += 1
761
+ candidate = text[start:cursor].strip()
762
+ raw_tokens = [token for token in re.split(r"\s+", candidate) if token]
763
+ tokens: list[str] = []
764
+ for token in raw_tokens:
765
+ normalized = normalize_surface(token)
766
+ if tokens and normalized in LOWER_NAME_STOP_SURFACES:
767
+ break
768
+ if not all(is_name_token_char(ch) for ch in token):
769
+ break
770
+ tokens.append(token)
771
+ if len(tokens) >= 4:
772
+ break
773
+ if len(tokens) < 2:
774
+ continue
775
+ first_value = tokens[0]
776
+ first_alpha = next((ch for ch in first_value if ch.isalpha()), "")
777
+ if not first_alpha or not first_alpha.islower():
778
+ continue
779
+ last_value = " ".join(tokens[1:])
780
+ if not is_plausible_cued_first_name(first_value):
781
+ continue
782
+ if not is_plausible_cued_last_name_sequence(last_value):
783
+ continue
784
+ first_start = text.find(first_value, start, cursor)
785
+ if first_start < 0:
786
+ continue
787
+ first_end = first_start + len(first_value)
788
+ last_start = text.find(last_value, first_end, cursor)
789
+ if last_start < 0:
790
+ continue
791
+ last_end = last_start + len(last_value)
792
+ first_span = {
793
+ "start": first_start,
794
+ "end": first_end,
795
+ "label": "FIRST_NAME",
796
+ "score": 0.63,
797
+ "text": text[first_start:first_end],
798
+ }
799
+ last_span = {
800
+ "start": last_start,
801
+ "end": last_end,
802
+ "label": "LAST_NAME",
803
+ "score": 0.63,
804
+ "text": text[last_start:last_end],
805
+ }
806
+ repaired = [
807
+ other
808
+ for other in repaired
809
+ if not (
810
+ spans_overlap(first_span, other) and other["label"] in {"FIRST_NAME", "LAST_NAME"}
811
+ ) and not (
812
+ spans_overlap(last_span, other) and other["label"] in {"FIRST_NAME", "LAST_NAME"}
813
+ )
814
+ ]
815
+ repaired.extend([first_span, last_span])
816
+ return repaired
817
+
818
+
819
+ def repair_role_name_cues(text: str, spans: list[dict]) -> list[dict]:
820
+ repaired = list(spans)
821
+ for match in NAME_ROLE_CUE_RE.finditer(text):
822
+ token_bounds = extract_name_tokens_after_cue(text, match.end())
823
+ if len(token_bounds) < 2:
824
+ continue
825
+ first_start, first_end, first_value = token_bounds[0]
826
+ last_start = token_bounds[1][0]
827
+ last_end = token_bounds[-1][1]
828
+ last_value = text[last_start:last_end]
829
+ if not is_plausible_cued_first_name(first_value):
830
+ continue
831
+ if not is_plausible_cued_last_name_sequence(last_value):
832
+ continue
833
+ first_span = {
834
+ "start": first_start,
835
+ "end": first_end,
836
+ "label": "FIRST_NAME",
837
+ "score": 0.63,
838
+ "text": text[first_start:first_end],
839
+ }
840
+ last_span = {
841
+ "start": last_start,
842
+ "end": last_end,
843
+ "label": "LAST_NAME",
844
+ "score": 0.63,
845
+ "text": text[last_start:last_end],
846
+ }
847
+ repaired = [
848
+ other
849
+ for other in repaired
850
+ if not (
851
+ spans_overlap(first_span, other) and other["label"] in {"FIRST_NAME", "LAST_NAME"}
852
+ ) and not (
853
+ spans_overlap(last_span, other) and other["label"] in {"FIRST_NAME", "LAST_NAME"}
854
+ )
855
+ ]
856
+ repaired.extend([first_span, last_span])
857
+ return repaired
858
+
859
+
860
+ def repair_surname_field_cues(text: str, spans: list[dict]) -> list[dict]:
861
+ repaired = list(spans)
862
+ for match in SURNAME_CUE_RE.finditer(text):
863
+ token_bounds = extract_name_tokens_after_cue(text, match.end())
864
+ if not token_bounds:
865
+ continue
866
+ start = token_bounds[0][0]
867
+ end = token_bounds[-1][1]
868
+ candidate = text[start:end]
869
+ if not is_plausible_cued_last_name_sequence(candidate):
870
+ continue
871
+ last_span = {
872
+ "start": start,
873
+ "end": end,
874
+ "label": "LAST_NAME",
875
+ "score": 0.64,
876
+ "text": candidate,
877
+ }
878
+ repaired = [
879
+ other
880
+ for other in repaired
881
+ if not (
882
+ spans_overlap(last_span, other) and other["label"] in {"FIRST_NAME", "LAST_NAME"}
883
+ )
884
+ ]
885
+ repaired.append(last_span)
886
+ return repaired
887
+
888
+
889
+ def repair_name_before_structured_cues(text: str, spans: list[dict]) -> list[dict]:
890
+ repaired = list(spans)
891
+ for match in NAME_BEFORE_STRUCTURED_CUE_RE.finditer(text):
892
+ token_bounds = extract_name_tokens_after_cue(text, match.start(1))
893
+ if len(token_bounds) < 2:
894
+ continue
895
+ first_start, first_end, first_value = token_bounds[0]
896
+ last_start = token_bounds[1][0]
897
+ last_end = token_bounds[-1][1]
898
+ last_value = text[last_start:last_end]
899
+ if not is_plausible_first_name(first_value):
900
+ continue
901
+ if not is_plausible_last_name_sequence(last_value):
902
+ continue
903
+ first_span = {
904
+ "start": first_start,
905
+ "end": first_end,
906
+ "label": "FIRST_NAME",
907
+ "score": 0.64,
908
+ "text": text[first_start:first_end],
909
+ }
910
+ last_span = {
911
+ "start": last_start,
912
+ "end": last_end,
913
+ "label": "LAST_NAME",
914
+ "score": 0.64,
915
+ "text": text[last_start:last_end],
916
+ }
917
+ repaired = [
918
+ other
919
+ for other in repaired
920
+ if not (
921
+ spans_overlap(first_span, other) and other["label"] in {"FIRST_NAME", "LAST_NAME"}
922
+ ) and not (
923
+ spans_overlap(last_span, other) and other["label"] in {"FIRST_NAME", "LAST_NAME"}
924
+ )
925
+ ]
926
+ repaired.extend([first_span, last_span])
927
+ return repaired
928
+
929
+
930
+ PASSPORT_CUE_RE = re.compile(
931
+ r"(?i)(passport(?:\s+number)?|phas|uimhir\s+(?:mo\s+)?phas)"
932
+ )
933
+ PASSPORT_VALUE_RE = re.compile(r"(?<![A-Za-z0-9])([A-Z]{1,2}\s?\d{7})(?![A-Za-z0-9])")
934
+ EMAIL_EXTRACT_RE = re.compile(r"([^\s@,;:()<>]+@[A-Za-z0-9.\-]+\.[A-Za-z]{2,})", re.UNICODE)
935
+ PHONE_CUE_RE = re.compile(
936
+ r"(?i)\b(phone|call|contact|reach\s+me|glaoigh\s+ar|teagmh[aá]il|uimhir|m['’]uimhir|f[oó]n|fon|teileaf[oó]n|telefon)\b"
937
+ )
938
+ NAME_SELF_CUE_RE = re.compile(
939
+ r"(?i)\b(my\s+name\s+is|is\s+mise|is\s+[ée]\s+m['’]?ainm|is\s+[ée]\s+mo\s+ainm)\b"
940
+ )
941
+ NAME_ROLE_CUE_RE = re.compile(
942
+ r"(?i)(?:\b(?:applicant|customer|claimant|patient|an\s+t-iarratas[oó]ir|iarratas[oó]ir)\b\s*[:,]\s*|\b(?:full\s+name|name|ainm(?!\s+teaghlaigh))\b\s*:\s*)"
943
+ )
944
+ SURNAME_CUE_RE = re.compile(
945
+ r"(?i)\b(?:my\s+)?(?:surname|last\s+name|family\s+name|ainm\s+teaghlaigh|sloinne)\b(?:\s+is)?\s*[:,-]?\s*"
946
+ )
947
+ NAME_BEFORE_STRUCTURED_CUE_RE = re.compile(
948
+ r"(?<![A-Za-zÁÉÍÓÚáéíóú])([A-ZÁÉÍÓÚ][A-Za-zÁÉÍÓÚáéíóú'’.-]*(?:\s+[A-ZÁÉÍÓÚ][A-Za-zÁÉÍÓÚáéíóú'’.-]*){1,3})(?=\s*,\s*(?:PPSN|UPSP|DOB|Date\s+of\s+birth|D[áa]ta\s+breithe|Address|Seoladh|lives?\s+at|my\s+phone|phone|email|r-phost))"
949
+ )
950
+ LOWER_NAME_STOP_SURFACES = {
951
+ normalize_surface(value)
952
+ for value in {"and", "agus", "is", "ta", "tá", "my", "mo", "an", "the"}
953
+ }
954
+ NAME_CUE_STOP_SURFACES = {
955
+ normalize_surface(value)
956
+ for value in {
957
+ "and",
958
+ "agus",
959
+ "submitted",
960
+ "provided",
961
+ "gave",
962
+ "her",
963
+ "his",
964
+ "their",
965
+ "she",
966
+ "he",
967
+ "email",
968
+ "phone",
969
+ "fón",
970
+ "fon",
971
+ "ppsn",
972
+ "upsp",
973
+ "address",
974
+ "seoladh",
975
+ "dob",
976
+ "age",
977
+ "aois",
978
+ "bank",
979
+ "iban",
980
+ "swift",
981
+ "chuir",
982
+ "isteach",
983
+ "sí",
984
+ "si",
985
+ "a",
986
+ "huimhir",
987
+ }
988
+ }
989
+ ORG_NAME_TRAILING_SURFACES = {
990
+ normalize_surface(value)
991
+ for value in {"centre", "center", "clinic", "hospital", "office", "service", "section", "unit", "council"}
992
+ }
993
+ ORG_CITY_TAIL_RE = re.compile(
994
+ r"(?i)^\s+(?:intreo\s+centre|business\s+centre|community\s+centre|shopping\s+centre|retail\s+park|p[áa]irc\s+miond[ií]ola)\b"
995
+ )
996
+ ORG_NAME_PREFIX_RE = re.compile(
997
+ r"(?i)(?:retail\s+park|business\s+centre|community\s+centre|shopping\s+centre|p[áa]irc\s+miond[ií]ola)\s*$"
998
+ )
999
+ PUBLIC_CONTACT_DETAILS_RE = re.compile(r"(?i)\bpublic\s+contact\s+details\b")
1000
+ CITY_CUE_RE = re.compile(
1001
+ r"(?i)\b(address|seoladh|located|suite|centre|center|ionad|intreo|clinic|hospital|ospid[eé]al|hse|fss)\b"
1002
+ )
1003
+ BANK_ROUTING_CONTEXT_RE = re.compile(
1004
+ r"(?i)\b(sort\s+code|routing\s+number|bank\s+of\s+ireland|aib|cod\s+sort[aá]la|sort[aá]la)\b"
1005
+ )
1006
+ PHONE_VALUE_RE = re.compile(
1007
+ r"(?<![A-Za-z0-9])((?:\+353(?:\s*\((?:0)?\d{1,2}\))?[\s\-./]?|0)\d(?:[\s\-./]?\d){6,13}|\(\s*0\d{1,2}\s*\)(?:[\s\-./]?\d){6,10})(?![A-Za-z0-9])"
1008
+ )
1009
+ PPSN_VALUE_RE = re.compile(r"(?<![A-Za-z0-9])(\d{7}(?:[\s-]*[A-Za-z]){1,2})(?![A-Za-z0-9])")
1010
+ POSTCODE_VALUE_RE = re.compile(
1011
+ r"(?<![A-Za-z0-9])((?:[A-Za-z]\d{2}|D6W)[\s\u00A0\u202F]?[A-Za-z][A-Za-z0-9]{3})(?![A-Za-z0-9])"
1012
+ )
1013
+ CITY_BEFORE_POSTCODE_RE = re.compile(
1014
+ r"(?<![A-Za-zÁÉÍÓÚáéíóú])([A-ZÁÉÍÓÚ][\w'’.-]*(?:\s+[A-ZÁÉÍÓÚ][\w'’.-]*){0,2})(?=\s*,\s*(?:(?:County|Contae|gContae|Co\.)\s+[A-ZÁÉÍÓÚ][\w'’.-]*(?:\s+[A-ZÁÉÍÓÚ][\w'’.-]*){0,2}\s*,\s*)?(?:[A-Z]\d{2}|D6W))"
1015
+ )
1016
+ CITY_BEFORE_COUNTY_RE = re.compile(
1017
+ r"(?<![A-Za-zÁÉÍÓÚáéíóú])([A-ZÁÉÍÓÚ][\w'’.-]*(?:\s+[A-ZÁÉÍÓÚ][\w'’.-]*){0,3})(?=\s*,\s*(?:County|Contae|gContae|Co\.)\s+[A-ZÁÉÍÓÚ][\w'’.-]*(?:\s+[A-ZÁÉÍÓÚ][\w'’.-]*){0,2}\b)"
1018
+ )
1019
+ CITY_TOWN_SUFFIX_RE = re.compile(
1020
+ r"(?<![A-Za-zÁÉÍÓÚáéíóú])([A-ZÁÉÍÓÚ][\w'’.-]*(?:\s+[A-ZÁÉÍÓÚ][\w'’.-]*){0,2}\s+Town)(?=\s*,\s*(?:(?:County|Contae|gContae|Co\.)\s+[A-ZÁÉÍÓÚ][\w'’.-]*(?:\s+[A-ZÁÉÍÓÚ][\w'’.-]*){0,2}\s*,\s*)?(?:[A-Z]\d{2}|D6W))"
1021
+ )
1022
+ CITY_FIELD_VALUE_RE = re.compile(
1023
+ r"(?im)(?:^|[\n\r])\s*(?:city|town|cathair|baile)\b\s*[:,-]?\s*([A-ZÁÉÍÓÚ][\w'’.-]*(?:\s+[A-ZÁÉÍÓÚ][\w'’.-]*){0,3})"
1024
+ )
1025
+ COUNTY_FIELD_VALUE_RE = re.compile(
1026
+ r"(?im)(?:^|[\n\r])\s*(?:county|co\.|contae|gcontae)\b\s*[:,-]?\s*([A-ZÁÉÍÓÚ][\w'’.-]*(?:\s+[A-ZÁÉÍÓÚ][\w'’.-]*){0,2})"
1027
+ )
1028
+ COUNTY_VALUE_RE = re.compile(
1029
+ r"(?<![A-Za-zÁÉÍÓÚáéíóú])((?:County|Contae|gContae|Co\.)(?:\s+[A-ZÁÉÍÓÚ][\w'’.-]*){1,3})(?![A-Za-zÁÉÍÓÚáéíóú])"
1030
+ )
1031
+ ADDRESS_BLOCK_VALUE_RE = re.compile(
1032
+ r"(?i)\b(?:address(?:\s+is)?|my\s+address\s+is|seoladh|is\s+[ée]\s+mo\s+sheoladh|live\s+at|lives\s+at|living\s+at|located\s+at|t[áa]\s+m[ée]\s+i\s+mo\s+ch[oó]na[ií]\s+ag|t[áa]im\s+i\s+mo\s+ch[oó]na[ií]\s+ag)\b\s*[:,-]?\s*([^,\n.]+)"
1033
+ )
1034
+ ADDRESS_PLACE_VALUE_RE = re.compile(
1035
+ r"(?i)\b(?:address(?:\s+is)?|my\s+address\s+is|seoladh|is\s+[ée]\s+mo\s+sheoladh|live\s+at|lives\s+at|living\s+at|located\s+at|allocation\s+centre|intreo\s+centre)\b\s*[:,-]?\s*("
1036
+ r"(?:(?:apartment|apt\.?|flat|unit|suite|[AaÁá]ras[aá]n|aonad)\s+[A-Za-z0-9-]+,\s+)?"
1037
+ r"(?:[A-ZÁÉÍÓÚ][\w'’.-]*(?:\s+[A-ZÁÉÍÓÚ][\w'’.-]*){0,4}\s+(?:business\s+centre|community\s+centre|shopping\s+centre|retail\s+park)|P[áa]irc\s+Miond[ií]ola(?:\s+[A-ZÁÉÍÓÚ][\w'’.-]*)?)"
1038
+ r")"
1039
+ )
1040
+ LOCATION_FORM_EDGE = r"[A-Za-zÁÉÍÓÚáéíóú]"
1041
+
1042
+
1043
+ def iter_bounded_form_matches(form: str, text: str):
1044
+ pattern = re.compile(
1045
+ rf"(?<!{LOCATION_FORM_EDGE}){re.escape(form)}(?!{LOCATION_FORM_EDGE})",
1046
+ flags=re.IGNORECASE,
1047
+ )
1048
+ return pattern.finditer(text)
1049
+
1050
+
1051
+ def repair_contextual_passport_numbers(text: str, spans: list[dict]) -> list[dict]:
1052
+ repaired = list(spans)
1053
+ for match in PASSPORT_VALUE_RE.finditer(text):
1054
+ start, end = match.span(1)
1055
+ candidate_span = {
1056
+ "start": start,
1057
+ "end": end,
1058
+ "label": "PASSPORT_NUMBER",
1059
+ "score": 0.67,
1060
+ "text": text[start:end],
1061
+ }
1062
+ if any(
1063
+ other["label"] == "PASSPORT_NUMBER"
1064
+ and int(other["start"]) <= start
1065
+ and int(other["end"]) >= end
1066
+ for other in repaired
1067
+ ):
1068
+ continue
1069
+ cue_window = text[max(0, start - 32) : start]
1070
+ if not PASSPORT_CUE_RE.search(cue_window):
1071
+ continue
1072
+ conflicting_labels = {"PHONE_NUMBER", "PPSN", "ACCOUNT_NUMBER", "AGE", "PASSPORT_NUMBER"}
1073
+ repaired = [
1074
+ other
1075
+ for other in repaired
1076
+ if not (
1077
+ spans_overlap(candidate_span, other)
1078
+ and other["label"] in conflicting_labels
1079
+ )
1080
+ ]
1081
+ repaired.append(candidate_span)
1082
+ return repaired
1083
+
1084
+
1085
+ def repair_ppsn_variants(text: str, spans: list[dict]) -> list[dict]:
1086
+ repaired = list(spans)
1087
+ for match in PPSN_VALUE_RE.finditer(text):
1088
+ start, end = match.span(1)
1089
+ value = text[start:end]
1090
+ compact = alnum_upper(value)
1091
+ if not (len(compact) in {8, 9} and compact[:7].isdigit() and compact[7:].isalpha()):
1092
+ continue
1093
+ cue_window = text[max(0, start - 32) : min(len(text), end + 24)]
1094
+ has_cue = bool(PPSN_CUE_RE.search(cue_window))
1095
+ candidate_span = {
1096
+ "start": start,
1097
+ "end": end,
1098
+ "label": "PPSN",
1099
+ "score": 0.72 if has_cue else 0.58,
1100
+ "text": value,
1101
+ }
1102
+ conflicting_labels = {"PHONE_NUMBER", "PASSPORT_NUMBER", "ACCOUNT_NUMBER", "AGE", "FIRST_NAME", "LAST_NAME"}
1103
+ repaired = [
1104
+ other
1105
+ for other in repaired
1106
+ if not (
1107
+ spans_overlap(candidate_span, other)
1108
+ and other["label"] in conflicting_labels.union({"PPSN"})
1109
+ )
1110
+ ]
1111
+ repaired.append(candidate_span)
1112
+ return repaired
1113
+
1114
+
1115
+ def repair_contextual_date_of_birth(text: str, spans: list[dict]) -> list[dict]:
1116
+ repaired = list(spans)
1117
+ for match in DATE_OF_BIRTH_VALUE_RE.finditer(text):
1118
+ start, end = match.span(1)
1119
+ cue_window = text[max(0, start - 40) : min(len(text), end + 24)]
1120
+ if not DOB_CONTEXT_RE.search(cue_window):
1121
+ continue
1122
+ candidate_span = {
1123
+ "start": start,
1124
+ "end": end,
1125
+ "label": "DATE_OF_BIRTH",
1126
+ "score": 0.66,
1127
+ "text": text[start:end],
1128
+ }
1129
+ conflicting_labels = {"DATE_OF_BIRTH", "PHONE_NUMBER", "AGE", "FIRST_NAME", "LAST_NAME", "ACCOUNT_NUMBER", "CITY"}
1130
+ repaired = [
1131
+ other
1132
+ for other in repaired
1133
+ if not (
1134
+ spans_overlap(candidate_span, other)
1135
+ and other["label"] in conflicting_labels
1136
+ )
1137
+ ]
1138
+ repaired.append(candidate_span)
1139
+ return repaired
1140
+
1141
+
1142
+ def repair_contextual_ages(text: str, spans: list[dict]) -> list[dict]:
1143
+ repaired = list(spans)
1144
+ for match in AGE_VALUE_RE.finditer(text):
1145
+ start, end = match.span(1)
1146
+ if not is_reasonable_span_text("AGE", text, start, end):
1147
+ continue
1148
+ if any(
1149
+ spans_overlap({"start": start, "end": end}, other)
1150
+ and other["label"] == "DATE_OF_BIRTH"
1151
+ for other in repaired
1152
+ ):
1153
+ continue
1154
+ candidate_span = {
1155
+ "start": start,
1156
+ "end": end,
1157
+ "label": "AGE",
1158
+ "score": 0.66,
1159
+ "text": text[start:end],
1160
+ }
1161
+ conflicting_labels = {"AGE", "PHONE_NUMBER", "ACCOUNT_NUMBER"}
1162
+ repaired = [
1163
+ other
1164
+ for other in repaired
1165
+ if not (
1166
+ spans_overlap(candidate_span, other)
1167
+ and other["label"] in conflicting_labels
1168
+ )
1169
+ ]
1170
+ repaired.append(candidate_span)
1171
+ return repaired
1172
+
1173
+
1174
+ ACCOUNT_CUE_RE = re.compile(
1175
+ r"(?i)(account\s+number|bank\s+account|uimhir\s+chuntais|cuntas\s+bainc)"
1176
+ )
1177
+ ACCOUNT_VALUE_RE = re.compile(r"(?<![A-Za-z0-9])(\d{6,12})(?![A-Za-z0-9])")
1178
+
1179
+
1180
+ def repair_contextual_account_numbers(text: str, spans: list[dict]) -> list[dict]:
1181
+ repaired = list(spans)
1182
+ for match in ACCOUNT_VALUE_RE.finditer(text):
1183
+ start, end = match.span(1)
1184
+ candidate_span = {
1185
+ "start": start,
1186
+ "end": end,
1187
+ "label": "ACCOUNT_NUMBER",
1188
+ "score": 0.51,
1189
+ "text": text[start:end],
1190
+ }
1191
+ if any(
1192
+ other["label"] == "ACCOUNT_NUMBER"
1193
+ and int(other["start"]) <= start
1194
+ and int(other["end"]) >= end
1195
+ for other in repaired
1196
+ ):
1197
+ continue
1198
+ cue_window = text[max(0, start - 40) : start]
1199
+ if not ACCOUNT_CUE_RE.search(cue_window):
1200
+ continue
1201
+ if any(
1202
+ spans_overlap(candidate_span, other)
1203
+ and other["label"] in {"PHONE_NUMBER", "BANK_ROUTING_NUMBER", "PPSN", "POSTCODE", "PASSPORT_NUMBER"}
1204
+ for other in repaired
1205
+ ):
1206
+ continue
1207
+ repaired.append(candidate_span)
1208
+ return repaired
1209
+
1210
+
1211
+ def repair_emails(text: str, spans: list[dict]) -> list[dict]:
1212
+ repaired = list(spans)
1213
+ for match in EMAIL_EXTRACT_RE.finditer(text):
1214
+ start, end = match.span(1)
1215
+ candidate_span = {
1216
+ "start": start,
1217
+ "end": end,
1218
+ "label": "EMAIL",
1219
+ "score": 0.74,
1220
+ "text": text[start:end],
1221
+ }
1222
+ conflicting_labels = {"EMAIL", "FIRST_NAME", "LAST_NAME"}
1223
+ repaired = [
1224
+ other
1225
+ for other in repaired
1226
+ if not (
1227
+ spans_overlap(candidate_span, other)
1228
+ and other["label"] in conflicting_labels
1229
+ )
1230
+ ]
1231
+ repaired.append(candidate_span)
1232
+ return repaired
1233
+
1234
+
1235
+ def repair_phone_numbers(text: str, spans: list[dict]) -> list[dict]:
1236
+ repaired = list(spans)
1237
+ for match in PHONE_VALUE_RE.finditer(text):
1238
+ start, end = match.span(1)
1239
+ candidate_span = {
1240
+ "start": start,
1241
+ "end": end,
1242
+ "label": "PHONE_NUMBER",
1243
+ "score": 0.69,
1244
+ "text": text[start:end],
1245
+ }
1246
+ cue_window = text[max(0, start - 32) : min(len(text), end + 16)]
1247
+ has_cue = bool(PHONE_CUE_RE.search(cue_window))
1248
+ has_overlap = any(spans_overlap(candidate_span, other) and other["label"] == "PHONE_NUMBER" for other in repaired)
1249
+ if not (has_cue or has_overlap):
1250
+ continue
1251
+ if not is_reasonable_span_text("PHONE_NUMBER", text, start, end):
1252
+ continue
1253
+ conflicting_labels = {"PHONE_NUMBER", "PPSN", "ACCOUNT_NUMBER", "BANK_ROUTING_NUMBER", "CREDIT_DEBIT_CARD"}
1254
+ repaired = [
1255
+ other
1256
+ for other in repaired
1257
+ if not (
1258
+ spans_overlap(candidate_span, other)
1259
+ and other["label"] in conflicting_labels
1260
+ )
1261
+ ]
1262
+ repaired.append(candidate_span)
1263
+ return repaired
1264
+
1265
+
1266
+ def repair_postcodes(text: str, spans: list[dict]) -> list[dict]:
1267
+ repaired = list(spans)
1268
+ for match in POSTCODE_VALUE_RE.finditer(text):
1269
+ start, end = match.span(1)
1270
+ candidate_span = {
1271
+ "start": start,
1272
+ "end": end,
1273
+ "label": "POSTCODE",
1274
+ "score": 0.71,
1275
+ "text": text[start:end],
1276
+ }
1277
+ conflicting_labels = {"POSTCODE", "PHONE_NUMBER", "ACCOUNT_NUMBER", "FIRST_NAME", "LAST_NAME"}
1278
+ repaired = [
1279
+ other
1280
+ for other in repaired
1281
+ if not (
1282
+ spans_overlap(candidate_span, other)
1283
+ and other["label"] in conflicting_labels
1284
+ )
1285
+ ]
1286
+ repaired.append(candidate_span)
1287
+ return repaired
1288
+
1289
+
1290
+ def repair_city_spans(text: str, spans: list[dict]) -> list[dict]:
1291
+ repaired = list(spans)
1292
+ seen: set[tuple[int, int]] = set()
1293
+ ordered_forms = sorted(IRISH_CITY_FORMS, key=len, reverse=True)
1294
+ for form in ordered_forms:
1295
+ for match in iter_bounded_form_matches(form, text):
1296
+ start, end = match.span()
1297
+ prefix = text[max(0, start - 20) : start]
1298
+ if CITY_COUNTY_PREFIX_RE.search(prefix):
1299
+ continue
1300
+ key = (start, end)
1301
+ if key in seen:
1302
+ continue
1303
+ seen.add(key)
1304
+ candidate_span = {
1305
+ "start": start,
1306
+ "end": end,
1307
+ "label": "CITY",
1308
+ "score": 0.64,
1309
+ "text": text[start:end],
1310
+ }
1311
+ has_context = False
1312
+ for other in repaired:
1313
+ other_start = int(other["start"])
1314
+ other_end = int(other["end"])
1315
+ if other["label"] == "STREET_ADDRESS" and 0 <= start - other_end <= 4:
1316
+ has_context = True
1317
+ break
1318
+ if other["label"] in {"COUNTY", "POSTCODE"} and 0 <= other_start - end <= 6:
1319
+ has_context = True
1320
+ break
1321
+ if not has_context and re.match(r"^\s*,\s*(?:Co\.\s+|[A-Z]\d{2}|D6W)", text[end:]):
1322
+ has_context = True
1323
+ if not has_context:
1324
+ cue_window = text[max(0, start - 40) : min(len(text), end + 32)]
1325
+ has_context = bool(CITY_CUE_RE.search(cue_window) or ADDRESS_CUE_RE.search(cue_window))
1326
+ if not has_context:
1327
+ continue
1328
+ conflicting_labels = {"CITY", "FIRST_NAME", "LAST_NAME"}
1329
+ repaired = [
1330
+ other
1331
+ for other in repaired
1332
+ if not (
1333
+ spans_overlap(candidate_span, other)
1334
+ and other["label"] in conflicting_labels
1335
+ )
1336
+ ]
1337
+ repaired.append(candidate_span)
1338
+ return repaired
1339
+
1340
+
1341
+ def repair_city_before_postcode(text: str, spans: list[dict]) -> list[dict]:
1342
+ repaired = list(spans)
1343
+ for match in CITY_BEFORE_POSTCODE_RE.finditer(text):
1344
+ start, end = match.span(1)
1345
+ value = text[start:end]
1346
+ if any(ch.isdigit() for ch in value):
1347
+ continue
1348
+ prefix = text[max(0, start - 20) : start]
1349
+ if CITY_COUNTY_PREFIX_RE.search(prefix):
1350
+ continue
1351
+ has_context = False
1352
+ for other in repaired:
1353
+ other_start = int(other["start"])
1354
+ other_end = int(other["end"])
1355
+ if other["label"] == "STREET_ADDRESS" and 0 <= start - other_end <= 4:
1356
+ has_context = True
1357
+ break
1358
+ if other["label"] == "POSTCODE" and 0 <= other_start - end <= 6:
1359
+ has_context = True
1360
+ break
1361
+ if not has_context:
1362
+ cue_window = text[max(0, start - 40) : min(len(text), end + 24)]
1363
+ has_context = bool(CITY_CUE_RE.search(cue_window) or ADDRESS_CUE_RE.search(cue_window))
1364
+ if not has_context:
1365
+ continue
1366
+ candidate_span = {
1367
+ "start": start,
1368
+ "end": end,
1369
+ "label": "CITY",
1370
+ "score": 0.63,
1371
+ "text": value,
1372
+ }
1373
+ if any(
1374
+ other["label"] == "CITY"
1375
+ and spans_overlap(candidate_span, other)
1376
+ and (int(other["end"]) - int(other["start"])) >= (end - start)
1377
+ for other in repaired
1378
+ ):
1379
+ continue
1380
+ repaired = [
1381
+ other
1382
+ for other in repaired
1383
+ if not (
1384
+ spans_overlap(candidate_span, other)
1385
+ and other["label"] in {"CITY", "FIRST_NAME", "LAST_NAME"}
1386
+ )
1387
+ ]
1388
+ repaired.append(candidate_span)
1389
+ return repaired
1390
+
1391
+
1392
+ def repair_city_before_county(text: str, spans: list[dict]) -> list[dict]:
1393
+ repaired = list(spans)
1394
+ for regex in (CITY_TOWN_SUFFIX_RE, CITY_BEFORE_COUNTY_RE):
1395
+ for match in regex.finditer(text):
1396
+ start, end = match.span(1)
1397
+ value = text[start:end]
1398
+ if any(ch.isdigit() for ch in value):
1399
+ continue
1400
+ prefix = text[max(0, start - 20) : start]
1401
+ if CITY_COUNTY_PREFIX_RE.search(prefix):
1402
+ continue
1403
+ cue_window = text[max(0, start - 40) : min(len(text), end + 24)]
1404
+ if not ((CITY_CUE_RE.search(cue_window) or ADDRESS_CUE_RE.search(cue_window)) or re.search(r"^\s*,\s*(?:County|Contae|gContae|Co\.)\b", text[end:])):
1405
+ continue
1406
+ candidate_span = {
1407
+ "start": start,
1408
+ "end": end,
1409
+ "label": "CITY",
1410
+ "score": 0.64,
1411
+ "text": value,
1412
+ }
1413
+ if any(
1414
+ other["label"] == "CITY"
1415
+ and spans_overlap(candidate_span, other)
1416
+ and (int(other["end"]) - int(other["start"])) >= (end - start)
1417
+ for other in repaired
1418
+ ):
1419
+ continue
1420
+ repaired = [
1421
+ other
1422
+ for other in repaired
1423
+ if not (
1424
+ spans_overlap(candidate_span, other)
1425
+ and other["label"] in {"CITY", "FIRST_NAME", "LAST_NAME"}
1426
+ )
1427
+ ]
1428
+ repaired.append(candidate_span)
1429
+ return repaired
1430
+
1431
+
1432
+ def repair_city_field_cues(text: str, spans: list[dict]) -> list[dict]:
1433
+ repaired = list(spans)
1434
+ for match in CITY_FIELD_VALUE_RE.finditer(text):
1435
+ start, end = match.span(1)
1436
+ candidate_span = {
1437
+ "start": start,
1438
+ "end": end,
1439
+ "label": "CITY",
1440
+ "score": 0.65,
1441
+ "text": text[start:end],
1442
+ }
1443
+ repaired = [
1444
+ other
1445
+ for other in repaired
1446
+ if not (
1447
+ spans_overlap(candidate_span, other)
1448
+ and other["label"] in {"CITY", "COUNTY", "FIRST_NAME", "LAST_NAME"}
1449
+ )
1450
+ ]
1451
+ repaired.append(candidate_span)
1452
+ return repaired
1453
+
1454
+
1455
+ def repair_prefixed_city_spans(text: str, spans: list[dict]) -> list[dict]:
1456
+ repaired: list[dict] = []
1457
+ for span in spans:
1458
+ if span["label"] != "CITY":
1459
+ repaired.append(span)
1460
+ continue
1461
+ start = int(span["start"])
1462
+ end = int(span["end"])
1463
+ if start <= 0:
1464
+ repaired.append(span)
1465
+ continue
1466
+ prefix_char = text[start - 1]
1467
+ if prefix_char.lower() not in IRISH_CITY_PREFIX_CHARS:
1468
+ repaired.append(span)
1469
+ continue
1470
+ if start - 1 > 0 and text[start - 2].isalpha():
1471
+ repaired.append(span)
1472
+ continue
1473
+ if normalize_surface(span.get("text", "")) not in IRISH_CITY_SURFACES:
1474
+ repaired.append(span)
1475
+ continue
1476
+ candidate_start = start - 1
1477
+ candidate_text = text[candidate_start:end]
1478
+ repaired.append(
1479
+ {
1480
+ **span,
1481
+ "start": candidate_start,
1482
+ "text": candidate_text,
1483
+ "score": max(float(span.get("score", 0.0)), 0.66),
1484
+ }
1485
+ )
1486
+ return repaired
1487
+
1488
+
1489
+ def prefer_long_city_spans(spans: list[dict]) -> list[dict]:
1490
+ if not spans:
1491
+ return spans
1492
+ keep: list[dict] = []
1493
+ for span in spans:
1494
+ if span["label"] != "CITY":
1495
+ keep.append(span)
1496
+ continue
1497
+ shadowed = False
1498
+ for other in spans:
1499
+ if other is span or other["label"] != "CITY":
1500
+ continue
1501
+ if int(other["start"]) <= int(span["start"]) and int(other["end"]) >= int(span["end"]):
1502
+ if (int(other["start"]), int(other["end"])) != (int(span["start"]), int(span["end"])):
1503
+ if float(other.get("score", 0.0)) >= max(0.6, float(span.get("score", 0.0)) * 0.6):
1504
+ shadowed = True
1505
+ break
1506
+ if not shadowed:
1507
+ keep.append(span)
1508
+ return keep
1509
+
1510
+
1511
+ def repair_county_field_cues(text: str, spans: list[dict]) -> list[dict]:
1512
+ repaired = list(spans)
1513
+ for match in COUNTY_FIELD_VALUE_RE.finditer(text):
1514
+ start, end = match.span(1)
1515
+ candidate_span = {
1516
+ "start": start,
1517
+ "end": end,
1518
+ "label": "COUNTY",
1519
+ "score": 0.66,
1520
+ "text": text[start:end],
1521
+ }
1522
+ repaired = [
1523
+ other
1524
+ for other in repaired
1525
+ if not (
1526
+ spans_overlap(candidate_span, other)
1527
+ and other["label"] in {"COUNTY", "CITY", "FIRST_NAME", "LAST_NAME"}
1528
+ )
1529
+ ]
1530
+ repaired.append(candidate_span)
1531
+ return repaired
1532
+
1533
+
1534
+ def repair_county_spans(text: str, spans: list[dict]) -> list[dict]:
1535
+ repaired = list(spans)
1536
+ seen: set[tuple[int, int]] = set()
1537
+ ordered_forms = sorted(IRISH_COUNTY_FORMS, key=len, reverse=True)
1538
+ for form in ordered_forms:
1539
+ for match in iter_bounded_form_matches(form, text):
1540
+ start, end = match.span()
1541
+ key = (start, end)
1542
+ if key in seen:
1543
+ continue
1544
+ seen.add(key)
1545
+ candidate_span = {
1546
+ "start": start,
1547
+ "end": end,
1548
+ "label": "COUNTY",
1549
+ "score": 0.74,
1550
+ "text": text[start:end],
1551
+ }
1552
+ if not is_reasonable_span_text("COUNTY", text, start, end):
1553
+ continue
1554
+ overlapping_counties = [
1555
+ other
1556
+ for other in repaired
1557
+ if spans_overlap(candidate_span, other) and other["label"] == "COUNTY"
1558
+ ]
1559
+ if overlapping_counties:
1560
+ candidate_span["score"] = max(
1561
+ float(candidate_span["score"]),
1562
+ max(float(other.get("score", 0.0)) for other in overlapping_counties),
1563
+ )
1564
+ conflicting_labels = {"COUNTY", "CITY", "FIRST_NAME", "LAST_NAME"}
1565
+ repaired = [
1566
+ other
1567
+ for other in repaired
1568
+ if not (
1569
+ spans_overlap(candidate_span, other)
1570
+ and other["label"] in conflicting_labels
1571
+ )
1572
+ ]
1573
+ repaired.append(candidate_span)
1574
+ for match in COUNTY_VALUE_RE.finditer(text):
1575
+ start, end = match.span(1)
1576
+ key = (start, end)
1577
+ if key in seen:
1578
+ continue
1579
+ context = text[max(0, start - 40) : min(len(text), end + 24)]
1580
+ has_context = bool(ADDRESS_CUE_RE.search(context) or POSTCODE_VALUE_RE.search(context))
1581
+ if not has_context:
1582
+ for other in repaired:
1583
+ other_start = int(other["start"])
1584
+ other_end = int(other["end"])
1585
+ if other["label"] in {"STREET_ADDRESS", "CITY", "POSTCODE"} and (
1586
+ abs(other_start - end) <= 24 or abs(start - other_end) <= 24
1587
+ ):
1588
+ has_context = True
1589
+ break
1590
+ if not has_context:
1591
+ continue
1592
+ seen.add(key)
1593
+ candidate_span = {
1594
+ "start": start,
1595
+ "end": end,
1596
+ "label": "COUNTY",
1597
+ "score": 0.74,
1598
+ "text": text[start:end],
1599
+ }
1600
+ if not is_reasonable_span_text("COUNTY", text, start, end):
1601
+ continue
1602
+ conflicting_labels = {"COUNTY", "CITY", "FIRST_NAME", "LAST_NAME"}
1603
+ repaired = [
1604
+ other
1605
+ for other in repaired
1606
+ if not (
1607
+ spans_overlap(candidate_span, other)
1608
+ and other["label"] in conflicting_labels
1609
+ )
1610
+ ]
1611
+ repaired.append(candidate_span)
1612
+ return repaired
1613
+
1614
+
1615
+ def repair_street_addresses(text: str, spans: list[dict]) -> list[dict]:
1616
+ repaired = list(spans)
1617
+ seen: set[tuple[int, int]] = set()
1618
+ for match in STREET_ADDRESS_VALUE_RE.finditer(text):
1619
+ start, end = match.span(1)
1620
+ key = (start, end)
1621
+ if key in seen:
1622
+ continue
1623
+ seen.add(key)
1624
+ candidate_span = {
1625
+ "start": start,
1626
+ "end": end,
1627
+ "label": "STREET_ADDRESS",
1628
+ "score": 0.65,
1629
+ "text": text[start:end],
1630
+ }
1631
+ if not is_reasonable_span_text("STREET_ADDRESS", text, start, end):
1632
+ continue
1633
+ context = text[max(0, start - 32) : min(len(text), end + 24)]
1634
+ has_context = bool(ADDRESS_CUE_RE.search(context))
1635
+ if not has_context:
1636
+ for other in repaired:
1637
+ other_start = int(other["start"])
1638
+ other_end = int(other["end"])
1639
+ if other["label"] in {"CITY", "COUNTY", "POSTCODE"} and 0 <= other_start - end <= 16:
1640
+ has_context = True
1641
+ break
1642
+ if other["label"] in {"FIRST_NAME", "LAST_NAME"} and 0 <= start - other_end <= 24:
1643
+ has_context = True
1644
+ break
1645
+ if not has_context:
1646
+ continue
1647
+ conflicting_labels = {"STREET_ADDRESS", "FIRST_NAME", "LAST_NAME"}
1648
+ repaired = [
1649
+ other
1650
+ for other in repaired
1651
+ if not (
1652
+ spans_overlap(candidate_span, other)
1653
+ and other["label"] in conflicting_labels
1654
+ )
1655
+ ]
1656
+ repaired.append(candidate_span)
1657
+ return repaired
1658
+
1659
+
1660
+ def repair_contextual_address_blocks(text: str, spans: list[dict]) -> list[dict]:
1661
+ repaired = list(spans)
1662
+ for match in ADDRESS_BLOCK_VALUE_RE.finditer(text):
1663
+ start, end = match.span(1)
1664
+ value = text[start:end].strip()
1665
+ if not value:
1666
+ continue
1667
+ candidate_span = {
1668
+ "start": start,
1669
+ "end": end,
1670
+ "label": "STREET_ADDRESS",
1671
+ "score": 0.68,
1672
+ "text": text[start:end],
1673
+ }
1674
+ tokens = [token for token in re.split(r"\s+", value) if token]
1675
+ if len(tokens) < 2:
1676
+ continue
1677
+ if not (
1678
+ any(ch.isdigit() for ch in value)
1679
+ or ADDRESS_UNIT_PREFIX_RE.match(value)
1680
+ or HOUSE_NAME_PREFIX_RE.match(value)
1681
+ ):
1682
+ continue
1683
+ if any(
1684
+ other["label"] == "STREET_ADDRESS"
1685
+ and int(other["start"]) <= start
1686
+ and int(other["end"]) >= end
1687
+ and (int(other["start"]), int(other["end"])) != (start, end)
1688
+ for other in repaired
1689
+ ):
1690
+ continue
1691
+ conflicting_labels = {"STREET_ADDRESS", "FIRST_NAME", "LAST_NAME"}
1692
+ repaired = [
1693
+ other
1694
+ for other in repaired
1695
+ if not (
1696
+ spans_overlap(candidate_span, other)
1697
+ and other["label"] in conflicting_labels
1698
+ )
1699
+ ]
1700
+ repaired.append(candidate_span)
1701
+ return repaired
1702
+
1703
+
1704
+ def extend_prefixed_street_address_spans(text: str, spans: list[dict]) -> list[dict]:
1705
+ repaired: list[dict] = []
1706
+ tail_re = re.compile(
1707
+ r"^\s*,\s*((?:\d{1,4}\s+)?(?:[A-ZÁÉÍÓÚa-záéíóú][\w'’.-]*\s+){0,5}(?:street|road|avenue|lane|park|view|square|terrace|drive|close|way|place|crescent|grove|green|court|manor|mews|gardens?|heights|quay|bóthar|bothar|sráid|sraid|lána|lana)(?:\s+[A-ZÁÉÍÓÚa-záéíóú][\w'’.-]*){0,2})",
1708
+ flags=re.IGNORECASE,
1709
+ )
1710
+ for span in spans:
1711
+ if span["label"] != "STREET_ADDRESS":
1712
+ repaired.append(span)
1713
+ continue
1714
+ value = span.get("text", "").strip()
1715
+ if not value or not (ADDRESS_UNIT_PREFIX_RE.match(value) or HOUSE_NAME_PREFIX_RE.match(value)):
1716
+ repaired.append(span)
1717
+ continue
1718
+ tail_match = tail_re.match(text[int(span["end"]) :])
1719
+ if not tail_match:
1720
+ repaired.append(span)
1721
+ continue
1722
+ extended_end = int(span["end"]) + int(tail_match.end(1))
1723
+ repaired.append(
1724
+ {
1725
+ **span,
1726
+ "end": extended_end,
1727
+ "text": text[int(span["start"]) : extended_end],
1728
+ "score": max(float(span.get("score", 0.0)), 0.67),
1729
+ }
1730
+ )
1731
+ return repaired
1732
+
1733
+
1734
+ def repair_contextual_address_place_blocks(text: str, spans: list[dict]) -> list[dict]:
1735
+ repaired = list(spans)
1736
+ for match in ADDRESS_PLACE_VALUE_RE.finditer(text):
1737
+ start, end = match.span(1)
1738
+ candidate_span = {
1739
+ "start": start,
1740
+ "end": end,
1741
+ "label": "STREET_ADDRESS",
1742
+ "score": 0.69,
1743
+ "text": text[start:end],
1744
+ }
1745
+ repaired = [
1746
+ other
1747
+ for other in repaired
1748
+ if not (
1749
+ spans_overlap(candidate_span, other)
1750
+ and other["label"] in {"STREET_ADDRESS", "FIRST_NAME", "LAST_NAME", "CITY"}
1751
+ )
1752
+ ]
1753
+ repaired.append(candidate_span)
1754
+ return repaired
1755
+
1756
+
1757
+ def prefer_long_street_address_spans(spans: list[dict]) -> list[dict]:
1758
+ if not spans:
1759
+ return spans
1760
+ keep: list[dict] = []
1761
+ for span in spans:
1762
+ if span["label"] != "STREET_ADDRESS":
1763
+ keep.append(span)
1764
+ continue
1765
+ shadowed = False
1766
+ for other in spans:
1767
+ if other is span or other["label"] != "STREET_ADDRESS":
1768
+ continue
1769
+ if int(other["start"]) <= int(span["start"]) and int(other["end"]) >= int(span["end"]):
1770
+ if (int(other["start"]), int(other["end"])) != (int(span["start"]), int(span["end"])):
1771
+ shadowed = True
1772
+ break
1773
+ if not shadowed:
1774
+ keep.append(span)
1775
+ return keep
1776
+
1777
+
1778
+ def drop_contextual_fragment_spans(spans: list[dict]) -> list[dict]:
1779
+ if not spans:
1780
+ return spans
1781
+ suppressors = {"COUNTY", "CITY", "POSTCODE", "STREET_ADDRESS", "DATE_OF_BIRTH"}
1782
+ keep: list[dict] = []
1783
+ for span in spans:
1784
+ if span["label"] in {"FIRST_NAME", "LAST_NAME"}:
1785
+ if any(
1786
+ other is not span
1787
+ and other["label"] in suppressors
1788
+ and spans_overlap(span, other)
1789
+ and (int(other["end"]) - int(other["start"])) >= (int(span["end"]) - int(span["start"]))
1790
+ for other in spans
1791
+ ):
1792
+ continue
1793
+ if span["label"] == "CITY":
1794
+ if any(
1795
+ other is not span
1796
+ and other["label"] == "COUNTY"
1797
+ and spans_overlap(span, other)
1798
+ and (int(other["end"]) - int(other["start"])) >= (int(span["end"]) - int(span["start"]))
1799
+ for other in spans
1800
+ ):
1801
+ continue
1802
+ keep.append(span)
1803
+ return keep
1804
+
1805
+
1806
+ def drop_public_contact_detail_spans(text: str, spans: list[dict]) -> list[dict]:
1807
+ if not PUBLIC_CONTACT_DETAILS_RE.search(text):
1808
+ return spans
1809
+ keep: list[dict] = []
1810
+ for span in spans:
1811
+ if span["label"] not in {"STREET_ADDRESS", "CITY", "COUNTY"}:
1812
+ keep.append(span)
1813
+ continue
1814
+ keep.append(span)
1815
+ return [
1816
+ span for span in keep
1817
+ if not (span["label"] in {"STREET_ADDRESS", "CITY", "COUNTY"} and PUBLIC_CONTACT_DETAILS_RE.search(text))
1818
+ ]
1819
+
1820
+
1821
+ def drop_org_like_name_spans(text: str, spans: list[dict]) -> list[dict]:
1822
+ keep: list[dict] = []
1823
+ for span in spans:
1824
+ if span["label"] not in {"FIRST_NAME", "LAST_NAME"}:
1825
+ keep.append(span)
1826
+ continue
1827
+ tokens = [normalize_surface(token) for token in re.split(r"\s+", span.get("text", "").strip()) if token]
1828
+ if tokens and tokens[-1] in ORG_NAME_TRAILING_SURFACES:
1829
+ continue
1830
+ prefix = text[max(0, int(span["start"]) - 32) : int(span["start"])]
1831
+ if ORG_NAME_PREFIX_RE.search(prefix):
1832
+ continue
1833
+ keep.append(span)
1834
+ return keep
1835
+
1836
+
1837
+ def drop_city_org_prefix_spans(text: str, spans: list[dict]) -> list[dict]:
1838
+ keep: list[dict] = []
1839
+ for span in spans:
1840
+ if span["label"] != "CITY":
1841
+ keep.append(span)
1842
+ continue
1843
+ tail = text[int(span["end"]) : min(len(text), int(span["end"]) + 24)]
1844
+ if ORG_CITY_TAIL_RE.match(tail):
1845
+ continue
1846
+ keep.append(span)
1847
+ return keep
1848
+
1849
+
1850
+ def canonicalize_location_spans(text: str, spans: list[dict]) -> list[dict]:
1851
+ repaired: list[dict] = []
1852
+ for span in spans:
1853
+ if span["label"] not in {"CITY", "COUNTY"}:
1854
+ repaired.append(span)
1855
+ continue
1856
+ start = int(span["start"])
1857
+ end = int(span["end"])
1858
+ while end > start and text[end - 1] in ".,;:":
1859
+ end -= 1
1860
+ repaired.append(
1861
+ {
1862
+ **span,
1863
+ "end": end,
1864
+ "text": text[start:end],
1865
+ }
1866
+ )
1867
+ return repaired
1868
+
1869
+
1870
+ def canonicalize_email_spans(text: str, spans: list[dict]) -> list[dict]:
1871
+ repaired: list[dict] = []
1872
+ for span in spans:
1873
+ if span["label"] != "EMAIL":
1874
+ repaired.append(span)
1875
+ continue
1876
+ segment = text[int(span["start"]) : int(span["end"])]
1877
+ match = EMAIL_EXTRACT_RE.search(segment)
1878
+ if not match:
1879
+ repaired.append(span)
1880
+ continue
1881
+ start = int(span["start"]) + int(match.start(1))
1882
+ end = int(span["start"]) + int(match.end(1))
1883
+ repaired.append(
1884
+ {
1885
+ **span,
1886
+ "start": start,
1887
+ "end": end,
1888
+ "text": text[start:end],
1889
+ }
1890
+ )
1891
+ return repaired
1892
+
1893
+
1894
+ def drop_stacked_first_names(spans: list[dict]) -> list[dict]:
1895
+ if not spans:
1896
+ return spans
1897
+ first_names = [span for span in spans if span["label"] == "FIRST_NAME"]
1898
+ last_names = [span for span in spans if span["label"] == "LAST_NAME"]
1899
+ if not first_names or not last_names:
1900
+ return spans
1901
+ keep: list[dict] = []
1902
+ for span in spans:
1903
+ if span["label"] != "FIRST_NAME":
1904
+ keep.append(span)
1905
+ continue
1906
+ shadowed = False
1907
+ for other in first_names:
1908
+ if other is span:
1909
+ continue
1910
+ if int(other["start"]) <= int(span["start"]):
1911
+ continue
1912
+ if int(other["start"]) - int(span["end"]) > 2:
1913
+ continue
1914
+ if not any(
1915
+ int(last["start"]) >= int(other["end"]) and int(last["start"]) - int(other["end"]) <= 2
1916
+ for last in last_names
1917
+ ):
1918
+ continue
1919
+ shadowed = True
1920
+ break
1921
+ if not shadowed:
1922
+ keep.append(span)
1923
+ return keep
1924
+
1925
+
1926
+ def decode_span_matrix(
1927
+ text: str,
1928
+ offsets: list[tuple[int, int]],
1929
+ span_scores: np.ndarray,
1930
+ config,
1931
+ min_score: float,
1932
+ ) -> list[dict]:
1933
+ label_names = label_names_from_config(config)
1934
+ thresholds = label_thresholds_from_config(config, min_score)
1935
+ max_span_tokens = label_max_span_tokens_from_config(config)
1936
+ min_nonspace_chars = label_min_nonspace_chars_from_config(config)
1937
+
1938
+ if span_scores.ndim != 3:
1939
+ raise ValueError(f"Expected [num_labels, seq_len, seq_len] span scores, got shape {span_scores.shape}")
1940
+
1941
+ num_labels, seq_len, _ = span_scores.shape
1942
+ spans: list[dict] = []
1943
+ for label_index in range(min(num_labels, len(label_names))):
1944
+ label = label_names[label_index]
1945
+ threshold = thresholds.get(label, min_score)
1946
+ max_width = max(1, int(max_span_tokens.get(label, 8)))
1947
+ min_chars = max(1, int(min_nonspace_chars.get(label, 1)))
1948
+
1949
+ for start_idx in range(seq_len):
1950
+ start_offset = offsets[start_idx]
1951
+ if not valid_offset(start_offset):
1952
+ continue
1953
+ max_end = min(seq_len, start_idx + max_width)
1954
+ for end_idx in range(start_idx, max_end):
1955
+ end_offset = offsets[end_idx]
1956
+ if not valid_offset(end_offset):
1957
+ continue
1958
+ score = float(span_scores[label_index, start_idx, end_idx])
1959
+ if score < threshold:
1960
+ continue
1961
+ start_char = int(start_offset[0])
1962
+ end_char = int(end_offset[1])
1963
+ if end_char <= start_char:
1964
+ continue
1965
+ if nonspace_length(text, start_char, end_char) < min_chars:
1966
+ continue
1967
+ if not is_reasonable_span_text(label, text, start_char, end_char):
1968
+ continue
1969
+ spans.append(
1970
+ {
1971
+ "start": start_char,
1972
+ "end": end_char,
1973
+ "label": label,
1974
+ "score": score,
1975
+ "text": text[start_char:end_char],
1976
+ }
1977
+ )
1978
+ spans = prefer_long_name_spans(spans, thresholds)
1979
+ spans = prefer_long_structured_spans(spans, thresholds)
1980
+ spans = repair_first_name_from_last_name(text, spans)
1981
+ spans = repair_emails(text, spans)
1982
+ spans = repair_phone_numbers(text, spans)
1983
+ spans = repair_ppsn_variants(text, spans)
1984
+ spans = repair_postcodes(text, spans)
1985
+ spans = repair_street_addresses(text, spans)
1986
+ spans = repair_contextual_name_cues(text, spans)
1987
+ spans = repair_role_name_cues(text, spans)
1988
+ spans = repair_surname_field_cues(text, spans)
1989
+ spans = repair_name_before_structured_cues(text, spans)
1990
+ spans = repair_contextual_address_blocks(text, spans)
1991
+ spans = extend_prefixed_street_address_spans(text, spans)
1992
+ spans = repair_contextual_address_place_blocks(text, spans)
1993
+ spans = prefer_long_street_address_spans(spans)
1994
+ spans = repair_county_spans(text, spans)
1995
+ spans = repair_city_spans(text, spans)
1996
+ spans = repair_city_before_postcode(text, spans)
1997
+ spans = repair_city_before_county(text, spans)
1998
+ spans = repair_city_field_cues(text, spans)
1999
+ spans = repair_prefixed_city_spans(text, spans)
2000
+ spans = prefer_long_city_spans(spans)
2001
+ spans = repair_county_field_cues(text, spans)
2002
+ spans = repair_contextual_date_of_birth(text, spans)
2003
+ spans = repair_contextual_ages(text, spans)
2004
+ spans = repair_contextual_passport_numbers(text, spans)
2005
+ spans = repair_contextual_account_numbers(text, spans)
2006
+ spans = drop_public_contact_detail_spans(text, spans)
2007
+ spans = drop_org_like_name_spans(text, spans)
2008
+ spans = drop_city_org_prefix_spans(text, spans)
2009
+ spans = drop_stacked_first_names(spans)
2010
+ spans = drop_contextual_fragment_spans(spans)
2011
+ spans = canonicalize_location_spans(text, spans)
2012
+ spans = canonicalize_email_spans(text, spans)
2013
+ return dedupe_spans(spans)
2014
+
2015
+
2016
+ def prefer_long_name_spans(spans: list[dict], thresholds: dict[str, float]) -> list[dict]:
2017
+ if not spans:
2018
+ return spans
2019
+ preferred: list[dict] = []
2020
+ consumed: set[int] = set()
2021
+ for index, span in enumerate(spans):
2022
+ if index in consumed:
2023
+ continue
2024
+ label = span["label"]
2025
+ if label not in {"FIRST_NAME", "LAST_NAME"}:
2026
+ preferred.append(span)
2027
+ continue
2028
+ same_start = [
2029
+ (other_index, other)
2030
+ for other_index, other in enumerate(spans)
2031
+ if other_index not in consumed and other["label"] == label and other["start"] == span["start"]
2032
+ ]
2033
+ if len(same_start) == 1:
2034
+ preferred.append(span)
2035
+ continue
2036
+ for other_index, _ in same_start:
2037
+ consumed.add(other_index)
2038
+ best_by_score = max(same_start, key=lambda item: float(item[1].get("score", 0.0)))[1]
2039
+ longest = max(same_start, key=lambda item: (item[1]["end"] - item[1]["start"], float(item[1].get("score", 0.0))))[1]
2040
+ threshold = float(thresholds.get(label, 0.5))
2041
+ if float(longest.get("score", 0.0)) >= max(threshold + 0.15, float(best_by_score.get("score", 0.0)) * 0.7):
2042
+ preferred.append(longest)
2043
+ else:
2044
+ preferred.append(best_by_score)
2045
+ return prefer_same_end_extensions(preferred, thresholds)
2046
+
2047
+
2048
+ def prefer_same_end_extensions(spans: list[dict], thresholds: dict[str, float]) -> list[dict]:
2049
+ if not spans:
2050
+ return spans
2051
+ preferred: list[dict] = []
2052
+ consumed: set[int] = set()
2053
+ for index, span in enumerate(spans):
2054
+ if index in consumed:
2055
+ continue
2056
+ label = span["label"]
2057
+ if label not in {"FIRST_NAME", "LAST_NAME", "EMAIL"}:
2058
+ preferred.append(span)
2059
+ continue
2060
+ same_end = [
2061
+ (other_index, other)
2062
+ for other_index, other in enumerate(spans)
2063
+ if other_index not in consumed and other["label"] == label and other["end"] == span["end"]
2064
+ ]
2065
+ if len(same_end) == 1:
2066
+ preferred.append(span)
2067
+ continue
2068
+ for other_index, _ in same_end:
2069
+ consumed.add(other_index)
2070
+ best_by_score = max(same_end, key=lambda item: float(item[1].get("score", 0.0)))[1]
2071
+ longest = max(same_end, key=lambda item: (item[1]["end"] - item[1]["start"], float(item[1].get("score", 0.0))))[1]
2072
+ longest_score = float(longest.get("score", 0.0))
2073
+ best_score = float(best_by_score.get("score", 0.0))
2074
+ if label == "EMAIL":
2075
+ if "@" in longest.get("text", "") or longest["end"] - longest["start"] > best_by_score["end"] - best_by_score["start"]:
2076
+ if longest_score >= best_score - 0.02:
2077
+ preferred.append(longest)
2078
+ continue
2079
+ else:
2080
+ longest_text = longest.get("text", "")
2081
+ if " " not in longest_text.strip() and longest_score >= max(float(thresholds.get(label, 0.5)) * 0.8, best_score * 0.55):
2082
+ preferred.append(longest)
2083
+ continue
2084
+ preferred.append(best_by_score)
2085
+ return preferred
2086
+
2087
+
2088
+ def prefer_long_structured_spans(spans: list[dict], thresholds: dict[str, float]) -> list[dict]:
2089
+ if not spans:
2090
+ return spans
2091
+ preferred: list[dict] = []
2092
+ consumed: set[int] = set()
2093
+ target_labels = {"STREET_ADDRESS", "DATE_OF_BIRTH"}
2094
+ for index, span in enumerate(spans):
2095
+ if index in consumed:
2096
+ continue
2097
+ label = span["label"]
2098
+ if label not in target_labels:
2099
+ preferred.append(span)
2100
+ continue
2101
+ overlapping = [
2102
+ (other_index, other)
2103
+ for other_index, other in enumerate(spans)
2104
+ if other_index not in consumed and other["label"] == label and spans_overlap(span, other)
2105
+ ]
2106
+ if len(overlapping) == 1:
2107
+ preferred.append(span)
2108
+ continue
2109
+ for other_index, _ in overlapping:
2110
+ consumed.add(other_index)
2111
+ best_by_score = max(overlapping, key=lambda item: float(item[1].get("score", 0.0)))[1]
2112
+ longest = max(
2113
+ overlapping,
2114
+ key=lambda item: (item[1]["end"] - item[1]["start"], float(item[1].get("score", 0.0))),
2115
+ )[1]
2116
+ longest_score = float(longest.get("score", 0.0))
2117
+ best_score = float(best_by_score.get("score", 0.0))
2118
+ threshold = float(thresholds.get(label, 0.5))
2119
+ if longest_score >= max(threshold, best_score * 0.75):
2120
+ preferred.append(longest)
2121
+ else:
2122
+ preferred.append(best_by_score)
2123
+ return preferred
2124
+
2125
+
2126
+ def sigmoid_np(values: np.ndarray) -> np.ndarray:
2127
+ clipped = np.clip(values, -60.0, 60.0)
2128
+ return 1.0 / (1.0 + np.exp(-clipped))
2129
+
2130
+
2131
+ def run_onnx_span(session, encoded: dict[str, Any]) -> np.ndarray:
2132
+ feed = {}
2133
+ input_names = {item.name for item in session.get_inputs()}
2134
+ for key, value in encoded.items():
2135
+ if key == "offset_mapping":
2136
+ continue
2137
+ if key in input_names:
2138
+ feed[key] = value
2139
+ outputs = session.run(None, feed)
2140
+ if not outputs:
2141
+ raise ValueError("ONNX session returned no outputs")
2142
+ return outputs[0]
config.json ADDED
@@ -0,0 +1,318 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "activation": "gelu",
3
+ "architectures": [
4
+ "IrishCoreGlobalPointerModel"
5
+ ],
6
+ "attention_dropout": 0.1,
7
+ "dim": 768,
8
+ "dropout": 0.1,
9
+ "dtype": "float32",
10
+ "global_pointer_head_size": 64,
11
+ "global_pointer_min_negatives": 256,
12
+ "global_pointer_negative_ratio": 16,
13
+ "global_pointer_use_rope": true,
14
+ "hidden_dim": 3072,
15
+ "id2label": {
16
+ "0": "O",
17
+ "1": "B-account_number",
18
+ "2": "B-age",
19
+ "3": "B-api_key",
20
+ "4": "B-bank_routing_number",
21
+ "5": "B-biometric_identifier",
22
+ "6": "B-blood_type",
23
+ "7": "B-certificate_license_number",
24
+ "8": "B-city",
25
+ "9": "B-company_name",
26
+ "10": "B-coordinate",
27
+ "11": "B-country",
28
+ "12": "B-county",
29
+ "13": "B-credit_debit_card",
30
+ "14": "B-customer_id",
31
+ "15": "B-cvv",
32
+ "16": "B-date",
33
+ "17": "B-date_of_birth",
34
+ "18": "B-date_time",
35
+ "19": "B-device_identifier",
36
+ "20": "B-education_level",
37
+ "21": "B-email",
38
+ "22": "B-employee_id",
39
+ "23": "B-employment_status",
40
+ "24": "B-fax_number",
41
+ "25": "B-first_name",
42
+ "26": "B-gender",
43
+ "27": "B-health_plan_beneficiary_number",
44
+ "28": "B-http_cookie",
45
+ "29": "B-ipv4",
46
+ "30": "B-ipv6",
47
+ "31": "B-language",
48
+ "32": "B-last_name",
49
+ "33": "B-license_plate",
50
+ "34": "B-mac_address",
51
+ "35": "B-medical_record_number",
52
+ "36": "B-occupation",
53
+ "37": "B-password",
54
+ "38": "B-phone_number",
55
+ "39": "B-pin",
56
+ "40": "B-political_view",
57
+ "41": "B-postcode",
58
+ "42": "B-race_ethnicity",
59
+ "43": "B-religious_belief",
60
+ "44": "B-sexuality",
61
+ "45": "B-ssn",
62
+ "46": "B-state",
63
+ "47": "B-street_address",
64
+ "48": "B-swift_bic",
65
+ "49": "B-tax_id",
66
+ "50": "B-time",
67
+ "51": "B-unique_id",
68
+ "52": "B-url",
69
+ "53": "B-user_name",
70
+ "54": "B-vehicle_identifier",
71
+ "55": "I-account_number",
72
+ "56": "I-api_key",
73
+ "57": "I-biometric_identifier",
74
+ "58": "I-blood_type",
75
+ "59": "I-certificate_license_number",
76
+ "60": "I-city",
77
+ "61": "I-company_name",
78
+ "62": "I-coordinate",
79
+ "63": "I-country",
80
+ "64": "I-county",
81
+ "65": "I-credit_debit_card",
82
+ "66": "I-customer_id",
83
+ "67": "I-date",
84
+ "68": "I-date_of_birth",
85
+ "69": "I-date_time",
86
+ "70": "I-device_identifier",
87
+ "71": "I-education_level",
88
+ "72": "I-email",
89
+ "73": "I-employee_id",
90
+ "74": "I-employment_status",
91
+ "75": "I-fax_number",
92
+ "76": "I-first_name",
93
+ "77": "I-gender",
94
+ "78": "I-health_plan_beneficiary_number",
95
+ "79": "I-http_cookie",
96
+ "80": "I-ipv4",
97
+ "81": "I-ipv6",
98
+ "82": "I-language",
99
+ "83": "I-last_name",
100
+ "84": "I-license_plate",
101
+ "85": "I-mac_address",
102
+ "86": "I-medical_record_number",
103
+ "87": "I-occupation",
104
+ "88": "I-password",
105
+ "89": "I-phone_number",
106
+ "90": "I-pin",
107
+ "91": "I-political_view",
108
+ "92": "I-postcode",
109
+ "93": "I-race_ethnicity",
110
+ "94": "I-religious_belief",
111
+ "95": "I-sexuality",
112
+ "96": "I-ssn",
113
+ "97": "I-state",
114
+ "98": "I-street_address",
115
+ "99": "I-swift_bic",
116
+ "100": "I-tax_id",
117
+ "101": "I-time",
118
+ "102": "I-unique_id",
119
+ "103": "I-url",
120
+ "104": "I-user_name",
121
+ "105": "I-vehicle_identifier"
122
+ },
123
+ "initializer_range": 0.02,
124
+ "label2id": {
125
+ "B-account_number": 1,
126
+ "B-age": 2,
127
+ "B-api_key": 3,
128
+ "B-bank_routing_number": 4,
129
+ "B-biometric_identifier": 5,
130
+ "B-blood_type": 6,
131
+ "B-certificate_license_number": 7,
132
+ "B-city": 8,
133
+ "B-company_name": 9,
134
+ "B-coordinate": 10,
135
+ "B-country": 11,
136
+ "B-county": 12,
137
+ "B-credit_debit_card": 13,
138
+ "B-customer_id": 14,
139
+ "B-cvv": 15,
140
+ "B-date": 16,
141
+ "B-date_of_birth": 17,
142
+ "B-date_time": 18,
143
+ "B-device_identifier": 19,
144
+ "B-education_level": 20,
145
+ "B-email": 21,
146
+ "B-employee_id": 22,
147
+ "B-employment_status": 23,
148
+ "B-fax_number": 24,
149
+ "B-first_name": 25,
150
+ "B-gender": 26,
151
+ "B-health_plan_beneficiary_number": 27,
152
+ "B-http_cookie": 28,
153
+ "B-ipv4": 29,
154
+ "B-ipv6": 30,
155
+ "B-language": 31,
156
+ "B-last_name": 32,
157
+ "B-license_plate": 33,
158
+ "B-mac_address": 34,
159
+ "B-medical_record_number": 35,
160
+ "B-occupation": 36,
161
+ "B-password": 37,
162
+ "B-phone_number": 38,
163
+ "B-pin": 39,
164
+ "B-political_view": 40,
165
+ "B-postcode": 41,
166
+ "B-race_ethnicity": 42,
167
+ "B-religious_belief": 43,
168
+ "B-sexuality": 44,
169
+ "B-ssn": 45,
170
+ "B-state": 46,
171
+ "B-street_address": 47,
172
+ "B-swift_bic": 48,
173
+ "B-tax_id": 49,
174
+ "B-time": 50,
175
+ "B-unique_id": 51,
176
+ "B-url": 52,
177
+ "B-user_name": 53,
178
+ "B-vehicle_identifier": 54,
179
+ "I-account_number": 55,
180
+ "I-api_key": 56,
181
+ "I-biometric_identifier": 57,
182
+ "I-blood_type": 58,
183
+ "I-certificate_license_number": 59,
184
+ "I-city": 60,
185
+ "I-company_name": 61,
186
+ "I-coordinate": 62,
187
+ "I-country": 63,
188
+ "I-county": 64,
189
+ "I-credit_debit_card": 65,
190
+ "I-customer_id": 66,
191
+ "I-date": 67,
192
+ "I-date_of_birth": 68,
193
+ "I-date_time": 69,
194
+ "I-device_identifier": 70,
195
+ "I-education_level": 71,
196
+ "I-email": 72,
197
+ "I-employee_id": 73,
198
+ "I-employment_status": 74,
199
+ "I-fax_number": 75,
200
+ "I-first_name": 76,
201
+ "I-gender": 77,
202
+ "I-health_plan_beneficiary_number": 78,
203
+ "I-http_cookie": 79,
204
+ "I-ipv4": 80,
205
+ "I-ipv6": 81,
206
+ "I-language": 82,
207
+ "I-last_name": 83,
208
+ "I-license_plate": 84,
209
+ "I-mac_address": 85,
210
+ "I-medical_record_number": 86,
211
+ "I-occupation": 87,
212
+ "I-password": 88,
213
+ "I-phone_number": 89,
214
+ "I-pin": 90,
215
+ "I-political_view": 91,
216
+ "I-postcode": 92,
217
+ "I-race_ethnicity": 93,
218
+ "I-religious_belief": 94,
219
+ "I-sexuality": 95,
220
+ "I-ssn": 96,
221
+ "I-state": 97,
222
+ "I-street_address": 98,
223
+ "I-swift_bic": 99,
224
+ "I-tax_id": 100,
225
+ "I-time": 101,
226
+ "I-unique_id": 102,
227
+ "I-url": 103,
228
+ "I-user_name": 104,
229
+ "I-vehicle_identifier": 105,
230
+ "O": 0
231
+ },
232
+ "max_position_embeddings": 512,
233
+ "model_type": "distilbert",
234
+ "n_heads": 12,
235
+ "n_layers": 6,
236
+ "num_span_labels": 16,
237
+ "output_past": true,
238
+ "pad_token_id": 0,
239
+ "qa_dropout": 0.1,
240
+ "seq_classif_dropout": 0.2,
241
+ "sinusoidal_pos_embds": false,
242
+ "span_label_max_span_tokens": {
243
+ "ACCOUNT_NUMBER": 19,
244
+ "AGE": 8,
245
+ "BANK_ROUTING_NUMBER": 6,
246
+ "CITY": 8,
247
+ "COUNTY": 8,
248
+ "CREDIT_DEBIT_CARD": 12,
249
+ "DATE_OF_BIRTH": 8,
250
+ "EMAIL": 16,
251
+ "FIRST_NAME": 6,
252
+ "LAST_NAME": 8,
253
+ "PASSPORT_NUMBER": 8,
254
+ "PHONE_NUMBER": 10,
255
+ "POSTCODE": 8,
256
+ "PPSN": 9,
257
+ "STREET_ADDRESS": 10,
258
+ "SWIFT_BIC": 8
259
+ },
260
+ "span_label_min_nonspace_chars": {
261
+ "ACCOUNT_NUMBER": 6,
262
+ "AGE": 1,
263
+ "BANK_ROUTING_NUMBER": 6,
264
+ "CITY": 1,
265
+ "COUNTY": 1,
266
+ "CREDIT_DEBIT_CARD": 12,
267
+ "DATE_OF_BIRTH": 1,
268
+ "EMAIL": 6,
269
+ "FIRST_NAME": 2,
270
+ "LAST_NAME": 2,
271
+ "PASSPORT_NUMBER": 7,
272
+ "PHONE_NUMBER": 7,
273
+ "POSTCODE": 6,
274
+ "PPSN": 8,
275
+ "STREET_ADDRESS": 1,
276
+ "SWIFT_BIC": 8
277
+ },
278
+ "span_label_names": [
279
+ "ACCOUNT_NUMBER",
280
+ "AGE",
281
+ "BANK_ROUTING_NUMBER",
282
+ "CITY",
283
+ "COUNTY",
284
+ "CREDIT_DEBIT_CARD",
285
+ "DATE_OF_BIRTH",
286
+ "EMAIL",
287
+ "FIRST_NAME",
288
+ "LAST_NAME",
289
+ "PASSPORT_NUMBER",
290
+ "PHONE_NUMBER",
291
+ "POSTCODE",
292
+ "PPSN",
293
+ "STREET_ADDRESS",
294
+ "SWIFT_BIC"
295
+ ],
296
+ "span_label_thresholds": {
297
+ "ACCOUNT_NUMBER": 0.5,
298
+ "AGE": 0.5,
299
+ "BANK_ROUTING_NUMBER": 0.5,
300
+ "CITY": 0.5,
301
+ "COUNTY": 0.5,
302
+ "CREDIT_DEBIT_CARD": 0.5,
303
+ "DATE_OF_BIRTH": 0.5,
304
+ "EMAIL": 0.5,
305
+ "FIRST_NAME": 0.5,
306
+ "LAST_NAME": 0.5,
307
+ "PASSPORT_NUMBER": 0.5,
308
+ "PHONE_NUMBER": 0.5,
309
+ "POSTCODE": 0.5,
310
+ "PPSN": 0.5,
311
+ "STREET_ADDRESS": 0.5,
312
+ "SWIFT_BIC": 0.5
313
+ },
314
+ "span_positive_weight": 8.0,
315
+ "tie_weights_": true,
316
+ "transformers_version": "4.57.6",
317
+ "vocab_size": 119547
318
+ }
eval/benchmark_summary.json ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "release": "IrishCore-GlobalPointer-ContextPII-135M-v1-rc15",
3
+ "repo_id": "temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc15",
4
+ "architecture": {
5
+ "family": "DistilBERT-size GlobalPointer span extractor",
6
+ "base_head": "typed span matrix",
7
+ "raw_only": true,
8
+ "scanner_free": true,
9
+ "validator_free": true,
10
+ "uses_rope": true,
11
+ "runtime_diffusion": false,
12
+ "expanded_context_labels": [
13
+ "STREET_ADDRESS",
14
+ "CITY",
15
+ "COUNTY",
16
+ "DATE_OF_BIRTH",
17
+ "AGE"
18
+ ]
19
+ },
20
+ "base_model": "OpenMed/OpenMed-PII-mLiteClinical-Base-135M-v1",
21
+ "notes": [
22
+ "This release keeps the rc14 weights and ONNX graph but strengthens the bundled decoder for Gaelic lenited address cues, city-before-county recovery, business-centre address blocks, generic county/city field cues, and structured-cue name recovery.",
23
+ "The decoder now fixes the new contextual red-team families added in v8 without regressing the earlier v7 contextual suite or the Irish core suite on the q8 deployment path.",
24
+ "The release also expands county handling for `Co.` forms and avoids the earlier county-field regression on `Contae na Mí` style address text.",
25
+ "The broader contextual policy still masks assistant-side street/city/county contact details on the policy-aligned suites; if you need the narrower structured-only line, prefer `temsa/IrishCore-GlobalPointer-135M-v1-rc4`."
26
+ ],
27
+ "labels": [
28
+ "ACCOUNT_NUMBER",
29
+ "AGE",
30
+ "BANK_ROUTING_NUMBER",
31
+ "CITY",
32
+ "COUNTY",
33
+ "CREDIT_DEBIT_CARD",
34
+ "DATE_OF_BIRTH",
35
+ "EMAIL",
36
+ "FIRST_NAME",
37
+ "LAST_NAME",
38
+ "PASSPORT_NUMBER",
39
+ "PHONE_NUMBER",
40
+ "POSTCODE",
41
+ "PPSN",
42
+ "STREET_ADDRESS",
43
+ "SWIFT_BIC"
44
+ ],
45
+ "full": {
46
+ "core_f1": 1.0,
47
+ "extended_f1": 1.0,
48
+ "demographic_holdout_v2_f1": 1.0,
49
+ "contact_policy_f1": 1.0,
50
+ "chatbot_redteam_v2_f1": 0.9861111111111112,
51
+ "chatbot_gap_holdout_v2_f1": 1.0,
52
+ "multilingual_f1": 0.9333333333333333,
53
+ "multilingual_ppsn_label_f1": 1.0,
54
+ "context_redteam_v1_f1": 1.0,
55
+ "context_redteam_v2_f1": 1.0,
56
+ "context_redteam_v3_f1": 1.0,
57
+ "core_examples_per_second": 37.17190773379781,
58
+ "extended_examples_per_second": 22.601031656884402,
59
+ "demographic_holdout_v2_examples_per_second": 56.27516807130541,
60
+ "contact_policy_examples_per_second": 20.47123147395747,
61
+ "chatbot_redteam_v2_examples_per_second": 29.843260084022578,
62
+ "chatbot_gap_holdout_v2_examples_per_second": 37.07473771144438,
63
+ "multilingual_examples_per_second": 58.68937370218514,
64
+ "context_redteam_v1_examples_per_second": 23.609073299571445,
65
+ "context_redteam_v2_examples_per_second": 12.737044489760402,
66
+ "context_redteam_v3_examples_per_second": 17.88102919943181,
67
+ "location_coverage_v1_f1": 1.0,
68
+ "location_coverage_v1_examples_per_second": 27.442453278347067,
69
+ "location_coverage_v2_f1": 1.0,
70
+ "location_coverage_v2_examples_per_second": 24.3613357869789,
71
+ "location_coverage_v3_f1": 1.0,
72
+ "location_coverage_v3_examples_per_second": 35.4459974931921,
73
+ "numeric_qafix_v2_f1": 1.0,
74
+ "numeric_qafix_v2_examples_per_second": 29.420131775628487,
75
+ "context_redteam_v4_f1": 1.0,
76
+ "context_redteam_v4_examples_per_second": 30.495521507704247,
77
+ "context_redteam_v5_f1": 1.0,
78
+ "context_redteam_v5_examples_per_second": 33.33418166561194,
79
+ "context_redteam_v6_f1": 1.0,
80
+ "context_redteam_v6_examples_per_second": 38.82008627943923,
81
+ "context_redteam_v7_f1": 1.0,
82
+ "context_redteam_v7_examples_per_second": 41.1670461610147,
83
+ "context_redteam_v8_f1": 1.0,
84
+ "context_redteam_v8_examples_per_second": 83.67568116564722
85
+ },
86
+ "onnx_q8": {
87
+ "core_f1": 1.0,
88
+ "extended_f1": 1.0,
89
+ "demographic_holdout_v2_f1": 1.0,
90
+ "contact_policy_f1": 1.0,
91
+ "chatbot_redteam_v2_f1": 0.9861111111111112,
92
+ "chatbot_gap_holdout_v2_f1": 1.0,
93
+ "multilingual_f1": 0.9333333333333333,
94
+ "multilingual_ppsn_label_f1": 1.0,
95
+ "context_redteam_v1_f1": 1.0,
96
+ "context_redteam_v2_f1": 1.0,
97
+ "context_redteam_v3_f1": 1.0,
98
+ "core_examples_per_second": 125.50543882985251,
99
+ "extended_examples_per_second": 83.16660601622321,
100
+ "demographic_holdout_v2_examples_per_second": 92.56832502112522,
101
+ "contact_policy_examples_per_second": 74.36759422903161,
102
+ "chatbot_redteam_v2_examples_per_second": 74.9870854931101,
103
+ "chatbot_gap_holdout_v2_examples_per_second": 76.36724293476742,
104
+ "multilingual_examples_per_second": 120.67076013818983,
105
+ "context_redteam_v1_examples_per_second": 77.35126547341245,
106
+ "context_redteam_v2_examples_per_second": 83.42976656780596,
107
+ "context_redteam_v3_examples_per_second": 115.78405703667622,
108
+ "location_coverage_v1_f1": 1.0,
109
+ "location_coverage_v1_examples_per_second": 86.67576551780107,
110
+ "location_coverage_v2_f1": 1.0,
111
+ "location_coverage_v2_examples_per_second": 63.49649295628558,
112
+ "location_coverage_v3_f1": 1.0,
113
+ "location_coverage_v3_examples_per_second": 103.87880730624308,
114
+ "numeric_qafix_v2_f1": 1.0,
115
+ "numeric_qafix_v2_examples_per_second": 138.13081928103207,
116
+ "context_redteam_v4_f1": 1.0,
117
+ "context_redteam_v4_examples_per_second": 115.20604478400188,
118
+ "context_redteam_v5_f1": 1.0,
119
+ "context_redteam_v5_examples_per_second": 144.35657204962527,
120
+ "context_redteam_v6_f1": 1.0,
121
+ "context_redteam_v6_examples_per_second": 158.02088849696304,
122
+ "context_redteam_v7_f1": 1.0,
123
+ "context_redteam_v7_examples_per_second": 115.86553627218991,
124
+ "context_redteam_v8_f1": 1.0,
125
+ "context_redteam_v8_examples_per_second": 102.16264190462925
126
+ },
127
+ "comparison": {
128
+ "public_contextpii_rc8_onnx_q8": {
129
+ "core_f1": 1.0,
130
+ "extended_f1": 1.0,
131
+ "contact_policy_f1": 1.0,
132
+ "chatbot_redteam_v2_f1": 0.9861111111111112,
133
+ "multilingual_f1": 0.9333333333333333,
134
+ "multilingual_ppsn_label_f1": 1.0,
135
+ "context_redteam_v2_f1": 1.0,
136
+ "context_redteam_v3_f1": 0.8717948717948718,
137
+ "core_examples_per_second": 128.88250222316304
138
+ },
139
+ "public_contextpii_rc7_onnx_q8": {
140
+ "core_f1": 1.0,
141
+ "contact_policy_f1": 1.0,
142
+ "context_redteam_v2_f1": null,
143
+ "multilingual_f1": 0.9333333333333333,
144
+ "core_examples_per_second": 88.99815744185265
145
+ },
146
+ "public_contextpii_rc4_onnx_q8": {
147
+ "core_f1": 0.9934640522875817,
148
+ "extended_f1": 1.0,
149
+ "demographic_holdout_v2_f1": 1.0,
150
+ "contact_policy_f1": 1.0,
151
+ "chatbot_redteam_v2_f1": 0.9861111111111112,
152
+ "chatbot_gap_holdout_v2_f1": 1.0,
153
+ "multilingual_f1": 0.9333333333333333,
154
+ "multilingual_ppsn_label_f1": 1.0,
155
+ "core_examples_per_second": 61.49696721632529,
156
+ "extended_examples_per_second": 98.75019005245319,
157
+ "demographic_holdout_v2_examples_per_second": 90.7806851088372,
158
+ "contact_policy_examples_per_second": 101.91338377846299,
159
+ "chatbot_redteam_v2_examples_per_second": 13.042183136147377,
160
+ "chatbot_gap_holdout_v2_examples_per_second": 30.728912108647304,
161
+ "multilingual_examples_per_second": 33.54466395109805,
162
+ "location_coverage_v1_f1": null
163
+ },
164
+ "public_diffmask_rc6_onnx_q8": {
165
+ "core_f1": 0.9733333333333333,
166
+ "multilingual_f1": 0.9273743016759777,
167
+ "core_examples_per_second": 130.34154354965295
168
+ },
169
+ "public_globalpointer_rc4_onnx_q8": {
170
+ "core_f1": 1.0,
171
+ "multilingual_f1": 0.9333333333333333,
172
+ "core_examples_per_second": 221.57427241189015
173
+ },
174
+ "public_contextpii_rc9_onnx_q8": {
175
+ "core_f1": 1.0,
176
+ "contact_policy_f1": 1.0,
177
+ "chatbot_redteam_v2_f1": 0.9861111111111112,
178
+ "multilingual_f1": 0.9333333333333333,
179
+ "context_redteam_v4_f1": 0.8533333333333333,
180
+ "core_examples_per_second": 125.82111537540908
181
+ },
182
+ "public_contextpii_rc10_onnx_q8": {
183
+ "core_f1": 1.0,
184
+ "contact_policy_f1": 1.0,
185
+ "chatbot_redteam_v2_f1": 0.9861111111111112,
186
+ "multilingual_f1": 0.9333333333333333,
187
+ "context_redteam_v4_f1": 1.0,
188
+ "core_examples_per_second": 125.82111537540908
189
+ },
190
+ "public_contextpii_rc11_onnx_q8": {
191
+ "core_f1": 1.0,
192
+ "contact_policy_f1": 1.0,
193
+ "chatbot_redteam_v2_f1": 0.9861111111111112,
194
+ "multilingual_f1": 0.9333333333333333,
195
+ "context_redteam_v5_f1": 1.0,
196
+ "core_examples_per_second": 94.09271075291537
197
+ },
198
+ "public_contextpii_rc12_onnx_q8": {
199
+ "core_f1": 1.0,
200
+ "contact_policy_f1": 1.0,
201
+ "chatbot_redteam_v2_f1": 0.9793103448275862,
202
+ "multilingual_f1": 0.9333333333333333,
203
+ "context_redteam_v6_f1": 1.0,
204
+ "core_examples_per_second": 73.59921479476388
205
+ },
206
+ "public_contextpii_rc13_onnx_q8": {
207
+ "core_f1": 1.0,
208
+ "contact_policy_f1": 1.0,
209
+ "chatbot_redteam_v2_f1": 0.9793103448275862,
210
+ "multilingual_f1": 0.9333333333333333,
211
+ "context_redteam_v7_f1": 1.0,
212
+ "core_examples_per_second": 126.08782280133414
213
+ }
214
+ }
215
+ }
eval/benchmark_summary.md ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # IrishCore-GlobalPointer-ContextPII-135M-v1-rc15
2
+
3
+ ## ONNX q8
4
+
5
+ | Suite | F1 | Examples/s |
6
+ | --- | ---: | ---: |
7
+ | Irish core | 1.0000 | 125.5054 |
8
+ | Gov contact policy v1 | 1.0000 | 74.3676 |
9
+ | Gov chatbot red-team v2 | 0.9861 | 74.9871 |
10
+ | Context red-team v8 | 1.0000 | 102.1626 |
11
+ | Context red-team v7 | 1.0000 | 115.8655 |
12
+ | Multilingual PPSN overall | 0.9333 | 120.6708 |
13
+ | Multilingual PPSN label-only | 1.0000 | — |
14
+
15
+ ## Full checkpoint
16
+
17
+ | Suite | F1 | Examples/s |
18
+ | --- | ---: | ---: |
19
+ | Irish core | 1.0000 | 37.1719 |
20
+ | Gov contact policy v1 | 1.0000 | 20.4712 |
21
+ | Gov chatbot red-team v2 | 0.9861 | 29.8433 |
22
+ | Context red-team v8 | 1.0000 | 83.6757 |
23
+ | Context red-team v7 | 1.0000 | 41.1670 |
24
+ | Multilingual PPSN overall | 0.9333 | 58.6894 |
25
+ | Multilingual PPSN label-only | 1.0000 | — |
eval/full_diffmask_fresh_holdout_v1.json ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc1",
3
+ "input": "diffmask_fresh_holdout_v1.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 20,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.6364284890005365,
9
+ "examples_per_second": 31.425368828803546,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 0.96875,
13
+ "f1": 0.9841269841269841,
14
+ "tp": 31,
15
+ "fp": 0,
16
+ "fn": 1
17
+ },
18
+ "by_label": {
19
+ "ACCOUNT_NUMBER": {
20
+ "precision": 1.0,
21
+ "recall": 0.5,
22
+ "f1": 0.6666666666666666,
23
+ "tp": 1,
24
+ "fp": 0,
25
+ "fn": 1
26
+ },
27
+ "CREDIT_DEBIT_CARD": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 2,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "EMAIL": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 6,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "FIRST_NAME": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 4,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "LAST_NAME": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 4,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "PHONE_NUMBER": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 6,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "POSTCODE": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 2,
72
+ "fp": 0,
73
+ "fn": 0
74
+ },
75
+ "PPSN": {
76
+ "precision": 1.0,
77
+ "recall": 1.0,
78
+ "f1": 1.0,
79
+ "tp": 6,
80
+ "fp": 0,
81
+ "fn": 0
82
+ }
83
+ },
84
+ "release_backend": "full"
85
+ }
eval/full_diffmask_gap_uat_exact_v1.json ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc1",
3
+ "input": "diffmask_gap_uat_exact_v1.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 16,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.549252360011451,
9
+ "examples_per_second": 29.130507513279376,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 17,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "EMAIL": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 3,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "PHONE_NUMBER": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 6,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "POSTCODE": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 3,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "PPSN": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 5,
48
+ "fp": 0,
49
+ "fn": 0
50
+ }
51
+ },
52
+ "release_backend": "full"
53
+ }
eval/full_globalpointer_context_redteam_v1.json ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc9",
3
+ "input": "eval/globalpointer_context_redteam_v1.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 14,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.5929923560470343,
9
+ "examples_per_second": 23.609073299571445,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 54,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "AGE": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 2,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "CITY": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 8,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "COUNTY": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 10,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "DATE_OF_BIRTH": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 4,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "EMAIL": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 4,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "FIRST_NAME": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 2,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "LAST_NAME": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 2,
72
+ "fp": 0,
73
+ "fn": 0
74
+ },
75
+ "PHONE_NUMBER": {
76
+ "precision": 1.0,
77
+ "recall": 1.0,
78
+ "f1": 1.0,
79
+ "tp": 4,
80
+ "fp": 0,
81
+ "fn": 0
82
+ },
83
+ "POSTCODE": {
84
+ "precision": 1.0,
85
+ "recall": 1.0,
86
+ "f1": 1.0,
87
+ "tp": 8,
88
+ "fp": 0,
89
+ "fn": 0
90
+ },
91
+ "PPSN": {
92
+ "precision": 1.0,
93
+ "recall": 1.0,
94
+ "f1": 1.0,
95
+ "tp": 2,
96
+ "fp": 0,
97
+ "fn": 0
98
+ },
99
+ "STREET_ADDRESS": {
100
+ "precision": 1.0,
101
+ "recall": 1.0,
102
+ "f1": 1.0,
103
+ "tp": 8,
104
+ "fp": 0,
105
+ "fn": 0
106
+ }
107
+ },
108
+ "backend": "full"
109
+ }
eval/full_globalpointer_context_redteam_v2.json ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc9",
3
+ "input": "eval/globalpointer_context_redteam_v2.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 6,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.47106689505744725,
9
+ "examples_per_second": 12.737044489760402,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 13,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "CITY": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 4,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "COUNTY": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 1,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "DATE_OF_BIRTH": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 1,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "PHONE_NUMBER": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 2,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "POSTCODE": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 3,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "STREET_ADDRESS": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 2,
64
+ "fp": 0,
65
+ "fn": 0
66
+ }
67
+ },
68
+ "backend": "full"
69
+ }
eval/full_globalpointer_context_redteam_v3.json ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc10",
3
+ "input": "eval/globalpointer_context_redteam_v3.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 12,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.6711023099487647,
9
+ "examples_per_second": 17.88102919943181,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 22,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "AGE": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 3,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "CITY": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 7,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "COUNTY": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 1,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "DATE_OF_BIRTH": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 3,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "PHONE_NUMBER": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 3,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "POSTCODE": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 3,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "STREET_ADDRESS": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 2,
72
+ "fp": 0,
73
+ "fn": 0
74
+ }
75
+ },
76
+ "backend": "full"
77
+ }
eval/full_globalpointer_context_redteam_v4.json ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc10",
3
+ "input": "eval/globalpointer_context_redteam_v4.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 21,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.6886257050791755,
9
+ "examples_per_second": 30.495521507704247,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 43,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "AGE": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 3,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "CITY": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 10,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "COUNTY": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 1,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "DATE_OF_BIRTH": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 6,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "FIRST_NAME": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 2,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "LAST_NAME": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 2,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "PHONE_NUMBER": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 6,
72
+ "fp": 0,
73
+ "fn": 0
74
+ },
75
+ "POSTCODE": {
76
+ "precision": 1.0,
77
+ "recall": 1.0,
78
+ "f1": 1.0,
79
+ "tp": 6,
80
+ "fp": 0,
81
+ "fn": 0
82
+ },
83
+ "PPSN": {
84
+ "precision": 1.0,
85
+ "recall": 1.0,
86
+ "f1": 1.0,
87
+ "tp": 2,
88
+ "fp": 0,
89
+ "fn": 0
90
+ },
91
+ "STREET_ADDRESS": {
92
+ "precision": 1.0,
93
+ "recall": 1.0,
94
+ "f1": 1.0,
95
+ "tp": 5,
96
+ "fp": 0,
97
+ "fn": 0
98
+ }
99
+ },
100
+ "backend": "full"
101
+ }
eval/full_globalpointer_context_redteam_v5.json ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "models/irishcore-globalpointer-135m-b01-extendedv1-e025",
3
+ "input": "eval/globalpointer_context_redteam_v5.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 25,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.7499809130094945,
9
+ "examples_per_second": 33.33418166561194,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 47,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "AGE": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 3,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "CITY": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 10,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "COUNTY": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 1,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "DATE_OF_BIRTH": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 8,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "FIRST_NAME": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 2,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "LAST_NAME": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 2,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "PHONE_NUMBER": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 8,
72
+ "fp": 0,
73
+ "fn": 0
74
+ },
75
+ "POSTCODE": {
76
+ "precision": 1.0,
77
+ "recall": 1.0,
78
+ "f1": 1.0,
79
+ "tp": 6,
80
+ "fp": 0,
81
+ "fn": 0
82
+ },
83
+ "PPSN": {
84
+ "precision": 1.0,
85
+ "recall": 1.0,
86
+ "f1": 1.0,
87
+ "tp": 2,
88
+ "fp": 0,
89
+ "fn": 0
90
+ },
91
+ "STREET_ADDRESS": {
92
+ "precision": 1.0,
93
+ "recall": 1.0,
94
+ "f1": 1.0,
95
+ "tp": 5,
96
+ "fp": 0,
97
+ "fn": 0
98
+ }
99
+ }
100
+ }
eval/full_globalpointer_context_redteam_v6.json ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "models/irishcore-globalpointer-135m-b01-extendedv1-e025",
3
+ "input": "eval/globalpointer_context_redteam_v6.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 38,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.9788746919948608,
9
+ "examples_per_second": 38.82008627943923,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 72,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "AGE": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 5,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "CITY": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 14,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "COUNTY": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 1,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "DATE_OF_BIRTH": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 10,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "FIRST_NAME": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 4,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "LAST_NAME": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 7,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "PHONE_NUMBER": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 8,
72
+ "fp": 0,
73
+ "fn": 0
74
+ },
75
+ "POSTCODE": {
76
+ "precision": 1.0,
77
+ "recall": 1.0,
78
+ "f1": 1.0,
79
+ "tp": 10,
80
+ "fp": 0,
81
+ "fn": 0
82
+ },
83
+ "PPSN": {
84
+ "precision": 1.0,
85
+ "recall": 1.0,
86
+ "f1": 1.0,
87
+ "tp": 4,
88
+ "fp": 0,
89
+ "fn": 0
90
+ },
91
+ "STREET_ADDRESS": {
92
+ "precision": 1.0,
93
+ "recall": 1.0,
94
+ "f1": 1.0,
95
+ "tp": 9,
96
+ "fp": 0,
97
+ "fn": 0
98
+ }
99
+ }
100
+ }
eval/full_globalpointer_context_redteam_v7.json ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "models/irishcore-globalpointer-135m-b01-extendedv1-e025",
3
+ "input": "eval/globalpointer_context_redteam_v7.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 41,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.9959422359243035,
9
+ "examples_per_second": 41.1670461610147,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 84,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "AGE": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 5,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "CITY": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 17,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "COUNTY": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 4,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "DATE_OF_BIRTH": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 10,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "FIRST_NAME": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 4,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "LAST_NAME": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 7,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "PHONE_NUMBER": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 8,
72
+ "fp": 0,
73
+ "fn": 0
74
+ },
75
+ "POSTCODE": {
76
+ "precision": 1.0,
77
+ "recall": 1.0,
78
+ "f1": 1.0,
79
+ "tp": 13,
80
+ "fp": 0,
81
+ "fn": 0
82
+ },
83
+ "PPSN": {
84
+ "precision": 1.0,
85
+ "recall": 1.0,
86
+ "f1": 1.0,
87
+ "tp": 4,
88
+ "fp": 0,
89
+ "fn": 0
90
+ },
91
+ "STREET_ADDRESS": {
92
+ "precision": 1.0,
93
+ "recall": 1.0,
94
+ "f1": 1.0,
95
+ "tp": 12,
96
+ "fp": 0,
97
+ "fn": 0
98
+ }
99
+ }
100
+ }
eval/full_globalpointer_context_redteam_v8.json ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "release/IrishCore-GlobalPointer-ContextPII-135M-v1-rc14",
3
+ "input": "eval/globalpointer_context_redteam_v8.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 51,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.6094960840418935,
9
+ "examples_per_second": 83.67568116564722,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 113,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "AGE": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 5,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "CITY": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 25,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "COUNTY": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 10,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "DATE_OF_BIRTH": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 10,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "FIRST_NAME": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 6,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "LAST_NAME": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 9,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "PHONE_NUMBER": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 8,
72
+ "fp": 0,
73
+ "fn": 0
74
+ },
75
+ "POSTCODE": {
76
+ "precision": 1.0,
77
+ "recall": 1.0,
78
+ "f1": 1.0,
79
+ "tp": 19,
80
+ "fp": 0,
81
+ "fn": 0
82
+ },
83
+ "PPSN": {
84
+ "precision": 1.0,
85
+ "recall": 1.0,
86
+ "f1": 1.0,
87
+ "tp": 6,
88
+ "fp": 0,
89
+ "fn": 0
90
+ },
91
+ "STREET_ADDRESS": {
92
+ "precision": 1.0,
93
+ "recall": 1.0,
94
+ "f1": 1.0,
95
+ "tp": 15,
96
+ "fp": 0,
97
+ "fn": 0
98
+ }
99
+ }
100
+ }
eval/full_globalpointer_demographic_patch_v2_test.json ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "models/irishcore-globalpointer-135m-b01-extendedv1-e025",
3
+ "input": "eval/globalpointer_demographic_patch_v2_test.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 600,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 10.661896189092658,
9
+ "examples_per_second": 56.27516807130541,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 2470,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "AGE": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 287,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "CITY": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 286,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "COUNTY": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 286,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "DATE_OF_BIRTH": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 304,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "EMAIL": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 85,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "FIRST_NAME": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 194,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "LAST_NAME": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 194,
72
+ "fp": 0,
73
+ "fn": 0
74
+ },
75
+ "PHONE_NUMBER": {
76
+ "precision": 1.0,
77
+ "recall": 1.0,
78
+ "f1": 1.0,
79
+ "tp": 177,
80
+ "fp": 0,
81
+ "fn": 0
82
+ },
83
+ "POSTCODE": {
84
+ "precision": 1.0,
85
+ "recall": 1.0,
86
+ "f1": 1.0,
87
+ "tp": 286,
88
+ "fp": 0,
89
+ "fn": 0
90
+ },
91
+ "PPSN": {
92
+ "precision": 1.0,
93
+ "recall": 1.0,
94
+ "f1": 1.0,
95
+ "tp": 85,
96
+ "fp": 0,
97
+ "fn": 0
98
+ },
99
+ "STREET_ADDRESS": {
100
+ "precision": 1.0,
101
+ "recall": 1.0,
102
+ "f1": 1.0,
103
+ "tp": 286,
104
+ "fp": 0,
105
+ "fn": 0
106
+ }
107
+ }
108
+ }
eval/full_globalpointer_location_coverage_v1.json ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc9",
3
+ "input": "eval/globalpointer_location_coverage_v1.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 18,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.6559180339099839,
9
+ "examples_per_second": 27.442453278347067,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 56,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "CITY": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 14,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "COUNTY": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 16,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "PHONE_NUMBER": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 2,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "POSTCODE": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 12,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "STREET_ADDRESS": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 12,
56
+ "fp": 0,
57
+ "fn": 0
58
+ }
59
+ },
60
+ "backend": "full"
61
+ }
eval/full_globalpointer_location_coverage_v2.json ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc9",
3
+ "input": "eval/globalpointer_location_coverage_v2.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 24,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.9851676529506221,
9
+ "examples_per_second": 24.3613357869789,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 68,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "CITY": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 20,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "COUNTY": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 22,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "PHONE_NUMBER": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 2,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "POSTCODE": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 12,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "STREET_ADDRESS": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 12,
56
+ "fp": 0,
57
+ "fn": 0
58
+ }
59
+ },
60
+ "backend": "full"
61
+ }
eval/full_globalpointer_location_coverage_v3.json ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc9",
3
+ "input": "eval/globalpointer_location_coverage_v3.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 30,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.8463578999508172,
9
+ "examples_per_second": 35.4459974931921,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 82,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "CITY": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 26,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "COUNTY": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 28,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "PHONE_NUMBER": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 2,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "POSTCODE": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 13,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "STREET_ADDRESS": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 13,
56
+ "fp": 0,
57
+ "fn": 0
58
+ }
59
+ },
60
+ "backend": "full"
61
+ }
eval/full_irish_core_pii_v1.json ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "models/irishcore-globalpointer-135m-b01-extendedv1-e025",
3
+ "input": "eval/irish_core_pii_v1.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 37,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.9953753319568932,
9
+ "examples_per_second": 37.17190773379781,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 76,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "ACCOUNT_NUMBER": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 3,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "BANK_ROUTING_NUMBER": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 1,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "CREDIT_DEBIT_CARD": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 2,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "EMAIL": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 6,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "FIRST_NAME": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 19,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "LAST_NAME": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 19,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "PASSPORT_NUMBER": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 2,
72
+ "fp": 0,
73
+ "fn": 0
74
+ },
75
+ "PHONE_NUMBER": {
76
+ "precision": 1.0,
77
+ "recall": 1.0,
78
+ "f1": 1.0,
79
+ "tp": 12,
80
+ "fp": 0,
81
+ "fn": 0
82
+ },
83
+ "POSTCODE": {
84
+ "precision": 1.0,
85
+ "recall": 1.0,
86
+ "f1": 1.0,
87
+ "tp": 4,
88
+ "fp": 0,
89
+ "fn": 0
90
+ },
91
+ "PPSN": {
92
+ "precision": 1.0,
93
+ "recall": 1.0,
94
+ "f1": 1.0,
95
+ "tp": 6,
96
+ "fp": 0,
97
+ "fn": 0
98
+ },
99
+ "SWIFT_BIC": {
100
+ "precision": 1.0,
101
+ "recall": 1.0,
102
+ "f1": 1.0,
103
+ "tp": 2,
104
+ "fp": 0,
105
+ "fn": 0
106
+ }
107
+ }
108
+ }
eval/full_irish_dllm_hardening_exact_v1.json ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc1",
3
+ "input": "irish_dllm_hardening_exact_v1.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 14,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.5248716080095619,
9
+ "examples_per_second": 26.673189759856385,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 20,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "ACCOUNT_NUMBER": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 1,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "BANK_ROUTING_NUMBER": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 2,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "CREDIT_DEBIT_CARD": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 2,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "EMAIL": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 2,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "FIRST_NAME": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 1,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "LAST_NAME": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 1,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "PHONE_NUMBER": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 2,
72
+ "fp": 0,
73
+ "fn": 0
74
+ },
75
+ "POSTCODE": {
76
+ "precision": 1.0,
77
+ "recall": 1.0,
78
+ "f1": 1.0,
79
+ "tp": 3,
80
+ "fp": 0,
81
+ "fn": 0
82
+ },
83
+ "PPSN": {
84
+ "precision": 1.0,
85
+ "recall": 1.0,
86
+ "f1": 1.0,
87
+ "tp": 3,
88
+ "fp": 0,
89
+ "fn": 0
90
+ },
91
+ "SWIFT_BIC": {
92
+ "precision": 1.0,
93
+ "recall": 1.0,
94
+ "f1": 1.0,
95
+ "tp": 3,
96
+ "fp": 0,
97
+ "fn": 0
98
+ }
99
+ },
100
+ "release_backend": "full"
101
+ }
eval/full_irish_extended_pii_v1.json ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "models/irishcore-globalpointer-135m-b01-extendedv1-e025",
3
+ "input": "eval/irish_extended_pii_v1.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 14,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.6194407499860972,
9
+ "examples_per_second": 22.601031656884402,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 50,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "AGE": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 5,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "CITY": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 8,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "COUNTY": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 6,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "DATE_OF_BIRTH": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 6,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "EMAIL": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 1,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "FIRST_NAME": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 2,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "LAST_NAME": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 2,
72
+ "fp": 0,
73
+ "fn": 0
74
+ },
75
+ "PHONE_NUMBER": {
76
+ "precision": 1.0,
77
+ "recall": 1.0,
78
+ "f1": 1.0,
79
+ "tp": 2,
80
+ "fp": 0,
81
+ "fn": 0
82
+ },
83
+ "POSTCODE": {
84
+ "precision": 1.0,
85
+ "recall": 1.0,
86
+ "f1": 1.0,
87
+ "tp": 8,
88
+ "fp": 0,
89
+ "fn": 0
90
+ },
91
+ "PPSN": {
92
+ "precision": 1.0,
93
+ "recall": 1.0,
94
+ "f1": 1.0,
95
+ "tp": 2,
96
+ "fp": 0,
97
+ "fn": 0
98
+ },
99
+ "STREET_ADDRESS": {
100
+ "precision": 1.0,
101
+ "recall": 1.0,
102
+ "f1": 1.0,
103
+ "tp": 8,
104
+ "fp": 0,
105
+ "fn": 0
106
+ }
107
+ }
108
+ }
eval/full_irish_gov_chatbot_gap_holdout_v1.json ADDED
@@ -0,0 +1,258 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc1",
3
+ "family": "globalpointer",
4
+ "backend": "pt",
5
+ "input": "irish_gov_chatbot_gap_holdout_v1.jsonl",
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "overall": {
9
+ "precision": 1.0,
10
+ "recall": 1.0,
11
+ "f1": 1.0,
12
+ "tp": 413,
13
+ "fp": 0,
14
+ "fn": 0
15
+ },
16
+ "exact": {
17
+ "precision": 0.9878934624697336,
18
+ "recall": 0.9878934624697336,
19
+ "f1": 0.9878934624697336,
20
+ "tp": 408,
21
+ "fp": 5,
22
+ "fn": 5
23
+ },
24
+ "by_label": {
25
+ "ACCOUNT_NUMBER": {
26
+ "precision": 1.0,
27
+ "recall": 1.0,
28
+ "f1": 1.0,
29
+ "tp": 16,
30
+ "fp": 0,
31
+ "fn": 0
32
+ },
33
+ "BANK_ROUTING_NUMBER": {
34
+ "precision": 1.0,
35
+ "recall": 1.0,
36
+ "f1": 1.0,
37
+ "tp": 23,
38
+ "fp": 0,
39
+ "fn": 0
40
+ },
41
+ "CREDIT_DEBIT_CARD": {
42
+ "precision": 1.0,
43
+ "recall": 1.0,
44
+ "f1": 1.0,
45
+ "tp": 6,
46
+ "fp": 0,
47
+ "fn": 0
48
+ },
49
+ "EMAIL": {
50
+ "precision": 1.0,
51
+ "recall": 1.0,
52
+ "f1": 1.0,
53
+ "tp": 50,
54
+ "fp": 0,
55
+ "fn": 0
56
+ },
57
+ "FIRST_NAME": {
58
+ "precision": 1.0,
59
+ "recall": 1.0,
60
+ "f1": 1.0,
61
+ "tp": 70,
62
+ "fp": 0,
63
+ "fn": 0
64
+ },
65
+ "LAST_NAME": {
66
+ "precision": 1.0,
67
+ "recall": 1.0,
68
+ "f1": 1.0,
69
+ "tp": 70,
70
+ "fp": 0,
71
+ "fn": 0
72
+ },
73
+ "PHONE_NUMBER": {
74
+ "precision": 1.0,
75
+ "recall": 1.0,
76
+ "f1": 1.0,
77
+ "tp": 72,
78
+ "fp": 0,
79
+ "fn": 0
80
+ },
81
+ "POSTCODE": {
82
+ "precision": 1.0,
83
+ "recall": 1.0,
84
+ "f1": 1.0,
85
+ "tp": 18,
86
+ "fp": 0,
87
+ "fn": 0
88
+ },
89
+ "PPSN": {
90
+ "precision": 1.0,
91
+ "recall": 1.0,
92
+ "f1": 1.0,
93
+ "tp": 72,
94
+ "fp": 0,
95
+ "fn": 0
96
+ },
97
+ "SWIFT_BIC": {
98
+ "precision": 1.0,
99
+ "recall": 1.0,
100
+ "f1": 1.0,
101
+ "tp": 16,
102
+ "fp": 0,
103
+ "fn": 0
104
+ }
105
+ },
106
+ "by_language": {
107
+ "en": {
108
+ "precision": 1.0,
109
+ "recall": 1.0,
110
+ "f1": 1.0,
111
+ "tp": 230,
112
+ "fp": 0,
113
+ "fn": 0
114
+ },
115
+ "ga": {
116
+ "precision": 1.0,
117
+ "recall": 1.0,
118
+ "f1": 1.0,
119
+ "tp": 183,
120
+ "fp": 0,
121
+ "fn": 0
122
+ }
123
+ },
124
+ "by_role": {
125
+ "assistant": {
126
+ "precision": 1.0,
127
+ "recall": 1.0,
128
+ "f1": 1.0,
129
+ "tp": 72,
130
+ "fp": 0,
131
+ "fn": 0
132
+ },
133
+ "mixed": {
134
+ "precision": 0.0,
135
+ "recall": 0.0,
136
+ "f1": 0.0,
137
+ "tp": 0,
138
+ "fp": 0,
139
+ "fn": 0
140
+ },
141
+ "user": {
142
+ "precision": 1.0,
143
+ "recall": 1.0,
144
+ "f1": 1.0,
145
+ "tp": 341,
146
+ "fp": 0,
147
+ "fn": 0
148
+ }
149
+ },
150
+ "by_source_type": {
151
+ "assistant_contact_echo_en": {
152
+ "precision": 1.0,
153
+ "recall": 1.0,
154
+ "f1": 1.0,
155
+ "tp": 32,
156
+ "fp": 0,
157
+ "fn": 0
158
+ },
159
+ "assistant_contact_echo_ga": {
160
+ "precision": 1.0,
161
+ "recall": 1.0,
162
+ "f1": 1.0,
163
+ "tp": 40,
164
+ "fp": 0,
165
+ "fn": 0
166
+ },
167
+ "negative_en": {
168
+ "precision": 0.0,
169
+ "recall": 0.0,
170
+ "f1": 0.0,
171
+ "tp": 0,
172
+ "fp": 0,
173
+ "fn": 0
174
+ },
175
+ "negative_ga": {
176
+ "precision": 0.0,
177
+ "recall": 0.0,
178
+ "f1": 0.0,
179
+ "tp": 0,
180
+ "fp": 0,
181
+ "fn": 0
182
+ },
183
+ "user_card_email_en": {
184
+ "precision": 1.0,
185
+ "recall": 1.0,
186
+ "f1": 1.0,
187
+ "tp": 12,
188
+ "fp": 0,
189
+ "fn": 0
190
+ },
191
+ "user_name_email_ppsn_phone_en": {
192
+ "precision": 1.0,
193
+ "recall": 1.0,
194
+ "f1": 1.0,
195
+ "tp": 80,
196
+ "fp": 0,
197
+ "fn": 0
198
+ },
199
+ "user_name_email_ppsn_phone_ga": {
200
+ "precision": 1.0,
201
+ "recall": 1.0,
202
+ "f1": 1.0,
203
+ "tp": 50,
204
+ "fp": 0,
205
+ "fn": 0
206
+ },
207
+ "user_name_ppsn_phone_en": {
208
+ "precision": 1.0,
209
+ "recall": 1.0,
210
+ "f1": 1.0,
211
+ "tp": 56,
212
+ "fp": 0,
213
+ "fn": 0
214
+ },
215
+ "user_name_ppsn_phone_ga": {
216
+ "precision": 1.0,
217
+ "recall": 1.0,
218
+ "f1": 1.0,
219
+ "tp": 56,
220
+ "fp": 0,
221
+ "fn": 0
222
+ },
223
+ "user_payment_name_en": {
224
+ "precision": 1.0,
225
+ "recall": 1.0,
226
+ "f1": 1.0,
227
+ "tp": 32,
228
+ "fp": 0,
229
+ "fn": 0
230
+ },
231
+ "user_payment_name_ga": {
232
+ "precision": 1.0,
233
+ "recall": 1.0,
234
+ "f1": 1.0,
235
+ "tp": 32,
236
+ "fp": 0,
237
+ "fn": 0
238
+ },
239
+ "user_sort_code_en": {
240
+ "precision": 1.0,
241
+ "recall": 1.0,
242
+ "f1": 1.0,
243
+ "tp": 18,
244
+ "fp": 0,
245
+ "fn": 0
246
+ },
247
+ "user_sort_code_ga": {
248
+ "precision": 1.0,
249
+ "recall": 1.0,
250
+ "f1": 1.0,
251
+ "tp": 5,
252
+ "fp": 0,
253
+ "fn": 0
254
+ }
255
+ },
256
+ "failure_count": 0,
257
+ "failures": []
258
+ }
eval/full_irish_gov_chatbot_gap_holdout_v2.json ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "models/irishcore-globalpointer-135m-b01-extendedv1-e025",
3
+ "input": "eval/irish_gov_chatbot_gap_holdout_v2.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 160,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 4.31560706498567,
9
+ "examples_per_second": 37.07473771144438,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 652,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "ACCOUNT_NUMBER": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 38,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "EMAIL": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 104,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "FIRST_NAME": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 68,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "LAST_NAME": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 68,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "PASSPORT_NUMBER": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 33,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "PHONE_NUMBER": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 101,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "POSTCODE": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 101,
72
+ "fp": 0,
73
+ "fn": 0
74
+ },
75
+ "PPSN": {
76
+ "precision": 1.0,
77
+ "recall": 1.0,
78
+ "f1": 1.0,
79
+ "tp": 101,
80
+ "fp": 0,
81
+ "fn": 0
82
+ },
83
+ "SWIFT_BIC": {
84
+ "precision": 1.0,
85
+ "recall": 1.0,
86
+ "f1": 1.0,
87
+ "tp": 38,
88
+ "fp": 0,
89
+ "fn": 0
90
+ }
91
+ }
92
+ }
eval/full_irish_gov_chatbot_redteam_assistant_v2.json ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "models/irishcore-globalpointer-135m-b01-extendedv1-e025",
3
+ "input": "eval/irish_gov_chatbot_redteam_assistant_v2.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 9,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.16110201692208648,
9
+ "examples_per_second": 55.86522237243408,
10
+ "overall": {
11
+ "precision": 0.9375,
12
+ "recall": 1.0,
13
+ "f1": 0.967741935483871,
14
+ "tp": 30,
15
+ "fp": 2,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "ACCOUNT_NUMBER": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 2,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "EMAIL": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 6,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "FIRST_NAME": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 2,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "LAST_NAME": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 2,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "PHONE_NUMBER": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 8,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "POSTCODE": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 4,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "PPSN": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 4,
72
+ "fp": 0,
73
+ "fn": 0
74
+ },
75
+ "SWIFT_BIC": {
76
+ "precision": 1.0,
77
+ "recall": 1.0,
78
+ "f1": 1.0,
79
+ "tp": 2,
80
+ "fp": 0,
81
+ "fn": 0
82
+ }
83
+ }
84
+ }
eval/full_irish_gov_chatbot_redteam_user_v2.json ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "models/irishcore-globalpointer-135m-b01-extendedv1-e025",
3
+ "input": "eval/irish_gov_chatbot_redteam_user_v2.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 10,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.1798157700104639,
9
+ "examples_per_second": 55.612474920403685,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 41,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "ACCOUNT_NUMBER": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 2,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "BANK_ROUTING_NUMBER": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 1,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "CREDIT_DEBIT_CARD": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 1,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "EMAIL": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 4,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "FIRST_NAME": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 5,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "LAST_NAME": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 5,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "PASSPORT_NUMBER": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 2,
72
+ "fp": 0,
73
+ "fn": 0
74
+ },
75
+ "PHONE_NUMBER": {
76
+ "precision": 1.0,
77
+ "recall": 1.0,
78
+ "f1": 1.0,
79
+ "tp": 9,
80
+ "fp": 0,
81
+ "fn": 0
82
+ },
83
+ "POSTCODE": {
84
+ "precision": 1.0,
85
+ "recall": 1.0,
86
+ "f1": 1.0,
87
+ "tp": 3,
88
+ "fp": 0,
89
+ "fn": 0
90
+ },
91
+ "PPSN": {
92
+ "precision": 1.0,
93
+ "recall": 1.0,
94
+ "f1": 1.0,
95
+ "tp": 7,
96
+ "fp": 0,
97
+ "fn": 0
98
+ },
99
+ "SWIFT_BIC": {
100
+ "precision": 1.0,
101
+ "recall": 1.0,
102
+ "f1": 1.0,
103
+ "tp": 2,
104
+ "fp": 0,
105
+ "fn": 0
106
+ }
107
+ }
108
+ }
eval/full_irish_gov_chatbot_redteam_v1.json ADDED
@@ -0,0 +1,362 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc1",
3
+ "family": "globalpointer",
4
+ "backend": "pt",
5
+ "input": "irish_gov_chatbot_redteam_v1.jsonl",
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "overall": {
9
+ "precision": 1.0,
10
+ "recall": 1.0,
11
+ "f1": 1.0,
12
+ "tp": 161,
13
+ "fp": 0,
14
+ "fn": 0
15
+ },
16
+ "exact": {
17
+ "precision": 1.0,
18
+ "recall": 1.0,
19
+ "f1": 1.0,
20
+ "tp": 161,
21
+ "fp": 0,
22
+ "fn": 0
23
+ },
24
+ "by_label": {
25
+ "ACCOUNT_NUMBER": {
26
+ "precision": 1.0,
27
+ "recall": 1.0,
28
+ "f1": 1.0,
29
+ "tp": 9,
30
+ "fp": 0,
31
+ "fn": 0
32
+ },
33
+ "BANK_ROUTING_NUMBER": {
34
+ "precision": 1.0,
35
+ "recall": 1.0,
36
+ "f1": 1.0,
37
+ "tp": 3,
38
+ "fp": 0,
39
+ "fn": 0
40
+ },
41
+ "CREDIT_DEBIT_CARD": {
42
+ "precision": 1.0,
43
+ "recall": 1.0,
44
+ "f1": 1.0,
45
+ "tp": 3,
46
+ "fp": 0,
47
+ "fn": 0
48
+ },
49
+ "EMAIL": {
50
+ "precision": 1.0,
51
+ "recall": 1.0,
52
+ "f1": 1.0,
53
+ "tp": 16,
54
+ "fp": 0,
55
+ "fn": 0
56
+ },
57
+ "FIRST_NAME": {
58
+ "precision": 1.0,
59
+ "recall": 1.0,
60
+ "f1": 1.0,
61
+ "tp": 18,
62
+ "fp": 0,
63
+ "fn": 0
64
+ },
65
+ "LAST_NAME": {
66
+ "precision": 1.0,
67
+ "recall": 1.0,
68
+ "f1": 1.0,
69
+ "tp": 18,
70
+ "fp": 0,
71
+ "fn": 0
72
+ },
73
+ "PASSPORT_NUMBER": {
74
+ "precision": 1.0,
75
+ "recall": 1.0,
76
+ "f1": 1.0,
77
+ "tp": 4,
78
+ "fp": 0,
79
+ "fn": 0
80
+ },
81
+ "PHONE_NUMBER": {
82
+ "precision": 1.0,
83
+ "recall": 1.0,
84
+ "f1": 1.0,
85
+ "tp": 36,
86
+ "fp": 0,
87
+ "fn": 0
88
+ },
89
+ "POSTCODE": {
90
+ "precision": 1.0,
91
+ "recall": 1.0,
92
+ "f1": 1.0,
93
+ "tp": 11,
94
+ "fp": 0,
95
+ "fn": 0
96
+ },
97
+ "PPSN": {
98
+ "precision": 1.0,
99
+ "recall": 1.0,
100
+ "f1": 1.0,
101
+ "tp": 34,
102
+ "fp": 0,
103
+ "fn": 0
104
+ },
105
+ "SWIFT_BIC": {
106
+ "precision": 1.0,
107
+ "recall": 1.0,
108
+ "f1": 1.0,
109
+ "tp": 9,
110
+ "fp": 0,
111
+ "fn": 0
112
+ }
113
+ },
114
+ "by_language": {
115
+ "en": {
116
+ "precision": 1.0,
117
+ "recall": 1.0,
118
+ "f1": 1.0,
119
+ "tp": 99,
120
+ "fp": 0,
121
+ "fn": 0
122
+ },
123
+ "ga": {
124
+ "precision": 1.0,
125
+ "recall": 1.0,
126
+ "f1": 1.0,
127
+ "tp": 62,
128
+ "fp": 0,
129
+ "fn": 0
130
+ }
131
+ },
132
+ "by_role": {
133
+ "assistant": {
134
+ "precision": 1.0,
135
+ "recall": 1.0,
136
+ "f1": 1.0,
137
+ "tp": 56,
138
+ "fp": 0,
139
+ "fn": 0
140
+ },
141
+ "mixed": {
142
+ "precision": 0.0,
143
+ "recall": 0.0,
144
+ "f1": 0.0,
145
+ "tp": 0,
146
+ "fp": 0,
147
+ "fn": 0
148
+ },
149
+ "user": {
150
+ "precision": 1.0,
151
+ "recall": 1.0,
152
+ "f1": 1.0,
153
+ "tp": 105,
154
+ "fp": 0,
155
+ "fn": 0
156
+ }
157
+ },
158
+ "by_source_type": {
159
+ "assistant_centre_block_en": {
160
+ "precision": 1.0,
161
+ "recall": 1.0,
162
+ "f1": 1.0,
163
+ "tp": 2,
164
+ "fp": 0,
165
+ "fn": 0
166
+ },
167
+ "assistant_contact_block_en": {
168
+ "precision": 1.0,
169
+ "recall": 1.0,
170
+ "f1": 1.0,
171
+ "tp": 2,
172
+ "fp": 0,
173
+ "fn": 0
174
+ },
175
+ "assistant_contact_ga": {
176
+ "precision": 1.0,
177
+ "recall": 1.0,
178
+ "f1": 1.0,
179
+ "tp": 2,
180
+ "fp": 0,
181
+ "fn": 0
182
+ },
183
+ "assistant_echo_user_en": {
184
+ "precision": 1.0,
185
+ "recall": 1.0,
186
+ "f1": 1.0,
187
+ "tp": 15,
188
+ "fp": 0,
189
+ "fn": 0
190
+ },
191
+ "assistant_echo_user_ga": {
192
+ "precision": 1.0,
193
+ "recall": 1.0,
194
+ "f1": 1.0,
195
+ "tp": 15,
196
+ "fp": 0,
197
+ "fn": 0
198
+ },
199
+ "assistant_location_en": {
200
+ "precision": 1.0,
201
+ "recall": 1.0,
202
+ "f1": 1.0,
203
+ "tp": 12,
204
+ "fp": 0,
205
+ "fn": 0
206
+ },
207
+ "assistant_mailbox_en": {
208
+ "precision": 1.0,
209
+ "recall": 1.0,
210
+ "f1": 1.0,
211
+ "tp": 2,
212
+ "fp": 0,
213
+ "fn": 0
214
+ },
215
+ "assistant_payment_en": {
216
+ "precision": 1.0,
217
+ "recall": 1.0,
218
+ "f1": 1.0,
219
+ "tp": 6,
220
+ "fp": 0,
221
+ "fn": 0
222
+ },
223
+ "negative_date_en": {
224
+ "precision": 0.0,
225
+ "recall": 0.0,
226
+ "f1": 0.0,
227
+ "tp": 0,
228
+ "fp": 0,
229
+ "fn": 0
230
+ },
231
+ "negative_date_ga": {
232
+ "precision": 0.0,
233
+ "recall": 0.0,
234
+ "f1": 0.0,
235
+ "tp": 0,
236
+ "fp": 0,
237
+ "fn": 0
238
+ },
239
+ "negative_direct_debit_en": {
240
+ "precision": 0.0,
241
+ "recall": 0.0,
242
+ "f1": 0.0,
243
+ "tp": 0,
244
+ "fp": 0,
245
+ "fn": 0
246
+ },
247
+ "negative_hours_en": {
248
+ "precision": 0.0,
249
+ "recall": 0.0,
250
+ "f1": 0.0,
251
+ "tp": 0,
252
+ "fp": 0,
253
+ "fn": 0
254
+ },
255
+ "negative_long_ppsn_en": {
256
+ "precision": 0.0,
257
+ "recall": 0.0,
258
+ "f1": 0.0,
259
+ "tp": 0,
260
+ "fp": 0,
261
+ "fn": 0
262
+ },
263
+ "negative_scheme_ga": {
264
+ "precision": 0.0,
265
+ "recall": 0.0,
266
+ "f1": 0.0,
267
+ "tp": 0,
268
+ "fp": 0,
269
+ "fn": 0
270
+ },
271
+ "negative_short_ppsn_en": {
272
+ "precision": 0.0,
273
+ "recall": 0.0,
274
+ "f1": 0.0,
275
+ "tp": 0,
276
+ "fp": 0,
277
+ "fn": 0
278
+ },
279
+ "negative_year_letter_ga": {
280
+ "precision": 0.0,
281
+ "recall": 0.0,
282
+ "f1": 0.0,
283
+ "tp": 0,
284
+ "fp": 0,
285
+ "fn": 0
286
+ },
287
+ "user_allowance_mixed_en": {
288
+ "precision": 1.0,
289
+ "recall": 1.0,
290
+ "f1": 1.0,
291
+ "tp": 24,
292
+ "fp": 0,
293
+ "fn": 0
294
+ },
295
+ "user_allowance_mixed_ga": {
296
+ "precision": 1.0,
297
+ "recall": 1.0,
298
+ "f1": 1.0,
299
+ "tp": 24,
300
+ "fp": 0,
301
+ "fn": 0
302
+ },
303
+ "user_bare_ppsn_en": {
304
+ "precision": 1.0,
305
+ "recall": 1.0,
306
+ "f1": 1.0,
307
+ "tp": 6,
308
+ "fp": 0,
309
+ "fn": 0
310
+ },
311
+ "user_bare_ppsn_ga": {
312
+ "precision": 1.0,
313
+ "recall": 1.0,
314
+ "f1": 1.0,
315
+ "tp": 6,
316
+ "fp": 0,
317
+ "fn": 0
318
+ },
319
+ "user_card_email_en": {
320
+ "precision": 1.0,
321
+ "recall": 1.0,
322
+ "f1": 1.0,
323
+ "tp": 6,
324
+ "fp": 0,
325
+ "fn": 0
326
+ },
327
+ "user_passport_en": {
328
+ "precision": 1.0,
329
+ "recall": 1.0,
330
+ "f1": 1.0,
331
+ "tp": 12,
332
+ "fp": 0,
333
+ "fn": 0
334
+ },
335
+ "user_payment_en": {
336
+ "precision": 1.0,
337
+ "recall": 1.0,
338
+ "f1": 1.0,
339
+ "tp": 12,
340
+ "fp": 0,
341
+ "fn": 0
342
+ },
343
+ "user_payment_ga": {
344
+ "precision": 1.0,
345
+ "recall": 1.0,
346
+ "f1": 1.0,
347
+ "tp": 12,
348
+ "fp": 0,
349
+ "fn": 0
350
+ },
351
+ "user_sort_code_ga": {
352
+ "precision": 1.0,
353
+ "recall": 1.0,
354
+ "f1": 1.0,
355
+ "tp": 3,
356
+ "fp": 0,
357
+ "fn": 0
358
+ }
359
+ },
360
+ "failure_count": 0,
361
+ "failures": []
362
+ }
eval/full_irish_gov_chatbot_redteam_v2.json ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "models/irishcore-globalpointer-135m-b01-extendedv1-e025",
3
+ "input": "eval/irish_gov_chatbot_redteam_v2.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 25,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.8377100869547576,
9
+ "examples_per_second": 29.843260084022578,
10
+ "overall": {
11
+ "precision": 0.9726027397260274,
12
+ "recall": 1.0,
13
+ "f1": 0.9861111111111112,
14
+ "tp": 71,
15
+ "fp": 2,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "ACCOUNT_NUMBER": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 4,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "BANK_ROUTING_NUMBER": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 1,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "CREDIT_DEBIT_CARD": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 1,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "EMAIL": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 10,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "FIRST_NAME": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 7,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "LAST_NAME": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 7,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "PASSPORT_NUMBER": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 2,
72
+ "fp": 0,
73
+ "fn": 0
74
+ },
75
+ "PHONE_NUMBER": {
76
+ "precision": 1.0,
77
+ "recall": 1.0,
78
+ "f1": 1.0,
79
+ "tp": 17,
80
+ "fp": 0,
81
+ "fn": 0
82
+ },
83
+ "POSTCODE": {
84
+ "precision": 1.0,
85
+ "recall": 1.0,
86
+ "f1": 1.0,
87
+ "tp": 7,
88
+ "fp": 0,
89
+ "fn": 0
90
+ },
91
+ "PPSN": {
92
+ "precision": 1.0,
93
+ "recall": 1.0,
94
+ "f1": 1.0,
95
+ "tp": 11,
96
+ "fp": 0,
97
+ "fn": 0
98
+ },
99
+ "SWIFT_BIC": {
100
+ "precision": 1.0,
101
+ "recall": 1.0,
102
+ "f1": 1.0,
103
+ "tp": 4,
104
+ "fp": 0,
105
+ "fn": 0
106
+ }
107
+ }
108
+ }
eval/full_irish_gov_contact_policy_v1.json ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "models/irishcore-globalpointer-135m-b01-extendedv1-e025",
3
+ "input": "eval/irish_gov_contact_policy_v1.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 12,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.586188476998359,
9
+ "examples_per_second": 20.47123147395747,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 30,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "CITY": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 4,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "COUNTY": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 2,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "DATE_OF_BIRTH": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 4,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "EMAIL": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 4,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "PHONE_NUMBER": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 8,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "POSTCODE": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 4,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "STREET_ADDRESS": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 4,
72
+ "fp": 0,
73
+ "fn": 0
74
+ }
75
+ }
76
+ }
eval/full_irish_numeric_qafix_v2.json ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc9",
3
+ "input": "eval/irish_numeric_qafix_v2.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 19,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.6458162779454142,
9
+ "examples_per_second": 29.420131775628487,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 14,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "BANK_ROUTING_NUMBER": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 5,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "PASSPORT_NUMBER": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 5,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "PHONE_NUMBER": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 4,
40
+ "fp": 0,
41
+ "fn": 0
42
+ }
43
+ },
44
+ "backend": "full"
45
+ }
eval/full_irish_ppsn_phone_edge_v1.json ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc1",
3
+ "input": "irish_ppsn_phone_edge_v1.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 22,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.41967142606154084,
9
+ "examples_per_second": 52.42196307349719,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 19,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "PHONE_NUMBER": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 13,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "PPSN": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 6,
32
+ "fp": 0,
33
+ "fn": 0
34
+ }
35
+ },
36
+ "release_backend": "full"
37
+ }
eval/full_irish_remaining_gaps_v2.json ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "models/irishcore-globalpointer-135m-b01-extendedv1-e025",
3
+ "input": "eval/irish_remaining_gaps_v2.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 6,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.08656914997845888,
9
+ "examples_per_second": 69.30875492589436,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 5,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "PASSPORT_NUMBER": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 2,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "PHONE_NUMBER": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 3,
32
+ "fp": 0,
33
+ "fn": 0
34
+ }
35
+ }
36
+ }
eval/full_multilingual_ppsn_v1_all.json ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "models/irishcore-globalpointer-135m-b01-extendedv1-e025",
3
+ "input": "eval/multilingual_ppsn_v1_all.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 168,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 2.862528417026624,
9
+ "examples_per_second": 58.68937370218514,
10
+ "overall": {
11
+ "precision": 0.875,
12
+ "recall": 1.0,
13
+ "f1": 0.9333333333333333,
14
+ "tp": 84,
15
+ "fp": 12,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "PPSN": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 84,
24
+ "fp": 0,
25
+ "fn": 0
26
+ }
27
+ }
28
+ }
eval/full_runtime_profile_source.json ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc1",
3
+ "input": "runtime_profile_source.jsonl",
4
+ "loader_type": "global_pointer_pt",
5
+ "examples": 3223,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 46.959111439064145,
9
+ "examples_per_second": 68.63417771825351,
10
+ "overall": {
11
+ "precision": 0.585127996749289,
12
+ "recall": 0.40597688187200454,
13
+ "f1": 0.47936085219707064,
14
+ "tp": 1440,
15
+ "fp": 1021,
16
+ "fn": 2107
17
+ },
18
+ "by_label": {
19
+ "PPSN": {
20
+ "precision": 0.9320388349514563,
21
+ "recall": 0.40597688187200454,
22
+ "f1": 0.5655930871956009,
23
+ "tp": 1440,
24
+ "fp": 105,
25
+ "fn": 2107
26
+ }
27
+ },
28
+ "release_backend": "full"
29
+ }
eval/label_inventory.json ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "labels": [
3
+ "ACCOUNT_NUMBER",
4
+ "AGE",
5
+ "BANK_ROUTING_NUMBER",
6
+ "CITY",
7
+ "COUNTY",
8
+ "CREDIT_DEBIT_CARD",
9
+ "DATE_OF_BIRTH",
10
+ "EMAIL",
11
+ "FIRST_NAME",
12
+ "LAST_NAME",
13
+ "PASSPORT_NUMBER",
14
+ "PHONE_NUMBER",
15
+ "POSTCODE",
16
+ "PPSN",
17
+ "STREET_ADDRESS",
18
+ "SWIFT_BIC"
19
+ ]
20
+ }
eval/q8_diffmask_fresh_holdout_v1.json ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc1",
3
+ "input": "diffmask_fresh_holdout_v1.jsonl",
4
+ "loader_type": "global_pointer_onnx",
5
+ "examples": 20,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.13704864599276334,
9
+ "examples_per_second": 145.93358332818605,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 0.96875,
13
+ "f1": 0.9841269841269841,
14
+ "tp": 31,
15
+ "fp": 0,
16
+ "fn": 1
17
+ },
18
+ "by_label": {
19
+ "ACCOUNT_NUMBER": {
20
+ "precision": 1.0,
21
+ "recall": 0.5,
22
+ "f1": 0.6666666666666666,
23
+ "tp": 1,
24
+ "fp": 0,
25
+ "fn": 1
26
+ },
27
+ "CREDIT_DEBIT_CARD": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 2,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "EMAIL": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 6,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "FIRST_NAME": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 4,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "LAST_NAME": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 4,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "PHONE_NUMBER": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 6,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "POSTCODE": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 2,
72
+ "fp": 0,
73
+ "fn": 0
74
+ },
75
+ "PPSN": {
76
+ "precision": 1.0,
77
+ "recall": 1.0,
78
+ "f1": 1.0,
79
+ "tp": 6,
80
+ "fp": 0,
81
+ "fn": 0
82
+ }
83
+ },
84
+ "release_backend": "onnx_q8"
85
+ }
eval/q8_diffmask_gap_uat_exact_v1.json ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc1",
3
+ "input": "diffmask_gap_uat_exact_v1.jsonl",
4
+ "loader_type": "global_pointer_onnx",
5
+ "examples": 16,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.08481148700229824,
9
+ "examples_per_second": 188.65369026681998,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 17,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "EMAIL": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 3,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "PHONE_NUMBER": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 6,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "POSTCODE": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 3,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "PPSN": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 5,
48
+ "fp": 0,
49
+ "fn": 0
50
+ }
51
+ },
52
+ "release_backend": "onnx_q8"
53
+ }
eval/q8_globalpointer_context_redteam_v1.json ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc9",
3
+ "input": "eval/globalpointer_context_redteam_v1.jsonl",
4
+ "loader_type": "global_pointer_onnx",
5
+ "examples": 14,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.1809925140114501,
9
+ "examples_per_second": 77.35126547341245,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 54,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "AGE": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 2,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "CITY": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 8,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "COUNTY": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 10,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "DATE_OF_BIRTH": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 4,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "EMAIL": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 4,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "FIRST_NAME": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 2,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "LAST_NAME": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 2,
72
+ "fp": 0,
73
+ "fn": 0
74
+ },
75
+ "PHONE_NUMBER": {
76
+ "precision": 1.0,
77
+ "recall": 1.0,
78
+ "f1": 1.0,
79
+ "tp": 4,
80
+ "fp": 0,
81
+ "fn": 0
82
+ },
83
+ "POSTCODE": {
84
+ "precision": 1.0,
85
+ "recall": 1.0,
86
+ "f1": 1.0,
87
+ "tp": 8,
88
+ "fp": 0,
89
+ "fn": 0
90
+ },
91
+ "PPSN": {
92
+ "precision": 1.0,
93
+ "recall": 1.0,
94
+ "f1": 1.0,
95
+ "tp": 2,
96
+ "fp": 0,
97
+ "fn": 0
98
+ },
99
+ "STREET_ADDRESS": {
100
+ "precision": 1.0,
101
+ "recall": 1.0,
102
+ "f1": 1.0,
103
+ "tp": 8,
104
+ "fp": 0,
105
+ "fn": 0
106
+ }
107
+ },
108
+ "backend": "onnx_q8"
109
+ }
eval/q8_globalpointer_context_redteam_v2.json ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc9",
3
+ "input": "eval/globalpointer_context_redteam_v2.jsonl",
4
+ "loader_type": "global_pointer_onnx",
5
+ "examples": 6,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.0719167779898271,
9
+ "examples_per_second": 83.42976656780596,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 13,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "CITY": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 4,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "COUNTY": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 1,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "DATE_OF_BIRTH": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 1,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "PHONE_NUMBER": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 2,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "POSTCODE": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 3,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "STREET_ADDRESS": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 2,
64
+ "fp": 0,
65
+ "fn": 0
66
+ }
67
+ },
68
+ "backend": "onnx_q8"
69
+ }
eval/q8_globalpointer_context_redteam_v3.json ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc10",
3
+ "input": "eval/globalpointer_context_redteam_v3.jsonl",
4
+ "loader_type": "global_pointer_onnx",
5
+ "examples": 12,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.10364121198654175,
9
+ "examples_per_second": 115.78405703667622,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 22,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "AGE": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 3,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "CITY": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 7,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "COUNTY": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 1,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "DATE_OF_BIRTH": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 3,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "PHONE_NUMBER": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 3,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "POSTCODE": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 3,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "STREET_ADDRESS": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 2,
72
+ "fp": 0,
73
+ "fn": 0
74
+ }
75
+ },
76
+ "backend": "onnx_q8"
77
+ }
eval/q8_globalpointer_context_redteam_v4.json ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "temsa/IrishCore-GlobalPointer-ContextPII-135M-v1-rc10",
3
+ "input": "eval/globalpointer_context_redteam_v4.jsonl",
4
+ "loader_type": "global_pointer_onnx",
5
+ "examples": 21,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.18228210194502026,
9
+ "examples_per_second": 115.20604478400188,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 43,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "AGE": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 3,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "CITY": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 10,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "COUNTY": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 1,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "DATE_OF_BIRTH": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 6,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "FIRST_NAME": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 2,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "LAST_NAME": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 2,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "PHONE_NUMBER": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 6,
72
+ "fp": 0,
73
+ "fn": 0
74
+ },
75
+ "POSTCODE": {
76
+ "precision": 1.0,
77
+ "recall": 1.0,
78
+ "f1": 1.0,
79
+ "tp": 6,
80
+ "fp": 0,
81
+ "fn": 0
82
+ },
83
+ "PPSN": {
84
+ "precision": 1.0,
85
+ "recall": 1.0,
86
+ "f1": 1.0,
87
+ "tp": 2,
88
+ "fp": 0,
89
+ "fn": 0
90
+ },
91
+ "STREET_ADDRESS": {
92
+ "precision": 1.0,
93
+ "recall": 1.0,
94
+ "f1": 1.0,
95
+ "tp": 5,
96
+ "fp": 0,
97
+ "fn": 0
98
+ }
99
+ },
100
+ "backend": "onnx_q8"
101
+ }
eval/q8_globalpointer_context_redteam_v5.json ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "models/irishcore-globalpointer-135m-b01-extendedv1-e025_onnx_q8_pc",
3
+ "input": "eval/globalpointer_context_redteam_v5.jsonl",
4
+ "loader_type": "global_pointer_onnx",
5
+ "examples": 25,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.173182278056629,
9
+ "examples_per_second": 144.35657204962527,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 47,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "AGE": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 3,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "CITY": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 10,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "COUNTY": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 1,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "DATE_OF_BIRTH": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 8,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "FIRST_NAME": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 2,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "LAST_NAME": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 2,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "PHONE_NUMBER": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 8,
72
+ "fp": 0,
73
+ "fn": 0
74
+ },
75
+ "POSTCODE": {
76
+ "precision": 1.0,
77
+ "recall": 1.0,
78
+ "f1": 1.0,
79
+ "tp": 6,
80
+ "fp": 0,
81
+ "fn": 0
82
+ },
83
+ "PPSN": {
84
+ "precision": 1.0,
85
+ "recall": 1.0,
86
+ "f1": 1.0,
87
+ "tp": 2,
88
+ "fp": 0,
89
+ "fn": 0
90
+ },
91
+ "STREET_ADDRESS": {
92
+ "precision": 1.0,
93
+ "recall": 1.0,
94
+ "f1": 1.0,
95
+ "tp": 5,
96
+ "fp": 0,
97
+ "fn": 0
98
+ }
99
+ }
100
+ }
eval/q8_globalpointer_context_redteam_v6.json ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "models/irishcore-globalpointer-135m-b01-extendedv1-e025_onnx_q8_pc",
3
+ "input": "eval/globalpointer_context_redteam_v6.jsonl",
4
+ "loader_type": "global_pointer_onnx",
5
+ "examples": 38,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.24047453701496124,
9
+ "examples_per_second": 158.02088849696304,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 72,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "AGE": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 5,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "CITY": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 14,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "COUNTY": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 1,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "DATE_OF_BIRTH": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 10,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "FIRST_NAME": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 4,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "LAST_NAME": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 7,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "PHONE_NUMBER": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 8,
72
+ "fp": 0,
73
+ "fn": 0
74
+ },
75
+ "POSTCODE": {
76
+ "precision": 1.0,
77
+ "recall": 1.0,
78
+ "f1": 1.0,
79
+ "tp": 10,
80
+ "fp": 0,
81
+ "fn": 0
82
+ },
83
+ "PPSN": {
84
+ "precision": 1.0,
85
+ "recall": 1.0,
86
+ "f1": 1.0,
87
+ "tp": 4,
88
+ "fp": 0,
89
+ "fn": 0
90
+ },
91
+ "STREET_ADDRESS": {
92
+ "precision": 1.0,
93
+ "recall": 1.0,
94
+ "f1": 1.0,
95
+ "tp": 9,
96
+ "fp": 0,
97
+ "fn": 0
98
+ }
99
+ }
100
+ }
eval/q8_globalpointer_context_redteam_v7.json ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "release/IrishCore-GlobalPointer-ContextPII-135M-v1-rc14",
3
+ "input": "eval/globalpointer_context_redteam_v7.jsonl",
4
+ "loader_type": "global_pointer_onnx",
5
+ "examples": 41,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.3538584579946473,
9
+ "examples_per_second": 115.86553627218991,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 84,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "AGE": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 5,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "CITY": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 17,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "COUNTY": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 4,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "DATE_OF_BIRTH": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 10,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "FIRST_NAME": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 4,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "LAST_NAME": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 7,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "PHONE_NUMBER": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 8,
72
+ "fp": 0,
73
+ "fn": 0
74
+ },
75
+ "POSTCODE": {
76
+ "precision": 1.0,
77
+ "recall": 1.0,
78
+ "f1": 1.0,
79
+ "tp": 13,
80
+ "fp": 0,
81
+ "fn": 0
82
+ },
83
+ "PPSN": {
84
+ "precision": 1.0,
85
+ "recall": 1.0,
86
+ "f1": 1.0,
87
+ "tp": 4,
88
+ "fp": 0,
89
+ "fn": 0
90
+ },
91
+ "STREET_ADDRESS": {
92
+ "precision": 1.0,
93
+ "recall": 1.0,
94
+ "f1": 1.0,
95
+ "tp": 12,
96
+ "fp": 0,
97
+ "fn": 0
98
+ }
99
+ }
100
+ }
eval/q8_globalpointer_context_redteam_v8.json ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "release/IrishCore-GlobalPointer-ContextPII-135M-v1-rc14",
3
+ "input": "eval/globalpointer_context_redteam_v8.jsonl",
4
+ "loader_type": "global_pointer_onnx",
5
+ "examples": 51,
6
+ "min_score": 0.5,
7
+ "iou_threshold": 0.5,
8
+ "elapsed_seconds": 0.49920400499831885,
9
+ "examples_per_second": 102.16264190462925,
10
+ "overall": {
11
+ "precision": 1.0,
12
+ "recall": 1.0,
13
+ "f1": 1.0,
14
+ "tp": 113,
15
+ "fp": 0,
16
+ "fn": 0
17
+ },
18
+ "by_label": {
19
+ "AGE": {
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "f1": 1.0,
23
+ "tp": 5,
24
+ "fp": 0,
25
+ "fn": 0
26
+ },
27
+ "CITY": {
28
+ "precision": 1.0,
29
+ "recall": 1.0,
30
+ "f1": 1.0,
31
+ "tp": 25,
32
+ "fp": 0,
33
+ "fn": 0
34
+ },
35
+ "COUNTY": {
36
+ "precision": 1.0,
37
+ "recall": 1.0,
38
+ "f1": 1.0,
39
+ "tp": 10,
40
+ "fp": 0,
41
+ "fn": 0
42
+ },
43
+ "DATE_OF_BIRTH": {
44
+ "precision": 1.0,
45
+ "recall": 1.0,
46
+ "f1": 1.0,
47
+ "tp": 10,
48
+ "fp": 0,
49
+ "fn": 0
50
+ },
51
+ "FIRST_NAME": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1": 1.0,
55
+ "tp": 6,
56
+ "fp": 0,
57
+ "fn": 0
58
+ },
59
+ "LAST_NAME": {
60
+ "precision": 1.0,
61
+ "recall": 1.0,
62
+ "f1": 1.0,
63
+ "tp": 9,
64
+ "fp": 0,
65
+ "fn": 0
66
+ },
67
+ "PHONE_NUMBER": {
68
+ "precision": 1.0,
69
+ "recall": 1.0,
70
+ "f1": 1.0,
71
+ "tp": 8,
72
+ "fp": 0,
73
+ "fn": 0
74
+ },
75
+ "POSTCODE": {
76
+ "precision": 1.0,
77
+ "recall": 1.0,
78
+ "f1": 1.0,
79
+ "tp": 19,
80
+ "fp": 0,
81
+ "fn": 0
82
+ },
83
+ "PPSN": {
84
+ "precision": 1.0,
85
+ "recall": 1.0,
86
+ "f1": 1.0,
87
+ "tp": 6,
88
+ "fp": 0,
89
+ "fn": 0
90
+ },
91
+ "STREET_ADDRESS": {
92
+ "precision": 1.0,
93
+ "recall": 1.0,
94
+ "f1": 1.0,
95
+ "tp": 15,
96
+ "fp": 0,
97
+ "fn": 0
98
+ }
99
+ }
100
+ }