amauricunha commited on
Commit
3bfff15
·
verified ·
1 Parent(s): 74f68ea

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +108 -53
app.py CHANGED
@@ -2,11 +2,12 @@
2
  import os
3
  import io
4
  import json
 
 
5
 
6
  from flask import Flask, request, jsonify, send_file
7
  from gtts import gTTS
8
  from groq import Groq
9
- # CORREÇÃO: A importação correta para a biblioteca do Google Generative AI
10
  import google.generativeai as genai
11
 
12
  # --- CONFIGURAÇÃO INICIAL ---
@@ -23,10 +24,10 @@ try:
23
  genai.configure(api_key=GEMINI_API_KEY)
24
  genai_client = genai
25
  else:
26
- print("AVISO: GEMINI_API_KEY não configurada. Gemini estará desativado para análise.")
27
  except Exception as e:
28
  genai_client = None
29
- print(f"ERRO ao inicializar o cliente Gemini: {e}. Funcionalidade de IA desativada.")
30
 
31
  # 2. Configuração Groq
32
  try:
@@ -34,15 +35,16 @@ try:
34
  if GROQ_API_KEY:
35
  groq_client = Groq(api_key=GROQ_API_KEY)
36
  else:
37
- print("AVISO: GROQ_API_KEY não configurada. Groq estará desativado.")
38
  except Exception as e:
39
  groq_client = None
40
- print(f"ERRO ao inicializar o cliente Groq: {e}. Funcionalidade de IA desativada.")
41
 
42
 
43
- # --- ROTA 1: TEXT-TO-SPEECH (TTS) - USANDO gTTS GRATUITO ---
44
  @app.route('/tts-proxy', methods=['POST'])
45
  def tts_proxy():
 
46
  data = request.get_json()
47
  text = data.get('text', '')
48
  if not text:
@@ -58,51 +60,15 @@ def tts_proxy():
58
  return jsonify({"error": f"Failed to generate audio via gTTS: {e}"}), 500
59
 
60
 
61
- # --- ROTA 2: TRADUÇÃO RÁPIDA E CONTEXTO (IA) - USANDO GEMINI OU GROQ ---
62
- def get_ai_response(provider, model_name, system_instruction, user_prompt, json_schema=None):
63
- if provider == 'gemini':
64
- if not genai_client:
65
- raise Exception("Gemini client not initialized. GEMINI_API_KEY is missing.")
66
- model = genai_client.GenerativeModel(model_name)
67
-
68
- # CORREÇÃO: A configuração de geração para JSON agora é um dicionário simples
69
- generation_config = None
70
- if json_schema:
71
- generation_config = {
72
- "response_mime_type": "application/json",
73
- "response_schema": json_schema
74
- }
75
-
76
- response = model.generate_content(user_prompt, generation_config=generation_config)
77
-
78
- if json_schema:
79
- json_text = response.candidates[0].content.parts[0].text.strip()
80
- return json.loads(json_text)
81
- else:
82
- return response.text.strip()
83
-
84
- elif provider == 'groq':
85
- if not groq_client:
86
- raise Exception("Groq client not initialized. GROQ_API_KEY is missing.")
87
- messages = [{"role": "system", "content": system_instruction}, {"role": "user", "content": user_prompt}]
88
- config_params = {}
89
- if json_schema:
90
- config_params['response_format'] = {"type": "json_object"}
91
- response = groq_client.chat.completions.create(model=model_name, messages=messages, **config_params)
92
- text_response = response.choices[0].message.content.strip()
93
- return json.loads(text_response) if json_schema else text_response
94
-
95
- else:
96
- raise Exception(f"Unsupported provider: {provider}")
97
-
98
-
99
  @app.route('/explain-proxy', methods=['POST'])
100
  def explain_proxy():
 
101
  data = request.get_json()
 
102
  word = data.get('word', '').strip()
103
  context = data.get('context', '')
104
  for_flashcard = data.get('for_flashcard', False)
105
- model_provider, model_name = data.get('model', 'gemini:gemini-1.5-flash').split(':', 1)
106
  context_focus = data.get('context_focus', 'General/Social')
107
  custom_prompt = data.get('custom_prompt', None)
108
 
@@ -114,7 +80,7 @@ def explain_proxy():
114
 
115
  try:
116
  if custom_prompt:
117
- text_response = get_ai_response(model_provider, model_name, system_instruction_base, custom_prompt)
118
  return jsonify({"explanation": text_response, "translation": "Activity Generated."})
119
 
120
  if not word:
@@ -122,23 +88,21 @@ def explain_proxy():
122
 
123
  if for_flashcard:
124
  flashcard_schema = {
125
- "type": "object",
126
- "properties": {
127
  "term": {"type": "string"}, "translation": {"type": "string"},
128
  "context_sentence": {"type": "string"}, "gapped_sentence": {"type": "string"},
129
  "definition": {"type": "string"},
130
- },
131
- "required": ["term", "translation", "context_sentence", "gapped_sentence", "definition"]
132
  }
133
  system_instruction = system_instruction_base + " Your task is to generate a JSON object for an 'intelligent flashcard'."
134
  user_prompt = f"Analyze the term '{word}' in the sentence: '{context}'. Generate a JSON object following the schema. The 'gapped_sentence' must replace '{word}' with '______________'."
135
- card_data = get_ai_response(model_provider, model_name, system_instruction, user_prompt, json_schema=flashcard_schema)
136
  return jsonify(card_data)
137
 
138
  else:
139
  system_instruction = system_instruction_base
140
  user_prompt = f"Analyze '{word}' in context: '{context}'. Provide a one-sentence English explanation, then '---', then the Portuguese translation."
141
- text_response = get_ai_response(model_provider, model_name, system_instruction, user_prompt)
142
  parts = text_response.split('---', 1)
143
  explanation = parts[0].strip()
144
  translation = parts[1].strip() if len(parts) > 1 else 'Tradução não disponível.'
@@ -148,7 +112,98 @@ def explain_proxy():
148
  print(f"Erro na análise de IA: {e}")
149
  return jsonify({"error": f"AI analysis failed: {e}"}), 500
150
 
151
- # --- ROTA DE INICIALIZAÇÃO E ARQUIVOS ESTÁTICOS ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
  @app.route('/')
153
  def root():
154
  return send_file('index.html')
 
2
  import os
3
  import io
4
  import json
5
+ import base64
6
+ from PIL import Image
7
 
8
  from flask import Flask, request, jsonify, send_file
9
  from gtts import gTTS
10
  from groq import Groq
 
11
  import google.generativeai as genai
12
 
13
  # --- CONFIGURAÇÃO INICIAL ---
 
24
  genai.configure(api_key=GEMINI_API_KEY)
25
  genai_client = genai
26
  else:
27
+ print("AVISO: GEMINI_API_KEY não configurada.")
28
  except Exception as e:
29
  genai_client = None
30
+ print(f"ERRO ao inicializar o cliente Gemini: {e}.")
31
 
32
  # 2. Configuração Groq
33
  try:
 
35
  if GROQ_API_KEY:
36
  groq_client = Groq(api_key=GROQ_API_KEY)
37
  else:
38
+ print("AVISO: GROQ_API_KEY não configurada.")
39
  except Exception as e:
40
  groq_client = None
41
+ print(f"ERRO ao inicializar o cliente Groq: {e}.")
42
 
43
 
44
+ # --- ROTA 1: TEXT-TO-SPEECH (TTS) ---
45
  @app.route('/tts-proxy', methods=['POST'])
46
  def tts_proxy():
47
+ # ... (código existente sem alterações) ...
48
  data = request.get_json()
49
  text = data.get('text', '')
50
  if not text:
 
60
  return jsonify({"error": f"Failed to generate audio via gTTS: {e}"}), 500
61
 
62
 
63
+ # --- ROTA 2: ANÁLISE DE TEXTO (FLASHCARDS, ETC.) ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  @app.route('/explain-proxy', methods=['POST'])
65
  def explain_proxy():
66
+ # ... (código existente sem alterações) ...
67
  data = request.get_json()
68
+ model_provider, model_name = data.get('model', 'gemini:gemini-1.5-flash-latest').split(':', 1)
69
  word = data.get('word', '').strip()
70
  context = data.get('context', '')
71
  for_flashcard = data.get('for_flashcard', False)
 
72
  context_focus = data.get('context_focus', 'General/Social')
73
  custom_prompt = data.get('custom_prompt', None)
74
 
 
80
 
81
  try:
82
  if custom_prompt:
83
+ text_response = get_ai_text_response(model_provider, model_name, system_instruction_base, custom_prompt)
84
  return jsonify({"explanation": text_response, "translation": "Activity Generated."})
85
 
86
  if not word:
 
88
 
89
  if for_flashcard:
90
  flashcard_schema = {
91
+ "type": "object", "properties": {
 
92
  "term": {"type": "string"}, "translation": {"type": "string"},
93
  "context_sentence": {"type": "string"}, "gapped_sentence": {"type": "string"},
94
  "definition": {"type": "string"},
95
+ }, "required": ["term", "translation", "context_sentence", "gapped_sentence", "definition"]
 
96
  }
97
  system_instruction = system_instruction_base + " Your task is to generate a JSON object for an 'intelligent flashcard'."
98
  user_prompt = f"Analyze the term '{word}' in the sentence: '{context}'. Generate a JSON object following the schema. The 'gapped_sentence' must replace '{word}' with '______________'."
99
+ card_data = get_ai_text_response(model_provider, model_name, system_instruction, user_prompt, json_schema=flashcard_schema)
100
  return jsonify(card_data)
101
 
102
  else:
103
  system_instruction = system_instruction_base
104
  user_prompt = f"Analyze '{word}' in context: '{context}'. Provide a one-sentence English explanation, then '---', then the Portuguese translation."
105
+ text_response = get_ai_text_response(model_provider, model_name, system_instruction, user_prompt)
106
  parts = text_response.split('---', 1)
107
  explanation = parts[0].strip()
108
  translation = parts[1].strip() if len(parts) > 1 else 'Tradução não disponível.'
 
112
  print(f"Erro na análise de IA: {e}")
113
  return jsonify({"error": f"AI analysis failed: {e}"}), 500
114
 
115
+ # --- ROTA 3: ANÁLISE DE IMAGEM ---
116
+ @app.route('/analyze-image', methods=['POST'])
117
+ def analyze_image():
118
+ # ... (código existente sem alterações) ...
119
+ if not genai_client:
120
+ return jsonify({"error": "GEMINI_API_KEY not configured for image analysis."}), 503
121
+
122
+ data = request.get_json()
123
+ base64_image = data.get('image')
124
+ if not base64_image:
125
+ return jsonify({"error": "No image data provided."}), 400
126
+
127
+ try:
128
+ image_data = base64.b64decode(base64_image.split(',')[1])
129
+ image = Image.open(io.BytesIO(image_data))
130
+ model = genai_client.GenerativeModel('gemini-1.5-flash-latest')
131
+
132
+ vocabulary_schema = { "type": "object", "properties": { "vocabulary": { "type": "array", "items": { "type": "object", "properties": { "term": {"type": "string"}, "definition": {"type": "string"} }, "required": ["term", "definition"] } } }, "required": ["vocabulary"] }
133
+ prompt = [ "You are an English teacher. Look at this image and identify 5 to 7 key objects or concepts. For each item, provide its English name and a simple one-sentence definition. Return the result as a single JSON object that conforms to the provided schema.", image ]
134
+
135
+ response = model.generate_content( prompt, generation_config={ "response_mime_type": "application/json", "response_schema": vocabulary_schema } )
136
+ json_response = json.loads(response.text)
137
+ return jsonify(json_response['vocabulary'])
138
+
139
+ except Exception as e:
140
+ print(f"Erro na análise de imagem: {e}")
141
+ return jsonify({"error": f"Image analysis failed: {e}"}), 500
142
+
143
+
144
+ # --- ROTA 4: CHAT COM IA (NOVO - IDEAL PARA GROQ) ---
145
+ @app.route('/chat-with-ai', methods=['POST'])
146
+ def chat_with_ai():
147
+ if not groq_client:
148
+ return jsonify({"error": "GROQ_API_KEY not configured for the chat feature."}), 503
149
+
150
+ data = request.get_json()
151
+ history = data.get('history', [])
152
+ user_message = data.get('message', '')
153
+
154
+ if not user_message:
155
+ return jsonify({"error": "No message provided."}), 400
156
+
157
+ try:
158
+ # Instrução de sistema para o tutor de IA
159
+ system_instruction = "You are a friendly and encouraging English tutor named 'Groq Chat'. Your goal is to help the user practice their English conversation skills. Keep your responses concise (1-2 sentences). If the user makes a grammar mistake, gently correct it and explain briefly. Ask questions to keep the conversation flowing. Always respond in English."
160
+
161
+ # Monta o histórico de mensagens para a API
162
+ messages = [{"role": "system", "content": system_instruction}]
163
+ messages.extend(history)
164
+ messages.append({"role": "user", "content": user_message})
165
+
166
+ # Chama a API da Groq
167
+ response = groq_client.chat.completions.create(
168
+ # Usando um modelo rápido, ideal para chat
169
+ model="llama-3.1-8b-instant",
170
+ messages=messages,
171
+ temperature=0.7
172
+ )
173
+
174
+ ai_response = response.choices[0].message.content.strip()
175
+ return jsonify({"response": ai_response})
176
+
177
+ except Exception as e:
178
+ print(f"Erro no chat com IA: {e}")
179
+ return jsonify({"error": f"AI chat failed: {e}"}), 500
180
+
181
+
182
+ # --- FUNÇÃO AUXILIAR PARA CHAMADAS DE IA (APENAS TEXTO) ---
183
+ def get_ai_text_response(provider, model_name, system_instruction, user_prompt, json_schema=None):
184
+ # ... (código existente sem alterações) ...
185
+ if provider == 'gemini':
186
+ if not genai_client:
187
+ raise Exception("Gemini client not initialized.")
188
+ model = genai_client.GenerativeModel(model_name)
189
+ generation_config = {"response_mime_type": "application/json", "response_schema": json_schema} if json_schema else None
190
+ response = model.generate_content(user_prompt, generation_config=generation_config)
191
+ return json.loads(response.candidates[0].content.parts[0].text.strip()) if json_schema else response.text.strip()
192
+
193
+ elif provider == 'groq':
194
+ if not groq_client:
195
+ raise Exception("Groq client not initialized.")
196
+ messages = [{"role": "system", "content": system_instruction}, {"role": "user", "content": user_prompt}]
197
+ config_params = {'response_format': {"type": "json_object"}} if json_schema else {}
198
+ response = groq_client.chat.completions.create(model=model_name, messages=messages, **config_params)
199
+ text_response = response.choices[0].message.content.strip()
200
+ return json.loads(text_response) if json_schema else text_response
201
+
202
+ else:
203
+ raise Exception(f"Unsupported provider: {provider}")
204
+
205
+
206
+ # --- ROTA DE INICIALIZAÇÃO ---
207
  @app.route('/')
208
  def root():
209
  return send_file('index.html')