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)