CoolFace
Apppublic

Yuming123/Reference-checker

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
app.py140 linesDownload Raw Back to root
1# app.py2import gradio as gr3import re4import pandas as pd5from docx import Document6 7# Extract unique citation pairs (Name, Year) + full text from the thesis document8def extract_citations_from_docx(doc_path):9    document = Document(doc_path)10    full_text = []11 12    # Extract text from paragraphs13    for para in document.paragraphs:14        full_text.append(para.text)15 16    # Extract text from tables17    for table in document.tables:18        for row in table.rows:19            for cell in row.cells:20                # Avoid duplication21                if cell.text not in full_text:22                    full_text.append(cell.text)23    text = ' '.join(full_text)24 25    # Regular expressions for various citation formats (according to APA7)26    patterns = [27        r'\b([A-Z][a-z]+) et al\. \((\d{4})\)',  # Narrative citation, More than three authors: e.g., Munikar et al. (2019)28        r'\b([A-Z][a-z]+) \((\d{4})\)',           # Narrative citation, Single / Two Author Citation e.g., Park (2023), Li and Hu (2024)29        r'\(([A-Z][a-z]+) et al\., (\d{4})\)',    # Parenthetical citation, More than three authors:  e.g., (Liu et al., 2023)30        r'\(([A-Z][a-z]+) & ([A-Z][a-z]+), (\d{4})\)',  # Parenthetical citation, Two Authors Citation e.g., (Batrinca & Treleaven, 2015)31        r'\(([A-Z][a-z]+), (\d{4})\)',            #  Parenthetical citation, Single Author Citation: e.g., (Weber, 1987)32        r"\b\(([A-Z][a-z]+( et al.)?,\s\d{4};?\s?)+\)\b", # Multiple Citations, e.g., (Weber, 1987; Orlikowski & Iacono, 2001; Li et al., 2024)33        r"\b\([A-Z][a-z]+,\s\d{4}[a-z]?(,\s\d{4}[a-z]?)?\)\b" # Same Author Multiple Works e.g., (Smith, 2020a, 2020b)34    ]35 36    citations = set()37    for pattern in patterns:38        matches = re.findall(pattern, text)39        for match in matches:40            if len(match) == 2:41                citations.add((match[0], match[1]))42            elif len(match) > 2:43                if ';' in match[0]:44                    sub_matches = re.findall(r'([A-Z][a-z]+)[^,;]*?, (\d{4})', match[0])45                    for sub_match in sub_matches:46                        citations.add((sub_match[0], sub_match[1]))47                else:48                    citations.add((match[1], match[2]))49            elif ';' in match:50                sub_matches = re.findall(r'([A-Z][a-z]+)[^,;]*?, (\d{4})', match)51                for sub_match in sub_matches:52                    citations.add((sub_match[0], sub_match[1]))53 54    return citations, text55 56# Extract references from the reference list in the Excel file57def references_from_excel(excel_path):58    df = pd.read_excel(excel_path, header=None)59    references = [str(cell) for cell in df[0] if pd.notna(cell)]60    return references61 62# Extract references in the format of (Name, Year)63def extract_references_from_excel(excel_path):64    df = pd.read_excel(excel_path, header=None)65    references = []66 67    for cell in df[0][1:]:68        if pd.isna(cell):69            continue70        cell_text = str(cell)71        name_match = re.match(r'([A-Z][a-z]+)', cell_text)72        year_match = re.search(r'\((\d{4})\)', cell_text)73        if name_match and year_match:74            references.append((name_match.group(1), year_match.group(1)))75 76    return references77 78# Check if thesis citations are present in the reference list79def check_citations_in_references(citations, references):80    citations_not_in_references = []81    for name, year in citations:82        found = False83        for cell in references:84            if name in cell and year in cell:85                found = True86                break87        if not found:88            citations_not_in_references.append((name, year))89 90    return citations_not_in_references91 92# Check if references are present in the thesis text93def check_references_in_citations(references, text):94    references_not_in_text = []95 96    for name, year in references:97        same_bracket_pattern = fr'\({name}[^)]*?{year}[^)]*?\)'98        same_bracket_pattern2 = fr'\(([^\)]*{name}[^,;]*?,\s*{year}[^)]*)\)'99        name_followed_by_year_pattern = fr'\b{name}\b(?:[^\(\)]*?\(\s*{year}\s*\))'100 101        if not (re.search(same_bracket_pattern, text) or re.search(same_bracket_pattern2, text) or re.search(name_followed_by_year_pattern, text)):102            references_not_in_text.append((name, year))103 104    return references_not_in_text105 106# Gradio interface function107def analyze_files(doc_file, excel_file):108    citations, text = extract_citations_from_docx(doc_file.name)109    references_all = references_from_excel(excel_file.name)110    references = extract_references_from_excel(excel_file.name)111 112    citations_not_in_references = check_citations_in_references(citations, references_all)113    references_not_in_text = check_references_in_citations(references, text)114 115    result = ""116    if citations_not_in_references:117        result += "Citations in the thesis not found in the reference list:\n"118        result += '\n'.join([f"{name} ({year})" for name, year in citations_not_in_references]) + "\n"119    else:120        result += "All citations in the thesis were found in the reference list.\n"121 122    if references_not_in_text:123        result += "\nReferences in the list not found in the thesis:\n"124        result += '\n'.join([f"{name} ({year})" for name, year in references_not_in_text]) + "\n"125    else:126        result += "All references in the list were found in the thesis.\n"127 128    return result129 130# Gradio UI setup131iface = gr.Interface(132    fn=analyze_files,133    inputs=[gr.File(label="Upload .docx file"), gr.File(label="Upload .xlsx file")],134    outputs="text",135    title="Citation and Reference Checker",136    description="Please upload your thesis (without Reference list) as .docx file, and an .xlsx reference list to check for citation and reference consistency."137)138 139iface.launch(share=True)140