Spaces:
Running
Running
File size: 11,496 Bytes
6217602 d035275 6217602 d035275 6217602 d035275 6217602 d035275 6217602 d035275 6217602 d035275 6217602 d035275 6217602 d035275 6217602 d035275 6217602 d035275 6217602 d035275 6217602 d035275 6217602 d035275 6217602 d035275 6217602 d035275 6217602 d035275 |
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 |
"""
π The Content Creator's Journey (AI-Powered Edition)
==================================================
This version replaces all mocked functions with real generative AI models
for image analysis, content generation, and translation.
- Stage 1: Inspiration Hub (Summarization AI)
- Stage 2: Creative Studio (Image-to-Text and Text Generation AI)
- Stage 3: Globalization Suite (Translation AI)
Author: Gemini
Date: July 4, 2025
"""
import os
import re
import gradio as gr
import arxiv
import nltk
from transformers import pipeline
from youtube_transcript_api import YouTubeTranscriptApi, NoTranscriptFound
from youtube_transcript_api.formatters import TextFormatter
from PIL import Image
# --- Model & Pipeline Setup (Lazy Loading) ---
# Dictionary to hold our models, loaded only when needed.
models = {}
def get_pipeline(task, model_name):
"""Initializes and returns a pipeline, caching it for reuse."""
if model_name not in models:
print(f"π Initializing {task} pipeline with model {model_name}...")
models[model_name] = pipeline(task, model=model_name)
print(f"β
{model_name} loaded.")
return models[model_name]
# --- Stage 1: The Spark (Inspiration Hub) ---
# This section already uses a real summarization model, so no changes are needed here.
# (Functions search_arxiv_papers and summarize_youtube_from_url are omitted for brevity but remain the same)
# ... (Previous code for Stage 1 remains here) ...
# --- Stage 2: The Craft (Creative Studio) ---
def analyze_image_with_ai(image: Image.Image) -> (str, dict):
"""Uses a real AI model to generate a description of the image."""
captioner = get_pipeline("image-to-text", "Salesforce/blip-image-captioning-large")
description = captioner(image)[0]['generated_text']
analysis = {"description": description}
report = (
f"**π¨ AI Vision Analysis:**\n\n"
f"- **Image Content:** {description}"
)
return report, analysis
def generate_creative_content_with_ai(style: str, audience: str, image_analysis: dict, custom_prompt: str) -> (str, str):
"""Uses a real LLM to generate content based on a detailed prompt."""
generator = get_pipeline("text-generation", "gpt2")
image_desc = image_analysis.get("description", "a visual scene")
# Create a detailed prompt for the LLM
prompt = (
f"Create a '{style}' for a '{audience}' audience. "
f"The content should be inspired by the following scene: '{image_desc}'. "
f"Follow this specific instruction: '{custom_prompt if custom_prompt else 'Be creative and engaging'}'.\n\n"
f"Here is the content:"
)
# Generate text and clean it up
generated_outputs = generator(prompt, max_length=150, num_return_sequences=1, pad_token_id=generator.tokenizer.eos_token_id)
generated_text = generated_outputs[0]['generated_text']
# Clean the output by removing the initial prompt
clean_text = generated_text.replace(prompt, "").strip()
# The analytics are now informational rather than predictive
analytics_report = (
f"**π Generation Details:**\n\n"
f"- **Model Used:** gpt2\n"
f"- **Core Prompt:** Based on a photo of '{image_desc[:40]}...'"
)
return clean_text, analytics_report
def run_creative_studio(uploaded_image, style, audience, custom_prompt):
"""Interface function to run the full AI-powered 'Craft' stage."""
if uploaded_image is None:
return "β Please upload an image.", "", ""
try:
image = uploaded_image
analysis_report, image_analysis = analyze_image_with_ai(image)
generated_text, analytics = generate_creative_content_with_ai(style, audience, image_analysis, custom_prompt)
return analysis_report, generated_text, analytics
except Exception as e:
return f"β οΈ Error: {e}", "", ""
# --- Stage 3: The Reach (Globalization Suite) ---
def translate_content_with_ai(text: str, languages: list) -> str:
"""Translates content using real AI models."""
if not text:
return "β Please provide text to translate."
if not languages:
return "β Please select at least one language."
lang_model_map = {
"German π©πͺ": "Helsinki-NLP/opus-mt-en-de",
"Spanish πͺπΈ": "Helsinki-NLP/opus-mt-en-es",
"Japanese π―π΅": "Helsinki-NLP/opus-mt-en-jap",
}
translations = [f"### π Translated Content\n"]
for lang_name in languages:
model_name = lang_model_map.get(lang_name)
if model_name:
translator = get_pipeline("translation", model_name)
translated_text = translator(text)[0]['translation_text']
translations.append(f"**{lang_name.upper()} VERSION:**\n\n{translated_text}")
return "\n\n---\n\n".join(translations)
# --- Full Gradio UI ---
# The UI structure remains the same, but the functions it calls are now AI-powered.
# The code for create_ui(), search_arxiv_papers, and summarize_youtube_from_url is omitted here
# for brevity, as it doesn't change from the previous version. You can just plug the
# new functions above into your existing app.py file.
# --- Helper functions from previous version to make the file runnable ---
def search_arxiv_papers(topic: str) -> str:
if not topic: return "β Please enter a topic to search."
summarizer = get_pipeline("summarization", "sshleifer/distilbart-cnn-12-6")
search = arxiv.Search(query=topic, max_results=3, sort_by=arxiv.SortCriterion.Relevance)
results = [f"**π {res.title}**\n\n**Summary:** {summarizer(res.summary.replace(' ', ' '), max_length=80, min_length=20, do_sample=False)[0]['summary_text']}\n\n**π [Read Paper]({res.pdf_url})**" for res in search.results()]
return "\n\n---\n\n".join(results) if results else "No papers found."
def summarize_youtube_from_url(video_url: str) -> str:
if not video_url: return "β Please enter a YouTube URL."
video_id_match = re.search(r"(?:v=|\/)([0-9A-Za-z_-]{11}).*", video_url)
if not video_id_match: return "β Invalid YouTube URL."
video_id = video_id_match.group(1)
try:
transcript_list = YouTubeTranscriptApi.get_transcript(video_id)
transcript_text = " ".join([d['text'] for d in transcript_list])
if len(transcript_text) < 200: return "Transcript too short."
summarizer = get_pipeline("summarization", "sshleifer/distilbart-cnn-12-6")
summary = summarizer(transcript_text, max_length=100, min_length=30, do_sample=False)
return f"**β
Summary:**\n\n{summary[0]['summary_text']}"
except NoTranscriptFound: return "β No transcript available."
except Exception as e: return f"β οΈ Error: {e}"
def create_ui():
css = """.gradio-container { font-family: 'Inter', sans-serif; background: #f5f7fa; } .tab-item { background: white; border-radius: 12px; padding: 25px; border: 1px solid #e0e0e0; } footer { display: none !important }"""
with gr.Blocks(theme=gr.themes.Base(), css=css, title="The Content Creator's Journey") as app:
gr.Markdown("""<div style="text-align: center; padding: 20px; background: #1f2937; color: white; border-radius: 12px;"><h1 style="font-size: 2.5em; margin: 0; font-weight: 700;">π The Content Creator's Journey</h1><p style="font-size: 1.2em; margin-top: 5px;">From a spark of an idea to a global message, in three stages.</p></div>""")
with gr.Tabs() as tabs:
with gr.TabItem("1. The Spark: Inspiration Hub", id=0, elem_classes=["tab-item"]):
gr.Markdown("### Every great creation starts with an idea. Research any topic to get summarized insights from academia and popular culture.")
with gr.Row(variant="panel"):
with gr.Column(min_width=400):
gr.Markdown("#### π¬ Academic Insights (from arXiv)")
inspire_topic = gr.Textbox(label="Enter a Topic to Search Papers", placeholder="e.g., 'sustainable technology'")
arxiv_btn = gr.Button("Search arXiv")
inspire_arxiv_output = gr.Markdown()
with gr.Column(min_width=400):
gr.Markdown("#### πΊ Video Insights (from YouTube URL)")
inspire_yt_url = gr.Textbox(label="Paste a YouTube Video URL", placeholder="e.g., 'https://www.youtube.com/watch?v=...'")
yt_btn = gr.Button("Summarize Video")
inspire_yt_output = gr.Markdown()
arxiv_btn.click(fn=search_arxiv_papers, inputs=inspire_topic, outputs=inspire_arxiv_output)
yt_btn.click(fn=summarize_youtube_from_url, inputs=inspire_yt_url, outputs=inspire_yt_output)
with gr.TabItem("2. The Craft: Creative Studio", id=1, elem_classes=["tab-item"]):
gr.Markdown("### Transform your idea into a polished piece of content. Upload a visual anchor and let the AI help you write.")
with gr.Row(variant="panel"):
with gr.Column(scale=1):
craft_image = gr.Image(label="πΌοΈ Upload a Visual Anchor", type="pil")
craft_style = gr.Dropdown(choices=["βοΈ Blog Post", "π¬ Social Media Caption", "π‘ Video Script Hook"], value="βοΈ Blog Post", label="π Content Format")
craft_audience = gr.Dropdown(choices=["π Experts", "π§ General Audience", "π©βπ» Tech Enthusiasts"], value="π§ General Audience", label="π₯ Target Audience")
craft_prompt = gr.Textbox(label="π Key Message or Note", placeholder="e.g., 'Focus on the human element...'")
craft_btn = gr.Button("π¨ Craft My Content")
with gr.Column(scale=2):
craft_analysis_output = gr.Markdown(label="AI Vision Analysis")
craft_text_output = gr.Textbox(label="βοΈ Generated Content", lines=10)
craft_analytics_output = gr.Markdown(label="Performance Analytics")
craft_btn.click(fn=run_creative_studio, inputs=[craft_image, craft_style, craft_audience, craft_prompt], outputs=[craft_analysis_output, craft_text_output, craft_analytics_output])
with gr.TabItem("3. The Reach: Globalization Suite", id=2, elem_classes=["tab-item"]):
gr.Markdown("### Your masterpiece is ready. Now, adapt it for a global audience with our translation suite.")
with gr.Row(variant="panel"):
with gr.Column(scale=2):
reach_text_input = gr.Textbox(label="Paste Content Here (from Stage 2)", lines=8)
reach_lang_select = gr.CheckboxGroup(choices=["German π©πͺ", "Spanish πͺπΈ", "Japanese π―π΅"], label="π Select Languages")
reach_btn = gr.Button("π Globalize My Content")
with gr.Column(scale=3):
reach_output = gr.Markdown(label="Adapted for Global Audiences")
reach_btn.click(fn=translate_content_with_ai, inputs=[reach_text_input, reach_lang_select], outputs=reach_output)
return app
if __name__ == "__main__":
# To enable lazy loading of models, the UI is created first.
# The get_pipeline function will handle model loading upon first use.
app = create_ui()
app.launch(debug=True) |