CineAI commited on
Commit
6c153a2
Β·
verified Β·
1 Parent(s): 61970c0

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +214 -0
app.py ADDED
@@ -0,0 +1,214 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import time
3
+
4
+ import streamlit as st
5
+ from google import genai
6
+ from google.genai.types import Tool, GenerateContentConfig, GoogleSearch
7
+ import google.api_core
8
+
9
+ # --- Configuration ---
10
+ st.set_page_config(
11
+ page_title="AI Niche Content Idea Generator",
12
+ page_icon="πŸ’‘",
13
+ layout="centered",
14
+ )
15
+
16
+ # --- Patreon Link ---
17
+ PATREON_URL = "https://www.patreon.com/cineAI"
18
+
19
+ # --- Model List ---
20
+ FALLBACK_MODELS = [
21
+ "gemini-2.0-flash-thinking-exp-01-21",
22
+ "gemini-2.5-flash-preview-04-17",
23
+ "gemini-1.5-flash",
24
+ "gemini-1.5-pro",
25
+ "gemini-2.0-flash",
26
+ "gemini-2.0-flash-lite",
27
+ "gemini-2.5-pro-preview-03-25",
28
+ ]
29
+
30
+ # --- Authentication ---
31
+ api_key = ""
32
+ try:
33
+ api_key = st.secrets["GOOGLE_API_KEY"]
34
+ api_key_configured = True
35
+ except (KeyError, FileNotFoundError):
36
+ st.error("🚨 Google API Key not found! Please go to the settings, then find the `Variables and secrets` item and click `New secret`, insert your Google API key.")
37
+ api_key_configured = False
38
+ st.stop()
39
+
40
+ # --- Helper Function for API Call with Fallback & Advanced Mode ---
41
+ def generate_content_ideas(niche, audience, content_format, num_ideas=4, advanced_mode=False):
42
+ """Generates content ideas using Google Generative AI, with fallback and optional search."""
43
+ if not api_key_configured:
44
+ return "API Key not configured. Cannot proceed."
45
+
46
+ # --- Base Prompt ---
47
+ base_prompt = f"""
48
+ Act as an expert content strategist specializing in the niche: '{niche}'.
49
+ Your task is to generate {num_ideas} fresh, specific, and engaging content ideas tailored for the following target audience: '{audience}'.
50
+ The desired content format is: '{content_format}'.
51
+ Focus on providing unique angles, addressing potential pain points or interests of the audience, and suggesting topics that are relevant within the niche. Avoid generic ideas.
52
+ """
53
+
54
+ # --- Enhance Prompt for Advanced Mode ---
55
+ if advanced_mode:
56
+ prompt = base_prompt + f"""
57
+ **IMPORTANT: Leverage current information from the web using the available search tool** to identify *trending topics*, *recent developments*, or *very specific audience questions* within the '{niche}' niche related to the '{audience}' audience. Ground your ideas in potentially searchable, up-to-date information.
58
+ """
59
+ else:
60
+ prompt = base_prompt + """
61
+ Generate the ideas based on your general knowledge of the niche and audience.
62
+ """
63
+
64
+ # --- Add Formatting Instruction ---
65
+ prompt += """
66
+ Please format the output as a numbered list. Each idea should be concise but descriptive.
67
+ Example for niche 'Sustainable Gardening', audience 'Urban Beginners', format 'Blog Post Titles':
68
+ 1. 5 Easy-to-Grow Vegetables for Your Tiny Balcony Garden
69
+ 2. Composting in Apartments: A No-Smell Guide for City Dwellers
70
+ 3. Choosing the Right Recycled Pots for Your Indoor Plants
71
+ 4. How to Attract Pollinators to Your Urban Oasis
72
+ 5. Watering Wisely: Saving Water in Your Container Garden
73
+ Now, generate the ideas for the requested niche, audience, and format:
74
+ """
75
+
76
+ last_error = None
77
+ last_error_message = ""
78
+
79
+ # --- Tool Configuration ---
80
+ if advanced_mode:
81
+ google_search_tool = Tool(google_search=GoogleSearch())
82
+ config = GenerateContentConfig(
83
+ tools=[google_search_tool],
84
+ response_modalities=['TEXT'],
85
+ # system_instruction=system_instruction_google_search,
86
+ max_output_tokens=4100,
87
+ )
88
+ else:
89
+ config = None
90
+
91
+ tool_status_msg = " (Advanced Mode with Google Search πŸ”)" if advanced_mode else ""
92
+
93
+ for model_name in FALLBACK_MODELS:
94
+ st.info(f"🧠 Attempting generation with model: `{model_name}`{tool_status_msg}...")
95
+ try:
96
+ model = genai.Client(api_key=api_key)
97
+ response = model.models.generate_content(
98
+ model=model_name,
99
+ contents=prompt,
100
+ config=config,
101
+ )
102
+ # --- Check for successful response (handle potential blocks) ---
103
+ if hasattr(response, 'text') and response.text:
104
+ st.success(f"βœ… Successfully generated ideas using `{model_name}`!")
105
+ return response.text
106
+ elif hasattr(response, 'prompt_feedback') and response.prompt_feedback.block_reason:
107
+ error_message = f"⚠️ Generation blocked by `{model_name}`. Reason: {response.prompt_feedback.block_reason.name}. Trying next model..."
108
+ st.warning(error_message)
109
+ last_error = BlockingIOError(f"{model_name}: Blocked - {response.prompt_feedback.block_reason.name}")
110
+ last_error_message = error_message
111
+ time.sleep(0.5)
112
+ continue
113
+ else:
114
+ error_message = f"⚠️ Generation failed with `{model_name}` (empty or invalid response structure). Trying next model..."
115
+ st.warning(error_message)
116
+ last_error = ValueError(f"{model_name}: Empty/Invalid response")
117
+ last_error_message = error_message
118
+ time.sleep(1)
119
+ continue
120
+
121
+ # --- Catch Specific API Errors ---
122
+ except google.api_core.exceptions.ResourceExhausted as e:
123
+ error_message = f"⏳ Model `{model_name}` likely rate limited: {e}. Trying next model..."
124
+ st.warning(error_message)
125
+ last_error = e
126
+ last_error_message = error_message
127
+ time.sleep(3)
128
+ continue
129
+ except google.api_core.exceptions.ServiceUnavailable as e:
130
+ error_message = f"☁️ Model `{model_name}` unavailable: {e}. Trying next model..."
131
+ st.warning(error_message)
132
+ last_error = e
133
+ last_error_message = error_message
134
+ time.sleep(3)
135
+ continue
136
+ except (google.api_core.exceptions.InvalidArgument, ValueError) as e:
137
+ err_str = str(e).lower()
138
+ if "tool" in err_str or "function" in err_str or "retriever" in err_str:
139
+ error_message = f"πŸ”§ Model `{model_name}` might not support the requested tool or configuration: {e}. Trying next model..."
140
+ st.warning(error_message)
141
+ else:
142
+ error_message = f"🚫 Invalid argument for `{model_name}`: {e}. Trying next model..."
143
+ st.warning(error_message)
144
+ last_error = e
145
+ last_error_message = error_message
146
+ continue
147
+ except google.api_core.exceptions.GoogleAPIError as e:
148
+ error_message = f"🚫 API Error with `{model_name}`: {e}. Trying next model..."
149
+ st.warning(error_message)
150
+ last_error = e
151
+ last_error_message = error_message
152
+ continue
153
+ # --- Catch General Errors ---
154
+ except Exception as e:
155
+ error_message = f"❌ Unexpected error with `{model_name}`: {type(e).__name__} - {e}. Trying next model..."
156
+ st.warning(error_message)
157
+ last_error = e
158
+ last_error_message = error_message
159
+ continue
160
+
161
+ st.error("πŸ’₯ All attempts failed.")
162
+ final_error_message = "⚠️ Failed to generate ideas after trying all configured models."
163
+ if last_error:
164
+ final_error_message += f"\nLast known issue: {last_error_message}"
165
+
166
+ return final_error_message
167
+
168
+ # --- Streamlit App Interface ---
169
+ st.sidebar.title("Support This Tool")
170
+ st.sidebar.markdown(f"""
171
+ If you find this AI Content Idea Generator useful, please consider supporting its ongoing development and hosting costs.
172
+ [**πŸ’– Support on Patreon**]({PATREON_URL})
173
+ Your support helps keep this tool running and allows for future improvements!
174
+ """)
175
+
176
+ st.title("πŸš€ AI Niche Content Idea Generator")
177
+ st.markdown("Define your niche, audience, and format. Use **Advanced Mode** for potentially more current ideas!")
178
+ st.divider()
179
+
180
+ # --- User Inputs ---
181
+ with st.form("content_idea_form"):
182
+ st.subheader("Tell us about your content needs:")
183
+ niche = st.text_input("🎯 Enter your Niche:", placeholder="e.g., Sustainable Home Decor, Retro PC Gaming")
184
+ audience = st.text_area("πŸ‘₯ Describe your Target Audience:", placeholder="e.g., Eco-conscious millennials, 90s Gamers", height=100)
185
+ content_format_options = ["Blog Post Titles", "Social Media Captions", "YouTube Video Ideas", "Podcast Topics", "Newsletter Subjects", "TikTok Video Concepts", "LinkedIn Article Headlines"]
186
+ content_format = st.selectbox("✍️ Select Desired Content Format:", options=content_format_options)
187
+ num_ideas_slider = st.slider("πŸ”’ Number of ideas:", min_value=3, max_value=15, value=4)
188
+ advanced_mode_toggle = st.toggle("πŸ” Advanced Mode (Use Google Search)", value=False, help="May use Google Search for more current ideas. Works best with Gemini models.")
189
+ submitted = st.form_submit_button("✨ Generate Ideas!")
190
+
191
+ # --- Output ---
192
+ if submitted:
193
+ if not niche or not audience or not content_format:
194
+ st.warning("⚠️ Please fill in all the fields.")
195
+ elif api_key_configured:
196
+ mode_msg = " (Advanced Mode)" if advanced_mode_toggle else ""
197
+ with st.spinner(f"🧠 Thinking up brilliant ideas{mode_msg}..."):
198
+ generated_ideas = generate_content_ideas(
199
+ niche, audience, content_format, num_ideas_slider, advanced_mode=advanced_mode_toggle
200
+ )
201
+
202
+ st.divider()
203
+ st.subheader("πŸ’‘ Here are your content ideas:")
204
+ if generated_ideas and not generated_ideas.startswith(("⚠️", "πŸ’₯")):
205
+ st.markdown(generated_ideas)
206
+ st.success("Ideas generated successfully!")
207
+ st.markdown("---")
208
+ st.markdown(f"**Hope these ideas help!** If this tool saved you time or sparked creativity, consider [supporting the creator on Patreon]({PATREON_URL}).")
209
+ elif generated_ideas:
210
+ st.error(generated_ideas)
211
+ else:
212
+ st.error("An unexpected issue occurred. No ideas were generated or returned.")
213
+ else:
214
+ st.error("API Key is not configured.")