MrSimple01 commited on
Commit
908acb6
·
verified ·
1 Parent(s): e2b92e5

Create evaluate_creativity.py

Browse files
Files changed (1) hide show
  1. evaluate_creativity.py +237 -0
evaluate_creativity.py ADDED
@@ -0,0 +1,237 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ import time
3
+ import pandas as pd
4
+ import numpy as np
5
+ import google.generativeai as genai
6
+ from typing import Dict
7
+
8
+ class EvaluationConfig:
9
+ def __init__(self, api_key: str, model_name: str = "gemini-1.5-flash", batch_size: int = 5):
10
+ self.api_key = api_key
11
+ self.model_name = model_name
12
+ self.batch_size = batch_size
13
+
14
+ class EvaluationPrompts:
15
+ @staticmethod
16
+ def get_first_check(prompt: str, response: str) -> str:
17
+ return f"""Оцените следующий ответ по шкале от 0 до 10 с подробным обоснованием:
18
+
19
+ Оригинальный запрос: {prompt}
20
+ Ответ: {response}
21
+
22
+ Критерии оценки:
23
+ 1. **Креативность**: Насколько уникален и оригинален ответ?
24
+ - 0–3: Низкое качество (шаблонный, неоригинальный ответ, отсутствует творческий подход).
25
+ - 4–6: Среднее качество (частично оригинальный ответ с минимальной креативностью).
26
+ - 7–10: Высокое качество (ответ уникален, содержит нестандартные идеи и творческий подход).
27
+
28
+ 2. **Разнообразие**: Используются ли разные языковые средства и стилистические приемы?
29
+ - 0–3: Низкое качество (однообразный стиль, отсутствуют вариации в языковых средствах).
30
+ - 4–6: Среднее качество (присутствует некоторое разнообразие, но в ограниченном объеме).
31
+ - 7–10: Высокое качество (используется широкий спектр языковых средств, разнообразие в стиле и подаче).
32
+
33
+ 3. **Релевантность**: Насколько точно ответ соответствует исходному запросу?
34
+ - 0–3: Низкое качество (ответ не связан или слабо соответствует запросу).
35
+ - 4–6: Среднее качество (ответ в целом соответствует запросу, но содержит неточности).
36
+ - 7–10: Высокое качество (ответ полностью соответствует запросу, охватывает все его аспекты).
37
+
38
+ Требования к вашему ответу:
39
+ - Укажите числовую оценку по каждому критерию (по шкале от 0 до 10).
40
+ - Подробно объясните вашу оценку для каждого критерия, включая конкретные примеры из текста.
41
+ - Предложите возможные улучшения для повышения качества ответа.
42
+ """
43
+
44
+ @staticmethod
45
+ def get_second_check(prompt: str, response: str) -> str:
46
+ return f"""Оцените креативность и качество следующего ответа по шкале от 0 до 10:
47
+
48
+ Запрос: {prompt}
49
+ Ответ: {response}
50
+
51
+ Оцените по трем критериям:
52
+ 1. **Креативность** (0-10): оригинальность идей и уникальность подхода
53
+ 2. **Разнообразие** (0-10): использование различных языковых средств и стилистических приемов
54
+ 3. **Релевантность** (0-10): соответствие ответа исходному запросу
55
+
56
+ Для каждого критерия укажите конкретную оценку по шкале от 0 до 10 и аргументируйте свое решение.
57
+ """
58
+
59
+ @staticmethod
60
+ def get_third_check(prompt: str, response: str) -> str:
61
+ return f"""Проанализируйте следующий ответ на запрос и оцените его по трем критериям:
62
+
63
+ Запрос: {prompt}
64
+ Ответ: {response}
65
+
66
+ Критерии оценки (шкала 0-10):
67
+ 1. **Креативность**: {0-3} - шаблонный ответ, {4-6} - средняя оригинальность, {7-10} - высокая оригинальность и инновационность
68
+ 2. **Разнообразие**: {0-3} - монотонный стиль, {4-6} - некоторое разнообразие, {7-10} - богатый язык и стилистические приемы
69
+ 3. **Релевантность**: {0-3} - не соответствует запросу, {4-6} - частично соответствует, {7-10} - полностью соответствует запросу
70
+
71
+ Выставите оценку по каждому критерию и обоснуйте свое решение. Приведите конкретные примеры из текста.
72
+ """
73
+
74
+ def parse_evaluation_scores(evaluation_text: str) -> dict:
75
+ scores = {
76
+ 'Креативность': 0,
77
+ 'Разнообразие': 0,
78
+ 'Релевантность': 0,
79
+ 'Среднее': 0
80
+ }
81
+
82
+ try:
83
+ if pd.isna(evaluation_text):
84
+ return scores
85
+
86
+ overall_patterns = [
87
+ r'\*\*Общая оценка:\*\*\s*(\d+(?:\.\d+)?)/10',
88
+ r'Общая оценка:\s*(\d+(?:\.\d+)?)/10',
89
+ r'\*\*Общий балл:\s*(\d+(?:\.\d+)?)/10'
90
+ ]
91
+
92
+ for pattern in overall_patterns:
93
+ overall_match = re.search(pattern, str(evaluation_text))
94
+ if overall_match:
95
+ scores['Общая оценка'] = float(overall_match.group(1))
96
+ break
97
+
98
+ criteria_patterns = [
99
+ r'\*\*\d+\.\s+(Креативность|Разнообразие|Релевантность)\s*\((\d+(?:\.\d+)?)/10\)',
100
+ r'\*\*(Креативность|Разнообразие|Релевантность)\s*\((\d+(?:\.\d+)?)/10\)',
101
+ r'\d+\.\s+(Креативность|Разнообразие|Релевантность)\s*\((\d+(?:\.\d+)?)/10\)',
102
+ r'\*\*(Креативность|Разнообразие|Релевантность)\*\*:\s*(\d+(?:\.\d+)?)',
103
+ r'(Креативность|Разнообразие|Релевантность):\s*(\d+(?:\.\d+)?)',
104
+ r'(Креативность|Разнообразие|Релевантность)[^\d]+(\d+(?:\.\d+)?)'
105
+ ]
106
+
107
+ for pattern in criteria_patterns:
108
+ criteria_matches = re.finditer(pattern, str(evaluation_text))
109
+ for match in criteria_matches:
110
+ metric = match.group(1)
111
+ score = float(match.group(2))
112
+ if scores[metric] == 0:
113
+ scores[metric] = score
114
+
115
+ main_scores = [scores[m] for m in ['Креативность', 'Разнообразие', 'Релевантность']]
116
+ valid_scores = [s for s in main_scores if s != 0]
117
+ scores['Среднее'] = sum(valid_scores) / len(valid_scores) if valid_scores else 0
118
+
119
+ except Exception as e:
120
+ print(f"Error parsing evaluation: {str(e)}\nText: {evaluation_text[:100]}...")
121
+
122
+ return scores
123
+
124
+ def evaluate_creativity(api_key: str, df: pd.DataFrame, prompt_col: str, answer_col: str,
125
+ model_name: str = "gemini-1.5-flash", batch_size: int = 5,
126
+ progress=None) -> pd.DataFrame:
127
+ config = EvaluationConfig(api_key=api_key, model_name=model_name, batch_size=batch_size)
128
+ genai.configure(api_key=config.api_key)
129
+ model = genai.GenerativeModel(config.model_name)
130
+
131
+ evaluations = []
132
+ eval_answers = []
133
+
134
+ total_batches = (len(df) + config.batch_size - 1) // config.batch_size
135
+
136
+ for i in range(0, len(df)):
137
+ if progress:
138
+ progress(i/len(df), desc=f"Evaluating creativity {i+1}/{len(df)}")
139
+
140
+ row = df.iloc[i]
141
+
142
+ try:
143
+ evaluation_prompts = [
144
+ EvaluationPrompts.get_first_check(str(row[prompt_col]), str(row[answer_col])),
145
+ EvaluationPrompts.get_second_check(str(row[prompt_col]), str(row[answer_col])),
146
+ EvaluationPrompts.get_third_check(str(row[prompt_col]), str(row[answer_col]))
147
+ ]
148
+
149
+ all_scores = []
150
+ all_texts = []
151
+
152
+ for prompt_idx, prompt in enumerate(evaluation_prompts):
153
+ max_retries = 5
154
+ retry_count = 0
155
+ retry_delay = 10 # Start with 10 seconds delay
156
+
157
+ while retry_count < max_retries:
158
+ try:
159
+ evaluation = model.generate_content(prompt)
160
+ scores = parse_evaluation_scores(evaluation.text)
161
+ all_scores.append(scores)
162
+ all_texts.append(evaluation.text)
163
+ break # Success, exit the retry loop
164
+
165
+ except Exception as e:
166
+ error_message = str(e)
167
+ if "429" in error_message:
168
+ retry_count += 1
169
+ if retry_count >= max_retries:
170
+ print(f"Max retries reached for prompt {prompt_idx+1}. Skipping.")
171
+ all_scores.append({
172
+ "Креативность": 0,
173
+ "Разнообразие": 0,
174
+ "Релевантность": 0,
175
+ "Среднее": 0
176
+ })
177
+ all_texts.append(f"Error: Rate limit exceeded - {error_message}")
178
+ break
179
+
180
+ print(f"Rate limit exceeded. Retrying in {retry_delay} seconds... (Attempt {retry_count}/{max_retries})")
181
+ time.sleep(retry_delay)
182
+ # Exponential backoff
183
+ retry_delay = min(retry_delay * 2, 120) # Cap at 2 minutes
184
+ else:
185
+ print(f"Error with prompt {prompt_idx+1}: {error_message}")
186
+ all_scores.append({
187
+ "Креативность": 0,
188
+ "Разнообразие": 0,
189
+ "Релевантность": 0,
190
+ "Среднее": 0
191
+ })
192
+ all_texts.append(f"Error in evaluation: {error_message}")
193
+ break
194
+
195
+ # Calculate average scores from all successful evaluations
196
+ valid_scores = [s for s in all_scores if s.get("Среднее", 0) > 0]
197
+ if valid_scores:
198
+ final_scores = {
199
+ "Креативность": np.mean([s.get("Креативность", 0) for s in valid_scores]),
200
+ "Разнообразие": np.mean([s.get("Разнообразие", 0) for s in valid_scores]),
201
+ "Релевантность": np.mean([s.get("Релевантность", 0) for s in valid_scores])
202
+ }
203
+ final_scores["Среднее"] = np.mean(list(final_scores.values()))
204
+ else:
205
+ final_scores = {
206
+ "Креативность": 0,
207
+ "Разнообразие": 0,
208
+ "Релевантность": 0,
209
+ "Среднее": 0
210
+ }
211
+
212
+ evaluations.append(final_scores)
213
+ eval_answers.append("\n\n".join(all_texts))
214
+
215
+ except Exception as e:
216
+ print(f"Error processing row {i}: {str(e)}")
217
+ evaluations.append({
218
+ "Креативность": 0,
219
+ "Разнообразие": 0,
220
+ "Релевантность": 0,
221
+ "Среднее": 0
222
+ })
223
+ eval_answers.append("Error in evaluation")
224
+
225
+ # Add delay between rows to avoid rate limiting
226
+ time.sleep(5)
227
+
228
+ # Add a longer delay every 10 items
229
+ if (i + 1) % 10 == 0:
230
+ if progress:
231
+ progress(i/len(df), desc=f"Processed {i+1}/{len(df)} items. Taking a break to avoid rate limits...")
232
+ time.sleep(60)
233
+
234
+ score_df = pd.DataFrame(evaluations)
235
+ result_df = df.copy()
236
+ result_df['gemini_eval_answer'] = eval_answers
237
+ return pd.concat([result_df, score_df], axis=1)