ryanshelley commited on
Commit
5c0ad64
Β·
verified Β·
1 Parent(s): aff8218

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +105 -114
app.py CHANGED
@@ -39,90 +39,110 @@ Use this template to create individual glossary pages for specific terms. Fill i
39
  * List URLs, book titles, or other references.
40
  """
41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  def _test_api_key(self, api_key: str) -> bool:
43
  """Test OpenAI API key with minimal request"""
44
  if not api_key or not api_key.strip():
45
  return False
46
-
47
  try:
48
- # Import here to avoid import-time issues
49
  from openai import OpenAI
50
-
51
  client = OpenAI(api_key=api_key.strip())
52
-
53
- # Test with minimal request
54
  response = client.chat.completions.create(
55
- model="gpt-3.5-turbo",
56
  messages=[{"role": "user", "content": "Hi"}],
57
  max_tokens=1
58
  )
59
  return True
60
-
61
  except Exception as e:
62
  print(f"API test error: {e}")
63
  return False
64
 
65
- def _call_openai_raw(self, api_key: str, prompt: str, model: str = "gpt-4", max_tokens: int = 2000) -> str:
66
- """Direct OpenAI API call using requests"""
67
  import requests
68
  import json
69
-
70
  if not api_key or not api_key.strip():
71
  return "πŸ”‘ Please enter your OpenAI API key above to generate content."
72
-
73
  clean_key = api_key.strip()
74
-
75
- # Direct API call to avoid client issues
 
 
76
  url = "https://api.openai.com/v1/chat/completions"
77
  headers = {
78
  "Authorization": f"Bearer {clean_key}",
79
  "Content-Type": "application/json"
80
  }
81
-
82
  data = {
83
  "model": model,
84
  "messages": [
85
  {"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."},
86
  {"role": "user", "content": prompt}
87
  ],
88
- "max_tokens": max_tokens,
89
  "temperature": 0.7,
90
  "top_p": 1,
91
  "frequency_penalty": 0,
92
  "presence_penalty": 0
93
  }
94
-
95
  try:
96
  print(f"πŸš€ Making direct API call to OpenAI...")
97
- response = requests.post(url, headers=headers, json=data, timeout=60)
 
98
  print(f"πŸ“Š Response status: {response.status_code}")
99
-
100
  if response.status_code == 200:
101
  result = response.json()
102
  content = result['choices'][0]['message']['content'].strip()
103
  print("βœ… API call successful")
104
  return content
105
-
106
  else:
107
- error_data = response.json() if response.content else {}
 
 
 
 
 
108
  error_msg = error_data.get('error', {}).get('message', 'Unknown error')
109
  error_code = error_data.get('error', {}).get('code', 'unknown')
110
-
111
  print(f"❌ API call failed: {response.status_code} - {error_msg}")
112
-
113
  if response.status_code == 401:
114
  return "❌ Invalid API key. Please check your OpenAI API key."
115
  elif response.status_code == 429:
116
  return "❌ Rate limit exceeded. Please wait a moment and try again."
117
- elif response.status_code == 404 and model == "gpt-4":
118
  # Try GPT-3.5 fallback
119
  print("πŸ”„ Trying GPT-3.5-turbo fallback...")
120
- return self._call_openai_raw(api_key, prompt, "gpt-3.5-turbo", max_tokens)
121
- elif "insufficient_quota" in error_msg.lower():
 
 
122
  return "❌ OpenAI API quota exceeded. Please check your billing at https://platform.openai.com/usage"
 
 
123
  else:
124
  return f"❌ OpenAI API Error ({response.status_code}): {error_msg}"
125
-
126
  except requests.exceptions.Timeout:
127
  return "❌ Request timeout. Please try again."
128
  except requests.exceptions.RequestException as e:
@@ -131,11 +151,10 @@ Use this template to create individual glossary pages for specific terms. Fill i
131
  return f"❌ Unexpected error: {str(e)}"
132
 
133
  def generate_new_content(self, api_key: str, term: str, context: str = "", target_audience: str = "general") -> str:
134
- """Generate new glossary content for a given term"""
135
-
136
  if not term.strip():
137
  return "Please enter a term to generate content for."
138
-
139
  prompt = f"""
140
  Create a comprehensive glossary entry for the term "{term}" following this EXACT template structure:
141
  {self.template}
@@ -158,16 +177,14 @@ Create a comprehensive glossary entry for the term "{term}" following this EXACT
158
  - Ensure professional, authoritative tone
159
  Generate the complete glossary entry now:
160
  """
161
-
162
- return self._call_openai_raw(api_key, prompt, max_tokens=2500)
163
 
164
  def update_existing_content(self, api_key: str, term: str, existing_content: str, update_instructions: str = "") -> Tuple[str, str]:
165
- """Analyze existing content and provide update recommendations"""
166
-
167
  if not term.strip() or not existing_content.strip():
168
  return "Please provide both term and existing content.", ""
169
-
170
- # First, analyze the content
171
  analysis_prompt = f"""
172
  Analyze this existing glossary content for "{term}" against the template standard and provide specific improvement recommendations.
173
  **EXISTING CONTENT:**
@@ -200,10 +217,8 @@ Analyze this existing glossary content for "{term}" against the template standar
200
  - Fact-checking requirements
201
  Format as a professional content analysis report.
202
  """
203
-
204
- recommendations = self._call_openai_raw(api_key, analysis_prompt, max_tokens=1500)
205
-
206
- # Then generate updated content
207
  update_prompt = f"""
208
  Create an improved version of the glossary entry for "{term}" based on the analysis and recommendations.
209
  **ORIGINAL CONTENT:**
@@ -223,17 +238,14 @@ Create an improved version of the glossary entry for "{term}" based on the analy
223
  7. Enhances SEO and user experience
224
  Generate the complete, improved glossary entry:
225
  """
226
-
227
- updated_content = self._call_openai_raw(api_key, update_prompt, max_tokens=2500)
228
-
229
  return recommendations, updated_content
230
 
231
  def create_outline_brief(self, api_key: str, topic: str, scope: str = "comprehensive") -> str:
232
- """Create an outline or brief for new glossary content"""
233
-
234
  if not topic.strip():
235
  return "Please enter a topic for the outline."
236
-
237
  prompt = f"""
238
  Create a comprehensive content brief for developing a glossary focused on "{topic}".
239
  **Scope:** {scope}
@@ -279,62 +291,56 @@ Create a comprehensive content brief for developing a glossary focused on "{topi
279
  - Conversion and utility measurements
280
  Create a comprehensive, actionable brief that will guide the entire glossary development process.
281
  """
282
-
283
- return self._call_openai_raw(api_key, prompt, max_tokens=3000)
284
 
285
  def create_gradio_interface():
286
  """Create the Gradio interface for the glossary generator"""
287
-
288
  generator = GlossaryGenerator()
289
-
290
  def test_api_key(api_key):
291
  """Test if the API key is valid"""
292
  if not api_key or not api_key.strip():
293
  return "❌ Please enter your OpenAI API key"
294
-
295
- # Basic format check
296
  clean_key = api_key.strip()
297
  if not clean_key.startswith('sk-'):
298
  return "❌ Invalid format - OpenAI API keys should start with 'sk-'"
299
-
300
  if len(clean_key) < 20:
301
  return "❌ API key too short - check if you copied the full key"
302
-
303
- # Test the key with direct API call
304
- test_result = generator._call_openai_raw(clean_key, "Test", "gpt-3.5-turbo", 1)
305
-
306
  if "❌" in test_result:
307
  return test_result
308
  else:
309
  return "βœ… API key is valid and connected!"
310
-
311
  def generate_new_wrapper(api_key, term, context, audience):
312
  if not term.strip():
313
  return "Please enter a term to generate content for."
314
  return generator.generate_new_content(api_key, term, context, audience)
315
-
316
  def update_existing_wrapper(api_key, term, existing_content, update_instructions):
317
  if not term.strip() or not existing_content.strip():
318
  return "Please provide both term and existing content.", ""
319
  recommendations, updated_content = generator.update_existing_content(api_key, term, existing_content, update_instructions)
320
  return recommendations, updated_content
321
-
322
  def create_outline_wrapper(api_key, topic, scope):
323
  if not topic.strip():
324
  return "Please enter a topic for the outline."
325
  return generator.create_outline_brief(api_key, topic, scope)
326
-
327
- # Create the Gradio interface
328
  with gr.Blocks(title="Glossary Content Generator", theme=gr.themes.Soft()) as demo:
329
  gr.Markdown("""
330
  # πŸ“š Glossary Content Generator
331
-
332
- **Powered by OpenAI GPT-4** - Professional glossary content creation and optimization tool.
333
-
334
  πŸ”‘ **Enter your OpenAI API key below to get started!**
335
  """)
336
-
337
- # API Key Section
338
  with gr.Row():
339
  with gr.Column(scale=2):
340
  api_key_input = gr.Textbox(
@@ -345,7 +351,7 @@ def create_gradio_interface():
345
  )
346
  with gr.Column(scale=1):
347
  test_key_btn = gr.Button("Test Key", variant="secondary")
348
- manual_test_btn = gr.Button("Skip Test & Try Anyway", variant="outline", size="sm")
349
  with gr.Column(scale=1):
350
  key_status = gr.Textbox(
351
  label="Status",
@@ -353,31 +359,30 @@ def create_gradio_interface():
353
  interactive=False,
354
  max_lines=2
355
  )
356
-
357
  def manual_override(api_key):
358
  if api_key and api_key.strip():
359
  return "⚠️ Test skipped - trying anyway..."
360
  return "❌ Please enter an API key first"
361
-
362
  test_key_btn.click(
363
  test_api_key,
364
  inputs=[api_key_input],
365
  outputs=[key_status]
366
  )
367
-
368
  manual_test_btn.click(
369
  manual_override,
370
  inputs=[api_key_input],
371
  outputs=[key_status]
372
  )
373
-
374
  gr.Markdown("---")
375
-
376
  with gr.Tabs():
377
- # Tab 1: Generate New Content
378
  with gr.TabItem("πŸ†• Generate New Content"):
379
- gr.Markdown("### Create a new glossary entry from scratch using GPT-4")
380
-
381
  with gr.Row():
382
  with gr.Column(scale=1):
383
  new_term = gr.Textbox(
@@ -395,8 +400,7 @@ def create_gradio_interface():
395
  choices=["general", "technical", "business", "beginner", "expert"],
396
  value="general"
397
  )
398
- generate_btn = gr.Button("πŸš€ Generate Content", variant="primary", size="lg")
399
-
400
  with gr.Column(scale=2):
401
  new_output = gr.Textbox(
402
  label="Generated Glossary Entry",
@@ -404,20 +408,18 @@ def create_gradio_interface():
404
  max_lines=30,
405
  show_copy_button=True
406
  )
407
-
408
  generate_btn.click(
409
  generate_new_wrapper,
410
  inputs=[api_key_input, new_term, new_context, new_audience],
411
  outputs=[new_output]
412
  )
413
-
414
- # Add examples
415
  gr.Markdown("**πŸ’‘ Example Terms:** API, Machine Learning, Blockchain, SaaS, Customer Journey, A/B Testing")
416
-
417
- # Tab 2: Update Existing Content
418
  with gr.TabItem("πŸ”„ Update Existing Content"):
419
  gr.Markdown("### Analyze and improve existing glossary entries with AI-powered recommendations")
420
-
421
  with gr.Row():
422
  with gr.Column(scale=1):
423
  update_term = gr.Textbox(
@@ -435,8 +437,7 @@ def create_gradio_interface():
435
  placeholder="e.g., 'Add more technical details', 'Include recent developments', 'Improve SEO focus'",
436
  lines=3
437
  )
438
- update_btn = gr.Button("πŸ” Analyze & Update", variant="primary", size="lg")
439
-
440
  with gr.Column(scale=2):
441
  with gr.Row():
442
  recommendations_output = gr.Textbox(
@@ -452,17 +453,16 @@ def create_gradio_interface():
452
  max_lines=15,
453
  show_copy_button=True
454
  )
455
-
456
  update_btn.click(
457
  update_existing_wrapper,
458
  inputs=[api_key_input, update_term, existing_content, update_instructions],
459
  outputs=[recommendations_output, updated_content_output]
460
  )
461
-
462
- # Tab 3: Create Outline/Brief
463
  with gr.TabItem("πŸ“‹ Create Content Brief"):
464
  gr.Markdown("### Generate a comprehensive strategy brief for glossary development")
465
-
466
  with gr.Row():
467
  with gr.Column(scale=1):
468
  outline_topic = gr.Textbox(
@@ -475,8 +475,7 @@ def create_gradio_interface():
475
  choices=["comprehensive", "focused", "basic", "advanced", "specialized"],
476
  value="comprehensive"
477
  )
478
- outline_btn = gr.Button("πŸ“‹ Create Strategic Brief", variant="primary", size="lg")
479
-
480
  with gr.Column(scale=2):
481
  outline_output = gr.Textbox(
482
  label="πŸ“ˆ Content Strategy Brief",
@@ -484,16 +483,15 @@ def create_gradio_interface():
484
  max_lines=30,
485
  show_copy_button=True
486
  )
487
-
488
  outline_btn.click(
489
  create_outline_wrapper,
490
  inputs=[api_key_input, outline_topic, outline_scope],
491
  outputs=[outline_output]
492
  )
493
-
494
  gr.Markdown("**πŸ’‘ Example Topics:** Digital Marketing, FinTech, SaaS Operations, Data Science, Cybersecurity")
495
-
496
- # Tab 4: Template Reference
497
  with gr.TabItem("πŸ“„ Template Reference"):
498
  gr.Markdown("### Official Glossary Template Structure")
499
  template_display = gr.Textbox(
@@ -504,33 +502,26 @@ def create_gradio_interface():
504
  interactive=False,
505
  show_copy_button=True
506
  )
507
-
508
  gr.Markdown("""
509
  ---
510
  ## πŸ”§ How to Get Your OpenAI API Key:
511
-
512
  1. **Visit** [platform.openai.com/api-keys](https://platform.openai.com/api-keys)
513
  2. **Sign up** or log in to your OpenAI account
514
- 3. **Add billing information** (GPT-4 requires a paid account)
515
  4. **Create a new secret key**
516
  5. **Copy and paste** it into the field above
517
-
518
- ## πŸ’° **Cost Information:**
519
- - **GPT-4 pricing**: ~$0.03 per 1K input tokens, ~$0.06 per 1K output tokens
520
- - **Per generation**: Approximately $0.02-0.10 depending on content length
521
- - **Very cost-effective** for professional content creation
522
-
523
- ## ✨ **Features:**
524
- - πŸ€– **GPT-4 Powered**: High-quality, professional content generation
525
- - πŸ“ **Template Consistency**: Follows your exact 6-section structure
526
- - πŸ” **Content Analysis**: Detailed improvement recommendations
527
- - πŸ“Š **Strategic Planning**: Comprehensive content briefs and roadmaps
528
- - 🎯 **SEO Optimized**: Includes PAA questions and keyword strategies
529
- - πŸ“‹ **Copy-Friendly**: Easy copy buttons for all outputs
530
- - πŸ”‘ **No Setup Required**: Just enter your API key and start generating!
531
- - πŸ› οΈ **Direct API**: Uses raw HTTP requests to avoid library conflicts
532
  """)
533
-
534
  return demo
535
 
536
  # Launch the application
 
39
  * List URLs, book titles, or other references.
40
  """
41
 
42
+ # ---- Token safety utilities ----
43
+ def _approx_tokens(self, text: str) -> int:
44
+ # Roughly 4 characters per token (very conservative heuristic)
45
+ return max(1, len(text) // 4)
46
+
47
+ def _safe_max_tokens(self, prompt: str, requested_max: int, model_context_limit: int = 128000) -> int:
48
+ """
49
+ Clamp max_tokens so (prompt_tokens + max_tokens) <= model_context_limit.
50
+ We include the system message length as well.
51
+ """
52
+ 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."
53
+ est_prompt_tokens = self._approx_tokens(system_msg) + self._approx_tokens(prompt)
54
+ room = max(256, model_context_limit - est_prompt_tokens) # leave a floor of 256
55
+ return max(1, min(requested_max, room))
56
+
57
  def _test_api_key(self, api_key: str) -> bool:
58
  """Test OpenAI API key with minimal request"""
59
  if not api_key or not api_key.strip():
60
  return False
 
61
  try:
 
62
  from openai import OpenAI
 
63
  client = OpenAI(api_key=api_key.strip())
 
 
64
  response = client.chat.completions.create(
65
+ model="gpt-4-turbo",
66
  messages=[{"role": "user", "content": "Hi"}],
67
  max_tokens=1
68
  )
69
  return True
 
70
  except Exception as e:
71
  print(f"API test error: {e}")
72
  return False
73
 
74
+ def _call_openai_raw(self, api_key: str, prompt: str, model: str = "gpt-4-turbo", max_tokens: int = 1200) -> str:
75
+ """Direct OpenAI API call using requests with safe max_tokens handling"""
76
  import requests
77
  import json
78
+
79
  if not api_key or not api_key.strip():
80
  return "πŸ”‘ Please enter your OpenAI API key above to generate content."
81
+
82
  clean_key = api_key.strip()
83
+
84
+ # Auto-clamp max_tokens based on estimated prompt size and 128k context
85
+ safe_max = self._safe_max_tokens(prompt, requested_max=max_tokens, model_context_limit=128000)
86
+
87
  url = "https://api.openai.com/v1/chat/completions"
88
  headers = {
89
  "Authorization": f"Bearer {clean_key}",
90
  "Content-Type": "application/json"
91
  }
92
+
93
  data = {
94
  "model": model,
95
  "messages": [
96
  {"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."},
97
  {"role": "user", "content": prompt}
98
  ],
99
+ "max_tokens": safe_max,
100
  "temperature": 0.7,
101
  "top_p": 1,
102
  "frequency_penalty": 0,
103
  "presence_penalty": 0
104
  }
105
+
106
  try:
107
  print(f"πŸš€ Making direct API call to OpenAI...")
108
+ print(f"ℹ️ Model: {model} | requested_max: {max_tokens} | safe_max: {safe_max}")
109
+ response = requests.post(url, headers=headers, json=data, timeout=90)
110
  print(f"πŸ“Š Response status: {response.status_code}")
111
+
112
  if response.status_code == 200:
113
  result = response.json()
114
  content = result['choices'][0]['message']['content'].strip()
115
  print("βœ… API call successful")
116
  return content
 
117
  else:
118
+ error_data = {}
119
+ try:
120
+ error_data = response.json() if response.content else {}
121
+ except Exception:
122
+ pass
123
+
124
  error_msg = error_data.get('error', {}).get('message', 'Unknown error')
125
  error_code = error_data.get('error', {}).get('code', 'unknown')
126
+
127
  print(f"❌ API call failed: {response.status_code} - {error_msg}")
128
+
129
  if response.status_code == 401:
130
  return "❌ Invalid API key. Please check your OpenAI API key."
131
  elif response.status_code == 429:
132
  return "❌ Rate limit exceeded. Please wait a moment and try again."
133
+ elif response.status_code == 404 and model == "gpt-4-turbo":
134
  # Try GPT-3.5 fallback
135
  print("πŸ”„ Trying GPT-3.5-turbo fallback...")
136
+ # Recompute safe max for same prompt
137
+ fallback_safe_max = self._safe_max_tokens(prompt, requested_max=max_tokens, model_context_limit=16384) # conservative for 3.5
138
+ return self._call_openai_raw(api_key, prompt, "gpt-3.5-turbo", fallback_safe_max)
139
+ elif "insufficient_quota" in str(error_msg).lower():
140
  return "❌ OpenAI API quota exceeded. Please check your billing at https://platform.openai.com/usage"
141
+ elif "maximum context length" in str(error_msg).lower() or "context length" in str(error_msg).lower():
142
+ return "❌ Context length exceeded. Try shortening your input or lowering max output length."
143
  else:
144
  return f"❌ OpenAI API Error ({response.status_code}): {error_msg}"
145
+
146
  except requests.exceptions.Timeout:
147
  return "❌ Request timeout. Please try again."
148
  except requests.exceptions.RequestException as e:
 
151
  return f"❌ Unexpected error: {str(e)}"
152
 
153
  def generate_new_content(self, api_key: str, term: str, context: str = "", target_audience: str = "general") -> str:
154
+ """Generate new glossary content for a given term (uses gpt-4-turbo)"""
 
155
  if not term.strip():
156
  return "Please enter a term to generate content for."
157
+
158
  prompt = f"""
159
  Create a comprehensive glossary entry for the term "{term}" following this EXACT template structure:
160
  {self.template}
 
177
  - Ensure professional, authoritative tone
178
  Generate the complete glossary entry now:
179
  """
180
+ # Default requested max_tokens for generation; will be auto-clamped
181
+ return self._call_openai_raw(api_key, prompt, model="gpt-4-turbo", max_tokens=1200)
182
 
183
  def update_existing_content(self, api_key: str, term: str, existing_content: str, update_instructions: str = "") -> Tuple[str, str]:
184
+ """Analyze existing content and provide update recommendations, then produce updated content"""
 
185
  if not term.strip() or not existing_content.strip():
186
  return "Please provide both term and existing content.", ""
187
+
 
188
  analysis_prompt = f"""
189
  Analyze this existing glossary content for "{term}" against the template standard and provide specific improvement recommendations.
190
  **EXISTING CONTENT:**
 
217
  - Fact-checking requirements
218
  Format as a professional content analysis report.
219
  """
220
+ recommendations = self._call_openai_raw(api_key, analysis_prompt, model="gpt-4-turbo", max_tokens=1000)
221
+
 
 
222
  update_prompt = f"""
223
  Create an improved version of the glossary entry for "{term}" based on the analysis and recommendations.
224
  **ORIGINAL CONTENT:**
 
238
  7. Enhances SEO and user experience
239
  Generate the complete, improved glossary entry:
240
  """
241
+ updated_content = self._call_openai_raw(api_key, update_prompt, model="gpt-4-turbo", max_tokens=1200)
 
 
242
  return recommendations, updated_content
243
 
244
  def create_outline_brief(self, api_key: str, topic: str, scope: str = "comprehensive") -> str:
245
+ """Create a strategic brief (uses gpt-4-turbo)"""
 
246
  if not topic.strip():
247
  return "Please enter a topic for the outline."
248
+
249
  prompt = f"""
250
  Create a comprehensive content brief for developing a glossary focused on "{topic}".
251
  **Scope:** {scope}
 
291
  - Conversion and utility measurements
292
  Create a comprehensive, actionable brief that will guide the entire glossary development process.
293
  """
294
+ # Slightly larger default for briefs; will still auto-clamp safely
295
+ return self._call_openai_raw(api_key, prompt, model="gpt-4-turbo", max_tokens=1500)
296
 
297
  def create_gradio_interface():
298
  """Create the Gradio interface for the glossary generator"""
299
+
300
  generator = GlossaryGenerator()
301
+
302
  def test_api_key(api_key):
303
  """Test if the API key is valid"""
304
  if not api_key or not api_key.strip():
305
  return "❌ Please enter your OpenAI API key"
306
+
 
307
  clean_key = api_key.strip()
308
  if not clean_key.startswith('sk-'):
309
  return "❌ Invalid format - OpenAI API keys should start with 'sk-'"
 
310
  if len(clean_key) < 20:
311
  return "❌ API key too short - check if you copied the full key"
312
+
313
+ test_result = generator._call_openai_raw(clean_key, "Test", "gpt-4-turbo", 1)
 
 
314
  if "❌" in test_result:
315
  return test_result
316
  else:
317
  return "βœ… API key is valid and connected!"
318
+
319
  def generate_new_wrapper(api_key, term, context, audience):
320
  if not term.strip():
321
  return "Please enter a term to generate content for."
322
  return generator.generate_new_content(api_key, term, context, audience)
323
+
324
  def update_existing_wrapper(api_key, term, existing_content, update_instructions):
325
  if not term.strip() or not existing_content.strip():
326
  return "Please provide both term and existing content.", ""
327
  recommendations, updated_content = generator.update_existing_content(api_key, term, existing_content, update_instructions)
328
  return recommendations, updated_content
329
+
330
  def create_outline_wrapper(api_key, topic, scope):
331
  if not topic.strip():
332
  return "Please enter a topic for the outline."
333
  return generator.create_outline_brief(api_key, topic, scope)
334
+
 
335
  with gr.Blocks(title="Glossary Content Generator", theme=gr.themes.Soft()) as demo:
336
  gr.Markdown("""
337
  # πŸ“š Glossary Content Generator
338
+
339
+ **Powered by OpenAI GPT-4 Turbo** - Professional glossary content creation and optimization tool.
340
+
341
  πŸ”‘ **Enter your OpenAI API key below to get started!**
342
  """)
343
+
 
344
  with gr.Row():
345
  with gr.Column(scale=2):
346
  api_key_input = gr.Textbox(
 
351
  )
352
  with gr.Column(scale=1):
353
  test_key_btn = gr.Button("Test Key", variant="secondary")
354
+ manual_test_btn = gr.Button("Skip Test & Try Anyway", variant="outline")
355
  with gr.Column(scale=1):
356
  key_status = gr.Textbox(
357
  label="Status",
 
359
  interactive=False,
360
  max_lines=2
361
  )
362
+
363
  def manual_override(api_key):
364
  if api_key and api_key.strip():
365
  return "⚠️ Test skipped - trying anyway..."
366
  return "❌ Please enter an API key first"
367
+
368
  test_key_btn.click(
369
  test_api_key,
370
  inputs=[api_key_input],
371
  outputs=[key_status]
372
  )
373
+
374
  manual_test_btn.click(
375
  manual_override,
376
  inputs=[api_key_input],
377
  outputs=[key_status]
378
  )
379
+
380
  gr.Markdown("---")
381
+
382
  with gr.Tabs():
 
383
  with gr.TabItem("πŸ†• Generate New Content"):
384
+ gr.Markdown("### Create a new glossary entry from scratch using GPT-4 Turbo")
385
+
386
  with gr.Row():
387
  with gr.Column(scale=1):
388
  new_term = gr.Textbox(
 
400
  choices=["general", "technical", "business", "beginner", "expert"],
401
  value="general"
402
  )
403
+ generate_btn = gr.Button("πŸš€ Generate Content", variant="primary")
 
404
  with gr.Column(scale=2):
405
  new_output = gr.Textbox(
406
  label="Generated Glossary Entry",
 
408
  max_lines=30,
409
  show_copy_button=True
410
  )
411
+
412
  generate_btn.click(
413
  generate_new_wrapper,
414
  inputs=[api_key_input, new_term, new_context, new_audience],
415
  outputs=[new_output]
416
  )
417
+
 
418
  gr.Markdown("**πŸ’‘ Example Terms:** API, Machine Learning, Blockchain, SaaS, Customer Journey, A/B Testing")
419
+
 
420
  with gr.TabItem("πŸ”„ Update Existing Content"):
421
  gr.Markdown("### Analyze and improve existing glossary entries with AI-powered recommendations")
422
+
423
  with gr.Row():
424
  with gr.Column(scale=1):
425
  update_term = gr.Textbox(
 
437
  placeholder="e.g., 'Add more technical details', 'Include recent developments', 'Improve SEO focus'",
438
  lines=3
439
  )
440
+ update_btn = gr.Button("πŸ” Analyze & Update", variant="primary")
 
441
  with gr.Column(scale=2):
442
  with gr.Row():
443
  recommendations_output = gr.Textbox(
 
453
  max_lines=15,
454
  show_copy_button=True
455
  )
456
+
457
  update_btn.click(
458
  update_existing_wrapper,
459
  inputs=[api_key_input, update_term, existing_content, update_instructions],
460
  outputs=[recommendations_output, updated_content_output]
461
  )
462
+
 
463
  with gr.TabItem("πŸ“‹ Create Content Brief"):
464
  gr.Markdown("### Generate a comprehensive strategy brief for glossary development")
465
+
466
  with gr.Row():
467
  with gr.Column(scale=1):
468
  outline_topic = gr.Textbox(
 
475
  choices=["comprehensive", "focused", "basic", "advanced", "specialized"],
476
  value="comprehensive"
477
  )
478
+ outline_btn = gr.Button("πŸ“‹ Create Strategic Brief", variant="primary")
 
479
  with gr.Column(scale=2):
480
  outline_output = gr.Textbox(
481
  label="πŸ“ˆ Content Strategy Brief",
 
483
  max_lines=30,
484
  show_copy_button=True
485
  )
486
+
487
  outline_btn.click(
488
  create_outline_wrapper,
489
  inputs=[api_key_input, outline_topic, outline_scope],
490
  outputs=[outline_output]
491
  )
492
+
493
  gr.Markdown("**πŸ’‘ Example Topics:** Digital Marketing, FinTech, SaaS Operations, Data Science, Cybersecurity")
494
+
 
495
  with gr.TabItem("πŸ“„ Template Reference"):
496
  gr.Markdown("### Official Glossary Template Structure")
497
  template_display = gr.Textbox(
 
502
  interactive=False,
503
  show_copy_button=True
504
  )
505
+
506
  gr.Markdown("""
507
  ---
508
  ## πŸ”§ How to Get Your OpenAI API Key:
509
+
510
  1. **Visit** [platform.openai.com/api-keys](https://platform.openai.com/api-keys)
511
  2. **Sign up** or log in to your OpenAI account
512
+ 3. **Add billing information** (GPT-4 access requires a paid account)
513
  4. **Create a new secret key**
514
  5. **Copy and paste** it into the field above
515
+
516
+ ## ✨ Features:
517
+ - πŸ€– **GPT-4 Turbo Powered**
518
+ - πŸ“ **Template Consistency**
519
+ - πŸ” **Content Analysis**
520
+ - πŸ“Š **Strategic Briefs**
521
+ - 🎯 **SEO-Oriented Outputs**
522
+ - πŸ”‘ **Direct API (raw HTTP)**
 
 
 
 
 
 
 
523
  """)
524
+
525
  return demo
526
 
527
  # Launch the application