Eric Marchand
commited on
Commit
·
98da9ec
1
Parent(s):
da9f7bb
First commit
Browse files- .gitignore +1 -0
- app.py +80 -0
- requirements.txt +5 -0
- src/amodel.py +75 -0
.gitignore
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
git-commit-push.bat
|
app.py
ADDED
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import spaces
|
3 |
+
from transformers import AutoTokenizer, AutoModelForCausalLM
|
4 |
+
import torch # avec pip sur windows, ERROR: No matching distribution found for torch
|
5 |
+
# à utiliser dans un environnement GPU, Colab ou Space
|
6 |
+
import os
|
7 |
+
|
8 |
+
from src.amodel import AModel
|
9 |
+
AModel.load_env_variables()
|
10 |
+
|
11 |
+
MODEL_ID = "OpenLLM-France/Lucie-7B-Instruct"
|
12 |
+
|
13 |
+
TOKENIZER = AutoTokenizer.from_pretrained(
|
14 |
+
MODEL_ID,
|
15 |
+
token=os.getenv("HUGGINGFACEHUB_API_TOKEN"),
|
16 |
+
trust_remote_code=True
|
17 |
+
)
|
18 |
+
MODEL = AutoModelForCausalLM.from_pretrained(
|
19 |
+
MODEL_ID,
|
20 |
+
token=os.getenv("HUGGINGFACEHUB_API_TOKEN"),
|
21 |
+
device_map="auto",
|
22 |
+
torch_dtype=torch.bfloat16,
|
23 |
+
trust_remote_code=True
|
24 |
+
)
|
25 |
+
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
|
26 |
+
|
27 |
+
with gr.Blocks(title="Lucie",
|
28 |
+
fill_height=True,
|
29 |
+
analytics_enabled=False,
|
30 |
+
css="footer {visibility: hidden}",
|
31 |
+
) as demo:
|
32 |
+
|
33 |
+
@spaces.GPU
|
34 |
+
def send(question):
|
35 |
+
system_prompt = '''Tu es Lucie, une assistante IA française serviable et amicale.
|
36 |
+
Tu réponds toujours en français de manière précise et utile.
|
37 |
+
Tu es honnête et si tu ne sais pas quelque chose, tu le dis simplement.'''
|
38 |
+
full_prompt = f"""<|system|>{system_prompt}</s><|user|>{question}</s><|assistant|>"""
|
39 |
+
inputs = TOKENIZER(full_prompt, return_tensors="pt").to(DEVICE)
|
40 |
+
outputs = MODEL.generate(
|
41 |
+
**inputs,
|
42 |
+
# max_new_tokens=max_new_tokens, # TODO: S'occuper des max_tokens avec tous les modèles
|
43 |
+
max_new_tokens=512,
|
44 |
+
# temperature=temperature,
|
45 |
+
# top_p=top_p,
|
46 |
+
# top_k=top_k,
|
47 |
+
# repetition_penalty=repetition_penalty,
|
48 |
+
do_sample=True,
|
49 |
+
pad_token_id=TOKENIZER.eos_token_id
|
50 |
+
)
|
51 |
+
response = TOKENIZER.decode(outputs[0], skip_special_tokens=True)
|
52 |
+
r = response.split("<|assistant|>")[-1].strip()
|
53 |
+
return r, gr.Image()
|
54 |
+
|
55 |
+
with gr.Tab("Chat"):
|
56 |
+
with gr.Row():
|
57 |
+
gr.Markdown('''# Lucie d'OpenLLM
|
58 |
+
|
59 |
+
## Discute avec Lucie
|
60 |
+
''')
|
61 |
+
with gr.Row():
|
62 |
+
gr.HTML('''<div><p align='right'>Pose ta question:</p></div>''')
|
63 |
+
question = gr.Textbox("", show_copy_button=False,
|
64 |
+
show_label=False,
|
65 |
+
container=False)
|
66 |
+
send_btn = gr.Button("Ok")
|
67 |
+
# L'image blanche qui affiche la progression
|
68 |
+
wait = gr.Image("./files/white.jpg", height=25, show_download_button=False,
|
69 |
+
show_fullscreen_button=False, show_label=False, show_share_button=False,
|
70 |
+
interactive=False, container=False, visible=True)
|
71 |
+
|
72 |
+
resp = gr.Textbox("", show_copy_button=False,
|
73 |
+
show_label=False,
|
74 |
+
container=False,
|
75 |
+
max_lines=15)
|
76 |
+
|
77 |
+
send_btn.click(send, inputs=[question], outputs=[resp, wait])
|
78 |
+
|
79 |
+
if __name__ == "__main__":
|
80 |
+
demo.queue().launch()
|
requirements.txt
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
gradio
|
2 |
+
torch
|
3 |
+
transformers
|
4 |
+
accelerate
|
5 |
+
spaces
|
src/amodel.py
ADDED
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from abc import ABC, abstractmethod
|
2 |
+
from enum import Enum
|
3 |
+
import os
|
4 |
+
|
5 |
+
class ModelType(Enum):
|
6 |
+
''' Les différentes technos de models '''
|
7 |
+
MTOPENAI = 1
|
8 |
+
MTOLLAMA = 2
|
9 |
+
MTHUGGINGFACE = 3
|
10 |
+
MTMISTRAL = 4
|
11 |
+
MTHUGGINGFACEURL = 5
|
12 |
+
|
13 |
+
@classmethod
|
14 |
+
def to_str(self, mt:int)->str:
|
15 |
+
match mt:
|
16 |
+
case 1: return "MTOPENAI"
|
17 |
+
case 2: return "MTOLLAMA"
|
18 |
+
case 3: return "MTHUGGINGFACE"
|
19 |
+
case 4: return "MTMISTRAL"
|
20 |
+
case _: return "UNKNOWN"
|
21 |
+
|
22 |
+
class AModel(ABC):
|
23 |
+
'''
|
24 |
+
Classe abstraite de base pour tous les models :
|
25 |
+
Ollama en local
|
26 |
+
OpenAI distant
|
27 |
+
HuggingFace distant
|
28 |
+
HuggingFace dans une app
|
29 |
+
...
|
30 |
+
'''
|
31 |
+
|
32 |
+
@classmethod
|
33 |
+
def load_env_variables(cls):
|
34 |
+
'''
|
35 |
+
Gestion des tokens par variables d'environnement
|
36 |
+
On utilise dotenv, sauf si la platforme est un space HuggingFace
|
37 |
+
Dans ce cas les variables d'env sont déjà chargées
|
38 |
+
'''
|
39 |
+
# HF_ACTIVE est une variable d'environnement créée dans les spaces HuggingFace
|
40 |
+
# Elle sert à savoir que l'appli tourne dans un space
|
41 |
+
if not os.getenv("HF_ACTIVE"): # Utilisation ailleurs que dans un space
|
42 |
+
# load_dotenv ne passe pas dans un space HuggingFace
|
43 |
+
from dotenv import load_dotenv
|
44 |
+
load_dotenv()
|
45 |
+
|
46 |
+
|
47 |
+
@abstractmethod
|
48 |
+
def ask_llm(self, question:str)->str:
|
49 |
+
pass
|
50 |
+
|
51 |
+
@abstractmethod
|
52 |
+
def create_vector(self, chunk:str)->list[float]:
|
53 |
+
pass
|
54 |
+
|
55 |
+
@abstractmethod
|
56 |
+
def create_vectors(self, chunks:list[str])->list[list[float]]:
|
57 |
+
pass
|
58 |
+
|
59 |
+
def get_llm_name(self):
|
60 |
+
return self.llm_name
|
61 |
+
|
62 |
+
def set_llm_name(self, llm_name:str):
|
63 |
+
self.llm_name = llm_name
|
64 |
+
|
65 |
+
def get_feature_name(self):
|
66 |
+
return self.feature_name
|
67 |
+
|
68 |
+
def set_feature_name(self, feature_name:str):
|
69 |
+
self.feature_name = feature_name
|
70 |
+
|
71 |
+
def get_temperature(self):
|
72 |
+
return self.temperature
|
73 |
+
|
74 |
+
def set_temperature(self, temperature:float):
|
75 |
+
self.temperature = temperature
|