File size: 10,100 Bytes
6c153a2 e801b3f 6c153a2 e801b3f 6c153a2 |
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 207 208 209 210 211 212 213 214 215 216 |
import os
import time
import streamlit as st
from google import genai
from google.genai.types import Tool, GenerateContentConfig, GoogleSearch
import google.api_core
# --- Configuration ---
st.set_page_config(
page_title="AI Niche Content Idea Generator",
page_icon="π‘",
layout="centered",
)
# --- Patreon Link ---
PATREON_URL = "https://www.patreon.com/cineAI"
# --- Model List ---
FALLBACK_MODELS = [
"gemini-2.0-flash-thinking-exp-01-21",
"gemini-2.5-flash-preview-04-17",
"gemini-1.5-flash",
"gemini-1.5-pro",
"gemini-2.0-flash",
"gemini-2.0-flash-lite",
"gemini-2.5-pro-preview-03-25",
]
# --- Authentication ---
api_key = ""
try:
api_key = st.secrets["GOOGLE_API_KEY"]
api_key_configured = True
except (KeyError, FileNotFoundError):
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.")
api_key_configured = False
st.stop()
# --- Helper Function for API Call with Fallback & Advanced Mode ---
def generate_content_ideas(niche, audience, content_format, num_ideas=4, advanced_mode=False):
"""Generates content ideas using Google Generative AI, with fallback and optional search."""
if not api_key_configured:
return "API Key not configured. Cannot proceed."
# --- Base Prompt ---
base_prompt = f"""
Act as an expert content strategist specializing in the niche: '{niche}'.
Your task is to generate {num_ideas} fresh, specific, and engaging content ideas tailored for the following target audience: '{audience}'.
The desired content format is: '{content_format}'.
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.
"""
# --- Enhance Prompt for Advanced Mode ---
if advanced_mode:
prompt = base_prompt + f"""
**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.
"""
else:
prompt = base_prompt + """
Generate the ideas based on your general knowledge of the niche and audience.
"""
# --- Add Formatting Instruction ---
prompt += """
Please format the output as a numbered list. Each idea should be concise but descriptive.
Example for niche 'Sustainable Gardening', audience 'Urban Beginners', format 'Blog Post Titles':
1. 5 Easy-to-Grow Vegetables for Your Tiny Balcony Garden
2. Composting in Apartments: A No-Smell Guide for City Dwellers
3. Choosing the Right Recycled Pots for Your Indoor Plants
4. How to Attract Pollinators to Your Urban Oasis
5. Watering Wisely: Saving Water in Your Container Garden
Now, generate the ideas for the requested niche, audience, and format:
"""
last_error = None
last_error_message = ""
# --- Tool Configuration ---
if advanced_mode:
google_search_tool = Tool(google_search=GoogleSearch())
config = GenerateContentConfig(
tools=[google_search_tool],
response_modalities=['TEXT'],
# system_instruction=system_instruction_google_search,
max_output_tokens=4100,
)
else:
config = None
tool_status_msg = " (Advanced Mode with Google Search π)" if advanced_mode else ""
for model_name in FALLBACK_MODELS:
st.info(f"π§ Attempting generation with model: `{model_name}`{tool_status_msg}...")
try:
model = genai.Client(api_key=api_key)
response = model.models.generate_content(
model=model_name,
contents=prompt,
config=config,
)
# --- Check for successful response (handle potential blocks) ---
if hasattr(response, 'text') and response.text:
st.success(f"β
Successfully generated ideas using `{model_name}`!")
return response.text
elif hasattr(response, 'prompt_feedback') and response.prompt_feedback.block_reason:
error_message = f"β οΈ Generation blocked by `{model_name}`. Reason: {response.prompt_feedback.block_reason.name}. Trying next model..."
st.warning(error_message)
last_error = BlockingIOError(f"{model_name}: Blocked - {response.prompt_feedback.block_reason.name}")
last_error_message = error_message
time.sleep(0.5)
continue
else:
error_message = f"β οΈ Generation failed with `{model_name}` (empty or invalid response structure). Trying next model..."
st.warning(error_message)
last_error = ValueError(f"{model_name}: Empty/Invalid response")
last_error_message = error_message
time.sleep(1)
continue
# --- Catch Specific API Errors ---
except google.api_core.exceptions.ResourceExhausted as e:
error_message = f"β³ Model `{model_name}` likely rate limited: {e}. Trying next model..."
st.warning(error_message)
last_error = e
last_error_message = error_message
time.sleep(3)
continue
except google.api_core.exceptions.ServiceUnavailable as e:
error_message = f"βοΈ Model `{model_name}` unavailable: {e}. Trying next model..."
st.warning(error_message)
last_error = e
last_error_message = error_message
time.sleep(3)
continue
except (google.api_core.exceptions.InvalidArgument, ValueError) as e:
err_str = str(e).lower()
if "tool" in err_str or "function" in err_str or "retriever" in err_str:
error_message = f"π§ Model `{model_name}` might not support the requested tool or configuration: {e}. Trying next model..."
st.warning(error_message)
else:
error_message = f"π« Invalid argument for `{model_name}`: {e}. Trying next model..."
st.warning(error_message)
last_error = e
last_error_message = error_message
continue
except google.api_core.exceptions.GoogleAPIError as e:
error_message = f"π« API Error with `{model_name}`: {e}. Trying next model..."
st.warning(error_message)
last_error = e
last_error_message = error_message
continue
# --- Catch General Errors ---
except Exception as e:
error_message = f"β Unexpected error with `{model_name}`: {type(e).__name__} - {e}. Trying next model..."
st.warning(error_message)
last_error = e
last_error_message = error_message
continue
st.error("π₯ All attempts failed.")
final_error_message = "β οΈ Failed to generate ideas after trying all configured models."
if last_error:
final_error_message += f"\nLast known issue: {last_error_message}"
return final_error_message
# --- Streamlit App Interface ---
st.sidebar.title("Support This Tool")
st.sidebar.markdown(f"""
If you find this AI Content Idea Generator useful, please consider supporting its ongoing development and hosting costs.
[**π Support on Patreon**]({PATREON_URL})
Your support helps keep this tool running and allows for future improvements!
""")
st.title("π AI Niche Content Idea Generator")
st.markdown("Define your niche, audience, and format. Use **Advanced Mode** for potentially more current ideas!")
st.divider()
# --- User Inputs ---
with st.form("content_idea_form"):
st.subheader("Tell us about your content needs:")
niche = st.text_input("π― Enter your Niche:", placeholder="e.g., Sustainable Home Decor, Retro PC Gaming")
audience = st.text_area("π₯ Describe your Target Audience:", placeholder="e.g., Eco-conscious millennials, 90s Gamers", height=100)
content_format_options = ["Blog Post Titles", "Social Media Captions", "YouTube Video Ideas", "Podcast Topics", "Newsletter Subjects", "TikTok Video Concepts", "LinkedIn Article Headlines"]
content_format = st.selectbox("βοΈ Select Desired Content Format:", options=content_format_options)
num_ideas_slider = st.slider("π’ Number of ideas:", min_value=3, max_value=15, value=4)
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.")
submitted = st.form_submit_button("β¨ Generate Ideas!")
# --- Output ---
if submitted:
if not niche or not audience or not content_format:
st.warning("β οΈ Please fill in all the fields.")
elif api_key_configured:
mode_msg = " (Advanced Mode)" if advanced_mode_toggle else ""
with st.spinner(f"π§ Thinking up brilliant ideas{mode_msg}..."):
generated_ideas = generate_content_ideas(
niche, audience, content_format, num_ideas_slider, advanced_mode=advanced_mode_toggle
)
st.divider()
st.subheader("π‘ Here are your content ideas:")
if generated_ideas and not generated_ideas.startswith(("β οΈ", "π₯")):
st.markdown(generated_ideas)
st.success("Ideas generated successfully!")
st.markdown("---")
st.markdown(f"**Hope these ideas help!** If this tool saved you time or sparked creativity, consider [supporting the creator on Patreon]({PATREON_URL}).")
elif generated_ideas:
st.error(generated_ideas)
else:
st.error("An unexpected issue occurred. No ideas were generated or returned.")
else:
st.error("API Key is not configured.") |