feat(search): add semantic similar session matching via Voyage AI embeddings

Adds vector-based similar session discovery using the existing Voyage AI
embedding infrastructure and pgvector cosine similarity search.

- New AISessionEmbedding model with vector(1024) column
- session_embedding_service: generate + upsert embeddings, find similar sessions
- Embeddings generated on session create (from problem_summary/domain) and
  updated on resolve (adds resolution_summary)
- GET /ai-sessions/{id}/similar endpoint returns top-N similar sessions
- Migration a7c9e3b1f402 creates ai_session_embeddings table

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-20 03:48:09 +00:00
parent ce68fa84ca
commit e356103408
6 changed files with 343 additions and 0 deletions

View File

@@ -493,6 +493,32 @@ async def search_sessions(
]
# ── Similar Sessions ──
@router.get("/{session_id}/similar")
@limiter.limit("15/minute")
async def get_similar_sessions(
request: Request,
session_id: UUID,
current_user: Annotated[User, Depends(get_current_active_user)],
db: Annotated[AsyncSession, Depends(get_db)],
limit: int = Query(5, ge=1, le=20),
):
"""Find sessions semantically similar to this one using vector embeddings."""
from app.services.session_embedding_service import find_similar_sessions
if not current_user.account_id:
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="No account")
results = await find_similar_sessions(
session_id=session_id,
account_id=current_user.account_id,
db=db,
limit=limit,
)
return results
# ── List sessions ──
@router.get("", response_model=list[AISessionSummary])