feat(api)!: memory single chain — async MemoryService, strict eval closure
Route all memory ingest/retrieve/enrichment/compaction through async MemoryService. Remove legacy sync memory implementations (ingest/retrieve/compaction); Celery and memoir Phase2 call asyncio.run into MemoryService-backed helpers. Memoir Phase1 batch ingest uses MemoryService.ingest_transcripts_batch; drop chapters. evidence_bundle_json mirror (Alembic 0015). Evaluation uses snapshot/link-only bundles; raise EvidenceClosureMissing instead of partial/fallback lineage tiers. Split memoir state into NarrativeCoverageState and InterviewControlState; delete the _interview_meta_store adapter layer. Remove rolling-query and recent-fact fallback settings from config and evidence assembly. Update judges, docs, tests, and PlaygroundPage alignment. Made-with: Cursor
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import time
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
@@ -9,7 +10,7 @@ from typing import Any
|
||||
from celery import shared_task
|
||||
|
||||
from app.core.config import settings
|
||||
from app.core.db import get_sync_db
|
||||
from app.core.db import AsyncSessionLocal
|
||||
from app.core.logging import get_logger
|
||||
from app.core.memory_compaction_schedule import (
|
||||
finalize_memory_compaction_run,
|
||||
@@ -19,12 +20,28 @@ from app.core.memory_compaction_schedule import (
|
||||
set_incremental_cursor_pair,
|
||||
)
|
||||
from app.core.redis_lock import acquire_redis_lock, release_redis_lock
|
||||
from app.features.memory.compaction_service import run_memory_compaction_sync
|
||||
from app.features.memory.repo import list_users_with_recent_chunks_sync
|
||||
from app.features.memory.repo import list_users_with_recent_chunks
|
||||
from app.features.memory.service import MemoryService
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
async def _list_users_with_recent_chunks_async(hours: int) -> list[str]:
|
||||
async with AsyncSessionLocal() as db:
|
||||
return await list_users_with_recent_chunks(db, hours=hours)
|
||||
|
||||
|
||||
async def _run_memory_compaction_async(
|
||||
user_id: str,
|
||||
context: dict[str, Any] | None,
|
||||
) -> dict[str, Any]:
|
||||
async with AsyncSessionLocal() as db:
|
||||
service = MemoryService(db)
|
||||
out = await service.compact_user(user_id, context)
|
||||
await db.commit()
|
||||
return out
|
||||
|
||||
|
||||
@shared_task
|
||||
def memory_compaction_sweep() -> dict[str, Any]:
|
||||
"""Beat:为近期有记忆写入的用户调度 compaction(debounce 仍由 schedule 合并)。"""
|
||||
@@ -32,8 +49,7 @@ def memory_compaction_sweep() -> dict[str, Any]:
|
||||
if not settings.memory_compaction_enabled:
|
||||
return {"skipped": True, "reason": "disabled"}
|
||||
hours = int(settings.memory_compaction_sweep_recent_hours)
|
||||
with get_sync_db() as session:
|
||||
user_ids = list_users_with_recent_chunks_sync(session, hours=hours)
|
||||
user_ids = asyncio.run(_list_users_with_recent_chunks_async(hours))
|
||||
ctx_base: dict[str, Any] = {"trigger_source": "beat", "sweep_hours": hours}
|
||||
for uid in user_ids:
|
||||
schedule_memory_compaction_run(uid, dict(ctx_base))
|
||||
@@ -84,9 +100,7 @@ def memory_compaction_run(
|
||||
return out
|
||||
|
||||
try:
|
||||
with get_sync_db() as session:
|
||||
out = run_memory_compaction_sync(session, user_id, ctx)
|
||||
session.commit()
|
||||
out = asyncio.run(_run_memory_compaction_async(user_id, ctx))
|
||||
|
||||
if out.get("new_cursor_ts") and out.get("new_cursor_id") is not None:
|
||||
set_incremental_cursor_pair(
|
||||
|
||||
Reference in New Issue
Block a user