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

@@ -32,7 +32,9 @@ class ConnectionManager:
try:
await websocket.send_json(message)
except (RuntimeError, Exception) as e:
logger.warning(f"发送消息失败 (conversation_id={conversation_id}): {e}")
logger.warning(
"发送消息失败 (conversation_id={}): {}", conversation_id, e
)
if conversation_id in self.active_connections:
del self.active_connections[conversation_id]

View File

@@ -873,4 +873,4 @@ async def process_conversation_segments(
len(segment_ids),
)
except Exception as e:
logger.error(f"提交 Celery 任务失败: {e}")
logger.error("提交 Celery 任务失败: {}", e)

View File

@@ -190,7 +190,7 @@ async def websocket_endpoint(
if i < ng - 1:
await asyncio.sleep(0.5)
except Exception as e:
logger.error(f"发送资料收集开场白失败: {e}", exc_info=True)
logger.exception("发送资料收集开场白失败: {}", e)
else:
try:
state = memoir_state
@@ -239,7 +239,7 @@ async def websocket_endpoint(
if i < no - 1:
await asyncio.sleep(0.5)
except Exception as e:
logger.error(f"发送空对话开场白失败: {e}", exc_info=True)
logger.exception("发送空对话开场白失败: {}", e)
while True:
try:
@@ -597,7 +597,7 @@ async def websocket_endpoint(
)
except Exception as e:
logger.error(f"处理音频消息失败: {e}", exc_info=True)
logger.exception("处理音频消息失败: {}", e)
await manager.send_message(
conversation_id,
{
@@ -638,7 +638,7 @@ async def websocket_endpoint(
},
)
except Exception as e:
logger.error(f"仅转写失败: {e}", exc_info=True)
logger.exception("仅转写失败: {}", e)
await manager.send_message(
conversation_id,
{
@@ -703,7 +703,7 @@ async def websocket_endpoint(
)
break
else:
logger.error(f"处理消息时发生 RuntimeError: {e}", exc_info=True)
logger.exception("处理消息时发生 RuntimeError: {}", e)
if conversation_id in manager.active_connections:
try:
await manager.send_message(
@@ -717,7 +717,7 @@ async def websocket_endpoint(
},
)
except Exception as send_error:
logger.warning(f"发送错误消息失败: {send_error}")
logger.warning("发送错误消息失败: {}", send_error)
break
except WebSocketDisconnect as disc:
logger.info(
@@ -727,7 +727,7 @@ async def websocket_endpoint(
)
break
except Exception as e:
logger.error(f"处理消息时发生错误: {e}", exc_info=True)
logger.exception("处理消息时发生错误: {}", e)
if conversation_id in manager.active_connections:
try:
await manager.send_message(
@@ -739,7 +739,7 @@ async def websocket_endpoint(
},
)
except Exception as send_error:
logger.warning(f"发送错误消息失败: {send_error}")
logger.warning("发送错误消息失败: {}", send_error)
break
except WebSocketDisconnect as disc:
@@ -751,7 +751,7 @@ async def websocket_endpoint(
await manager.disconnect(conversation_id)
cleanup_segment_states(conversation_id)
except Exception as e:
logger.error(f"WebSocket 端点发生错误: {e}", exc_info=True)
logger.exception("WebSocket 端点发生错误: {}", e)
await manager.disconnect(conversation_id)
cleanup_segment_states(conversation_id)
finally: