update to ollama & openwebui
This commit is contained in:
parent
944ce3eae8
commit
ca15f31551
@ -1,9 +0,0 @@
|
|||||||
docker-compose.yml
|
|
||||||
models/
|
|
||||||
images/
|
|
||||||
app/bin
|
|
||||||
app/lib
|
|
||||||
app/lib64
|
|
||||||
app/__pycache__
|
|
||||||
app/pyvenv.cfg
|
|
||||||
app/include
|
|
||||||
19
.env
19
.env
@ -1,19 +0,0 @@
|
|||||||
#########################LOCALAI#########################
|
|
||||||
|
|
||||||
# local-ai quand flask dockerisé
|
|
||||||
LOCALAI_HOST=local-ai
|
|
||||||
|
|
||||||
MODELS_PATH=/models
|
|
||||||
|
|
||||||
DEBUG=true
|
|
||||||
REBUILD=false
|
|
||||||
|
|
||||||
#THREADS=4
|
|
||||||
|
|
||||||
DEFAULT_MODEL=gpt-3.5-turbo
|
|
||||||
PRELOAD_MODELS=[{"url":"github:go-skynet/model-gallery/gpt4all-j.yaml","name":"gpt-3.5-turbo"},{"url":"github:go-skynet/model-gallery/stablediffusion.yaml","name":"stablediffusion"}]
|
|
||||||
|
|
||||||
#DEFAULT_MODEL=wizard-lm
|
|
||||||
#PRELOAD_MODELS=[{"url":"github:go-skynet/model-gallery/openllama_7b.yaml","name":"open_llama"}]
|
|
||||||
|
|
||||||
#GALLERIES=[{"name":"model-gallery","url":"github:go-skynet/model-gallery/index.yaml"}]
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
FROM python:3.10-slim-bullseye
|
|
||||||
ENV PYTHONDONTWRITEBYTECODE 1
|
|
||||||
ENV PYTHONUNBUFFERED 1
|
|
||||||
WORKDIR /
|
|
||||||
COPY . .
|
|
||||||
RUN pip3 install -r requirements.txt
|
|
||||||
WORKDIR /app
|
|
||||||
CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0"]
|
|
||||||
86
README.md
86
README.md
@ -2,10 +2,7 @@
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
Projet pour héberger un Chat-GPT local s'appuyant sur le projet [LocalAI](https://localai.io/)
|
Projet pour héberger un Chat-GPT local s'appuyant sur les projets [Ollama](https://github.com/ollama/ollama) et [OpenWebUI](https://github.com/open-webui/open-webui)
|
||||||
utilisant une simple flaskapp comme frontend.
|
|
||||||
|
|
||||||
:warning: seulement le model ggml-gpt4all-j (gpt-3.5-turbo) est pris en charge pour le moment
|
|
||||||
|
|
||||||
## PREREQUIS :paperclip:
|
## PREREQUIS :paperclip:
|
||||||
|
|
||||||
@ -13,87 +10,28 @@ utilisant une simple flaskapp comme frontend.
|
|||||||
|
|
||||||
## MODELS :moyai:
|
## MODELS :moyai:
|
||||||
|
|
||||||
- compatibles: [LocalAI](https://github.com/go-skynet/model-gallery)
|
- compatibles: [Ollama modèles librairie](https://ollama.com/library)
|
||||||
- tous: [HugginFace](https://huggingface.co/models?search=ggml)
|
|
||||||
|
|
||||||
## CONFIGURATION :wrench:
|
## CONFIGURATION :wrench:
|
||||||
|
|
||||||
La configuration se fait dans le .env.local:
|
### BASE
|
||||||
- THREADS -> nombre de cores du CPU utilisés (privilègier le nombre de cores physiques au max)
|
|
||||||
<img src="https://indipest.files.wordpress.com/2021/03/bw6d5zz.gif" width="200px">
|
|
||||||
- DEFAULT_MODEL -> Le modèle chargé par défault (dans la RAM)
|
|
||||||
- PRELOAD_MODELS -> Renseigner les adresses des modèles que l'on veux télécharger via l'adresse https://github.com/go-skynet/model-gallery/model.yaml
|
|
||||||
|
|
||||||
:warning: L'image LocalAI fait un peu plus de 12Go et les modèles 7B ou 13B font en moyenne 4 à 6Go
|
|
||||||
|
### OIDC :key:
|
||||||
|
|
||||||
|
Renseigner les variables d'environnement dans le docker-compose.yml
|
||||||
|
|
||||||
## UTILISATION :checkered_flag:
|
## UTILISATION :checkered_flag:
|
||||||
|
|
||||||
- Premier lancement:
|
- Démarrer la stack:
|
||||||
```bash
|
```bash
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
:hourglass: Attendre que la stack se build :coffee:
|
- Ajouter des modèles:
|
||||||
|
|
||||||
- L'interface est accessible à cette adresse:
|

|
||||||
|
|
||||||
> http://localhost:5000
|
- Choisir les modèles disponible pour les utilisateurs:
|
||||||
|
|
||||||
- Après les premier lancement:
|

|
||||||
|
|
||||||
```bash
|
|
||||||
nano .env
|
|
||||||
REBUILD=false
|
|
||||||
```
|
|
||||||
|
|
||||||
> A chaque modification des PRELOAD_MODELS, REBUILD=true
|
|
||||||
|
|
||||||
#### voir les logs
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker compose logs -f
|
|
||||||
```
|
|
||||||
|
|
||||||
## OIDC :key:
|
|
||||||
|
|
||||||
> voir le [README](https://git.legaragenumerique.fr/GARAGENUM/flask-keycloak/README.md) dans le projet flask-keycloak
|
|
||||||
|
|
||||||
## MODELS OK
|
|
||||||
|
|
||||||
:white_check_mark: ggml-gpt4all-j.bin (= gpt-turbo-3.5)
|
|
||||||
:white_check_mark: stablediffusion (image generator)
|
|
||||||
- [ ] wizardlm-13b-v1.1-superhot-8k.ggmlv3.q4_0.bin
|
|
||||||
- [ ] open-llama-7b-q4_0.bin -> HS pour le moment
|
|
||||||
- [ ] whisper (audio to text)
|
|
||||||
- [ ] bloomz (traduction)
|
|
||||||
- [ ] wizardcode (code) -> URL model HS
|
|
||||||
|
|
||||||
## TEST HARDWARE :computer:
|
|
||||||
|
|
||||||
| MODEL | PROMPT | i5-8350U 16G RAM | RYZEN 7 5800X 32G RAM | TEMP
|
|
||||||
| :--------------- |:-----------------:| ---------------------:|:----------------:|:------:|
|
|
||||||
| GPT-TURBO-3.5 | WRITE JS FUNCTION | 41S | 16s | 0.5 |
|
|
||||||
| STABLEDIFFUSION | BLUE FLOWER | 90s | 20S | X |
|
|
||||||
|
|
||||||
|
|
||||||
## TO DO :bookmark_tabs:
|
|
||||||
|
|
||||||
:white_check_mark: une page gpt / une page stablediffusion avec navbar dans base.html
|
|
||||||
:white_check_mark: Temperature bouton
|
|
||||||
:white_check_mark: formater code (```js ```)
|
|
||||||
:white_check_mark: Flask app frontend
|
|
||||||
:white_check_mark: authentification Keycloak -> https://git.legaragenumerique.fr/GARAGENUM/flask-keycloak
|
|
||||||
:white_check_mark: wsgi.py for prod + DNS
|
|
||||||
- [ ] ajouter config Nginx (ai.domaine.tld + image.domaine.tld)
|
|
||||||
- [ ] bouton stop generating ?
|
|
||||||
- [ ] bouton home
|
|
||||||
- [ ] conserver context (sqlite / json / session ?)
|
|
||||||
- [ ] Traduction via [LibreTranslate](https://github.com/LibreTranslate/LibreTranslate) :gb: -> :fr:
|
|
||||||
- [ ] restart container si timeout
|
|
||||||
- [ ] utiliser GPU
|
|
||||||
- [ ] entraîner avec big GPU
|
|
||||||
|
|
||||||
### bugs :ghost:
|
|
||||||
|
|
||||||
:white_check_mark: permissions dossier models (root != user)
|
|
||||||
:white_check_mark: image url en prod
|
|
||||||
|
|||||||
19
app/.env
19
app/.env
@ -1,19 +0,0 @@
|
|||||||
#########################LOCALAI#########################
|
|
||||||
|
|
||||||
# local-ai quand flask dockerisé
|
|
||||||
LOCALAI_HOST=local-ai
|
|
||||||
|
|
||||||
MODELS_PATH=/models
|
|
||||||
|
|
||||||
DEBUG=true
|
|
||||||
REBUILD=false
|
|
||||||
|
|
||||||
#THREADS=4
|
|
||||||
|
|
||||||
DEFAULT_MODEL=gpt-3.5-turbo
|
|
||||||
PRELOAD_MODELS=[{"url":"github:go-skynet/model-gallery/gpt4all-j.yaml","name":"gpt-3.5-turbo"},{"url":"github:go-skynet/model-gallery/stablediffusion.yaml","name":"stablediffusion"}]
|
|
||||||
|
|
||||||
#DEFAULT_MODEL=wizard-lm
|
|
||||||
#PRELOAD_MODELS=[{"url":"github:go-skynet/model-gallery/openllama_7b.yaml","name":"open_llama"}]
|
|
||||||
|
|
||||||
#GALLERIES=[{"name":"model-gallery","url":"github:go-skynet/model-gallery/index.yaml"}]
|
|
||||||
88
app/app.py
88
app/app.py
@ -1,88 +0,0 @@
|
|||||||
import os, re
|
|
||||||
import requests, time
|
|
||||||
from dotenv import load_dotenv
|
|
||||||
from flask_oidc import OpenIDConnect
|
|
||||||
from flask import Flask, redirect, render_template, request, url_for
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
|
||||||
model = "ggml-gpt4all-j.bin"
|
|
||||||
|
|
||||||
load_dotenv()
|
|
||||||
host = os.getenv("LOCALAI_HOST")
|
|
||||||
|
|
||||||
# CHAT BOT: GPT-TURBO-3.5
|
|
||||||
@app.route("/", methods=("GET", "POST"))
|
|
||||||
def index():
|
|
||||||
|
|
||||||
result = ''
|
|
||||||
temps = ''
|
|
||||||
|
|
||||||
if request.method == "POST":
|
|
||||||
|
|
||||||
question = request.form["question"]
|
|
||||||
temp = request.form["temperature"]
|
|
||||||
|
|
||||||
url = "http://" + host + ":8080/v1/chat/completions"
|
|
||||||
|
|
||||||
payload = {
|
|
||||||
# "role": "system", "content": "You are Yoda, the character of Star Wars and you answer the question like he would.",
|
|
||||||
"model": 'gpt-3.5-turbo',
|
|
||||||
"messages": [{"role": "user", "content": question}],
|
|
||||||
"temperature": float(temp)
|
|
||||||
}
|
|
||||||
|
|
||||||
tic = time.perf_counter()
|
|
||||||
|
|
||||||
response = requests.post(url, json=payload)
|
|
||||||
if response.status_code == 200:
|
|
||||||
result = '<md>' + response.json()['choices'][0]['message']['content'] + '</md>'
|
|
||||||
|
|
||||||
else:
|
|
||||||
result = "Erreur de connection avec l'API"
|
|
||||||
|
|
||||||
toc = time.perf_counter()
|
|
||||||
|
|
||||||
temps = f"temps de réponse: {toc - tic:0.4f} seconds"
|
|
||||||
|
|
||||||
return render_template("index.html", result=result, time=temps)
|
|
||||||
|
|
||||||
|
|
||||||
# IMAGE GENERATOR: STABLEDIFFUSION
|
|
||||||
@app.route("/image", methods=("GET", "POST"))
|
|
||||||
def image():
|
|
||||||
|
|
||||||
result = ''
|
|
||||||
temps = ''
|
|
||||||
|
|
||||||
if request.method == "POST":
|
|
||||||
question = request.form["image"]
|
|
||||||
url = "http://" + host + ":8080/v1/images/generations"
|
|
||||||
|
|
||||||
headers = {
|
|
||||||
"Content-Type": "application/json"
|
|
||||||
}
|
|
||||||
|
|
||||||
data = {
|
|
||||||
"prompt": question,
|
|
||||||
"size": "256x256",
|
|
||||||
"directory": "/tmp"
|
|
||||||
}
|
|
||||||
|
|
||||||
tic = time.perf_counter()
|
|
||||||
|
|
||||||
response = requests.post(url, headers=headers, json=data)
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
|
||||||
image_url = response.json()['data'][0]['url'].replace("local-ai", "localhost")
|
|
||||||
|
|
||||||
else:
|
|
||||||
result = "Erreur de connection avec l'API"
|
|
||||||
|
|
||||||
toc = time.perf_counter()
|
|
||||||
|
|
||||||
temps = f"temps de réponse: {toc - tic:0.4f} seconds"
|
|
||||||
result = '<img src=' + image_url + ' >'
|
|
||||||
|
|
||||||
|
|
||||||
return render_template("image.html", result=result, time=temps)
|
|
||||||
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 7.6 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 370 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB |
@ -1,213 +0,0 @@
|
|||||||
@font-face {
|
|
||||||
font-family: "ColfaxAI";
|
|
||||||
src: url(https://cdn.openai.com/API/fonts/ColfaxAIRegular.woff2)
|
|
||||||
format("woff2"),
|
|
||||||
url(https://cdn.openai.com/API/fonts/ColfaxAIRegular.woff) format("woff");
|
|
||||||
font-weight: normal;
|
|
||||||
font-style: normal;
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: "ColfaxAI";
|
|
||||||
src: url(https://cdn.openai.com/API/fonts/ColfaxAIBold.woff2) format("woff2"),
|
|
||||||
url(https://cdn.openai.com/API/fonts/ColfaxAIBold.woff) format("woff");
|
|
||||||
font-weight: bold;
|
|
||||||
font-style: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
body,
|
|
||||||
input {
|
|
||||||
font-size: 16px;
|
|
||||||
line-height: 24px;
|
|
||||||
color: #353740;
|
|
||||||
font-family: "ColfaxAI", Helvetica, sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
background-color: #24262B;
|
|
||||||
/* background: url("matrix.gif"); */
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
/* padding-top: 60px; */
|
|
||||||
min-height: 100%;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
width: 34px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
font-size: 32px;
|
|
||||||
line-height: 40px;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #fff;
|
|
||||||
margin: 16px 0 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
form {
|
|
||||||
margin-top: 10px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
width: 400px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="text"] {
|
|
||||||
padding: 12px 16px;
|
|
||||||
border: 1px solid #10a37f;
|
|
||||||
border-radius: 4px;
|
|
||||||
margin-top: 5px;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
::placeholder {
|
|
||||||
color: #8e8ea0;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="submit"] {
|
|
||||||
padding: 12px 0;
|
|
||||||
color: #fff;
|
|
||||||
background-color: #10a37f;
|
|
||||||
border: none;
|
|
||||||
border-radius: 4px;
|
|
||||||
text-align: center;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.result {
|
|
||||||
color: #10a37f;
|
|
||||||
max-width: 80%;
|
|
||||||
max-height: 80%;
|
|
||||||
border: 1px solid #10a37f;
|
|
||||||
border-radius: 4px;
|
|
||||||
cursor: pointer;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-top: 40px;
|
|
||||||
margin-left: 50px;
|
|
||||||
margin-right: 50px;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
label {
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spinner {
|
|
||||||
padding-top: 250px;
|
|
||||||
width: 30%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer {
|
|
||||||
padding: 10px 0;
|
|
||||||
/* position: fixed; */
|
|
||||||
color: #fff;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
select, input {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
option {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.settings {
|
|
||||||
border: 1px solid #10a37f;
|
|
||||||
border-radius: 4px;
|
|
||||||
text-align: center;
|
|
||||||
cursor: pointer;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.temps {
|
|
||||||
color: #fff;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div {
|
|
||||||
margin-left: 10px;
|
|
||||||
margin-top: 10px;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.jumbotron {
|
|
||||||
height: auto;
|
|
||||||
padding-top: 0.3em;
|
|
||||||
padding-bottom: 0.3em;
|
|
||||||
margin: 20px;
|
|
||||||
background-color: #E9ECEF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center; /* Centre verticalement */
|
|
||||||
align-items: center; /* Centre horizontalement */
|
|
||||||
}
|
|
||||||
|
|
||||||
a.nav-link {
|
|
||||||
color: cornflowerblue;
|
|
||||||
font-size: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
|
||||||
background-color: #f4f4f4;
|
|
||||||
margin-left: 5px;
|
|
||||||
margin-right: 5px;
|
|
||||||
margin-top: 5px;
|
|
||||||
border: 1px solid #000;
|
|
||||||
padding: 10px;
|
|
||||||
white-space: pre;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
padding: 12px 10px;
|
|
||||||
color: #fff;
|
|
||||||
background-color: #10a37f;
|
|
||||||
border: none;
|
|
||||||
border-radius: 4px;
|
|
||||||
text-align: center;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin-left: 5px;
|
|
||||||
margin-right: 5px;
|
|
||||||
margin-top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#loading-spinner {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
height: 100vh; /* Hauteur égale à la hauteur de la fenêtre */
|
|
||||||
position: fixed;
|
|
||||||
width: 100%;
|
|
||||||
background-color: rgba(255, 255, 255, 0.8); /* Fond semi-transparent */
|
|
||||||
z-index: 9999; /* S'assurer qu'il apparaît au-dessus du contenu */
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* #loading-spinner::after {
|
|
||||||
content: '';
|
|
||||||
display: inline-block;
|
|
||||||
width: 50px;
|
|
||||||
height: 50px;
|
|
||||||
border: 5px solid #3498db;
|
|
||||||
border-radius: 50%;
|
|
||||||
border-top: 5px solid #f3f3f3;
|
|
||||||
} */
|
|
||||||
|
|
||||||
/* @keyframes spin {
|
|
||||||
0% { transform: rotate(0deg); }
|
|
||||||
100% { transform: rotate(360deg); }
|
|
||||||
} */
|
|
||||||
@ -1,92 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
||||||
<!-- Bootstrap CSS -->
|
|
||||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='main.css') }}" />
|
|
||||||
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
|
||||||
|
|
||||||
<title>Garage AI</title>
|
|
||||||
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div id="loading-spinner">
|
|
||||||
<img src="{{ url_for('static', filename='loader.gif') }}" class="spinner">
|
|
||||||
<p>Loading ...</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h3>Garage AI</h3>
|
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
<nav class="navbar navbar-expand-lg navbar-light bg-light jumbotron">
|
|
||||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
|
||||||
<span class="navbar-toggler-icon"></span>
|
|
||||||
</button>
|
|
||||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
|
||||||
<ul class="navbar-nav mr-auto">
|
|
||||||
{% if request.path != '/' %}
|
|
||||||
<li class="nav-item active">
|
|
||||||
<a class="nav-link" href="{{ url_for('index') }}">CHAT <span class="sr-only">(current)</span></a>
|
|
||||||
</li>
|
|
||||||
{% elif request.path != '/image' %}
|
|
||||||
<li class="nav-item active">
|
|
||||||
<a class="nav-link" href="{{ url_for('image') }}">IMAGE <span class="sr-only">(current)</span></a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container jumbotron">
|
|
||||||
{% block content %}
|
|
||||||
{% endblock %}
|
|
||||||
<button id="copyButton" style="display: none;" onclick="copyCodeToClipboard()">Copier le code</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="footer">
|
|
||||||
<div class="temps">{{ time }}</div>
|
|
||||||
<div>
|
|
||||||
<img src="{{ url_for('static', filename='logo.png') }}" style="max-width: 50%;">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
|
|
||||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
|
|
||||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
|
|
||||||
<script src="https://cdn.jsdelivr.net/gh/MarketingPipeline/Markdown-Tag/markdown-tag-GitHub.js"></script>
|
|
||||||
<script>
|
|
||||||
const myForm = document.getElementById("form");
|
|
||||||
const loadingSpinner = document.getElementById("loading-spinner");
|
|
||||||
|
|
||||||
myForm.addEventListener("submit", function (event) {
|
|
||||||
loadingSpinner.style.display = "block";
|
|
||||||
});
|
|
||||||
|
|
||||||
function onPageLoaded() {
|
|
||||||
loadingSpinner.style.display = "none";
|
|
||||||
if (document.getElementsByTagName("code").length > 0)
|
|
||||||
{
|
|
||||||
var copyButton = document.getElementById("copyButton").style.display = "block"; // Affiche le bouton
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function copyCodeToClipboard() {
|
|
||||||
var codeToCopy = document.querySelector("code");
|
|
||||||
var textArea = document.createElement("textarea");
|
|
||||||
textArea.value = codeToCopy.textContent;
|
|
||||||
document.body.appendChild(textArea);
|
|
||||||
textArea.select();
|
|
||||||
document.execCommand("copy");
|
|
||||||
document.body.removeChild(textArea);
|
|
||||||
}
|
|
||||||
window.addEventListener("load", onPageLoaded);
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
<form action="/image" method="post" id="form">
|
|
||||||
<input type="text" name="image" placeholder="Description de l'image ici!" required />
|
|
||||||
<input type="submit" value="Go!" />
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{% if result %}
|
|
||||||
<div class="result">{{ result|safe }}</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
<form action="/" method="post" id="form">
|
|
||||||
<div class="settings">
|
|
||||||
<br>
|
|
||||||
<label for="valeur">Sélectionnez la température :</label>
|
|
||||||
<input type="range" id="valeur" name="temperature" min="0" max="1" step=".1">
|
|
||||||
<br>
|
|
||||||
<input type="text" name="question" placeholder="Ecrire la question ici!" required />
|
|
||||||
<br>
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
<input type="submit" value="Go!" />
|
|
||||||
<br>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{% if result %}
|
|
||||||
<div class="result">{{ result|safe }}</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
from app import app # Remplacez "votre_application" par le nom de votre application Flask
|
|
||||||
if __name__ == "__main__":
|
|
||||||
app.run()
|
|
||||||
@ -1,33 +1,54 @@
|
|||||||
version: '3.6'
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
|
||||||
local-ai:
|
web-ui:
|
||||||
image: quay.io/go-skynet/local-ai:latest
|
image: ghcr.io/open-webui/open-webui:main
|
||||||
container_name: local-ai
|
container_name: open-webui
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
- 8080:8080
|
- 3100:8080
|
||||||
env_file:
|
|
||||||
- .env
|
|
||||||
volumes:
|
volumes:
|
||||||
- ./models:/models:cached
|
- ./open-webui:/app/backend/data
|
||||||
- ./images:/tmp/generated/images
|
environment:
|
||||||
command: ["chmod -R 777 /tmp", "/usr/bin/local-ai"]
|
- "OLLAMA_BASE_URL=http://ollama:11434"
|
||||||
healthcheck:
|
- "ENV=prod"
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:8080/readyz"]
|
- "DEFAULT_MODELS=fr-FR"
|
||||||
interval: 1m
|
- "ENABLE_OAUTH_SIGNUP=true"
|
||||||
timeout: 20m
|
- "OAUTH_MERGE_ACCOUNTS_BY_EMAIL=true"
|
||||||
retries: 20
|
- "ENABLE_LOGIN_FORM=false"
|
||||||
|
- "ENABLE_COMMUNITY_SHARING=false"
|
||||||
|
- "ENABLE_OLLAMA_API=true"
|
||||||
|
- "ENV=prod"
|
||||||
|
- "GLOBAL_LOG_LEVEL=INFO"
|
||||||
|
- "WEBUI_AUTH=true"
|
||||||
|
- "OAUTH_USERNAME_CLAIM=name"
|
||||||
|
- "SCARF_NO_ANALYTICS=true"
|
||||||
|
- "DO_NOT_TRACK=true"
|
||||||
|
- "ANONYMIZED_TELEMETRY=false"
|
||||||
|
- "WEBUI_SESSION_COOKIE_SECURE=true"
|
||||||
|
- "RAG_EMBEDDING_MODEL_TRUST_REMOTE_CODE=false"
|
||||||
|
# OIDC
|
||||||
|
- "ENABLE_OPENAI_API=true"
|
||||||
|
- "OPENAI_API_KEY="
|
||||||
|
- "OAUTH_CLIENT_ID=ai"
|
||||||
|
- "OAUTH_CLIENT_SECRET=redacted"
|
||||||
|
- "OPENID_PROVIDER_URL=https://keycloak/auth/realms/realm/.well-known/openid-configuration"
|
||||||
|
- "OAUTH_PROVIDER_NAME=keycloak"
|
||||||
|
- "OAUTH_SCOPES=openid profile email"
|
||||||
|
|
||||||
flask-ui:
|
ollama:
|
||||||
build:
|
image: ollama/ollama
|
||||||
context: .
|
container_name: ollama
|
||||||
image: local/flask-ui:1.0
|
|
||||||
container_name: flask-ui
|
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
- 5000:5000
|
- 11434:11434
|
||||||
depends_on:
|
volumes:
|
||||||
local-ai:
|
- ./ollama:/root/.ollama
|
||||||
condition: service_healthy
|
|
||||||
|
# GPU USE
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
reservations:
|
||||||
|
devices:
|
||||||
|
- driver: nvidia
|
||||||
|
count: 1
|
||||||
|
capabilities: [gpu]
|
||||||
BIN
docs/modèles.png
Normal file
BIN
docs/modèles.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 77 KiB |
BIN
docs/workspace.png
Normal file
BIN
docs/workspace.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 78 KiB |
@ -1,10 +0,0 @@
|
|||||||
Flask==2.0.2
|
|
||||||
Jinja2==3.0.2
|
|
||||||
MarkupSafe==2.0.1
|
|
||||||
openpyxl==3.0.9
|
|
||||||
requests==2.26.0
|
|
||||||
urllib3==1.26.7
|
|
||||||
Werkzeug==2.0.2
|
|
||||||
gunicorn==21.2.0
|
|
||||||
itsdangerous==2.0.1
|
|
||||||
python-dotenv
|
|
||||||
Loading…
x
Reference in New Issue
Block a user