import gradio as gr import os from typing import Dict, List, Tuple import time class GlossaryGenerator: def __init__(self): self.template = """ **Glossary Page Template** Use this template to create individual glossary pages for specific terms. Fill in each section with relevant information. **[TERM NAME]** **1. Introduction / Brief Definition (AI Overview)** * **Purpose:** Provide the absolute clearest, most concise, and direct answer to "What is [TERM NAME]?" This should be a short, no-fluff definition, similar to an AI overview or a quick dictionary entry. * **Content:** Start immediately with the core definition. Get straight to the point. **2. Detailed Explanation** * **Purpose:** Expand on the brief definition, offering a comprehensive explanation of the term. This section should follow a "reverse pyramid" structure, meaning the most critical information is presented first, followed by supporting details. * **Content:** * **Elaborate on the core concept:** Build upon the initial definition, providing more depth and context. * **Explore related questions (PAA / Query Fans):** Anticipate what users might ask next or what related topics they might search for. Integrate answers to "People Also Ask" (PAA) type questions or expand into "query fan" concepts that naturally branch off the main term. * Provide context, background, or the purpose of the term. * Include key characteristics, functions, or processes associated with the term. * Use examples to illustrate the concept clearly. * Break down complex ideas into simpler parts. **3. Key Concepts / Components (Optional)** * **Purpose:** If the term has distinct sub-sections, components, or related key ideas that warrant separate discussion, list and explain them here. * **Content:** * Use bullet points or sub-headings for each key concept. * Briefly define and explain each component. **4. Importance / Application (Optional)** * **Purpose:** Explain why the term is significant, its impact, or how it is applied in real-world scenarios. * **Content:** Discuss the relevance, benefits, challenges, or practical uses of the term. **5. Related Terms / Concepts** * **Purpose:** Link to other relevant terms within your glossary or related concepts that readers might find useful for further understanding. * **Content:** * List terms that are closely associated or often discussed alongside the current term. **6. Sources / References** * **Purpose:** Cite the sources from which the information was gathered. This adds credibility and allows readers to explore further. * **Content:** * List URLs, book titles, or other references. """ # ---- Token safety utilities ---- def _approx_tokens(self, text: str) -> int: # Roughly 4 characters per token (very conservative heuristic) return max(1, len(text) // 4) def _safe_max_tokens(self, prompt: str, requested_max: int, model_context_limit: int = 128000) -> int: """ Clamp max_tokens so (prompt_tokens + max_tokens) <= model_context_limit. We include the system message length as well. """ system_msg = "You are a professional content writer specializing in creating high-quality glossary entries. You follow templates precisely and create comprehensive, well-structured content." est_prompt_tokens = self._approx_tokens(system_msg) + self._approx_tokens(prompt) room = max(256, model_context_limit - est_prompt_tokens) # leave a floor of 256 return max(1, min(requested_max, room)) def _test_api_key(self, api_key: str) -> bool: """Test OpenAI API key with minimal request""" if not api_key or not api_key.strip(): return False try: from openai import OpenAI client = OpenAI(api_key=api_key.strip()) response = client.chat.completions.create( model="gpt-4-turbo", messages=[{"role": "user", "content": "Hi"}], max_tokens=1 ) return True except Exception as e: print(f"API test error: {e}") return False def _call_openai_raw(self, api_key: str, prompt: str, model: str = "gpt-4-turbo", max_tokens: int = 1200) -> str: """Direct OpenAI API call using requests with safe max_tokens handling""" import requests import json if not api_key or not api_key.strip(): return "🔑 Please enter your OpenAI API key above to generate content." clean_key = api_key.strip() # Auto-clamp max_tokens based on estimated prompt size and 128k context safe_max = self._safe_max_tokens(prompt, requested_max=max_tokens, model_context_limit=128000) url = "https://api.openai.com/v1/chat/completions" headers = { "Authorization": f"Bearer {clean_key}", "Content-Type": "application/json" } data = { "model": model, "messages": [ {"role": "system", "content": "You are a professional content writer specializing in creating high-quality glossary entries. You follow templates precisely and create comprehensive, well-structured content."}, {"role": "user", "content": prompt} ], "max_tokens": safe_max, "temperature": 0.7, "top_p": 1, "frequency_penalty": 0, "presence_penalty": 0 } try: print(f"🚀 Making direct API call to OpenAI...") print(f"â„šī¸ Model: {model} | requested_max: {max_tokens} | safe_max: {safe_max}") response = requests.post(url, headers=headers, json=data, timeout=90) print(f"📊 Response status: {response.status_code}") if response.status_code == 200: result = response.json() content = result['choices'][0]['message']['content'].strip() print("✅ API call successful") return content else: error_data = {} try: error_data = response.json() if response.content else {} except Exception: pass error_msg = error_data.get('error', {}).get('message', 'Unknown error') error_code = error_data.get('error', {}).get('code', 'unknown') print(f"❌ API call failed: {response.status_code} - {error_msg}") if response.status_code == 401: return "❌ Invalid API key. Please check your OpenAI API key." elif response.status_code == 429: return "❌ Rate limit exceeded. Please wait a moment and try again." elif response.status_code == 404 and model == "gpt-4-turbo": # Try GPT-3.5 fallback print("🔄 Trying GPT-3.5-turbo fallback...") # Recompute safe max for same prompt fallback_safe_max = self._safe_max_tokens(prompt, requested_max=max_tokens, model_context_limit=16384) # conservative for 3.5 return self._call_openai_raw(api_key, prompt, "gpt-3.5-turbo", fallback_safe_max) elif "insufficient_quota" in str(error_msg).lower(): return "❌ OpenAI API quota exceeded. Please check your billing at https://platform.openai.com/usage" elif "maximum context length" in str(error_msg).lower() or "context length" in str(error_msg).lower(): return "❌ Context length exceeded. Try shortening your input or lowering max output length." else: return f"❌ OpenAI API Error ({response.status_code}): {error_msg}" except requests.exceptions.Timeout: return "❌ Request timeout. Please try again." except requests.exceptions.RequestException as e: return f"❌ Network error: {str(e)}" except Exception as e: return f"❌ Unexpected error: {str(e)}" def generate_new_content(self, api_key: str, term: str, context: str = "", target_audience: str = "general") -> str: """Generate new glossary content for a given term (uses gpt-4-turbo)""" if not term.strip(): return "Please enter a term to generate content for." prompt = f""" Create a comprehensive glossary entry for the term "{term}" following this EXACT template structure: {self.template} **Requirements:** - Replace [TERM NAME] with "{term}" - Target Audience: {target_audience} - Additional Context: {context if context else "No additional context provided"} - Fill in ALL sections with relevant, accurate information - Use the "reverse pyramid" structure - most important info first - Include relevant PAA (People Also Ask) questions in section 2 - Remove optional sections only if truly not applicable - Maintain clear, concise language - Provide at least 3 related terms in section 5 - Include credible sources/references in section 6 **Focus Areas:** - Make the brief definition crystal clear and direct - Expand thoroughly in the detailed explanation - Include practical examples and use cases - Address common questions people might have - Ensure professional, authoritative tone Generate the complete glossary entry now: """ # Default requested max_tokens for generation; will be auto-clamped return self._call_openai_raw(api_key, prompt, model="gpt-4-turbo", max_tokens=1200) def update_existing_content(self, api_key: str, term: str, existing_content: str, update_instructions: str = "") -> Tuple[str, str]: """Analyze existing content and provide update recommendations, then produce updated content""" if not term.strip() or not existing_content.strip(): return "Please provide both term and existing content.", "" analysis_prompt = f""" Analyze this existing glossary content for "{term}" against the template standard and provide specific improvement recommendations. **EXISTING CONTENT:** {existing_content} **TEMPLATE STANDARD:** {self.template} **UPDATE INSTRUCTIONS:** {update_instructions if update_instructions else "General content improvement"} **Provide a detailed analysis covering:** 1. **STRUCTURAL ANALYSIS:** - Does it follow the template structure? - Which sections are missing or incomplete? - Is the reverse pyramid structure implemented? 2. **CONTENT QUALITY ASSESSMENT:** - Clarity and conciseness of the brief definition - Depth and comprehensiveness of detailed explanation - Relevance and usefulness of examples - Quality of related terms and references 3. **SPECIFIC RECOMMENDATIONS (prioritized):** - HIGH PRIORITY: Critical improvements needed - MEDIUM PRIORITY: Important enhancements - LOW PRIORITY: Nice-to-have improvements 4. **SEO & USER EXPERIENCE:** - Missing PAA questions to address - Keyword opportunities - Cross-linking possibilities - Readability improvements 5. **SOURCES & CREDIBILITY:** - Quality of current references - Missing authoritative sources - Fact-checking requirements Format as a professional content analysis report. """ recommendations = self._call_openai_raw(api_key, analysis_prompt, model="gpt-4-turbo", max_tokens=1000) update_prompt = f""" Create an improved version of the glossary entry for "{term}" based on the analysis and recommendations. **ORIGINAL CONTENT:** {existing_content} **ANALYSIS & RECOMMENDATIONS:** {recommendations} **TEMPLATE TO FOLLOW:** {self.template} **UPDATE INSTRUCTIONS:** {update_instructions if update_instructions else "Apply the key recommendations from the analysis"} **Create the improved glossary entry that:** 1. Follows the template structure exactly 2. Implements the high and medium priority recommendations 3. Maintains the best elements from the original 4. Adds missing sections or information 5. Improves clarity, structure, and usefulness 6. Includes better examples and explanations 7. Enhances SEO and user experience Generate the complete, improved glossary entry: """ updated_content = self._call_openai_raw(api_key, update_prompt, model="gpt-4-turbo", max_tokens=1200) return recommendations, updated_content def create_outline_brief(self, api_key: str, topic: str, scope: str = "comprehensive") -> str: """Create a strategic brief (uses gpt-4-turbo)""" if not topic.strip(): return "Please enter a topic for the outline." prompt = f""" Create a comprehensive content brief for developing a glossary focused on "{topic}". **Scope:** {scope} **Template Standard:** Follow the 6-section template structure provided **Create a detailed brief covering:** **1. TOPIC OVERVIEW & STRATEGY** - Comprehensive topic definition and boundaries - Target audience analysis and segmentation - Content complexity and depth recommendations - Competitive landscape and differentiation opportunities **2. TERM IDENTIFICATION & PRIORITIZATION** - **Primary Terms (10-15 key terms):** Most important, high-search volume terms - **Secondary Terms (8-12 supporting terms):** Important supporting concepts - **Long-tail Terms (5-10 specific terms):** Niche but valuable terms - **Priority Matrix:** High/Medium/Low priority for each term with reasoning **3. CONTENT ARCHITECTURE** - Template section recommendations for each term type - Suggested content depth and length for each priority level - Cross-linking strategy between terms - Information hierarchy and user journey mapping **4. RESEARCH & DEVELOPMENT PLAN** - **Primary Sources:** Authoritative websites, publications, studies - **Expert Sources:** Industry leaders, academic researchers, practitioners - **User Research:** Common questions, search patterns, knowledge gaps - **Competitive Analysis:** What others are doing well/poorly **5. SEO & DISCOVERABILITY STRATEGY** - **Primary Keywords:** Main search terms for each priority level - **Long-tail Keywords:** Specific phrases users search for - **PAA Questions:** "People Also Ask" questions to address - **Content Gap Analysis:** Opportunities competitors are missing - **Internal Linking Strategy:** How terms connect to each other **6. PRODUCTION ROADMAP** - **Phase 1:** High-priority terms (timeline and resource allocation) - **Phase 2:** Secondary terms and enhancements - **Phase 3:** Long-tail terms and optimization - **Resource Requirements:** Estimated hours per term type - **Quality Assurance:** Review process and standards - **Maintenance Plan:** Update frequency and monitoring **7. SUCCESS METRICS & KPIs** - Content quality indicators - User engagement metrics - SEO performance targets - Conversion and utility measurements Create a comprehensive, actionable brief that will guide the entire glossary development process. """ # Slightly larger default for briefs; will still auto-clamp safely return self._call_openai_raw(api_key, prompt, model="gpt-4-turbo", max_tokens=1500) def create_gradio_interface(): """Create the Gradio interface for the glossary generator""" generator = GlossaryGenerator() def test_api_key(api_key): """Test if the API key is valid""" if not api_key or not api_key.strip(): return "❌ Please enter your OpenAI API key" clean_key = api_key.strip() if not clean_key.startswith('sk-'): return "❌ Invalid format - OpenAI API keys should start with 'sk-'" if len(clean_key) < 20: return "❌ API key too short - check if you copied the full key" test_result = generator._call_openai_raw(clean_key, "Test", "gpt-4-turbo", 1) if "❌" in test_result: return test_result else: return "✅ API key is valid and connected!" def generate_new_wrapper(api_key, term, context, audience): if not term.strip(): return "Please enter a term to generate content for." return generator.generate_new_content(api_key, term, context, audience) def update_existing_wrapper(api_key, term, existing_content, update_instructions): if not term.strip() or not existing_content.strip(): return "Please provide both term and existing content.", "" recommendations, updated_content = generator.update_existing_content(api_key, term, existing_content, update_instructions) return recommendations, updated_content def create_outline_wrapper(api_key, topic, scope): if not topic.strip(): return "Please enter a topic for the outline." return generator.create_outline_brief(api_key, topic, scope) with gr.Blocks(title="Glossary Content Generator", theme=gr.themes.Soft()) as demo: gr.Markdown(""" # 📚 Glossary Content Generator **Powered by OpenAI GPT-4 Turbo** - Professional glossary content creation and optimization tool. 🔑 **Enter your OpenAI API key below to get started!** """) with gr.Row(): with gr.Column(scale=2): api_key_input = gr.Textbox( label="🔑 OpenAI API Key", placeholder="sk-proj-... or sk-...", type="password", info="Get your API key at https://platform.openai.com/api-keys" ) with gr.Column(scale=1): test_key_btn = gr.Button("Test Key", variant="secondary") manual_test_btn = gr.Button("Skip Test & Try Anyway", variant="outline") with gr.Column(scale=1): key_status = gr.Textbox( label="Status", value="❌ No API key provided", interactive=False, max_lines=2 ) def manual_override(api_key): if api_key and api_key.strip(): return "âš ī¸ Test skipped - trying anyway..." return "❌ Please enter an API key first" test_key_btn.click( test_api_key, inputs=[api_key_input], outputs=[key_status] ) manual_test_btn.click( manual_override, inputs=[api_key_input], outputs=[key_status] ) gr.Markdown("---") with gr.Tabs(): with gr.TabItem("🆕 Generate New Content"): gr.Markdown("### Create a new glossary entry from scratch using GPT-4 Turbo") with gr.Row(): with gr.Column(scale=1): new_term = gr.Textbox( label="Term to Define", placeholder="e.g., Machine Learning, CPQ, SEO, API", lines=1 ) new_context = gr.Textbox( label="Additional Context (Optional)", placeholder="Provide industry context, specific use cases, or background information", lines=3 ) new_audience = gr.Dropdown( label="Target Audience", choices=["general", "technical", "business", "beginner", "expert"], value="general" ) generate_btn = gr.Button("🚀 Generate Content", variant="primary") with gr.Column(scale=2): new_output = gr.Textbox( label="Generated Glossary Entry", lines=25, max_lines=30, show_copy_button=True ) generate_btn.click( generate_new_wrapper, inputs=[api_key_input, new_term, new_context, new_audience], outputs=[new_output] ) gr.Markdown("**💡 Example Terms:** API, Machine Learning, Blockchain, SaaS, Customer Journey, A/B Testing") with gr.TabItem("🔄 Update Existing Content"): gr.Markdown("### Analyze and improve existing glossary entries with AI-powered recommendations") with gr.Row(): with gr.Column(scale=1): update_term = gr.Textbox( label="Term Name", placeholder="Name of the term being updated", lines=1 ) existing_content = gr.Textbox( label="Existing Content", placeholder="Paste your current glossary entry here", lines=10 ) update_instructions = gr.Textbox( label="Update Instructions (Optional)", placeholder="e.g., 'Add more technical details', 'Include recent developments', 'Improve SEO focus'", lines=3 ) update_btn = gr.Button("🔍 Analyze & Update", variant="primary") with gr.Column(scale=2): with gr.Row(): recommendations_output = gr.Textbox( label="📊 Analysis & Recommendations", lines=12, max_lines=15, show_copy_button=True ) with gr.Row(): updated_content_output = gr.Textbox( label="✨ Updated Content", lines=12, max_lines=15, show_copy_button=True ) update_btn.click( update_existing_wrapper, inputs=[api_key_input, update_term, existing_content, update_instructions], outputs=[recommendations_output, updated_content_output] ) with gr.TabItem("📋 Create Content Brief"): gr.Markdown("### Generate a comprehensive strategy brief for glossary development") with gr.Row(): with gr.Column(scale=1): outline_topic = gr.Textbox( label="Topic/Subject Area", placeholder="e.g., Digital Marketing, Cloud Computing, Artificial Intelligence, E-commerce", lines=1 ) outline_scope = gr.Dropdown( label="Scope & Depth", choices=["comprehensive", "focused", "basic", "advanced", "specialized"], value="comprehensive" ) outline_btn = gr.Button("📋 Create Strategic Brief", variant="primary") with gr.Column(scale=2): outline_output = gr.Textbox( label="📈 Content Strategy Brief", lines=25, max_lines=30, show_copy_button=True ) outline_btn.click( create_outline_wrapper, inputs=[api_key_input, outline_topic, outline_scope], outputs=[outline_output] ) gr.Markdown("**💡 Example Topics:** Digital Marketing, FinTech, SaaS Operations, Data Science, Cybersecurity") with gr.TabItem("📄 Template Reference"): gr.Markdown("### Official Glossary Template Structure") template_display = gr.Textbox( label="Template Guidelines", value=generator.template, lines=35, max_lines=40, interactive=False, show_copy_button=True ) gr.Markdown(""" --- ## 🔧 How to Get Your OpenAI API Key: 1. **Visit** [platform.openai.com/api-keys](https://platform.openai.com/api-keys) 2. **Sign up** or log in to your OpenAI account 3. **Add billing information** (GPT-4 access requires a paid account) 4. **Create a new secret key** 5. **Copy and paste** it into the field above ## ✨ Features: - 🤖 **GPT-4 Turbo Powered** - 📝 **Template Consistency** - 🔍 **Content Analysis** - 📊 **Strategic Briefs** - đŸŽ¯ **SEO-Oriented Outputs** - 🔑 **Direct API (raw HTTP)** """) return demo # Launch the application if __name__ == "__main__": app = create_gradio_interface() app.launch( share=False, server_name="0.0.0.0", server_port=7860 )