File size: 4,018 Bytes
e4ab6d0
 
 
 
b366f52
 
 
 
 
 
 
 
 
 
 
 
 
e4ab6d0
b366f52
e4ab6d0
b366f52
 
 
 
 
 
 
 
 
 
 
57dd211
b366f52
 
e4ab6d0
b366f52
e4ab6d0
b366f52
 
 
 
 
 
 
 
57dd211
b366f52
 
 
e4ab6d0
3cd5de7
 
b366f52
 
3cd5de7
 
 
 
 
 
 
 
 
 
b366f52
e4ab6d0
57dd211
 
 
 
 
 
 
b366f52
 
 
 
 
 
 
57dd211
 
b366f52
 
e4ab6d0
 
b366f52
 
e4ab6d0
26dd9d1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e4ab6d0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';

type Grade = 'lowergrade' | 'midgrade' | 'highergrade';
type DbLevel = 'low' | 'mid' | 'high';

function resolveBaseUrl(): string {
  const isHF = location.hostname.endsWith('hf.space');
  if (isHF) return 'https://pykara-py-learn-backend.hf.space/rag';
  if (location.hostname === 'localhost' || location.hostname === '127.0.0.1') {
    return 'http://localhost:5000/rag';
  }
  return '/rag';
}

@Injectable({ providedIn: 'root' })
export class ApiService {
  private baseUrl = resolveBaseUrl();

  private getGrade(): Grade {
    const g = (localStorage.getItem('gradeLevel') || 'highergrade').toLowerCase();
    if (g === 'lowergrade' || g === 'midgrade' || g === 'highergrade') return g as Grade;
    return 'highergrade';
  }
  private toDbLevel(g: Grade): DbLevel {
    return g === 'lowergrade' ? 'low' : g === 'midgrade' ? 'mid' : 'high';
  }
  private makeHeaders(g: Grade): HttpHeaders {
    return new HttpHeaders({
      'Content-Type': 'application/json',
      'X-User': g,
    });
  }

  constructor(private http: HttpClient) { }

  generateOpenQuestions(payload: { qtype: 'OPEN'; n?: number; topic?: string }): Observable<any> {
    const grade = this.getGrade();
    const headers = this.makeHeaders(grade);
    const body = {
      qtype: 'OPEN',
      n: payload.n ?? 5,
      topic: payload.topic ?? '',
      model: 'gpt-4o-mini',
      db_level: this.toDbLevel(grade),
    };
    return this.http.post<any>(`${this.baseUrl}/generate-questions`, body, { headers });
  }

  // Accept either a string (legacy) or an object { question, synthesize_audio, synthesize_video }
  explainGrammar(payload: string | any): Observable<any> {
    const grade = this.getGrade();
    const headers = this.makeHeaders(grade);

    // Normalize payload into an object
    const body = typeof payload === 'string' ? { question: payload } : { ...payload };

    // Ensure backend gets db_level and model so it selects the right vectorstore/LLM
    if (!body.db_level) body.db_level = this.toDbLevel(grade);
    if (!body.model) body.model = 'gpt-4o-mini';

    const url = `${this.baseUrl}/explain-grammar`;
    return this.http.post(url, body, { headers });
  }

  // ✅ Updated to carry source_ids so follow-ups stay in the same textbook pages
  suggestFollowups(payload: {
    last_question: string;
    last_answer: string;
    n?: number;
    source_ids?: string[];     // ← NEW
  }): Observable<any> {
    const grade = this.getGrade();
    const headers = this.makeHeaders(grade);
    const body = {
      last_question: payload.last_question,
      last_answer: payload.last_answer,
      n: payload.n ?? 5,
      model: 'gpt-4o-mini',
      db_level: this.toDbLevel(grade),
      source_ids: payload.source_ids ?? [],   // ← NEW
    };
    return this.http.post<any>(`${this.baseUrl}/suggest-followups`, body, { headers });
  }

  askQuestion(userInput: string, _sessionId: string | null): Observable<any> {
    return this.explainGrammar(userInput);
  }



  // add method in ApiService
  synthesizeAudio(text: string, language = 'en', referenceFiles?: string[]) {
    const payload: any = { text, language };
    if (referenceFiles) payload.reference_files = referenceFiles;
    return this.http.post<{ audio_url: string }>(`${this.baseUrl}/synthesize-audio`, payload);
  }

  // New: synthesize video (calls backend D-ID flow)
  synthesizeVideo(text: string, language = 'en') {
    const payload: any = { text, language };
    return this.http.post<{ video_url: string }>(`${this.baseUrl}/synthesize-video`, payload);
  }

  punctuate(text: string): Observable<any> {
    const headers = {
      'Content-Type': 'application/json',
      'X-User': localStorage.getItem('username') || ''
    };
    // Use the port your backend runs on (your local runner uses 7000)
    return this.http.post<any>(`${this.baseUrl}/punctuate`, { text }, { headers });
  }
}