This commit is contained in:
+113
-6
@@ -30,6 +30,79 @@ ROUTERAI_CONFIG = {
|
||||
# Настройки журналирования
|
||||
LOG_FILE = os.getenv('LOG_FILE', 'ai_namer.log') # Путь к лог-файлу
|
||||
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):
|
||||
"""
|
||||
@@ -89,6 +162,8 @@ def _generate_shortname_by_api(text):
|
||||
"max_tokens": 5000,
|
||||
"temperature": 0.3,
|
||||
}
|
||||
|
||||
_log_routerai_request(text, prompt)
|
||||
|
||||
try:
|
||||
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()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
_log_routerai_response(response, error_body=error_info.get("body"))
|
||||
log_message(f"Ошибка 429: Превышен лимит запросов. Ответ API: {json.dumps(error_info, ensure_ascii=False)}")
|
||||
print("Ошибка 429: Превышен лимит запросов. Подробности в логе.")
|
||||
# Не sys.exit — эта функция вызывается и из веб-API Flask
|
||||
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()
|
||||
_log_routerai_response(response, result=result)
|
||||
|
||||
# Извлекаем только текст ответа (у thinking-моделей ответ в content,
|
||||
# рассуждения — в 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()
|
||||
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
|
||||
|
||||
# Удаляем возможные кавычки и лишние символы
|
||||
@@ -148,15 +239,31 @@ def _generate_shortname_by_api(text):
|
||||
error_info["body"] = e.response.json()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
_log_routerai_response(e.response, error_body=error_info.get("body"))
|
||||
log_message(f"Ошибка 429: Превышен лимит запросов. Ответ API: {json.dumps(error_info, ensure_ascii=False)}")
|
||||
print("Ошибка 429: Превышен лимит запросов. Подробности в логе.")
|
||||
raise RuntimeError("RouterAI 429: превышен лимит запросов")
|
||||
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}"
|
||||
log_message(error_msg)
|
||||
print(error_msg)
|
||||
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:
|
||||
raise
|
||||
except Exception as e:
|
||||
|
||||
Reference in New Issue
Block a user