真人素材库本地完成

This commit is contained in:
2026-07-06 15:13:41 +08:00
parent 75d1f7a428
commit ab67bdf19e
52 changed files with 4131 additions and 137 deletions
@@ -1,70 +1,8 @@
from __future__ import annotations
import json
import os
import re
import traceback
from datetime import datetime
from typing import Any
from app.services.log_config import LOG_DATE_FORMAT, LOG_DIR, is_enabled
MAX_LOG_FIELD_LENGTH = 20000
MAX_TRACEBACK_LENGTH = 12000
MODULE_LOG_ROOT = os.path.join(os.path.dirname(LOG_DIR), "ModuleGeneration")
def _safe_module_name(module: str | None) -> str:
value = str(module or "unknown_module").strip() or "unknown_module"
value = re.sub(r"[^a-zA-Z0-9_.-]+", "_", value)
return value[:120] or "unknown_module"
def _safe_dump_value(value: Any) -> Any:
"""限制单字段长度,避免超长 base64 / 响应体把日志打爆。"""
if value is None:
return None
if isinstance(value, str):
if len(value) > MAX_LOG_FIELD_LENGTH:
return value[:MAX_LOG_FIELD_LENGTH] + f"...<truncated:{len(value) - MAX_LOG_FIELD_LENGTH}>"
return value
if isinstance(value, dict):
return {str(k): _safe_dump_value(v) for k, v in value.items()}
if isinstance(value, list):
return [_safe_dump_value(v) for v in value]
return value
def build_exception_detail(exc: BaseException | None, extra: dict[str, Any] | None = None) -> dict[str, Any]:
"""构造统一异常日志 detail。日志方法必须吞异常,业务不能被日志影响。"""
detail: dict[str, Any] = dict(extra or {})
if exc is not None:
tb = "".join(traceback.format_exception(type(exc), exc, exc.__traceback__))
if len(tb) > MAX_TRACEBACK_LENGTH:
tb = tb[:MAX_TRACEBACK_LENGTH] + f"...<traceback_truncated:{len(tb) - MAX_TRACEBACK_LENGTH}>"
detail.update(
{
"exception_type": type(exc).__name__,
"exception_message": str(exc),
"traceback": tb,
}
)
return detail
def _append_module_log(module: str, entry: dict[str, Any]) -> None:
if not is_enabled():
return
try:
module_dir = os.path.join(MODULE_LOG_ROOT, _safe_module_name(module))
os.makedirs(module_dir, exist_ok=True)
today = datetime.now().strftime(LOG_DATE_FORMAT)
log_file = os.path.join(module_dir, f"{today}.log")
with open(log_file, "a", encoding="utf-8") as f:
f.write(json.dumps(entry, ensure_ascii=False, default=str) + "\n")
except Exception:
# 日志失败绝不能影响业务主流程。
pass
from app.services.operation_log_service import build_exception_detail, log_operation_error, log_operation_event
def log_module_event_file(
@@ -78,24 +16,19 @@ def log_module_event_file(
detail: dict[str, Any] | None = None,
error: str | None = None,
) -> None:
"""记录模块流程事件到 JSONL 文件。
统一落盘目录:log/ModuleGeneration/{module}/YYYY-MM-DD.log
不再写 module_generation_events 表。
"""
entry = {
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"log_type": "module_event",
"module": module,
"event_type": event_type,
"project_id": project_id,
"step_id": step_id,
"user_id": user_id,
"message": message,
"detail": _safe_dump_value(detail or {}),
"error": error,
}
_append_module_log(module, entry)
log_operation_event(
domain="module_generation",
module=module,
event_type=event_type,
project_id=project_id,
step_id=step_id,
user_id=user_id,
message=message,
detail=detail,
error=error,
event_status="failed" if error else "success",
source="service",
)
def log_module_prompt_event(
@@ -111,22 +44,19 @@ def log_module_prompt_event(
token_usage: dict[str, Any] | None = None,
error: str | None = None,
) -> None:
"""记录模块 AI 提词/分析请求和响应到 JSONL 文件。"""
entry = {
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"log_type": "module_prompt",
"module": module,
"event_type": event_type,
"prompt_type": prompt_type,
"project_id": project_id,
"step_id": step_id,
"user_id": user_id,
"request": _safe_dump_value(request or {}),
"response": _safe_dump_value(response or {}),
"token_usage": _safe_dump_value(token_usage or {}),
"error": error,
}
_append_module_log(module, entry)
log_operation_event(
domain="module_generation",
module=module,
event_type=event_type,
project_id=project_id,
step_id=step_id,
user_id=user_id,
message=f"模块 AI 请求:{prompt_type}",
detail={"prompt_type": prompt_type, "request": request or {}, "response": response or {}, "token_usage": token_usage or {}},
error=error,
event_status="failed" if error else "success",
source="service",
)
def log_module_error(
@@ -141,23 +71,16 @@ def log_module_error(
error: str | None = None,
exc: BaseException | None = None,
) -> None:
"""记录模块异常日志。
- 兼容原有 detail/error 参数。
- 新增 exc 后自动记录 exception_type、message、traceback。
- 日志写入失败会被底层吞掉,不影响主流程。
"""
merged_detail = build_exception_detail(exc, detail)
entry = {
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"log_type": "module_error",
"module": module,
"event_type": event_type,
"project_id": project_id,
"step_id": step_id,
"user_id": user_id,
"message": message,
"detail": _safe_dump_value(merged_detail),
"error": error if error is not None else (str(exc) if exc is not None else None),
}
_append_module_log(module, entry)
log_operation_error(
domain="module_generation",
module=module,
event_type=event_type,
project_id=project_id,
step_id=step_id,
user_id=user_id,
message=message,
detail=detail,
error=error if error is not None else (str(exc) if exc else None),
exc=exc,
source="service",
)