rwayz commited on
Commit
1ffd040
·
verified ·
1 Parent(s): fbecdf8

Delete agentchain.md

Browse files
Files changed (1) hide show
  1. agentchain.md +0 -361
agentchain.md DELETED
@@ -1,361 +0,0 @@
1
- import os
2
- import time
3
- import shutil
4
- import pandas as pd
5
- from sqlalchemy import create_engine
6
- from langchain_openai import ChatOpenAI
7
- from langchain_community.agent_toolkits import create_sql_agent
8
- from langchain_community.utilities import SQLDatabase
9
- from huggingface_hub import InferenceClient
10
- import gradio as gr
11
- from dotenv import load_dotenv
12
- import logging
13
- from sqlalchemy.types import DateTime, Integer, Float
14
-
15
- load_dotenv()
16
-
17
- UPLOAD_DIR = "uploaded_data"
18
- os.makedirs(UPLOAD_DIR, exist_ok=True)
19
-
20
- DEFAULT_CSV_PATH = "tabela.csv"
21
- UPLOADED_CSV_PATH = os.path.join(UPLOAD_DIR, "tabela.csv")
22
- SQL_DB_PATH = "data.db"
23
-
24
- HUGGINGFACE_API_KEY = os.getenv("HUGGINGFACE_API_KEY")
25
- OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
26
-
27
- LLAMA_MODELS = {
28
- "LLaMA 70B": "meta-llama/Llama-3.3-70B-Instruct",
29
- "LlaMA 8B": "meta-llama/Llama-3.1-8B-Instruct",
30
- "Qwen 32B": "Qwen/QwQ-32B"
31
- }
32
-
33
- MAX_TOKENS_MAP = {
34
- "meta-llama/Llama-3.3-70B-Instruct": 900,
35
- "meta-llama/Llama-3.1-8B-Instruct": 700,
36
- "Qwen/QwQ-32B": 8192
37
- }
38
-
39
- hf_client = InferenceClient(
40
- provider="together", api_key=HUGGINGFACE_API_KEY
41
- )
42
-
43
- os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY
44
-
45
- query_cache = {}
46
- history_log = []
47
- recent_history = []
48
- show_history_flag = False
49
- engine = None
50
-
51
- logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
52
-
53
- def get_active_csv_path():
54
- """Retorna o CSV ativo: o carregado ou o padrão.."""
55
- if os.path.exists(UPLOADED_CSV_PATH):
56
- logging.info(f"[CSV] Usando arquivo CSV carregado: {UPLOADED_CSV_PATH}")
57
- return UPLOADED_CSV_PATH
58
- else:
59
- logging.info(f"[CSV] Usando arquivo CSV padrão: {DEFAULT_CSV_PATH}")
60
- return DEFAULT_CSV_PATH
61
-
62
- def create_engine_and_load_db(csv_path, sql_db_path):
63
- if os.path.exists(sql_db_path):
64
- print("Banco de dados SQL já existe. Carregando...")
65
- return create_engine(f"sqlite:///{sql_db_path}")
66
- else:
67
- print("Banco de dados SQL não encontrado. Criando...")
68
- engine = create_engine(f"sqlite:///{sql_db_path}")
69
-
70
- df = pd.read_csv(
71
- csv_path,
72
- sep=";",
73
- encoding='utf-8',
74
- parse_dates=["DATA_INICIAL", "DATA_FINAL"],
75
- dayfirst=True,
76
- on_bad_lines="skip"
77
- )
78
-
79
- colunas_para_float = [
80
- "PRECO_VISTA", "PRECO_CHEIO"
81
- ]
82
-
83
- colunas_para_int = [
84
- "QUANTIDADE", "TOTAL_PAGINAS_CAPA", "VALOR_MEDIDA", "DIAS_VALIDADE"
85
- ]
86
-
87
- for col in colunas_para_float:
88
- if col in df.columns:
89
- df[col] = pd.to_numeric(df[col].replace("-", None), errors="coerce")
90
-
91
- for col in colunas_para_int:
92
- if col in df.columns:
93
- df[col] = pd.to_numeric(df[col].replace("-", None), errors="coerce")
94
- df[col] = df[col].where(df[col].dropna() == df[col].dropna().astype(int))
95
- df[col] = df[col].astype("Int64")
96
-
97
- sql_dtype = {
98
- "DATA_INICIAL": DateTime(),
99
- "DATA_FINAL": DateTime(),
100
- "QUANTIDADE": Integer(),
101
- "PRECO_VISTA": Float(),
102
- "PRECO_CHEIO": Float(),
103
- "TOTAL_PAGINAS_CAPA": Integer(),
104
- "VALOR_MEDIDA": Integer(),
105
- "DIAS_VALIDADE": Integer()
106
-
107
- }
108
-
109
- print("[DEBUG] Tipos das colunas:")
110
- print(df.dtypes)
111
-
112
- df.to_sql("tabela", engine, index=False, if_exists="replace", dtype=sql_dtype)
113
- print("Banco de dados SQL criado com sucesso!")
114
- return engine
115
-
116
- def handle_csv_upload(file):
117
- global engine, db, sql_agent
118
-
119
- try:
120
- file_path = file.name
121
- shutil.copy(file_path, UPLOADED_CSV_PATH)
122
- logging.info(f"[UPLOAD] CSV salvo como: {UPLOADED_CSV_PATH}")
123
-
124
- engine = create_engine_and_load_db(UPLOADED_CSV_PATH, SQL_DB_PATH)
125
- db = SQLDatabase(engine=engine)
126
- logging.info("[UPLOAD] Novo banco carregado e DB atualizado.")
127
-
128
- sql_agent = create_sql_agent(
129
- ChatOpenAI(model="gpt-4o-mini", temperature=0),
130
- db=db,
131
- agent_type="openai-tools",
132
- verbose=True,
133
- max_iterations=40,
134
- return_intermediate_steps=True
135
- )
136
-
137
- logging.info("[UPLOAD] Novo banco carregado e agente recriado. Cache limpo.")
138
- query_cache.clear()
139
- history_log.clear()
140
- recent_history.clear()
141
-
142
- return "✅ CSV carregado com sucesso!"
143
-
144
- except Exception as e:
145
- logging.error(f"[ERRO] Falha ao processar novo CSV: {e}")
146
- return f"❌ Erro ao processar CSV: {e}"
147
-
148
- def reset_app():
149
- global engine, db, sql_agent, query_cache, history_log, recent_history
150
-
151
- try:
152
- if os.path.exists(UPLOADED_CSV_PATH):
153
- os.remove(UPLOADED_CSV_PATH)
154
- logging.info("[RESET] CSV personalizado removido.")
155
-
156
- engine = create_engine_and_load_db(DEFAULT_CSV_PATH, SQL_DB_PATH)
157
- db = SQLDatabase(engine=engine)
158
- 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)
159
- query_cache.clear()
160
- history_log.clear()
161
- recent_history.clear()
162
-
163
- return "🔄 Sistema resetado para o estado inicial."
164
-
165
- except Exception as e:
166
- return f"❌ Erro ao resetar: {e}"
167
-
168
- engine = create_engine_and_load_db(get_active_csv_path(), SQL_DB_PATH)
169
- db = SQLDatabase(engine=engine)
170
- llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
171
- sql_agent = create_sql_agent(llm, db=db, agent_type="openai-tools", verbose=True, max_iterations=40, return_intermediate_steps=True)
172
-
173
- def generate_initial_context(db_sample):
174
- return (
175
- f"Você é um assistente que gera queries SQL objetivas e eficientes. Sempre inclua LIMIT 20 nas queries. Aqui está o banco de dados:\n\n"
176
- f"Exemplos do banco de dados:\n{db_sample.head().to_string(index=False)}\n\n"
177
- "\n***IMPORTANTE***: Detecte automaticamente o idioma da pergunta do usuário e responda sempre no mesmo idioma."
178
- "\nEsta base contém os SKUs (produtos) que foram promocionados por meio de TABLOIDE OU PROMOCAO OU ANUNCIO.\n"
179
- "Cada linha representa um SKU OU PRODUTO único PRESENTE NO TABLOIDE OU PROMOCAO OU ANUNCIO, incluindo sua descrição completa, os veículos OU MIDIAS de promoção utilizados e o respectivo período em que a promoção ocorreu.\n"
180
-
181
- "\nInformações imporatantes:\n"
182
- "- Use `LIKE '%<palavras-chave>%'` para buscas em colunas de texto.\n"
183
- "- Quando o usuário mencionar uma categoria, procure nas colunas: `CATEGORIA_PRODUTO_SKU`.\n"
184
- "- Se o usuário se referir a Nestle, o jeito correto de se escrever é Nestle sem acento e não Nestlé.\n"
185
- "- Você está usando um banco de dados SQLite.\n"
186
-
187
- "\nRetorne apenas a pergunta e a query SQL mais eficiente para entregar ao agent SQL do LangChain para gerar uma resposta para a pergunta. O formato deve ser:\n"
188
- "\nPergunta: <pergunta do usuário>\n"
189
- "\nOpção de Query SQL:\n<query SQL>"
190
- "\nIdioma: <idioma>"
191
- )
192
-
193
- def is_greeting(user_query):
194
- greetings = ["olá", "oi", "bom dia", "boa tarde", "boa noite", "oi, tudo bem?"]
195
- return user_query.lower().strip() in greetings
196
-
197
- def query_with_llama(user_query, db_sample, selected_model_name):
198
- model_id = LLAMA_MODELS[selected_model_name]
199
- max_tokens = MAX_TOKENS_MAP.get(model_id, 512)
200
-
201
- initial_context = generate_initial_context(db_sample)
202
- formatted_history = "\n".join(
203
- [f"{msg['role'].capitalize()}: {msg['content']}" for msg in recent_history[-2:]]
204
- )
205
-
206
- full_prompt = f"{initial_context}\n\nHistórico recente:\n{formatted_history}\n\nPergunta do usuário:\n{user_query}"
207
-
208
- logging.info(f"[DEBUG] Contexto enviado ao ({selected_model_name}):\n{full_prompt}\n")
209
-
210
- start_time = time.time()
211
-
212
- try:
213
- response = hf_client.chat.completions.create(
214
- model=model_id,
215
- messages=[{"role": "system", "content": full_prompt}],
216
- max_tokens=max_tokens,
217
- stream=False
218
- )
219
-
220
- llama_response = response["choices"][0]["message"]["content"]
221
- end_time = time.time()
222
- 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")
223
- return llama_response.strip(), model_id
224
-
225
- except Exception as e:
226
- logging.error(f"[ERRO] Falha ao interagir com o modelo {selected_model_name}: {e}")
227
- return None, model_id
228
-
229
- def query_sql_agent(user_query, selected_model_name):
230
- try:
231
- if user_query in query_cache:
232
- print(f"[CACHE] Retornando resposta do cache para a consulta: {user_query}")
233
- return query_cache[user_query]
234
-
235
- if is_greeting(user_query):
236
- greeting_response = "Olá! Estou aqui para ajudar com suas consultas. Pergunte algo relacionado aos dados carregados no agente!"
237
- query_cache[user_query] = greeting_response
238
- return greeting_response
239
-
240
- column_data = pd.read_sql_query("SELECT * FROM tabela LIMIT 10", engine)
241
- llama_instruction = query_with_llama(user_query, column_data, selected_model_name)
242
-
243
- if not llama_instruction:
244
- return "Erro: O modelo Llama não conseguiu gerar uma instrução válida."
245
-
246
- print("------- Agent SQL: Executando query -------")
247
- response = sql_agent.invoke({"input": llama_instruction})
248
- sql_response = response.get("output", "Erro ao obter a resposta do agente.")
249
-
250
- query_cache[user_query] = sql_response
251
- return sql_response
252
-
253
- except Exception as e:
254
- return f"Erro ao consultar o agente SQL: {e}"
255
-
256
- advanced_mode_enabled = False # Novo estado global
257
-
258
- def toggle_advanced_mode(state):
259
- global advanced_mode_enabled
260
- advanced_mode_enabled = state
261
- logging.info(f"[MODO AVANÇADO] {'Ativado' if state else 'Desativado'}")
262
- return "Modo avançado ativado." if state else "Modo avançado desativado."
263
-
264
- def refine_response_with_llm(user_question, sql_response, chart_md=""):
265
- prompt = (
266
- f"Pergunta do usuário:\n{user_question}\n\n"
267
- f"Resposta gerada pelo agente SQL:\n{sql_response}\n\n"
268
- "Sua tarefa é refinar, complementar e melhorar a resposta.\n"
269
- "Adicione interpretações estatísticas ou insights relevantes."
270
- )
271
-
272
- logging.info(f"[DEBUG] Prompt enviado ao modelo de refinamento:\n{prompt}\n")
273
-
274
- try:
275
- response = hf_client.chat.completions.create(
276
- model=LLAMA_MODELS["LLaMA 70B"],
277
- messages=[{"role": "system", "content": prompt}],
278
- max_tokens=1200,
279
- stream=False
280
- )
281
- improved_response = response["choices"][0]["message"]["content"]
282
- logging.info(f"[DEBUG] Resposta do modelo de refinamento:\n{improved_response}\n")
283
- return improved_response + ("\n\n" + chart_md if chart_md else "")
284
-
285
- except Exception as e:
286
- logging.error(f"[ERRO] Falha ao refinar resposta com LLM: {e}")
287
- return sql_response + ("\n\n" + chart_md if chart_md else "")
288
-
289
- def chatbot_response(user_input, selected_model_name):
290
- start_time = time.time()
291
- response = query_sql_agent(user_input, selected_model_name)
292
- end_time = time.time()
293
-
294
- model_id = LLAMA_MODELS[selected_model_name]
295
-
296
- if advanced_mode_enabled:
297
- response = refine_response_with_llm(user_input, response)
298
-
299
- history_log.append({
300
- "Modelo LLM": model_id,
301
- "Pergunta": user_input,
302
- "Resposta": response,
303
- "Tempo de Resposta (s)": round(end_time - start_time, 2)
304
- })
305
-
306
- recent_history.append({"role": "user", "content": user_input})
307
- recent_history.append({"role": "assistant", "content": response})
308
-
309
- if len(recent_history) > 4:
310
- recent_history.pop(0)
311
- recent_history.pop(0)
312
-
313
- return response
314
-
315
- def toggle_history():
316
- global show_history_flag
317
- show_history_flag = not show_history_flag
318
- return history_log if show_history_flag else {}
319
-
320
-
321
- with gr.Blocks(theme=gr.themes.Soft()) as demo:
322
- with gr.Row():
323
- with gr.Column(scale=1):
324
- gr.Markdown("## Configurações")
325
- model_selector = gr.Dropdown(list(LLAMA_MODELS.keys()), value="LLaMA 70B", label="")
326
- csv_file = gr.File(file_types=[".csv"], label="")
327
- upload_feedback = gr.Markdown()
328
- advanced_checkbox = gr.Checkbox(label="Refinar Resposta")
329
- reset_btn = gr.Button("Resetar")
330
-
331
- with gr.Column(scale=4):
332
- gr.Markdown("## Reasoning Agent")
333
- chatbot = gr.Chatbot(height=500)
334
- msg = gr.Textbox(placeholder="Digite sua pergunta aqui...", lines=1, label="")
335
- btn = gr.Button("Enviar", variant="primary")
336
- history_btn = gr.Button("Histórico", variant="secondary")
337
- history_output = gr.JSON()
338
- download_file = gr.File(visible=False)
339
-
340
- def respond(message, chat_history, selected_model):
341
- response = chatbot_response(message, selected_model)
342
- chat_history.append((message, response))
343
- return "", chat_history
344
-
345
- def handle_csv_and_clear_chat(file):
346
- feedback = handle_csv_upload(file)
347
- return feedback, []
348
-
349
- def reset_all():
350
- feedback = reset_app()
351
- return feedback, [], None
352
-
353
- msg.submit(respond, [msg, chatbot, model_selector], [msg, chatbot])
354
- btn.click(respond, [msg, chatbot, model_selector], [msg, chatbot])
355
- history_btn.click(toggle_history, outputs=history_output)
356
- csv_file.change(handle_csv_and_clear_chat, inputs=csv_file, outputs=[upload_feedback, chatbot])
357
- reset_btn.click(reset_all, outputs=[upload_feedback, chatbot, csv_file])
358
- advanced_checkbox.change(toggle_advanced_mode, inputs=advanced_checkbox, outputs=[])
359
-
360
- if __name__ == "__main__":
361
- demo.launch(share=False)