MMOON commited on
Commit
9486a95
·
verified ·
1 Parent(s): 04eec55

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +209 -38
src/streamlit_app.py CHANGED
@@ -1,40 +1,211 @@
1
- import altair as alt
2
- import numpy as np
3
- import pandas as pd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  import streamlit as st
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
-
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
15
-
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
1
+ Absolument ! Voici une version améliorée du code.
2
+
3
+ Cette nouvelle version intègre plusieurs améliorations clés :
4
+
5
+ Design et Interface Utilisateur (UI) : Utilisation de st.sidebar pour les options et les crédits, et st.container pour une meilleure organisation visuelle du chat.
6
+
7
+ Gestion des Modèles : Le code est maintenant plus flexible. Il vous permet de choisir entre le modèle original (Apertus-8B) et le modèle plus puissant que vous avez suggéré (Apertus-70B), et même d'autres si vous le souhaitez.
8
+
9
+ Authentification Hugging Face : Intégration de la connexion via huggingface_hub pour utiliser des modèles qui pourraient être privés ou nécessiter une authentification. Le token est demandé de manière sécurisée via st.text_input de type "password".
10
+
11
+ Paramètres de Génération Ajustables : Les paramètres comme la température, le top_p et le nombre maximum de tokens sont maintenant des curseurs dans la barre latérale, permettant à l'utilisateur de les ajuster dynamiquement.
12
+
13
+ Optimisation et Clarté : Le code est restructuré en fonctions plus claires pour une meilleure lisibilité et maintenance.
14
+
15
+ Aperçu du nouveau design
16
+
17
+ L'interface sera divisée en deux parties :
18
+
19
+ Une barre latérale (Sidebar) à gauche pour la configuration :
20
+
21
+ Connexion à Hugging Face.
22
+
23
+ Sélection du modèle.
24
+
25
+ Réglage des paramètres de génération.
26
+
27
+ Un bouton pour effacer l'historique.
28
+
29
+ La fenêtre de chat principale à droite pour la conversation.
30
+
31
+ Le Code Amélioré
32
+ code
33
+ Python
34
+ download
35
+ content_copy
36
+ expand_less
37
+
38
  import streamlit as st
39
+ import torch
40
+ from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
41
+ from huggingface_hub import login
42
+
43
+ # --- CONFIGURATION DE LA PAGE ---
44
+ st.set_page_config(
45
+ page_title="Chat Avancé avec Apertus",
46
+ page_icon="🚀",
47
+ layout="wide",
48
+ initial_sidebar_state="expanded",
49
+ )
50
+
51
+ # --- STYLES CSS PERSONNALISÉS (Optionnel) ---
52
+ st.markdown("""
53
+ <style>
54
+ .stSpinner > div > div {
55
+ border-top-color: #f63366;
56
+ }
57
+ .stChatMessage {
58
+ background-color: #f0f2f6;
59
+ border-radius: 10px;
60
+ padding: 15px;
61
+ margin-bottom: 10px;
62
+ }
63
+ </style>
64
+ """, unsafe_allow_html=True)
65
+
66
+
67
+ # --- BARRE LATÉRALE DE CONFIGURATION ---
68
+ with st.sidebar:
69
+ st.title("🚀 Paramètres")
70
+ st.markdown("Configurez l'assistant et le modèle de langage.")
71
+
72
+ # --- Authentification Hugging Face ---
73
+ st.subheader("Authentification Hugging Face")
74
+ hf_token = st.text_input("Votre Token Hugging Face (hf_...)", type="password")
75
+ if st.button("Se Connecter"):
76
+ if hf_token:
77
+ try:
78
+ login(token=hf_token)
79
+ st.success("Connecté à Hugging Face Hub !")
80
+ st.session_state.hf_logged_in = True
81
+ except Exception as e:
82
+ st.error(f"Échec de la connexion : {e}")
83
+ else:
84
+ st.warning("Veuillez entrer un token Hugging Face.")
85
+
86
+ # --- Sélection du Modèle ---
87
+ st.subheader("Sélection du Modèle")
88
+ model_options = {
89
+ "Apertus 8B (Rapide)": "swiss-ai/Apertus-8B-Instruct-2509",
90
+ "Apertus 70B (Puissant)": "swiss-ai/Apertus-70B-2509"
91
+ }
92
+ selected_model_name = st.selectbox("Choisissez un modèle :", options=list(model_options.keys()))
93
+ model_id = model_options[selected_model_name]
94
+ st.caption(f"ID du modèle : `{model_id}`")
95
+
96
+
97
+ # --- Paramètres de Génération ---
98
+ st.subheader("Paramètres de Génération")
99
+ temperature = st.slider("Température", min_value=0.1, max_value=1.5, value=0.7, step=0.05,
100
+ help="Plus la valeur est élevée, plus la réponse est créative et aléatoire.")
101
+ max_new_tokens = st.slider("Tokens Max", min_value=64, max_value=1024, value=256, step=64,
102
+ help="Longueur maximale de la réponse générée.")
103
+ top_p = st.slider("Top-p (Nucleus Sampling)", min_value=0.1, max_value=1.0, value=0.95, step=0.05,
104
+ help="Contrôle la diversité en sélectionnant les mots les plus probables dont la somme des probabilités dépasse ce seuil.")
105
+
106
+ # --- Bouton pour effacer l'historique ---
107
+ if st.button("🗑️ Effacer l'historique"):
108
+ st.session_state.messages = []
109
+ st.experimental_rerun()
110
+
111
+
112
+ # --- CHARGEMENT DU MODÈLE (MIS EN CACHE) ---
113
+ @st.cache_resource(show_spinner=False)
114
+ def load_model(model_identifier):
115
+ """Charge le tokenizer et le modèle avec quantification 4-bit."""
116
+ with st.spinner(f"Chargement du modèle '{model_identifier}'... Cela peut prendre un moment. ⏳"):
117
+ bnb_config = BitsAndBytesConfig(
118
+ load_in_4bit=True,
119
+ bnb_4bit_quant_type="nf4",
120
+ bnb_4bit_compute_dtype=torch.bfloat16,
121
+ )
122
+ tokenizer = AutoTokenizer.from_pretrained(model_identifier)
123
+ model = AutoModelForCausalLM.from_pretrained(
124
+ model_identifier,
125
+ quantization_config=bnb_config,
126
+ device_map="auto",
127
+ )
128
+ return tokenizer, model
129
+
130
+ # Charge le modèle sélectionné
131
+ try:
132
+ tokenizer, model = load_model(model_id)
133
+ except Exception as e:
134
+ st.error(f"Impossible de charger le modèle. Assurez-vous d'être connecté si le modèle est privé. Erreur : {e}")
135
+ st.stop()
136
+
137
+
138
+ # --- INTERFACE DE CHAT PRINCIPALE ---
139
+ st.title("🤖 Chat avec Apertus")
140
+ st.caption(f"Vous discutez actuellement avec **{selected_model_name}**.")
141
+
142
+ # Initialisation de l'historique du chat
143
+ if "messages" not in st.session_state:
144
+ st.session_state.messages = []
145
+
146
+ # Affichage des messages de l'historique
147
+ for message in st.session_state.messages:
148
+ with st.chat_message(message["role"]):
149
+ st.markdown(message["content"])
150
+
151
+ # Zone de saisie utilisateur
152
+ if prompt := st.chat_input("Posez votre question à Apertus..."):
153
+ # Ajout et affichage du message utilisateur
154
+ st.session_state.messages.append({"role": "user", "content": prompt})
155
+ with st.chat_message("user"):
156
+ st.markdown(prompt)
157
+
158
+ # --- GÉNÉRATION DE LA RÉPONSE ---
159
+ with st.chat_message("assistant"):
160
+ response_placeholder = st.empty()
161
+ with st.spinner("Réflexion en cours... 🤔"):
162
+ # Préparation des entrées pour le modèle
163
+ full_prompt = f"User: {prompt}\nAssistant:"
164
+ input_ids = tokenizer(full_prompt, return_tensors="pt").to(model.device)
165
+
166
+ # Génération de la réponse
167
+ outputs = model.generate(
168
+ **input_ids,
169
+ max_new_tokens=max_new_tokens,
170
+ do_sample=True,
171
+ temperature=temperature,
172
+ top_p=top_p,
173
+ eos_token_id=tokenizer.eos_token_id
174
+ )
175
+
176
+ # Décodage et nettoyage de la réponse
177
+ response_text = tokenizer.decode(outputs[0], skip_special_tokens=True)
178
+ # Nettoyage pour retirer la question initiale de la réponse
179
+ cleaned_response = response_text.replace(full_prompt, "").strip()
180
+
181
+ response_placeholder.markdown(cleaned_response)
182
+
183
+ # Ajout de la réponse de l'assistant à l'historique
184
+ st.session_state.messages.append({"role": "assistant", "content": cleaned_response})
185
+ Comment exécuter ce code
186
+
187
+ Sauvegardez le code dans un fichier Python, par exemple app_v2.py.
188
+
189
+ Installez les bibliothèques nécessaires si ce n'est pas déjà fait :
190
+
191
+ code
192
+ Bash
193
+ download
194
+ content_copy
195
+ expand_less
196
+ IGNORE_WHEN_COPYING_START
197
+ IGNORE_WHEN_COPYING_END
198
+ pip install streamlit torch transformers bitsandbytes accelerate huggingface_hub
199
+
200
+ Lancez l'application depuis votre terminal :
201
+
202
+ code
203
+ Bash
204
+ download
205
+ content_copy
206
+ expand_less
207
+ IGNORE_WHEN_COPYING_START
208
+ IGNORE_WHEN_COPYING_END
209
+ streamlit run app_v2.py
210
 
211
+ Votre navigateur s'ouvrira avec cette nouvelle interface, prête à l'emploi