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:
@@ -15,6 +15,7 @@ from app.core.config import settings
|
||||
from app.core.llm_call import LLMCallError, llm_json_call
|
||||
from app.core.logging import get_logger
|
||||
from app.features.conversation.models import Segment
|
||||
from app.features.memoir.constants import memoir
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
@@ -68,7 +69,7 @@ def run_batch_phase1_prep(
|
||||
llm,
|
||||
prompt,
|
||||
BatchPhase1LLMOutput,
|
||||
max_tokens=int(settings.memoir_phase1_batch_llm_max_tokens),
|
||||
max_tokens=int(memoir.phase1_batch_llm_max_tokens),
|
||||
agent="BatchPhase1Prep.run",
|
||||
)
|
||||
except LLMCallError as e:
|
||||
|
||||
@@ -26,6 +26,7 @@ from app.core.config import settings
|
||||
from app.core.json_utils import extract_json_payload
|
||||
from app.core.llm_call import LLMCallError, llm_json_call
|
||||
from app.core.logging import get_logger
|
||||
from app.features.memoir.constants import memoir
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
@@ -144,7 +145,7 @@ class ClassificationAgent:
|
||||
llm,
|
||||
prompt,
|
||||
ClassificationOutput,
|
||||
max_tokens=settings.memoir_classification_max_tokens,
|
||||
max_tokens=memoir.classification_max_tokens,
|
||||
agent="ClassificationAgent.classify",
|
||||
)
|
||||
category = _normalize_llm_category(out.category)
|
||||
|
||||
@@ -14,6 +14,7 @@ from app.agents.stage_constants import normalize_chat_stage
|
||||
from app.core.config import settings
|
||||
from app.core.llm_call import LLMCallError, llm_json_call
|
||||
from app.core.logging import get_logger
|
||||
from app.features.memoir.constants import memoir
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
@@ -64,7 +65,7 @@ class ExtractionAgent:
|
||||
llm,
|
||||
prompt,
|
||||
StateExtractionOutput,
|
||||
max_tokens=settings.memoir_extraction_max_tokens,
|
||||
max_tokens=memoir.extraction_max_tokens,
|
||||
agent="ExtractionAgent.extract",
|
||||
)
|
||||
raw_slots = parsed.slots or {}
|
||||
|
||||
@@ -13,6 +13,7 @@ from app.agents.memoir.schemas import FidelityOutput
|
||||
from app.core.config import settings
|
||||
from app.core.llm_call import LLMCallError, llm_json_call
|
||||
from app.core.logging import get_logger
|
||||
from app.features.memoir.constants import memoir
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
@@ -46,7 +47,7 @@ class FidelityCheckAgent:
|
||||
existing_canonical_markdown: str | None = None,
|
||||
is_append: bool = False,
|
||||
) -> bool:
|
||||
if not llm or not settings.memoir_fidelity_check_enabled:
|
||||
if not llm or not memoir.fidelity_check_enabled:
|
||||
return True
|
||||
oral = (oral_text or "").strip()
|
||||
gen = (narrative_json or "").strip()
|
||||
@@ -108,7 +109,7 @@ class FidelityCheckAgent:
|
||||
llm,
|
||||
prompt,
|
||||
FidelityOutput,
|
||||
max_tokens=settings.memoir_fidelity_check_max_tokens,
|
||||
max_tokens=memoir.fidelity_check_max_tokens,
|
||||
agent="FidelityCheckAgent.passes",
|
||||
)
|
||||
ok = bool(out.pass_)
|
||||
@@ -120,7 +121,7 @@ class FidelityCheckAgent:
|
||||
return ok
|
||||
except LLMCallError as e:
|
||||
logger.warning("FidelityCheckAgent 解析失败: {}", e)
|
||||
if is_append or settings.memoir_fidelity_fail_open_on_parse_error:
|
||||
if is_append or memoir.fidelity_fail_open_on_parse_error:
|
||||
logger.info("event=fidelity_parse_fail_open is_append={}", is_append)
|
||||
return True
|
||||
logger.warning("event=fidelity_parse_fail_closed")
|
||||
|
||||
@@ -18,6 +18,7 @@ from app.core.config import settings
|
||||
from app.core.langchain_llm import invoke_json_object
|
||||
from app.core.llm_call import llm_json_call
|
||||
from app.core.logging import get_logger
|
||||
from app.features.memoir.constants import memoir
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
@@ -63,7 +64,7 @@ class NarrativeAgent:
|
||||
llm,
|
||||
prompt,
|
||||
MemoirTitleOutput,
|
||||
max_tokens=settings.memoir_title_max_tokens,
|
||||
max_tokens=memoir.title_max_tokens,
|
||||
agent="NarrativeAgent.generate_title",
|
||||
fallback_factory=_title_fallback,
|
||||
)
|
||||
@@ -118,7 +119,7 @@ class NarrativeAgent:
|
||||
occupation=occupation,
|
||||
language=language,
|
||||
)
|
||||
max_tokens = int(settings.memoir_narrative_merge_max_tokens)
|
||||
max_tokens = int(memoir.narrative_merge_max_tokens)
|
||||
agent_name = "NarrativeAgent.generate_narrative_merge"
|
||||
else:
|
||||
prompt = get_narrative_json_prompt(
|
||||
@@ -132,7 +133,7 @@ class NarrativeAgent:
|
||||
occupation=occupation,
|
||||
language=language,
|
||||
)
|
||||
max_tokens = int(settings.memoir_narrative_max_tokens)
|
||||
max_tokens = int(memoir.narrative_max_tokens)
|
||||
agent_name = "NarrativeAgent.generate_narrative"
|
||||
return invoke_json_object(
|
||||
llm,
|
||||
|
||||
@@ -29,6 +29,7 @@ from app.core.agent_logging import agent_span, agent_summary_enabled, log_agent_
|
||||
from app.core.config import settings
|
||||
from app.core.logging import get_logger
|
||||
from app.features.conversation.models import Segment
|
||||
from app.features.memoir.constants import memoir
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
@@ -90,7 +91,7 @@ class MemoirOrchestrator:
|
||||
use_batch = (
|
||||
bool(segments)
|
||||
and classify_extract_llm is not None
|
||||
and settings.memoir_phase1_batch_llm_enabled
|
||||
and memoir.phase1_batch_llm_enabled
|
||||
)
|
||||
if use_batch:
|
||||
try:
|
||||
@@ -204,7 +205,7 @@ class MemoirOrchestrator:
|
||||
segments,
|
||||
state,
|
||||
classify_extract_llm,
|
||||
chunk_size=int(settings.memoir_phase1_batch_llm_chunk_size),
|
||||
chunk_size=int(memoir.phase1_batch_llm_chunk_size),
|
||||
on_chunk=on_phase1_chunk,
|
||||
language=language,
|
||||
)
|
||||
|
||||
@@ -21,6 +21,8 @@ from app.core.config import settings
|
||||
from app.core.llm_call import LLMCallError, llm_json_call
|
||||
from app.core.logging import get_logger
|
||||
from app.features.story.models import Story
|
||||
from app.features.memoir.constants import memoir
|
||||
from app.features.story.constants import story
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
@@ -47,7 +49,7 @@ def default_append_target_story_id(
|
||||
ordered = sort_stories_for_route(
|
||||
candidate_stories,
|
||||
meta,
|
||||
summary_min_chars=int(settings.story_route_summary_min_chars),
|
||||
summary_min_chars=int(story.route_summary_min_chars),
|
||||
)
|
||||
if not ordered:
|
||||
return None
|
||||
@@ -247,7 +249,7 @@ class StoryRouteAgent:
|
||||
llm,
|
||||
prompt,
|
||||
StoryRouteDecision,
|
||||
max_tokens=settings.memoir_story_route_max_tokens,
|
||||
max_tokens=memoir.story_route_max_tokens,
|
||||
agent="StoryRouteAgent.decide",
|
||||
fallback_factory=_decide_fallback,
|
||||
)
|
||||
@@ -295,7 +297,7 @@ class StoryRouteAgent:
|
||||
llm,
|
||||
prompt,
|
||||
StoryBatchPlan,
|
||||
max_tokens=settings.memoir_story_batch_plan_max_tokens,
|
||||
max_tokens=memoir.story_batch_plan_max_tokens,
|
||||
agent="StoryRouteAgent.plan_batch",
|
||||
)
|
||||
except LLMCallError as e:
|
||||
|
||||
@@ -15,6 +15,7 @@ if TYPE_CHECKING:
|
||||
from app.core.config import Settings
|
||||
|
||||
from app.features.story.models import Story
|
||||
from app.features.story.constants import story
|
||||
|
||||
_PLAIN_SNIPPET_NOISE = re.compile(r"[`*_#]+")
|
||||
|
||||
@@ -213,11 +214,11 @@ def build_route_candidate_rows(
|
||||
) -> list[dict[str, Any]]:
|
||||
"""排序 + 完整候选行(尚未做总预算降级)。"""
|
||||
meta = story_meta or {}
|
||||
summary_min = int(settings.story_route_summary_min_chars)
|
||||
summary_min = int(story.route_summary_min_chars)
|
||||
ordered = sort_stories_for_route(stories, meta, summary_min_chars=summary_min)
|
||||
body_max = int(settings.story_route_candidate_body_max_chars)
|
||||
head_c = int(settings.story_route_long_body_head_chars)
|
||||
tail_c = int(settings.story_route_long_body_tail_chars)
|
||||
body_max = int(story.route_candidate_body_max_chars)
|
||||
head_c = int(story.route_long_body_head_chars)
|
||||
tail_c = int(story.route_long_body_tail_chars)
|
||||
rows: list[dict[str, Any]] = []
|
||||
for s in ordered:
|
||||
rows.append(
|
||||
@@ -231,8 +232,8 @@ def build_route_candidate_rows(
|
||||
)
|
||||
)
|
||||
by_id = {str(s.id): s for s in ordered}
|
||||
total_max = int(settings.story_route_candidate_total_max_chars)
|
||||
index_prev = int(settings.story_route_index_preview_chars)
|
||||
total_max = int(story.route_candidate_total_max_chars)
|
||||
index_prev = int(story.route_index_preview_chars)
|
||||
return apply_total_budget_downgrade(
|
||||
rows,
|
||||
stories_by_id=by_id,
|
||||
|
||||
Reference in New Issue
Block a user