cd@bziiit.com
commited on
Commit
·
59ba192
1
Parent(s):
e39ca6e
Refactor : pass variable & prompt template by UAML file
Browse files- README.md +65 -1
- app.py +16 -25
- config.yaml +24 -1
- pages/chatbot.py +1 -1
- pages/form.py +7 -3
- rag.py +12 -5
- requirements.txt +1 -4
- util.py +7 -0
README.md
CHANGED
@@ -9,4 +9,68 @@ app_file: app.py
|
|
9 |
pinned: false
|
10 |
---
|
11 |
|
12 |
-
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
pinned: false
|
10 |
---
|
11 |
|
12 |
+
<!-- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference -->
|
13 |
+
|
14 |
+
# Application Template - README
|
15 |
+
|
16 |
+
## Introduction
|
17 |
+
|
18 |
+
Cette application sert de base/template pour en déployer d'autres sur le même modèle via Huggingface. Elle est facilement duplicable en dupliquant l'espace. Elle est décomposée en plusieurs sections pour offrir une gestion complète des documents et des dialogues avec une Intelligence Artificielle (IA).
|
19 |
+
|
20 |
+
### Structure de l'application
|
21 |
+
|
22 |
+
L'application est structurée en trois parties principales :
|
23 |
+
|
24 |
+
- **Documents**
|
25 |
+
- *Communs*
|
26 |
+
- *Vos Documents*
|
27 |
+
- **Configurations**
|
28 |
+
- *Prompt système*
|
29 |
+
- *Paramètres*
|
30 |
+
- **Dialogue**
|
31 |
+
- *Chatbot*
|
32 |
+
|
33 |
+
### Fonctionnement des sections
|
34 |
+
|
35 |
+
#### 1. Documents
|
36 |
+
|
37 |
+
- **Documents Communs** :
|
38 |
+
Cette section permet de déposer des documents accessibles à tous les utilisateurs de l'application. Ces documents sont vectorisés et stockés dans une base de données vectorielle (voir section dédiée). Ils seront explorés lors des interactions avec l'IA.
|
39 |
+
|
40 |
+
- **Vos Documents** :
|
41 |
+
Chaque utilisateur peut uploader ses propres documents, qui seront pris en compte pendant sa session. Ces documents sont temporaires et ne sont accessibles que durant la session active de l'utilisateur.
|
42 |
+
|
43 |
+
#### 2. Configurations
|
44 |
+
|
45 |
+
- **Prompt système** :
|
46 |
+
Cette section permet de configurer le *prompt système* utilisé lors des conversations avec l'IA. Ce prompt influence le comportement de l'IA pendant le dialogue.
|
47 |
+
|
48 |
+
- **Paramètres** :
|
49 |
+
Ici, vous pouvez ajuster les paramètres dynamiques de l'application, tels que les préférences utilisateurs ou les options spécifiques à votre usage.
|
50 |
+
|
51 |
+
#### 3. Dialogue
|
52 |
+
|
53 |
+
- **Chatbot** :
|
54 |
+
Une interface de discussion avec l'IA, où il est possible de choisir le modèle d'IA avec lequel interagir. Vous pouvez aussi commencer la conversation à partir d'un *prompt* pré-défini.
|
55 |
+
|
56 |
+
## Base de Données Vectorielle
|
57 |
+
|
58 |
+
Les documents (communs et personnels) sont vectorisés et stockés dans une base de données vectorielle. Cela permet à l'IA de rechercher et d'explorer ces documents pour enrichir les conversations en fonction des informations disponibles.
|
59 |
+
|
60 |
+
## Paramètres Dynamiques
|
61 |
+
|
62 |
+
Cette application permet la gestion de paramètres dynamiques configurables via l'interface utilisateur. Ces paramètres modifient le comportement de l'application et de l'IA en fonction des besoins de l'utilisateur.
|
63 |
+
|
64 |
+
## Prompts par Défaut
|
65 |
+
|
66 |
+
Des *prompts* par défaut peuvent être définis pour démarrer les conversations avec l'IA. Ces *prompts* sont personnalisables dans la section "Prompt système" des **Configurations**.
|
67 |
+
|
68 |
+
## Déploiement
|
69 |
+
|
70 |
+
Pour déployer cette application sur Huggingface :
|
71 |
+
|
72 |
+
1. Dupliquez l'espace Huggingface existant.
|
73 |
+
2. Configurez les fichiers de l'application (paramètres, prompts par défaut, etc.).
|
74 |
+
3. Assurez-vous que la base de données vectorielle est correctement co
|
75 |
+
|
76 |
+
|
app.py
CHANGED
@@ -6,18 +6,16 @@ from rag import Rag
|
|
6 |
from vectore_store.PineconeConnector import PineconeConnector
|
7 |
from vectore_store.VectoreStoreManager import VectoreStoreManager
|
8 |
|
|
|
9 |
|
10 |
load_dotenv()
|
11 |
|
12 |
GROUP_NAME = os.environ.get("APP_NAME")
|
13 |
-
LOGO = "assets/
|
14 |
|
15 |
def init_app():
|
16 |
-
|
17 |
-
|
18 |
-
variables = os.environ.get('VARIABLES')
|
19 |
-
keys = variables.split(',')
|
20 |
-
data_dict = {key: '' for key in keys} # Initialize with empty values
|
21 |
|
22 |
if len(st.session_state) == 0:
|
23 |
# Define Vectore store strategy
|
@@ -46,25 +44,18 @@ def main():
|
|
46 |
|
47 |
pg = st.navigation(
|
48 |
{
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
}
|
61 |
-
# [
|
62 |
-
# saved_documents,
|
63 |
-
# prompt_system,
|
64 |
-
# documents,
|
65 |
-
# form,
|
66 |
-
# chatbot
|
67 |
-
# ]
|
68 |
)
|
69 |
|
70 |
pg.run()
|
|
|
6 |
from vectore_store.PineconeConnector import PineconeConnector
|
7 |
from vectore_store.VectoreStoreManager import VectoreStoreManager
|
8 |
|
9 |
+
from util import getYamlConfig
|
10 |
|
11 |
load_dotenv()
|
12 |
|
13 |
GROUP_NAME = os.environ.get("APP_NAME")
|
14 |
+
LOGO = "assets/logo.png"
|
15 |
|
16 |
def init_app():
|
17 |
+
|
18 |
+
data_dict = getYamlConfig()['variables']
|
|
|
|
|
|
|
19 |
|
20 |
if len(st.session_state) == 0:
|
21 |
# Define Vectore store strategy
|
|
|
44 |
|
45 |
pg = st.navigation(
|
46 |
{
|
47 |
+
"Documents": [
|
48 |
+
saved_documents,
|
49 |
+
documents,
|
50 |
+
],
|
51 |
+
"Configurations": [
|
52 |
+
prompt_system,
|
53 |
+
form,
|
54 |
+
],
|
55 |
+
"Dialogue": [
|
56 |
+
chatbot
|
57 |
+
],
|
58 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
)
|
60 |
|
61 |
pg.run()
|
config.yaml
CHANGED
@@ -9,4 +9,27 @@ prompts:
|
|
9 |
- "Comment fonctionne la rotation des cultures et pourquoi est-elle importante ?"
|
10 |
- "Explique les avantages de l'irrigation goutte à goutte pour les cultures."
|
11 |
- "Quels sont les types de fertilisants les plus utilisés en agriculture et leurs impacts ?"
|
12 |
-
- "Quelles sont les techniques de lutte biologique contre les nuisibles ?"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
- "Comment fonctionne la rotation des cultures et pourquoi est-elle importante ?"
|
10 |
- "Explique les avantages de l'irrigation goutte à goutte pour les cultures."
|
11 |
- "Quels sont les types de fertilisants les plus utilisés en agriculture et leurs impacts ?"
|
12 |
+
- "Quelles sont les techniques de lutte biologique contre les nuisibles ?"
|
13 |
+
|
14 |
+
variables:
|
15 |
+
- label : Mon paramètre 1
|
16 |
+
key : param1
|
17 |
+
value :
|
18 |
+
- label : Mon paramètre 2
|
19 |
+
key : param2
|
20 |
+
value :
|
21 |
+
- label : Mon paramètre 3
|
22 |
+
key : param3
|
23 |
+
value :
|
24 |
+
|
25 |
+
prompt_template: "
|
26 |
+
Paramètre 1 : {param1}
|
27 |
+
Paramètre 2 : {param2}
|
28 |
+
Paramètre 3 : {param3}
|
29 |
+
|
30 |
+
Documents partagées : {commonContext}
|
31 |
+
Document de référence : {documentContext}
|
32 |
+
|
33 |
+
Voici l'historique des messages : {messages}
|
34 |
+
Les attentes de l'utilisateur sont : {query}
|
35 |
+
"
|
pages/chatbot.py
CHANGED
@@ -12,7 +12,7 @@ def display_messages():
|
|
12 |
|
13 |
# Charger les données YAML
|
14 |
def load_yaml(file_path):
|
15 |
-
with open(file_path, 'r') as file:
|
16 |
data = yaml.safe_load(file)
|
17 |
return data
|
18 |
|
|
|
12 |
|
13 |
# Charger les données YAML
|
14 |
def load_yaml(file_path):
|
15 |
+
with open(file_path, 'r', encoding='utf-8') as file:
|
16 |
data = yaml.safe_load(file)
|
17 |
return data
|
18 |
|
pages/form.py
CHANGED
@@ -3,8 +3,12 @@ import streamlit as st
|
|
3 |
def page():
|
4 |
st.subheader("Définissez vos paramètres")
|
5 |
|
6 |
-
|
7 |
-
|
8 |
-
|
|
|
|
|
|
|
|
|
9 |
|
10 |
page()
|
|
|
3 |
def page():
|
4 |
st.subheader("Définissez vos paramètres")
|
5 |
|
6 |
+
# Boucle pour créer des inputs basés sur data_dict (qui est une liste ici)
|
7 |
+
for param in st.session_state.data_dict:
|
8 |
+
# Utilisation de la clé 'label' et 'value' pour afficher et récupérer les valeurs
|
9 |
+
value = st.text_input(label=param['label'], value=param['value'] if param['value'] else "")
|
10 |
+
|
11 |
+
# Mettre à jour la valeur dans le dictionnaire après la saisie utilisateur
|
12 |
+
param['value'] = value
|
13 |
|
14 |
page()
|
rag.py
CHANGED
@@ -10,10 +10,9 @@ from langchain.text_splitter import RecursiveCharacterTextSplitter
|
|
10 |
from langchain.schema.runnable import RunnablePassthrough
|
11 |
from langchain.prompts import PromptTemplate
|
12 |
from langchain_community.vectorstores.utils import filter_complex_metadata
|
13 |
-
#add new import
|
14 |
from langchain_community.document_loaders.csv_loader import CSVLoader
|
15 |
|
16 |
-
from
|
17 |
|
18 |
|
19 |
# load .env in local dev
|
@@ -31,6 +30,8 @@ class Rag:
|
|
31 |
self.embedding = MistralAIEmbeddings(model="mistral-embed", mistral_api_key=env_api_key)
|
32 |
|
33 |
self.text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100, length_function=len)
|
|
|
|
|
34 |
self.prompt = PromptTemplate.from_template(base_template)
|
35 |
|
36 |
self.vector_store = vectore_store
|
@@ -71,7 +72,7 @@ class Rag:
|
|
71 |
},
|
72 |
)
|
73 |
|
74 |
-
def ask(self, query: str, messages: list, variables:
|
75 |
self.chain = self.prompt | self.model | StrOutputParser()
|
76 |
|
77 |
# Retrieve the context document
|
@@ -94,9 +95,15 @@ class Rag:
|
|
94 |
# Suppression des valeurs nulles (facultatif)
|
95 |
chain_input = {k: v for k, v in chain_input.items() if v is not None}
|
96 |
|
97 |
-
#
|
98 |
-
|
|
|
|
|
|
|
|
|
|
|
99 |
|
|
|
100 |
return self.chain.invoke(chain_input)
|
101 |
|
102 |
def clear(self):
|
|
|
10 |
from langchain.schema.runnable import RunnablePassthrough
|
11 |
from langchain.prompts import PromptTemplate
|
12 |
from langchain_community.vectorstores.utils import filter_complex_metadata
|
|
|
13 |
from langchain_community.document_loaders.csv_loader import CSVLoader
|
14 |
|
15 |
+
from util import getYamlConfig
|
16 |
|
17 |
|
18 |
# load .env in local dev
|
|
|
30 |
self.embedding = MistralAIEmbeddings(model="mistral-embed", mistral_api_key=env_api_key)
|
31 |
|
32 |
self.text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100, length_function=len)
|
33 |
+
|
34 |
+
base_template = getYamlConfig()['prompt_template']
|
35 |
self.prompt = PromptTemplate.from_template(base_template)
|
36 |
|
37 |
self.vector_store = vectore_store
|
|
|
72 |
},
|
73 |
)
|
74 |
|
75 |
+
def ask(self, query: str, messages: list, variables: list = None):
|
76 |
self.chain = self.prompt | self.model | StrOutputParser()
|
77 |
|
78 |
# Retrieve the context document
|
|
|
95 |
# Suppression des valeurs nulles (facultatif)
|
96 |
chain_input = {k: v for k, v in chain_input.items() if v is not None}
|
97 |
|
98 |
+
# Si des variables sous forme de liste sont fournies
|
99 |
+
if variables:
|
100 |
+
# Convertir la liste en dictionnaire avec 'key' comme clé et 'value' comme valeur
|
101 |
+
extra_vars = {item['key']: item['value'] for item in variables if 'key' in item and 'value' in item}
|
102 |
+
|
103 |
+
# Fusionner avec chain_input
|
104 |
+
chain_input.update(extra_vars)
|
105 |
|
106 |
+
|
107 |
return self.chain.invoke(chain_input)
|
108 |
|
109 |
def clear(self):
|
requirements.txt
CHANGED
@@ -1,16 +1,13 @@
|
|
1 |
streamlit==1.37.0
|
2 |
streamlit_chat
|
3 |
-
# abc
|
4 |
python-dotenv
|
5 |
pymupdf
|
|
|
6 |
python-multipart
|
7 |
pydantic
|
8 |
-
langchain-pinecone
|
9 |
pinecone-notebooks
|
10 |
pinecone-client[grpc]
|
11 |
async-timeout
|
12 |
-
pymupdf
|
13 |
-
python-dotenv
|
14 |
typing-extensions
|
15 |
langchain
|
16 |
langchain-openai
|
|
|
1 |
streamlit==1.37.0
|
2 |
streamlit_chat
|
|
|
3 |
python-dotenv
|
4 |
pymupdf
|
5 |
+
pypdf
|
6 |
python-multipart
|
7 |
pydantic
|
|
|
8 |
pinecone-notebooks
|
9 |
pinecone-client[grpc]
|
10 |
async-timeout
|
|
|
|
|
11 |
typing-extensions
|
12 |
langchain
|
13 |
langchain-openai
|
util.py
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import yaml
|
3 |
+
|
4 |
+
def getYamlConfig():
|
5 |
+
file_path = os.path.join(os.path.dirname(__file__), 'config.yaml')
|
6 |
+
with open(file_path, 'r', encoding='utf-8') as file:
|
7 |
+
return yaml.safe_load(file)
|