Spaces:
Runtime error
Runtime error
| import gradio as gr | |
| import requests | |
| from huggingface_hub import InferenceClient | |
| import spaces | |
| from citation_validator import validate_citation, format_authors | |
| # Create icons on startup | |
| try: | |
| import subprocess | |
| subprocess.run(['python', 'create_icons.py'], check=True) | |
| print("Icons created successfully") | |
| except Exception as e: | |
| print(f"Could not create icons: {e}") | |
| # Initialize Llama 4 client with Cerebras provider | |
| model_id = "meta-llama/Llama-4-Scout-17B-16E-Instruct" | |
| # Use Cerebras as the inference provider | |
| client = InferenceClient(model=model_id, provider="cerebras") | |
| def search_crossref(query): | |
| """Search Crossref API for publication metadata""" | |
| try: | |
| # Check if input is a DOI | |
| if query.startswith('10.'): | |
| url = f"https://api.crossref.org/works/{query}" | |
| else: | |
| # Search by title/author | |
| url = f"https://api.crossref.org/works?query={query}&rows=1" | |
| response = requests.get(url, headers={'User-Agent': 'CitationTool/1.0 (mailto:your-email@example.com)'}) | |
| if response.status_code == 200: | |
| data = response.json() | |
| if 'message' in data: | |
| if 'items' in data['message']: | |
| return data['message']['items'][0] if data['message']['items'] else None | |
| else: | |
| return data['message'] | |
| return None | |
| except Exception as e: | |
| print(f"Crossref API error: {e}") | |
| return None | |
| def generate_intext_citation(crossref_data, citation_style, page_numbers=""): | |
| """Generate in-text citation from Crossref data""" | |
| if not crossref_data: | |
| return None | |
| work = crossref_data | |
| authors = work.get('author', []) | |
| year = work.get('published-print', {}).get('date-parts', [[None]])[0][0] or \ | |
| work.get('published-online', {}).get('date-parts', [[None]])[0][0] | |
| if citation_style == "APA7": | |
| if len(authors) == 0: | |
| return f"(Unknown Author, {year or 'n.d.'}{', p. ' + page_numbers if page_numbers else ''})" | |
| elif len(authors) == 1: | |
| author_name = authors[0].get('family', 'Unknown') | |
| return f"({author_name}, {year or 'n.d.'}{', p. ' + page_numbers if page_numbers else ''})" | |
| elif len(authors) == 2: | |
| author1 = authors[0].get('family', 'Unknown') | |
| author2 = authors[1].get('family', 'Unknown') | |
| return f"({author1} & {author2}, {year or 'n.d.'}{', p. ' + page_numbers if page_numbers else ''})" | |
| else: | |
| author_name = authors[0].get('family', 'Unknown') | |
| return f"({author_name} et al., {year or 'n.d.'}{', p. ' + page_numbers if page_numbers else ''})" | |
| elif citation_style == "Chicago": | |
| if len(authors) == 0: | |
| title = work.get('title', ['Unknown Title'])[0] | |
| short_title = title.split(':')[0][:30] + "..." if len(title) > 30 else title | |
| return f"({short_title}, {year or 'n.d.'}{', ' + page_numbers if page_numbers else ''})" | |
| elif len(authors) == 1: | |
| author_name = authors[0].get('family', 'Unknown') | |
| return f"({author_name}, {year or 'n.d.'}{', ' + page_numbers if page_numbers else ''})" | |
| else: | |
| author_name = authors[0].get('family', 'Unknown') | |
| return f"({author_name} et al., {year or 'n.d.'}{', ' + page_numbers if page_numbers else ''})" | |
| elif citation_style == "MLA": | |
| if len(authors) == 0: | |
| return f"(Unknown Author{' ' + page_numbers if page_numbers else ''})" | |
| elif len(authors) == 1: | |
| author_name = authors[0].get('family', 'Unknown') | |
| return f"({author_name}{' ' + page_numbers if page_numbers else ''})" | |
| elif len(authors) == 2: | |
| author1 = authors[0].get('family', 'Unknown') | |
| author2 = authors[1].get('family', 'Unknown') | |
| return f"({author1} and {author2}{' ' + page_numbers if page_numbers else ''})" | |
| else: | |
| author_name = authors[0].get('family', 'Unknown') | |
| return f"({author_name} et al.{' ' + page_numbers if page_numbers else ''})" | |
| def generate_citation(input_text, citation_style, citation_type, page_numbers=""): | |
| if not input_text.strip(): | |
| return "Please enter some text to generate a citation." | |
| # First, try to get structured data from Crossref | |
| crossref_data = search_crossref(input_text) | |
| # Generate in-text citation if requested | |
| if citation_type == "In-Text Citation" and crossref_data: | |
| intext = generate_intext_citation(crossref_data, citation_style, page_numbers) | |
| if intext: | |
| return intext + "\n✅ In-text citation generated" | |
| # Prepare the prompt for Llama 4 for full citations | |
| if crossref_data: | |
| # Extract and format key information from Crossref | |
| work = crossref_data | |
| authors = format_authors(work.get('author', [])) | |
| title = work.get('title', [''])[0] if work.get('title') else '' | |
| journal = work.get('container-title', [''])[0] if work.get('container-title') else '' | |
| year = work.get('published-print', {}).get('date-parts', [[None]])[0][0] or \ | |
| work.get('published-online', {}).get('date-parts', [[None]])[0][0] | |
| doi = work.get('DOI', '') | |
| if citation_type == "In-Text Citation": | |
| if citation_style == "MLA": | |
| prompt = f"""Create an MLA in-text citation using this data: | |
| Authors: {authors} | |
| Page numbers: {page_numbers} | |
| Generate only the in-text citation (e.g., (Author page) or (Author and Author page)).""" | |
| else: | |
| prompt = f"""Create a {citation_style} in-text citation using this data: | |
| Authors: {authors} | |
| Year: {year} | |
| Page numbers: {page_numbers} | |
| Generate only the in-text citation (e.g., (Author, Year) or (Author, Year, p. X)).""" | |
| else: | |
| prompt = f"""Create a perfect {citation_style} full reference citation using this verified publication data: | |
| Authors: {authors} | |
| Title: {title} | |
| Journal/Publication: {journal} | |
| Year: {year} | |
| DOI: {doi} | |
| Format this as a complete, properly formatted {citation_style} reference citation following all style guidelines exactly.""" | |
| else: | |
| if citation_type == "In-Text Citation": | |
| prompt = f"""Create a {citation_style} in-text citation from this information: {input_text} | |
| Page numbers: {page_numbers} | |
| Generate only the in-text citation format. Follow {citation_style} guidelines exactly.""" | |
| else: | |
| prompt = f"""Create a {citation_style} full reference citation from this information: {input_text} | |
| Follow {citation_style} formatting guidelines exactly. If information is missing, use appropriate placeholders like [Author] or [Year].""" | |
| try: | |
| # Use conversational approach with Cerebras | |
| messages = [{"role": "user", "content": prompt}] | |
| response = client.chat_completion( | |
| messages=messages, | |
| max_tokens=500, | |
| temperature=0.1 | |
| ) | |
| # Extract the citation from the response | |
| citation = response.choices[0].message.content | |
| # Validate the generated citation | |
| errors = validate_citation(citation, citation_style) | |
| if errors: | |
| warning = "\n⚠️ Validation warnings:\n" + "\n".join(f"• {error}" for error in errors) | |
| return citation + warning | |
| else: | |
| return citation + "\n✅ Citation validated" | |
| except Exception as e: | |
| return f"Error generating citation: {str(e)}" | |
| # Create Gradio interface | |
| with gr.Blocks(title="Citation Tool PWA") as app: | |
| gr.Markdown("# 📚 Citation Generation Tool") | |
| gr.Markdown("*AI-powered citations for APA7, Chicago, and MLA styles*") | |
| with gr.Row(): | |
| with gr.Column(): | |
| input_text = gr.Textbox( | |
| label="Enter DOI, title, or citation information", | |
| placeholder="e.g., 10.1038/nature12373 or 'The Structure of Scientific Revolutions'", | |
| lines=3 | |
| ) | |
| with gr.Row(): | |
| citation_style = gr.Dropdown( | |
| choices=["APA7", "Chicago", "MLA"], | |
| value="APA7", | |
| label="Citation Style" | |
| ) | |
| citation_type = gr.Dropdown( | |
| choices=["Full Citation", "In-Text Citation"], | |
| value="Full Citation", | |
| label="Citation Type" | |
| ) | |
| page_numbers = gr.Textbox( | |
| label="Page numbers (for in-text citations)", | |
| placeholder="e.g., 15-20 or 42", | |
| visible=False | |
| ) | |
| generate_btn = gr.Button("Generate Citation", variant="primary") | |
| with gr.Row(): | |
| output = gr.Textbox( | |
| label="Generated Citation", | |
| lines=5, | |
| interactive=False | |
| ) | |
| # Example section | |
| gr.Markdown("### Examples:") | |
| gr.Markdown("- **DOI**: `10.1038/nature12373`") | |
| gr.Markdown("- **Title**: `The Structure of Scientific Revolutions`") | |
| gr.Markdown("- **Author + Title**: `Kuhn Scientific Revolutions`") | |
| # Show/hide page numbers based on citation type | |
| def toggle_page_numbers(citation_type): | |
| return gr.update(visible=(citation_type == "In-Text Citation")) | |
| citation_type.change( | |
| toggle_page_numbers, | |
| inputs=[citation_type], | |
| outputs=[page_numbers] | |
| ) | |
| generate_btn.click( | |
| generate_citation, | |
| inputs=[input_text, citation_style, citation_type, page_numbers], | |
| outputs=output | |
| ) | |
| if __name__ == "__main__": | |
| app.launch() |