MisterAI commited on
Commit
ee22467
·
verified ·
1 Parent(s): 773253a

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +169 -0
app.py ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #MisterAI/Docker_Ollama
2
+ #app.py_04
3
+ #https://huggingface.co/spaces/MisterAI/Docker_Ollama/
4
+ #Ajouter Historique
5
+ #Corriger Recuperation Taille Modele si != nXm ou nXb cause erreur runtime 2025.08
6
+
7
+
8
+ import logging
9
+ import requests
10
+ from pydantic import BaseModel
11
+ from langchain_community.llms import Ollama
12
+ from langchain.callbacks.manager import CallbackManager
13
+ from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
14
+ import gradio as gr
15
+ import threading
16
+ import subprocess
17
+ from bs4 import BeautifulSoup
18
+
19
+ logging.basicConfig(level=logging.INFO)
20
+ logger = logging.getLogger(__name__)
21
+
22
+ # Cache pour stocker les modèles déjà chargés
23
+ loaded_models = {}
24
+
25
+ # Variable pour suivre l'état du bouton "Stop"
26
+ stop_flag = False
27
+
28
+ def get_model_list():
29
+ url = "https://ollama.com/search"
30
+ response = requests.get(url)
31
+
32
+ # Vérifier si la requête a réussi
33
+ if response.status_code == 200:
34
+ # Utiliser BeautifulSoup pour analyser le HTML
35
+ soup = BeautifulSoup(response.text, 'html.parser')
36
+ model_list = []
37
+
38
+ # Trouver tous les éléments de modèle
39
+ model_elements = soup.find_all('li', {'x-test-model': True})
40
+
41
+ for model_element in model_elements:
42
+ model_name = model_element.find('span', {'x-test-search-response-title': True}).text.strip()
43
+ size_elements = model_element.find_all('span', {'x-test-size': True})
44
+
45
+ # Filtrer les modèles par taille
46
+ for size_element in size_elements:
47
+ size = size_element.text.strip().lower() # Convertir en minuscules
48
+ if 'x' in size:
49
+ # Exclure les modèles avec des tailles de type nXm ou nXb
50
+ continue
51
+ elif size.endswith('m'):
52
+ # Tous les modèles en millions sont acceptés
53
+ model_list.append(f"{model_name}:{size}")
54
+ elif size.endswith('b'):
55
+ # Extraire Partie Numérique avant b
56
+ size_str = size[:-1]
57
+ # Si Nombre Valide Ajouter a La Liste Sinon Ignorer Modèle
58
+ if size_str.isdigit():
59
+ size_value = float(size_str)
60
+ if size_value <= 10:
61
+ model_list.append(f"{model_name}:{size}")
62
+ # Si ce n'est pas un nombre (ex: "e2b"), ignorer
63
+
64
+ # elif size.endswith('b'):
65
+ # # Convertir les modèles en milliards en milliards
66
+ # size_value = float(size[:-1])
67
+ # if size_value <= 10: # Filtrer les modèles <= 10 milliards de paramètres
68
+ # model_list.append(f"{model_name}:{size}")
69
+
70
+
71
+
72
+ return model_list
73
+ else:
74
+ logger.error(f"Erreur lors de la récupération de la liste des modèles : {response.status_code} - {response.text}")
75
+ return []
76
+
77
+ def get_llm(model_name):
78
+ callback_manager = CallbackManager([StreamingStdOutCallbackHandler()])
79
+ return Ollama(model=model_name, callback_manager=callback_manager)
80
+
81
+ class InputData(BaseModel):
82
+ model_name: str
83
+ input: str
84
+ max_tokens: int = 256
85
+ temperature: float = 0.7
86
+
87
+ def pull_model(model_name):
88
+ try:
89
+ # Exécuter la commande pour tirer le modèle
90
+ subprocess.run(["ollama", "pull", model_name], check=True)
91
+ logger.info(f"Model {model_name} pulled successfully.")
92
+ except subprocess.CalledProcessError as e:
93
+ logger.error(f"Failed to pull model {model_name}: {e}")
94
+ raise
95
+
96
+ def check_and_load_model(model_name):
97
+ # Vérifier si le modèle est déjà chargé
98
+ if model_name in loaded_models:
99
+ logger.info(f"Model {model_name} is already loaded.")
100
+ return loaded_models[model_name]
101
+ else:
102
+ logger.info(f"Loading model {model_name}...")
103
+ # Tirer le modèle si nécessaire
104
+ pull_model(model_name)
105
+ llm = get_llm(model_name)
106
+ loaded_models[model_name] = llm
107
+ return llm
108
+
109
+ # Interface Gradio
110
+ def gradio_interface(model_name, input, max_tokens, temperature, history):
111
+ global stop_flag
112
+ stop_flag = False
113
+
114
+ # Ajouter la requête de l'utilisateur à l'historique une seule fois
115
+ history.append((input, ""))
116
+ yield history, history
117
+
118
+ def worker():
119
+ llm = check_and_load_model(model_name)
120
+ response = ""
121
+ for token in llm.stream(input, max_tokens=max_tokens, temperature=temperature):
122
+ if stop_flag:
123
+ break
124
+ response += token
125
+ history[-1] = (input, response)
126
+ yield history, history
127
+
128
+ # Utiliser un thread pour gérer le streaming
129
+ for result in worker():
130
+ if stop_flag:
131
+ break
132
+ yield result
133
+
134
+ model_list = get_model_list()
135
+
136
+ demo = gr.Interface(
137
+ fn=gradio_interface,
138
+ inputs=[
139
+ gr.Dropdown(model_list, label="Select Model", value="mistral:7b"),
140
+ gr.Textbox(label="Input"),
141
+ gr.Slider(minimum=1, maximum=2048, step=1, label="Max Tokens", value=256),
142
+ gr.Slider(minimum=0.0, maximum=1.0, step=0.1, label="Temperature", value=0.7),
143
+ gr.State(value=[]) # Ajout de l'historique
144
+ ],
145
+ outputs=[
146
+ gr.Chatbot(label="History"), # Utilisation de Chatbot pour l'historique
147
+ gr.State() # Ajout de l'historique
148
+ ],
149
+ title="Ollama Demo 🐳 🦙 🤗",
150
+ description="""
151
+ Bienvenue sur Docker_Ollama, un espace dédié à l'exploration et au test des modèles Ollama.
152
+
153
+ Cette Démo permet aux utilisateurs de tester tous les modèles Ollama dont la taille est inférieure à 10 milliards de paramètres directement depuis cette interface.
154
+
155
+ L'Application tourne sur une machine Hugging Face Free Space : 2 CPU - 16Gb RAM
156
+
157
+ Soyez patient. Chaque Nouveau Modèle Selectionner Devra Etre Télécharger Avant de Répondre.
158
+
159
+ Il faut compter 2 a 3 minutes pour la réponse d'un modèle 7b alors que quelques dizaines de secondes suffisent pour un modèle 1b.
160
+
161
+ """
162
+ )
163
+
164
+ def stop_processing():
165
+ global stop_flag
166
+ stop_flag = True
167
+
168
+ if __name__ == "__main__":
169
+ demo.launch(server_name="0.0.0.0", server_port=7860, pwa=True)