[ZILANT] коррекция работы фронта с долгим ответом ИИ
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
+16
-2
@@ -1011,12 +1011,23 @@ def api_generate_shortname(post_id):
|
|||||||
try:
|
try:
|
||||||
post = db.get_post(post_id)
|
post = db.get_post(post_id)
|
||||||
if not post:
|
if not post:
|
||||||
return jsonify({'error': 'Post not found'}), 404
|
return jsonify({'success': False, 'error': 'Post not found'}), 404
|
||||||
|
|
||||||
log_event(f"Генерация названия для поста ID: {post_id}")
|
log_event(f"Генерация названия для поста ID: {post_id}")
|
||||||
shortname = generate_ai_shortname(post['text'])
|
shortname = generate_ai_shortname(post['text'])
|
||||||
|
if not shortname:
|
||||||
|
return jsonify({
|
||||||
|
'success': False,
|
||||||
|
'error': 'Не удалось сгенерировать название (пустой ответ AI)',
|
||||||
|
}), 500
|
||||||
|
|
||||||
|
# После долгого AI-запроса MySQL-соединение могло протухнуть
|
||||||
|
try:
|
||||||
|
db.conn.ping(reconnect=True)
|
||||||
|
except Exception:
|
||||||
|
db.close()
|
||||||
|
db = get_db()
|
||||||
|
|
||||||
# Обновляем shortname в базе данных
|
|
||||||
with db.conn.cursor() as cursor:
|
with db.conn.cursor() as cursor:
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"UPDATE posts SET shortname = %s WHERE id = %s",
|
"UPDATE posts SET shortname = %s WHERE id = %s",
|
||||||
@@ -1031,7 +1042,10 @@ def api_generate_shortname(post_id):
|
|||||||
log_event(error_msg)
|
log_event(error_msg)
|
||||||
return jsonify({'success': False, 'error': error_msg}), 500
|
return jsonify({'success': False, 'error': error_msg}), 500
|
||||||
finally:
|
finally:
|
||||||
|
try:
|
||||||
db.close()
|
db.close()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
@bp.route('/api/publish_post/<int:post_id>', methods=['POST'])
|
@bp.route('/api/publish_post/<int:post_id>', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
|
|||||||
+18
-8
@@ -91,7 +91,7 @@ def _generate_shortname_by_api(text):
|
|||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = requests.post(url, headers=headers, json=data, timeout=60)
|
response = requests.post(url, headers=headers, json=data, timeout=180)
|
||||||
|
|
||||||
# Обработка ошибки 429 (Too Many Requests)
|
# Обработка ошибки 429 (Too Many Requests)
|
||||||
if response.status_code == 429:
|
if response.status_code == 429:
|
||||||
@@ -109,12 +109,14 @@ def _generate_shortname_by_api(text):
|
|||||||
|
|
||||||
log_message(f"Ошибка 429: Превышен лимит запросов. Ответ API: {json.dumps(error_info, ensure_ascii=False)}")
|
log_message(f"Ошибка 429: Превышен лимит запросов. Ответ API: {json.dumps(error_info, ensure_ascii=False)}")
|
||||||
print("Ошибка 429: Превышен лимит запросов. Подробности в логе.")
|
print("Ошибка 429: Превышен лимит запросов. Подробности в логе.")
|
||||||
sys.exit(1)
|
# Не sys.exit — эта функция вызывается и из веб-API Flask
|
||||||
|
raise RuntimeError("RouterAI 429: превышен лимит запросов")
|
||||||
|
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
result = response.json()
|
result = response.json()
|
||||||
|
|
||||||
# Извлекаем только текст ответа
|
# Извлекаем только текст ответа (у thinking-моделей ответ в content,
|
||||||
|
# рассуждения — в reasoning_content / reasoning)
|
||||||
message = result['choices'][0]['message']
|
message = result['choices'][0]['message']
|
||||||
shortname = (message.get('content') or '').strip()
|
shortname = (message.get('content') or '').strip()
|
||||||
if not shortname:
|
if not shortname:
|
||||||
@@ -123,6 +125,12 @@ def _generate_shortname_by_api(text):
|
|||||||
|
|
||||||
# Удаляем возможные кавычки и лишние символы
|
# Удаляем возможные кавычки и лишние символы
|
||||||
shortname = re.sub(r'^["\']|["\']$', '', shortname)
|
shortname = re.sub(r'^["\']|["\']$', '', shortname)
|
||||||
|
# Если модель вернула многострочный ответ — берём первую непустую строку
|
||||||
|
for line in shortname.splitlines():
|
||||||
|
line = line.strip()
|
||||||
|
if line:
|
||||||
|
shortname = line
|
||||||
|
break
|
||||||
|
|
||||||
# Обрезаем до 80 символов
|
# Обрезаем до 80 символов
|
||||||
return shortname[:80]
|
return shortname[:80]
|
||||||
@@ -143,12 +151,14 @@ def _generate_shortname_by_api(text):
|
|||||||
|
|
||||||
log_message(f"Ошибка 429: Превышен лимит запросов. Ответ API: {json.dumps(error_info, ensure_ascii=False)}")
|
log_message(f"Ошибка 429: Превышен лимит запросов. Ответ API: {json.dumps(error_info, ensure_ascii=False)}")
|
||||||
print("Ошибка 429: Превышен лимит запросов. Подробности в логе.")
|
print("Ошибка 429: Превышен лимит запросов. Подробности в логе.")
|
||||||
sys.exit(1)
|
raise RuntimeError("RouterAI 429: превышен лимит запросов")
|
||||||
else:
|
else:
|
||||||
error_msg = f"HTTP ошибка при генерации названия: {e}"
|
error_msg = f"HTTP ошибка при генерации названия: {e}"
|
||||||
log_message(error_msg)
|
log_message(error_msg)
|
||||||
print(error_msg)
|
print(error_msg)
|
||||||
return None
|
return None
|
||||||
|
except RuntimeError:
|
||||||
|
raise
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error_msg = f"Ошибка при генерации названия: {e}"
|
error_msg = f"Ошибка при генерации названия: {e}"
|
||||||
log_message(error_msg)
|
log_message(error_msg)
|
||||||
@@ -238,10 +248,10 @@ def ai_shortname_all():
|
|||||||
|
|
||||||
log_message("Обработка всех записей завершена")
|
log_message("Обработка всех записей завершена")
|
||||||
print("Обработка завершена")
|
print("Обработка завершена")
|
||||||
except SystemExit:
|
except RuntimeError as e:
|
||||||
# Перехватываем системный выход для корректного закрытия соединения
|
# 429 и прочие явные ошибки RouterAI
|
||||||
log_message("Завершение работы из-за ошибки 429")
|
log_message(f"Завершение работы: {e}")
|
||||||
print("Завершение работы из-за ошибки 429")
|
print(f"Завершение работы: {e}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error_msg = f"Произошла ошибка при обработке записей: {e}"
|
error_msg = f"Произошла ошибка при обработке записей: {e}"
|
||||||
log_message(error_msg)
|
log_message(error_msg)
|
||||||
|
|||||||
+32
-9
@@ -1579,23 +1579,46 @@
|
|||||||
'X-Requested-With': 'XMLHttpRequest'
|
'X-Requested-With': 'XMLHttpRequest'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(response => response.json())
|
.then(async response => {
|
||||||
.then(data => {
|
let data = null;
|
||||||
|
try {
|
||||||
|
data = await response.json();
|
||||||
|
} catch (e) {
|
||||||
|
// Прокси мог оборвать долгий ответ (502/504 HTML) — название часто уже в БД
|
||||||
|
throw new Error(
|
||||||
|
`Сервер вернул не-JSON (HTTP ${response.status}). ` +
|
||||||
|
`Если запрос был долгим, название могло уже сохраниться — обновите список.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error((data && data.error) || `HTTP ${response.status}`);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
})
|
||||||
|
.then(async data => {
|
||||||
hideProcessingMessage();
|
hideProcessingMessage();
|
||||||
if (data.success) {
|
if (data && data.success) {
|
||||||
alert('Название успешно сгенерировано: ' + data.shortname);
|
alert('Название успешно сгенерировано: ' + data.shortname);
|
||||||
loadPosts(); // Перезагружаем список постов
|
await loadPosts();
|
||||||
// Восстанавливаем выбранный пост
|
|
||||||
highlightSelectedPost(postId);
|
highlightSelectedPost(postId);
|
||||||
showPostDetails(postId);
|
await showPostDetails(postId);
|
||||||
} else {
|
} else {
|
||||||
alert('Ошибка генерации названия: ' + (data.error || 'неизвестная ошибка'));
|
alert('Ошибка генерации названия: ' + ((data && data.error) || 'неизвестная ошибка'));
|
||||||
|
await loadPosts();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(async error => {
|
||||||
hideProcessingMessage();
|
hideProcessingMessage();
|
||||||
console.error('Ошибка генерации названия:', error);
|
console.error('Ошибка генерации названия:', error);
|
||||||
alert('Произошла ошибка при генерации названия');
|
// После таймаута прокси название часто уже записано — подтянем список
|
||||||
|
try {
|
||||||
|
await loadPosts();
|
||||||
|
highlightSelectedPost(postId);
|
||||||
|
await showPostDetails(postId);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Не удалось обновить список после ошибки:', e);
|
||||||
|
}
|
||||||
|
alert('Ошибка при генерации названия: ' + (error.message || error));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Функция для публикации конкретного поста
|
// Функция для публикации конкретного поста
|
||||||
|
|||||||
Reference in New Issue
Block a user