Spaces:
Sleeping
Sleeping
import os | |
import uuid | |
import gradio as gr | |
from openai import OpenAI | |
from langfuse import Langfuse | |
from dotenv import load_dotenv | |
# Load environment variables from .env file if it exists | |
load_dotenv() | |
# Initialize OpenAI client with error handling | |
try: | |
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) | |
except Exception as e: | |
print(f"Warning: OpenAI client initialization failed: {e}") | |
client = None | |
# Initialize Langfuse client with error handling | |
try: | |
langfuse = Langfuse( | |
public_key=os.getenv("LANGFUSE_PUBLIC_KEY"), | |
secret_key=os.getenv("LANGFUSE_SECRET_KEY"), | |
) | |
except Exception as e: | |
print(f"Warning: Langfuse client initialization failed: {e}") | |
langfuse = None | |
def create_chat_interface(): | |
# Initialize session state | |
session_id = str(uuid.uuid4()) | |
# Create a new trace for this session if Langfuse is available | |
trace = None | |
if langfuse: | |
try: | |
trace = langfuse.trace( | |
id=session_id, | |
name="chat_session", | |
metadata={"session_id": session_id} | |
) | |
except Exception as e: | |
print(f"Warning: Failed to create Langfuse trace: {e}") | |
def respond(message, chat_history): | |
if not message: | |
return chat_history, "" | |
# Track user message if Langfuse is available | |
span = None | |
if trace: | |
try: | |
span = trace.span( | |
name="user_message", | |
input={"message": message} | |
) | |
except Exception as e: | |
print(f"Warning: Failed to create Langfuse span: {e}") | |
try: | |
if not client: | |
return chat_history + [(message, "Error: OpenAI client not initialized. Please check your API key.")], "" | |
# Format chat history for OpenAI | |
messages = [ | |
{"role": "system", "content": """ | |
You are GREG LOGAN — brand strategist, provocateur, and author of *Creating a Blockbuster Brand*. | |
Your mission: WRITE WITH ZERO FLUFF. | |
Every sentence punches. Every insight cuts. Every word earns its place. | |
Tone of Voice: | |
- Direct. Punchy. Provocative. | |
- High emotional clarity. No hedging. | |
- You speak in contrasts and stings. You don't explain — you land. | |
You are allergic to: | |
- Clichés and motivational filler | |
- Weak qualifiers ("just", "maybe", "sort of", "pretty good") | |
- Corporate-speak or thought-leader sludge | |
- Passive voice and over-explaining | |
- Warm intros, nice outros, or trying to sound "helpful" | |
You are obsessed with: | |
- Making bold, counterintuitive points | |
- Creating "A vs B" contrast frames to spark clarity | |
- Short, high-impact sentence structure | |
- Emotionally resonant insight rooted in real systems | |
- Writing like a challenger brand, never a cheerleader | |
Ground Rules: | |
- You are NOT a coach. You are a strategic weapon. | |
- Lead with TRUTH, not encouragement. | |
- One idea per sentence. Two max. | |
- Speak in absolutes. No hedging. | |
- Cut anything that doesn't hit. | |
Output Formats: | |
- Social posts (hooks, carousels, threads) | |
- Email subject lines and body copy | |
- Sales page headlines and system copy | |
- Positioning statements and product narratives | |
- Influencer kit intros and brand voice scripts | |
- Short-form video scripts and outlines | |
Style Examples: | |
> Builders win. | |
> They don't wait for trends. They architect them. | |
> And while the rest are stuck playing catch-up, they attract what everyone else is chasing. | |
> Branding isn't about logos. It's about leverage. | |
> Get the system right, and the visuals become obvious. | |
> Miss the system, and you'll be rebranding every 18 months. | |
> Your audience isn't confused. | |
> They're bored. | |
> Clarity isn't the goal. Emotional sharpness is. | |
You are here to provoke, clarify, and reposition. | |
Write like the stakes are real. Because they are. | |
"""} | |
] | |
# Add chat history | |
for user_msg, assistant_msg in chat_history: | |
messages.append({"role": "user", "content": user_msg}) | |
messages.append({"role": "assistant", "content": assistant_msg}) | |
# Add current message | |
messages.append({"role": "user", "content": message}) | |
# Get response from OpenAI | |
response = client.chat.completions.create( | |
model="gpt-3.5-turbo", | |
messages=messages | |
) | |
assistant_message = response.choices[0].message.content | |
# Track assistant response if Langfuse is available | |
if span: | |
try: | |
span.end( | |
output={"response": assistant_message}, | |
metadata={ | |
"model": "gpt-3.5-turbo", | |
"tokens": response.usage.total_tokens | |
} | |
) | |
except Exception as e: | |
print(f"Warning: Failed to end Langfuse span: {e}") | |
chat_history.append((message, assistant_message)) | |
return chat_history, "" | |
except Exception as e: | |
# End span with error if Langfuse is available | |
if span: | |
try: | |
span.end( | |
output={"error": str(e)}, | |
level="ERROR" | |
) | |
except Exception as span_error: | |
print(f"Warning: Failed to end Langfuse span with error: {span_error}") | |
error_message = f"Error: {str(e)}" | |
return chat_history + [(message, error_message)], "" | |
# Create Gradio interface | |
with gr.Blocks() as demo: | |
gr.Markdown("# Greg Logan AI - Brand Strategy Assistant") | |
gr.Markdown("Get direct, punchy, and provocative brand strategy insights from Greg Logan's perspective.") | |
chatbot = gr.Chatbot(height=600) | |
with gr.Row(): | |
msg = gr.Textbox( | |
show_label=False, | |
placeholder="Enter your message here...", | |
container=False | |
) | |
submit = gr.Button("Send") | |
submit.click(respond, [msg, chatbot], [chatbot, msg]) | |
msg.submit(respond, [msg, chatbot], [chatbot, msg]) | |
return demo | |
# Create and launch the interface | |
demo = create_chat_interface() | |
demo.launch() |