angeetoile commited on
Commit
ed50d5b
·
verified ·
1 Parent(s): bce8b20

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +69 -16
main.py CHANGED
@@ -1,8 +1,9 @@
1
  import os
2
- from fastapi import FastAPI, UploadFile, File, HTTPException
3
  from fastapi.middleware.cors import CORSMiddleware
4
  from pydantic import BaseModel
5
  from groq import Groq
 
6
 
7
  app = FastAPI(title="BSTP-Cameroun-AI-Engine")
8
 
@@ -18,7 +19,7 @@ app.add_middleware(
18
  GROQ_API_KEY = os.getenv("GROQ_API_KEY")
19
 
20
  if not GROQ_API_KEY:
21
- print("⚠️ Attention: GROQ_API_KEY n'est pas configurée dans les secrets de l'espace Hugging Face.")
22
 
23
  groq_client = Groq(api_key=GROQ_API_KEY) if GROQ_API_KEY else None
24
 
@@ -31,12 +32,12 @@ if os.path.exists(KNOWLEDGE_FILE_PATH):
31
  with open(KNOWLEDGE_FILE_PATH, "r", encoding="utf-8") as f:
32
  BSTP_KNOWLEDGE_BASE = f.read()
33
  else:
34
- print(f"⚠️ Erreur: Le fichier {KNOWLEDGE_FILE_PATH} est introuvable. Initialisation d'une base vide.")
35
  BSTP_KNOWLEDGE_BASE = "Base de connaissances non disponible."
36
 
37
- # =========================================================
38
  # SYSTEM PROMPT EN ANGLAIS
39
- # =========================================================
40
  SYSTEM_PROMPT = (
41
  "ROLE AND MANDATE:\n"
42
  "You are BSTP-Intellect, the advanced, specialized, and authoritative AI Governance & Sourcing Assistant "
@@ -78,7 +79,6 @@ SYSTEM_PROMPT = (
78
  "If the query is in English, close naturally with: 'For any further guidance regarding the BSTP ecosystem or the execution of our operational cockpits, I remain entirely at your disposal.'"
79
  )
80
 
81
- # Assemblage final du Prompt et du contexte de la base de connaissances
82
  FULL_SYSTEM_PROMPT = SYSTEM_PROMPT + "\n\nOFFICIAL BSTP REFERENCE CONTEXT FROM DATABASE:\n" + BSTP_KNOWLEDGE_BASE
83
 
84
  class TextRequest(BaseModel):
@@ -106,7 +106,7 @@ async def chat_text(request: TextRequest):
106
  {"role": "system", "content": FULL_SYSTEM_PROMPT},
107
  {"role": "user", "content": request.text}
108
  ],
109
- temperature=0.3, # Température basse pour maintenir une exactitude maximale
110
  max_tokens=1024
111
  )
112
  return {"ai_response": completion.choices[0].message.content}
@@ -122,22 +122,18 @@ async def chat_voice(file: UploadFile = File(...)):
122
  raise HTTPException(status_code=500, detail="Le moteur d'IA Groq n'est pas configuré.")
123
 
124
  try:
125
- # Étape A : Transcription de la note vocale industrielle
126
  transcription = groq_client.audio.transcriptions.create(
127
  file=(file.filename, await file.read()),
128
  model="whisper-large-v3",
129
  response_format="json"
130
  )
131
-
132
  user_text = transcription.text
133
-
134
  if not user_text or not user_text.strip():
135
  return {
136
  "user_said": "",
137
  "ai_response": "Je n'ai pas pu intercepter de flux audio distinct concernant la BSTP. Pouvez-vous reformuler ? / I could not process the audio instruction. Please try again."
138
  }
139
 
140
- # Étape B : Soumission du texte transcrit au modèle orienté BSTP
141
  completion = groq_client.chat.completions.create(
142
  model="llama-3.3-70b-versatile",
143
  messages=[
@@ -147,11 +143,68 @@ async def chat_voice(file: UploadFile = File(...)):
147
  temperature=0.3,
148
  max_tokens=1024
149
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
 
151
- return {
152
- "user_said": user_text,
153
- "ai_response": completion.choices[0].message.content
154
- }
155
 
156
  except Exception as e:
157
- raise HTTPException(status_code=500, detail=f"Erreur du pipeline vocal Groq BSTP : {str(e)}")
 
1
  import os
2
+ from fastapi import FastAPI, UploadFile, File, HTTPException, Form
3
  from fastapi.middleware.cors import CORSMiddleware
4
  from pydantic import BaseModel
5
  from groq import Groq
6
+ import base64
7
 
8
  app = FastAPI(title="BSTP-Cameroun-AI-Engine")
9
 
 
19
  GROQ_API_KEY = os.getenv("GROQ_API_KEY")
20
 
21
  if not GROQ_API_KEY:
22
+ print("Attention: GROQ_API_KEY n'est pas configurée dans les secrets de l'espace Hugging Face.")
23
 
24
  groq_client = Groq(api_key=GROQ_API_KEY) if GROQ_API_KEY else None
25
 
 
32
  with open(KNOWLEDGE_FILE_PATH, "r", encoding="utf-8") as f:
33
  BSTP_KNOWLEDGE_BASE = f.read()
34
  else:
35
+ print(f"Erreur: Le fichier {KNOWLEDGE_FILE_PATH} est introuvable. Initialisation d'une base vide.")
36
  BSTP_KNOWLEDGE_BASE = "Base de connaissances non disponible."
37
 
38
+ # ========================
39
  # SYSTEM PROMPT EN ANGLAIS
40
+ # ========================
41
  SYSTEM_PROMPT = (
42
  "ROLE AND MANDATE:\n"
43
  "You are BSTP-Intellect, the advanced, specialized, and authoritative AI Governance & Sourcing Assistant "
 
79
  "If the query is in English, close naturally with: 'For any further guidance regarding the BSTP ecosystem or the execution of our operational cockpits, I remain entirely at your disposal.'"
80
  )
81
 
 
82
  FULL_SYSTEM_PROMPT = SYSTEM_PROMPT + "\n\nOFFICIAL BSTP REFERENCE CONTEXT FROM DATABASE:\n" + BSTP_KNOWLEDGE_BASE
83
 
84
  class TextRequest(BaseModel):
 
106
  {"role": "system", "content": FULL_SYSTEM_PROMPT},
107
  {"role": "user", "content": request.text}
108
  ],
109
+ temperature=0.3,
110
  max_tokens=1024
111
  )
112
  return {"ai_response": completion.choices[0].message.content}
 
122
  raise HTTPException(status_code=500, detail="Le moteur d'IA Groq n'est pas configuré.")
123
 
124
  try:
 
125
  transcription = groq_client.audio.transcriptions.create(
126
  file=(file.filename, await file.read()),
127
  model="whisper-large-v3",
128
  response_format="json"
129
  )
 
130
  user_text = transcription.text
 
131
  if not user_text or not user_text.strip():
132
  return {
133
  "user_said": "",
134
  "ai_response": "Je n'ai pas pu intercepter de flux audio distinct concernant la BSTP. Pouvez-vous reformuler ? / I could not process the audio instruction. Please try again."
135
  }
136
 
 
137
  completion = groq_client.chat.completions.create(
138
  model="llama-3.3-70b-versatile",
139
  messages=[
 
143
  temperature=0.3,
144
  max_tokens=1024
145
  )
146
+ return {"user_said": user_text, "ai_response": completion.choices[0].message.content}
147
+ except Exception as e:
148
+ raise HTTPException(status_code=500, detail=f"Erreur du pipeline vocal Groq BSTP : {str(e)}")
149
+
150
+ # ===================================
151
+ # ROUTE 3 : AUDIT DOCUMENTAIRE VISION
152
+ # ===================================
153
+ @app.post("/api/document-audit")
154
+ async def audit_document(file: UploadFile = File(...), document_type: str = Form(...)):
155
+ """
156
+ document_type doit être l'un des suivants: 'rccm', 'niu', 'cnps', 'attestation_fiscale'
157
+ """
158
+ if not groq_client:
159
+ raise HTTPException(status_code=500, detail="Le moteur d'IA Groq n'est pas configuré.")
160
+
161
+ valid_types = ['rccm', 'niu', 'cnps', 'attestation_fiscale']
162
+ if document_type.lower() not in valid_types:
163
+ raise HTTPException(status_code=400, detail=f"Type de document invalide. Choisissez parmi : {valid_types}")
164
+
165
+ try:
166
+ # Lecture de l'image et encodage en Base64 pour l'API Vision de Groq
167
+ image_bytes = await file.read()
168
+ base64_image = base64.b64encode(image_bytes).decode('utf-8')
169
+
170
+ # Construction du prompt d'analyse d'image ciblé sur la base de connaissances
171
+ vision_prompt = (
172
+ f"You are the document verification submodule of BSTP-Intellect.\n"
173
+ f"The user has uploaded an image that is claimed to be a '{document_type.upper()}'.\n"
174
+ f"Analyze this image carefully. Perform OCR to extract key administrative data, then cross-reference "
175
+ f"the visual text with the official 'SME PROFILING DOCUMENT COMPLIANCE CRITERIA' in our knowledge base.\n\n"
176
+ f"Provide a structured JSON response in the identical language of the system with the following keys:\n"
177
+ f"1. 'is_valid': boolean (true if it matches the expected document type and criteria, false otherwise).\n"
178
+ f"2. 'extracted_info': a short text summarizing the key numbers, dates, or corporate names identified.\n"
179
+ f"3. 'compliance_report': a detailed administrative explanation of why the document is accepted or rejected based on Cameroon regulations.\n"
180
+ f"Do not return any conversational text around the JSON, return ONLY a valid JSON object."
181
+ )
182
+ response = groq_client.chat.completions.create(
183
+ model="llama-3.2-11b-vision-preview",
184
+ messages=[
185
+ {
186
+ "role": "system",
187
+ "content": f"{BSTP_KNOWLEDGE_BASE}\n\nYou must strictly output valid JSON structures."
188
+ },
189
+ {
190
+ "role": "user",
191
+ "content": [
192
+ {"type": "text", "text": vision_prompt},
193
+ {
194
+ "type": "image_url",
195
+ "image_url": {
196
+ "url": f"data:image/jpeg;base64,{base64_image}"
197
+ }
198
+ }
199
+ ]
200
+ }
201
+ ],
202
+ temperature=0.1,
203
+ response_format={"type": "json_object"}
204
+ )
205
 
206
+ import json
207
+ return json.loads(response.choices[0].message.content)
 
 
208
 
209
  except Exception as e:
210
+ raise HTTPException(status_code=500, detail=f"Erreur lors de l'analyse OCR/Vision par Groq : {str(e)}")