Spaces:
Paused
Paused
Download src/scifact_loader.py from Param0304/truthlens-ml-api: direct link, hf CLI and curl.
- Browser
- Download file 6.16 kB
-
https://huggingface.co/spaces/Param0304/truthlens-ml-api/resolve/main/src/scifact_loader.py
- Command line
-
hf download hf://spaces/Param0304/truthlens-ml-api/src/scifact_loader.py
-
curl -L -o scifact_loader.py https://huggingface.co/spaces/Param0304/truthlens-ml-api/resolve/main/src/scifact_loader.py
6.16 kB
| """ | |
| scifact_loader.py - SciFact Dataset Loader and Evidence Extractor for TruthLens AI. | |
| This module handles loading and parsing the SciFact scientific fact-checking | |
| benchmark (Wadden et al., EMNLP 2020). It loads the research paper corpus and | |
| claim annotations, reconstructing grounded (claim, evidence_text, label) triples. | |
| """ | |
| import json | |
| import os | |
| from typing import Dict, List, Any, Optional, Tuple | |
| import pandas as pd | |
| import numpy as np | |
| def load_scifact_corpus(corpus_path: str) -> Dict[int, Dict[str, Any]]: | |
| """ | |
| Loads the SciFact corpus of scientific papers from corpus.jsonl. | |
| Returns: | |
| Dict mapping doc_id (int) to document dictionary with: | |
| {'doc_id': int, 'title': str, 'abstract': List[str], 'structured': bool} | |
| """ | |
| corpus = {} | |
| if not os.path.exists(corpus_path): | |
| raise FileNotFoundError(f"SciFact corpus not found at: {corpus_path}") | |
| with open(corpus_path, "r", encoding="utf-8") as f: | |
| for line in f: | |
| line_str = line.strip() | |
| if line_str: | |
| doc = json.loads(line_str) | |
| corpus[int(doc["doc_id"])] = doc | |
| return corpus | |
| def load_scifact_claims(claims_path: str) -> List[Dict[str, Any]]: | |
| """ | |
| Loads SciFact claim annotations from a JSONL file. | |
| Returns: | |
| List of claim dictionaries. | |
| """ | |
| if not os.path.exists(claims_path): | |
| raise FileNotFoundError(f"SciFact claims file not found: {claims_path}") | |
| claims = [] | |
| with open(claims_path, "r", encoding="utf-8") as f: | |
| for line in f: | |
| line_str = line.strip() | |
| if line_str: | |
| claims.append(json.loads(line_str)) | |
| return claims | |
| def reconstruct_scifact_triples( | |
| claims: List[Dict[str, Any]], | |
| corpus: Dict[int, Dict[str, Any]], | |
| include_nei: bool = True | |
| ) -> pd.DataFrame: | |
| """ | |
| Reconstructs explicit (claim, evidence_text, label) triples from SciFact annotations. | |
| For claims with rationales: | |
| Extracts the exact sentence text from the cited document's abstract. | |
| For claims without evidence (empty evidence dict): | |
| Label is set to 'NOT_ENOUGH_INFO' with empty evidence. | |
| Returns: | |
| DataFrame with columns: | |
| ['claim_id', 'claim', 'doc_id', 'doc_title', 'sentence_indices', 'evidence_text', 'label'] | |
| """ | |
| rows = [] | |
| for claim_obj in claims: | |
| claim_id = claim_obj["id"] | |
| claim_text = claim_obj["claim"] | |
| evidence_dict = claim_obj.get("evidence", {}) | |
| if not evidence_dict: | |
| if include_nei: | |
| rows.append({ | |
| "claim_id": claim_id, | |
| "claim": claim_text, | |
| "doc_id": None, | |
| "doc_title": None, | |
| "sentence_indices": [], | |
| "evidence_text": "", | |
| "label": "NOT_ENOUGH_INFO", | |
| }) | |
| continue | |
| for doc_id_str, rationale_list in evidence_dict.items(): | |
| doc_id = int(doc_id_str) | |
| doc = corpus.get(doc_id) | |
| doc_title = doc["title"] if doc else "" | |
| abstract_sents = doc["abstract"] if doc else [] | |
| for item in rationale_list: | |
| label = item.get("label", "UNKNOWN") | |
| sentence_indices = item.get("sentences", []) | |
| # Extract sentence text | |
| ev_sentences = [ | |
| abstract_sents[idx] | |
| for idx in sentence_indices | |
| if idx < len(abstract_sents) | |
| ] | |
| evidence_text = " ".join(ev_sentences) | |
| rows.append({ | |
| "claim_id": claim_id, | |
| "claim": claim_text, | |
| "doc_id": doc_id, | |
| "doc_title": doc_title, | |
| "sentence_indices": sentence_indices, | |
| "evidence_text": evidence_text, | |
| "label": label, | |
| }) | |
| return pd.DataFrame(rows) | |
| def get_scifact_statistics( | |
| claims: List[Dict[str, Any]], | |
| corpus: Optional[Dict[int, Dict[str, Any]]] = None, | |
| split_name: str = "split" | |
| ) -> Dict[str, Any]: | |
| """ | |
| Computes summary statistics for a SciFact split. | |
| """ | |
| total_claims = len(claims) | |
| if total_claims == 0: | |
| return {"total_claims": 0} | |
| df_claims = pd.DataFrame(claims) | |
| claim_words = df_claims["claim"].astype(str).apply(lambda s: len(s.split())) | |
| has_evidence_list = [] | |
| evidence_item_labels = [] | |
| cited_docs = set() | |
| for c in claims: | |
| ev = c.get("evidence", {}) | |
| has_ev = bool(ev) | |
| has_evidence_list.append(has_ev) | |
| if "cited_doc_ids" in c: | |
| cited_docs.update(c["cited_doc_ids"]) | |
| if ev: | |
| for doc_id, ev_list in ev.items(): | |
| for item in ev_list: | |
| evidence_item_labels.append(item.get("label", "UNKNOWN")) | |
| has_ev_series = pd.Series(has_evidence_list) | |
| label_series = pd.Series(evidence_item_labels) | |
| stats = { | |
| "split": split_name, | |
| "total_claims": total_claims, | |
| "claims_with_evidence": int(has_ev_series.sum()), | |
| "claims_without_evidence_nei": int((~has_ev_series).sum()), | |
| "evidence_label_counts": label_series.value_counts().to_dict() if len(label_series) > 0 else {}, | |
| "unique_cited_docs": len(cited_docs), | |
| "claim_word_length": { | |
| "min": int(claim_words.min()), | |
| "max": int(claim_words.max()), | |
| "mean": float(round(claim_words.mean(), 2)), | |
| "median": float(round(claim_words.median(), 2)), | |
| }, | |
| } | |
| if corpus is not None: | |
| stats["corpus_total_docs"] = len(corpus) | |
| abstract_lens = [len(d.get("abstract", [])) for d in corpus.values()] | |
| stats["corpus_total_sentences"] = sum(abstract_lens) | |
| stats["mean_abstract_sentences"] = float(round(np.mean(abstract_lens), 2)) | |
| return stats | |