SlouchyBuffalo commited on
Commit
a17c43e
·
verified ·
1 Parent(s): 6a2e33b

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +236 -0
app.py ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import requests
3
+ from huggingface_hub import InferenceClient
4
+ import spaces
5
+ from citation_validator import validate_citation, format_authors
6
+
7
+ # Create icons on startup
8
+ try:
9
+ import subprocess
10
+ subprocess.run(['python', 'create_icons.py'], check=True)
11
+ print("Icons created successfully")
12
+ except Exception as e:
13
+ print(f"Could not create icons: {e}")
14
+
15
+ # Initialize Llama 4 client
16
+ model_id = "meta-llama/Llama-4-Scout-17B-16E-Instruct"
17
+ client = InferenceClient(model=model_id)
18
+
19
+ def search_crossref(query):
20
+ """Search Crossref API for publication metadata"""
21
+ try:
22
+ # Check if input is a DOI
23
+ if query.startswith('10.'):
24
+ url = f"https://api.crossref.org/works/{query}"
25
+ else:
26
+ # Search by title/author
27
+ url = f"https://api.crossref.org/works?query={query}&rows=1"
28
+
29
+ response = requests.get(url, headers={'User-Agent': 'CitationTool/1.0 (mailto:your-email@example.com)'})
30
+
31
+ if response.status_code == 200:
32
+ data = response.json()
33
+ if 'message' in data:
34
+ if 'items' in data['message']:
35
+ return data['message']['items'][0] if data['message']['items'] else None
36
+ else:
37
+ return data['message']
38
+ return None
39
+ except Exception as e:
40
+ print(f"Crossref API error: {e}")
41
+ return None
42
+
43
+ def generate_intext_citation(crossref_data, citation_style, page_numbers=""):
44
+ """Generate in-text citation from Crossref data"""
45
+ if not crossref_data:
46
+ return None
47
+
48
+ work = crossref_data
49
+ authors = work.get('author', [])
50
+ year = work.get('published-print', {}).get('date-parts', [[None]])[0][0] or \
51
+ work.get('published-online', {}).get('date-parts', [[None]])[0][0]
52
+
53
+ if citation_style == "APA7":
54
+ if len(authors) == 0:
55
+ return f"(Unknown Author, {year or 'n.d.'}{', p. ' + page_numbers if page_numbers else ''})"
56
+ elif len(authors) == 1:
57
+ author_name = authors[0].get('family', 'Unknown')
58
+ return f"({author_name}, {year or 'n.d.'}{', p. ' + page_numbers if page_numbers else ''})"
59
+ elif len(authors) == 2:
60
+ author1 = authors[0].get('family', 'Unknown')
61
+ author2 = authors[1].get('family', 'Unknown')
62
+ return f"({author1} & {author2}, {year or 'n.d.'}{', p. ' + page_numbers if page_numbers else ''})"
63
+ else:
64
+ author_name = authors[0].get('family', 'Unknown')
65
+ return f"({author_name} et al., {year or 'n.d.'}{', p. ' + page_numbers if page_numbers else ''})"
66
+
67
+ elif citation_style == "Chicago":
68
+ if len(authors) == 0:
69
+ title = work.get('title', ['Unknown Title'])[0]
70
+ short_title = title.split(':')[0][:30] + "..." if len(title) > 30 else title
71
+ return f"({short_title}, {year or 'n.d.'}{', ' + page_numbers if page_numbers else ''})"
72
+ elif len(authors) == 1:
73
+ author_name = authors[0].get('family', 'Unknown')
74
+ return f"({author_name}, {year or 'n.d.'}{', ' + page_numbers if page_numbers else ''})"
75
+ else:
76
+ author_name = authors[0].get('family', 'Unknown')
77
+ return f"({author_name} et al., {year or 'n.d.'}{', ' + page_numbers if page_numbers else ''})"
78
+
79
+ elif citation_style == "MLA":
80
+ if len(authors) == 0:
81
+ return f"(Unknown Author{' ' + page_numbers if page_numbers else ''})"
82
+ elif len(authors) == 1:
83
+ author_name = authors[0].get('family', 'Unknown')
84
+ return f"({author_name}{' ' + page_numbers if page_numbers else ''})"
85
+ elif len(authors) == 2:
86
+ author1 = authors[0].get('family', 'Unknown')
87
+ author2 = authors[1].get('family', 'Unknown')
88
+ return f"({author1} and {author2}{' ' + page_numbers if page_numbers else ''})"
89
+ else:
90
+ author_name = authors[0].get('family', 'Unknown')
91
+ return f"({author_name} et al.{' ' + page_numbers if page_numbers else ''})"
92
+
93
+ @spaces.GPU
94
+ def generate_citation(input_text, citation_style, citation_type, page_numbers=""):
95
+ if not input_text.strip():
96
+ return "Please enter some text to generate a citation."
97
+
98
+ # First, try to get structured data from Crossref
99
+ crossref_data = search_crossref(input_text)
100
+
101
+ # Generate in-text citation if requested
102
+ if citation_type == "In-Text Citation" and crossref_data:
103
+ intext = generate_intext_citation(crossref_data, citation_style, page_numbers)
104
+ if intext:
105
+ return intext + "\n✅ In-text citation generated"
106
+
107
+ # Prepare the prompt for Llama 4 for full citations
108
+ if crossref_data:
109
+ # Extract and format key information from Crossref
110
+ work = crossref_data
111
+ authors = format_authors(work.get('author', []))
112
+ title = work.get('title', [''])[0] if work.get('title') else ''
113
+ journal = work.get('container-title', [''])[0] if work.get('container-title') else ''
114
+ year = work.get('published-print', {}).get('date-parts', [[None]])[0][0] or \
115
+ work.get('published-online', {}).get('date-parts', [[None]])[0][0]
116
+ doi = work.get('DOI', '')
117
+
118
+ if citation_type == "In-Text Citation":
119
+ if citation_style == "MLA":
120
+ prompt = f"""Create an MLA in-text citation using this data:
121
+ Authors: {authors}
122
+ Page numbers: {page_numbers}
123
+
124
+ Generate only the in-text citation (e.g., (Author page) or (Author and Author page))."""
125
+ else:
126
+ prompt = f"""Create a {citation_style} in-text citation using this data:
127
+ Authors: {authors}
128
+ Year: {year}
129
+ Page numbers: {page_numbers}
130
+
131
+ Generate only the in-text citation (e.g., (Author, Year) or (Author, Year, p. X))."""
132
+ else:
133
+ prompt = f"""Create a perfect {citation_style} full reference citation using this verified publication data:
134
+ Authors: {authors}
135
+ Title: {title}
136
+ Journal/Publication: {journal}
137
+ Year: {year}
138
+ DOI: {doi}
139
+
140
+ Format this as a complete, properly formatted {citation_style} reference citation following all style guidelines exactly."""
141
+ else:
142
+ if citation_type == "In-Text Citation":
143
+ prompt = f"""Create a {citation_style} in-text citation from this information: {input_text}
144
+ Page numbers: {page_numbers}
145
+
146
+ Generate only the in-text citation format. Follow {citation_style} guidelines exactly."""
147
+ else:
148
+ prompt = f"""Create a {citation_style} full reference citation from this information: {input_text}
149
+
150
+ Follow {citation_style} formatting guidelines exactly. If information is missing, use appropriate placeholders like [Author] or [Year]."""
151
+
152
+ try:
153
+ # Use conversational approach
154
+ messages = [{"role": "user", "content": prompt}]
155
+ response = client.chat_completion(
156
+ messages=messages,
157
+ max_tokens=500,
158
+ temperature=0.1
159
+ )
160
+
161
+ # Extract the citation from the response
162
+ citation = response.choices[0].message.content
163
+
164
+ # Validate the generated citation
165
+ errors = validate_citation(citation, citation_style)
166
+
167
+ if errors:
168
+ warning = "\n⚠️ Validation warnings:\n" + "\n".join(f"• {error}" for error in errors)
169
+ return citation + warning
170
+ else:
171
+ return citation + "\n✅ Citation validated"
172
+
173
+ except Exception as e:
174
+ return f"Error generating citation: {str(e)}"
175
+
176
+ # Create Gradio interface
177
+ with gr.Blocks(title="Citation Tool PWA") as app:
178
+ gr.Markdown("# 📚 Citation Generation Tool")
179
+ gr.Markdown("*AI-powered citations for APA7, Chicago, and MLA styles*")
180
+
181
+ with gr.Row():
182
+ with gr.Column():
183
+ input_text = gr.Textbox(
184
+ label="Enter DOI, title, or citation information",
185
+ placeholder="e.g., 10.1038/nature12373 or 'The Structure of Scientific Revolutions'",
186
+ lines=3
187
+ )
188
+ with gr.Row():
189
+ citation_style = gr.Dropdown(
190
+ choices=["APA7", "Chicago", "MLA"],
191
+ value="APA7",
192
+ label="Citation Style"
193
+ )
194
+ citation_type = gr.Dropdown(
195
+ choices=["Full Citation", "In-Text Citation"],
196
+ value="Full Citation",
197
+ label="Citation Type"
198
+ )
199
+ page_numbers = gr.Textbox(
200
+ label="Page numbers (for in-text citations)",
201
+ placeholder="e.g., 15-20 or 42",
202
+ visible=False
203
+ )
204
+ generate_btn = gr.Button("Generate Citation", variant="primary")
205
+
206
+ with gr.Row():
207
+ output = gr.Textbox(
208
+ label="Generated Citation",
209
+ lines=5,
210
+ interactive=False
211
+ )
212
+
213
+ # Example section
214
+ gr.Markdown("### Examples:")
215
+ gr.Markdown("- **DOI**: `10.1038/nature12373`")
216
+ gr.Markdown("- **Title**: `The Structure of Scientific Revolutions`")
217
+ gr.Markdown("- **Author + Title**: `Kuhn Scientific Revolutions`")
218
+
219
+ # Show/hide page numbers based on citation type
220
+ def toggle_page_numbers(citation_type):
221
+ return gr.update(visible=(citation_type == "In-Text Citation"))
222
+
223
+ citation_type.change(
224
+ toggle_page_numbers,
225
+ inputs=[citation_type],
226
+ outputs=[page_numbers]
227
+ )
228
+
229
+ generate_btn.click(
230
+ generate_citation,
231
+ inputs=[input_text, citation_style, citation_type, page_numbers],
232
+ outputs=output
233
+ )
234
+
235
+ if __name__ == "__main__":
236
+ app.launch()