Prise en compte du langage de l'utilisateur pour le prompt de réponse. Si par exemple l'interface est en anglais, les IA vont favoriser l'anglais pour la réponse
This commit is contained in:
18
web/src/app/interceptors/language.interceptor.ts
Normal file
18
web/src/app/interceptors/language.interceptor.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { HttpInterceptorFn } from '@angular/common/http';
|
||||
import { inject } from '@angular/core';
|
||||
import { LanguageService } from '../services/language.service';
|
||||
|
||||
/**
|
||||
* Ajoute l'entête `X-User-Language` (langue choisie dans l'UI : `fr`/`en`) à
|
||||
* toutes les requêtes HttpClient. Le Core la relaie au Brain, qui rédige alors
|
||||
* ses réponses IA dans cette langue.
|
||||
*
|
||||
* NB : les appels SSE en `fetch()` (chat, imports, notebooks) ne passent PAS par
|
||||
* les intercepteurs Angular — ils ajoutent l'entête manuellement de leur côté.
|
||||
*/
|
||||
export const languageInterceptor: HttpInterceptorFn = (req, next) => {
|
||||
const language = inject(LanguageService);
|
||||
return next(
|
||||
req.clone({ setHeaders: { 'X-User-Language': language.current } })
|
||||
);
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { LanguageService } from './language.service';
|
||||
|
||||
/**
|
||||
* Un message d'une conversation IA (vue front).
|
||||
@@ -47,6 +48,7 @@ export type NarrativeEntityType = 'arc' | 'chapter' | 'scene' | 'character' | 'n
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AiChatService {
|
||||
private readonly translate = inject(TranslateService);
|
||||
private readonly language = inject(LanguageService);
|
||||
private readonly loreEndpoint = '/api/ai/chat/stream';
|
||||
private readonly campaignEndpoint = '/api/ai/chat/stream-campaign';
|
||||
private readonly sessionEndpoint = '/api/ai/chat/stream-session';
|
||||
@@ -110,7 +112,8 @@ export class AiChatService {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'text/event-stream'
|
||||
'Accept': 'text/event-stream',
|
||||
'X-User-Language': this.language.current
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
signal: controller.signal
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
CampaignImportProposal,
|
||||
CampaignImportStreamEvent
|
||||
} from './campaign-import.model';
|
||||
import { LanguageService } from './language.service';
|
||||
|
||||
/**
|
||||
* Service HTTP pour l'import d'un PDF de campagne.
|
||||
@@ -17,7 +18,7 @@ import {
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CampaignImportService {
|
||||
constructor(private http: HttpClient, private translate: TranslateService) {}
|
||||
constructor(private http: HttpClient, private translate: TranslateService, private language: LanguageService) {}
|
||||
|
||||
importStructureStream(campaignId: string, file: File): Observable<CampaignImportStreamEvent> {
|
||||
return new Observable<CampaignImportStreamEvent>((subscriber) => {
|
||||
@@ -27,7 +28,7 @@ export class CampaignImportService {
|
||||
|
||||
fetch(`/api/campaigns/${campaignId}/import-structure/stream`, {
|
||||
method: 'POST',
|
||||
headers: { 'Accept': 'text/event-stream' },
|
||||
headers: { 'Accept': 'text/event-stream', 'X-User-Language': this.language.current },
|
||||
body: form,
|
||||
signal: controller.signal
|
||||
})
|
||||
|
||||
@@ -3,6 +3,7 @@ import { HttpClient, HttpParams } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { GameSystem, GameSystemCreate, RulesImportResponse, RulesImportStreamEvent } from './game-system.model';
|
||||
import { LanguageService } from './language.service';
|
||||
|
||||
/**
|
||||
* Service HTTP pour les GameSystems (systèmes de JDR).
|
||||
@@ -11,7 +12,7 @@ import { GameSystem, GameSystemCreate, RulesImportResponse, RulesImportStreamEve
|
||||
export class GameSystemService {
|
||||
private apiUrl = '/api/game-systems';
|
||||
|
||||
constructor(private http: HttpClient, private translate: TranslateService) {}
|
||||
constructor(private http: HttpClient, private translate: TranslateService, private language: LanguageService) {}
|
||||
|
||||
getAll(): Observable<GameSystem[]> {
|
||||
return this.http.get<GameSystem[]>(this.apiUrl);
|
||||
@@ -63,7 +64,7 @@ export class GameSystemService {
|
||||
|
||||
fetch(`${this.apiUrl}/import-rules/stream`, {
|
||||
method: 'POST',
|
||||
headers: { 'Accept': 'text/event-stream' },
|
||||
headers: { 'Accept': 'text/event-stream', 'X-User-Language': this.language.current },
|
||||
body: form,
|
||||
signal: controller.signal
|
||||
})
|
||||
|
||||
@@ -3,6 +3,7 @@ import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Notebook, NotebookArchive, NotebookDetail, NotebookSource, NotebookChatEvent } from './notebook.model';
|
||||
import { LanguageService } from './language.service';
|
||||
|
||||
/**
|
||||
* Service des notebooks (atelier RAG) : CRUD, upload/indexation de sources,
|
||||
@@ -12,7 +13,7 @@ import { Notebook, NotebookArchive, NotebookDetail, NotebookSource, NotebookChat
|
||||
export class NotebookService {
|
||||
private readonly apiUrl = '/api/notebooks';
|
||||
|
||||
constructor(private http: HttpClient, private zone: NgZone, private translate: TranslateService) {}
|
||||
constructor(private http: HttpClient, private zone: NgZone, private translate: TranslateService, private language: LanguageService) {}
|
||||
|
||||
listByCampaign(campaignId: string): Observable<Notebook[]> {
|
||||
return this.http.get<Notebook[]>(`${this.apiUrl}/campaign/${campaignId}`);
|
||||
@@ -73,7 +74,7 @@ export class NotebookService {
|
||||
try {
|
||||
const response = await fetch(`${this.apiUrl}/${notebookId}/chat/stream`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', 'Accept': 'text/event-stream' },
|
||||
headers: { 'Content-Type': 'application/json', 'Accept': 'text/event-stream', 'X-User-Language': this.language.current },
|
||||
credentials: 'include',
|
||||
body: JSON.stringify({
|
||||
message, deep,
|
||||
|
||||
Reference in New Issue
Block a user