SlouchyBuffalo commited on
Commit
5948255
·
verified ·
1 Parent(s): 4147556

Create app.py

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