refactor(api): TOML 配置 SSOT、统一错误契约、Auth/事务加固与可观测性 (#33)
配置 SSOT(TOML + .env) 统一错误契约 Auth 与事务边界 Redis / Celery 可靠性:业务 Redis(DB/0)与 Celery broker/backend(DB/1)显式拆分;连接池、sync client 可观测性(OpenTelemetry + LGTM)
This commit is contained in:
@@ -12,6 +12,7 @@ from typing import Any
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.core.config import settings
|
||||
from app.core.db import transactional
|
||||
from app.core.dependencies import (
|
||||
EvalJudgeProvider,
|
||||
build_eval_judge_llm_spec,
|
||||
@@ -47,6 +48,8 @@ from app.features.evaluation.transcript_for_judge import (
|
||||
from app.features.evaluation.user_export_fixtures import read_user_export_fixture
|
||||
from app.features.memoir.repo import get_chapters_for_memoir_list
|
||||
from app.features.story.repo import get_stories_for_user
|
||||
from app.features.evaluation.constants import eval_cfg
|
||||
from app.features.memoir.constants import memoir
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
@@ -55,8 +58,7 @@ _MAX_EVAL_STORIES = 40 # memoir_snapshot 等仍限幅
|
||||
_PRIOR_TRANSCRIPT_MAX_CHARS = 8000
|
||||
|
||||
_JUDGE_CONFIG_HINT = (
|
||||
"评审未配置:智谱需 eval_judge_api_key 或 zhipu_api_key;"
|
||||
"DeepSeek 需 deepseek_api_key(或 llm_api_key)"
|
||||
"评审未配置:智谱需 ZHIPU_API_KEY;DeepSeek 需 DEEPSEEK_API_KEY"
|
||||
)
|
||||
|
||||
|
||||
@@ -126,7 +128,7 @@ def _clip_md_for_judge(text: str, max_chars: int | None = None) -> str:
|
||||
cap = (
|
||||
max_chars
|
||||
if max_chars is not None
|
||||
else max(1000, int(settings.eval_judge_memoir_body_max_chars))
|
||||
else max(1000, int(eval_cfg.judge_memoir_body_max_chars))
|
||||
)
|
||||
s = (text or "").strip()
|
||||
if len(s) <= cap:
|
||||
@@ -170,11 +172,12 @@ class EvalJudgeManualService:
|
||||
self, conversation_id: str, bundle: dict[str, Any]
|
||||
) -> None:
|
||||
try:
|
||||
row = await conversation_repo.set_playground_conversation_judge_json(
|
||||
conversation_id, self._db, bundle
|
||||
)
|
||||
if row is not None:
|
||||
await self._db.commit()
|
||||
async with transactional(self._db):
|
||||
row = await conversation_repo.set_playground_conversation_judge_json(
|
||||
conversation_id, self._db, bundle
|
||||
)
|
||||
if row is None:
|
||||
return
|
||||
except Exception:
|
||||
logger.exception(
|
||||
"persist playground_conversation_judge_json failed conversation_id={}",
|
||||
@@ -717,7 +720,7 @@ class EvalJudgeManualService:
|
||||
if (getattr(x, "canonical_markdown", None) or "").strip()
|
||||
)
|
||||
|
||||
conc = max(1, min(32, int(settings.eval_judge_memoir_chapter_concurrency)))
|
||||
conc = max(1, min(32, int(eval_cfg.judge_memoir_chapter_concurrency)))
|
||||
logger.info(
|
||||
"event=eval_memoir_judge_start user_id={} judge_provider={} judge_model={} "
|
||||
"chapters_total={} chapters_nonempty={} chapter_concurrency={}",
|
||||
@@ -741,7 +744,7 @@ class EvalJudgeManualService:
|
||||
baseline_excerpt = _clip_md_for_judge(
|
||||
bl.body,
|
||||
max_chars=max(
|
||||
1000, int(settings.eval_judge_memoir_evidence_max_chars)
|
||||
1000, int(eval_cfg.judge_memoir_evidence_max_chars)
|
||||
),
|
||||
)
|
||||
md = f"# 章节:{ch.title}\n\n{_clip_md_for_judge(body)}"
|
||||
@@ -959,7 +962,7 @@ class EvalJudgeManualService:
|
||||
baseline_excerpt = _clip_md_for_judge(
|
||||
bl.body,
|
||||
max_chars=max(
|
||||
1000, int(settings.eval_judge_memoir_evidence_max_chars)
|
||||
1000, int(eval_cfg.judge_memoir_evidence_max_chars)
|
||||
),
|
||||
)
|
||||
md = f"# 章节:{ch.title}\n\n{_clip_md_for_judge(body)}"
|
||||
@@ -999,7 +1002,7 @@ class EvalJudgeManualService:
|
||||
|
||||
yield {"event": "chapters_prepared", "count": len(prepared)}
|
||||
|
||||
conc = max(1, min(32, int(settings.eval_judge_memoir_chapter_concurrency)))
|
||||
conc = max(1, min(32, int(eval_cfg.judge_memoir_chapter_concurrency)))
|
||||
sem = asyncio.Semaphore(conc)
|
||||
result_queue: asyncio.Queue[dict[str, Any] | None] = asyncio.Queue()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user