vioott commited on
Commit
5b5c1df
·
1 Parent(s): e9ba6dc

refactor: reorganized project by separating routes and services

Browse files
app.py CHANGED
@@ -1,221 +1,13 @@
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, user_histories
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
- try:
38
- genai.configure(api_key=os.environ['GOOGLE_API_KEY_3'])
39
-
40
- # Testa se a chave reserva 2 está disponível
41
- test_model = genai.GenerativeModel("gemini-1.5-flash")
42
- test_model.start_chat().send_message("ping")
43
-
44
- return
45
-
46
- except Exception:
47
- print("❌ Todas as chaves falharam.")
48
-
49
-
50
- genai_configuration()
51
-
52
- # Definir o modelo generativo com as funções disponíveis
53
- magical_if = genai.GenerativeModel("gemini-1.5-flash")
54
-
55
- GENRES = sorted([
56
- 'ficção', 'não-ficção', 'ciência', 'fantasia', 'romance', 'mistério',
57
- 'terror', 'aventura', 'história', 'biografia', 'autoajuda',
58
- 'espiritualidade', 'filosofia', 'poesia', 'drama', 'humor', 'tecnologia',
59
- 'educação', 'negócios'
60
- ])
61
-
62
-
63
- def ia_decision(user_id, history):
64
- business_rules = """
65
- Analise o histórico de compras do usuário e recomende livros a ele.
66
-
67
- Regras:
68
- 1. Se o usuário demonstrou interesse em ficção, recomende ficção.
69
- 2. Se o usuário demonstrou interesse em não ficção, recomende não-ficção.
70
- 3. Se o usuário demonstrou interesse em ciência, recomende ciência.
71
- 4. Se o usuário demonstrou interesse em fantasia, recomende fantasia.
72
- 5. Se o usuário não demonstrou interesse em nenhuma categoria, recomende
73
- os livros mais vendidos no último mês.
74
- """
75
-
76
- user_decision = magical_if.start_chat(
77
- enable_automatic_function_calling=True
78
- )
79
-
80
- message = (
81
- f"Histórico do usuário {user_id}: {history}\n"
82
- f"Regras de negócio:\n{business_rules}"
83
- )
84
-
85
- response = user_decision.send_message(message)
86
-
87
- return response.text
88
-
89
-
90
- @app.route('/', methods=['GET', 'POST'])
91
- def inicio():
92
- if request.method == 'POST':
93
- name = request.form.get('name')
94
- preferences = request.form.getlist('preferences')
95
-
96
- # Simula criação de novo ID
97
- new_id = max(user_histories.keys()) + 1
98
-
99
- user_histories[new_id] = {
100
- 'name': name,
101
- 'preferences': preferences
102
- }
103
-
104
- return redirect(f'/chat/{new_id}')
105
-
106
- return render_template(
107
- 'start.html',
108
- profiles=user_histories,
109
- genres=GENRES
110
- )
111
-
112
-
113
- @app.route('/perfil/<int:user_id>', methods=['GET', 'POST'])
114
- def perfil(user_id):
115
- history = get_user_history(user_id)
116
-
117
- if not history:
118
- return '''
119
- <html>
120
- <head>
121
- <meta http-equiv="refresh" content="2;url=/">
122
- </head>
123
- <body>
124
- <h2>Ops, algo deu errado por aqui.</h2>
125
- <p>Vou te levar de volta para a página inicial.</p>
126
- </body>
127
- </html>
128
- '''
129
-
130
- if request.method == 'POST':
131
-
132
- name = request.form.get('name')
133
- preferences = request.form.getlist('preferences')
134
-
135
- # aqui vamos salvar nome e preferências
136
- history['name'] = name
137
- history['preferences'] = preferences
138
-
139
- return redirect(f'/chat/{user_id}')
140
-
141
- return render_template(
142
- 'profile.html',
143
- user_id=user_id,
144
- history=history,
145
- genres=GENRES
146
- )
147
-
148
-
149
- @app.route('/chat/<int:user_id>', methods=['GET', 'POST'])
150
- def chat(user_id):
151
- history = get_user_history(user_id)
152
-
153
- if not history:
154
- return '''
155
- <html>
156
- <head>
157
- <meta http-equiv="refresh" content="2;url=/">
158
- </head>
159
- <body>
160
- <h2>Ops, algo deu errado por aqui.</h2>
161
- <p>Vou te levar de volta para a página inicial.</p>
162
- </body>
163
- </html>
164
- '''
165
-
166
- response = None
167
-
168
- if request.method == 'POST':
169
- question = request.form.get('question')
170
-
171
- user_decision = magical_if.start_chat(
172
- enable_automatic_function_calling=True
173
- )
174
-
175
- name = history.get("name", f"Usuário {user_id}")
176
- preferences = history.get("preferences", [])
177
-
178
- prompt = (
179
- f"Você é uma especialista em livros e pode conversar livremente "
180
- f"sobre obras literárias, personagens, enredos, gêneros e autores."
181
- f" O nome do usuário é {name} e seu ID é {user_id}. A informação "
182
- f"sobre o id é somente para você, não mencione nada sobre isso ao "
183
- f"usuário. As preferências dele são: "
184
- f"{', '.join(preferences) or 'nenhuma preferência registrada'}. "
185
- f"Histórico de compras: {history}. "
186
- f"Pergunta: {question}"
187
- f"Responda na mesma língua em que foi feita a pergunta."
188
- f"Sempre fale com o usuário se dirigindo diretamente a ele, "
189
- f"não se refira a ele em terceira pessoa, como se estivesse "
190
- f"falando de outra pessoa."
191
- f" Dê respostas com no máximo 500 caracteres."
192
- )
193
-
194
- gemini_response = user_decision.send_message(prompt)
195
- response = gemini_response.text
196
-
197
- save_log(user_id, history, response)
198
-
199
- formatted_response = None
200
- if response:
201
- formatted_response = response.replace('\n', '<br>')
202
-
203
- formatted_response = re.sub(
204
- r'(?<=<br>)\s*(Ficção|Não[- ]Ficção|Ciência|Fantasia)\s*:(?=<br>)',
205
- r'<b>\1:</b>',
206
- f"<br>{formatted_response}<br>"
207
- )[4:-4]
208
-
209
- formatted_response = formatted_response.replace('**', '')
210
- formatted_response = formatted_response.replace('* ', '• ')
211
-
212
- return render_template(
213
- 'chat.html',
214
- user_id=user_id,
215
- response=formatted_response,
216
- history=history
217
- )
218
-
219
 
220
  if __name__ == '__main__':
221
  app.run(debug=True)
 
1
+ from flask import Flask
2
+ from routes.home import home_bp
3
+ from routes.chat import chat_bp
4
+ from routes.profile import profile_bp
 
 
5
 
6
  app = Flask(__name__)
7
 
8
+ app.register_blueprint(home_bp)
9
+ app.register_blueprint(chat_bp)
10
+ app.register_blueprint(profile_bp)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
  if __name__ == '__main__':
13
  app.run(debug=True)
constants/genres.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ # Lista de gêneros literários disponíveis para seleção de preferências.
2
+
3
+ GENRES = sorted([
4
+ 'ficção', 'não-ficção', 'ciência', 'fantasia', 'romance', 'mistério',
5
+ 'terror', 'aventura', 'história', 'biografia', 'autoajuda',
6
+ 'espiritualidade', 'filosofia', 'poesia', 'drama', 'humor',
7
+ 'tecnologia', 'educação', 'negócios'
8
+ ])
routes/__init__.py ADDED
File without changes
routes/chat.py ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ from flask import Blueprint, render_template, request
3
+ from services.genai_service import configure_genai
4
+ from logs import get_user_history, save_log
5
+
6
+ chat_bp = Blueprint('chat', __name__)
7
+
8
+ model = configure_genai()
9
+
10
+
11
+ @chat_bp.route('/chat/<int:user_id>', methods=['GET', 'POST'])
12
+ def chat(user_id):
13
+ """
14
+ Rota para interação do usuário com a IA.
15
+ """
16
+ history = get_user_history(user_id)
17
+
18
+ if not history:
19
+ return '''
20
+ <html>
21
+ <head>
22
+ <meta http-equiv="refresh" content="2;url=/" />
23
+ </head>
24
+ <body>
25
+ <h2>Ops, algo deu errado por aqui.</h2>
26
+ <p>Vou te levar de volta para a página inicial.</p>
27
+ </body>
28
+ </html>
29
+ '''
30
+
31
+ response = None
32
+
33
+ if request.method == 'POST':
34
+ question = request.form.get('question')
35
+
36
+ session = model.start_chat(enable_automatic_function_calling=True)
37
+
38
+ prompt = (
39
+ f"Você é uma especialista em livros e pode conversar livremente "
40
+ f"sobre obras literárias, personagens, enredos, gêneros e autores. "
41
+ f"O nome do usuário é {history.get('name', f'Usuário {user_id}')}. "
42
+ f"As preferências dele são: "
43
+ f"{', '.join(history.get('preferences', [])) or 'nenhuma'}. "
44
+ f"Histórico: {history}. "
45
+ f"Pergunta: {question} "
46
+ f"Responda na mesma língua da pergunta, com até 500 caracteres. "
47
+ f"Fale diretamente com o usuário."
48
+ )
49
+
50
+ gemini_response = session.send_message(prompt)
51
+ response = gemini_response.text
52
+
53
+ save_log(user_id, history, response)
54
+
55
+ formatted_response = None
56
+ if response:
57
+ formatted_response = response.replace('\n', '<br>')
58
+ formatted_response = re.sub(
59
+ r'(?<=<br>)\s*(Ficção|Não[- ]Ficção|Ciência|Fantasia)\s*:(?=<br>)',
60
+ r'<b>\1:</b>',
61
+ f"<br>{formatted_response}<br>"
62
+ )[4:-4]
63
+ formatted_response = formatted_response.replace('**', '')
64
+ formatted_response = formatted_response.replace('* ', '• ')
65
+
66
+ return render_template(
67
+ 'chat.html',
68
+ user_id=user_id,
69
+ response=formatted_response,
70
+ history=history
71
+ )
routes/home.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Blueprint, render_template, request, redirect
2
+ from logs import get_user_history
3
+ from constants.genres import GENRES
4
+
5
+ home_bp = Blueprint('home', __name__)
6
+
7
+
8
+ @home_bp.route('/', methods=['GET', 'POST'])
9
+ def inicio():
10
+ """
11
+ Rota inicial para criação de perfil ou acesso a perfis existentes.
12
+ """
13
+ if request.method == 'POST':
14
+ name = request.form.get('name')
15
+ preferences = request.form.getlist('preferences')
16
+
17
+ # Simula criação de novo ID com base no maior já existente
18
+ new_id = max(get_user_history.keys(), default=0) + 1
19
+
20
+ get_user_history[new_id] = {
21
+ 'name': name,
22
+ 'preferences': preferences
23
+ }
24
+
25
+ return redirect(f'/chat/{new_id}')
26
+
27
+ return render_template(
28
+ 'start.html',
29
+ profiles=get_user_history,
30
+ genres=GENRES
31
+ )
routes/profile.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Blueprint, render_template, request, redirect
2
+ from logs import get_user_history
3
+ from constants.genres import GENRES
4
+
5
+ profile_bp = Blueprint('profile', __name__)
6
+
7
+
8
+ @profile_bp.route('/perfil/<int:user_id>', methods=['GET', 'POST'])
9
+ def perfil(user_id):
10
+ """
11
+ Rota para visualizar e atualizar nome e preferências do perfil.
12
+ """
13
+ history = get_user_history(user_id)
14
+
15
+ if not history:
16
+ return '''
17
+ <html>
18
+ <head>
19
+ <meta http-equiv="refresh" content="2;url=/" />
20
+ </head>
21
+ <body>
22
+ <h2>Ops, algo deu errado por aqui.</h2>
23
+ <p>Vou te levar de volta para a página inicial.</p>
24
+ </body>
25
+ </html>
26
+ '''
27
+
28
+ if request.method == 'POST':
29
+ name = request.form.get('name')
30
+ preferences = request.form.getlist('preferences')
31
+
32
+ history['name'] = name
33
+ history['preferences'] = preferences
34
+
35
+ return redirect(f'/chat/{user_id}')
36
+
37
+ return render_template(
38
+ 'profile.html',
39
+ user_id=user_id,
40
+ history=history,
41
+ genres=GENRES
42
+ )
services/__init__.py ADDED
File without changes
services/genai_service.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import google.generativeai as genai
3
+
4
+
5
+ def configure_genai():
6
+ """
7
+ Configura a chave de API e inicializa o modelo Gemini.
8
+ """
9
+ api_key = os.environ.get("GOOGLE_API_KEY")
10
+
11
+ if not api_key:
12
+ raise EnvironmentError(
13
+ "❌ A variável de ambiente GOOGLE_API_KEY não está definida."
14
+ )
15
+
16
+ try:
17
+ genai.configure(api_key=api_key)
18
+
19
+ # Testa se a chave está funcionando
20
+ model = genai.GenerativeModel("gemini-1.5-flash")
21
+ model.start_chat().send_message("ping")
22
+
23
+ print("✅ Chave da API configurada com sucesso.")
24
+ return model
25
+
26
+ except Exception as e:
27
+ raise RuntimeError(f"❌ Falha ao configurar a chave da API: {e}")