yoshizen commited on
Commit
0d4c845
·
verified ·
1 Parent(s): 7c56a86

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +110 -59
app.py CHANGED
@@ -7,6 +7,8 @@ import json
7
  import logging
8
  import time
9
  import sys
 
 
10
 
11
  # Настройка логирования
12
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
@@ -14,43 +16,81 @@ logger = logging.getLogger("GAIA-Mastermind")
14
 
15
  # Конфигурация
16
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
17
- MODEL_NAME = "google/flan-t5-base" # Упрощенная модель для быстрой работы
18
  API_RETRIES = 3
19
  API_TIMEOUT = 30
20
 
 
 
 
 
21
  class GAIAExpert:
 
 
 
 
 
 
 
 
 
22
  def __init__(self):
23
- self.device = "cuda" if torch.cuda.is_available() else "cpu"
24
- logger.info(f"Инициализация модели на {self.device.upper()}")
25
-
26
- try:
 
 
27
  self.tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
28
- self.model = AutoModelForSeq2SeqLM.from_pretrained(
29
- MODEL_NAME,
30
- torch_dtype=torch.float32,
31
- low_cpu_mem_usage=True
32
- ).eval()
33
- logger.info("Модель готова")
34
- except Exception as e:
35
- logger.exception("Ошибка загрузки модели")
36
- raise RuntimeError(f"Ошибка инициализации: {str(e)}")
 
 
 
 
 
 
 
 
 
 
37
 
 
38
  def process_question(self, question: str) -> str:
39
- """Обработка вопроса с минимальной задержкой"""
40
  try:
 
 
 
 
41
  inputs = self.tokenizer(
42
  f"Вопрос: {question}\nОтвет:",
43
  return_tensors="pt",
44
  max_length=256,
45
- truncation=True
 
46
  )
47
 
48
- outputs = self.model.generate(
49
- **inputs,
50
- max_new_tokens=50,
51
- num_beams=1, # Ускорение генерации
52
- early_stopping=True
53
- )
 
 
 
 
 
 
 
54
 
55
  answer = self.tokenizer.decode(outputs[0], skip_special_tokens=True)
56
  return json.dumps({"final_answer": answer.strip()})
@@ -64,13 +104,16 @@ class GAIAEvaluator:
64
  self.submit_url = f"{api_url}/submit"
65
  self.session = requests.Session()
66
  self.session.headers.update({"Content-Type": "application/json"})
 
 
67
 
68
  def run_evaluation(self, username: str, agent_code: str):
69
  """Консольный процесс оценки без интерфейса"""
 
70
  agent = GAIAExpert()
71
 
72
- # Получение вопросов
73
- questions = self._fetch_questions()
74
  if not isinstance(questions, list):
75
  logger.error(f"Ошибка получения вопросов: {questions}")
76
  return 0, 0
@@ -98,42 +141,50 @@ class GAIAEvaluator:
98
  "answer": f"ERROR: {str(e)}"
99
  })
100
 
101
- # Отправка ответов
102
- return self._submit_answers(username, agent_code, answers)
103
 
104
- def _fetch_questions(self):
105
- """Получение вопросов с API"""
106
- try:
107
- response = self.session.get(self.questions_url, timeout=API_TIMEOUT)
108
- if response.status_code == 200:
109
- return response.json()
110
- return f"HTTP error {response.status_code}"
111
- except Exception as e:
112
- return f"Connection error: {str(e)}"
 
 
 
 
113
 
114
- def _submit_answers(self, username: str, agent_code: str, answers: list):
115
- """Отправка ответов на сервер"""
116
- try:
117
- payload = {
118
- "username": username.strip(),
119
- "agent_code": agent_code.strip(),
120
- "answers": answers
121
- }
122
-
123
- response = self.session.post(
124
- self.submit_url,
125
- json=payload,
126
- timeout=API_TIMEOUT * 2
127
- )
128
-
129
- if response.status_code == 200:
130
- result = response.json()
131
- score = result.get("score", 0)
132
- return score, len(answers)
133
- return 0, len(answers)
134
- except Exception as e:
135
- logger.error(f"Ошибка отправки: {str(e)}")
136
- return 0, len(answers)
 
 
 
 
137
 
138
  if __name__ == "__main__":
139
  # Параметры запуска
@@ -153,4 +204,4 @@ if __name__ == "__main__":
153
  if total > 0:
154
  logger.info(f"Точность: {score/total*100:.1f}%")
155
  else:
156
- logger.error("Не удалось обработать ни одного вопроса")
 
7
  import logging
8
  import time
9
  import sys
10
+ import os
11
+ from functools import lru_cache
12
 
13
  # Настройка логирования
14
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
 
16
 
17
  # Конфигурация
18
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
19
+ MODEL_NAME = "google/flan-t5-base" # Используем меньшую модель для быстрой загрузки
20
  API_RETRIES = 3
21
  API_TIMEOUT = 30
22
 
23
+ # Настройка кэширования моделей
24
+ os.environ["TRANSFORMERS_CACHE"] = "/tmp/transformers_cache"
25
+ os.environ["HF_HOME"] = "/tmp/hf_home"
26
+
27
  class GAIAExpert:
28
+ _instance = None
29
+ _is_initialized = False
30
+
31
+ def __new__(cls):
32
+ # Паттерн Singleton для предотвращения повторной загрузки модели
33
+ if cls._instance is None:
34
+ cls._instance = super(GAIAExpert, cls).__new__(cls)
35
+ return cls._instance
36
+
37
  def __init__(self):
38
+ # Инициализируем только один раз
39
+ if not GAIAExpert._is_initialized:
40
+ self.device = "cuda" if torch.cuda.is_available() else "cpu"
41
+ logger.info(f"Инициализация модели на {self.device.upper()}")
42
+
43
+ # Отложенная инициализация - токенизатор загружаем сразу, модель - по требованию
44
  self.tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
45
+ self.model = None
46
+ GAIAExpert._is_initialized = True
47
+
48
+ def _ensure_model_loaded(self):
49
+ """Ленивая загрузка модели только при необходимости"""
50
+ if self.model is None:
51
+ try:
52
+ logger.info("Загрузка модели...")
53
+ # Оптимизированная загрузка модели
54
+ self.model = AutoModelForSeq2SeqLM.from_pretrained(
55
+ MODEL_NAME,
56
+ torch_dtype=torch.float16 if self.device == "cuda" else torch.float32,
57
+ low_cpu_mem_usage=True,
58
+ device_map="auto" # Автоматическое распределение на доступные устройства
59
+ ).eval()
60
+ logger.info("Модель успешно загружена")
61
+ except Exception as e:
62
+ logger.exception("Ошибка загрузки модели")
63
+ raise RuntimeError(f"Ошибка инициализации: {str(e)}")
64
 
65
+ @lru_cache(maxsize=100) # Кэширование ответов для повторяющихся вопросов
66
  def process_question(self, question: str) -> str:
67
+ """Обработка вопроса с оптимизацией и кэшированием"""
68
  try:
69
+ # Загружаем модель только при первом вызове
70
+ self._ensure_model_loaded()
71
+
72
+ # Оптимизированная обработка токенов
73
  inputs = self.tokenizer(
74
  f"Вопрос: {question}\nОтвет:",
75
  return_tensors="pt",
76
  max_length=256,
77
+ truncation=True,
78
+ padding="max_length"
79
  )
80
 
81
+ # Перемещаем тензоры на нужное устройство
82
+ if self.device == "cuda":
83
+ inputs = {k: v.to(self.device) for k, v in inputs.items()}
84
+
85
+ # Оптимизированная генерация
86
+ with torch.no_grad(): # Отключаем вычисление градиентов для экономии памяти
87
+ outputs = self.model.generate(
88
+ **inputs,
89
+ max_new_tokens=50,
90
+ num_beams=1, # Ускорение генерации
91
+ early_stopping=True,
92
+ do_sample=False # Детерминированная генерация для скорости
93
+ )
94
 
95
  answer = self.tokenizer.decode(outputs[0], skip_special_tokens=True)
96
  return json.dumps({"final_answer": answer.strip()})
 
104
  self.submit_url = f"{api_url}/submit"
105
  self.session = requests.Session()
106
  self.session.headers.update({"Content-Type": "application/json"})
107
+ # Настройка повторных попыток и таймаутов
108
+ self.session.mount('https://', requests.adapters.HTTPAdapter(max_retries=API_RETRIES))
109
 
110
  def run_evaluation(self, username: str, agent_code: str):
111
  """Консольный процесс оценки без интерфейса"""
112
+ # Создаем агента только при необходимости
113
  agent = GAIAExpert()
114
 
115
+ # Получение вопросов с повторными попытками
116
+ questions = self._fetch_questions_with_retry()
117
  if not isinstance(questions, list):
118
  logger.error(f"Ошибка получения вопросов: {questions}")
119
  return 0, 0
 
141
  "answer": f"ERROR: {str(e)}"
142
  })
143
 
144
+ # Отправка ответов с повторными попытками
145
+ return self._submit_answers_with_retry(username, agent_code, answers)
146
 
147
+ def _fetch_questions_with_retry(self, max_retries=3):
148
+ """Получение вопросов с API с повторными попытками"""
149
+ for attempt in range(max_retries):
150
+ try:
151
+ response = self.session.get(self.questions_url, timeout=API_TIMEOUT)
152
+ if response.status_code == 200:
153
+ return response.json()
154
+ logger.warning(f"HTTP error {response.status_code}, попытка {attempt+1}/{max_retries}")
155
+ time.sleep(2 ** attempt) # Экспоненциальная задержка между попытками
156
+ except Exception as e:
157
+ logger.warning(f"Connection error: {str(e)}, попытка {attempt+1}/{max_retries}")
158
+ time.sleep(2 ** attempt)
159
+ return f"Failed after {max_retries} attempts"
160
 
161
+ def _submit_answers_with_retry(self, username: str, agent_code: str, answers: list, max_retries=3):
162
+ """Отправка ответов на сервер с повторными попытками"""
163
+ for attempt in range(max_retries):
164
+ try:
165
+ payload = {
166
+ "username": username.strip(),
167
+ "agent_code": agent_code.strip(),
168
+ "answers": answers
169
+ }
170
+
171
+ response = self.session.post(
172
+ self.submit_url,
173
+ json=payload,
174
+ timeout=API_TIMEOUT * 2
175
+ )
176
+
177
+ if response.status_code == 200:
178
+ result = response.json()
179
+ score = result.get("score", 0)
180
+ return score, len(answers)
181
+
182
+ logger.warning(f"HTTP error {response.status_code}, попытка {attempt+1}/{max_retries}")
183
+ time.sleep(2 ** attempt)
184
+ except Exception as e:
185
+ logger.error(f"Ошибка отправки: {str(e)}, попытка {attempt+1}/{max_retries}")
186
+ time.sleep(2 ** attempt)
187
+ return 0, len(answers)
188
 
189
  if __name__ == "__main__":
190
  # Параметры запуска
 
204
  if total > 0:
205
  logger.info(f"Точность: {score/total*100:.1f}%")
206
  else:
207
+ logger.error("Не удалось обработать ни одного вопроса")