Update app.py
Browse files
app.py
CHANGED
@@ -806,6 +806,19 @@ with gr.Blocks(theme=gr.themes.Soft()) as app:
|
|
806 |
if __name__ == "__main__":
|
807 |
app.launch(share=True)'''
|
808 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
809 |
import gradio as gr
|
810 |
import os
|
811 |
import time
|
@@ -822,27 +835,19 @@ load_dotenv()
|
|
822 |
# Configuration
|
823 |
HF_TOKEN = os.getenv("HF_TOKEN")
|
824 |
HF_USERNAME = "jsakshi"
|
825 |
-
AUTHOR_NAME = "Sarah Johnson"
|
826 |
HEADERS = {"Authorization": f"Bearer {HF_TOKEN}"}
|
827 |
|
828 |
def generate_blog_content(topic, seo_keywords):
|
829 |
try:
|
830 |
-
prompt = f"""Write a high-quality
|
831 |
-
|
832 |
-
-
|
833 |
-
-
|
834 |
-
- Use subheadings, bullet points, and real-world examples
|
835 |
-
- Bold 3-5 key terms using **bold** formatting
|
836 |
-
- Include: "This article was written by {AUTHOR_NAME}, combining research and industry expertise"
|
837 |
- SEO keywords: {', '.join(seo_keywords)}
|
838 |
-
-
|
839 |
-
-
|
840 |
-
|
841 |
-
2. 3-5 main sections with clear subheadings
|
842 |
-
3. Practical advice/actionable takeaways
|
843 |
-
4. Conclusion with thought-provoking question
|
844 |
-
|
845 |
-
Make it flow naturally with varied sentence structure. Avoid markdown formatting except for bolding."""
|
846 |
|
847 |
response = requests.post(
|
848 |
"https://api-inference.huggingface.co/models/mistralai/Mistral-7B-Instruct-v0.2",
|
@@ -854,142 +859,131 @@ def generate_blog_content(topic, seo_keywords):
|
|
854 |
return None, f"API Error: {response.text}"
|
855 |
|
856 |
blog_text = response.json()[0]['generated_text']
|
|
|
857 |
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
|
863 |
|
864 |
except Exception as e:
|
865 |
return None, f"Error: {str(e)}"
|
866 |
|
867 |
-
def
|
868 |
-
|
869 |
-
|
870 |
-
|
871 |
-
|
872 |
-
|
873 |
-
# Extract title and subtitle
|
874 |
-
lines = blog_text.split('\n')
|
875 |
-
title = lines[0].strip().replace('#', '').strip()
|
876 |
-
subtitle = next((line.strip() for line in lines[1:10] if line.strip() and not line.startswith('#')), "In-Depth Analysis")
|
877 |
-
|
878 |
-
# Find key points for bold formatting
|
879 |
-
bold_terms = list(set(re.findall(r'\*\*(.*?)\*\*', blog_text)))
|
880 |
-
|
881 |
-
return {
|
882 |
-
"title": title,
|
883 |
-
"subtitle": subtitle,
|
884 |
-
"content": blog_text,
|
885 |
-
"bold_terms": bold_terms[:5]
|
886 |
-
}
|
887 |
|
888 |
def create_hosted_blog(topic, seo_keywords):
|
889 |
try:
|
890 |
-
# Generate
|
891 |
content_data, error = generate_blog_content(topic, seo_keywords)
|
892 |
if error:
|
893 |
return f"Error: {error}", ""
|
894 |
|
895 |
-
# Create space
|
896 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
897 |
|
898 |
-
#
|
899 |
-
|
900 |
-
|
|
|
901 |
<head>
|
902 |
-
<meta charset="UTF-8">
|
903 |
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
904 |
<title>{content_data['title']}</title>
|
905 |
-
<meta name="description" content="{content_data['subtitle']}">
|
906 |
-
<meta name="keywords" content="{', '.join(seo_keywords)}">
|
907 |
-
<meta name="author" content="{AUTHOR_NAME}">
|
908 |
-
<!-- Keep previous styles, add these enhancements -->
|
909 |
<style>
|
910 |
-
|
911 |
-
|
912 |
-
|
913 |
-
|
914 |
-
|
915 |
-
|
916 |
-
|
917 |
-
|
918 |
-
|
919 |
-
|
920 |
-
|
921 |
-
|
922 |
-
|
923 |
-
|
924 |
-
|
925 |
-
|
926 |
-
|
927 |
-
|
928 |
-
|
929 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
930 |
}}
|
931 |
-
/* Keep previous styles */
|
932 |
</style>
|
933 |
</head>
|
934 |
<body>
|
935 |
-
<header
|
936 |
-
|
|
|
937 |
<div class="container">
|
938 |
-
|
939 |
-
<article class="main-content">
|
940 |
-
<div class="author-bio">
|
941 |
-
<img src="author-placeholder.png" alt="{AUTHOR_NAME}" class="author-img">
|
942 |
-
<div>
|
943 |
-
<h4>{AUTHOR_NAME}</h4>
|
944 |
-
<p>Industry expert with 10+ years experience in {topic.split()[-1]}</p>
|
945 |
-
</div>
|
946 |
-
</div>
|
947 |
-
|
948 |
-
<div class="key-terms">
|
949 |
-
<h4>Key Terms in This Article:</h4>
|
950 |
-
<p>{', '.join(content_data['bold_terms'])}</p>
|
951 |
-
</div>
|
952 |
-
|
953 |
-
<!-- Content sections -->
|
954 |
-
{process_content(content_data['content'])}
|
955 |
-
|
956 |
-
<!-- Keep footer and other elements -->
|
957 |
-
</article>
|
958 |
-
</div>
|
959 |
</div>
|
|
|
|
|
|
|
960 |
</body>
|
961 |
</html>
|
962 |
"""
|
963 |
-
|
964 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
965 |
|
|
|
|
|
966 |
except Exception as e:
|
967 |
return f"Error: {str(e)}", ""
|
968 |
|
969 |
-
|
970 |
-
|
971 |
-
|
972 |
-
return markdown.markdown(content)
|
973 |
-
|
974 |
-
# Enhanced Gradio UI
|
975 |
-
with gr.Blocks(theme=gr.themes.Soft()) as app:
|
976 |
-
gr.Markdown("# ✍️ Human-Written Blog Generator")
|
977 |
-
gr.Markdown("Create authentic, SEO-optimized articles that read like human-written content")
|
978 |
|
979 |
with gr.Row():
|
980 |
with gr.Column():
|
981 |
-
topic_input = gr.Textbox(label="
|
982 |
-
|
983 |
-
|
984 |
-
placeholder="AI sustainability, green tech, eco-friendly AI")
|
985 |
-
generate_btn = gr.Button("Create Article", variant="primary")
|
986 |
|
987 |
with gr.Column():
|
988 |
-
gr.Markdown("### Live Blog URL")
|
989 |
blog_link = gr.Markdown()
|
990 |
-
gr.Markdown("### Content Preview")
|
991 |
blog_output = gr.Markdown()
|
992 |
-
status = gr.Textbox(label="Generation Status")
|
993 |
|
994 |
generate_btn.click(
|
995 |
fn=create_hosted_blog,
|
@@ -998,4 +992,4 @@ with gr.Blocks(theme=gr.themes.Soft()) as app:
|
|
998 |
)
|
999 |
|
1000 |
if __name__ == "__main__":
|
1001 |
-
app.launch(share=True)
|
|
|
806 |
if __name__ == "__main__":
|
807 |
app.launch(share=True)'''
|
808 |
|
809 |
+
|
810 |
+
|
811 |
+
|
812 |
+
|
813 |
+
|
814 |
+
|
815 |
+
|
816 |
+
|
817 |
+
|
818 |
+
|
819 |
+
|
820 |
+
|
821 |
+
|
822 |
import gradio as gr
|
823 |
import os
|
824 |
import time
|
|
|
835 |
# Configuration
|
836 |
HF_TOKEN = os.getenv("HF_TOKEN")
|
837 |
HF_USERNAME = "jsakshi"
|
838 |
+
AUTHOR_NAME = "Sarah Johnson"
|
839 |
HEADERS = {"Authorization": f"Bearer {HF_TOKEN}"}
|
840 |
|
841 |
def generate_blog_content(topic, seo_keywords):
|
842 |
try:
|
843 |
+
prompt = f"""Write a high-quality blog post about {topic} that sounds human-written. Include:
|
844 |
+
- Engaging introduction with a hook
|
845 |
+
- 3-5 main sections with subheadings
|
846 |
+
- Bold key terms using **bold**
|
|
|
|
|
|
|
847 |
- SEO keywords: {', '.join(seo_keywords)}
|
848 |
+
- Conclusion with actionable advice
|
849 |
+
- Author attribution for {AUTHOR_NAME}
|
850 |
+
Avoid AI-sounding language. Use conversational tone."""
|
|
|
|
|
|
|
|
|
|
|
851 |
|
852 |
response = requests.post(
|
853 |
"https://api-inference.huggingface.co/models/mistralai/Mistral-7B-Instruct-v0.2",
|
|
|
859 |
return None, f"API Error: {response.text}"
|
860 |
|
861 |
blog_text = response.json()[0]['generated_text']
|
862 |
+
blog_text += f"\n\n*This article was written by {AUTHOR_NAME}, combining research and practical experience.*"
|
863 |
|
864 |
+
return {
|
865 |
+
"title": extract_title(blog_text),
|
866 |
+
"content": blog_text,
|
867 |
+
"bold_terms": re.findall(r'\*\*(.*?)\*\*', blog_text)
|
868 |
+
}, None
|
869 |
|
870 |
except Exception as e:
|
871 |
return None, f"Error: {str(e)}"
|
872 |
|
873 |
+
def extract_title(text):
|
874 |
+
lines = text.split('\n')
|
875 |
+
for line in lines:
|
876 |
+
if line.strip() and not line.startswith('#'):
|
877 |
+
return line.strip().replace('#', '')
|
878 |
+
return "Professional Analysis"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
879 |
|
880 |
def create_hosted_blog(topic, seo_keywords):
|
881 |
try:
|
882 |
+
# Generate content
|
883 |
content_data, error = generate_blog_content(topic, seo_keywords)
|
884 |
if error:
|
885 |
return f"Error: {error}", ""
|
886 |
|
887 |
+
# Create space
|
888 |
+
space_id = f"blog-{uuid.uuid4().hex[:8]}"
|
889 |
+
space_name = f"{HF_USERNAME}/{space_id}"
|
890 |
+
api = HfApi(token=HF_TOKEN)
|
891 |
+
api.create_repo(
|
892 |
+
repo_id=space_name,
|
893 |
+
repo_type="space",
|
894 |
+
space_sdk="static",
|
895 |
+
private=False
|
896 |
+
)
|
897 |
|
898 |
+
# Create HTML with improved styling
|
899 |
+
html_content = f"""
|
900 |
+
<!DOCTYPE html>
|
901 |
+
<html>
|
902 |
<head>
|
|
|
|
|
903 |
<title>{content_data['title']}</title>
|
|
|
|
|
|
|
|
|
904 |
<style>
|
905 |
+
body {{
|
906 |
+
font-family: Arial, sans-serif;
|
907 |
+
line-height: 1.6;
|
908 |
+
background-color: #f4f4f4;
|
909 |
+
color: #333;
|
910 |
+
margin: 0;
|
911 |
+
padding: 0;
|
912 |
+
}}
|
913 |
+
.container {{
|
914 |
+
width: 80%;
|
915 |
+
margin: auto;
|
916 |
+
overflow: hidden;
|
917 |
+
background: white;
|
918 |
+
padding: 20px;
|
919 |
+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
920 |
+
border-radius: 10px;
|
921 |
+
}}
|
922 |
+
h1, h2, h3 {{
|
923 |
+
color: #222;
|
924 |
+
}}
|
925 |
+
header {{
|
926 |
+
background: linear-gradient(135deg, #ff7e5f, #feb47b);
|
927 |
+
color: white;
|
928 |
+
padding: 20px 0;
|
929 |
+
text-align: center;
|
930 |
+
border-radius: 10px 10px 0 0;
|
931 |
+
}}
|
932 |
+
footer {{
|
933 |
+
text-align: center;
|
934 |
+
padding: 10px;
|
935 |
+
background: #222;
|
936 |
+
color: white;
|
937 |
+
margin-top: 20px;
|
938 |
+
border-radius: 0 0 10px 10px;
|
939 |
+
}}
|
940 |
+
img {{
|
941 |
+
width: 100%;
|
942 |
+
border-radius: 10px;
|
943 |
+
margin-bottom: 10px;
|
944 |
}}
|
|
|
945 |
</style>
|
946 |
</head>
|
947 |
<body>
|
948 |
+
<header>
|
949 |
+
<h1>{content_data['title']}</h1>
|
950 |
+
</header>
|
951 |
<div class="container">
|
952 |
+
{markdown.markdown(content_data['content'])}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
953 |
</div>
|
954 |
+
<footer>
|
955 |
+
<p>© 2025 {AUTHOR_NAME}. All Rights Reserved.</p>
|
956 |
+
</footer>
|
957 |
</body>
|
958 |
</html>
|
959 |
"""
|
960 |
+
|
961 |
+
# Upload HTML
|
962 |
+
upload_file(
|
963 |
+
path_or_fileobj=html_content.encode(),
|
964 |
+
path_in_repo="index.html",
|
965 |
+
repo_id=space_name,
|
966 |
+
repo_type="space"
|
967 |
+
)
|
968 |
|
969 |
+
return f"https://huggingface.co/spaces/{space_name}", content_data['content']
|
970 |
+
|
971 |
except Exception as e:
|
972 |
return f"Error: {str(e)}", ""
|
973 |
|
974 |
+
# Gradio interface
|
975 |
+
with gr.Blocks() as app:
|
976 |
+
gr.Markdown("# Professional Blog Generator")
|
|
|
|
|
|
|
|
|
|
|
|
|
977 |
|
978 |
with gr.Row():
|
979 |
with gr.Column():
|
980 |
+
topic_input = gr.Textbox(label="Topic")
|
981 |
+
seo_input = gr.Textbox(label="SEO Keywords (comma-separated)")
|
982 |
+
generate_btn = gr.Button("Generate", variant="primary")
|
|
|
|
|
983 |
|
984 |
with gr.Column():
|
|
|
985 |
blog_link = gr.Markdown()
|
|
|
986 |
blog_output = gr.Markdown()
|
|
|
987 |
|
988 |
generate_btn.click(
|
989 |
fn=create_hosted_blog,
|
|
|
992 |
)
|
993 |
|
994 |
if __name__ == "__main__":
|
995 |
+
app.launch(share=True)
|