This commit is contained in:
+113
-6
@@ -30,6 +30,79 @@ ROUTERAI_CONFIG = {
|
|||||||
# Настройки журналирования
|
# Настройки журналирования
|
||||||
LOG_FILE = os.getenv('LOG_FILE', 'ai_namer.log') # Путь к лог-файлу
|
LOG_FILE = os.getenv('LOG_FILE', 'ai_namer.log') # Путь к лог-файлу
|
||||||
LOG_PREFIX = "AI_namer" # Уникальный префикс для идентификации скрипта
|
LOG_PREFIX = "AI_namer" # Уникальный префикс для идентификации скрипта
|
||||||
|
LOG_AI_RESPONSE_MAX = int(os.getenv('LOG_AI_RESPONSE_MAX', '8000')) # обрезка длинных полей в логе
|
||||||
|
|
||||||
|
|
||||||
|
def _truncate_for_log(value, max_len=None):
|
||||||
|
"""Обрезает длинные значения для журнала, не теряя информацию о размере."""
|
||||||
|
if value is None:
|
||||||
|
return None
|
||||||
|
if not isinstance(value, str):
|
||||||
|
value = json.dumps(value, ensure_ascii=False, default=str)
|
||||||
|
limit = max_len if max_len is not None else LOG_AI_RESPONSE_MAX
|
||||||
|
if len(value) <= limit:
|
||||||
|
return value
|
||||||
|
return f"{value[:limit]}... [обрезано, всего {len(value)} символов]"
|
||||||
|
|
||||||
|
|
||||||
|
def _message_fields_for_log(message):
|
||||||
|
"""Все значимые поля message из ответа chat/completions."""
|
||||||
|
if not message:
|
||||||
|
return {}
|
||||||
|
logged = {}
|
||||||
|
for key in (
|
||||||
|
'role', 'content', 'reasoning_content', 'reasoning',
|
||||||
|
'refusal', 'tool_calls', 'function_call', 'audio',
|
||||||
|
):
|
||||||
|
if key not in message:
|
||||||
|
continue
|
||||||
|
value = message.get(key)
|
||||||
|
if value in (None, '', [], {}):
|
||||||
|
logged[key] = value
|
||||||
|
elif isinstance(value, str):
|
||||||
|
logged[key] = _truncate_for_log(value)
|
||||||
|
else:
|
||||||
|
logged[key] = _truncate_for_log(json.dumps(value, ensure_ascii=False, default=str))
|
||||||
|
return logged
|
||||||
|
|
||||||
|
|
||||||
|
def _log_routerai_request(text, prompt):
|
||||||
|
"""Журнал параметров исходящего запроса (без API-ключа)."""
|
||||||
|
log_message(
|
||||||
|
"Запрос RouterAI: "
|
||||||
|
f"model={ROUTERAI_CONFIG['model']}, "
|
||||||
|
f"text_len={len(text)}, prompt_len={len(prompt)}, "
|
||||||
|
f"text_preview={_truncate_for_log(text.strip(), 300)}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _log_routerai_response(response, result=None, error_body=None):
|
||||||
|
"""Подробный журнал HTTP-ответа RouterAI."""
|
||||||
|
payload = {
|
||||||
|
"http_status": getattr(response, 'status_code', None),
|
||||||
|
"model": ROUTERAI_CONFIG.get('model'),
|
||||||
|
}
|
||||||
|
if result is not None:
|
||||||
|
payload["response_id"] = result.get("id")
|
||||||
|
payload["object"] = result.get("object")
|
||||||
|
payload["created"] = result.get("created")
|
||||||
|
payload["usage"] = result.get("usage")
|
||||||
|
payload["system_fingerprint"] = result.get("system_fingerprint")
|
||||||
|
choices = result.get("choices") or []
|
||||||
|
payload["choices_count"] = len(choices)
|
||||||
|
payload["choices"] = []
|
||||||
|
for i, choice in enumerate(choices):
|
||||||
|
payload["choices"].append({
|
||||||
|
"index": choice.get("index", i),
|
||||||
|
"finish_reason": choice.get("finish_reason"),
|
||||||
|
"message": _message_fields_for_log(choice.get("message") or {}),
|
||||||
|
"logprobs": choice.get("logprobs"),
|
||||||
|
})
|
||||||
|
if result.get("error"):
|
||||||
|
payload["api_error"] = result.get("error")
|
||||||
|
if error_body is not None:
|
||||||
|
payload["error_body"] = _truncate_for_log(error_body)
|
||||||
|
log_message(f"Ответ RouterAI: {json.dumps(payload, ensure_ascii=False, default=str)}")
|
||||||
|
|
||||||
def log_message(message, max_retries=5, retry_delay=0.1):
|
def log_message(message, max_retries=5, retry_delay=0.1):
|
||||||
"""
|
"""
|
||||||
@@ -89,6 +162,8 @@ def _generate_shortname_by_api(text):
|
|||||||
"max_tokens": 5000,
|
"max_tokens": 5000,
|
||||||
"temperature": 0.3,
|
"temperature": 0.3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_log_routerai_request(text, prompt)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = requests.post(url, headers=headers, json=data, timeout=180)
|
response = requests.post(url, headers=headers, json=data, timeout=180)
|
||||||
@@ -106,21 +181,37 @@ def _generate_shortname_by_api(text):
|
|||||||
error_info["body"] = response.json()
|
error_info["body"] = response.json()
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
_log_routerai_response(response, error_body=error_info.get("body"))
|
||||||
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 — эта функция вызывается и из веб-API Flask
|
# Не sys.exit — эта функция вызывается и из веб-API Flask
|
||||||
raise RuntimeError("RouterAI 429: превышен лимит запросов")
|
raise RuntimeError("RouterAI 429: превышен лимит запросов")
|
||||||
|
|
||||||
response.raise_for_status()
|
if not response.ok:
|
||||||
|
_log_routerai_response(response, error_body=response.text)
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
result = response.json()
|
result = response.json()
|
||||||
|
_log_routerai_response(response, result=result)
|
||||||
|
|
||||||
# Извлекаем только текст ответа (у thinking-моделей ответ в content,
|
# Извлекаем только текст ответа (у thinking-моделей ответ в content,
|
||||||
# рассуждения — в reasoning_content / reasoning)
|
# рассуждения — в reasoning_content / reasoning)
|
||||||
message = result['choices'][0]['message']
|
choices = result.get('choices') or []
|
||||||
|
if not choices:
|
||||||
|
log_message("RouterAI вернул пустой choices — название не извлечь")
|
||||||
|
return None
|
||||||
|
|
||||||
|
message = choices[0].get('message') or {}
|
||||||
shortname = (message.get('content') or '').strip()
|
shortname = (message.get('content') or '').strip()
|
||||||
if not shortname:
|
if not shortname:
|
||||||
log_message(f"Пустой content в ответе RouterAI: {json.dumps(result, ensure_ascii=False)[:1000]}")
|
reasoning = (message.get('reasoning_content') or message.get('reasoning') or '').strip()
|
||||||
|
log_message(
|
||||||
|
"Пустой content в ответе RouterAI; "
|
||||||
|
f"finish_reason={choices[0].get('finish_reason')!r}, "
|
||||||
|
f"message_keys={list(message.keys())}, "
|
||||||
|
f"reasoning_len={len(reasoning)}"
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Удаляем возможные кавычки и лишние символы
|
# Удаляем возможные кавычки и лишние символы
|
||||||
@@ -148,15 +239,31 @@ def _generate_shortname_by_api(text):
|
|||||||
error_info["body"] = e.response.json()
|
error_info["body"] = e.response.json()
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
_log_routerai_response(e.response, error_body=error_info.get("body"))
|
||||||
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: Превышен лимит запросов. Подробности в логе.")
|
||||||
raise RuntimeError("RouterAI 429: превышен лимит запросов")
|
raise RuntimeError("RouterAI 429: превышен лимит запросов")
|
||||||
else:
|
else:
|
||||||
|
if e.response is not None:
|
||||||
|
try:
|
||||||
|
_log_routerai_response(e.response, error_body=e.response.text)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
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 requests.exceptions.Timeout as e:
|
||||||
|
error_msg = f"Таймаут запроса RouterAI ({e})"
|
||||||
|
log_message(error_msg)
|
||||||
|
print(error_msg)
|
||||||
|
return None
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
error_msg = f"Сетевая ошибка RouterAI: {e}"
|
||||||
|
log_message(error_msg)
|
||||||
|
print(error_msg)
|
||||||
|
return None
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
raise
|
raise
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
Reference in New Issue
Block a user