yuvrajyadav commited on
Commit
c0bd113
Β·
verified Β·
1 Parent(s): 11a6b70

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +254 -219
app.py CHANGED
@@ -1,4 +1,4 @@
1
- import streamlit as st
2
  import pandas as pd
3
  import requests
4
  import openai
@@ -8,46 +8,69 @@ from typing import List, Dict, Tuple
8
  import re
9
  from urllib.parse import quote_plus
10
  from datetime import datetime, timedelta
11
- import asyncio
12
- import aiohttp
13
 
14
- # Page config
15
- st.set_page_config(
16
- page_title="Citation Checker & Verification System",
17
- page_icon="πŸ”",
18
- layout="wide"
19
- )
20
 
21
  class CitationChecker:
22
  def __init__(self):
23
- self.openai_api_key = "OAPI1"
24
- self.deepseek_api_key = "DAPI"
25
- self.google_cse_keys = ["API1", "API2", "API3"]
26
- self.google_cse_ids = ["CX1", "CX2", "CX3"]
27
-
28
- def initialize_apis(self, openai_key, deepseek_key, google_keys, google_ids):
29
- """Initialize API keys"""
30
- self.openai_api_key = openai_key
31
- self.deepseek_api_key = deepseek_key
32
- self.google_cse_keys = google_keys
33
- self.google_cse_ids = google_ids
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
  # Set OpenAI API key
36
- openai.api_key = openai_key
 
 
 
 
 
 
 
 
 
37
 
38
  def parse_csv_data(self, df):
39
  """Parse CSV data and extract requirements"""
40
  requirements = []
41
 
42
  for idx, row in df.iterrows():
43
- if pd.notna(row['Requirement']) and row['Requirement'].strip():
44
  requirement_data = {
45
- 'id': row['ID'],
46
- 'rubric': row['Rubric'],
47
- 'weight': row['Weight'],
48
- 'requirement': row['Requirement'].strip(),
49
- 'evaluation_rules': row.get('Important Evaluation Rules', '') if pd.notna(row.get('Important Evaluation Rules', '')) else '',
50
- 'original_prompt': row['Prompt']
51
  }
52
  requirements.append(requirement_data)
53
 
@@ -108,7 +131,7 @@ class CitationChecker:
108
  return []
109
 
110
  except Exception as e:
111
- st.error(f"Error extracting claims: {str(e)}")
112
  return []
113
 
114
  def search_google_cse(self, query, cse_key, cse_id, num_results=10):
@@ -144,11 +167,11 @@ class CitationChecker:
144
 
145
  return results
146
  else:
147
- st.warning(f"Google CSE API error: {response.status_code}")
148
  return []
149
 
150
  except Exception as e:
151
- st.error(f"Search error: {str(e)}")
152
  return []
153
 
154
  def verify_claim_with_sources(self, claim, search_results):
@@ -229,7 +252,7 @@ class CitationChecker:
229
  }
230
 
231
  except Exception as e:
232
- st.error(f"Verification error: {str(e)}")
233
  return {
234
  "verification_status": "ERROR",
235
  "confidence_score": 0.0,
@@ -241,7 +264,7 @@ class CitationChecker:
241
  "recommendation": "Manual review required"
242
  }
243
 
244
- def process_requirement(self, requirement_data, progress_callback=None):
245
  """Process a single requirement - extract claims, search, and verify"""
246
 
247
  results = {
@@ -256,15 +279,13 @@ class CitationChecker:
256
  'timestamp': datetime.now().isoformat()
257
  }
258
 
259
- if progress_callback:
260
- progress_callback(f"Extracting claims for {requirement_data['id']}...")
261
 
262
  # Extract key claims
263
  claims = self.extract_key_claims(requirement_data['requirement'], requirement_data['evaluation_rules'])
264
 
265
  for i, claim in enumerate(claims):
266
- if progress_callback:
267
- progress_callback(f"Verifying claim {i+1}/{len(claims)} for {requirement_data['id']}...")
268
 
269
  # Search for each claim using multiple CSE instances
270
  all_search_results = []
@@ -297,6 +318,8 @@ class CitationChecker:
297
  results['claims'].append(claim_result)
298
  results['sources_found'].extend(unique_results[:5]) # Add top sources to overall list
299
 
 
 
300
  # Generate overall assessment
301
  results['overall_assessment'] = self.generate_overall_assessment(results)
302
 
@@ -390,203 +413,215 @@ class CitationChecker:
390
  except Exception as e:
391
  return f"Error generating final report: {str(e)}"
392
 
393
- # Streamlit UI
394
- def main():
395
- st.title("πŸ” Citation Checker & Verification System")
396
- st.markdown("### Verify requirements against internet sources with comprehensive citation analysis")
 
 
 
 
397
 
398
- # Sidebar for API configuration
399
- with st.sidebar:
400
- st.header("πŸ”‘ API Configuration")
401
 
402
- openai_key = st.text_input("OpenAI API Key", type="password")
403
- deepseek_key = st.text_input("DeepSeek API Key", type="password")
 
 
404
 
405
- st.subheader("Google CSE Configuration")
406
- num_cse = st.number_input("Number of Google CSE instances", min_value=1, max_value=3, value=3)
 
407
 
408
- google_keys = []
409
- google_ids = []
410
 
411
- for i in range(num_cse):
412
- st.write(f"**CSE Instance {i+1}**")
413
- key = st.text_input(f"Google API Key {i+1}", type="password", key=f"google_key_{i}")
414
- cse_id = st.text_input(f"CSE ID {i+1}", key=f"cse_id_{i}")
415
-
416
- if key and cse_id:
417
- google_keys.append(key)
418
- google_ids.append(cse_id)
419
-
420
- # Main interface
421
- tab1, tab2, tab3 = st.tabs(["πŸ“Š Upload & Process", "πŸ“‹ Results", "πŸ“„ Final Report"])
422
-
423
- with tab1:
424
- st.header("Upload CSV and Process Requirements")
425
-
426
- # File upload
427
- uploaded_file = st.file_uploader(
428
- "Upload your CSV file with requirements",
429
- type=['csv'],
430
- help="CSV should contain columns: Prompt, Rubric, ID, Weight, Requirement, Important Evaluation Rules"
431
- )
432
 
433
- if uploaded_file is not None:
434
- # Load CSV
435
- try:
436
- df = pd.read_csv(uploaded_file)
437
- st.success(f"βœ… Loaded CSV with {len(df)} rows")
438
-
439
- # Show preview
440
- st.subheader("πŸ“‹ Data Preview")
441
- st.dataframe(df.head())
442
-
443
- # Initialize checker
444
- if all([openai_key, len(google_keys) > 0, len(google_ids) > 0]):
445
- checker = CitationChecker()
446
- checker.initialize_apis(openai_key, deepseek_key, google_keys, google_ids)
447
-
448
- # Parse requirements
449
- requirements = checker.parse_csv_data(df)
450
- st.info(f"πŸ“ Found {len(requirements)} requirements to verify")
451
-
452
- # Process button
453
- if st.button("πŸš€ Start Verification Process", type="primary"):
454
-
455
- # Progress tracking
456
- progress_bar = st.progress(0)
457
- status_text = st.empty()
458
- results_container = st.container()
459
-
460
- all_results = []
461
-
462
- for i, requirement in enumerate(requirements):
463
- def progress_callback(message):
464
- status_text.text(f"Processing {i+1}/{len(requirements)}: {message}")
465
-
466
- # Process requirement
467
- result = checker.process_requirement(requirement, progress_callback)
468
- all_results.append(result)
469
-
470
- # Update progress
471
- progress_bar.progress((i + 1) / len(requirements))
472
-
473
- # Show intermediate results
474
- with results_container:
475
- st.write(f"**βœ… Completed: {requirement['id']}**")
476
- st.write(f"Assessment: {result['overall_assessment']}")
477
-
478
- # Store results in session state
479
- st.session_state['verification_results'] = all_results
480
- st.session_state['final_report'] = checker.generate_final_report(all_results)
481
-
482
- status_text.text("βœ… Verification complete!")
483
- st.success("All requirements have been processed successfully!")
484
-
485
- else:
486
- st.warning("⚠️ Please configure all API keys in the sidebar before processing")
487
-
488
- except Exception as e:
489
- st.error(f"Error loading CSV: {str(e)}")
490
-
491
- with tab2:
492
- st.header("πŸ“‹ Detailed Verification Results")
493
 
494
- if 'verification_results' in st.session_state:
495
- results = st.session_state['verification_results']
 
496
 
497
- # Summary metrics
498
- col1, col2, col3, col4 = st.columns(4)
499
 
500
- total_requirements = len(results)
501
- verified_requirements = len([r for r in results if 'WELL_SUPPORTED' in r['overall_assessment']])
502
- contradicted_requirements = len([r for r in results if 'CONTRADICTED' in r['overall_assessment']])
503
- total_claims = sum(len(r['claims']) for r in results)
 
504
 
505
- col1.metric("Total Requirements", total_requirements)
506
- col2.metric("Well Supported", verified_requirements)
507
- col3.metric("Contradicted", contradicted_requirements)
508
- col4.metric("Total Claims Checked", total_claims)
509
 
510
- # Detailed results
511
- for result in results:
512
- with st.expander(f"πŸ“Š {result['requirement_id']} - {result['rubric']}"):
513
-
514
- st.write(f"**Weight:** {result['weight']}")
515
- st.write(f"**Requirement:** {result['requirement_text']}")
516
- st.write(f"**Overall Assessment:** {result['overall_assessment']}")
517
-
518
- if result['evaluation_rules']:
519
- st.write(f"**Evaluation Rules:** {result['evaluation_rules']}")
520
-
521
- st.subheader("πŸ” Claims Analysis")
522
-
523
- for i, claim_result in enumerate(result['claims'], 1):
524
- claim = claim_result['claim']
525
- verification = claim_result['verification']
526
-
527
- # Status color
528
- status_colors = {
529
- 'VERIFIED': '🟒',
530
- 'CONTRADICTED': 'πŸ”΄',
531
- 'PARTIALLY_VERIFIED': '🟑',
532
- 'INSUFFICIENT_DATA': 'βšͺ',
533
- 'ERROR': '⚫'
534
- }
535
-
536
- status_icon = status_colors.get(verification['verification_status'], 'βšͺ')
537
-
538
- st.write(f"**{status_icon} Claim {i}:** {claim['claim']}")
539
- st.write(f"**Status:** {verification['verification_status']} (Confidence: {verification['confidence_score']:.2f})")
540
- st.write(f"**Summary:** {verification['summary']}")
541
-
542
- if verification['specific_data_found']:
543
- st.write(f"**Data Found:** {verification['specific_data_found']}")
544
-
545
- if verification['recommendation']:
546
- st.write(f"**Recommendation:** {verification['recommendation']}")
547
-
548
- # Show sources
549
- if claim_result['search_results']:
550
- st.write("**πŸ“š Sources Found:**")
551
- for j, source in enumerate(claim_result['search_results'][:3], 1):
552
- st.write(f"{j}. [{source['title']}]({source['link']}) - {source['displayLink']}")
553
-
554
- st.write("---")
555
- else:
556
- st.info("No results available. Please process requirements in the Upload & Process tab first.")
557
-
558
- with tab3:
559
- st.header("πŸ“„ Comprehensive Final Report")
560
-
561
- if 'final_report' in st.session_state:
562
- report = st.session_state['final_report']
563
 
564
- # Display report
565
- st.markdown(report)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
566
 
567
- # Download button
568
- st.download_button(
569
- label="πŸ“₯ Download Full Report",
570
- data=report,
571
- file_name=f"citation_verification_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.md",
572
- mime="text/markdown"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
573
  )
 
 
 
 
 
 
 
574
 
575
- # Download detailed results as JSON
576
- if 'verification_results' in st.session_state:
577
- results_json = json.dumps(st.session_state['verification_results'], indent=2, default=str)
578
- st.download_button(
579
- label="πŸ“₯ Download Detailed Results (JSON)",
580
- data=results_json,
581
- file_name=f"verification_results_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json",
582
- mime="application/json"
583
- )
584
- else:
585
- st.info("No report available. Please process requirements first.")
 
 
 
 
 
 
 
 
 
586
 
587
- # Footer
588
- st.markdown("---")
589
- st.markdown("**Citation Checker & Verification System** - Powered by OpenAI GPT-4, DeepSeek, and Google Custom Search")
590
 
 
591
  if __name__ == "__main__":
592
- main()
 
 
1
+ import gradio as gr
2
  import pandas as pd
3
  import requests
4
  import openai
 
8
  import re
9
  from urllib.parse import quote_plus
10
  from datetime import datetime, timedelta
11
+ import os
 
12
 
13
+ # Load environment variables for Hugging Face Spaces
14
+ OPENAI_API_KEY = os.getenv("OaPI1")
15
+ DEEPSEEK_API_KEY = os.getenv("DAPI")
16
+ GOOGLE_CSE_KEYS = os.getenv("API1", "API2", "API3") # comma-separated
17
+ GOOGLE_CSE_IDS = os.getenv("CX1", "CX2", "CX3") # comma-separated
 
18
 
19
  class CitationChecker:
20
  def __init__(self):
21
+ self.openai_api_key = None
22
+ self.deepseek_api_key = None
23
+ self.google_cse_keys = []
24
+ self.google_cse_ids = []
25
+
26
+ def initialize_apis(self, openai_key, deepseek_key, google_keys_str, google_ids_str):
27
+ """Initialize API keys - use provided keys or fall back to environment variables"""
28
+
29
+ # Use provided keys if available, otherwise use environment variables
30
+ self.openai_api_key = openai_key if openai_key.strip() else OPENAI_API_KEY
31
+ self.deepseek_api_key = deepseek_key if deepseek_key.strip() else DEEPSEEK_API_KEY
32
+
33
+ # Handle Google keys
34
+ if google_keys_str.strip():
35
+ self.google_cse_keys = [k.strip() for k in google_keys_str.split(',') if k.strip()]
36
+ elif GOOGLE_CSE_KEYS:
37
+ self.google_cse_keys = [k.strip() for k in GOOGLE_CSE_KEYS.split(',') if k.strip()]
38
+ else:
39
+ self.google_cse_keys = []
40
+
41
+ # Handle Google CSE IDs
42
+ if google_ids_str.strip():
43
+ self.google_cse_ids = [i.strip() for i in google_ids_str.split(',') if i.strip()]
44
+ elif GOOGLE_CSE_IDS:
45
+ self.google_cse_ids = [i.strip() for i in GOOGLE_CSE_IDS.split(',') if i.strip()]
46
+ else:
47
+ self.google_cse_ids = []
48
 
49
  # Set OpenAI API key
50
+ if self.openai_api_key:
51
+ openai.api_key = self.openai_api_key
52
+
53
+ # Validate that we have the required keys
54
+ if not self.openai_api_key:
55
+ raise ValueError("OpenAI API key is required")
56
+ if not self.google_cse_keys or not self.google_cse_ids:
57
+ raise ValueError("Google CSE keys and IDs are required")
58
+ if len(self.google_cse_keys) != len(self.google_cse_ids):
59
+ raise ValueError("Number of Google CSE keys must match number of CSE IDs")
60
 
61
  def parse_csv_data(self, df):
62
  """Parse CSV data and extract requirements"""
63
  requirements = []
64
 
65
  for idx, row in df.iterrows():
66
+ if pd.notna(row.get('Requirement', '')) and str(row['Requirement']).strip():
67
  requirement_data = {
68
+ 'id': row.get('ID', f'req_{idx}'),
69
+ 'rubric': row.get('Rubric', 'Unknown'),
70
+ 'weight': row.get('Weight', 1),
71
+ 'requirement': str(row['Requirement']).strip(),
72
+ 'evaluation_rules': str(row.get('Important Evaluation Rules', '')) if pd.notna(row.get('Important Evaluation Rules', '')) else '',
73
+ 'original_prompt': row.get('Prompt', '')
74
  }
75
  requirements.append(requirement_data)
76
 
 
131
  return []
132
 
133
  except Exception as e:
134
+ print(f"Error extracting claims: {str(e)}")
135
  return []
136
 
137
  def search_google_cse(self, query, cse_key, cse_id, num_results=10):
 
167
 
168
  return results
169
  else:
170
+ print(f"Google CSE API error: {response.status_code}")
171
  return []
172
 
173
  except Exception as e:
174
+ print(f"Search error: {str(e)}")
175
  return []
176
 
177
  def verify_claim_with_sources(self, claim, search_results):
 
252
  }
253
 
254
  except Exception as e:
255
+ print(f"Verification error: {str(e)}")
256
  return {
257
  "verification_status": "ERROR",
258
  "confidence_score": 0.0,
 
264
  "recommendation": "Manual review required"
265
  }
266
 
267
+ def process_requirement(self, requirement_data, progress=gr.Progress()):
268
  """Process a single requirement - extract claims, search, and verify"""
269
 
270
  results = {
 
279
  'timestamp': datetime.now().isoformat()
280
  }
281
 
282
+ progress(0.1, desc=f"Extracting claims for {requirement_data['id']}...")
 
283
 
284
  # Extract key claims
285
  claims = self.extract_key_claims(requirement_data['requirement'], requirement_data['evaluation_rules'])
286
 
287
  for i, claim in enumerate(claims):
288
+ progress(0.1 + (0.8 * i / len(claims)), desc=f"Verifying claim {i+1}/{len(claims)} for {requirement_data['id']}...")
 
289
 
290
  # Search for each claim using multiple CSE instances
291
  all_search_results = []
 
318
  results['claims'].append(claim_result)
319
  results['sources_found'].extend(unique_results[:5]) # Add top sources to overall list
320
 
321
+ progress(0.9, desc="Generating assessment...")
322
+
323
  # Generate overall assessment
324
  results['overall_assessment'] = self.generate_overall_assessment(results)
325
 
 
413
  except Exception as e:
414
  return f"Error generating final report: {str(e)}"
415
 
416
+ # Initialize the citation checker
417
+ checker = CitationChecker()
418
+
419
+ def process_csv_and_verify(csv_file, openai_key, deepseek_key, google_keys, google_ids, progress=gr.Progress()):
420
+ """Main function to process CSV and run verification"""
421
+
422
+ if not csv_file:
423
+ return "❌ Please upload a CSV file", "", ""
424
 
425
+ try:
426
+ # Initialize APIs (will use environment variables if inputs are empty)
427
+ checker.initialize_apis(openai_key, deepseek_key, google_keys, google_ids)
428
 
429
+ except ValueError as e:
430
+ return f"❌ API Configuration Error: {str(e)}", "", ""
431
+ except Exception as e:
432
+ return f"❌ Error initializing APIs: {str(e)}", "", ""
433
 
434
+ # Read CSV file
435
+ df = pd.read_csv(csv_file.name)
436
+ progress(0.05, desc="Parsing CSV data...")
437
 
438
+ # Parse requirements
439
+ requirements = checker.parse_csv_data(df)
440
 
441
+ if not requirements:
442
+ return "❌ No valid requirements found in CSV", "", ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
443
 
444
+ progress(0.1, desc=f"Found {len(requirements)} requirements to verify...")
445
+
446
+ all_results = []
447
+ detailed_output = f"# πŸ“Š Verification Results\n\n**Total Requirements:** {len(requirements)}\n\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
448
 
449
+ # Process each requirement
450
+ for i, requirement in enumerate(requirements):
451
+ progress(0.1 + (0.7 * i / len(requirements)), desc=f"Processing requirement {i+1}/{len(requirements)}: {requirement['id']}")
452
 
453
+ result = checker.process_requirement(requirement, progress)
454
+ all_results.append(result)
455
 
456
+ # Add to detailed output
457
+ detailed_output += f"## πŸ“‹ {result['requirement_id']} - {result['rubric']}\n\n"
458
+ detailed_output += f"**Weight:** {result['weight']}\n\n"
459
+ detailed_output += f"**Requirement:** {result['requirement_text']}\n\n"
460
+ detailed_output += f"**Overall Assessment:** {result['overall_assessment']}\n\n"
461
 
462
+ if result['evaluation_rules']:
463
+ detailed_output += f"**Evaluation Rules:** {result['evaluation_rules']}\n\n"
 
 
464
 
465
+ detailed_output += "### πŸ” Claims Analysis\n\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
466
 
467
+ for j, claim_result in enumerate(result['claims'], 1):
468
+ claim = claim_result['claim']
469
+ verification = claim_result['verification']
470
+
471
+ status_icons = {
472
+ 'VERIFIED': 'βœ…',
473
+ 'CONTRADICTED': '❌',
474
+ 'PARTIALLY_VERIFIED': '⚠️',
475
+ 'INSUFFICIENT_DATA': '❓',
476
+ 'ERROR': '❌'
477
+ }
478
+
479
+ status_icon = status_icons.get(verification['verification_status'], '❓')
480
+
481
+ detailed_output += f"**{status_icon} Claim {j}:** {claim['claim']}\n\n"
482
+ detailed_output += f"**Status:** {verification['verification_status']} (Confidence: {verification['confidence_score']:.2f})\n\n"
483
+ detailed_output += f"**Summary:** {verification['summary']}\n\n"
484
+
485
+ if verification['specific_data_found']:
486
+ detailed_output += f"**Data Found:** {verification['specific_data_found']}\n\n"
487
+
488
+ if verification['recommendation']:
489
+ detailed_output += f"**Recommendation:** {verification['recommendation']}\n\n"
490
+
491
+ # Show top sources
492
+ if claim_result['search_results'][:3]:
493
+ detailed_output += "**πŸ“š Top Sources:**\n\n"
494
+ for k, source in enumerate(claim_result['search_results'][:3], 1):
495
+ detailed_output += f"{k}. [{source['title']}]({source['link']}) - {source['displayLink']}\n\n"
496
+
497
+ detailed_output += "---\n\n"
498
+
499
+ progress(0.9, desc="Generating final report...")
500
+
501
+ # Generate final report
502
+ final_report = checker.generate_final_report(all_results)
503
+
504
+ # Generate summary
505
+ verified_requirements = len([r for r in all_results if 'WELL_SUPPORTED' in r['overall_assessment']])
506
+ contradicted_requirements = len([r for r in all_results if 'CONTRADICTED' in r['overall_assessment']])
507
+ total_claims = sum(len(r['claims']) for r in all_results)
508
+
509
+ summary = f"""# βœ… Processing Complete!
510
+
511
+ **πŸ“Š Summary Metrics:**
512
+ - Total Requirements: {len(requirements)}
513
+ - Well Supported: {verified_requirements}
514
+ - Contradicted: {contradicted_requirements}
515
+ - Total Claims Checked: {total_claims}
516
+
517
+ **⏰ Processed at:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
518
+
519
+ Use the tabs below to view detailed results and the comprehensive final report.
520
+ """
521
+
522
+ progress(1.0, desc="Complete!")
523
+
524
+ return summary, detailed_output, final_report
525
+
526
+ except Exception as e:
527
+ return f"❌ Error processing file: {str(e)}", "", ""
528
+
529
+ def create_interface():
530
+ """Create the Gradio interface"""
531
+
532
+ with gr.Blocks(title="πŸ” Citation Checker & Verification System", theme=gr.themes.Soft()) as demo:
533
+
534
+ gr.Markdown("""
535
+ # πŸ” Citation Checker & Verification System
536
+ ### Verify requirements against internet sources with comprehensive citation analysis
537
+
538
+ Upload your CSV file with requirements and provide API credentials to start the verification process.
539
+ """)
540
+
541
+ with gr.Row():
542
+ with gr.Column(scale=1):
543
+ gr.Markdown("## πŸ“ File Upload")
544
+ csv_file = gr.File(
545
+ label="Upload CSV File",
546
+ file_types=[".csv"],
547
+ type="filepath"
548
+ )
549
+
550
+ gr.Markdown("""
551
+ **CSV Requirements:**
552
+ - Must contain columns: `Requirement`, `ID`, `Rubric`, `Weight`
553
+ - Optional: `Important Evaluation Rules`, `Prompt`
554
+ """)
555
 
556
+ with gr.Column(scale=1):
557
+ gr.Markdown("## πŸ”‘ API Configuration")
558
+
559
+ openai_key = gr.Textbox(
560
+ label="OpenAI API Key",
561
+ type="password",
562
+ placeholder="sk-... (or set OPENAI_API_KEY environment variable)",
563
+ value=OPENAI_API_KEY if OPENAI_API_KEY else ""
564
+ )
565
+
566
+ deepseek_key = gr.Textbox(
567
+ label="DeepSeek API Key (Optional)",
568
+ type="password",
569
+ placeholder="sk-... (or set DEEPSEEK_API_KEY environment variable)",
570
+ value=DEEPSEEK_API_KEY if DEEPSEEK_API_KEY else ""
571
+ )
572
+
573
+ google_keys = gr.Textbox(
574
+ label="Google CSE API Keys",
575
+ placeholder="key1,key2,key3 (comma-separated) or set GOOGLE_CSE_KEYS env var",
576
+ info="Multiple keys for better rate limiting",
577
+ value=GOOGLE_CSE_KEYS if GOOGLE_CSE_KEYS else ""
578
+ )
579
+
580
+ google_ids = gr.Textbox(
581
+ label="Google CSE IDs",
582
+ placeholder="cx1,cx2,cx3 (comma-separated) or set GOOGLE_CSE_IDS env var",
583
+ info="Corresponding CSE IDs for each API key",
584
+ value=GOOGLE_CSE_IDS if GOOGLE_CSE_IDS else ""
585
+ )
586
+
587
+ with gr.Row():
588
+ process_btn = gr.Button(
589
+ "πŸš€ Start Verification Process",
590
+ variant="primary",
591
+ size="lg"
592
  )
593
+
594
+ with gr.Row():
595
+ summary_output = gr.Markdown(label="Summary")
596
+
597
+ with gr.Tabs():
598
+ with gr.TabItem("πŸ“Š Detailed Results"):
599
+ detailed_output = gr.Markdown()
600
 
601
+ with gr.TabItem("πŸ“„ Final Report"):
602
+ final_report = gr.Markdown()
603
+
604
+ # Set up the processing function
605
+ process_btn.click(
606
+ fn=process_csv_and_verify,
607
+ inputs=[csv_file, openai_key, deepseek_key, google_keys, google_ids],
608
+ outputs=[summary_output, detailed_output, final_report],
609
+ show_progress=True
610
+ )
611
+
612
+ gr.Markdown("""
613
+ ---
614
+ **Citation Checker & Verification System** - Powered by OpenAI GPT-4, DeepSeek, and Google Custom Search
615
+
616
+ **πŸ” For Hugging Face Deployment:**
617
+ - Set environment variables: `OPENAI_API_KEY`, `GOOGLE_CSE_KEYS`, `GOOGLE_CSE_IDS`
618
+ - Or enter API keys manually in the form above
619
+ - Environment variables will be used automatically if form fields are left empty
620
+ """)
621
 
622
+ return demo
 
 
623
 
624
+ # Create and launch the interface
625
  if __name__ == "__main__":
626
+ demo = create_interface()
627
+ demo.launch()