Repository navigation
Expand file tree
/
Copy pathllm.py
More file actions
175 lines (142 loc) · 6.37 KB
/
Copy pathllm.py
File metadata and controls
175 lines (142 loc) · 6.37 KB
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
"""
LLM Service for generating marketing content using OpenAI or Azure OpenAI.
This module handles all interactions with the OpenAI/Azure OpenAI API to generate
channel-specific marketing content for events.
"""
import json
import logging
from typing import Dict, Any
from openai import OpenAI, AzureOpenAI
from app.core.config import settings
logger = logging.getLogger(__name__)
def _get_client():
"""Initialize and return the appropriate OpenAI client based on settings."""
if settings.LLM_PROVIDER == "azure":
logger.info("Using Azure OpenAI (AI Foundry) client")
return AzureOpenAI(
azure_endpoint=settings.AZURE_OPENAI_ENDPOINT,
api_key=settings.AZURE_OPENAI_API_KEY,
api_version=settings.AZURE_OPENAI_API_VERSION,
)
else:
logger.info("Using OpenAI client")
return OpenAI(api_key=settings.OPENAI_API_KEY)
def _get_model():
"""Get the model/deployment name based on provider."""
if settings.LLM_PROVIDER == "azure":
return settings.AZURE_OPENAI_DEPLOYMENT
return "gpt-4o-mini"
client = _get_client()
def generate_marketing_content(
event_data: Dict[str, Any],
feedback: str = None,
previous_content: Dict[str, str] = None,
) -> Dict[str, str]:
"""
Generate channel-specific marketing content for an event.
This function takes event details and uses OpenAI's GPT model to generate
tailored marketing copy for different platforms (Instagram, WhatsApp, Email, etc.)
Args:
event_data: Dictionary containing event details:
- title: Event name
- description: Event description
- location: Where the event takes place
- starts_at: Date/time of the event
- tone: Desired tone (casual, professional, hype)
- perks: Any perks/benefits (optional)
- audience: Target audience (optional)
- rsvp_link: Registration link (optional)
feedback: Optional user feedback for regeneration (e.g., "Make it more casual")
previous_content: Optional previously generated content to refine
Returns:
Dictionary with generated content for each channel:
- instagram: Caption with emojis and hashtags
- whatsapp: Conversational message
- email_subject: Email subject line
- email_body: Email body content
- engage: Campus engagement platform description
"""
# Extract event details with defaults for optional fields
title = event_data.get("title", "")
description = event_data.get("description", "")
location = event_data.get("location", "")
starts_at = event_data.get("starts_at", "")
tone = event_data.get("tone", "casual")
perks = event_data.get("perks", "")
audience = event_data.get("audience", "")
rsvp_link = event_data.get("rsvp_link", "")
# Build the prompt for OpenAI
prompt = f"""You are a marketing copywriter helping a student organization promote their event. Generate channel-specific marketing content that is engaging, concise, and appropriate for each platform.
Event Details:
- Title: {title}
- Description: {description}
- Location: {location}
- Date/Time: {starts_at}
- Tone: {tone}
{f"- Perks: {perks}" if perks else ""}
{f"- Target Audience: {audience}" if audience else ""}
{f"- RSVP Link: {rsvp_link}" if rsvp_link else ""}
Generate content for these channels. Return your response as a valid JSON object with these exact keys:
{{
"instagram": "Instagram caption with emojis and hashtags (max 300 chars)",
"whatsapp": "WhatsApp message - conversational and concise (max 200 chars)",
"email_subject": "Email subject line (max 60 chars)",
"email_body": "Email body - professional but friendly (max 400 chars)",
"engage": "Campus engagement platform description - structured and informative (max 300 chars)"
}}
Guidelines:
- Instagram: Use relevant emojis, 3-5 hashtags, engaging hook
- WhatsApp: Casual, conversational, include key details
- Email Subject: Compelling, clear, action-oriented
- Email Body: Structured with greeting, details, and CTA
- Engage: Professional, all key info (what, when, where, why)
- Tone: Adapt to "{tone}" style
- Include RSVP link naturally if provided
Return ONLY the JSON object, no other text."""
# Add regeneration context if feedback and previous content are provided
if previous_content and feedback:
regeneration_context = f"""
---
REGENERATION REQUEST:
Previously Generated Content:
- Instagram: {previous_content.get('instagram', 'N/A')}
- WhatsApp: {previous_content.get('whatsapp', 'N/A')}
- Email Subject: {previous_content.get('email_subject', 'N/A')}
- Email Body: {previous_content.get('email_body', 'N/A')}
- Engage: {previous_content.get('engage', 'N/A')}
User Feedback: {feedback}
Please regenerate ALL content incorporating this feedback. Keep what worked well from the previous version while addressing the user's concerns. Return the complete JSON with all channels updated."""
prompt += regeneration_context
try:
# Call OpenAI/Azure OpenAI API
response = client.chat.completions.create(
model=_get_model(),
messages=[
{
"role": "system",
"content": "You are a helpful marketing copywriter. Always respond with valid JSON only.",
},
{"role": "user", "content": prompt},
],
max_tokens=1500,
temperature=0.7, # Balance creativity and consistency
)
# Extract the response text
response_text = response.choices[0].message.content
# Parse JSON response
content = json.loads(response_text)
return content
except json.JSONDecodeError as e:
# If JSON parsing fails, return fallback content
logger.warning(f"Failed to parse JSON response: {e}")
logger.debug(f"Response was: {response_text}")
return {
"instagram": f"🎉 {title} - {location} - Don't miss out! #event #campus",
"whatsapp": f"Hey! {title} is happening at {location}. See you there!",
"email_subject": f"You're Invited: {title}",
"email_body": f"Join us for {title} at {location}. {description}",
"engage": f"{title} - {location} - {description}",
}
except Exception as e:
logger.error(f"Error generating content: {e}")
raise