Nefertury commited on
Commit
166f868
·
verified ·
1 Parent(s): 15de1d7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +29 -54
app.py CHANGED
@@ -10,19 +10,14 @@ from peft import PeftModel
10
 
11
  # --- 1. Конфигурация и загрузка модели ---
12
 
13
- # ID базовой модели
14
  BASE_MODEL_ID = "Tweeties/tweety-7b-tatar-v24a"
15
-
16
- # ID адаптера и ключи API загружаются из переменных окружения Render
17
  ADAPTER_ID = os.getenv("ADAPTER_ID")
18
  YANDEX_API_KEY = os.getenv("YANDEX_API_KEY")
19
  YANDEX_FOLDER_ID = os.getenv("YANDEX_FOLDER_ID")
20
 
21
- # Проверяем, что все переменные окружения установлены
22
  if not all([ADAPTER_ID, YANDEX_API_KEY, YANDEX_FOLDER_ID]):
23
  raise ValueError("Необходимо установить переменные окружения: ADAPTER_ID, YANDEX_API_KEY, YANDEX_FOLDER_ID")
24
 
25
- # Параметры генерации
26
  MAX_NEW_TOKENS = 256
27
  TEMPERATURE = 0.7
28
  TOP_P = 0.9
@@ -34,44 +29,39 @@ SYS_PROMPT_TT = (
34
  )
35
 
36
  print("Загрузка модели с 4-битной квантизацией...")
37
- # Используем квантизацию для экономии оперативной памяти
38
- quantization_config = BitsAndBytesConfig(
39
- load_in_4bit=True,
40
- bnb_4bit_compute_dtype=torch.bfloat16
41
- )
42
-
43
- # Загружаем токенизатор из приватного репозитория
44
- # Библиотека transformers автоматически использует токен HF_TOKEN из переменных окружения
45
  tok = AutoTokenizer.from_pretrained(ADAPTER_ID, use_fast=False)
46
  if tok.pad_token is None:
47
  tok.pad_token = tok.eos_token
48
-
49
- base = AutoModelForCausalLM.from_pretrained(
50
- BASE_MODEL_ID,
51
- quantization_config=quantization_config,
52
- device_map="auto",
53
- )
54
-
55
  print("Применяем LoRA адаптер...")
56
  model = PeftModel.from_pretrained(base, ADAPTER_ID)
57
  model.config.use_cache = True
58
  model.eval()
59
  print("✅ Модель успешно загружена!")
60
 
61
-
62
  # --- 2. Логика приложения (функции перевода и генерации) ---
63
 
64
  YANDEX_TRANSLATE_URL = "https://translate.api.cloud.yandex.net/translate/v2/translate"
65
- generation_lock = Lock() # Для обработки одного запроса за раз
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
  def _yandex_translate(texts: List[str], source: str, target: str) -> List[str]:
68
  headers = {"Authorization": f"Api-Key {YANDEX_API_KEY}"}
69
- payload = {
70
- "folderId": YANDEX_FOLDER_ID,
71
- "texts": texts,
72
- "sourceLanguageCode": source,
73
- "targetLanguageCode": target,
74
- }
75
  try:
76
  resp = requests.post(YANDEX_TRANSLATE_URL, headers=headers, json=payload, timeout=30)
77
  resp.raise_for_status()
@@ -88,7 +78,6 @@ def tt2ru(text: str) -> str:
88
  return _yandex_translate([text], "tt", "ru")[0]
89
 
90
  def render_prompt(messages: List[Dict[str, str]]) -> str:
91
- # Ваша функция рендеринга промпта без изменений
92
  if getattr(tok, "chat_template", None):
93
  try:
94
  return tok.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
@@ -125,41 +114,30 @@ def generate_tt_reply(messages: List[Dict[str, str]]) -> str:
125
  with generation_lock:
126
  prompt = render_prompt(messages)
127
  inputs = tok(prompt, return_tensors="pt").to(model.device)
128
- out = model.generate(
129
- **inputs,
130
- max_new_tokens=MAX_NEW_TOKENS,
131
- do_sample=True,
132
- temperature=TEMPERATURE,
133
- top_p=TOP_P,
134
- repetition_penalty=REPETITION_PENALTY,
135
- eos_token_id=tok.eos_token_id,
136
- pad_token_id=tok.pad_token_id,
137
- )
138
  gen_text = tok.decode(out[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True)
139
  return gen_text.strip()
140
 
141
-
142
-
143
-
144
  # --- 3. Gradio интерфейс ---
145
 
146
  def chat_fn(message, history):
147
- # message -> ваш новый вопрос на русском
148
- # history -> предыдущий диалог, который теперь будет на татарском
149
-
150
  # 1. Формируем историю для модели
151
  messages = [{"role": "system", "content": SYS_PROMPT_TT}]
152
- # Теперь user_msg и bot_msg в истории уже на татарском, их не нужно переводить
153
  for user_msg, bot_msg in history:
154
  messages.append({"role": "user", "content": user_msg})
155
- if bot_msg: # Ответ бота может отсутствовать, если пользователь отправил сообщение
156
  messages.append({"role": "assistant", "content": bot_msg})
157
 
158
- # 2. Переводим ваш новый русский вопрос на татарский
159
- user_tt = ru2tt(message)
 
 
 
 
 
160
  messages.append({"role": "user", "content": user_tt})
161
 
162
- # 3. Генерируем ответ модели (он уже на татарском)
163
  tt_reply = generate_tt_reply(messages)
164
 
165
  # 4. Добавляем в историю татарский вопрос и татарский ответ
@@ -172,10 +150,7 @@ def chat_fn(message, history):
172
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
173
  gr.Markdown("## Татарский чат-бот от команды Сбера")
174
  chatbot = gr.Chatbot(label="Диалог", height=500)
175
- msg = gr.Textbox(
176
- label="Хәбәрегезне рус телендә языгыз",
177
- placeholder="Татарстанның башкаласы нинди шәһәр?"
178
- )
179
  clear = gr.Button("🗑️ Чистарту")
180
 
181
  msg.submit(chat_fn, inputs=[msg, chatbot], outputs=chatbot)
 
10
 
11
  # --- 1. Конфигурация и загрузка модели ---
12
 
 
13
  BASE_MODEL_ID = "Tweeties/tweety-7b-tatar-v24a"
 
 
14
  ADAPTER_ID = os.getenv("ADAPTER_ID")
15
  YANDEX_API_KEY = os.getenv("YANDEX_API_KEY")
16
  YANDEX_FOLDER_ID = os.getenv("YANDEX_FOLDER_ID")
17
 
 
18
  if not all([ADAPTER_ID, YANDEX_API_KEY, YANDEX_FOLDER_ID]):
19
  raise ValueError("Необходимо установить переменные окружения: ADAPTER_ID, YANDEX_API_KEY, YANDEX_FOLDER_ID")
20
 
 
21
  MAX_NEW_TOKENS = 256
22
  TEMPERATURE = 0.7
23
  TOP_P = 0.9
 
29
  )
30
 
31
  print("Загрузка модели с 4-битной квантизацией...")
32
+ quantization_config = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_compute_dtype=torch.bfloat16)
 
 
 
 
 
 
 
33
  tok = AutoTokenizer.from_pretrained(ADAPTER_ID, use_fast=False)
34
  if tok.pad_token is None:
35
  tok.pad_token = tok.eos_token
36
+ base = AutoModelForCausalLM.from_pretrained(BASE_MODEL_ID, quantization_config=quantization_config, device_map="auto")
 
 
 
 
 
 
37
  print("Применяем LoRA адаптер...")
38
  model = PeftModel.from_pretrained(base, ADAPTER_ID)
39
  model.config.use_cache = True
40
  model.eval()
41
  print("✅ Модель успешно загружена!")
42
 
 
43
  # --- 2. Логика приложения (функции перевода и генерации) ---
44
 
45
  YANDEX_TRANSLATE_URL = "https://translate.api.cloud.yandex.net/translate/v2/translate"
46
+ YANDEX_DETECT_URL = "https://translate.api.cloud.yandex.net/translate/v2/detect" # НОВЫЙ URL ДЛЯ ОПРЕДЕЛЕНИЯ ЯЗЫКА
47
+ generation_lock = Lock()
48
+
49
+ # НОВАЯ ФУНКЦИЯ для определения языка 🧠
50
+ def detect_language(text: str) -> str:
51
+ headers = {"Authorization": f"Api-Key {YANDEX_API_KEY}"}
52
+ payload = {"folderId": YANDEX_FOLDER_ID, "text": text}
53
+ try:
54
+ resp = requests.post(YANDEX_DETECT_URL, headers=headers, json=payload, timeout=10)
55
+ resp.raise_for_status()
56
+ data = resp.json()
57
+ return data.get("languageCode", "ru") # Если не определился, считаем, что русский
58
+ except requests.exceptions.RequestException as e:
59
+ print(f"Ошибка определения языка: {e}")
60
+ return "ru" # В случае ошибки считаем, что это русский для безопасности
61
 
62
  def _yandex_translate(texts: List[str], source: str, target: str) -> List[str]:
63
  headers = {"Authorization": f"Api-Key {YANDEX_API_KEY}"}
64
+ payload = {"folderId": YANDEX_FOLDER_ID, "texts": texts, "sourceLanguageCode": source, "targetLanguageCode": target}
 
 
 
 
 
65
  try:
66
  resp = requests.post(YANDEX_TRANSLATE_URL, headers=headers, json=payload, timeout=30)
67
  resp.raise_for_status()
 
78
  return _yandex_translate([text], "tt", "ru")[0]
79
 
80
  def render_prompt(messages: List[Dict[str, str]]) -> str:
 
81
  if getattr(tok, "chat_template", None):
82
  try:
83
  return tok.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
 
114
  with generation_lock:
115
  prompt = render_prompt(messages)
116
  inputs = tok(prompt, return_tensors="pt").to(model.device)
117
+ out = model.generate(**inputs, max_new_tokens=MAX_NEW_TOKENS, do_sample=True, temperature=TEMPERATURE, top_p=TOP_P, repetition_penalty=REPETITION_PENALTY, eos_token_id=tok.eos_token_id, pad_token_id=tok.pad_token_id)
 
 
 
 
 
 
 
 
 
118
  gen_text = tok.decode(out[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True)
119
  return gen_text.strip()
120
 
 
 
 
121
  # --- 3. Gradio интерфейс ---
122
 
123
  def chat_fn(message, history):
 
 
 
124
  # 1. Формируем историю для модели
125
  messages = [{"role": "system", "content": SYS_PROMPT_TT}]
 
126
  for user_msg, bot_msg in history:
127
  messages.append({"role": "user", "content": user_msg})
128
+ if bot_msg:
129
  messages.append({"role": "assistant", "content": bot_msg})
130
 
131
+ # 2. ОПРЕДЕЛЯЕМ ЯЗЫК и переводим, если нужно 🛡️
132
+ detected_lang = detect_language(message)
133
+ if detected_lang != "tt":
134
+ user_tt = ru2tt(message)
135
+ else:
136
+ user_tt = message # Уже на татарском, используем как есть
137
+
138
  messages.append({"role": "user", "content": user_tt})
139
 
140
+ # 3. Генерируем ответ модели
141
  tt_reply = generate_tt_reply(messages)
142
 
143
  # 4. Добавляем в историю татарский вопрос и татарский ответ
 
150
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
151
  gr.Markdown("## Татарский чат-бот от команды Сбера")
152
  chatbot = gr.Chatbot(label="Диалог", height=500)
153
+ msg = gr.Textbox(label="Хәбәрегезне рус яки татар телендә языгыз", placeholder="Татарстанның башкаласы нинди шәһәр?")
 
 
 
154
  clear = gr.Button("🗑️ Чистарту")
155
 
156
  msg.submit(chat_fn, inputs=[msg, chatbot], outputs=chatbot)