amauricunha commited on
Commit
bc329fa
·
verified ·
1 Parent(s): d2f6b40

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +27 -15
app.py CHANGED
@@ -41,11 +41,11 @@ except Exception as e:
41
  print(f"ERRO ao inicializar o cliente Groq: {e}.")
42
 
43
 
44
- # --- NOVA ROTA PARA LISTAR MODELOS DINAMICAMENTE ---
45
  @app.route('/list-models')
46
  def list_models():
47
  available_models = []
48
- # CORREÇÃO: Lista de modelos Groq para geração de texto foi atualizada.
49
  groq_text_models = [
50
  "llama-3.1-8b-instant",
51
  "llama-3.3-70b-versatile",
@@ -54,7 +54,6 @@ def list_models():
54
  ]
55
 
56
  try:
57
- # Busca modelos Gemini
58
  if genai_client:
59
  for m in genai_client.list_models():
60
  if 'generateContent' in m.supported_generation_methods:
@@ -65,7 +64,6 @@ def list_models():
65
  "name": m.display_name
66
  })
67
 
68
- # Adiciona modelos Groq
69
  if groq_client:
70
  for model_id in groq_text_models:
71
  display_name = model_id.split('/')[-1].replace('-instant', '').replace('-versatile', '')
@@ -76,7 +74,6 @@ def list_models():
76
 
77
  except Exception as e:
78
  print(f"Erro ao listar modelos: {e}")
79
- # Retorna uma lista de fallback em caso de erro na API
80
  return jsonify([
81
  {"value": "gemini:gemini-2.5-flash-latest", "name": "Gemini 2.5 Flash (Fallback)"},
82
  {"value": "groq:llama-3.1-8b-instant", "name": "Llama 3.1 8B (Fallback)"}
@@ -91,8 +88,7 @@ def list_models():
91
  def tts_proxy():
92
  data = request.get_json()
93
  text = data.get('text', '')
94
- if not text:
95
- return jsonify({"error": "No text provided"}), 400
96
  try:
97
  tts = gTTS(text=text, lang='en', tld='co.uk')
98
  mp3_fp = io.BytesIO()
@@ -125,7 +121,7 @@ def explain_proxy():
125
 
126
  if for_flashcard:
127
  schema = {"type": "object", "properties": {"term": {"type": "string"}, "translation": {"type": "string"}, "context_sentence": {"type": "string"}, "gapped_sentence": {"type": "string"}, "definition": {"type": "string"}}, "required": ["term", "translation", "context_sentence", "gapped_sentence", "definition"]}
128
- prompt = f"Analyze '{word}' in context: '{context}'. Generate a JSON for a flashcard. The 'gapped_sentence' must replace '{word}' with '______________'. You must strictly follow the JSON schema and provide valid, non-empty values for all fields."
129
  return jsonify(get_ai_text_response(model_provider, model_name, system_instruction_base, prompt, json_schema=schema))
130
 
131
  else:
@@ -144,8 +140,7 @@ def activity_feedback():
144
  original_prompt = data.get('original_prompt', '')
145
  user_response = data.get('user_response', '')
146
 
147
- if not original_prompt or not user_response:
148
- return jsonify({"error": "Original prompt and user response are required."}), 400
149
 
150
  if (model_provider == 'gemini' and not genai_client) or (model_provider == 'groq' and not groq_client):
151
  return jsonify({"error": f"{model_provider.upper()}_API_KEY not configured."}), 503
@@ -225,7 +220,6 @@ def generate_image():
225
  prompt = data.get('prompt')
226
  if not prompt: return jsonify({"error": "Image prompt is required."}), 400
227
  try:
228
- # Usa um modelo de imagem específico e estável
229
  model = genai_client.GenerativeModel(model_name='gemini-2.5-flash-image-preview')
230
  response = model.generate_content(prompt)
231
  base64_image_data = response.parts[0].inline_data.data
@@ -236,19 +230,37 @@ def generate_image():
236
  # --- FUNÇÃO AUXILIAR E ROTA RAIZ ---
237
  def get_ai_text_response(provider, model_name, system_instruction, user_prompt, json_schema=None):
238
  if provider == 'gemini':
239
- # Usa o model_name diretamente, que agora vem da lista dinâmica
240
  model = genai_client.GenerativeModel(model_name, system_instruction=system_instruction)
241
  config = {}
242
  if json_schema:
243
  config = {"response_mime_type": "application/json", "response_schema": json_schema}
244
  response = model.generate_content(user_prompt, generation_config=config)
245
- return json.loads(response.text) if json_schema else response.text.strip()
246
 
 
 
 
 
 
 
 
247
  elif provider == 'groq':
248
- messages = [{"role": "system", "content": system_instruction}, {"role": "user", "content": user_prompt}]
 
 
 
 
249
  config = {'response_format': {"type": "json_object"}} if json_schema else {}
250
  response = groq_client.chat.completions.create(model=model_name, messages=messages, **config)
251
- return json.loads(response.choices[0].message.content) if json_schema else response.choices[0].message.content.strip()
 
 
 
 
 
 
 
 
 
252
  raise Exception(f"Unsupported provider: {provider}")
253
 
254
  @app.route('/')
 
41
  print(f"ERRO ao inicializar o cliente Groq: {e}.")
42
 
43
 
44
+ # --- ROTA PARA LISTAR MODELOS DINAMICAMENTE ---
45
  @app.route('/list-models')
46
  def list_models():
47
  available_models = []
48
+ # Lista de modelos Groq para geração de texto foi atualizada.
49
  groq_text_models = [
50
  "llama-3.1-8b-instant",
51
  "llama-3.3-70b-versatile",
 
54
  ]
55
 
56
  try:
 
57
  if genai_client:
58
  for m in genai_client.list_models():
59
  if 'generateContent' in m.supported_generation_methods:
 
64
  "name": m.display_name
65
  })
66
 
 
67
  if groq_client:
68
  for model_id in groq_text_models:
69
  display_name = model_id.split('/')[-1].replace('-instant', '').replace('-versatile', '')
 
74
 
75
  except Exception as e:
76
  print(f"Erro ao listar modelos: {e}")
 
77
  return jsonify([
78
  {"value": "gemini:gemini-2.5-flash-latest", "name": "Gemini 2.5 Flash (Fallback)"},
79
  {"value": "groq:llama-3.1-8b-instant", "name": "Llama 3.1 8B (Fallback)"}
 
88
  def tts_proxy():
89
  data = request.get_json()
90
  text = data.get('text', '')
91
+ if not text: return jsonify({"error": "No text provided"}), 400
 
92
  try:
93
  tts = gTTS(text=text, lang='en', tld='co.uk')
94
  mp3_fp = io.BytesIO()
 
121
 
122
  if for_flashcard:
123
  schema = {"type": "object", "properties": {"term": {"type": "string"}, "translation": {"type": "string"}, "context_sentence": {"type": "string"}, "gapped_sentence": {"type": "string"}, "definition": {"type": "string"}}, "required": ["term", "translation", "context_sentence", "gapped_sentence", "definition"]}
124
+ prompt = f"Analyze '{word}' in context: '{context}'. Generate a JSON for a flashcard. The 'gapped_sentence' must replace '{word}' with '______________'."
125
  return jsonify(get_ai_text_response(model_provider, model_name, system_instruction_base, prompt, json_schema=schema))
126
 
127
  else:
 
140
  original_prompt = data.get('original_prompt', '')
141
  user_response = data.get('user_response', '')
142
 
143
+ if not original_prompt or not user_response: return jsonify({"error": "Original prompt and user response are required."}), 400
 
144
 
145
  if (model_provider == 'gemini' and not genai_client) or (model_provider == 'groq' and not groq_client):
146
  return jsonify({"error": f"{model_provider.upper()}_API_KEY not configured."}), 503
 
220
  prompt = data.get('prompt')
221
  if not prompt: return jsonify({"error": "Image prompt is required."}), 400
222
  try:
 
223
  model = genai_client.GenerativeModel(model_name='gemini-2.5-flash-image-preview')
224
  response = model.generate_content(prompt)
225
  base64_image_data = response.parts[0].inline_data.data
 
230
  # --- FUNÇÃO AUXILIAR E ROTA RAIZ ---
231
  def get_ai_text_response(provider, model_name, system_instruction, user_prompt, json_schema=None):
232
  if provider == 'gemini':
 
233
  model = genai_client.GenerativeModel(model_name, system_instruction=system_instruction)
234
  config = {}
235
  if json_schema:
236
  config = {"response_mime_type": "application/json", "response_schema": json_schema}
237
  response = model.generate_content(user_prompt, generation_config=config)
 
238
 
239
+ parsed_json = json.loads(response.text)
240
+ if json_schema:
241
+ required_keys = json_schema.get("required", [])
242
+ if not all(key in parsed_json and parsed_json[key] for key in required_keys):
243
+ raise ValueError(f"AI response missing required keys. Required: {required_keys}, Got: {list(parsed_json.keys())}")
244
+ return parsed_json
245
+
246
  elif provider == 'groq':
247
+ final_user_prompt = user_prompt
248
+ if json_schema:
249
+ final_user_prompt += f"\n\nYou MUST respond with a single JSON object that strictly follows this schema. Do not add any other text before or after the JSON object:\n{json.dumps(json_schema)}"
250
+
251
+ messages = [{"role": "system", "content": system_instruction}, {"role": "user", "content": final_user_prompt}]
252
  config = {'response_format': {"type": "json_object"}} if json_schema else {}
253
  response = groq_client.chat.completions.create(model=model_name, messages=messages, **config)
254
+
255
+ if json_schema:
256
+ parsed_json = json.loads(response.choices[0].message.content)
257
+ required_keys = json_schema.get("required", [])
258
+ if not all(key in parsed_json and parsed_json[key] for key in required_keys):
259
+ raise ValueError(f"AI response missing required keys. Required: {required_keys}, Got: {list(parsed_json.keys())}")
260
+ return parsed_json
261
+ else:
262
+ return response.choices[0].message.content.strip()
263
+
264
  raise Exception(f"Unsupported provider: {provider}")
265
 
266
  @app.route('/')