Spaces:
Running
Running
File size: 12,183 Bytes
9e7cbd8 95abc0b 9e7cbd8 64cd544 f43467c 64cd544 9e7cbd8 f43467c 9e7cbd8 629886b 3c15d19 9e7cbd8 95abc0b 9e7cbd8 95abc0b 9e7cbd8 c3e4c21 9e7cbd8 f43467c 9e7cbd8 952523e 9e7cbd8 f43467c 9e7cbd8 f43467c 9e7cbd8 f43467c 9e7cbd8 a165e08 9e7cbd8 f43467c 9e7cbd8 f43467c 9e7cbd8 a165e08 9e7cbd8 f43467c 9e7cbd8 95abc0b 9e7cbd8 c3e4c21 9e7cbd8 c3e4c21 9e7cbd8 c3e4c21 9e7cbd8 6d2b0a3 95abc0b 9e7cbd8 24052a1 95abc0b 9e7cbd8 95abc0b 9e7cbd8 95abc0b 9e7cbd8 6d2b0a3 9e7cbd8 6d2b0a3 9e7cbd8 1077963 5192410 9e7cbd8 1077963 9e7cbd8 1077963 5192410 95abc0b 9e7cbd8 1077963 64cd544 9e7cbd8 95abc0b 1077963 9e7cbd8 a95697b 9e7cbd8 95abc0b 9e7cbd8 a95697b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 |
import json
import os
import tempfile
from typing import List, Dict, Any
import fitz # PyMuPDF
import gradio as gr
from openai import OpenAI
# Load API key from environment variable
OPENROUTER_API_KEY = os.getenv("OPENROUTER_API_KEY")
def load_pitfalls() -> List[Dict[str, Any]]:
"""Load pitfalls from the JSON file."""
try:
with open("pitfalls.json", "r") as f:
data = json.load(f)
return data.get("pitfalls", [])
except FileNotFoundError:
gr.Warning("pitfalls.json file not found!")
return []
except json.JSONDecodeError:
gr.Warning("Invalid JSON in pitfalls.json file!")
return []
def extract_text_from_pdf(pdf_file) -> str:
"""Extract text content from a PDF file."""
try:
pdf_path = pdf_file.name
doc = fitz.open(pdf_path)
text_content = ""
for page_num in range(len(doc)):
page = doc[page_num]
text_content += f"\n--- Page {page_num + 1} ---\n"
text_content += page.get_text()
doc.close()
return text_content
except Exception as e:
raise gr.Error(f"Error extracting text from {pdf_file.name}: {str(e)}")
def format_paper_text(paper_text: str) -> Dict[str, Any]:
"""First stage: Format the paper text to make it more readable and suitable for analysis."""
# Check if API key is available
if not OPENROUTER_API_KEY:
return {
"formatted_text": None,
"success": False,
"error": "OpenRouter API key not found. Please set the OPENROUTER_API_KEY environment variable.",
}
# Initialize OpenAI client with OpenRouter
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=OPENROUTER_API_KEY,
)
format_prompt = f"""You are an expert academic text processor. Your task is to clean and format the following research paper text to make it more readable and suitable for detailed analysis.
Please:
1. Remove excessive whitespace and formatting artifacts
2. Organize the text into clear sections (Abstract, Introduction, Methods, Results, Discussion, Conclusion, References, Appendix)
3. Preserve all important content including figures, tables, and equations
4. Make the text flow better while maintaining academic integrity
5. Ensure all evaluation-related content is clearly identifiable
6. Keep the text under 8000 characters while preserving key information
Original paper text:
{paper_text}
Please provide the cleaned and formatted text:"""
try:
completion = client.chat.completions.create(
extra_headers={
"HTTP-Referer": "https://github.com/paper-eval-checker",
"X-Title": "Paper Evaluation Pitfall Checker",
},
model="x-ai/grok-4-fast:free",
messages=[{"role": "user", "content": format_prompt}],
temperature=0.1, # Very low temperature for consistent formatting
max_tokens=3000,
)
return {
"formatted_text": completion.choices[0].message.content,
"success": True,
"error": None,
}
except Exception as e:
return {"formatted_text": None, "success": False, "error": str(e)}
def analyze_paper_for_pitfalls(
formatted_text: str, pitfalls: List[Dict[str, Any]]
) -> Dict[str, Any]:
"""Second stage: Use OpenRouter API with Grok model to analyze the formatted paper for potential pitfalls."""
# Check if API key is available
if not OPENROUTER_API_KEY:
return {
"analysis": None,
"success": False,
"error": "OpenRouter API key not found. Please set the OPENROUTER_API_KEY environment variable.",
}
# Initialize OpenAI client with OpenRouter
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=OPENROUTER_API_KEY,
)
# Create the prompt for pitfall analysis
pitfalls_description = "\n\n".join(
[
f"**{pitfall['name']}** {pitfall['emoji']}\n"
f"Category: {pitfall['category']}\n"
f"Description: {pitfall['description']}\n"
f"Subjective/Objective: {pitfall['subjective_objective']}\n"
f"Actors Most Affected: {', '.join(pitfall['actors_most_affected'])}\n"
f"Evaluation Use: {pitfall['evaluation_use']}\n"
f"Modalities: {', '.join(pitfall['modalities'])}"
for pitfall in pitfalls
]
)
analysis_prompt = f"""You are an expert research paper reviewer specializing in identifying evaluation pitfalls in academic papers.
Your task is to analyze the provided formatted research paper text and identify any potential pitfalls from the following list:
{pitfalls_description}
Please analyze the paper carefully and provide:
1. A list of potential pitfalls found (if any)
2. For each pitfall found, provide:
- The pitfall name (and emoji)
- Specific evidence from the paper that suggests this pitfall
- The section/page where this evidence appears
- Suggestions for improvement
3. Be concise, and use markdown formatting.
4. If you find evidence of a pitfall, make sure to look at ALL of the paper to see if it is mitigated elsewhere -- make sure to check the appendix of the paper as well.
The output format:
# Overall
 (for low use green, for medium use yellow, for high use red)
 (either write 'subjective', 'objective', or include two images in case both are present in the paper)
[One sentence summary of evaluation use]
# Pitfall
## Evidence
"specific evidence from the paper"
If no pitfalls are found, please state that clearly.
Formatted paper text to analyze:
{formatted_text}
Please provide your analysis in a structured format."""
try:
completion = client.chat.completions.create(
extra_headers={
"HTTP-Referer": "https://github.com/paper-eval-checker",
"X-Title": "Paper Evaluation Pitfall Checker",
},
model="x-ai/grok-4-fast:free",
messages=[{"role": "user", "content": analysis_prompt}],
temperature=0.3, # Lower temperature for more consistent analysis
max_tokens=2000,
)
return {
"analysis": completion.choices[0].message.content,
"success": True,
"error": None,
}
except Exception as e:
return {"analysis": None, "success": False, "error": str(e)}
def process_paper(pdf_file, progress=gr.Progress()):
"""Main function to process a research paper for pitfall detection using two-stage approach."""
if not pdf_file:
return gr.Markdown(
"β οΈ No PDF file uploaded. Please upload a research paper PDF."
)
if not OPENROUTER_API_KEY:
return gr.Markdown(
"β οΈ OpenRouter API key not found. Please set the OPENROUTER_API_KEY environment variable."
)
try:
# Step 1: Load pitfalls
progress(0.1, desc="Loading pitfalls definitions...")
pitfalls = load_pitfalls()
if not pitfalls:
return gr.Markdown(
"β οΈ No pitfalls definitions found. Please check pitfalls.json file."
)
# Step 2: Extract text from PDF
progress(0.2, desc="Extracting text from PDF...")
paper_text = extract_text_from_pdf(pdf_file)
if not paper_text.strip():
return gr.Markdown(
"β οΈ No text content found in the PDF. Please check if the PDF contains readable text."
)
# Step 3: Format paper text (First AI call)
progress(0.3, desc="Formatting paper text for analysis...")
format_result = format_paper_text(paper_text)
if not format_result["success"]:
return gr.Markdown(
f"β Error during text formatting: {format_result['error']}"
)
# Step 4: Analyze for pitfalls (Second AI call)
progress(0.7, desc="Analyzing paper for potential pitfalls...")
analysis_result = analyze_paper_for_pitfalls(
format_result["formatted_text"], pitfalls
)
if not analysis_result["success"]:
return gr.Markdown(f"β Error during analysis: {analysis_result['error']}")
# Step 5: Format final results
progress(0.9, desc="Preparing final report...")
analysis_text = analysis_result["analysis"]
# Create a formatted markdown report
report = f"""# Research Paper Pitfall Analysis Report
## Analysis Results
{analysis_text}
---
*Analysis completed using OpenRouter API with Grok model (two-stage processing)*
"""
progress(1.0, desc="Analysis complete!")
return gr.Markdown(report)
except Exception as e:
return gr.Markdown(f"β An error occurred: {str(e)}")
# Define the Gradio interface
with gr.Blocks(title="Research Paper Pitfall Checker") as demo:
gr.HTML(
"""<h1 style='text-align: center;'>π Research Paper Pitfall Checker</h1>
<center><i>Identify potential evaluation pitfalls in academic research papers</i></center>"""
)
gr.HTML(
"""
<div style="max-width: 800px; margin: 0 auto; padding: 20px;">
<h3>How it works:</h3>
<ol>
<li><strong>Upload a PDF</strong> of your research paper</li>
<li><strong>Click "Analyze Paper"</strong> to scan for potential pitfalls</li>
<li><strong>Review the analysis</strong> to identify areas for improvement</li>
</ol>
<h3>Supported Pitfalls:</h3>
<ul>
<li>π The Lock-In Effect</li>
<li>ππ Apples-to-Oranges Comparisons</li>
<li>π§ Contamination Leak</li>
<li>π€β Unvalidated Automation</li>
<li>π§ Vague Scales</li>
</ul>
</div>
"""
)
with gr.Row():
with gr.Column(scale=3):
pdf_file = gr.File(label="Upload Research Paper (PDF)", file_types=[".pdf"])
with gr.Column(scale=1):
analyze_button = gr.Button(
"π Analyze Paper for Pitfalls",
variant="primary",
size="lg",
elem_id="analyze-btn",
)
with gr.Row():
results = gr.Markdown(
value="Upload a PDF to get started with pitfall analysis.",
elem_id="results",
)
# Add loading animation CSS
demo.css = """
#analyze-btn {
background: linear-gradient(45deg, #ff6b6b, #4ecdc4, #45b7d1, #96ceb4, #feca57);
background-size: 400% 400%;
animation: gradient 3s ease infinite;
border: none;
color: white;
font-weight: bold;
}
@keyframes gradient {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
#results {
min-height: 200px;
padding: 20px;
border: 1px solid #e0e0e0;
border-radius: 8px;
background-color: #ffffff;
color: #333333;
}
#results .markdown {
color: #333333 !important;
}
#results h1, #results h2, #results h3, #results h4, #results h5, #results h6 {
color: #2c3e50 !important;
}
#results p, #results li, #results div {
color: #333333 !important;
}
#results code {
background-color: #f8f9fa;
color: #e83e8c;
padding: 2px 4px;
border-radius: 3px;
}
#results pre {
background-color: #f8f9fa;
color: #333333;
padding: 10px;
border-radius: 5px;
border: 1px solid #e9ecef;
}
"""
# Connect the button to the processing function
analyze_button.click(
fn=process_paper,
inputs=[pdf_file],
outputs=[results],
)
if __name__ == "__main__":
demo.launch()
|