ChatBot - Intents Dinamicas a funcionar/traduções/estrutura

This commit is contained in:
Ricardo Cunha 2025-06-17 20:06:49 +01:00
parent d823baed31
commit d6180e4973
3 changed files with 60 additions and 154 deletions

View File

@ -173,6 +173,20 @@ def chat_with_gpt(prompt, attempts=3):
except Exception as e:
return f"Erro genérico com a API OpenAI: {type(e).__name__} - {e}"
def extract_intent_and_params(user_input):
prompt = f"""
Analisa a seguinte pergunta de utilizador e devolve um JSON com:
- "intent": a intenção principal (ex: comparar_total, comparar_kwh, listar_faturas, total_kwh_tipo_edificio, top_consumidores, etc)
- "params": dicionário com parâmetros relevantes (ex: mes, ano, tipo_edificio, cunit_id, etc)
Pergunta: "{user_input}"
Exemplo de resposta: {{"intent": "comparar_total", "params": {{"mes": 1, "ano": 2025}}}}
"""
response = chat_with_gpt(prompt)
try:
return json.loads(response)
except Exception:
return {"intent": "unknown", "params": {}}
def get_price_comparison():
conn = connect_db()
if not conn:
@ -555,7 +569,6 @@ if __name__ == "__main__":
"janeiro": 1,
"fevereiro": 2,
"março": 3,
"março": 3,
"abril": 4,
"maio": 5,
"junho": 6,
@ -572,173 +585,60 @@ if __name__ == "__main__":
if user_input.lower() in ["quit", "exit", "bye"]:
break
if any(word in user_input.lower() for word in ["tabela", "coluna", "campos", "estrutura", "schema"]):
schema_info = get_schema_with_examples()
if isinstance(schema_info, str):
print(f"Chatbot: {schema_info}")
else:
if re.search(r"tabelas|todas as tabelas", user_input.lower()):
nomes = [t['table'] for t in schema_info]
print(f"Chatbot: As tabelas disponíveis são: {', '.join(nomes)}")
else:
for t in schema_info:
if t['table'].lower() in user_input.lower():
colunas = ", ".join([
next((k for k, v in column_mapping.items() if v == c['name']), c['name'])
for c in t['columns']
])
print(f"Chatbot: A tabela '{t['table']}' tem as colunas: {colunas}.")
if t['example']:
exemplo_traduzido = {
next((k for k, v in column_mapping.items() if v == k or v == k or v == col), col): val
for col, val in t['example'].items()
}
exemplo_traduzido = {
next((k for k, v in column_mapping.items() if v == col), col): val
for col, val in t['example'].items()
}
print(f"Exemplo de linha: {exemplo_traduzido}")
break
else:
print("Chatbot: Não encontrei essa tabela. Pergunte por outra ou peça 'tabelas' para ver todas.")
continue
cunit_id, date_billling_begin, date_billing_end, total_requested = parse_user_input(user_input)
if total_requested and cunit_id:
data = get_total_by_cunit(cunit_id)
print(f"Chatbot: Aqui estão os totais encontrados:\n{data}")
continue
if cunit_id or date_billling_begin or date_billing_end:
data = get_filtered_data(cunit_id, date_billling_begin, date_billing_end)
print(f"Chatbot: Aqui estão os dados encontrados:\n{data}")
continue
if "preços faturados" in user_input.lower():
data = get_price_comparison()
print(f"Chatbot: Aqui está a comparação dos preços:\n{data}")
continue
if re.search(r"mês atual.*igual período.*ano anterior", user_input.lower()):
data = compare_current_vs_previous_year()
print(f"Chatbot: {data}")
continue
if re.search(r"mês.*igual período.*ano anterior", user_input.lower()):
match = re.search(
r"(?:mês\s+de\s+([a-zç]+|\d{1,2}))(?:\s+do\s+ano\s+(\d{4}))?",
user_input.lower()
)
if match:
mes_input = match.group(1).strip().lower()
ano = int(match.group(2)) if match.group(2) else datetime.now().year
if mes_input.isdigit():
mes = int(mes_input)
else:
mes = month_map.get(mes_input)
if not mes:
print("Chatbot: Mês não reconhecido. Tenta novamente.")
continue
else:
mes = datetime.now().month
ano = datetime.now().year
# NOVO: Extração dinâmica de intenção e parâmetros
intent_data = extract_intent_and_params(user_input)
intent = intent_data.get("intent")
params = intent_data.get("params", {})
if intent == "comparar_total":
mes = params.get("mes")
ano = params.get("ano")
data = compare_current_vs_previous_year(month=mes, year=ano)
print(f"Chatbot: {data}")
continue
if "homólogo" in user_input.lower():
match = re.search(r"homólogo.*?(\d{4})", user_input.lower())
ano = int(match.group(1)) if match else None
data = get_top_consumers(current=False, year=ano)
if ano:
print(f"Chatbot: Aqui estão as instalações com maior consumo no período homólogo de {ano}:\n{data}")
else:
print(f"Chatbot: Aqui estão as instalações com maior consumo no período homólogo atual:\n{data}")
continue
if re.search(r"total de kwh.*mês.*ano anterior", user_input.lower()):
match = re.search(
r"(?:mês\s+de\s+([a-zç]+|\d{1,2}))(?:\s+do\s+ano\s+(\d{4}))?",
user_input.lower()
)
if match:
mes_input = match.group(1).strip().lower()
ano = int(match.group(2)) if match.group(2) else datetime.now().year
if mes_input.isdigit():
mes = int(mes_input)
else:
mes = month_map.get(mes_input)
if not mes:
print("Chatbot: Mês não reconhecido. Tenta novamente.")
continue
else:
mes = datetime.now().month
ano = datetime.now().year
if intent == "comparar_kwh":
mes = params.get("mes")
ano = params.get("ano")
data = compare_kwh_current_vs_previous_year(month=mes, year=ano)
print(f"Chatbot: {data}")
continue
if re.search(r"quantas faturas.*mês", user_input.lower()):
match = re.search(
r"(?:mês\s+de\s+([a-zç]+|\d{1,2}))(?:\s+do\s+ano\s+(\d{4}))?",
user_input.lower()
)
if match:
mes_input = match.group(1).strip().lower()
ano = int(match.group(2)) if match.group(2) else datetime.now().year
if mes_input.isdigit():
mes = int(mes_input)
else:
mes = month_map.get(mes_input)
if not mes:
print("Chatbot: Mês não reconhecido. Tenta novamente.")
continue
else:
mes = datetime.now().month
ano = datetime.now().year
data = get_invoices_by_month_year(month=mes, year=ano)
print(f"Chatbot: {data}")
continue
if re.search(r"faturas.*instalações.*inativas", user_input.lower()):
if intent == "listar_faturas_inativas":
data = get_invoices_from_inactive_units()
print(f"Chatbot: {data}")
continue
if re.search(r"total de kwh.*tipo de edifícios", user_input.lower()):
match = re.search(r"tipo de edifícios\s+([a-zçãõáéíóúâêîôûäëïöü\s]+)", user_input.lower())
building_type = match.group(1).strip() if match else None
if building_type:
data = get_total_kwh_by_building_type(building_type=building_type)
print(f"Chatbot: Aqui está o total de kWh para o tipo de edifício '{building_type}':\n{data}")
else:
data = get_total_kwh_by_building_type()
print(f"Chatbot: Aqui está o total de kWh por tipo de edifício:\n{data}")
if intent == "listar_faturas_mes":
mes = params.get("mes")
ano = params.get("ano")
data = get_invoices_by_month_year(month=mes, year=ano)
print(f"Chatbot: {data}")
continue
if user_input.lower() in ["cunitbills", "cunits", "cunittypes"]:
data = get_data(table_name=user_input)
print(f"\nDados da tabela {user_input}:\n{data}")
if intent == "total_kwh_tipo_edificio":
tipo = params.get("tipo_edificio")
data = get_total_kwh_by_building_type(building_type=tipo)
print(f"Chatbot: {data}")
continue
if "dados" in user_input.lower():
data = get_data()
print(f"\nDados do SQL Server:\n{data}")
if intent == "top_consumidores":
ano = params.get("ano")
data = get_top_consumers(year=ano)
print(f"Chatbot: {data}")
continue
# ...adiciona mais intents conforme necessário...
# fallback: resposta do LLM se não reconhecer a intenção
response = chat_with_gpt(user_input)
print("Chatbot: ", response)
print("Chatbot:", response)
# --- CÓDIGO ANTIGO (comentado, não removido) ---
# if "No mês de Janeiro estamos a pagar mais ou menos que em igual período do ano anterior?" in user_input:
# print("Chatbot: Estamos a pagar menos em 01/2025 (219711.01) do que no mesmo período do ano passado (250508.93).")
# continue
# if "total do CUnitId" in user_input:
# # lógica antiga...
# continue
# ...restante código hardcoded...

View File

@ -211,6 +211,15 @@ def chat():
user_input = data.get("message", "")
lower_input = user_input.lower()
if "cunits" in lower_input or "dados cunit" in lower_input or "dados unidades" in lower_input:
return make_reply(translate_any(get_data(table_name="CUnits"), column_mapping_inv))
if "cunittypes" in lower_input or "cunitstypes" in lower_input or "dados cunittypes" in lower_input or "dados tipos" in lower_input:
return make_reply(translate_any(get_data(table_name="CUnitTypes"), column_mapping_inv))
if "cunitbills" in lower_input or "dados" in lower_input:
return make_reply(translate_any(get_data(table_name="CUnitBills"), column_mapping_inv))
if "tabela" in lower_input or "coluna" in lower_input:
return make_reply(answer_schema_question(lower_input))
@ -286,9 +295,6 @@ def chat():
pref = f"para o tipo de edifício '{building}'" if building else "por tipo de edifício"
return make_reply(f"Aqui está o total de kWh {pref}:\n" + dicts_to_markdown(translate_any(dados, column_mapping_inv)))
if "dados" in lower_input:
return make_reply(translate_any(get_data(), column_mapping_inv))
return make_reply(chat_with_gpt(user_input))
if __name__ == "__main__":