Spaces:
Runtime error
Runtime error
Upload 3 files
Browse files- app.py +200 -0
- ecommerce.db +0 -0
- requirements.txt +27 -0
app.py
ADDED
@@ -0,0 +1,200 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from sqlalchemy import create_engine, MetaData
|
2 |
+
|
3 |
+
url = 'ecommerce.db'
|
4 |
+
engine = create_engine(f'sqlite:///{url}')
|
5 |
+
|
6 |
+
metadata_obj = MetaData()
|
7 |
+
metadata_obj.reflect(engine)
|
8 |
+
|
9 |
+
import os
|
10 |
+
|
11 |
+
key = os.getenv("GROQ_API")
|
12 |
+
|
13 |
+
modelo="llama-3.1-70b-versatile"
|
14 |
+
modelo_hf_emb="BAAI/bge-m3"
|
15 |
+
|
16 |
+
from llama_index.core import Settings
|
17 |
+
from llama_index.llms.groq import Groq
|
18 |
+
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
|
19 |
+
|
20 |
+
Settings.llm = Groq(model=modelo, api_key = key)
|
21 |
+
Settings.embed_model = HuggingFaceEmbedding(model_name = modelo_hf_emb)
|
22 |
+
|
23 |
+
from llama_index.core import SQLDatabase
|
24 |
+
from llama_index.core.objects import SQLTableNodeMapping
|
25 |
+
|
26 |
+
sql_database = SQLDatabase(engine)
|
27 |
+
table_node_map = SQLTableNodeMapping(sql_database)
|
28 |
+
|
29 |
+
llm = Groq(model=modelo, api_key = key)
|
30 |
+
|
31 |
+
def gerar_descricao_tabela(nome_tabela, df_amostra):
|
32 |
+
prompt = f"""
|
33 |
+
Analise a amostra da tabela '{nome_tabela}' abaixo e forneça uma curta e breve descrição do conteúdo dessa tabela.
|
34 |
+
Informe até o máximo de 5 valores únicos de cada coluna.
|
35 |
+
|
36 |
+
|
37 |
+
Amostra da Tabela:
|
38 |
+
{df_amostra}
|
39 |
+
|
40 |
+
Descrição:
|
41 |
+
"""
|
42 |
+
|
43 |
+
resposta = llm.complete(prompt = prompt)
|
44 |
+
|
45 |
+
return resposta.text
|
46 |
+
|
47 |
+
import pandas as pd
|
48 |
+
|
49 |
+
nomes_tabelas = metadata_obj.tables.keys()
|
50 |
+
dicionario_tabelas = {}
|
51 |
+
|
52 |
+
for nome_tabela in nomes_tabelas:
|
53 |
+
df = pd.read_sql_table(nome_tabela,engine)
|
54 |
+
df_amostra = df.head(5).to_string()
|
55 |
+
|
56 |
+
descricao = gerar_descricao_tabela(nome_tabela, df_amostra)
|
57 |
+
dicionario_tabelas[nome_tabela] = descricao
|
58 |
+
print(f'Tabela: {nome_tabela}\n Descrição: {descricao}')
|
59 |
+
print('-'*15)
|
60 |
+
|
61 |
+
from llama_index.core.objects import SQLTableSchema
|
62 |
+
from llama_index.core import VectorStoreIndex
|
63 |
+
from llama_index.core.objects import ObjectIndex
|
64 |
+
|
65 |
+
table_schema_objs = [
|
66 |
+
SQLTableSchema(table_name= nome_tabela,context_str= dicionario_tabelas[nome_tabela])
|
67 |
+
for nome_tabela in nomes_tabelas
|
68 |
+
]
|
69 |
+
|
70 |
+
obj_index = ObjectIndex.from_objects(table_schema_objs,table_node_map, VectorStoreIndex)
|
71 |
+
obj_retriever = obj_index.as_retriever(similarity_top_k=1)
|
72 |
+
|
73 |
+
texto2sql = """Dada uma pergunta em linguagem natural, crie uma consulta {dialect} sintaticamente correta para executar e, em seguida, verifique os resultados da consulta e retorne a resposta. Você pode ordenar os resultados por uma coluna relevante para retornar os exemplos mais informativos no banco de dados.
|
74 |
+
|
75 |
+
Nunca consulte todas as colunas de uma tabela específica. Pergunte apenas por algumas colunas relevantes, de acordo com a pergunta.
|
76 |
+
|
77 |
+
Preste atenção para usar apenas os nomes de colunas que você pode ver na descrição do esquema. Tenha cuidado para não consultar colunas que não existem. Preste atenção em qual coluna está em qual tabela. Além disso, qualifique os nomes das colunas com o nome da tabela quando necessário.
|
78 |
+
|
79 |
+
Use o seguinte formato, cada um em uma linha:
|
80 |
+
|
81 |
+
Pergunta: Pergunta aqui
|
82 |
+
ConsultaSQL: Consulta SQL para executar
|
83 |
+
ResultadoSQL: Resultado da ConsultaSQL
|
84 |
+
Resposta: Resposta final aqui
|
85 |
+
|
86 |
+
Use apenas as tabelas listadas abaixo.
|
87 |
+
|
88 |
+
{schema}
|
89 |
+
|
90 |
+
Pergunta: {pergunta_user}
|
91 |
+
ConsultaSQL:
|
92 |
+
"""
|
93 |
+
|
94 |
+
from llama_index.core import PromptTemplate
|
95 |
+
|
96 |
+
prompt_1 = PromptTemplate(texto2sql, dialect = engine.dialect.name)
|
97 |
+
|
98 |
+
from typing import List
|
99 |
+
|
100 |
+
def descricao_tabela (schema_tabelas: List[SQLTableSchema]):
|
101 |
+
descricao_str = []
|
102 |
+
for tabela_schema in schema_tabelas:
|
103 |
+
info_tabela = sql_database.get_single_table_info(tabela_schema.table_name)
|
104 |
+
info_tabela += (' A descrição da tabela é: '+tabela_schema.context_str)
|
105 |
+
|
106 |
+
descricao_str.append(info_tabela)
|
107 |
+
return '\n\n'.join(descricao_str)
|
108 |
+
|
109 |
+
from llama_index.core.query_pipeline import FnComponent
|
110 |
+
|
111 |
+
contexto_tabela = FnComponent(fn=descricao_tabela)
|
112 |
+
|
113 |
+
from llama_index.core.llms import ChatResponse
|
114 |
+
|
115 |
+
def resposta_sql (resposta: ChatResponse) -> str:
|
116 |
+
conteudo_resposta = resposta.message.content
|
117 |
+
|
118 |
+
sql_consulta = conteudo_resposta.split("ConsultaSQL: ", 1)[-1].split("ResultadoSQL: ", 1)[0]
|
119 |
+
return sql_consulta.strip().strip('```').strip()
|
120 |
+
|
121 |
+
consulta_sql = FnComponent(fn=resposta_sql)
|
122 |
+
|
123 |
+
from llama_index.core.retrievers import SQLRetriever
|
124 |
+
|
125 |
+
resultado_sql = SQLRetriever(sql_database)
|
126 |
+
|
127 |
+
prompt_2_str = '''
|
128 |
+
Você é o "Assitente de consulta de banco de dados da Zoop".
|
129 |
+
Dada a seguinte pergunta, a consulta SQL correspondente e o resultado SQL, responda à pergunta de modo agradável e objetivamente.
|
130 |
+
Evite iniciar conversas com cumprimentos e apresentações, como "Olá".
|
131 |
+
|
132 |
+
Pergunta: {pergunta_user}
|
133 |
+
Consulta SQL: {consulta}
|
134 |
+
Resultado SQL: {resultado}
|
135 |
+
Resposta:
|
136 |
+
'''
|
137 |
+
|
138 |
+
prompt_2 = PromptTemplate(
|
139 |
+
prompt_2_str,
|
140 |
+
)
|
141 |
+
|
142 |
+
from llama_index.core.query_pipeline import QueryPipeline, InputComponent
|
143 |
+
|
144 |
+
qp = QueryPipeline(
|
145 |
+
modules = {
|
146 |
+
'entrada': InputComponent(),
|
147 |
+
'acesso_tabela': obj_retriever,
|
148 |
+
'contexto_tabela': contexto_tabela,
|
149 |
+
'prompt_1': prompt_1,
|
150 |
+
'llm_1': llm,
|
151 |
+
'consulta_sql': consulta_sql,
|
152 |
+
'resultado_sql': resultado_sql,
|
153 |
+
'prompt_2': prompt_2,
|
154 |
+
'llm_2': llm,
|
155 |
+
},
|
156 |
+
verbose=False
|
157 |
+
)
|
158 |
+
|
159 |
+
qp.add_chain(['entrada', 'acesso_tabela', 'contexto_tabela'])
|
160 |
+
qp.add_link('entrada', 'prompt_1', dest_key='pergunta_user')
|
161 |
+
qp.add_link('contexto_tabela', 'prompt_1', dest_key='schema')
|
162 |
+
qp.add_chain(['prompt_1', 'llm_1', 'consulta_sql', 'resultado_sql'])
|
163 |
+
qp.add_link('entrada', 'prompt_2', dest_key='pergunta_user')
|
164 |
+
qp.add_link('consulta_sql', 'prompt_2', dest_key= 'consulta')
|
165 |
+
qp.add_link('resultado_sql', 'prompt_2', dest_key='resultado')
|
166 |
+
qp.add_link('prompt_2', 'llm_2')
|
167 |
+
|
168 |
+
def entrada_saida (msg_user: str):
|
169 |
+
saida = qp.run(query=msg_user)
|
170 |
+
return str(saida.message.content)
|
171 |
+
|
172 |
+
def adicao_historico(msg_user, historico):
|
173 |
+
msg_assistente = entrada_saida(msg_user)
|
174 |
+
|
175 |
+
historico.append([msg_user, msg_assistente])
|
176 |
+
return msg_assistente, historico
|
177 |
+
|
178 |
+
import gradio as gr
|
179 |
+
|
180 |
+
with gr.Blocks() as demo:
|
181 |
+
gr.Markdown('## Chat com Assistente SQL')
|
182 |
+
gr.Markdown(
|
183 |
+
'''
|
184 |
+
Este é um assistente SQL interativo, projetado para responder perguntas sobre os dados da loja Zoop.
|
185 |
+
Insira sua pergunta no campo abaixo e o assistente irá responder com base no resultado da consulta SQL
|
186 |
+
nos dados disponíveis.
|
187 |
+
'''
|
188 |
+
)
|
189 |
+
chatbot = gr.Chatbot(label='Chat com Assistente')
|
190 |
+
msg = gr.Textbox(label='Digite a sua pergunta e tecle Enter para enviar',
|
191 |
+
placeholder='Digite o texto aqui.')
|
192 |
+
limpeza = gr.Button('Limpar a conversa')
|
193 |
+
def atualizar_historico (msg_user, historico):
|
194 |
+
msg_assistente, historico = adicao_historico(msg_user, historico)
|
195 |
+
return '', historico
|
196 |
+
msg.submit(atualizar_historico, inputs=[msg, chatbot], outputs=[msg, chatbot], queue= False)
|
197 |
+
limpeza.click(lambda: None, inputs=None, outputs=chatbot, queue=False)
|
198 |
+
|
199 |
+
demo.queue()
|
200 |
+
demo.launch()
|
ecommerce.db
ADDED
Binary file (28.7 kB). View file
|
|
requirements.txt
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
pandas==2.2.2
|
2 |
+
sqlalchemy==2.0.36
|
3 |
+
llama-cloud==0.1.5
|
4 |
+
llama-index==0.12.1
|
5 |
+
llama-index-agent-openai==0.4.0
|
6 |
+
llama-index-cli==0.4.0
|
7 |
+
llama-index-core==0.12.1
|
8 |
+
llama-index-embeddings-adapter==0.3.0
|
9 |
+
llama-index-embeddings-huggingface==0.4.0
|
10 |
+
llama-index-embeddings-openai==0.3.0
|
11 |
+
llama-index-experimental==0.5.0
|
12 |
+
llama-index-finetuning==0.3.0
|
13 |
+
llama-index-indices-managed-llama-cloud==0.6.2
|
14 |
+
llama-index-legacy==0.9.48.post4
|
15 |
+
llama-index-llms-azure-openai==0.3.0
|
16 |
+
llama-index-llms-groq==0.3.0
|
17 |
+
llama-index-llms-mistralai==0.3.0
|
18 |
+
llama-index-llms-openai==0.3.1
|
19 |
+
llama-index-llms-openai-like==0.3.0
|
20 |
+
llama-index-multi-modal-llms-openai==0.3.0
|
21 |
+
llama-index-postprocessor-cohere-rerank==0.3.0
|
22 |
+
llama-index-program-openai==0.3.0
|
23 |
+
llama-index-question-gen-openai==0.3.0
|
24 |
+
llama-index-readers-file==0.4.0
|
25 |
+
llama-index-readers-llama-parse==0.4.0
|
26 |
+
llama-parse==0.5.14
|
27 |
+
gradio==5.6.0
|