feat(api): 拆分章节物化与 Story 后处理,并加固 Redis 锁与腾讯 ASR
回忆录 Story 流水线(同步) - 同步路径仅写入 Story 与章节关联,改为 mark_chapter_dirty_sync,不再内联 compose - 物化由 Celery recompose_chapter 异步完成;compose 不变量与异常时保留 dirty 的语义在 repo 中补充说明 - Evidence:大批次时降低 top_k;路由候选 story 携带 char_count/version_count;append 超长/版本过多时强制新开 story - 叙事 prompt:relevant_chunks 去重,减少重复证据噪声 - 叙事回退与忠实度 gate:返回 fallback 类型并记录结构化日志(含耗时、JSON 有效性等) Post-commit 与任务编排 - 新增 post_commit.enqueue_story_post_commit_effects:统一派发 generate_story_image(Redis 去重)、延迟 recompose_chapter、可选 memory compaction - memoir_tasks / story_service / story_image_tasks 改为调用 post-commit 入口;主图回填后按关联章节重算并调度物化与 compacs(锁委托、Redis 单例、ASR to_thread) - 更新 test_narrative_pipeline 以适配 _apply_narrative_fallbacks 返回值
This commit is contained in:
@@ -115,6 +115,21 @@ def mark_chapters_dirty_for_story_sync(session: Session, story_id: str) -> None:
|
||||
)
|
||||
|
||||
|
||||
def get_chapter_ids_linked_to_story_sync(session: Session, story_id: str) -> list[str]:
|
||||
stmt = select(ChapterStoryLink.chapter_id).where(
|
||||
ChapterStoryLink.story_id == story_id
|
||||
)
|
||||
return list(dict.fromkeys(session.scalars(stmt).all()))
|
||||
|
||||
|
||||
def mark_chapter_dirty_sync(session: Session, chapter_id: str) -> None:
|
||||
"""幂等:将章节标为需物化 markdown(多次调用安全)。"""
|
||||
ch = session.get(Chapter, chapter_id)
|
||||
if ch:
|
||||
ch.markdown_compose_dirty = True
|
||||
session.flush()
|
||||
|
||||
|
||||
async def get_chapter_with_story_links_for_compose(
|
||||
chapter_id: str, db: AsyncSession
|
||||
) -> Chapter | None:
|
||||
@@ -229,6 +244,8 @@ def compose_chapter_from_story_links_sync(session: Session, chapter_id: str) ->
|
||||
"""
|
||||
按 story_links 重组 canonical_markdown 并写入版本链。
|
||||
若无 story_links 则清除 dirty 并返回 False。
|
||||
|
||||
不变量:成功物化或空链接分支均会将 markdown_compose_dirty=False;异常退出保留 dirty。
|
||||
"""
|
||||
stmt = (
|
||||
select(Chapter)
|
||||
|
||||
Reference in New Issue
Block a user