feat: 回忆录证据血缘与内部评测可追溯,顺带对齐本地评测台与 CI

数据库与模型:新增多版迁移(章节证据快照、对话血缘、记忆事实/时间线 lineage 等),把「成稿 ↔ 对话/记忆」的溯源信息落到表结构里。
业务链路:会话与 WS、回忆录/故事流水线、记忆写入与 enrichment 等跟着接上线索与快照;新增章节证据快照与评测侧 EvalTraceService 等模块,方便组评审用的证据包。
内部评测:自动化 run 与手工 memoir 评审共用可追溯证据;rubric/ judge 相关脚本与文档有配套调整。
app-eval-web:Memoir/实验详情里能展开看证据摘要与 evidence_trace(含对话轮次 id);Vite 代理与 development.sh 注入的 API 端口与当前默认内部评测端口一致,避免改端口后页面连错服务。
工程杂项:GitHub Actions / 仓库说明有更新;各适配器与支付/配额/plan 等多处为小改动或跟随主改动的收尾;新增/扩充了?
This commit is contained in:
Kevin
2026-04-08 15:37:09 +08:00
parent 6772e1269c
commit 309a051038
109 changed files with 4125 additions and 858 deletions

View File

@@ -7,8 +7,12 @@ from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import Session, joinedload
from app.core.db import utc_now
from app.core.logging import get_logger
from app.features.asset.models import Asset
from app.features.memoir.asset_resolver import collect_asset_ids_for_chapter
from app.features.memoir.chapter_evidence_snapshot import (
refresh_chapter_evidence_snapshot_with_retry_sync,
)
from app.features.memoir.chapter_markdown_compose import (
materialize_chapter_markdown_from_loaded_chapter,
)
@@ -26,6 +30,8 @@ from app.features.memoir.reading_segment_materialize import (
from app.features.story.models import Story
from app.features.story.time_hints import life_sort_key_parts
logger = get_logger(__name__)
async def get_current_book(user_id: str, db: AsyncSession) -> Book | None:
stmt = (
@@ -51,6 +57,7 @@ async def get_chapters_for_memoir_list(
.where(Chapter.user_id == user_id)
.options(
joinedload(Chapter.images),
joinedload(Chapter.current_evidence_snapshot),
joinedload(Chapter.story_links)
.joinedload(ChapterStoryLink.story)
.joinedload(Story.image_intents),
@@ -71,6 +78,7 @@ async def get_chapter_by_id(chapter_id: str, db: AsyncSession) -> Chapter | None
.where(Chapter.id == chapter_id)
.options(
joinedload(Chapter.images),
joinedload(Chapter.current_evidence_snapshot),
joinedload(Chapter.story_links)
.joinedload(ChapterStoryLink.story)
.joinedload(Story.image_intents),
@@ -173,6 +181,18 @@ async def append_chapter_compose_version_async(
chapter.markdown_composed_at = utc_now()
chapter.reading_segments_json = build_reading_segments_snapshot(chapter)
def _snap(sess: Session) -> None:
refresh_chapter_evidence_snapshot_with_retry_sync(sess, str(chapter.id))
try:
await db.run_sync(_snap)
except Exception as e:
logger.warning(
"evidence_snapshot_refresh_failed async compose path chapter_id={}: {}",
chapter.id,
e,
)
def append_chapter_compose_version_sync(
session: Session,
@@ -267,6 +287,7 @@ def compose_chapter_from_story_links_sync(session: Session, chapter_id: str) ->
return False
md = materialize_chapter_markdown_from_loaded_chapter(chapter)
append_chapter_compose_version_sync(session, chapter, md)
refresh_chapter_evidence_snapshot_with_retry_sync(session, str(chapter.id))
return True