danielraynaud commited on
Commit
f26a057
·
verified ·
1 Parent(s): fd4a644

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +253 -78
app.py CHANGED
@@ -1,11 +1,120 @@
 
1
  import gradio as gr
2
  from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
3
  import json
4
  import os
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
  class RevalidaBot:
7
  def __init__(self):
8
- # Inicializa o modelo
 
 
 
9
  self.model_id = "meta-llama/Llama-2-7b-chat-hf"
10
  self.tokenizer = AutoTokenizer.from_pretrained(self.model_id)
11
  self.pipeline = pipeline(
@@ -15,109 +124,171 @@ class RevalidaBot:
15
  max_length=500
16
  )
17
 
18
- # Carrega a base de conhecimento
19
- self.knowledge = self.load_knowledge()
20
-
21
- # Define os comandos disponíveis
22
  self.commands = {
23
  "/start": self.start_command,
 
 
 
24
  "/estudo": self.study_mode,
25
- "/caso": self.clinical_case,
26
- "/questao": self.question_mode,
27
  "/ajuda": self.help_command
28
  }
29
-
30
- def load_knowledge(self):
31
- """Carrega base de conhecimento do Revalida"""
32
- try:
33
- if os.path.exists("knowledge_base.json"):
34
- with open("knowledge_base.json", "r", encoding="utf-8") as f:
35
- return json.load(f)
36
- return {}
37
- except Exception as e:
38
- print(f"Erro ao carregar conhecimento: {e}")
39
- return {}
40
-
41
- def process_message(self, message, history):
42
  """Processa mensagens recebidas"""
43
  try:
44
- # Verifica se é um comando
45
  if message.startswith("/"):
46
  command = message.split()[0]
47
  if command in self.commands:
48
- return self.commands[command](message)
49
  return "Comando não reconhecido. Use /ajuda para ver os comandos disponíveis."
50
 
51
- # Processa pergunta normal
52
  return self.generate_response(message, history)
53
 
54
  except Exception as e:
55
  return f"Desculpe, ocorreu um erro: {str(e)}"
56
 
57
- def generate_response(self, message, history):
58
- """Gera resposta para perguntas sobre o Revalida"""
59
- prompt = f"""
60
- Pergunta sobre Revalida: {message}
61
-
62
- Como assistente especializado em Revalida, forneça uma resposta:
63
- 1. Objetiva e direta
64
- 2. Baseada em evidências
65
- 3. Focada no exame
66
- 4. Com exemplos práticos quando relevante
67
- """
68
-
69
- response = self.pipeline(prompt, max_length=500)[0]['generated_text']
70
- return response
71
-
72
- # Comandos
73
- def start_command(self, _):
74
- return """🏥 Bem-vindo ao Assistente Revalida!
75
-
76
- Comandos disponíveis:
77
- /estudo - Modo estudo direcionado
78
- /caso - Gerar caso clínico
79
- /questao - Questão exemplo
80
- /ajuda - Ver ajuda
81
-
82
- Digite sua dúvida a qualquer momento!"""
83
-
84
- def study_mode(self, message):
85
- topic = message.replace("/estudo", "").strip()
86
- if not topic:
87
- return "Por favor, especifique o tópico após /estudo. Exemplo: /estudo clínica médica"
88
 
89
- prompt = f"Prepare um resumo focado para o Revalida sobre: {topic}"
90
- return self.generate_response(prompt, None)
91
-
92
- def clinical_case(self, _):
93
- prompt = "Gere um caso clínico objetivo para estudo do Revalida"
94
- return self.generate_response(prompt, None)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
 
96
- def question_mode(self, _):
97
- prompt = "Crie uma questão de múltipla escolha no estilo Revalida"
98
- return self.generate_response(prompt, None)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
 
100
- def help_command(self, _):
101
- return """📚 Comandos do Assistente Revalida:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
 
103
- /start - Iniciar/Reiniciar
104
- /estudo [tópico] - Estudar um tópico específico
105
- /caso - Gerar caso clínico para estudo
106
- /questao - Gerar questão exemplo
107
- /ajuda - Ver esta mensagem
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
 
109
- 💡 Dicas:
110
- - Digite sua dúvida normalmente para perguntar
111
- - Seja específico nas perguntas
112
- - Use os comandos para funções especiais"""
113
 
114
  def create_interface():
115
- """Cria a interface Gradio"""
116
  bot = RevalidaBot()
117
 
118
  with gr.Blocks(title="Assistente Revalida") as interface:
119
- gr.Markdown("# 🏥 Assistente Revalida")
120
- gr.Markdown("### Seu companheiro de estudos para o Revalida")
 
 
 
 
 
 
 
121
 
122
  chatbot = gr.Chatbot()
123
  msg = gr.Textbox(
@@ -126,8 +297,12 @@ def create_interface():
126
  )
127
  clear = gr.ClearButton([msg, chatbot])
128
 
 
 
 
 
129
  msg.submit(
130
- bot.process_message,
131
  [msg, chatbot],
132
  [chatbot]
133
  )
 
1
+ # app.py
2
  import gradio as gr
3
  from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
4
  import json
5
  import os
6
+ import sqlite3
7
+ from datetime import datetime, timedelta
8
+ import pandas as pd
9
+ from typing import Dict, List, Optional
10
+
11
+ class RevalidaDatabase:
12
+ def __init__(self):
13
+ self.conn = sqlite3.connect('revalida.db')
14
+ self.create_tables()
15
+ self.load_previous_questions()
16
+
17
+ def create_tables(self):
18
+ """Cria tabelas necessárias"""
19
+ self.conn.execute('''
20
+ CREATE TABLE IF NOT EXISTS users (
21
+ user_id TEXT PRIMARY KEY,
22
+ name TEXT,
23
+ study_hours INTEGER,
24
+ start_date DATE,
25
+ target_date DATE,
26
+ weak_areas TEXT
27
+ )''')
28
+
29
+ self.conn.execute('''
30
+ CREATE TABLE IF NOT EXISTS study_progress (
31
+ user_id TEXT,
32
+ date DATE,
33
+ topic TEXT,
34
+ hours_studied FLOAT,
35
+ questions_answered INTEGER,
36
+ performance_score FLOAT,
37
+ FOREIGN KEY (user_id) REFERENCES users(user_id)
38
+ )''')
39
+
40
+ self.conn.execute('''
41
+ CREATE TABLE IF NOT EXISTS previous_questions (
42
+ id INTEGER PRIMARY KEY,
43
+ year INTEGER,
44
+ area TEXT,
45
+ question_text TEXT,
46
+ options TEXT,
47
+ correct_answer TEXT,
48
+ explanation TEXT
49
+ )''')
50
+
51
+ self.conn.commit()
52
+
53
+ def load_previous_questions(self):
54
+ """Carrega questões de provas anteriores do arquivo JSON"""
55
+ try:
56
+ with open('previous_questions.json', 'r', encoding='utf-8') as f:
57
+ questions = json.load(f)
58
+ cursor = self.conn.cursor()
59
+ for q in questions:
60
+ cursor.execute('''
61
+ INSERT OR IGNORE INTO previous_questions
62
+ (year, area, question_text, options, correct_answer, explanation)
63
+ VALUES (?, ?, ?, ?, ?, ?)
64
+ ''', (q['year'], q['area'], q['question_text'],
65
+ json.dumps(q['options']), q['correct_answer'], q['explanation']))
66
+ self.conn.commit()
67
+ except Exception as e:
68
+ print(f"Erro ao carregar questões: {e}")
69
+
70
+ class StudyPlanGenerator:
71
+ def __init__(self, db: RevalidaDatabase):
72
+ self.db = db
73
+
74
+ def create_study_plan(self, user_id: str, available_hours: int,
75
+ target_date: str, weak_areas: List[str]) -> Dict:
76
+ """Gera plano de estudos personalizado"""
77
+
78
+ # Calcula período total de estudo
79
+ start_date = datetime.now()
80
+ target_date = datetime.strptime(target_date, '%Y-%m-%d')
81
+ total_days = (target_date - start_date).days
82
+
83
+ # Define distribuição de tópicos
84
+ topics = {
85
+ "Clínica Médica": 0.25,
86
+ "Cirurgia": 0.20,
87
+ "Pediatria": 0.15,
88
+ "Ginecologia e Obstetrícia": 0.15,
89
+ "Medicina de Família": 0.15,
90
+ "Saúde Mental": 0.10
91
+ }
92
+
93
+ # Ajusta pesos para áreas fracas
94
+ for area in weak_areas:
95
+ if area in topics:
96
+ topics[area] += 0.05
97
+
98
+ # Normaliza pesos
99
+ total_weight = sum(topics.values())
100
+ topics = {k: v/total_weight for k, v in topics.items()}
101
+
102
+ # Gera cronograma
103
+ schedule = {}
104
+ for week in range(total_days // 7 + 1):
105
+ schedule[f"Semana {week+1}"] = {
106
+ topic: round(hours * available_hours * topics[topic], 1)
107
+ for topic in topics
108
+ }
109
+
110
+ return schedule
111
 
112
  class RevalidaBot:
113
  def __init__(self):
114
+ self.db = RevalidaDatabase()
115
+ self.planner = StudyPlanGenerator(self.db)
116
+
117
+ # Modelo de linguagem
118
  self.model_id = "meta-llama/Llama-2-7b-chat-hf"
119
  self.tokenizer = AutoTokenizer.from_pretrained(self.model_id)
120
  self.pipeline = pipeline(
 
124
  max_length=500
125
  )
126
 
127
+ # Comandos disponíveis
 
 
 
128
  self.commands = {
129
  "/start": self.start_command,
130
+ "/plano": self.create_plan,
131
+ "/progresso": self.check_progress,
132
+ "/questoes": self.previous_questions,
133
  "/estudo": self.study_mode,
 
 
134
  "/ajuda": self.help_command
135
  }
136
+
137
+ def process_message(self, message: str, user_id: str, history: List) -> str:
 
 
 
 
 
 
 
 
 
 
 
138
  """Processa mensagens recebidas"""
139
  try:
 
140
  if message.startswith("/"):
141
  command = message.split()[0]
142
  if command in self.commands:
143
+ return self.commands[command](message, user_id)
144
  return "Comando não reconhecido. Use /ajuda para ver os comandos disponíveis."
145
 
 
146
  return self.generate_response(message, history)
147
 
148
  except Exception as e:
149
  return f"Desculpe, ocorreu um erro: {str(e)}"
150
 
151
+ def create_plan(self, message: str, user_id: str) -> str:
152
+ """Cria plano de estudos personalizado"""
153
+ try:
154
+ # Extrai parâmetros da mensagem
155
+ # Formato: /plano horas_diarias YYYY-MM-DD área1,área2
156
+ parts = message.split()
157
+ if len(parts) < 3:
158
+ return "Formato: /plano horas_diarias YYYY-MM-DD área1,área2"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
 
160
+ hours = int(parts[1])
161
+ target_date = parts[2]
162
+ weak_areas = parts[3].split(',') if len(parts) > 3 else []
163
+
164
+ plan = self.planner.create_study_plan(
165
+ user_id, hours, target_date, weak_areas
166
+ )
167
+
168
+ # Formata resposta
169
+ response = "📚 Seu Plano de Estudos:\n\n"
170
+ for week, topics in plan.items():
171
+ response += f"{week}:\n"
172
+ for topic, hours in topics.items():
173
+ response += f"- {topic}: {hours}h\n"
174
+ response += "\n"
175
+
176
+ return response
177
+
178
+ except Exception as e:
179
+ return f"Erro ao criar plano: {str(e)}"
180
 
181
+ def check_progress(self, message: str, user_id: str) -> str:
182
+ """Verifica progresso do usuário"""
183
+ try:
184
+ cursor = self.db.conn.cursor()
185
+ cursor.execute('''
186
+ SELECT topic, SUM(hours_studied) as total_hours,
187
+ AVG(performance_score) as avg_score
188
+ FROM study_progress
189
+ WHERE user_id = ?
190
+ GROUP BY topic
191
+ ''', (user_id,))
192
+
193
+ progress = cursor.fetchall()
194
+
195
+ response = "📊 Seu Progresso:\n\n"
196
+ for topic, hours, score in progress:
197
+ response += f"{topic}:\n"
198
+ response += f"- Horas estudadas: {hours:.1f}h\n"
199
+ response += f"- Desempenho médio: {score:.1f}%\n\n"
200
+
201
+ return response
202
+
203
+ except Exception as e:
204
+ return f"Erro ao verificar progresso: {str(e)}"
205
 
206
+ def previous_questions(self, message: str, user_id: str) -> str:
207
+ """Busca questões de provas anteriores"""
208
+ try:
209
+ # Formato: /questoes área [ano]
210
+ parts = message.split()
211
+ if len(parts) < 2:
212
+ return "Formato: /questoes área [ano]"
213
+
214
+ area = parts[1]
215
+ year = int(parts[2]) if len(parts) > 2 else None
216
+
217
+ cursor = self.db.conn.cursor()
218
+ if year:
219
+ cursor.execute('''
220
+ SELECT question_text, options, correct_answer, explanation
221
+ FROM previous_questions
222
+ WHERE area = ? AND year = ?
223
+ ORDER BY RANDOM()
224
+ LIMIT 1
225
+ ''', (area, year))
226
+ else:
227
+ cursor.execute('''
228
+ SELECT question_text, options, correct_answer, explanation
229
+ FROM previous_questions
230
+ WHERE area = ?
231
+ ORDER BY RANDOM()
232
+ LIMIT 1
233
+ ''', (area,))
234
+
235
+ question = cursor.fetchone()
236
+ if not question:
237
+ return "Nenhuma questão encontrada com esses critérios."
238
+
239
+ response = f"📝 Questão:\n\n{question[0]}\n\n"
240
+ options = json.loads(question[1])
241
+ for letter, text in options.items():
242
+ response += f"{letter}) {text}\n"
243
+ response += f"\nResposta: {question[2]}\n"
244
+ response += f"Explicação: {question[3]}"
245
+
246
+ return response
247
+
248
+ except Exception as e:
249
+ return f"Erro ao buscar questão: {str(e)}"
250
 
251
+ def study_mode(self, message: str, user_id: str) -> str:
252
+ """Modo estudo com acompanhamento"""
253
+ try:
254
+ # Formato: /estudo área horas
255
+ parts = message.split()
256
+ if len(parts) < 3:
257
+ return "Formato: /estudo área horas"
258
+
259
+ area = parts[1]
260
+ hours = float(parts[2])
261
+
262
+ # Registra estudo
263
+ cursor = self.db.conn.cursor()
264
+ cursor.execute('''
265
+ INSERT INTO study_progress
266
+ (user_id, date, topic, hours_studied, questions_answered, performance_score)
267
+ VALUES (?, ?, ?, ?, ?, ?)
268
+ ''', (user_id, datetime.now().date(), area, hours, 0, 0.0))
269
+ self.db.conn.commit()
270
+
271
+ return f"✅ Registrado: {hours}h de estudo em {area}\n\nContinue assim! Use /progresso para ver seu desenvolvimento."
272
+
273
+ except Exception as e:
274
+ return f"Erro ao registrar estudo: {str(e)}"
275
 
276
+ # Outros métodos necessários...
 
 
 
277
 
278
  def create_interface():
279
+ """Cria interface Gradio"""
280
  bot = RevalidaBot()
281
 
282
  with gr.Blocks(title="Assistente Revalida") as interface:
283
+ gr.Markdown("# 🏥 Assistente Revalida Pro")
284
+ gr.Markdown("### Seu mentor personalizado para o Revalida")
285
+
286
+ with gr.Row():
287
+ with gr.Column():
288
+ user_id = gr.Textbox(
289
+ label="Seu ID (email ou telefone)",
290
+ placeholder="Digite seu ID único..."
291
+ )
292
 
293
  chatbot = gr.Chatbot()
294
  msg = gr.Textbox(
 
297
  )
298
  clear = gr.ClearButton([msg, chatbot])
299
 
300
+ def process_message_with_user(message, history):
301
+ user = user_id.value if user_id.value else "default_user"
302
+ return bot.process_message(message, user, history)
303
+
304
  msg.submit(
305
+ process_message_with_user,
306
  [msg, chatbot],
307
  [chatbot]
308
  )