Spaces:
Sleeping
Sleeping
| """ | |
| π 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) |