vioott commited on
Commit
b2548e5
·
1 Parent(s): 809791b

refactor(app): improve AI logic, key fallback, and response formatting

Browse files

- Refactored the ia_decision logic to simplify recommendations and remove dependency on function calling.
- Added support for a third fallback API key (GOOGLE_API_KEY_3) for more robustness.
- Improved 404 response by adding clearer fallback and auto-redirect to homepage.
- Enhanced prompt to personalize answers and improve AI response quality.
- Adjusted response formatting for better readability.
- Removed unused /recomendacoes route and its dependencies.

Files changed (1) hide show
  1. app.py +103 -84
app.py CHANGED
@@ -1,48 +1,70 @@
1
  import os
 
2
  import google.generativeai as genai
3
  from flask import Flask, redirect, render_template, request
4
  from user_data import get_user_history
5
  from logs import save_log
6
- from book_recommendations import (
7
- recommend_fiction,
8
- recommend_non_fiction,
9
- recommend_science,
10
- recommend_fantasy
11
- )
12
 
13
  app = Flask(__name__)
14
 
15
- # Configurar a chave de API
16
- GOOGLE_API_KEY = os.environ.get('GOOGLE_API_KEY')
17
- genai.configure(api_key=GOOGLE_API_KEY)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
  # Definir o modelo generativo com as funções disponíveis
20
- magical_if = genai.GenerativeModel(
21
- "gemini-1.5-flash",
22
- tools=[
23
- recommend_fiction,
24
- recommend_non_fiction,
25
- recommend_science,
26
- recommend_fantasy
27
- ]
28
- )
29
 
30
 
31
  def ia_decision(user_id, history):
32
  business_rules = """
33
- Analise o histórico de compras do usuário e chame diretamente a função
34
- correspondente à categoria de livros recomendada.
35
 
36
  Regras:
37
- 1. Se o usuário comprou mais livros de ficção, recomende ficção.
38
- 2. Se o usuário comprou mais livros de não ficção, recomende não ficção.
39
  3. Se o usuário demonstrou interesse em ciência, recomende ciência.
40
  4. Se o usuário demonstrou interesse em fantasia, recomende fantasia.
41
- 5. Caso contrário, ofereça uma recomendação geral de ficção.
42
-
43
- ATENÇÃO: Sempre retorne a resposta da função chamada.
44
- Não explique, apenas chame.
45
  """
 
46
  user_decision = magical_if.start_chat(
47
  enable_automatic_function_calling=True
48
  )
@@ -54,24 +76,6 @@ def ia_decision(user_id, history):
54
 
55
  response = user_decision.send_message(message)
56
 
57
- # Tenta obter a chamada de função feita pela IA
58
- try:
59
- function_call = response.candidates[0].content.parts[0].function_call
60
- function_name = function_call.name
61
-
62
- user_function = {
63
- "recommend_fiction": recommend_fiction,
64
- "recommend_non_fiction": recommend_non_fiction,
65
- "recommend_science": recommend_science,
66
- "recommend_fantasy": recommend_fantasy
67
- }.get(function_name)
68
-
69
- if user_function:
70
- return user_function(user_id)
71
- except (AttributeError, IndexError):
72
- pass
73
-
74
- # Caso nenhuma função tenha sido chamada, retorna o texto
75
  return response.text
76
 
77
 
@@ -101,12 +105,25 @@ def inicio():
101
  @app.route('/perfil/<int:user_id>', methods=['GET', 'POST'])
102
  def perfil(user_id):
103
  history = get_user_history(user_id)
 
104
  if not history:
105
- return "Usuário não encontrado", 404
 
 
 
 
 
 
 
 
 
 
106
 
107
  if request.method == 'POST':
 
108
  name = request.form.get('name')
109
  preferences = request.form.getlist('preferences')
 
110
  # aqui vamos salvar nome e preferências
111
  history['name'] = name
112
  history['preferences'] = preferences
@@ -117,69 +134,71 @@ def perfil(user_id):
117
  @app.route('/chat/<int:user_id>', methods=['GET', 'POST'])
118
  def chat(user_id):
119
  history = get_user_history(user_id)
 
120
  if not history:
121
- return "Usuário não encontrado", 404
 
 
 
 
 
 
 
 
 
 
122
 
123
  response = None
124
 
125
  if request.method == 'POST':
126
  question = request.form.get('question')
 
127
  user_decision = magical_if.start_chat(
128
  enable_automatic_function_calling=True
129
  )
 
130
  name = history.get("name", f"Usuário {user_id}")
131
  preferences = history.get("preferences", [])
 
132
  prompt = (
133
- f"O nome do usuário é {name}. "
134
- f"As preferências dele são: "
 
 
 
135
  f"{', '.join(preferences) or 'nenhuma preferência registrada'}. "
136
  f"Histórico de compras: {history}. "
137
  f"Pergunta: {question}"
 
 
 
 
 
138
  )
 
139
  gemini_response = user_decision.send_message(prompt)
140
- try:
141
- function_call = (
142
- gemini_response
143
- .candidates[0]
144
- .content.parts[0]
145
- .function_call
146
- )
147
- function_name = function_call.name
148
- user_function = {
149
- "recommend_fiction": recommend_fiction,
150
- "recommend_non_fiction": recommend_non_fiction,
151
- "recommend_science": recommend_science,
152
- "recommend_fantasy": recommend_fantasy
153
- }.get(function_name)
154
-
155
- if user_function:
156
- response = user_function(user_id)
157
- else:
158
- response = gemini_response.text
159
- except (AttributeError, IndexError):
160
- response = gemini_response.text
161
 
162
  save_log(user_id, history, response)
163
 
164
- return render_template(
165
- 'chat.html',
166
- user_id=user_id,
167
- response=response,
168
- history=history
169
- )
170
 
 
 
 
 
 
 
 
 
171
 
172
- @app.route('/recomendacoes/<int:user_id>')
173
- def recommend(user_id):
174
- history = get_user_history(user_id)
175
- if not history:
176
- return "Usuário não encontrado", 404
177
- ia_response = ia_decision(user_id, history)
178
- save_log(user_id, history, ia_response)
179
  return render_template(
180
- 'recommendation.html',
181
  user_id=user_id,
182
- message=ia_response
 
183
  )
184
 
185
 
 
1
  import os
2
+ import re
3
  import google.generativeai as genai
4
  from flask import Flask, redirect, render_template, request
5
  from user_data import get_user_history
6
  from logs import save_log
 
 
 
 
 
 
7
 
8
  app = Flask(__name__)
9
 
10
+
11
+ # Função para configurar a chave de API
12
+ def genai_configuration():
13
+ try:
14
+ genai.configure(api_key=os.environ['GOOGLE_API_KEY'])
15
+
16
+ # Testa se a chave principal está disponível
17
+ test_model = genai.GenerativeModel("gemini-1.5-flash")
18
+ test_model.start_chat().send_message("ping")
19
+
20
+ return
21
+
22
+ except Exception:
23
+ print("⚠️ Falha com a chave principal, tentando chave reserva 1.")
24
+
25
+ try:
26
+ genai.configure(api_key=os.environ['GOOGLE_API_KEY_2'])
27
+
28
+ # Testa se a chave reserva 1 está disponível
29
+ test_model = genai.GenerativeModel("gemini-1.5-flash")
30
+ test_model.start_chat().send_message("ping")
31
+
32
+ return
33
+
34
+ except Exception:
35
+ print("⚠️ Falha com a chave reserva 1, tentando chave reserva 2.")
36
+
37
+ genai.configure(api_key=os.environ['GOOGLE_API_KEY_3'])
38
+
39
+ # Testa se a chave reserva 2 está disponível
40
+ test_model = genai.GenerativeModel("gemini-1.5-flash")
41
+ test_model.start_chat().send_message("ping")
42
+
43
+ return
44
+
45
+ except Exception:
46
+ print("❌ Todas as chaves falharam.")
47
+
48
+
49
+ genai_configuration()
50
 
51
  # Definir o modelo generativo com as funções disponíveis
52
+ magical_if = genai.GenerativeModel("gemini-1.5-flash")
 
 
 
 
 
 
 
 
53
 
54
 
55
  def ia_decision(user_id, history):
56
  business_rules = """
57
+ Analise o histórico de compras do usuário e recomende livros a ele.
 
58
 
59
  Regras:
60
+ 1. Se o usuário demonstrou interesse em ficção, recomende ficção.
61
+ 2. Se o usuário demonstrou interesse em não ficção, recomende não-ficção.
62
  3. Se o usuário demonstrou interesse em ciência, recomende ciência.
63
  4. Se o usuário demonstrou interesse em fantasia, recomende fantasia.
64
+ 5. Se o usuário não demonstrou interesse em nenhuma categoria, recomende
65
+ os livros mais vendidos no último mês.
 
 
66
  """
67
+
68
  user_decision = magical_if.start_chat(
69
  enable_automatic_function_calling=True
70
  )
 
76
 
77
  response = user_decision.send_message(message)
78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  return response.text
80
 
81
 
 
105
  @app.route('/perfil/<int:user_id>', methods=['GET', 'POST'])
106
  def perfil(user_id):
107
  history = get_user_history(user_id)
108
+
109
  if not history:
110
+ return '''
111
+ <html>
112
+ <head>
113
+ <meta http-equiv="refresh" content="2;url=/">
114
+ </head>
115
+ <body>
116
+ <h2>Ops, algo deu errado por aqui.</h2>
117
+ <p>Vou te levar de volta para a página inicial.</p>
118
+ </body>
119
+ </html>
120
+ '''
121
 
122
  if request.method == 'POST':
123
+
124
  name = request.form.get('name')
125
  preferences = request.form.getlist('preferences')
126
+
127
  # aqui vamos salvar nome e preferências
128
  history['name'] = name
129
  history['preferences'] = preferences
 
134
  @app.route('/chat/<int:user_id>', methods=['GET', 'POST'])
135
  def chat(user_id):
136
  history = get_user_history(user_id)
137
+
138
  if not history:
139
+ return '''
140
+ <html>
141
+ <head>
142
+ <meta http-equiv="refresh" content="2;url=/">
143
+ </head>
144
+ <body>
145
+ <h2>Ops, algo deu errado por aqui.</h2>
146
+ <p>Vou te levar de volta para a página inicial.</p>
147
+ </body>
148
+ </html>
149
+ '''
150
 
151
  response = None
152
 
153
  if request.method == 'POST':
154
  question = request.form.get('question')
155
+
156
  user_decision = magical_if.start_chat(
157
  enable_automatic_function_calling=True
158
  )
159
+
160
  name = history.get("name", f"Usuário {user_id}")
161
  preferences = history.get("preferences", [])
162
+
163
  prompt = (
164
+ f"Você é uma especialista em livros e pode conversar livremente "
165
+ f"sobre obras literárias, personagens, enredos, gêneros e autores."
166
+ f" O nome do usuário é {name} e seu ID é {user_id}. A informação "
167
+ f"sobre o id é somente para você, não mencione nada sobre isso ao "
168
+ f"usuário. As preferências dele são: "
169
  f"{', '.join(preferences) or 'nenhuma preferência registrada'}. "
170
  f"Histórico de compras: {history}. "
171
  f"Pergunta: {question}"
172
+ f"Responda na mesma língua em que foi feita a pergunta."
173
+ f"Sempre fale com o usuário se dirigindo diretamente a ele, "
174
+ f"não se refira a ele em terceira pessoa, como se estivesse "
175
+ f"falando de outra pessoa."
176
+ f" Dê respostas com no máximo 500 caracteres."
177
  )
178
+
179
  gemini_response = user_decision.send_message(prompt)
180
+ response = gemini_response.text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
 
182
  save_log(user_id, history, response)
183
 
184
+ formatted_response = None
185
+ if response:
186
+ formatted_response = response.replace('\n', '<br>')
 
 
 
187
 
188
+ formatted_response = re.sub(
189
+ r'(?<=<br>)\s*(Ficção|Não[- ]Ficção|Ciência|Fantasia)\s*:(?=<br>)',
190
+ r'<b>\1:</b>',
191
+ f"<br>{formatted_response}<br>"
192
+ )[4:-4]
193
+
194
+ formatted_response = formatted_response.replace('**', '')
195
+ formatted_response = formatted_response.replace('* ', '• ')
196
 
 
 
 
 
 
 
 
197
  return render_template(
198
+ 'chat.html',
199
  user_id=user_id,
200
+ response=formatted_response,
201
+ history=history
202
  )
203
 
204