Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ai-agent/backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ COPY mlp_intent_classifier_improved.npy .
# Instalar dependências
RUN pip install --no-cache-dir -r requirements.txt \
&& python -m spacy download pt_core_news_sm \
&& python -m nltk.downloader stopwords punkt
&& python -m nltk.downloader stopwords punkt punkt_tab

# Expor a porta do FastAPI
EXPOSE 8000
Expand Down
58 changes: 58 additions & 0 deletions ai-agent/backend/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,69 @@ class Query(BaseModel):
def health():
return {"status": "ok", "items": len(KNOWLEDGE_BASE)}


@app.post("/query")
def query(q: Query):
question = q.question
top_k = q.top_k or 3

# 1. Predição com MLP
tokens = preprocess_text(question)
embedding = get_sentence_embedding(tokens, w2v_model)
embedding = scaler.transform([embedding])

probs = mlp.predict_proba(embedding)[0]
max_prob = np.max(probs)
pred = mlp.predict(embedding)[0]
intent_id = le.inverse_transform([pred])[0]

results = []

# 2. Verifica se é MLP com alta confiança
if max_prob > CONFIDENCE_THRESHOLD and intent_id in ID_TO_CONTENT:
item = ID_TO_CONTENT[intent_id]
results.append({
"topic": item['topic'],
"module": item.get('module', 'Geral'),
"content": item['content'],
"confidence": float(max_prob),
"source": "MLP"
})
else:
# 3. Fallback para BM25/TF-IDF se MLP falhar
fallback_results = fallback_search(question, top_k)

# Filtra resultados do fallback que tenham um score mínimo aceitável
# (BM25 scores variam, mas geralmente algo > 0 mostra relevância)
valid_fallback = [res for res in fallback_results if res['score'] > 1.0]

if valid_fallback:
for res in valid_fallback:
results.append({
"topic": res['topic'],
"module": res.get('module', 'Geral'),
"content": res['content'],
"score": res['score'],
"source": "Fallback Search"
})
else:
# 4. FALLBACK FINAL (Nenhum modelo encontrou resposta relevante)
# Retornamos a resposta amigável sugerindo reformulação
return {
"query": question,
"results": [{
"topic": "Não entendi bem",
"module": "Sistema",
"content": "Desculpe, não encontrei essa informação no guia. Tente reformular sua pergunta ou use palavras-chave mais simples (ex: 'banho', 'alimentação', 'diabetes').",
"confidence": 0.0,
"source": "System Fallback"
}]
}

return {"query": question, "results": results}
question = q.question
top_k = q.top_k or 3

# Predição com MLP
tokens = preprocess_text(question)
embedding = get_sentence_embedding(tokens, w2v_model)
Expand Down
62 changes: 44 additions & 18 deletions ai-agent/backend/chatbot_ml.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
# Baixar recursos NLTK
nltk.download('stopwords', quiet=True)
nltk.download('punkt', quiet=True)
nltk.download('punkt_tab', quiet=True)

# Configurações
STOPWORDS = set(stopwords.words('portuguese')) - {'cuidador', 'idoso', 'saúde'} # Manter palavras relevantes
Expand Down Expand Up @@ -72,44 +73,69 @@ def get_sentence_embedding(tokens, w2v_model):
return np.mean(vectors, axis=0) if vectors else np.zeros(WORD2VEC_SIZE)

# Gerar dados sintéticos mais robustos
# No arquivo chatbot_ml.py

def generate_synthetic_data():
data = []
labels = []
templates = [

# Templates para conteúdo técnico (Módulos do manual)
technical_templates = [
"O que é {topic}?", "Explique {topic}", "Como lidar com {topic}?",
"Dicas para {topic}", "Cuidados com {topic}", "O que fazer sobre {topic}?",
"{topic} em idosos", "Como prevenir {topic}?", "Informações sobre {topic}",
"Cuidados relacionados a {topic}", "Como ajudar com {topic}?",
"O que significa {topic} no cuidado de idosos?", "{keywords}",
"Quero saber sobre {topic}"
]

# Templates para conversação (Saudação, Despedida)
conversational_templates = [
"{keywords}", "{topic}", "Diga {topic}", "Fazer {topic}"
]

for item in KNOWLEDGE_BASE:
intent_id = item['id']
topic = item['topic']
keywords = item.get('keywords', [])
content = item['content']
module = item.get('module', 'Geral')

# Gerar variações com templates
for template in templates:
# Seleciona templates baseados no módulo
if module == "Conversação":
current_templates = conversational_templates
# Para conversação, as keywords são o principal gatilho
for kw in keywords:
data.extend([kw, kw.capitalize(), kw.upper()])
labels.extend([intent_id] * 3)
else:
current_templates = technical_templates
# Adiciona variações baseadas no conteúdo para itens técnicos
sentences = nltk.sent_tokenize(content, language='portuguese')
for sent in sentences[:2]:
data.append(sent)
labels.append(intent_id)

# Gerar variações com templates gerais
for template in current_templates:
if '{keywords}' in template:
data.append(' '.join(keywords))
# Se o template for apenas keywords, já tratamos acima para conversação,
# mas para técnico adicionamos a string unida
if module != "Conversação":
data.append(' '.join(keywords))
labels.append(intent_id)
else:
data.append(template.format(topic=topic))
labels.append(intent_id)

# Variações com keywords
for kw in keywords:
data.extend([
f"O que significa {kw}?", f"Como prevenir {kw}?",
f"Cuidados com {kw}", f"{kw} em idosos"
])
labels.extend([intent_id] * 4)
labels.append(intent_id)

# Variações com trechos do conteúdo
sentences = nltk.sent_tokenize(content, language='portuguese')
for sent in sentences[:2]: # Limitar a 2 sentenças
data.append(sent)
labels.append(intent_id)
# Para itens técnicos, reforçar keywords individuais
if module != "Conversação":
for kw in keywords:
data.extend([
f"O que significa {kw}?", f"Como prevenir {kw}?",
f"Cuidados com {kw}", f"{kw} em idosos", kw
])
labels.extend([intent_id] * 5)

return data, labels

Expand Down
47 changes: 47 additions & 0 deletions ai-agent/backend/knowledge_base.json
Original file line number Diff line number Diff line change
Expand Up @@ -485,5 +485,52 @@
"movimento"
],
"module": "Módulo 12"
},
{
"id": 1,
"topic": "saudacao",
"content": "Olá! Sou o Chatbot D-Care. Estou aqui para ajudar com dúvidas sobre o cuidado com idosos baseadas no manual 'Amar é Cuidar'. Como posso ajudar você hoje?",
"keywords": [
"oi",
"olá",
"bom dia",
"boa tarde",
"boa noite",
"e ai",
"tudo bem",
"iniciar",
"começar"
],
"module": "Conversação"
},
{
"id": 2,
"topic": "despedida",
"content": "Foi um prazer ajudar! Se tiver mais dúvidas sobre os cuidados, estarei por aqui. Cuide-se bem!",
"keywords": [
"tchau",
"adeus",
"até logo",
"até mais",
"encerrar",
"fim",
"obrigado",
"obrigada"
],
"module": "Conversação"
},
{
"id": 3,
"topic": "ajuda_fallback",
"content": "Ainda estou aprendendo. Tente perguntar de forma diferente, por exemplo: 'Como dar banho no leito?', 'Sinais de diabetes' ou 'Prevenção de quedas'.",
"keywords": [
"ajuda",
"não entendi",
"o que você faz",
"socorro",
"menu",
"opções"
],
"module": "Conversação"
}
]
Binary file modified ai-agent/backend/mlp_intent_classifier_improved.npy
Binary file not shown.
Binary file modified ai-agent/backend/word2vec_model_improved.bin
Binary file not shown.