MBilal-72 commited on
Commit
e9e89f3
Β·
verified Β·
1 Parent(s): 4bbb5d4

update app.py add extra gui

Browse files
Files changed (1) hide show
  1. app.py +391 -59
app.py CHANGED
@@ -8,6 +8,7 @@ import os
8
  import tempfile
9
  import json
10
  from typing import Dict, Any, List
 
11
 
12
  # Import our custom modules
13
  from utils.parser import PDFParser, TextParser, WebpageParser
@@ -183,7 +184,7 @@ class GEOSEOApp:
183
  st.error(f"An error occurred: {str(e)}")
184
 
185
  def render_content_enhancement_tab(self):
186
- """Render Content Enhancement tab"""
187
  st.header("πŸ”§ Content Enhancement")
188
  st.markdown("Analyze and optimize your content for better AI/LLM performance.")
189
 
@@ -194,84 +195,415 @@ class GEOSEOApp:
194
  key="enhancement_input"
195
  )
196
 
197
- # Analysis options
 
198
  col1, col2 = st.columns(2)
 
199
  with col1:
200
- analyze_only = st.checkbox("Analysis only (no rewriting)", value=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
  with col2:
202
- include_keywords = st.checkbox("Include keyword suggestions", value=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
 
204
  # Submit button
205
- if st.button("πŸ”§ Analyze & Enhance", key="enhancement_submit"):
206
  if not input_text.strip():
207
  st.warning("Please enter some content to analyze.")
208
  return
209
 
210
  try:
211
- with st.spinner("Analyzing content..."):
212
- # Run content analysis and optimization
213
- result = self.content_optimizer.optimize_content(
214
- input_text,
215
- analyze_only=analyze_only,
216
- include_keywords=include_keywords
217
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
 
219
  if result.get("error"):
220
- st.error(f"Analysis failed: {result['error']}")
221
  return
222
 
223
- # Display results
224
- if analyze_only:
225
- st.success("Content analysis and enhancement completed successfully!")
226
- st.markdown("### πŸ“Š Analysis Results")
227
 
228
- # Show scores
229
- scores = result.get("scores", {})
230
- if scores:
231
- col1, col2, col3 = st.columns(3)
232
-
233
- with col1:
234
- clarity = scores.get("clarity", 0)
235
- st.metric("Clarity", f"{clarity}/10")
236
 
237
- with col2:
238
- structure = scores.get("structuredness", 0)
239
- st.metric("Structure", f"{structure}/10")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
240
 
241
- with col3:
242
- answerability = scores.get("answerability", 0)
243
- st.metric("Answerability", f"{answerability}/10")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
244
 
245
- # Show keywords
246
- keywords = result.get("keywords", [])
247
- if keywords:
248
- st.markdown("#### πŸ”‘ Key Terms")
249
- st.write(", ".join(keywords))
250
-
251
- # Show optimized content
252
- optimized_text = result.get("optimized_text", "")
253
- # if optimized_text and not analyze_only:
254
- if optimized_text :
255
- st.markdown("#### ✨ Optimized Content")
256
- st.text_area(
257
- "Enhanced version:",
258
- value=optimized_text,
259
- height=200,
260
- key="optimized_output"
261
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
 
263
- # Export option
264
- if st.button("πŸ“₯ Export Results"):
265
- export_data = self.result_exporter.export_enhancement_results(result)
266
- st.download_button(
267
- label="Download Analysis Report",
268
- data=json.dumps(export_data, indent=2),
269
- file_name=f"content_analysis_{int(time.time())}.json",
270
- mime="application/json"
271
- )
272
 
273
- except Exception as e:
274
- st.error(f"An error occurred: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
275
 
276
  def render_website_analysis_tab(self):
277
  """Render Website GEO Analysis tab"""
 
8
  import tempfile
9
  import json
10
  from typing import Dict, Any, List
11
+ import time # Add this if not present
12
 
13
  # Import our custom modules
14
  from utils.parser import PDFParser, TextParser, WebpageParser
 
184
  st.error(f"An error occurred: {str(e)}")
185
 
186
  def render_content_enhancement_tab(self):
187
+ """Render Content Enhancement tab with optimization type selector"""
188
  st.header("πŸ”§ Content Enhancement")
189
  st.markdown("Analyze and optimize your content for better AI/LLM performance.")
190
 
 
195
  key="enhancement_input"
196
  )
197
 
198
+ # Optimization type selector
199
+ st.markdown("### βš™οΈ Optimization Settings")
200
  col1, col2 = st.columns(2)
201
+
202
  with col1:
203
+ optimization_type = st.selectbox(
204
+ "Select Optimization Type:",
205
+ options=[
206
+ "standard",
207
+ "seo",
208
+ "competitive",
209
+ "voice_search",
210
+ "batch_optimize",
211
+ "content_variations",
212
+ "readability_analysis",
213
+ "entity_extraction"
214
+ ],
215
+ format_func=lambda x: {
216
+ "standard": "πŸ”§ Standard Enhancement",
217
+ "seo": "🌐 SEO-Focused Optimization",
218
+ "competitive": "πŸ“Š Competitive Analysis",
219
+ "voice_search": "🎀 Voice Search Optimization",
220
+ "batch_optimize": "πŸ“¦ Batch Optimization",
221
+ "content_variations": "πŸ”„ Content Variations",
222
+ "readability_analysis": "πŸ“– Readability Analysis",
223
+ "entity_extraction": "🏷️ Entity Extraction"
224
+ }[x],
225
+ index=0,
226
+ help="Choose the type of optimization to apply to your content"
227
+ )
228
+
229
  with col2:
230
+ # Additional options based on optimization type
231
+ if optimization_type in ["standard", "seo"]:
232
+ analyze_only = st.checkbox("Analysis only (no rewriting)", value=False)
233
+ include_keywords = st.checkbox("Include keyword suggestions", value=True)
234
+ elif optimization_type == "batch_optimize":
235
+ st.info("For batch optimization, separate multiple content pieces with '---' in the text area above")
236
+ elif optimization_type == "content_variations":
237
+ num_variations = st.slider("Number of variations", min_value=1, max_value=5, value=3)
238
+ else:
239
+ analyze_only = False
240
+ include_keywords = True
241
+ num_variations = 3
242
+
243
+ # Show description based on optimization type
244
+ optimization_descriptions = {
245
+ "standard": "General content enhancement focusing on clarity, structure, and AI answerability.",
246
+ "seo": "SEO-focused optimization for AI search engines with semantic keyword analysis.",
247
+ "competitive": "Competitive analysis against AI search best practices with gap identification.",
248
+ "voice_search": "Optimization for voice search and conversational AI systems.",
249
+ "batch_optimize": "Process multiple content pieces simultaneously.",
250
+ "content_variations": "Generate multiple optimized variations of the same content.",
251
+ "readability_analysis": "Detailed readability analysis specifically for AI systems.",
252
+ "entity_extraction": "Extract key entities, topics, and concepts for optimization insights."
253
+ }
254
+
255
+ st.info(f"**{optimization_descriptions[optimization_type]}**")
256
 
257
  # Submit button
258
+ if st.button("πŸš€ Process Content", key="enhancement_submit"):
259
  if not input_text.strip():
260
  st.warning("Please enter some content to analyze.")
261
  return
262
 
263
  try:
264
+ with st.spinner(f"Processing content with {optimization_type} optimization..."):
265
+ # Handle different optimization types
266
+ if optimization_type == "standard":
267
+ result = self.content_optimizer.optimize_content(
268
+ input_text,
269
+ analyze_only=analyze_only,
270
+ include_keywords=include_keywords,
271
+ optimization_type="standard"
272
+ )
273
+
274
+ elif optimization_type == "seo":
275
+ result = self.content_optimizer.optimize_content(
276
+ input_text,
277
+ analyze_only=analyze_only,
278
+ include_keywords=include_keywords,
279
+ optimization_type="seo"
280
+ )
281
+
282
+ elif optimization_type == "competitive":
283
+ result = self.content_optimizer.optimize_content(
284
+ input_text,
285
+ optimization_type="competitive"
286
+ )
287
+
288
+ elif optimization_type == "voice_search":
289
+ result = self.content_optimizer.optimize_for_voice_search(input_text)
290
+
291
+ elif optimization_type == "batch_optimize":
292
+ # Split content by '---' separator
293
+ content_pieces = [piece.strip() for piece in input_text.split('---') if piece.strip()]
294
+ if len(content_pieces) > 1:
295
+ result = self.content_optimizer.batch_optimize_content(content_pieces)
296
+ else:
297
+ st.warning("For batch optimization, please separate content pieces with '---'")
298
+ return
299
+
300
+ elif optimization_type == "content_variations":
301
+ result = self.content_optimizer.generate_content_variations(
302
+ input_text,
303
+ num_variations=num_variations
304
+ )
305
+
306
+ elif optimization_type == "readability_analysis":
307
+ result = self.content_optimizer.analyze_content_readability(input_text)
308
+
309
+ elif optimization_type == "entity_extraction":
310
+ result = self.content_optimizer.extract_key_entities(input_text)
311
 
312
  if result.get("error"):
313
+ st.error(f"Processing failed: {result['error']}")
314
  return
315
 
316
+ # Display results based on optimization type
317
+ self.display_enhancement_results(result, optimization_type, input_text)
 
 
318
 
319
+ except Exception as e:
320
+ st.error(f"An error occurred: {str(e)}")
 
 
 
 
 
 
321
 
322
+ def display_enhancement_results(self, result, optimization_type, original_text):
323
+ """Display results based on optimization type"""
324
+ st.success(f"{optimization_type.title()} optimization completed successfully!")
325
+
326
+ if optimization_type == "batch_optimize":
327
+ self.display_batch_results(result)
328
+ elif optimization_type == "content_variations":
329
+ self.display_variation_results(result)
330
+ elif optimization_type == "readability_analysis":
331
+ self.display_readability_results(result)
332
+ elif optimization_type == "entity_extraction":
333
+ self.display_entity_results(result)
334
+ elif optimization_type == "voice_search":
335
+ self.display_voice_search_results(result)
336
+ else:
337
+ self.display_standard_results(result, optimization_type)
338
+
339
+ # Export functionality
340
+ self.display_export_options(result, optimization_type, original_text)
341
 
342
+ def display_standard_results(self, result, optimization_type):
343
+ """Display results for standard, SEO, and competitive optimizations"""
344
+ st.markdown("### πŸ“Š Analysis Results")
345
+
346
+ # Show scores if available
347
+ scores = result.get("scores", {})
348
+ if scores:
349
+ col1, col2, col3 = st.columns(3)
350
+
351
+ with col1:
352
+ clarity = scores.get("clarity", 0)
353
+ st.metric("Clarity", f"{clarity}/10")
354
+
355
+ with col2:
356
+ structure = scores.get("structuredness", 0)
357
+ st.metric("Structure", f"{structure}/10")
358
+
359
+ with col3:
360
+ answerability = scores.get("answerability", 0)
361
+ st.metric("Answerability", f"{answerability}/10")
362
+
363
+ # Show SEO analysis if available
364
+ if "seo_analysis" in result:
365
+ st.markdown("#### 🌐 SEO Analysis")
366
+ seo_data = result["seo_analysis"]
367
+ if "readability_score" in seo_data:
368
+ st.metric("Readability Score", f"{seo_data['readability_score']}/10")
369
+ if "semantic_gaps" in seo_data:
370
+ st.write("**Semantic Gaps:**", ", ".join(seo_data["semantic_gaps"]))
371
+
372
+ # Show competitive analysis if available
373
+ if "competitive_analysis" in result:
374
+ st.markdown("#### πŸ“Š Competitive Analysis")
375
+ comp_data = result["competitive_analysis"]
376
+ for key, value in comp_data.items():
377
+ if isinstance(value, list):
378
+ st.write(f"**{key.replace('_', ' ').title()}:**", ", ".join(value))
379
+ else:
380
+ st.write(f"**{key.replace('_', ' ').title()}:**", value)
381
+
382
+ # Show keywords
383
+ keywords = result.get("keywords", [])
384
+ if keywords:
385
+ st.markdown("#### πŸ”‘ Key Terms")
386
+ st.write(", ".join(keywords))
387
+
388
+ # Show optimized content
389
+ optimized_content = result.get("optimized_text") or result.get("optimized_content", {}).get("enhanced_content", "")
390
+ if optimized_content:
391
+ st.markdown("#### ✨ Optimized Content")
392
+ st.text_area(
393
+ "Enhanced version:",
394
+ value=optimized_content,
395
+ height=200,
396
+ key="optimized_output"
397
+ )
398
+
399
+ # Show recommendations
400
+ recommendations = result.get("recommendations", [])
401
+ if recommendations:
402
+ st.markdown("#### πŸ’‘ Recommendations")
403
+ for i, rec in enumerate(recommendations, 1):
404
+ st.write(f"**{i}.** {rec}")
405
 
406
+ def display_batch_results(self, results):
407
+ """Display batch optimization results"""
408
+ st.markdown("### πŸ“¦ Batch Processing Results")
409
+
410
+ successful_results = [r for r in results if not r.get('error')]
411
+ failed_results = [r for r in results if r.get('error')]
412
+
413
+ col1, col2, col3 = st.columns(3)
414
+ with col1:
415
+ st.metric("Total Pieces", len(results))
416
+ with col2:
417
+ st.metric("Successful", len(successful_results))
418
+ with col3:
419
+ st.metric("Failed", len(failed_results))
420
+
421
+ # Show individual results
422
+ for result in results:
423
+ idx = result.get('batch_index', 0)
424
+ st.markdown(f"#### Content Piece {idx + 1}")
425
+
426
+ if result.get('error'):
427
+ st.error(f"Processing failed: {result['error']}")
428
+ else:
429
+ # Show scores
430
+ scores = result.get("scores", {})
431
+ if scores:
432
+ col1, col2, col3 = st.columns(3)
433
+ with col1:
434
+ st.metric("Clarity", f"{scores.get('clarity', 0)}/10")
435
+ with col2:
436
+ st.metric("Structure", f"{scores.get('structuredness', 0)}/10")
437
+ with col3:
438
+ st.metric("Answerability", f"{scores.get('answerability', 0)}/10")
439
 
440
+ # Show optimized content if available
441
+ optimized = result.get("optimized_text", "")
442
+ if optimized:
443
+ with st.expander("View optimized content"):
444
+ st.text_area("", value=optimized, height=150, key=f"batch_output_{idx}")
 
 
 
 
445
 
446
+ st.write("---")
447
+
448
+ def display_variation_results(self, variations):
449
+ """Display content variation results"""
450
+ st.markdown("### πŸ”„ Content Variations")
451
+
452
+ for i, variation in enumerate(variations):
453
+ if variation.get('error'):
454
+ st.error(f"Variation {i+1} failed: {variation['error']}")
455
+ continue
456
+
457
+ variation_type = variation.get('variation_type', f'Variation {i+1}')
458
+ st.markdown(f"#### {variation_type.title()} Version")
459
+
460
+ # Show variation details
461
+ target_use_case = variation.get('target_use_case', '')
462
+ if target_use_case:
463
+ st.info(f"**Target Use Case:** {target_use_case}")
464
+
465
+ # Show key changes
466
+ key_changes = variation.get('key_changes', [])
467
+ if key_changes:
468
+ st.write("**Key Changes:**")
469
+ for change in key_changes:
470
+ st.write(f"β€’ {change}")
471
+
472
+ # Show optimized content
473
+ optimized_content = variation.get('optimized_content', '')
474
+ if optimized_content:
475
+ st.text_area(
476
+ f"{variation_type} content:",
477
+ value=optimized_content,
478
+ height=150,
479
+ key=f"variation_{i}"
480
+ )
481
+
482
+ st.write("---")
483
+
484
+ def display_readability_results(self, result):
485
+ """Display readability analysis results"""
486
+ st.markdown("### πŸ“– Readability Analysis")
487
+
488
+ # Basic metrics
489
+ basic_metrics = result.get('basic_metrics', {})
490
+ if basic_metrics:
491
+ st.markdown("#### πŸ“Š Basic Metrics")
492
+ col1, col2, col3, col4 = st.columns(4)
493
+
494
+ with col1:
495
+ st.metric("Total Words", basic_metrics.get('total_words', 0))
496
+ with col2:
497
+ st.metric("Sentences", basic_metrics.get('total_sentences', 0))
498
+ with col3:
499
+ st.metric("Paragraphs", basic_metrics.get('total_paragraphs', 0))
500
+ with col4:
501
+ st.metric("AI Readability", f"{result.get('ai_readability_score', 0)}/10")
502
+
503
+ # Complexity indicators
504
+ complexity = result.get('complexity_indicators', {})
505
+ if complexity:
506
+ st.markdown("#### 🎯 Complexity Analysis")
507
+ col1, col2 = st.columns(2)
508
+
509
+ with col1:
510
+ st.metric("Long Sentences", f"{complexity.get('long_sentences_percentage', 0):.1f}%")
511
+ with col2:
512
+ st.metric("Complex Words", f"{complexity.get('complex_words_percentage', 0):.1f}%")
513
+
514
+ # Recommendations
515
+ recommendations = result.get('recommendations', [])
516
+ if recommendations:
517
+ st.markdown("#### πŸ’‘ Readability Recommendations")
518
+ for i, rec in enumerate(recommendations, 1):
519
+ st.write(f"**{i}.** {rec}")
520
+
521
+ def display_entity_results(self, result):
522
+ """Display entity extraction results"""
523
+ st.markdown("### 🏷️ Entity Analysis")
524
+
525
+ # Named entities
526
+ named_entities = result.get('named_entities', [])
527
+ if named_entities:
528
+ st.markdown("#### πŸ‘₯ Named Entities")
529
+ st.write(", ".join(named_entities))
530
+
531
+ # Key topics
532
+ key_topics = result.get('key_topics', [])
533
+ if key_topics:
534
+ st.markdown("#### πŸ“‹ Key Topics")
535
+ st.write(", ".join(key_topics))
536
+
537
+ # Technical terms
538
+ technical_terms = result.get('technical_terms', [])
539
+ if technical_terms:
540
+ st.markdown("#### πŸ”§ Technical Terms")
541
+ st.write(", ".join(technical_terms))
542
+
543
+ # Semantic keywords
544
+ semantic_keywords = result.get('semantic_keywords', [])
545
+ if semantic_keywords:
546
+ st.markdown("#### πŸ” Semantic Keywords")
547
+ st.write(", ".join(semantic_keywords))
548
+
549
+ # Question opportunities
550
+ questions = result.get('question_opportunities', [])
551
+ if questions:
552
+ st.markdown("#### ❓ Question Opportunities")
553
+ for q in questions:
554
+ st.write(f"β€’ {q}")
555
+
556
+ def display_voice_search_results(self, result):
557
+ """Display voice search optimization results"""
558
+ st.markdown("### 🎀 Voice Search Optimization")
559
+
560
+ # Conversational score
561
+ conv_score = result.get('conversational_score', 0)
562
+ if conv_score:
563
+ st.metric("Conversational Score", f"{conv_score}/10")
564
+
565
+ # Question-answer pairs
566
+ qa_pairs = result.get('question_answer_pairs', [])
567
+ if qa_pairs:
568
+ st.markdown("#### ❓ Question-Answer Pairs")
569
+ for qa in qa_pairs:
570
+ st.write(f"**Q:** {qa.get('question', '')}")
571
+ st.write(f"**A:** {qa.get('answer', '')}")
572
+ st.write("---")
573
+
574
+ # Featured snippet candidates
575
+ snippets = result.get('featured_snippet_candidates', [])
576
+ if snippets:
577
+ st.markdown("#### 🌟 Featured Snippet Candidates")
578
+ for i, snippet in enumerate(snippets, 1):
579
+ st.write(f"**{i}.** {snippet}")
580
+
581
+ # Voice optimized content
582
+ voice_content = result.get('voice_optimized_content', '')
583
+ if voice_content:
584
+ st.markdown("#### 🎀 Voice-Optimized Content")
585
+ st.text_area("Conversational version:", value=voice_content, height=200, key="voice_output")
586
+
587
+ def display_export_options(self, result, optimization_type, original_text):
588
+ """Display export options for results"""
589
+ st.markdown("### πŸ“₯ Export Results")
590
+
591
+ if st.button("πŸ“Š Generate Report", key="export_button"):
592
+ import time
593
+ export_data = {
594
+ 'timestamp': time.time(),
595
+ 'optimization_type': optimization_type,
596
+ 'original_text': original_text,
597
+ 'original_word_count': len(original_text.split()),
598
+ 'results': result
599
+ }
600
+
601
+ st.download_button(
602
+ label="Download Analysis Report",
603
+ data=json.dumps(export_data, indent=2),
604
+ file_name=f"{optimization_type}_analysis_{int(time.time())}.json",
605
+ mime="application/json"
606
+ )
607
 
608
  def render_website_analysis_tab(self):
609
  """Render Website GEO Analysis tab"""