mirror of
https://github.com/velocitatem/cvfs.git
synced 2026-07-15 19:03: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:
@@ -1,4 +1,5 @@
|
||||
const API = "";
|
||||
export const IS_DEMO = process.env.NEXT_PUBLIC_DEMO === 'true';
|
||||
|
||||
export type StructuredBlock = {
|
||||
path: string;
|
||||
@@ -87,6 +88,21 @@ export type PublicAssetAnalytics = {
|
||||
last_viewed_at?: string | null;
|
||||
};
|
||||
|
||||
export type OperationImpact = { operation: string; total: number; positive: number; rate: number };
|
||||
export type KeywordSignal = { keyword: string; positive_count: number; negative_count: number; lift: number };
|
||||
export type SectionImpact = { section: string; positive_rate: number; count: number };
|
||||
|
||||
export type InsightsResult = {
|
||||
total_submissions: number;
|
||||
positive_count: number;
|
||||
positive_rate: number;
|
||||
operation_impact: OperationImpact[];
|
||||
top_positive_keywords: KeywordSignal[];
|
||||
top_negative_keywords: KeywordSignal[];
|
||||
section_impact: SectionImpact[];
|
||||
has_data: boolean;
|
||||
};
|
||||
|
||||
// reads OIDC bearer token from client-readable cookie (set by /api/auth/callback)
|
||||
function getAuthHeader(): Record<string, string> {
|
||||
if (typeof document === 'undefined') return {};
|
||||
@@ -238,6 +254,9 @@ export async function deleteDocument(documentId: string): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
export const fetchInsights = (): Promise<InsightsResult> =>
|
||||
req<InsightsResult>('/api/v1/insights');
|
||||
|
||||
export async function deleteVersion(versionId: string): Promise<void> {
|
||||
const res = await fetch(`${API}/api/v1/versions/${versionId}`, {
|
||||
method: 'DELETE',
|
||||
|
||||
Reference in New Issue
Block a user