Chat atelier : evenement SSE sources + affichage des pages utilisees

Le Brain emet un evenement sources (source_id, page, score des passages
retenus) AVANT le premier token ; le Core le relaie tel quel (JSON brut) ;
l UI affiche une ligne discrete sous la reponse (ex: 12, 47, 103),
prefixee du nom de fichier si plusieurs sources. Transparence pour le MJ
et diagnostic immediat quand le RAG repond a cote.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 15:45:56 +02:00
parent 0e4820a2f8
commit 3d1cf6e495
10 changed files with 102 additions and 10 deletions

View File

@@ -16,12 +16,22 @@ export interface NotebookSource {
pageCount: number;
}
/** Passage source utilisé par le RAG pour ancrer une réponse (transparence). */
export interface NotebookChatSource {
sourceId: string;
/** Numéro de page 1-based, null si inconnu. */
page: number | null;
score: number;
}
export interface NotebookMessage {
id?: string;
notebookId?: string;
/** "user" | "assistant" */
role: string;
content: string;
/** Passages utilisés (réponses streamées uniquement — non persisté). */
sources?: NotebookChatSource[];
}
export interface NotebookDetail {
@@ -35,6 +45,7 @@ export interface NotebookDetail {
/** Évènements du chat ancré streamé. */
export type NotebookChatEvent =
| { type: 'token'; value: string }
| { type: 'sources'; sources: NotebookChatSource[] }
| { type: 'progress'; current: number; total: number }
| { type: 'done' }
| { type: 'error'; message: string };

View File

@@ -78,6 +78,16 @@ export class NotebookService {
if (name === 'token') {
try { emit({ type: 'token', value: (JSON.parse(currentData) as { token?: string }).token ?? '' }); }
catch { /* ignore */ }
} else if (name === 'sources') {
try {
const o = JSON.parse(currentData) as { sources?: { source_id?: string; page?: number | null; score?: number }[] };
emit({
type: 'sources',
sources: (o.sources ?? []).map(s => ({
sourceId: s.source_id ?? '', page: s.page ?? null, score: s.score ?? 0
}))
});
} catch { /* ignore */ }
} else if (name === 'progress') {
try {
const o = JSON.parse(currentData) as { current?: number; total?: number };