File size: 9,333 Bytes
497ffa2 899e3cc 497ffa2 2797f1c 99afab7 2797f1c 497ffa2 899e3cc fc25d8a 899e3cc fc25d8a 899e3cc 3eb6df4 899e3cc 497ffa2 1f078fd 497ffa2 2797f1c 497ffa2 2797f1c 497ffa2 2797f1c 497ffa2 2797f1c 497ffa2 2797f1c 497ffa2 2797f1c 497ffa2 2797f1c 497ffa2 2797f1c 497ffa2 2797f1c 497ffa2 5232e60 497ffa2 2797f1c 497ffa2 2797f1c 497ffa2 2797f1c 497ffa2 2797f1c 497ffa2 2797f1c 497ffa2 2797f1c 497ffa2 2797f1c 497ffa2 2797f1c 899e3cc 2797f1c 497ffa2 899e3cc aa1f8c6 899e3cc 497ffa2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
import os
import time
import pandas as pd
from sqlalchemy import create_engine
from langchain_openai import ChatOpenAI
from langchain_community.agent_toolkits import create_sql_agent
from langchain_community.utilities import SQLDatabase
from huggingface_hub import InferenceClient
import gradio as gr
from dotenv import load_dotenv
import logging
load_dotenv()
UPLOAD_DIR = "uploaded_data"
os.makedirs(UPLOAD_DIR, exist_ok=True)
CSV_FILE_PATH = "anomalia_vendas.csv"
SQL_DB_PATH = "data.db"
HUGGINGFACE_API_KEY = os.getenv("HUGGINGFACE_API_KEY")
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
LLAMA_MODELS = {
"LLaMA 70B": "meta-llama/Llama-3.3-70B-Instruct",
"LlaMA 8B": "meta-llama/Llama-3.1-8B-Instruct",
"Qwen 32B": "Qwen/QwQ-32B"
}
MAX_TOKENS_MAP = {
"meta-llama/Llama-3.3-70B-Instruct": 900,
"meta-llama/Llama-3.1-8B-Instruct": 600,
"Qwen/QwQ-32B": 8192
}
hf_client = InferenceClient(
provider="sambanova",
api_key=HUGGINGFACE_API_KEY,
)
os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY
query_cache = {}
history_log = []
recent_history = []
show_history_flag = False
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def create_or_load_sql_database(csv_path, sql_db_path):
if os.path.exists(sql_db_path):
print("Banco de dados SQL já existe. Carregando...")
return create_engine(f"sqlite:///{sql_db_path}")
else:
print("Banco de dados SQL não encontrado. Criando...")
engine = create_engine(f"sqlite:///{sql_db_path}")
df = pd.read_csv(csv_path, sep=";", on_bad_lines="skip")
print(f"CSV carregado: {len(df)} linhas, {len(df.columns)} colunas")
df.to_sql("anomalia_vendas", engine, index=False, if_exists="replace")
print("Banco de dados SQL criado com sucesso!")
return engine
def load_uploaded_csv_and_create_db(uploaded_file):
if uploaded_file is None:
return None
print(f"[UPLOAD] CSV recebido: {uploaded_file}")
engine = create_engine(f"sqlite:///{SQL_DB_PATH}")
df = pd.read_csv(uploaded_file, sep=";", on_bad_lines="skip")
df.to_sql("anomalia_vendas", engine, index=False, if_exists="replace")
print("Banco recriado com base no novo CSV.")
print(f"CSV carregado: {len(df)} linhas, {len(df.columns)} colunas")
print(f"[DEBUG] Novo engine criado: {engine}")
return engine
engine = create_or_load_sql_database(CSV_FILE_PATH, SQL_DB_PATH)
db = SQLDatabase(engine=engine)
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
sql_agent = create_sql_agent(llm, db=db, agent_type="openai-tools", verbose=True, max_iterations=40, return_intermediate_steps=True)
def generate_initial_context(db_sample):
return (
f"Você é um assistente que gera queries SQL objetivas e eficientes. Sempre inclua LIMIT 15 nas queries. Aqui está o banco de dados:\n\n"
f"Exemplos do banco de dados:\n{db_sample.head().to_string(index=False)}\n\n"
"\n***IMPORTANTE***: Detecte automaticamente o idioma da pergunta do usuário e responda sempre no mesmo idioma.\n"
"Essa base de dados representa o sellout de 2025, janeiro, fevereiro e março até dia 11, de uma farmácia.\n"
"Cada linha representa a venda de um SKU em uma determinada data.\n"
"\nRetorne apenas a pergunta e a query SQL mais eficiente para entregar ao agent SQL do LangChain para gerar uma resposta. O formato deve ser:\n"
"\nPergunta: <pergunta do usuário>\n"
"\nOpção de Query SQL:\n<query SQL>"
"\nIdioma: <idioma>"
)
def is_greeting(user_query):
greetings = ["olá", "oi", "bom dia", "boa tarde", "boa noite", "oi, tudo bem?"]
return user_query.lower().strip() in greetings
def query_with_llama(user_query, db_sample, selected_model_name):
model_id = LLAMA_MODELS[selected_model_name]
max_tokens = MAX_TOKENS_MAP.get(model_id, 512)
initial_context = generate_initial_context(db_sample)
formatted_history = "\n".join(
[f"{msg['role'].capitalize()}: {msg['content']}" for msg in recent_history[-2:]]
)
full_prompt = f"{initial_context}\n\nHistórico recente:\n{formatted_history}\n\nPergunta do usuário:\n{user_query}"
logging.info(f"[DEBUG] Contexto enviado ao ({selected_model_name}):\n{full_prompt}\n")
start_time = time.time()
try:
response = hf_client.chat.completions.create(
model=model_id,
messages=[{"role": "system", "content": full_prompt}],
max_tokens=max_tokens,
stream=False
)
llama_response = response["choices"][0]["message"]["content"]
end_time = time.time()
logging.info(f"[DEBUG] Resposta do {selected_model_name} para o Agent SQL:\n{llama_response.strip()}\n[Tempo de execução: {end_time - start_time:.2f}s]\n")
return llama_response.strip(), model_id
except Exception as e:
logging.error(f"[ERRO] Falha ao interagir com o modelo {selected_model_name}: {e}")
return None, model_id
def query_sql_agent(user_query, selected_model_name):
try:
if user_query in query_cache:
print(f"[CACHE] Retornando resposta do cache para a consulta: {user_query}")
return query_cache[user_query]
if is_greeting(user_query):
greeting_response = "Olá! Estou aqui para ajudar com suas consultas. Pergunte algo relacionado aos dados carregados no agente!"
query_cache[user_query] = greeting_response
return greeting_response
column_data = pd.read_sql_query("SELECT * FROM anomalia_vendas LIMIT 10", engine)
llama_instruction = query_with_llama(user_query, column_data, selected_model_name)
if not llama_instruction:
return "Erro: O modelo Llama não conseguiu gerar uma instrução válida."
print("------- Agent SQL: Executando query -------")
response = sql_agent.invoke({"input": llama_instruction})
sql_response = response.get("output", "Erro ao obter a resposta do agente.")
query_cache[user_query] = sql_response
return sql_response
except Exception as e:
return f"Erro ao consultar o agente SQL: {e}"
def chatbot_response(user_input, selected_model_name):
start_time = time.time()
response = query_sql_agent(user_input, selected_model_name)
end_time = time.time()
model_id = LLAMA_MODELS[selected_model_name]
history_log.append({
"Modelo LLM": model_id,
"Pergunta": user_input,
"Resposta": response,
"Tempo de Resposta (s)": round(end_time - start_time, 2)
})
recent_history.append({"role": "user", "content": user_input})
recent_history.append({"role": "assistant", "content": response})
if len(recent_history) > 4:
recent_history.pop(0)
recent_history.pop(0)
return response
def toggle_history():
global show_history_flag
show_history_flag = not show_history_flag
return history_log if show_history_flag else {}
with gr.Blocks(theme=gr.themes.Soft()) as demo:
gr.Markdown("# 🧠 Anomalia Agent")
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("## ⚙️ Configurações")
model_selector = gr.Dropdown(
choices=list(LLAMA_MODELS.keys()),
label="Escolha o Modelo LLM para gerar a query SQL",
value="LLaMA 70B"
)
csv_file = gr.File(label="📂 Enviar novo CSV", file_types=[".csv"])
with gr.Column(scale=4):
chatbot = gr.Chatbot(height=600)
msg = gr.Textbox(placeholder="Digite sua pergunta aqui...", label=" ", lines=1)
btn = gr.Button("Enviar", variant="primary")
history_btn = gr.Button("Histórico", variant="secondary")
def respond(message, chat_history, selected_model_name):
response = chatbot_response(message, selected_model_name)
chat_history.append((message, response))
return "", chat_history
msg.submit(respond, [msg, chatbot, model_selector], [msg, chatbot])
btn.click(respond, [msg, chatbot, model_selector], [msg, chatbot])
history_output = gr.JSON()
history_btn.click(toggle_history, inputs=[], outputs=history_output)
def handle_csv_upload(file):
global engine, db, sql_agent
try:
engine = load_uploaded_csv_and_create_db(file)
if engine is not None:
db = SQLDatabase(engine=engine)
sql_agent = create_sql_agent(
ChatOpenAI(model="gpt-4o-mini", temperature=0),
db=db,
agent_type="openai-tools",
verbose=True,
max_iterations=40,
return_intermediate_steps=True
)
print("[UPLOAD] Banco e agente SQL atualizados com sucesso.")
except Exception as e:
print(f"[ERRO] Falha ao processar novo CSV: {e}")
csv_file.change(handle_csv_upload, inputs=csv_file, outputs=csv_file)
if __name__ == "__main__":
demo.launch(share=False) |