ionosphere commited on
Commit
7676537
·
1 Parent(s): c355ad8
Files changed (7) hide show
  1. app.py +6 -5
  2. config.yaml +10 -11
  3. model/ModelIntegrations.py +1 -1
  4. model/selector.py +1 -1
  5. pages/chatbot.py +55 -39
  6. rag.py +7 -2
  7. requirements.txt +3 -2
app.py CHANGED
@@ -15,7 +15,7 @@ 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
@@ -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"] = 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="Communs", icon="🗃️")
40
- documents = st.Page("pages/documents.py", title="Vos documents", icon="📂")
41
- prompt_system = st.Page("pages/prompt_system.py", title="Prompt système", icon="🖊️", default=True)
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 : CR = CO + CS
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 : MB = PR - CO
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 : MN = PR - CR
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 langchain_community.chat_models import ChatOpenAI
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 yaml
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
- def process_input():
21
- if "user_input" in st.session_state and st.session_state["user_input"] and len(st.session_state["user_input"].strip()) > 0:
22
- user_text = st.session_state["user_input"].strip()
 
 
 
 
 
23
 
24
- prompt_sys = st.session_state.prompt_system if 'prompt_system' in st.session_state and st.session_state.prompt_system != '' else ""
25
-
26
- with st.session_state["thinking_spinner"], st.spinner(f"Je réfléchis"):
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
- file_path = os.path.join(os.path.dirname(__file__), '..', 'config.yaml')
35
- yaml_data = load_yaml(file_path)
36
-
37
- # Boucle à travers les éléments YAML
38
- for categroy in yaml_data['prompts']: # Exemple avec la catégorie conversation
39
- st.write(categroy.capitalize())
 
 
 
 
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
- st.text_input("Message", key="user_input", on_change=process_input)
 
 
 
 
 
 
 
 
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.invoke(chain_input)
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