feat(eval): memoir A/B chapter judging and eval-web parity with dialogue

- Judge baseline excerpt and library chapter separately; build_memoir_compare_summary for gate, nine-dim and leaf deltas.

- Memoir SSE chapter payload: baseline_judge, compare_summary, baseline_judge_error.

- MemoirJudgeOutput: loose score coercion and post-validate clamp; memoir judge prompt caps from settings.

- app-eval-web: two-column MemoirScoreCard layout, MemoirCompareSummary, chapter blocks and CSS.

- Add memoir_compare_summary, log_events, celery_log_context, memoir_pipeline_progress; tests and migration 0014.

- Misc: memory/evidence and enrichment paths, task/orchestrator updates, internal-eval docs, env examples.
This commit is contained in:
Kevin
2026-04-10 10:23:43 +08:00
parent b0251e5b26
commit ac49bc7f23
59 changed files with 4773 additions and 696 deletions

View File

@@ -0,0 +1,62 @@
"""log_eventsformat_log_event 与 celery_prerun_extras。"""
from __future__ import annotations
from app.core.log_events import (
celery_prerun_extras,
correlation_bind_kwargs,
format_log_event,
)
def test_format_log_event_msg_last() -> None:
s = format_log_event(
"demo",
z_last=1,
a_first="x",
msg="你好 世界",
)
assert s.startswith("event=demo ")
assert s.endswith(" msg=你好 世界")
assert "a_first=x" in s
assert "z_last=1" in s
def test_format_log_event_skips_empty() -> None:
s = format_log_event("x", empty="", none_val=None, ok=5)
assert "empty=" not in s
assert "none_val=" not in s
assert "ok=5" in s
def test_format_log_event_float() -> None:
s = format_log_event("t", duration_ms=12.3456)
assert "duration_ms=12.3" in s
def test_correlation_bind_kwargs() -> None:
d = correlation_bind_kwargs(
user_id="u1",
memoir_correlation_id="c1",
)
assert d == {"user_id": "u1", "correlation_id": "c1"}
def test_celery_prerun_extras_from_kwargs() -> None:
ex = celery_prerun_extras(
"app.tasks.memory_enrichment_tasks.enrich_memory_source",
("uid", "sid"),
{"memoir_correlation_id": "mc"},
)
assert ex["user_id"] == "uid"
assert ex["source_id"] == "sid"
assert ex["correlation_id"] == "mc"
def test_celery_prerun_extras_positional_only() -> None:
ex = celery_prerun_extras(
"app.tasks.chapter_compose_tasks.recompose_chapter",
("chap-1",),
{},
)
assert ex == {"chapter_id": "chap-1"}