jsakshi commited on
Commit
3a37236
·
verified ·
1 Parent(s): 8255e46

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +467 -1
app.py CHANGED
@@ -163,7 +163,7 @@ with gr.Blocks(title="AI Blog Generator", theme=gr.themes.Soft()) as app:
163
  if __name__ == "__main__":
164
  app.launch(share=False)'''
165
 
166
- import gradio as gr
167
  import os
168
  import time
169
  import requests
@@ -337,5 +337,471 @@ with gr.Blocks(theme=gr.themes.Soft()) as app:
337
  outputs=[blog_link, blog_output]
338
  )
339
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
340
  if __name__ == "__main__":
341
  app.launch(share=True)
 
163
  if __name__ == "__main__":
164
  app.launch(share=False)'''
165
 
166
+ '''import gradio as gr
167
  import os
168
  import time
169
  import requests
 
337
  outputs=[blog_link, blog_output]
338
  )
339
 
340
+ if __name__ == "__main__":
341
+ app.launch(share=True)'''
342
+
343
+
344
+ import gradio as gr
345
+ import os
346
+ import time
347
+ import requests
348
+ import re
349
+ import uuid
350
+ import markdown
351
+ from datetime import datetime
352
+ from dotenv import load_dotenv
353
+ from huggingface_hub import HfApi, upload_file
354
+
355
+ load_dotenv()
356
+
357
+ # Configuration
358
+ HF_TOKEN = os.getenv("HF_TOKEN")
359
+ HF_USERNAME = "jsakshi"
360
+ HEADERS = {"Authorization": f"Bearer {HF_TOKEN}"}
361
+
362
+ def generate_blog_content(topic):
363
+ try:
364
+ prompt = f"""Create a detailed, professional blog post about {topic} including:
365
+ - A compelling title and subtitle
366
+ - An introduction
367
+ - 3 main sections with descriptive headings
368
+ - Key points and data examples in each section
369
+ - A conclusion
370
+ Use an informative, professional tone."""
371
+
372
+ response = requests.post(
373
+ "https://api-inference.huggingface.co/models/mistralai/Mistral-7B-Instruct-v0.2",
374
+ headers=HEADERS,
375
+ json={"inputs": prompt, "parameters": {"max_length": 2000}}
376
+ )
377
+
378
+ if response.status_code != 200:
379
+ return None, f"API Error: {response.text}"
380
+
381
+ blog_text = response.json()[0]['generated_text']
382
+
383
+ # Extract title (assuming first line contains the title)
384
+ lines = blog_text.split('\n')
385
+ title = topic
386
+ subtitle = "A comprehensive analysis and exploration"
387
+
388
+ for line in lines[:5]:
389
+ if line.strip() and not line.startswith('#'):
390
+ title = line.strip()
391
+ break
392
+
393
+ # Look for a possible subtitle
394
+ for line in lines[1:10]:
395
+ if line.strip() and line != title and not line.startswith('#'):
396
+ subtitle = line.strip()
397
+ break
398
+
399
+ return {
400
+ "title": title,
401
+ "subtitle": subtitle,
402
+ "content": blog_text
403
+ }, None
404
+
405
+ except Exception as e:
406
+ return None, f"Error: {str(e)}"
407
+
408
+ def create_hosted_blog(topic):
409
+ try:
410
+ # Generate blog content first
411
+ content_data, error = generate_blog_content(topic)
412
+ if error or not content_data:
413
+ return f"Error generating content: {error}", ""
414
+
415
+ # Create unique space
416
+ space_id = f"blog-{uuid.uuid4().hex[:8]}"
417
+ space_name = f"{HF_USERNAME}/{space_id}"
418
+
419
+ # Initialize Hub API
420
+ api = HfApi(token=HF_TOKEN)
421
+ api.create_repo(
422
+ repo_id=space_name,
423
+ repo_type="space",
424
+ space_sdk="static",
425
+ private=False
426
+ )
427
+
428
+ # Generate and upload images
429
+ image_paths = []
430
+ image_prompts = [
431
+ f"Professional illustration about {topic}, clean design, minimalist style",
432
+ f"Data visualization or concept diagram related to {topic}, professional look"
433
+ ]
434
+
435
+ for idx, img_prompt in enumerate(image_prompts):
436
+ response = requests.post(
437
+ "https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-xl-base-1.0",
438
+ headers=HEADERS,
439
+ json={"inputs": img_prompt}
440
+ )
441
+ if response.status_code == 200:
442
+ img_filename = f"image_{idx}.png"
443
+ upload_file(
444
+ path_or_fileobj=response.content,
445
+ path_in_repo=img_filename,
446
+ repo_id=space_name,
447
+ repo_type="space"
448
+ )
449
+ image_paths.append(img_filename)
450
+ time.sleep(2) # Add delay to prevent rate limiting
451
+
452
+ # Format the current date
453
+ current_date = datetime.now().strftime("%B %d, %Y")
454
+
455
+ # Create HTML using the modern template from the example
456
+ title = content_data.get("title", topic)
457
+ subtitle = content_data.get("subtitle", "A comprehensive analysis")
458
+ content = content_data.get("content", "")
459
+
460
+ # Process the content to get sections for TOC
461
+ sections = []
462
+ section_pattern = re.compile(r'^##?\s+(.+)$', re.MULTILINE)
463
+ section_matches = section_pattern.findall(content)
464
+
465
+ for i, section in enumerate(section_matches[:6]):
466
+ section_id = section.lower().replace(' ', '-').replace(':', '')
467
+ sections.append({
468
+ "title": section,
469
+ "id": section_id
470
+ })
471
+
472
+ # Convert markdown content to HTML with proper section IDs
473
+ html_content = content
474
+ for section in sections:
475
+ pattern = f"## {section['title']}"
476
+ replacement = f"<h2 id=\"{section['id']}\">{section['title']}</h2>"
477
+ html_content = html_content.replace(pattern, replacement)
478
+
479
+ html_content = markdown.markdown(html_content)
480
+
481
+ # Create complete HTML
482
+ complete_html = f"""<!DOCTYPE html>
483
+ <html lang="en">
484
+ <head>
485
+ <meta charset="UTF-8">
486
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
487
+ <title>{title}</title>
488
+ <style>
489
+ :root {{
490
+ --primary-color: #2D68C4;
491
+ --secondary-color: #f8f9fa;
492
+ --text-color: #333;
493
+ --light-gray: #e9ecef;
494
+ --dark-gray: #495057;
495
+ }}
496
+
497
+ * {{
498
+ margin: 0;
499
+ padding: 0;
500
+ box-sizing: border-box;
501
+ }}
502
+
503
+ body {{
504
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
505
+ line-height: 1.6;
506
+ color: var(--text-color);
507
+ background-color: #fff;
508
+ }}
509
+
510
+ header {{
511
+ background: linear-gradient(135deg, var(--primary-color), #1d4ed8);
512
+ color: white;
513
+ padding: 2rem 0;
514
+ text-align: center;
515
+ }}
516
+
517
+ .container {{
518
+ max-width: 1200px;
519
+ margin: 0 auto;
520
+ padding: 0 2rem;
521
+ }}
522
+
523
+ .blog-header {{
524
+ display: flex;
525
+ flex-direction: column;
526
+ align-items: center;
527
+ }}
528
+
529
+ .blog-title {{
530
+ font-size: 2.5rem;
531
+ margin-bottom: 1rem;
532
+ }}
533
+
534
+ .blog-subtitle {{
535
+ font-size: 1.2rem;
536
+ opacity: 0.9;
537
+ }}
538
+
539
+ .blog-meta {{
540
+ display: flex;
541
+ margin-top: 1rem;
542
+ font-size: 0.9rem;
543
+ }}
544
+
545
+ .blog-meta div {{
546
+ margin-right: 1.5rem;
547
+ display: flex;
548
+ align-items: center;
549
+ }}
550
+
551
+ .blog-content {{
552
+ display: grid;
553
+ grid-template-columns: 1fr;
554
+ gap: 2rem;
555
+ margin: 3rem 0;
556
+ }}
557
+
558
+ @media (min-width: 768px) {{
559
+ .blog-content {{
560
+ grid-template-columns: 7fr 3fr;
561
+ }}
562
+ }}
563
+
564
+ .main-content {{
565
+ background-color: white;
566
+ border-radius: 8px;
567
+ box-shadow: 0 4px 6px rgba(0,0,0,0.05);
568
+ padding: 2rem;
569
+ }}
570
+
571
+ .sidebar {{
572
+ position: sticky;
573
+ top: 2rem;
574
+ height: fit-content;
575
+ }}
576
+
577
+ .sidebar-section {{
578
+ background-color: white;
579
+ border-radius: 8px;
580
+ box-shadow: 0 4px 6px rgba(0,0,0,0.05);
581
+ padding: 1.5rem;
582
+ margin-bottom: 2rem;
583
+ }}
584
+
585
+ .sidebar-title {{
586
+ font-size: 1.2rem;
587
+ margin-bottom: 1rem;
588
+ padding-bottom: 0.5rem;
589
+ border-bottom: 2px solid var(--light-gray);
590
+ }}
591
+
592
+ .toc-list {{
593
+ list-style: none;
594
+ }}
595
+
596
+ .toc-list li {{
597
+ margin-bottom: 0.5rem;
598
+ }}
599
+
600
+ .toc-list a {{
601
+ color: var(--primary-color);
602
+ text-decoration: none;
603
+ }}
604
+
605
+ .toc-list a:hover {{
606
+ text-decoration: underline;
607
+ }}
608
+
609
+ h1, h2, h3, h4 {{
610
+ margin: 1.5rem 0 1rem 0;
611
+ line-height: 1.3;
612
+ }}
613
+
614
+ h1 {{
615
+ font-size: 2rem;
616
+ }}
617
+
618
+ h2 {{
619
+ font-size: 1.75rem;
620
+ border-bottom: 2px solid var(--light-gray);
621
+ padding-bottom: 0.5rem;
622
+ }}
623
+
624
+ h3 {{
625
+ font-size: 1.4rem;
626
+ }}
627
+
628
+ p {{
629
+ margin-bottom: 1.5rem;
630
+ }}
631
+
632
+ .blog-image {{
633
+ width: 100%;
634
+ height: auto;
635
+ border-radius: 8px;
636
+ margin: 1.5rem 0;
637
+ }}
638
+
639
+ .highlight-box {{
640
+ background-color: var(--secondary-color);
641
+ border-left: 4px solid var(--primary-color);
642
+ padding: 1.5rem;
643
+ margin: 1.5rem 0;
644
+ border-radius: 0 8px 8px 0;
645
+ }}
646
+
647
+ .highlight-box h4 {{
648
+ margin-top: 0;
649
+ color: var(--primary-color);
650
+ }}
651
+
652
+ footer {{
653
+ background-color: var(--dark-gray);
654
+ color: white;
655
+ padding: 2rem 0;
656
+ margin-top: 3rem;
657
+ }}
658
+
659
+ .footer-content {{
660
+ display: flex;
661
+ flex-direction: column;
662
+ align-items: center;
663
+ text-align: center;
664
+ }}
665
+
666
+ @media (min-width: 768px) {{
667
+ .footer-content {{
668
+ flex-direction: row;
669
+ justify-content: space-between;
670
+ text-align: left;
671
+ }}
672
+ }}
673
+
674
+ .footer-links {{
675
+ list-style: none;
676
+ display: flex;
677
+ margin-top: 1rem;
678
+ }}
679
+
680
+ .footer-links li {{
681
+ margin-right: 1rem;
682
+ }}
683
+
684
+ .footer-links a {{
685
+ color: white;
686
+ text-decoration: none;
687
+ }}
688
+
689
+ .footer-links a:hover {{
690
+ text-decoration: underline;
691
+ }}
692
+ </style>
693
+ </head>
694
+ <body>
695
+ <header>
696
+ <div class="container">
697
+ <div class="blog-header">
698
+ <h1 class="blog-title">{title}</h1>
699
+ <p class="blog-subtitle">{subtitle}</p>
700
+ <div class="blog-meta">
701
+ <div>Published: {current_date}</div>
702
+ <div>Reading time: 8 minutes</div>
703
+ </div>
704
+ </div>
705
+ </div>
706
+ </header>
707
+
708
+ <div class="container">
709
+ <div class="blog-content">
710
+ <article class="main-content">
711
+ {f'<img src="{image_paths[0]}" alt="{topic} illustration" class="blog-image" />' if image_paths else ''}
712
+
713
+ {html_content}
714
+
715
+ {f'<img src="{image_paths[1]}" alt="{topic} visualization" class="blog-image" />' if len(image_paths) > 1 else ''}
716
+
717
+ <div class="highlight-box">
718
+ <h4>Key Takeaways</h4>
719
+ <p>This article explores the essential aspects of {topic}, providing insights into current trends, challenges, and future opportunities in this field.</p>
720
+ </div>
721
+ </article>
722
+
723
+ <aside class="sidebar">
724
+ <div class="sidebar-section">
725
+ <h3 class="sidebar-title">Table of Contents</h3>
726
+ <ul class="toc-list">
727
+ {''.join([f'<li><a href="#{section["id"]}">{section["title"]}</a></li>' for section in sections])}
728
+ </ul>
729
+ </div>
730
+
731
+ <div class="sidebar-section">
732
+ <h3 class="sidebar-title">About the Author</h3>
733
+ <p>This article was created by our AI content system that combines research, writing, and design capabilities to produce comprehensive, informative content on cutting-edge topics.</p>
734
+ </div>
735
+
736
+ <div class="sidebar-section">
737
+ <h3 class="sidebar-title">Related Topics</h3>
738
+ <ul class="toc-list">
739
+ <li><a href="#">Latest Developments in {topic}</a></li>
740
+ <li><a href="#">Industry Perspectives on {topic}</a></li>
741
+ <li><a href="#">Research Advancements in {topic}</a></li>
742
+ <li><a href="#">Case Studies: {topic} in Action</a></li>
743
+ </ul>
744
+ </div>
745
+ </aside>
746
+ </div>
747
+ </div>
748
+
749
+ <footer>
750
+ <div class="container">
751
+ <div class="footer-content">
752
+ <div>
753
+ <p>&copy; {datetime.now().year} Professional Blog Hub</p>
754
+ <p>Created with AI Blog Generator</p>
755
+ </div>
756
+ <ul class="footer-links">
757
+ <li><a href="#">Home</a></li>
758
+ <li><a href="#">About</a></li>
759
+ <li><a href="#">Topics</a></li>
760
+ <li><a href="#">Contact</a></li>
761
+ </ul>
762
+ </div>
763
+ </div>
764
+ </footer>
765
+ </body>
766
+ </html>
767
+ """
768
+
769
+ # Upload HTML file
770
+ upload_file(
771
+ path_or_fileobj=complete_html.encode(),
772
+ path_in_repo="index.html",
773
+ repo_id=space_name,
774
+ repo_type="space"
775
+ )
776
+
777
+ return f"https://huggingface.co/spaces/{space_name}", content_data.get("content", "")
778
+
779
+ except Exception as e:
780
+ return f"Error: {str(e)}", ""
781
+
782
+ # Gradio interface
783
+ with gr.Blocks(theme=gr.themes.Soft()) as app:
784
+ gr.Markdown("# 📄 Professional Blog Generator")
785
+ gr.Markdown("Create well-structured, professional blog posts with just a topic")
786
+
787
+ with gr.Row():
788
+ with gr.Column():
789
+ topic_input = gr.Textbox(label="Enter Blog Topic",
790
+ placeholder="e.g., Future of AI in Healthcare")
791
+ generate_btn = gr.Button("Generate Blog", variant="primary")
792
+ status = gr.Textbox(label="Status", interactive=False)
793
+
794
+ with gr.Column():
795
+ gr.Markdown("### Blog URL")
796
+ blog_link = gr.Markdown("Your blog link will appear here...")
797
+ gr.Markdown("### Preview")
798
+ blog_output = gr.Markdown()
799
+
800
+ generate_btn.click(
801
+ fn=create_hosted_blog,
802
+ inputs=topic_input,
803
+ outputs=[blog_link, blog_output]
804
+ )
805
+
806
  if __name__ == "__main__":
807
  app.launch(share=True)