Commit
·
7676537
1
Parent(s):
c355ad8
Update
Browse files- app.py +6 -5
- config.yaml +10 -11
- model/ModelIntegrations.py +1 -1
- model/selector.py +1 -1
- pages/chatbot.py +55 -39
- rag.py +7 -2
- requirements.txt +3 -2
app.py
CHANGED
@@ -15,7 +15,7 @@ LOGO = "assets/logo.png"
|
|
15 |
|
16 |
def init_app():
|
17 |
|
18 |
-
|
19 |
|
20 |
if len(st.session_state) == 0:
|
21 |
# Define Vectore store strategy
|
@@ -24,7 +24,8 @@ def init_app():
|
|
24 |
|
25 |
st.session_state["messages"] = []
|
26 |
st.session_state["assistant"] = Rag(vectore_store=vs_manager)
|
27 |
-
st.session_state["data_dict"] =
|
|
|
28 |
|
29 |
|
30 |
def main():
|
@@ -36,9 +37,9 @@ def main():
|
|
36 |
st.logo(LOGO)
|
37 |
st.title(GROUP_NAME)
|
38 |
|
39 |
-
saved_documents = st.Page("pages/persistent_documents.py", title="
|
40 |
-
documents = st.Page("pages/documents.py", title="
|
41 |
-
prompt_system = st.Page("pages/prompt_system.py", title="Prompt
|
42 |
form = st.Page("pages/form.py", title="Paramètres", icon="📋")
|
43 |
chatbot = st.Page("pages/chatbot.py", title="Chatbot", icon="🤖")
|
44 |
|
|
|
15 |
|
16 |
def init_app():
|
17 |
|
18 |
+
config = getYamlConfig()
|
19 |
|
20 |
if len(st.session_state) == 0:
|
21 |
# Define Vectore store strategy
|
|
|
24 |
|
25 |
st.session_state["messages"] = []
|
26 |
st.session_state["assistant"] = Rag(vectore_store=vs_manager)
|
27 |
+
st.session_state["data_dict"] = config['variables']
|
28 |
+
st.session_state["prompt_system"] = config['prompt_system']
|
29 |
|
30 |
|
31 |
def main():
|
|
|
37 |
st.logo(LOGO)
|
38 |
st.title(GROUP_NAME)
|
39 |
|
40 |
+
saved_documents = st.Page("pages/persistent_documents.py", title="Documents de référence", icon="🗃️")
|
41 |
+
documents = st.Page("pages/documents.py", title="Documents de l'exploitation", icon="📂")
|
42 |
+
prompt_system = st.Page("pages/prompt_system.py", title="Prompt conseiller", icon="🖊️", default=True)
|
43 |
form = st.Page("pages/form.py", title="Paramètres", icon="📋")
|
44 |
chatbot = st.Page("pages/chatbot.py", title="Chatbot", icon="🤖")
|
45 |
|
config.yaml
CHANGED
@@ -17,28 +17,21 @@ variables:
|
|
17 |
key : param3
|
18 |
value :
|
19 |
|
20 |
-
prompt_template: "
|
21 |
-
Paramètre 1 : {param1}
|
22 |
-
Paramètre 2 : {param2}
|
23 |
-
Paramètre 3 : {param3}
|
24 |
-
|
25 |
-
Documents partagées : {commonContext}
|
26 |
-
|
27 |
-
Document utilisateur : {documentContext}
|
28 |
|
|
|
29 |
Tu es un expert en gestion agricole des grandes cultures dans les régions Centre, Ile de france, Hauts de france et Grand est.
|
30 |
Tu sais calculer une marge brute par hectare et un coût de revient par hectare à partir de documents statistiques agricoles français.
|
31 |
Si tu ne connais pas la réponse, ne réponds pas. Tu répondras toujours en Français.
|
32 |
|
33 |
-
Le coût de production ou coût de revient (CR) est calculé en additionnant toutes les charges opérationnelles (engrais, produits phytosanitaires, semences) (CO) par hectare ainsi que les charges de structure (main d'œuvre, foncier, matériel, bâtiment) (CS) par hectare selon la formule
|
34 |
|
35 |
Le coût de production en grande culture se situe en moyenne entre 500 € / hectare et 2000 € / hectare.
|
36 |
|
37 |
-
La marge brute (MB) est calculée en additionnant tous les produits (Ventes & indemnité, Aides couplées) (PR) issue de la culture et en soustrayant les charges opérationnelles (CO) selon la formule suivante
|
38 |
|
39 |
La marge brute (MB) en grande culture se situe en moyenne entre 300 € / hectare et 1500 € / hectare.
|
40 |
|
41 |
-
La marge nette (MN) est calculée en additionnant tous les produits (Ventes & indemnité, Aides couplées) (PR) issue de la culture et en soustrayant le coût de revient (CR) selon la formule suivante
|
42 |
|
43 |
La marge nette (MN) en grande culture se situe en moyenne entre 100 € / hectare et 800 € / hectare.
|
44 |
|
@@ -46,9 +39,15 @@ A partir des documents du contexte, tu vas produire des tableaux et des indicate
|
|
46 |
Pour le coût de production (CR), il est impératif de détailler l'ensemble des calculs poste par poste pour les charges opérationnelles (engrais, produits phytosanitaires, semences) (CO) et pour les charges de structure (main d'oeuvre, foncier, matériel, batiment) (CS).
|
47 |
|
48 |
La présentation sera effectuée dès que possible en format tableau. Si une information est demandée pour une superficie précise, les tableaux devront fournir, sur la première colonne, une information à l'hectare et sur la seconde, une information pour la superficie indiquée par l'utilisateur. Si aucune superficie n'est précisée par le client, l'information sera donnée par hectare.
|
|
|
49 |
|
|
|
50 |
{prompt_system}
|
51 |
|
|
|
|
|
|
|
|
|
52 |
Voici l'historique des messages : {messages}
|
53 |
La demande de l'utilisateur est : {query}
|
54 |
"
|
|
|
17 |
key : param3
|
18 |
value :
|
19 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
|
21 |
+
prompt_system: "
|
22 |
Tu es un expert en gestion agricole des grandes cultures dans les régions Centre, Ile de france, Hauts de france et Grand est.
|
23 |
Tu sais calculer une marge brute par hectare et un coût de revient par hectare à partir de documents statistiques agricoles français.
|
24 |
Si tu ne connais pas la réponse, ne réponds pas. Tu répondras toujours en Français.
|
25 |
|
26 |
+
Le coût de production ou coût de revient (CR) est calculé en additionnant toutes les charges opérationnelles (engrais, produits phytosanitaires, semences) (CO) par hectare ainsi que les charges de structure (main d'œuvre, foncier, matériel, bâtiment) (CS) par hectare selon la formule CR = CO + CS
|
27 |
|
28 |
Le coût de production en grande culture se situe en moyenne entre 500 € / hectare et 2000 € / hectare.
|
29 |
|
30 |
+
La marge brute (MB) est calculée en additionnant tous les produits (Ventes & indemnité, Aides couplées) (PR) issue de la culture et en soustrayant les charges opérationnelles (CO) selon la formule suivante MB = PR - CO
|
31 |
|
32 |
La marge brute (MB) en grande culture se situe en moyenne entre 300 € / hectare et 1500 € / hectare.
|
33 |
|
34 |
+
La marge nette (MN) est calculée en additionnant tous les produits (Ventes & indemnité, Aides couplées) (PR) issue de la culture et en soustrayant le coût de revient (CR) selon la formule suivante MN = PR - CR
|
35 |
|
36 |
La marge nette (MN) en grande culture se situe en moyenne entre 100 € / hectare et 800 € / hectare.
|
37 |
|
|
|
39 |
Pour le coût de production (CR), il est impératif de détailler l'ensemble des calculs poste par poste pour les charges opérationnelles (engrais, produits phytosanitaires, semences) (CO) et pour les charges de structure (main d'oeuvre, foncier, matériel, batiment) (CS).
|
40 |
|
41 |
La présentation sera effectuée dès que possible en format tableau. Si une information est demandée pour une superficie précise, les tableaux devront fournir, sur la première colonne, une information à l'hectare et sur la seconde, une information pour la superficie indiquée par l'utilisateur. Si aucune superficie n'est précisée par le client, l'information sera donnée par hectare.
|
42 |
+
"
|
43 |
|
44 |
+
prompt_template: "
|
45 |
{prompt_system}
|
46 |
|
47 |
+
Documents partagées : {commonContext}
|
48 |
+
|
49 |
+
Document utilisateur : {documentContext}
|
50 |
+
|
51 |
Voici l'historique des messages : {messages}
|
52 |
La demande de l'utilisateur est : {query}
|
53 |
"
|
model/ModelIntegrations.py
CHANGED
@@ -2,7 +2,7 @@ import os
|
|
2 |
|
3 |
from .ModelStrategy import ModelStrategy
|
4 |
|
5 |
-
from
|
6 |
from langchain_mistralai.chat_models import ChatMistralAI
|
7 |
from langchain_anthropic import ChatAnthropic
|
8 |
|
|
|
2 |
|
3 |
from .ModelStrategy import ModelStrategy
|
4 |
|
5 |
+
from langchain_openai import ChatOpenAI
|
6 |
from langchain_mistralai.chat_models import ChatMistralAI
|
7 |
from langchain_anthropic import ChatAnthropic
|
8 |
|
model/selector.py
CHANGED
@@ -38,5 +38,5 @@ def ModelSelector():
|
|
38 |
|
39 |
if(st.session_state["assistant"]):
|
40 |
splitter = model_mapping[selected_model_option].split(".")
|
41 |
-
st.session_state["assistant"].setModel(ModelManager().get_model(splitter[0], splitter[1]))
|
42 |
|
|
|
38 |
|
39 |
if(st.session_state["assistant"]):
|
40 |
splitter = model_mapping[selected_model_option].split(".")
|
41 |
+
st.session_state["assistant"].setModel(ModelManager().get_model(splitter[0], splitter[1]), splitter[1])
|
42 |
|
pages/chatbot.py
CHANGED
@@ -1,66 +1,82 @@
|
|
1 |
import streamlit as st
|
2 |
-
import
|
3 |
-
import os
|
4 |
-
from streamlit_chat import message
|
5 |
from model import selector
|
|
|
|
|
6 |
|
7 |
def display_messages():
|
8 |
-
for i, (msg, is_user) in enumerate(st.session_state["messages"]):
|
9 |
-
message(msg, is_user=is_user, key=str(i))
|
10 |
-
st.session_state["thinking_spinner"] = st.empty()
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
|
|
|
19 |
|
20 |
-
|
21 |
-
|
22 |
-
|
|
|
|
|
|
|
|
|
|
|
23 |
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
agent_text = st.session_state["assistant"].ask(user_text, prompt_sys, st.session_state["messages"] if "messages" in st.session_state else [], variables=st.session_state["data_dict"])
|
28 |
|
29 |
-
st.session_state["messages"].append((user_text, True))
|
30 |
-
st.session_state["messages"].append((agent_text, False))
|
31 |
|
32 |
-
@st.dialog("Choisissez votre question prédéfinie")
|
33 |
def show_prompts():
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
for categroy in yaml_data
|
39 |
-
|
|
|
|
|
|
|
|
|
40 |
|
41 |
-
for item in yaml_data['prompts'][categroy]:
|
42 |
-
if st.button(item, key=f"button_{item}"):
|
43 |
-
st.session_state["user_input"] = item
|
44 |
-
st.rerun()
|
45 |
|
46 |
def page():
|
47 |
st.subheader("Posez vos questions")
|
48 |
|
49 |
-
if "user_input" in st.session_state:
|
50 |
-
process_input()
|
51 |
-
|
52 |
if "assistant" not in st.session_state:
|
53 |
st.text("Assistant non initialisé")
|
54 |
-
|
55 |
-
# Bouton pour ouvrir la modale
|
56 |
-
if st.button("Questions pré-définies"):
|
57 |
-
show_prompts()
|
58 |
|
|
|
|
|
|
|
|
|
59 |
|
|
|
|
|
|
|
|
|
60 |
selector.ModelSelector()
|
61 |
|
|
|
62 |
display_messages()
|
63 |
|
64 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
|
66 |
page()
|
|
|
1 |
import streamlit as st
|
2 |
+
from langchain_core.messages import AIMessage, HumanMessage
|
|
|
|
|
3 |
from model import selector
|
4 |
+
from util import getYamlConfig
|
5 |
+
from st_copy_to_clipboard import st_copy_to_clipboard
|
6 |
|
7 |
def display_messages():
|
|
|
|
|
|
|
8 |
|
9 |
+
for i, message in enumerate(st.session_state.chat_history):
|
10 |
+
if isinstance(message, AIMessage):
|
11 |
+
with st.chat_message("AI"):
|
12 |
+
# Display the model from the kwargs
|
13 |
+
model = message.kwargs.get("model", "Unknown Model") # Get the model, default to "Unknown Model"
|
14 |
+
st.write(f"**Model :** {model}")
|
15 |
+
st.markdown(message.content)
|
16 |
+
st_copy_to_clipboard(message.content,key=f"message_{i}")
|
17 |
+
|
18 |
+
elif isinstance(message, HumanMessage):
|
19 |
+
with st.chat_message("Moi"):
|
20 |
+
st.write(message.content)
|
21 |
|
|
|
|
|
|
|
|
|
|
|
22 |
|
23 |
+
def launchQuery(query: str = None):
|
24 |
|
25 |
+
# Initialize the assistant's response
|
26 |
+
full_response = st.write_stream(
|
27 |
+
st.session_state["assistant"].ask(
|
28 |
+
query,
|
29 |
+
prompt_system=st.session_state.prompt_system,
|
30 |
+
messages=st.session_state["chat_history"] if "chat_history" in st.session_state else [],
|
31 |
+
variables=st.session_state["data_dict"]
|
32 |
+
))
|
33 |
|
34 |
+
# Temporary placeholder AI message in chat history
|
35 |
+
st.session_state["chat_history"].append(AIMessage(content=full_response, kwargs={"model": st.session_state["assistant"].getReadableModel()}))
|
36 |
+
st.rerun()
|
|
|
37 |
|
|
|
|
|
38 |
|
|
|
39 |
def show_prompts():
|
40 |
+
yaml_data = getYamlConfig()["prompts"]
|
41 |
+
|
42 |
+
expander = st.expander("Prompts pré-définis")
|
43 |
+
|
44 |
+
for categroy in yaml_data:
|
45 |
+
expander.write(categroy.capitalize())
|
46 |
+
|
47 |
+
for item in yaml_data[categroy]:
|
48 |
+
if expander.button(item, key=f"button_{item}"):
|
49 |
+
launchQuery(item)
|
50 |
|
|
|
|
|
|
|
|
|
51 |
|
52 |
def page():
|
53 |
st.subheader("Posez vos questions")
|
54 |
|
|
|
|
|
|
|
55 |
if "assistant" not in st.session_state:
|
56 |
st.text("Assistant non initialisé")
|
|
|
|
|
|
|
|
|
57 |
|
58 |
+
if "chat_history" not in st.session_state:
|
59 |
+
st.session_state["chat_history"] = []
|
60 |
+
|
61 |
+
st.markdown("<style>iframe{height:50px;}</style>", unsafe_allow_html=True)
|
62 |
|
63 |
+
# Collpase for default prompts
|
64 |
+
show_prompts()
|
65 |
+
|
66 |
+
# Models selector
|
67 |
selector.ModelSelector()
|
68 |
|
69 |
+
# Displaying messages
|
70 |
display_messages()
|
71 |
|
72 |
+
|
73 |
+
user_query = st.chat_input("")
|
74 |
+
if user_query is not None and user_query != "":
|
75 |
+
|
76 |
+
st.session_state["chat_history"].append(HumanMessage(content=user_query))
|
77 |
+
|
78 |
+
# Stream and display response
|
79 |
+
launchQuery(user_query)
|
80 |
+
|
81 |
|
82 |
page()
|
rag.py
CHANGED
@@ -23,6 +23,7 @@ class Rag:
|
|
23 |
document_vector_store = None
|
24 |
retriever = None
|
25 |
chain = None
|
|
|
26 |
|
27 |
def __init__(self, vectore_store=None):
|
28 |
|
@@ -36,9 +37,13 @@ class Rag:
|
|
36 |
|
37 |
self.vector_store = vectore_store
|
38 |
|
39 |
-
def setModel(self, model):
|
40 |
self.model = model
|
|
|
41 |
|
|
|
|
|
|
|
42 |
def ingestToDb(self, file_path: str, filename: str):
|
43 |
|
44 |
docs = PyPDFLoader(file_path=file_path).load()
|
@@ -105,7 +110,7 @@ class Rag:
|
|
105 |
chain_input.update(extra_vars)
|
106 |
|
107 |
|
108 |
-
return self.chain.
|
109 |
|
110 |
def clear(self):
|
111 |
self.document_vector_store = None
|
|
|
23 |
document_vector_store = None
|
24 |
retriever = None
|
25 |
chain = None
|
26 |
+
readableModelName = ""
|
27 |
|
28 |
def __init__(self, vectore_store=None):
|
29 |
|
|
|
37 |
|
38 |
self.vector_store = vectore_store
|
39 |
|
40 |
+
def setModel(self, model, readableModelName = ""):
|
41 |
self.model = model
|
42 |
+
self.readableModelName = readableModelName
|
43 |
|
44 |
+
def getReadableModel(self):
|
45 |
+
return self.readableModelName
|
46 |
+
|
47 |
def ingestToDb(self, file_path: str, filename: str):
|
48 |
|
49 |
docs = PyPDFLoader(file_path=file_path).load()
|
|
|
110 |
chain_input.update(extra_vars)
|
111 |
|
112 |
|
113 |
+
return self.chain.stream(chain_input)
|
114 |
|
115 |
def clear(self):
|
116 |
self.document_vector_store = None
|
requirements.txt
CHANGED
@@ -12,9 +12,10 @@ typing-extensions
|
|
12 |
langchain
|
13 |
langchain-openai
|
14 |
langchain-community
|
|
|
15 |
langchain-pinecone
|
16 |
langchain_mistralai
|
17 |
langchain_anthropic
|
18 |
-
langchain-experimental
|
19 |
llamaapi
|
20 |
-
pyyaml
|
|
|
|
12 |
langchain
|
13 |
langchain-openai
|
14 |
langchain-community
|
15 |
+
langchain-experimental
|
16 |
langchain-pinecone
|
17 |
langchain_mistralai
|
18 |
langchain_anthropic
|
|
|
19 |
llamaapi
|
20 |
+
pyyaml
|
21 |
+
st_copy_to_clipboard
|