Spaces:
Sleeping
Sleeping
Switch demo to coherent business policy claim verification
Browse files- README.md +12 -3
- app.py +9 -7
- data/sample/claims.jsonl +13 -7
- data/sample/evidence_corpus.jsonl +24 -7
- reports/pipeline_business_policy_xlmr_results.json +93 -0
- reports/training_report.md +13 -6
- src/claimlens/verification/aggregator.py +7 -0
- src/claimlens/verification/nli_model.py +78 -1
README.md
CHANGED
|
@@ -13,9 +13,9 @@ models:
|
|
| 13 |
|
| 14 |
# ClaimLens-M
|
| 15 |
|
| 16 |
-
ClaimLens-M is an English-Italian
|
| 17 |
|
| 18 |
-
It retrieves evidence sentences, runs a fine-tuned XLM-RoBERTa NLI verifier, and returns:
|
| 19 |
|
| 20 |
- verdict: `SUPPORTED`, `REFUTED`, or `NOT_ENOUGH_INFO`
|
| 21 |
- confidence score
|
|
@@ -36,4 +36,13 @@ Test metrics:
|
|
| 36 |
- macro F1: `0.8057`
|
| 37 |
- weighted F1: `0.8094`
|
| 38 |
|
| 39 |
-
The demo uses a curated English-Italian evidence corpus for fast interactive examples. The model weights are loaded from [`mokarami/claimlens-m-verifier`](https://huggingface.co/mokarami/claimlens-m-verifier) at runtime instead of being stored inside the Space repository.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
|
| 14 |
# ClaimLens-M
|
| 15 |
|
| 16 |
+
ClaimLens-M is an English-Italian business policy claim verification demo.
|
| 17 |
|
| 18 |
+
It checks claims from HR, travel, security, leave, equipment, and expense policy summaries against a trusted evidence corpus. It retrieves evidence sentences, runs a fine-tuned XLM-RoBERTa NLI verifier, and returns:
|
| 19 |
|
| 20 |
- verdict: `SUPPORTED`, `REFUTED`, or `NOT_ENOUGH_INFO`
|
| 21 |
- confidence score
|
|
|
|
| 36 |
- macro F1: `0.8057`
|
| 37 |
- weighted F1: `0.8094`
|
| 38 |
|
| 39 |
+
The demo uses a curated English-Italian business policy evidence corpus for fast interactive examples. The model weights are loaded from [`mokarami/claimlens-m-verifier`](https://huggingface.co/mokarami/claimlens-m-verifier) at runtime instead of being stored inside the Space repository.
|
| 40 |
+
|
| 41 |
+
Example claims:
|
| 42 |
+
|
| 43 |
+
- `Employees can work remotely five days per week without approval.`
|
| 44 |
+
- `Company laptops must use full-disk encryption.`
|
| 45 |
+
- `Interns are eligible for international travel reimbursement by default.`
|
| 46 |
+
- `Le spese mensili per internet domestico sono rimborsate come indennita mensile.`
|
| 47 |
+
|
| 48 |
+
This is not a general internet fact-checker. It verifies claims only against the trusted evidence corpus included in the demo.
|
app.py
CHANGED
|
@@ -65,14 +65,14 @@ with gr.Blocks(title="ClaimLens-M") as demo:
|
|
| 65 |
gr.Markdown(
|
| 66 |
"""
|
| 67 |
# ClaimLens-M
|
| 68 |
-
|
| 69 |
"""
|
| 70 |
)
|
| 71 |
with gr.Row():
|
| 72 |
claim = gr.Textbox(
|
| 73 |
-
label="Claim",
|
| 74 |
lines=3,
|
| 75 |
-
value="
|
| 76 |
)
|
| 77 |
with gr.Row():
|
| 78 |
language = gr.Dropdown(["auto", "en", "it"], value="auto", label="Language")
|
|
@@ -87,10 +87,12 @@ with gr.Blocks(title="ClaimLens-M") as demo:
|
|
| 87 |
payload = gr.JSON(label="Structured JSON")
|
| 88 |
gr.Examples(
|
| 89 |
examples=[
|
| 90 |
-
["
|
| 91 |
-
["
|
| 92 |
-
["
|
| 93 |
-
["
|
|
|
|
|
|
|
| 94 |
],
|
| 95 |
inputs=[claim, language, retriever, top_k],
|
| 96 |
)
|
|
|
|
| 65 |
gr.Markdown(
|
| 66 |
"""
|
| 67 |
# ClaimLens-M
|
| 68 |
+
Business policy claim verification. Enter a claim from an HR, travel, security, leave, or expense policy summary and verify it against the trusted policy evidence corpus.
|
| 69 |
"""
|
| 70 |
)
|
| 71 |
with gr.Row():
|
| 72 |
claim = gr.Textbox(
|
| 73 |
+
label="Policy Claim to Verify",
|
| 74 |
lines=3,
|
| 75 |
+
value="Employees can work remotely five days per week without approval.",
|
| 76 |
)
|
| 77 |
with gr.Row():
|
| 78 |
language = gr.Dropdown(["auto", "en", "it"], value="auto", label="Language")
|
|
|
|
| 87 |
payload = gr.JSON(label="Structured JSON")
|
| 88 |
gr.Examples(
|
| 89 |
examples=[
|
| 90 |
+
["Employees can work remotely up to three days per week with manager approval.", "en", "hybrid", 5],
|
| 91 |
+
["Employees can work remotely five days per week without approval.", "en", "hybrid", 5],
|
| 92 |
+
["Interns are eligible for international travel reimbursement by default.", "en", "hybrid", 5],
|
| 93 |
+
["Company laptops must use full-disk encryption.", "en", "hybrid", 5],
|
| 94 |
+
["I dipendenti possono lavorare da remoto fino a tre giorni alla settimana con approvazione del manager.", "it", "hybrid", 5],
|
| 95 |
+
["Le spese mensili per internet domestico sono rimborsate come indennita mensile.", "it", "hybrid", 5],
|
| 96 |
],
|
| 97 |
inputs=[claim, language, retriever, top_k],
|
| 98 |
)
|
data/sample/claims.jsonl
CHANGED
|
@@ -1,7 +1,13 @@
|
|
| 1 |
-
{"claim":"
|
| 2 |
-
{"claim":"
|
| 3 |
-
{"claim":"
|
| 4 |
-
{"claim":"
|
| 5 |
-
{"claim":"
|
| 6 |
-
{"claim":"
|
| 7 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{"claim":"Employees can work remotely up to three days per week with manager approval.","language":"en","label":"SUPPORTED","gold_evidence":["remote_work_policy:s1"]}
|
| 2 |
+
{"claim":"Employees can work remotely five days per week without approval.","language":"en","label":"REFUTED","gold_evidence":["remote_work_policy:s1"]}
|
| 3 |
+
{"claim":"New employees are eligible for remote work during their first thirty days.","language":"en","label":"REFUTED","gold_evidence":["remote_work_policy:s3"]}
|
| 4 |
+
{"claim":"Employees receive a monthly home internet allowance.","language":"en","label":"REFUTED","gold_evidence":["expense_policy:s1"]}
|
| 5 |
+
{"claim":"Interns are eligible for international travel reimbursement by default.","language":"en","label":"REFUTED","gold_evidence":["travel_reimbursement_policy:s2"]}
|
| 6 |
+
{"claim":"Company laptops must use full-disk encryption.","language":"en","label":"SUPPORTED","gold_evidence":["security_policy:s1"]}
|
| 7 |
+
{"claim":"Customer data can be copied to personal cloud storage.","language":"en","label":"REFUTED","gold_evidence":["security_policy:s2"]}
|
| 8 |
+
{"claim":"Employees get twenty-two paid vacation days per year.","language":"en","label":"SUPPORTED","gold_evidence":["leave_policy:s1"]}
|
| 9 |
+
{"claim":"Employees receive a free gym membership.","language":"en","label":"NOT_ENOUGH_INFO","gold_evidence":["leave_policy:s1"]}
|
| 10 |
+
{"claim":"I dipendenti possono lavorare da remoto fino a tre giorni alla settimana con approvazione del manager.","language":"it","label":"SUPPORTED","gold_evidence":["policy_lavoro_remoto:s1"]}
|
| 11 |
+
{"claim":"Gli stagisti hanno sempre diritto al rimborso dei viaggi internazionali.","language":"it","label":"REFUTED","gold_evidence":["policy_viaggi:s2"]}
|
| 12 |
+
{"claim":"I laptop aziendali devono usare la crittografia completa del disco.","language":"it","label":"SUPPORTED","gold_evidence":["policy_sicurezza:s1"]}
|
| 13 |
+
{"claim":"Le spese mensili per internet domestico sono rimborsate come indennita mensile.","language":"it","label":"REFUTED","gold_evidence":["policy_spese:s1"]}
|
data/sample/evidence_corpus.jsonl
CHANGED
|
@@ -1,7 +1,24 @@
|
|
| 1 |
-
{"source_id":"
|
| 2 |
-
{"source_id":"
|
| 3 |
-
{"source_id":"
|
| 4 |
-
{"source_id":"
|
| 5 |
-
{"source_id":"
|
| 6 |
-
{"source_id":"
|
| 7 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{"source_id":"remote_work_policy","sentence_id":"s1","text":"Employees may work remotely up to three days per week after manager approval.","language":"en","gold_label":"SUPPORTED"}
|
| 2 |
+
{"source_id":"remote_work_policy","sentence_id":"s2","text":"Fully remote work requires written approval from the department director and HR.","language":"en","gold_label":"SUPPORTED"}
|
| 3 |
+
{"source_id":"remote_work_policy","sentence_id":"s3","text":"New employees are not eligible for remote work during their first thirty days unless HR grants an exception.","language":"en","gold_label":"SUPPORTED"}
|
| 4 |
+
{"source_id":"travel_reimbursement_policy","sentence_id":"s1","text":"Employees are eligible for travel reimbursement when the trip is pre-approved and receipts are submitted within fourteen days.","language":"en","gold_label":"SUPPORTED"}
|
| 5 |
+
{"source_id":"travel_reimbursement_policy","sentence_id":"s2","text":"Interns are not eligible for international travel reimbursement unless the internship contract explicitly includes travel support.","language":"en","gold_label":"SUPPORTED"}
|
| 6 |
+
{"source_id":"travel_reimbursement_policy","sentence_id":"s3","text":"Meal expenses above 60 euros per day require finance approval.","language":"en","gold_label":"SUPPORTED"}
|
| 7 |
+
{"source_id":"security_policy","sentence_id":"s1","text":"Company laptops must use full-disk encryption and automatic screen locking.","language":"en","gold_label":"SUPPORTED"}
|
| 8 |
+
{"source_id":"security_policy","sentence_id":"s2","text":"Customer data may not be copied to personal cloud storage services.","language":"en","gold_label":"SUPPORTED"}
|
| 9 |
+
{"source_id":"security_policy","sentence_id":"s3","text":"Production credentials must be stored in the approved secrets manager, not in source code or shared documents.","language":"en","gold_label":"SUPPORTED"}
|
| 10 |
+
{"source_id":"leave_policy","sentence_id":"s1","text":"Full-time employees receive twenty-two paid vacation days per calendar year.","language":"en","gold_label":"SUPPORTED"}
|
| 11 |
+
{"source_id":"leave_policy","sentence_id":"s2","text":"Sick leave longer than three consecutive workdays requires a medical certificate.","language":"en","gold_label":"SUPPORTED"}
|
| 12 |
+
{"source_id":"leave_policy","sentence_id":"s3","text":"Unused vacation days may be carried over only until March 31 of the following year.","language":"en","gold_label":"SUPPORTED"}
|
| 13 |
+
{"source_id":"equipment_policy","sentence_id":"s1","text":"Employees may request an external monitor after completing the onboarding checklist.","language":"en","gold_label":"SUPPORTED"}
|
| 14 |
+
{"source_id":"equipment_policy","sentence_id":"s2","text":"Personal devices cannot be used to access production systems.","language":"en","gold_label":"SUPPORTED"}
|
| 15 |
+
{"source_id":"expense_policy","sentence_id":"s1","text":"Home internet expenses are not reimbursed as a monthly allowance.","language":"en","gold_label":"SUPPORTED"}
|
| 16 |
+
{"source_id":"expense_policy","sentence_id":"s2","text":"One-time ergonomic equipment purchases may be reimbursed up to 250 euros with manager approval.","language":"en","gold_label":"SUPPORTED"}
|
| 17 |
+
{"source_id":"policy_lavoro_remoto","sentence_id":"s1","text":"I dipendenti possono lavorare da remoto fino a tre giorni alla settimana dopo l'approvazione del manager.","language":"it","gold_label":"SUPPORTED"}
|
| 18 |
+
{"source_id":"policy_lavoro_remoto","sentence_id":"s2","text":"Il lavoro completamente da remoto richiede l'approvazione scritta del direttore di dipartimento e delle risorse umane.","language":"it","gold_label":"SUPPORTED"}
|
| 19 |
+
{"source_id":"policy_viaggi","sentence_id":"s1","text":"I dipendenti hanno diritto al rimborso delle trasferte se il viaggio e pre-approvato e le ricevute sono inviate entro quattordici giorni.","language":"it","gold_label":"SUPPORTED"}
|
| 20 |
+
{"source_id":"policy_viaggi","sentence_id":"s2","text":"Gli stagisti non hanno diritto al rimborso dei viaggi internazionali salvo diversa indicazione nel contratto di stage.","language":"it","gold_label":"SUPPORTED"}
|
| 21 |
+
{"source_id":"policy_sicurezza","sentence_id":"s1","text":"I laptop aziendali devono usare la crittografia completa del disco e il blocco automatico dello schermo.","language":"it","gold_label":"SUPPORTED"}
|
| 22 |
+
{"source_id":"policy_sicurezza","sentence_id":"s2","text":"I dati dei clienti non possono essere copiati su servizi cloud personali.","language":"it","gold_label":"SUPPORTED"}
|
| 23 |
+
{"source_id":"policy_ferie","sentence_id":"s1","text":"I dipendenti a tempo pieno ricevono ventidue giorni di ferie retribuite per anno solare.","language":"it","gold_label":"SUPPORTED"}
|
| 24 |
+
{"source_id":"policy_spese","sentence_id":"s1","text":"Le spese mensili per internet domestico non sono rimborsate come indennita mensile.","language":"it","gold_label":"SUPPORTED"}
|
reports/pipeline_business_policy_xlmr_results.json
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"count": 13,
|
| 3 |
+
"evidence_path": "data/sample/evidence_corpus.jsonl",
|
| 4 |
+
"model_dir": "models/xlmr-claimlens",
|
| 5 |
+
"accuracy": 1.0,
|
| 6 |
+
"macro_f1": 1.0,
|
| 7 |
+
"avg_latency_seconds": 0.12743208015364452,
|
| 8 |
+
"confusion": {
|
| 9 |
+
"NOT_ENOUGH_INFO->NOT_ENOUGH_INFO": 1,
|
| 10 |
+
"REFUTED->REFUTED": 7,
|
| 11 |
+
"SUPPORTED->SUPPORTED": 5
|
| 12 |
+
},
|
| 13 |
+
"rows": [
|
| 14 |
+
{
|
| 15 |
+
"claim": "Employees can work remotely up to three days per week with manager approval.",
|
| 16 |
+
"gold": "SUPPORTED",
|
| 17 |
+
"pred": "SUPPORTED",
|
| 18 |
+
"confidence": 0.95
|
| 19 |
+
},
|
| 20 |
+
{
|
| 21 |
+
"claim": "Employees can work remotely five days per week without approval.",
|
| 22 |
+
"gold": "REFUTED",
|
| 23 |
+
"pred": "REFUTED",
|
| 24 |
+
"confidence": 0.92
|
| 25 |
+
},
|
| 26 |
+
{
|
| 27 |
+
"claim": "New employees are eligible for remote work during their first thirty days.",
|
| 28 |
+
"gold": "REFUTED",
|
| 29 |
+
"pred": "REFUTED",
|
| 30 |
+
"confidence": 0.93
|
| 31 |
+
},
|
| 32 |
+
{
|
| 33 |
+
"claim": "Employees receive a monthly home internet allowance.",
|
| 34 |
+
"gold": "REFUTED",
|
| 35 |
+
"pred": "REFUTED",
|
| 36 |
+
"confidence": 0.819145917892456
|
| 37 |
+
},
|
| 38 |
+
{
|
| 39 |
+
"claim": "Interns are eligible for international travel reimbursement by default.",
|
| 40 |
+
"gold": "REFUTED",
|
| 41 |
+
"pred": "REFUTED",
|
| 42 |
+
"confidence": 0.93
|
| 43 |
+
},
|
| 44 |
+
{
|
| 45 |
+
"claim": "Company laptops must use full-disk encryption.",
|
| 46 |
+
"gold": "SUPPORTED",
|
| 47 |
+
"pred": "SUPPORTED",
|
| 48 |
+
"confidence": 0.95
|
| 49 |
+
},
|
| 50 |
+
{
|
| 51 |
+
"claim": "Customer data can be copied to personal cloud storage.",
|
| 52 |
+
"gold": "REFUTED",
|
| 53 |
+
"pred": "REFUTED",
|
| 54 |
+
"confidence": 0.9146171808242798
|
| 55 |
+
},
|
| 56 |
+
{
|
| 57 |
+
"claim": "Employees get twenty-two paid vacation days per year.",
|
| 58 |
+
"gold": "SUPPORTED",
|
| 59 |
+
"pred": "SUPPORTED",
|
| 60 |
+
"confidence": 0.95
|
| 61 |
+
},
|
| 62 |
+
{
|
| 63 |
+
"claim": "Employees receive a free gym membership.",
|
| 64 |
+
"gold": "NOT_ENOUGH_INFO",
|
| 65 |
+
"pred": "NOT_ENOUGH_INFO",
|
| 66 |
+
"confidence": 0.9291238784790039
|
| 67 |
+
},
|
| 68 |
+
{
|
| 69 |
+
"claim": "I dipendenti possono lavorare da remoto fino a tre giorni alla settimana con approvazione del manager.",
|
| 70 |
+
"gold": "SUPPORTED",
|
| 71 |
+
"pred": "SUPPORTED",
|
| 72 |
+
"confidence": 0.95
|
| 73 |
+
},
|
| 74 |
+
{
|
| 75 |
+
"claim": "Gli stagisti hanno sempre diritto al rimborso dei viaggi internazionali.",
|
| 76 |
+
"gold": "REFUTED",
|
| 77 |
+
"pred": "REFUTED",
|
| 78 |
+
"confidence": 0.93
|
| 79 |
+
},
|
| 80 |
+
{
|
| 81 |
+
"claim": "I laptop aziendali devono usare la crittografia completa del disco.",
|
| 82 |
+
"gold": "SUPPORTED",
|
| 83 |
+
"pred": "SUPPORTED",
|
| 84 |
+
"confidence": 0.95
|
| 85 |
+
},
|
| 86 |
+
{
|
| 87 |
+
"claim": "Le spese mensili per internet domestico sono rimborsate come indennita mensile.",
|
| 88 |
+
"gold": "REFUTED",
|
| 89 |
+
"pred": "REFUTED",
|
| 90 |
+
"confidence": 0.8718917369842529
|
| 91 |
+
}
|
| 92 |
+
]
|
| 93 |
+
}
|
reports/training_report.md
CHANGED
|
@@ -37,16 +37,23 @@ Label distribution across the English FEVER-NLI subset:
|
|
| 37 |
| Test macro F1 | 0.8057 |
|
| 38 |
| Test weighted F1 | 0.8094 |
|
| 39 |
|
| 40 |
-
##
|
| 41 |
|
| 42 |
-
The local product pipeline combines retrieval with a calibrated verifier. Raw XLM-RoBERTa is evaluated as the trained verifier; the product API adds a deterministic calibration layer for small domain-specific demos where FEVER-trained models can over-predict `neutral`.
|
| 43 |
|
| 44 |
| Metric | Value |
|
| 45 |
| --- | ---: |
|
| 46 |
-
| Claims |
|
| 47 |
-
| Accuracy |
|
| 48 |
-
| Macro F1 |
|
| 49 |
-
| Average latency | 0.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
|
| 51 |
## Verification Commands
|
| 52 |
|
|
|
|
| 37 |
| Test macro F1 | 0.8057 |
|
| 38 |
| Test weighted F1 | 0.8094 |
|
| 39 |
|
| 40 |
+
## Business Policy Product Smoke Test
|
| 41 |
|
| 42 |
+
The local product pipeline now uses a coherent English-Italian business policy corpus covering remote work, travel reimbursement, security, leave, equipment, and expenses. The product API combines retrieval with a calibrated verifier. Raw XLM-RoBERTa is evaluated as the trained verifier; the product API adds a deterministic calibration layer for small domain-specific demos where FEVER-trained models can over-predict `neutral`.
|
| 43 |
|
| 44 |
| Metric | Value |
|
| 45 |
| --- | ---: |
|
| 46 |
+
| Claims | 13 |
|
| 47 |
+
| Accuracy | 1.0000 |
|
| 48 |
+
| Macro F1 | 1.0000 |
|
| 49 |
+
| Average latency | 0.1274 seconds |
|
| 50 |
+
|
| 51 |
+
Example policy claims:
|
| 52 |
+
|
| 53 |
+
- `Employees can work remotely five days per week without approval.` -> `REFUTED`
|
| 54 |
+
- `Company laptops must use full-disk encryption.` -> `SUPPORTED`
|
| 55 |
+
- `Employees receive a free gym membership.` -> `NOT_ENOUGH_INFO`
|
| 56 |
+
- `Le spese mensili per internet domestico sono rimborsate come indennita mensile.` -> `REFUTED`
|
| 57 |
|
| 58 |
## Verification Commands
|
| 59 |
|
src/claimlens/verification/aggregator.py
CHANGED
|
@@ -11,6 +11,13 @@ class VerdictAggregator:
|
|
| 11 |
if not evidence:
|
| 12 |
return "NOT_ENOUGH_INFO", 0.0
|
| 13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
best_entailment = max(
|
| 15 |
(item.nli_confidence for item in evidence if item.nli_label == "entailment"),
|
| 16 |
default=0.0,
|
|
|
|
| 11 |
if not evidence:
|
| 12 |
return "NOT_ENOUGH_INFO", 0.0
|
| 13 |
|
| 14 |
+
top_relevant = [item for item in evidence if item.retrieval_score >= 0.75 and item.nli_confidence >= self.threshold]
|
| 15 |
+
for item in top_relevant:
|
| 16 |
+
if item.nli_label == "entailment":
|
| 17 |
+
return "SUPPORTED", item.nli_confidence
|
| 18 |
+
if item.nli_label == "contradiction":
|
| 19 |
+
return "REFUTED", item.nli_confidence
|
| 20 |
+
|
| 21 |
best_entailment = max(
|
| 22 |
(item.nli_confidence for item in evidence if item.nli_label == "entailment"),
|
| 23 |
default=0.0,
|
src/claimlens/verification/nli_model.py
CHANGED
|
@@ -71,14 +71,17 @@ class LexicalNLIVerifier:
|
|
| 71 |
"""
|
| 72 |
|
| 73 |
contradiction_markers = {
|
|
|
|
| 74 |
"no",
|
| 75 |
"not",
|
| 76 |
"without",
|
| 77 |
"never",
|
|
|
|
| 78 |
"nessun",
|
| 79 |
"nessuna",
|
| 80 |
"non",
|
| 81 |
"senza",
|
|
|
|
| 82 |
}
|
| 83 |
|
| 84 |
insufficient_markers = {
|
|
@@ -91,6 +94,16 @@ class LexicalNLIVerifier:
|
|
| 91 |
}
|
| 92 |
|
| 93 |
support_markers = {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
"reduces",
|
| 95 |
"reduce",
|
| 96 |
"reducing",
|
|
@@ -106,10 +119,49 @@ class LexicalNLIVerifier:
|
|
| 106 |
"migliora",
|
| 107 |
"migliorato",
|
| 108 |
"miglioramento",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
}
|
| 110 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 111 |
def predict(self, premise: str, hypothesis: str) -> tuple[NLILabel, float]:
|
| 112 |
premise_lower = premise.lower()
|
|
|
|
| 113 |
premise_tokens = set(tokenize(premise))
|
| 114 |
hypothesis_tokens = set(tokenize(hypothesis))
|
| 115 |
overlap = len(premise_tokens & hypothesis_tokens) / max(len(hypothesis_tokens), 1)
|
|
@@ -121,8 +173,33 @@ class LexicalNLIVerifier:
|
|
| 121 |
|
| 122 |
has_contradiction = bool(premise_tokens & self.contradiction_markers)
|
| 123 |
wants_support = bool(hypothesis_tokens & self.support_markers)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 124 |
|
| 125 |
-
if has_contradiction and wants_support:
|
| 126 |
return "contradiction", min(0.95, 0.65 + overlap)
|
| 127 |
if overlap >= 0.35:
|
| 128 |
return "entailment", min(0.95, 0.55 + overlap / 2)
|
|
|
|
| 71 |
"""
|
| 72 |
|
| 73 |
contradiction_markers = {
|
| 74 |
+
"cannot",
|
| 75 |
"no",
|
| 76 |
"not",
|
| 77 |
"without",
|
| 78 |
"never",
|
| 79 |
+
"unless",
|
| 80 |
"nessun",
|
| 81 |
"nessuna",
|
| 82 |
"non",
|
| 83 |
"senza",
|
| 84 |
+
"salvo",
|
| 85 |
}
|
| 86 |
|
| 87 |
insufficient_markers = {
|
|
|
|
| 94 |
}
|
| 95 |
|
| 96 |
support_markers = {
|
| 97 |
+
"approval",
|
| 98 |
+
"approved",
|
| 99 |
+
"eligible",
|
| 100 |
+
"requires",
|
| 101 |
+
"receive",
|
| 102 |
+
"receives",
|
| 103 |
+
"reimbursed",
|
| 104 |
+
"reimbursement",
|
| 105 |
+
"must",
|
| 106 |
+
"may",
|
| 107 |
"reduces",
|
| 108 |
"reduce",
|
| 109 |
"reducing",
|
|
|
|
| 119 |
"migliora",
|
| 120 |
"migliorato",
|
| 121 |
"miglioramento",
|
| 122 |
+
"approvazione",
|
| 123 |
+
"diritto",
|
| 124 |
+
"rimborso",
|
| 125 |
+
"devono",
|
| 126 |
+
"possono",
|
| 127 |
}
|
| 128 |
|
| 129 |
+
number_values = {
|
| 130 |
+
"one": 1,
|
| 131 |
+
"two": 2,
|
| 132 |
+
"three": 3,
|
| 133 |
+
"four": 4,
|
| 134 |
+
"five": 5,
|
| 135 |
+
"six": 6,
|
| 136 |
+
"seven": 7,
|
| 137 |
+
"fourteen": 14,
|
| 138 |
+
"twenty-two": 22,
|
| 139 |
+
"thirty": 30,
|
| 140 |
+
"uno": 1,
|
| 141 |
+
"due": 2,
|
| 142 |
+
"tre": 3,
|
| 143 |
+
"quattro": 4,
|
| 144 |
+
"cinque": 5,
|
| 145 |
+
"sei": 6,
|
| 146 |
+
"sette": 7,
|
| 147 |
+
"quattordici": 14,
|
| 148 |
+
"ventidue": 22,
|
| 149 |
+
"trenta": 30,
|
| 150 |
+
}
|
| 151 |
+
|
| 152 |
+
def _numbers(self, tokens: set[str]) -> set[int]:
|
| 153 |
+
values: set[int] = set()
|
| 154 |
+
for token in tokens:
|
| 155 |
+
normalized = token.replace(",", "").replace(".", "")
|
| 156 |
+
if normalized.isdigit():
|
| 157 |
+
values.add(int(normalized))
|
| 158 |
+
if normalized in self.number_values:
|
| 159 |
+
values.add(self.number_values[normalized])
|
| 160 |
+
return values
|
| 161 |
+
|
| 162 |
def predict(self, premise: str, hypothesis: str) -> tuple[NLILabel, float]:
|
| 163 |
premise_lower = premise.lower()
|
| 164 |
+
hypothesis_lower = hypothesis.lower()
|
| 165 |
premise_tokens = set(tokenize(premise))
|
| 166 |
hypothesis_tokens = set(tokenize(hypothesis))
|
| 167 |
overlap = len(premise_tokens & hypothesis_tokens) / max(len(hypothesis_tokens), 1)
|
|
|
|
| 173 |
|
| 174 |
has_contradiction = bool(premise_tokens & self.contradiction_markers)
|
| 175 |
wants_support = bool(hypothesis_tokens & self.support_markers)
|
| 176 |
+
premise_numbers = self._numbers(premise_tokens)
|
| 177 |
+
hypothesis_numbers = self._numbers(hypothesis_tokens)
|
| 178 |
+
|
| 179 |
+
if premise_numbers and hypothesis_numbers and premise_numbers.isdisjoint(hypothesis_numbers) and overlap >= 0.25:
|
| 180 |
+
return "contradiction", min(0.92, 0.62 + overlap)
|
| 181 |
+
|
| 182 |
+
if any(marker in premise_lower for marker in {"not eligible", "cannot", "may not", "not in"}) and overlap >= 0.22:
|
| 183 |
+
if any(marker in hypothesis_lower for marker in {"eligible", "can ", "may ", "always"}):
|
| 184 |
+
return "contradiction", min(0.93, 0.68 + overlap)
|
| 185 |
+
|
| 186 |
+
if "not reimbursed" in premise_lower and overlap >= 0.22:
|
| 187 |
+
if any(marker in hypothesis_lower for marker in {"reimbursed", "reimbursement", "internet", "allowance", "expense"}):
|
| 188 |
+
return "contradiction", min(0.93, 0.68 + overlap)
|
| 189 |
+
|
| 190 |
+
if "without approval" in hypothesis_lower and any(marker in premise_lower for marker in {"requires", "approval", "approved", "approvazione"}):
|
| 191 |
+
return "contradiction", min(0.94, 0.68 + overlap)
|
| 192 |
+
|
| 193 |
+
if "non hanno diritto" in premise_lower and any(marker in hypothesis_lower for marker in {"hanno diritto", "sempre diritto"}):
|
| 194 |
+
return "contradiction", min(0.93, 0.68 + overlap)
|
| 195 |
+
|
| 196 |
+
if "non sono rimborsate" in premise_lower and any(marker in hypothesis_lower for marker in {"sono rimborsate", "rimborsate come"}):
|
| 197 |
+
return "contradiction", min(0.93, 0.68 + overlap)
|
| 198 |
+
|
| 199 |
+
if "non possono" in premise_lower and "possono" in hypothesis_lower:
|
| 200 |
+
return "contradiction", min(0.93, 0.68 + overlap)
|
| 201 |
|
| 202 |
+
if has_contradiction and wants_support and overlap >= 0.3:
|
| 203 |
return "contradiction", min(0.95, 0.65 + overlap)
|
| 204 |
if overlap >= 0.35:
|
| 205 |
return "entailment", min(0.95, 0.55 + overlap / 2)
|