Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
Upload 4 files
Browse files- app.py +166 -0
- llms.py +71 -0
- pages/Config.py +18 -0
- requirements.txt +0 -0
app.py
ADDED
@@ -0,0 +1,166 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
from llms import LLM
|
3 |
+
|
4 |
+
st.set_page_config(page_title="Multi-LLM", layout="wide", page_icon=":robot_face:", initial_sidebar_state="expanded")
|
5 |
+
st.title("Multi-LLM 🤖")
|
6 |
+
|
7 |
+
st.sidebar.title("Escolha um provedor de LLM")
|
8 |
+
provider = st.sidebar.selectbox("Provedor", ["OpenAI", "Groq"], key="provider_selectbox")
|
9 |
+
|
10 |
+
# Inicializa o estado da sessão se não existir
|
11 |
+
if 'provider' not in st.session_state:
|
12 |
+
st.session_state.provider = provider
|
13 |
+
st.session_state.model = None
|
14 |
+
|
15 |
+
# Inicializa as chaves API para cada provedor se não existirem
|
16 |
+
if 'api_keys' not in st.session_state:
|
17 |
+
st.session_state.api_keys = {
|
18 |
+
"OpenAI": "",
|
19 |
+
"Groq": ""
|
20 |
+
}
|
21 |
+
|
22 |
+
# Campo para API key específica do provedor selecionado
|
23 |
+
api_key = st.sidebar.text_input(
|
24 |
+
f"Insira sua chave API para {provider}:",
|
25 |
+
type="password",
|
26 |
+
value=st.session_state.api_keys[provider]
|
27 |
+
)
|
28 |
+
|
29 |
+
# Armazena a chave API do provedor atual
|
30 |
+
if api_key:
|
31 |
+
st.session_state.api_keys[provider] = api_key
|
32 |
+
|
33 |
+
# Verifica se houve mudança de provedor
|
34 |
+
if st.session_state.provider != provider:
|
35 |
+
st.session_state.provider = provider
|
36 |
+
st.session_state.model = None
|
37 |
+
st.rerun()
|
38 |
+
|
39 |
+
# Adiciona botão para limpar sessão no sidebar
|
40 |
+
if st.sidebar.button("Novo Chat"):
|
41 |
+
# Guarda temporariamente as chaves API e a mensagem do sistema
|
42 |
+
api_keys_temp = st.session_state.api_keys
|
43 |
+
mensagem_sistema_temp = st.session_state.mensagem_sistema
|
44 |
+
provider_temp = st.session_state.provider
|
45 |
+
|
46 |
+
# Limpa todo o estado da sessão
|
47 |
+
for key in list(st.session_state.keys()):
|
48 |
+
del st.session_state[key]
|
49 |
+
|
50 |
+
# Restaura as chaves API e a mensagem do sistema
|
51 |
+
st.session_state.api_keys = api_keys_temp
|
52 |
+
st.session_state.mensagem_sistema = mensagem_sistema_temp
|
53 |
+
st.session_state.provider = provider_temp
|
54 |
+
|
55 |
+
# Força o recarregamento da página
|
56 |
+
st.rerun()
|
57 |
+
|
58 |
+
# Só mostra o select de modelos se tiver API key para o provedor atual
|
59 |
+
if st.session_state.api_keys[provider]:
|
60 |
+
# Define os modelos disponíveis para cada provedor
|
61 |
+
models = {
|
62 |
+
"OpenAI": ["gpt-4", "gpt-4o-mini", "gpt-3.5-turbo"],
|
63 |
+
"Groq": [
|
64 |
+
"llama3-groq-70b-8192-tool-use-preview",
|
65 |
+
"llama-3.1-70b-versatile",
|
66 |
+
"mixtral-8x7b-32768"
|
67 |
+
]
|
68 |
+
}
|
69 |
+
|
70 |
+
# Inicializa as configurações no estado da sessão se não existirem
|
71 |
+
if 'selected_model' not in st.session_state:
|
72 |
+
st.session_state.selected_model = models[provider][0] # Primeiro modelo como padrão
|
73 |
+
|
74 |
+
if 'temperatura' not in st.session_state:
|
75 |
+
st.session_state.temperatura = 0.5 # Valor padrão
|
76 |
+
|
77 |
+
if 'quantidade_tokens' not in st.session_state:
|
78 |
+
st.session_state.quantidade_tokens = 150 # Valor padrão
|
79 |
+
|
80 |
+
if 'quantidade_tokens_input' not in st.session_state:
|
81 |
+
st.session_state.quantidade_tokens_input = "" # Valor padrão
|
82 |
+
|
83 |
+
# Mostra selectbox com os modelos do provedor escolhido e atualiza o estado da sessão
|
84 |
+
selected_model = st.sidebar.selectbox(
|
85 |
+
"Escolha o modelo:",
|
86 |
+
models[provider],
|
87 |
+
key="model_selectbox",
|
88 |
+
index=models[provider].index(st.session_state.selected_model) if st.session_state.selected_model in models[provider] else 0
|
89 |
+
)
|
90 |
+
st.session_state.selected_model = selected_model
|
91 |
+
|
92 |
+
# Controles para temperatura
|
93 |
+
temperatura = st.sidebar.slider(
|
94 |
+
"Temperatura:",
|
95 |
+
min_value=0.0,
|
96 |
+
max_value=1.0,
|
97 |
+
value=st.session_state.temperatura,
|
98 |
+
step=0.1
|
99 |
+
)
|
100 |
+
st.session_state.temperatura = temperatura
|
101 |
+
|
102 |
+
# Campo para quantidade de tokens (opcional)
|
103 |
+
quantidade_tokens_input = st.sidebar.text_input(
|
104 |
+
"Quantidade de tokens (deixe em branco para padrão):",
|
105 |
+
value=st.session_state.quantidade_tokens_input,
|
106 |
+
placeholder="Ex: 150"
|
107 |
+
)
|
108 |
+
st.session_state.quantidade_tokens_input = quantidade_tokens_input
|
109 |
+
|
110 |
+
# Converte a entrada para um número ou usa o padrão
|
111 |
+
if quantidade_tokens_input.strip() == "": # Se o campo estiver vazio
|
112 |
+
quantidade_tokens = 150 # Valor padrão
|
113 |
+
else:
|
114 |
+
quantidade_tokens = int(quantidade_tokens_input) if quantidade_tokens_input.isdigit() else 150 # Converte ou usa padrão
|
115 |
+
|
116 |
+
st.session_state.quantidade_tokens = quantidade_tokens
|
117 |
+
|
118 |
+
# Verifica se a mensagem do sistema foi inicializada
|
119 |
+
if 'mensagem_sistema' not in st.session_state:
|
120 |
+
st.session_state.mensagem_sistema = "" # Inicializa se não existir
|
121 |
+
|
122 |
+
# Recupera a mensagem do sistema do estado da sessão
|
123 |
+
mensagem = st.session_state.mensagem_sistema
|
124 |
+
|
125 |
+
# Cria o container para o chat
|
126 |
+
chat_container = st.container()
|
127 |
+
|
128 |
+
# Inicializa o histórico de mensagens se não existir
|
129 |
+
if "messages" not in st.session_state:
|
130 |
+
st.session_state.messages = []
|
131 |
+
|
132 |
+
# Mostra histórico de mensagens
|
133 |
+
with chat_container:
|
134 |
+
for message in st.session_state.messages:
|
135 |
+
with st.chat_message(message["role"]):
|
136 |
+
st.write(message["content"])
|
137 |
+
|
138 |
+
# Campo de entrada do usuário
|
139 |
+
if prompt := st.chat_input("Digite sua mensagem..."):
|
140 |
+
# Adiciona mensagem do usuário ao histórico
|
141 |
+
st.session_state.messages.append({"role": "user", "content": prompt})
|
142 |
+
|
143 |
+
# Mostra mensagem do usuário
|
144 |
+
with chat_container:
|
145 |
+
with st.chat_message("user"):
|
146 |
+
st.write(prompt)
|
147 |
+
|
148 |
+
# Placeholder para resposta do assistente
|
149 |
+
with st.chat_message("assistant"):
|
150 |
+
message_placeholder = st.empty()
|
151 |
+
message_placeholder.write("Pensando...")
|
152 |
+
|
153 |
+
# Chama a função para gerar a resposta com base no provedor selecionado
|
154 |
+
llm_instance = LLM(
|
155 |
+
api_key=st.session_state.api_keys[provider],
|
156 |
+
modelo=st.session_state.selected_model,
|
157 |
+
temperatura=st.session_state.temperatura,
|
158 |
+
quantidade_tokens=st.session_state.quantidade_tokens,
|
159 |
+
mensagem=st.session_state.mensagem_sistema
|
160 |
+
)
|
161 |
+
llm_instance.prompt = prompt
|
162 |
+
response = llm_instance.gerar_resposta()
|
163 |
+
message_placeholder.write(response)
|
164 |
+
|
165 |
+
# Adiciona resposta do assistente ao histórico
|
166 |
+
st.session_state.messages.append({"role": "assistant", "content": response})
|
llms.py
ADDED
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from openai import OpenAI
|
2 |
+
from groq import Groq
|
3 |
+
|
4 |
+
class LLM:
|
5 |
+
def __init__(self, api_key, modelo, temperatura=0.5, quantidade_tokens=150, mensagem=""):
|
6 |
+
self.temperatura = temperatura
|
7 |
+
self.quantidade_tokens = quantidade_tokens
|
8 |
+
self.mensagem = mensagem
|
9 |
+
self.modelo = modelo
|
10 |
+
self.api_key = api_key
|
11 |
+
self.openai_client = None
|
12 |
+
self.groq_client = None
|
13 |
+
|
14 |
+
def _init_openai_client(self):
|
15 |
+
if not self.openai_client:
|
16 |
+
self.openai_client = OpenAI(api_key=self.api_key)
|
17 |
+
|
18 |
+
def _init_groq_client(self):
|
19 |
+
if not self.groq_client:
|
20 |
+
self.groq_client = Groq(api_key=self.api_key)
|
21 |
+
|
22 |
+
def gerar_resposta_openai(self):
|
23 |
+
self._init_openai_client()
|
24 |
+
messages = []
|
25 |
+
|
26 |
+
if self.mensagem.strip():
|
27 |
+
messages.append({"role": "system", "content": self.mensagem})
|
28 |
+
|
29 |
+
messages.append({"role": "user", "content": self.prompt})
|
30 |
+
|
31 |
+
response = self.openai_client.chat.completions.create(
|
32 |
+
model=self.modelo,
|
33 |
+
messages=messages,
|
34 |
+
temperature=self.temperatura,
|
35 |
+
max_tokens=self.quantidade_tokens,
|
36 |
+
top_p=1,
|
37 |
+
frequency_penalty=0,
|
38 |
+
presence_penalty=0
|
39 |
+
)
|
40 |
+
return response.choices[0].message.content.strip()
|
41 |
+
|
42 |
+
def gerar_resposta_groq(self):
|
43 |
+
self._init_groq_client()
|
44 |
+
messages = []
|
45 |
+
|
46 |
+
if self.mensagem.strip():
|
47 |
+
messages.append({"role": "system", "content": self.mensagem})
|
48 |
+
|
49 |
+
messages.append({"role": "user", "content": self.prompt})
|
50 |
+
|
51 |
+
completion = self.groq_client.chat.completions.create(
|
52 |
+
model=self.modelo,
|
53 |
+
messages=messages,
|
54 |
+
temperature=self.temperatura,
|
55 |
+
max_tokens=self.quantidade_tokens,
|
56 |
+
top_p=0.65,
|
57 |
+
stream=False, # Mudamos para False para manter consistência com OpenAI
|
58 |
+
stop=None
|
59 |
+
)
|
60 |
+
return completion.choices[0].message.content.strip()
|
61 |
+
|
62 |
+
def gerar_resposta(self):
|
63 |
+
"""Método principal para gerar respostas baseado no modelo selecionado"""
|
64 |
+
if "gpt" in self.modelo: # Modelos OpenAI
|
65 |
+
return self.gerar_resposta_openai()
|
66 |
+
elif "llama" in self.modelo or "mixtral" in self.modelo: # Modelos Groq
|
67 |
+
return self.gerar_resposta_groq()
|
68 |
+
else:
|
69 |
+
raise ValueError(f"Modelo não suportado: {self.modelo}")
|
70 |
+
|
71 |
+
|
pages/Config.py
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
|
3 |
+
st.title("Configurações")
|
4 |
+
|
5 |
+
# Inicializa o estado da sessão para a mensagem do sistema se não existir
|
6 |
+
if 'mensagem_sistema' not in st.session_state:
|
7 |
+
st.session_state.mensagem_sistema = ""
|
8 |
+
|
9 |
+
# Campo de entrada para a mensagem do sistema
|
10 |
+
mensagem = st.text_area("Mensagem para o sistema:", value=st.session_state.mensagem_sistema, height=150, max_chars=800)
|
11 |
+
|
12 |
+
# Botão "OK" para atualizar a mensagem do sistema
|
13 |
+
if st.button("OK"):
|
14 |
+
# Atualiza a mensagem do sistema no estado da sessão
|
15 |
+
st.session_state.mensagem_sistema = mensagem
|
16 |
+
|
17 |
+
# Exibe a contagem de caracteres
|
18 |
+
st.write(f"Contagem de caracteres: {len(st.session_state.mensagem_sistema)} / 800")
|
requirements.txt
ADDED
Binary file (142 Bytes). View file
|
|