mirror of
https://github.com/velocitatem/cvfs.git
synced 2026-05-31 16:53:38 +00:00
feat: NLP patch insights + standalone demo mode
- dlib/ai/insights.py: pure-Python NLP analysis that correlates accepted AI suggestion operations/keywords/sections with submission outcomes (pending_review / published = positive, archived = negative) - Backend: GET /api/v1/insights route + service + Pydantic schema - Frontend: InsightsPanel component with bar charts for operation impact, section impact, and keyword signal lift scores - Insights tab added to the version panel; compact preview on doc overview - NEXT_PUBLIC_DEMO=true makes the webapp fully standalone: loads DEMO_DOCUMENTS / DEMO_SUBMISSIONS / DEMO_INSIGHTS from demo-data.ts, disables all mutating actions, shows a DEMO badge in the top bar - apps/webapp/public/demo-cv.docx: static dummy CV (Alex Rivera) for demo - scripts/gen_demo_cv.py: script to regenerate the demo DOCX - .env.example: document NEXT_PUBLIC_DEMO flag https://claude.ai/code/session_01LWxu2qrwY6BRjUFXXn7NiM
This commit is contained in:
37
apps/backend/fastapi/app/services/insights.py
Normal file
37
apps/backend/fastapi/app/services/insights.py
Normal file
@@ -0,0 +1,37 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy.orm import selectinload
|
||||
|
||||
from dlib.ai.insights import InsightsResult, SubmissionRecord, SuggestionRecord, analyze
|
||||
from app.models import AiSuggestion, CvDocument, CvVersion, Submission
|
||||
|
||||
|
||||
async def get_insights(session: AsyncSession, *, owner_id: str) -> InsightsResult:
|
||||
stmt = (
|
||||
select(Submission)
|
||||
.join(Submission.version)
|
||||
.join(CvVersion.document)
|
||||
.where(CvDocument.owner_id == owner_id)
|
||||
.options(selectinload(Submission.suggestions))
|
||||
)
|
||||
rows = list((await session.execute(stmt)).scalars().all())
|
||||
|
||||
records = [
|
||||
SubmissionRecord(
|
||||
status=s.status.value,
|
||||
suggestions=[
|
||||
SuggestionRecord(
|
||||
operation=sug.operation,
|
||||
target_path=sug.target_path,
|
||||
proposed_text=sug.proposed_text,
|
||||
rationale=sug.rationale,
|
||||
accepted=sug.accepted,
|
||||
)
|
||||
for sug in s.suggestions
|
||||
],
|
||||
)
|
||||
for s in rows
|
||||
]
|
||||
return analyze(records)
|
||||
Reference in New Issue
Block a user