arittrabag commited on
Commit
02e306a
·
verified ·
1 Parent(s): 766f064

Upload 2 files

Browse files
Files changed (2) hide show
  1. enhanced_prompt_builder.py +131 -0
  2. feedback_analyzer.py +228 -0
enhanced_prompt_builder.py ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from enhanced_retriever import EnhancedRetriever
2
+ from enhanced_knowledge_graph import EnhancedKnowledgeGraph
3
+ from feedback_analyzer import FeedbackAnalyzer
4
+ from typing import List, Dict
5
+
6
+ class EnhancedPromptBuilder:
7
+ """Enhanced prompt builder with all advanced features integrated"""
8
+
9
+ def __init__(self):
10
+ self.retriever = EnhancedRetriever()
11
+ self.knowledge_graph = EnhancedKnowledgeGraph()
12
+ self.feedback_analyzer = FeedbackAnalyzer()
13
+
14
+ def build_adaptive_prompt(self, ad_text: str, tone: str, platforms: List[str]) -> str:
15
+ """Build an adaptive prompt using all enhancement layers"""
16
+
17
+ # 1. Get enhanced RAG results with relevance scores
18
+ rag_results = self.retriever.retrieve_with_relevance(tone, platforms)
19
+ formatted_guidance = self.retriever.format_guidance_with_scores(rag_results)
20
+
21
+ # 2. Get knowledge graph insights with traversal
22
+ kg_insights = []
23
+
24
+ # Get recommendations for each platform
25
+ for platform in platforms:
26
+ recommendations = self.knowledge_graph.get_recommendations(tone, platform)
27
+ kg_insights.append(f"\n{platform} Insights:")
28
+ kg_insights.append(f" - Compatibility Score: {recommendations['compatibility_score']:.2f}")
29
+
30
+ if recommendations['suggested_elements']:
31
+ kg_insights.append(" - Suggestions: " + ", ".join(recommendations['suggested_elements']))
32
+
33
+ if recommendations['warnings']:
34
+ kg_insights.append(" - ⚠️ Warnings: " + ", ".join(recommendations['warnings']))
35
+
36
+ if recommendations['creative_types']:
37
+ kg_insights.append(" - Recommended Creative Types: " + ", ".join(recommendations['creative_types']))
38
+
39
+ # Add relationship explanations
40
+ relationship = self.knowledge_graph.explain_relationship(tone, platform)
41
+ kg_insights.append(f" - Relationship: {relationship}")
42
+
43
+ kg_insights_str = "\n".join(kg_insights)
44
+
45
+ # 3. Get adaptive weights from feedback analysis
46
+ weights = self.feedback_analyzer.get_adaptive_weights()
47
+
48
+ # 4. Add performance insights if available
49
+ analysis = self.feedback_analyzer.analyze_patterns()
50
+ performance_notes = []
51
+
52
+ if analysis.get("recommendations"):
53
+ relevant_recs = [rec for rec in analysis["recommendations"]
54
+ if any(p.lower() in rec.lower() for p in platforms) or tone.lower() in rec.lower()]
55
+ if relevant_recs:
56
+ performance_notes.append("\nHistorical Performance Notes:")
57
+ performance_notes.extend([f" - {rec}" for rec in relevant_recs[:3]])
58
+
59
+ performance_str = "\n".join(performance_notes) if performance_notes else ""
60
+
61
+ # 5. Build the enhanced prompt
62
+ platform_str = ", ".join(platforms)
63
+
64
+ # Apply adaptive weights to emphasize better-performing combinations
65
+ weight_notes = []
66
+ for platform in platforms:
67
+ combo_key = f"{tone}_{platform}"
68
+ weight = weights.get(combo_key, 1.0)
69
+ if weight > 0.8:
70
+ weight_notes.append(f" - {platform}: High confidence (historical success)")
71
+ elif weight < 0.6:
72
+ weight_notes.append(f" - {platform}: Needs improvement (based on feedback)")
73
+
74
+ weight_str = "\n".join(weight_notes) if weight_notes else ""
75
+
76
+ prompt = f"""
77
+ You are an expert ad copywriter with access to advanced AI assistance.
78
+
79
+ TASK: Rewrite the following ad text in a {tone} tone and optimize it individually for: {platform_str}
80
+
81
+ ORIGINAL AD TEXT: "{ad_text}"
82
+
83
+ === ENHANCED GUIDANCE (with Relevance Scores) ===
84
+ {formatted_guidance}
85
+
86
+ === KNOWLEDGE GRAPH INSIGHTS ===
87
+ {kg_insights_str}
88
+
89
+ === ADAPTIVE LEARNING INSIGHTS ===
90
+ {weight_str}
91
+ {performance_str}
92
+
93
+ === INSTRUCTIONS ===
94
+ 1. Maintain the core message and key information from the original ad
95
+ 2. Adapt the tone and style according to the guidelines above
96
+ 3. Consider the compatibility scores and warnings for each platform
97
+ 4. Use suggested elements where appropriate
98
+ 5. Avoid any warned elements or approaches
99
+ 6. Apply lessons from historical performance data
100
+
101
+ OUTPUT FORMAT:
102
+ Provide a separate, optimized version for each platform:
103
+
104
+ {''.join([f'{p}:\n<Your rewritten ad text here>\n\n' for p in platforms])}
105
+
106
+ Remember: Each platform version should be uniquely tailored while maintaining brand consistency.
107
+ """
108
+
109
+ return prompt
110
+
111
+ def get_improvement_suggestions(self) -> List[str]:
112
+ """Get suggestions for improving the system based on feedback"""
113
+ analysis = self.feedback_analyzer.analyze_patterns()
114
+ suggestions = []
115
+
116
+ # Check overall performance
117
+ avg_rating = analysis.get("average_rating", 0)
118
+ if avg_rating < 3.5:
119
+ suggestions.append("Consider updating tone guidelines based on feedback patterns")
120
+
121
+ # Check for problematic combinations
122
+ for pattern in analysis.get("low_performing_patterns", []):
123
+ tone, platform = pattern["pattern"].split("_")
124
+ suggestions.append(f"Review and update guidelines for {tone} tone on {platform}")
125
+
126
+ # Suggest new relationships for KG
127
+ high_performers = analysis.get("high_performing_patterns", [])
128
+ if high_performers:
129
+ suggestions.append("Consider strengthening KG relationships for high-performing combinations")
130
+
131
+ return suggestions
feedback_analyzer.py ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ from datetime import datetime
3
+ from typing import Dict, List, Tuple
4
+ from collections import defaultdict
5
+ import statistics
6
+
7
+ class FeedbackAnalyzer:
8
+ """Analyze feedback patterns and provide improvement recommendations"""
9
+
10
+ def __init__(self, feedback_file: str = "feedback_store.json"):
11
+ self.feedback_file = feedback_file
12
+ self.feedback_data = self._load_feedback()
13
+
14
+ def _load_feedback(self) -> List[Dict]:
15
+ """Load feedback from JSON file"""
16
+ try:
17
+ with open(self.feedback_file, 'r', encoding='utf-8') as f:
18
+ return json.load(f)
19
+ except (FileNotFoundError, json.JSONDecodeError):
20
+ return []
21
+
22
+ def analyze_patterns(self) -> Dict[str, any]:
23
+ """Analyze patterns in feedback data"""
24
+ if not self.feedback_data:
25
+ return {"error": "No feedback data available"}
26
+
27
+ analysis = {
28
+ "total_feedback": len(self.feedback_data),
29
+ "average_rating": 0,
30
+ "tone_performance": defaultdict(list),
31
+ "platform_performance": defaultdict(list),
32
+ "tone_platform_combo": defaultdict(list),
33
+ "low_performing_patterns": [],
34
+ "high_performing_patterns": [],
35
+ "recommendations": []
36
+ }
37
+
38
+ # Collect ratings by different dimensions
39
+ all_ratings = []
40
+
41
+ for entry in self.feedback_data:
42
+ rating = entry.get("rating", 0)
43
+ tone = entry.get("tone", "unknown")
44
+ platforms = entry.get("platforms", [])
45
+
46
+ all_ratings.append(rating)
47
+ analysis["tone_performance"][tone].append(rating)
48
+
49
+ for platform in platforms:
50
+ analysis["platform_performance"][platform].append(rating)
51
+ combo_key = f"{tone}_{platform}"
52
+ analysis["tone_platform_combo"][combo_key].append(rating)
53
+
54
+ # Calculate averages
55
+ analysis["average_rating"] = statistics.mean(all_ratings) if all_ratings else 0
56
+
57
+ # Analyze tone performance
58
+ tone_stats = {}
59
+ for tone, ratings in analysis["tone_performance"].items():
60
+ if ratings:
61
+ avg = statistics.mean(ratings)
62
+ tone_stats[tone] = {
63
+ "average": avg,
64
+ "count": len(ratings),
65
+ "std_dev": statistics.stdev(ratings) if len(ratings) > 1 else 0
66
+ }
67
+
68
+ analysis["tone_stats"] = tone_stats
69
+
70
+ # Analyze platform performance
71
+ platform_stats = {}
72
+ for platform, ratings in analysis["platform_performance"].items():
73
+ if ratings:
74
+ avg = statistics.mean(ratings)
75
+ platform_stats[platform] = {
76
+ "average": avg,
77
+ "count": len(ratings),
78
+ "std_dev": statistics.stdev(ratings) if len(ratings) > 1 else 0
79
+ }
80
+
81
+ analysis["platform_stats"] = platform_stats
82
+
83
+ # Find patterns
84
+ combo_stats = {}
85
+ for combo, ratings in analysis["tone_platform_combo"].items():
86
+ if ratings:
87
+ avg = statistics.mean(ratings)
88
+ combo_stats[combo] = {
89
+ "average": avg,
90
+ "count": len(ratings),
91
+ "ratings": ratings
92
+ }
93
+
94
+ # Identify low and high performers
95
+ if avg < 2.5 and len(ratings) >= 2:
96
+ analysis["low_performing_patterns"].append({
97
+ "pattern": combo,
98
+ "average_rating": avg,
99
+ "sample_size": len(ratings)
100
+ })
101
+ elif avg >= 4.0 and len(ratings) >= 2:
102
+ analysis["high_performing_patterns"].append({
103
+ "pattern": combo,
104
+ "average_rating": avg,
105
+ "sample_size": len(ratings)
106
+ })
107
+
108
+ analysis["combo_stats"] = combo_stats
109
+
110
+ # Generate recommendations
111
+ analysis["recommendations"] = self._generate_recommendations(analysis)
112
+
113
+ return analysis
114
+
115
+ def _generate_recommendations(self, analysis: Dict) -> List[str]:
116
+ """Generate actionable recommendations based on analysis"""
117
+ recommendations = []
118
+
119
+ # Tone recommendations
120
+ tone_stats = analysis.get("tone_stats", {})
121
+ for tone, stats in tone_stats.items():
122
+ if stats["average"] < 3.0:
123
+ recommendations.append(
124
+ f"Consider adjusting '{tone}' tone guidelines - average rating is {stats['average']:.2f}"
125
+ )
126
+ elif stats["average"] > 4.5:
127
+ recommendations.append(
128
+ f"'{tone}' tone is performing excellently (avg: {stats['average']:.2f}) - use as reference"
129
+ )
130
+
131
+ # Platform recommendations
132
+ platform_stats = analysis.get("platform_stats", {})
133
+ for platform, stats in platform_stats.items():
134
+ if stats["std_dev"] > 1.5:
135
+ recommendations.append(
136
+ f"{platform} shows high variance (σ={stats['std_dev']:.2f}) - consider more consistent approach"
137
+ )
138
+
139
+ # Combo recommendations
140
+ for pattern in analysis.get("low_performing_patterns", []):
141
+ tone, platform = pattern["pattern"].split("_")
142
+ recommendations.append(
143
+ f"{tone} tone on {platform} is underperforming (avg: {pattern['average_rating']:.2f}) - needs revision"
144
+ )
145
+
146
+ for pattern in analysis.get("high_performing_patterns", []):
147
+ tone, platform = pattern["pattern"].split("_")
148
+ recommendations.append(
149
+ f"{tone} tone on {platform} is a winning combination (avg: {pattern['average_rating']:.2f})"
150
+ )
151
+
152
+ # General recommendations
153
+ overall_avg = analysis.get("average_rating", 0)
154
+ if overall_avg < 3.5:
155
+ recommendations.append(
156
+ "Overall performance needs improvement - consider reviewing prompt templates"
157
+ )
158
+
159
+ if len(analysis.get("feedback_data", [])) < 10:
160
+ recommendations.append(
161
+ "Limited feedback data - collect more samples for reliable patterns"
162
+ )
163
+
164
+ return recommendations
165
+
166
+ def get_adaptive_weights(self) -> Dict[str, float]:
167
+ """Generate adaptive weights for prompt building based on feedback"""
168
+ analysis = self.analyze_patterns()
169
+ weights = {}
170
+
171
+ # Base weights
172
+ default_weight = 1.0
173
+
174
+ # Adjust weights based on performance
175
+ for combo, stats in analysis.get("combo_stats", {}).items():
176
+ if stats["count"] >= 2: # Only adjust if we have enough data
177
+ performance_ratio = stats["average"] / 5.0 # Normalize to 0-1
178
+ weights[combo] = 0.5 + (performance_ratio * 0.5) # Scale between 0.5-1.0
179
+ else:
180
+ weights[combo] = default_weight
181
+
182
+ return weights
183
+
184
+ def get_time_based_trends(self) -> Dict[str, any]:
185
+ """Analyze trends over time"""
186
+ if not self.feedback_data:
187
+ return {"error": "No feedback data available"}
188
+
189
+ # Sort by timestamp
190
+ sorted_feedback = sorted(
191
+ self.feedback_data,
192
+ key=lambda x: datetime.fromisoformat(x.get("timestamp", "2024-01-01"))
193
+ )
194
+
195
+ # Group by day
196
+ daily_ratings = defaultdict(list)
197
+ for entry in sorted_feedback:
198
+ timestamp = datetime.fromisoformat(entry.get("timestamp", "2024-01-01"))
199
+ day = timestamp.date().isoformat()
200
+ daily_ratings[day].append(entry.get("rating", 0))
201
+
202
+ # Calculate daily averages
203
+ trends = {}
204
+ for day, ratings in daily_ratings.items():
205
+ trends[day] = {
206
+ "average_rating": statistics.mean(ratings),
207
+ "count": len(ratings)
208
+ }
209
+
210
+ return trends
211
+
212
+ def export_insights(self, output_file: str = "feedback_insights.json"):
213
+ """Export analysis insights to a file"""
214
+ analysis = self.analyze_patterns()
215
+ trends = self.get_time_based_trends()
216
+ weights = self.get_adaptive_weights()
217
+
218
+ insights = {
219
+ "generated_at": datetime.now().isoformat(),
220
+ "analysis": analysis,
221
+ "trends": trends,
222
+ "adaptive_weights": weights
223
+ }
224
+
225
+ with open(output_file, 'w', encoding='utf-8') as f:
226
+ json.dump(insights, f, indent=2)
227
+
228
+ return insights