Ilyas KHIAT commited on
Commit
38cf0bb
1 Parent(s): ce4fc2a

chatbot and bug fix

Browse files
Files changed (4) hide show
  1. app.py +6 -1
  2. chat_with_pps.py +75 -0
  3. partie_prenante_carte.py +64 -17
  4. pp_viz.py +9 -9
app.py CHANGED
@@ -20,6 +20,7 @@ from collaborons import display_company_selection_for_materiality,display_materi
20
  from documentations import display_documentation
21
  from RAG_PDF_WEB import rag_pdf_web
22
  from prompt import get_prompts_list,prompt_execution,execute_prompt
 
23
 
24
  def main():
25
  st.markdown(":point_left: Cliquez pour vous inspirer", unsafe_allow_html=True)
@@ -71,7 +72,8 @@ def main():
71
  "Générations de contenus RSE",
72
  "Parties prenantes",
73
  "Cartographie",
74
- "Matrice de matérialité"
 
75
  ]
76
  )
77
 
@@ -95,6 +97,9 @@ def main():
95
  if selected_company:
96
  display_materiality_matrix(selected_company, data, bziiit_data)
97
 
 
 
 
98
  elif ia_mode == "Audit flash RSE de vos contenus":
99
  rag_pdf_web()
100
 
 
20
  from documentations import display_documentation
21
  from RAG_PDF_WEB import rag_pdf_web
22
  from prompt import get_prompts_list,prompt_execution,execute_prompt
23
+ from chat_with_pps import display_chat
24
 
25
  def main():
26
  st.markdown(":point_left: Cliquez pour vous inspirer", unsafe_allow_html=True)
 
72
  "Générations de contenus RSE",
73
  "Parties prenantes",
74
  "Cartographie",
75
+ "Matrice de matérialité",
76
+ "Chatbot Matrice de matérialité"
77
  ]
78
  )
79
 
 
97
  if selected_company:
98
  display_materiality_matrix(selected_company, data, bziiit_data)
99
 
100
+ elif ia_mode == "Chatbot Matrice de matérialité":
101
+ display_chat()
102
+
103
  elif ia_mode == "Audit flash RSE de vos contenus":
104
  rag_pdf_web()
105
 
chat_with_pps.py ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from langchain_core.messages import AIMessage, HumanMessage
3
+ from langchain_openai import ChatOpenAI
4
+ from dotenv import load_dotenv
5
+ from langchain_core.output_parsers import StrOutputParser
6
+ from langchain_core.prompts import ChatPromptTemplate
7
+
8
+
9
+ load_dotenv()
10
+
11
+ def format_context(df,brand_name):
12
+ formatted_string = "le nom de la marque est " + brand_name + "\n" + "Les parties prenantes et leur pouvoir en pourcentage sont les suivants:\n"
13
+ for index, row in df.iterrows():
14
+ formatted_string += f"{row['partie_prenante']}: {row['pouvoir']}%\n"
15
+ return formatted_string
16
+
17
+
18
+
19
+ def get_response(user_query, chat_history, context):
20
+
21
+ template = """
22
+ Fournir des réponses précises et contextuelles en agissant comme un expert en affaires, en utilisant le contexte des parties prenantes et leur pouvoir en pourcentage pour expliquer les implications pour la marque. Le modèle doit connecter les informations du contexte et de l'historique de la conversation pour donner une réponse éclairée à la dernière question posée.
23
+
24
+ Contexte: {context}
25
+
26
+ Chat history: {chat_history}
27
+
28
+ User question: {user_question}
29
+ """
30
+
31
+ prompt = ChatPromptTemplate.from_template(template)
32
+
33
+ llm = ChatOpenAI(model="gpt-4o")
34
+
35
+ chain = prompt | llm | StrOutputParser()
36
+
37
+ return chain.stream({
38
+ "context": context,
39
+ "chat_history": chat_history,
40
+ "user_question": user_query,
41
+ })
42
+
43
+ def display_chat():
44
+ # app config
45
+ st.title("Chatbot")
46
+
47
+ # session state
48
+ if "chat_history" not in st.session_state:
49
+ st.session_state.chat_history = [
50
+ AIMessage(content="Salut, pose-moi des questions sur tes parties prenantes."),
51
+ ]
52
+
53
+
54
+ # conversation
55
+ for message in st.session_state.chat_history:
56
+ if isinstance(message, AIMessage):
57
+ with st.chat_message("AI"):
58
+ st.write(message.content)
59
+ elif isinstance(message, HumanMessage):
60
+ with st.chat_message("Moi"):
61
+ st.write(message.content)
62
+
63
+ # user input
64
+ user_query = st.chat_input("Par ici...")
65
+ if user_query is not None and user_query != "":
66
+ st.session_state.chat_history.append(HumanMessage(content=user_query))
67
+
68
+ with st.chat_message("Moi"):
69
+ st.markdown(user_query)
70
+
71
+ with st.chat_message("AI"):
72
+ response = st.write_stream(get_response(user_query, st.session_state.chat_history,format_context(st.session_state['partie_prenante_grouped'],st.session_state['Nom de la marque'])))
73
+
74
+
75
+ st.session_state.chat_history.append(AIMessage(content=response))
partie_prenante_carte.py CHANGED
@@ -71,26 +71,22 @@ def fill_promptQ_template(input_variables, template):
71
  prompt = PromptTemplate(input_variables=["BRAND_NAME","BRAND_DESCRIPTION"], template=template)
72
  return prompt.format(BRAND_NAME=input_variables["BRAND_NAME"], BRAND_DESCRIPTION=input_variables["BRAND_DESCRIPTION"])
73
 
74
- template_extraction_PP = '''
75
- Objectif : identifiez et proposez tout les noms de marques qui serviront comme partie prenante de la marque suivante pour développer un marketing de coopération (co-op marketing)
76
-
77
- Le nom de la marque de référence est le suivant : {BRAND_NAME}
78
- Son activité est la suivante : {BRAND_DESCRIPTION}
79
-
80
- TA REPONSE DOIT ETRE SOUS FORME DE LISTE DE NOMS DE MARQUES
81
- '''
82
- #don't forget to add the input variables from the maim function
83
-
84
  def text_to_list(text):
85
  lines = text.replace("- ","").split('\n')
86
 
87
  lines = [line.split() for line in lines]
88
  items = [[' '.join(line[:-1]),line[-1]] for line in lines]
 
89
  # Assuming `items` is the list of items
90
  for item in items:
91
  item[1] = re.sub(r'\D', '', item[1])
92
  return items
93
 
 
 
 
 
 
94
  def display_list_urls():
95
  for index, item in enumerate(st.session_state["urls"]):
96
  emp = st.empty() # Create an empty placeholder
@@ -98,6 +94,8 @@ def display_list_urls():
98
 
99
  # Button to delete the entry, placed in the second column
100
  if col2.button("❌", key=f"but{index}"):
 
 
101
  del st.session_state.urls[index]
102
  del st.session_state["parties_prenantes"][index]
103
  st.experimental_rerun() # Rerun the app to update the display
@@ -112,12 +110,14 @@ def display_list_urls():
112
 
113
  def extract_pp(urls,input_variables):
114
  template_extraction_PP = '''
115
- Objectif : identifiez et proposez tout les noms de marques qui serviront comme partie prenante de la marque suivante pour développer un marketing de coopération (co-op marketing)
116
 
117
  Le nom de la marque de référence est le suivant : {BRAND_NAME}
118
  Son activité est la suivante : {BRAND_DESCRIPTION}
119
 
120
  TA REPONSE DOIT ETRE SOUS FORME DE LISTE DE NOMS DE MARQUES
 
 
121
  '''
122
  #don't forget to add the input variables from the maim function
123
 
@@ -166,7 +166,37 @@ def disp_vertical_slider(partie_prenante):
166
  )
167
  st.write(tst)
168
 
169
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
 
171
  def display_pp():
172
 
@@ -183,6 +213,8 @@ def display_pp():
183
  st.session_state["urls"] = []
184
  if "parties_prenantes" not in st.session_state:
185
  st.session_state['parties_prenantes'] = []
 
 
186
 
187
  st.header("Parties prenantes de la marque")
188
  #set brand name and description
@@ -195,22 +227,35 @@ def display_pp():
195
  #if the user chooses to extract from website
196
  if option == "A partir de votre site web":
197
 
198
-
199
  url = st.text_input("Ajouter une URL")
200
 
201
  #if the user clicks on the button
202
  if st.button("ajouter"):
203
- if url in st.session_state["urls"]:
 
 
 
204
  st.error("URL déjà ajoutée")
205
  else:
 
 
 
 
 
 
206
  with st.spinner("Processing..."):
207
 
208
  #handle the extraction
209
  input_variables = {"BRAND_NAME": brand_name, "BRAND_DESCRIPTION": brand_description}
210
  partie_prenante = extract_pp([url], input_variables)
211
- partie_prenante = sorted(partie_prenante)
212
- st.session_state['parties_prenantes'].append(partie_prenante)
213
- st.session_state["urls"].append(url)
 
 
 
 
 
214
  # alphabet = [ pp[0] for pp in partie_prenante]
215
  # pouvoir = [ 50 for _ in range(len(partie_prenante))]
216
  # df = pd.DataFrame({'partie_prenante': partie_prenante, 'pouvoir': pouvoir, 'code couleur': partie_prenante})
@@ -227,8 +272,10 @@ def display_pp():
227
 
228
  # disp_vertical_slider(partie_prenante)
229
  # st.altair_chart(c, use_container_width=True)
 
230
  display_list_urls()
231
  display_viz()
 
232
 
233
 
234
 
 
71
  prompt = PromptTemplate(input_variables=["BRAND_NAME","BRAND_DESCRIPTION"], template=template)
72
  return prompt.format(BRAND_NAME=input_variables["BRAND_NAME"], BRAND_DESCRIPTION=input_variables["BRAND_DESCRIPTION"])
73
 
 
 
 
 
 
 
 
 
 
 
74
  def text_to_list(text):
75
  lines = text.replace("- ","").split('\n')
76
 
77
  lines = [line.split() for line in lines]
78
  items = [[' '.join(line[:-1]),line[-1]] for line in lines]
79
+
80
  # Assuming `items` is the list of items
81
  for item in items:
82
  item[1] = re.sub(r'\D', '', item[1])
83
  return items
84
 
85
+ def delete_pp(pps):
86
+ for pp in pps:
87
+ st.session_state['partie_prenante_grouped'] = st.session_state['partie_prenante_grouped'].drop(st.session_state['partie_prenante_grouped'][st.session_state['partie_prenante_grouped']['partie_prenante'] == pp].index)
88
+ st.session_state['partie_prenante_grouped'].reset_index()
89
+
90
  def display_list_urls():
91
  for index, item in enumerate(st.session_state["urls"]):
92
  emp = st.empty() # Create an empty placeholder
 
94
 
95
  # Button to delete the entry, placed in the second column
96
  if col2.button("❌", key=f"but{index}"):
97
+ temp = st.session_state['parties_prenantes'][index]
98
+ delete_pp(temp)
99
  del st.session_state.urls[index]
100
  del st.session_state["parties_prenantes"][index]
101
  st.experimental_rerun() # Rerun the app to update the display
 
110
 
111
  def extract_pp(urls,input_variables):
112
  template_extraction_PP = '''
113
+ Objectif : identifiez tout les noms de marques qui sont des parties prenantes de la marque suivante pour développer un marketing de coopération (co-op marketing)
114
 
115
  Le nom de la marque de référence est le suivant : {BRAND_NAME}
116
  Son activité est la suivante : {BRAND_DESCRIPTION}
117
 
118
  TA REPONSE DOIT ETRE SOUS FORME DE LISTE DE NOMS DE MARQUES
119
+
120
+ SI TU NE TROUVES PAS DE NOM DE MARQUE, REPONDS "444"
121
  '''
122
  #don't forget to add the input variables from the maim function
123
 
 
166
  )
167
  st.write(tst)
168
 
169
+ def add_pp(new_pp, default_value=50):
170
+ new_pp = sorted(new_pp)
171
+ new_pp = [item.lower().capitalize() for item in new_pp]
172
+ st.session_state['parties_prenantes'].append(new_pp)
173
+ for pp in new_pp:
174
+ if pp not in st.session_state['partie_prenante_grouped']['partie_prenante'].values:
175
+ st.session_state['partie_prenante_grouped'].loc[len(st.session_state['partie_prenante_grouped'])] = [pp, default_value, pp]
176
+ st.session_state['partie_prenante_grouped'] = st.session_state['partie_prenante_grouped'].sort_values(by='partie_prenante')
177
+ st.session_state['partie_prenante_grouped'] = st.session_state['partie_prenante_grouped'].reset_index(drop=True)
178
+
179
+ def complete_and_verify_url(partial_url):
180
+ # Regex pattern for validating a URL
181
+ regex = re.compile(
182
+ r'^(?:http|ftp)s?://' # http:// or https://
183
+ r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?|' # domain
184
+ r'localhost|' # localhost...
185
+ r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip
186
+ r'(?::\d+)?' # optional port
187
+ r'(?:/?|[/?]\S+)$', re.IGNORECASE)
188
+
189
+ # Complete the URL if it doesn't have http:// or https://
190
+ if not partial_url.startswith(('http://', 'https://')):
191
+ complete_url = 'http://' + partial_url
192
+ else:
193
+ complete_url = partial_url
194
+
195
+ # Check if the URL is valid
196
+ if re.match(regex, complete_url):
197
+ return (True, complete_url)
198
+ else:
199
+ return (False, complete_url)
200
 
201
  def display_pp():
202
 
 
213
  st.session_state["urls"] = []
214
  if "parties_prenantes" not in st.session_state:
215
  st.session_state['parties_prenantes'] = []
216
+ if "partie_prenante_grouped" not in st.session_state: #servira pour le plot et la cartographie
217
+ st.session_state['partie_prenante_grouped'] = pd.DataFrame(columns=['partie_prenante', 'pouvoir', 'Code couleur'])
218
 
219
  st.header("Parties prenantes de la marque")
220
  #set brand name and description
 
227
  #if the user chooses to extract from website
228
  if option == "A partir de votre site web":
229
 
 
230
  url = st.text_input("Ajouter une URL")
231
 
232
  #if the user clicks on the button
233
  if st.button("ajouter"):
234
+ is_valid,url = complete_and_verify_url(url)
235
+ if not is_valid:
236
+ st.error("URL invalide")
237
+ elif url in st.session_state["urls"] :
238
  st.error("URL déjà ajoutée")
239
  else:
240
+ # Création de l'expander
241
+ with st.expander("Cliquez ici pour éditer et voir le document"):
242
+ cleaned_text = re.sub(r'\n\n+', '\n\n', get_docs_from_website(url)[0].page_content.strip())
243
+ text_value = st.text_area("Modifier le texte ci-dessous:", value=cleaned_text, height=300)
244
+ if st.button('Sauvegarder'):
245
+ st.success("Texte sauvegardé avec succès!")
246
  with st.spinner("Processing..."):
247
 
248
  #handle the extraction
249
  input_variables = {"BRAND_NAME": brand_name, "BRAND_DESCRIPTION": brand_description}
250
  partie_prenante = extract_pp([url], input_variables)
251
+
252
+ if "444" in partie_prenante:
253
+ st.error("Aucune partie prenante trouvée")
254
+ else:
255
+ partie_prenante = sorted(partie_prenante)
256
+ st.session_state["urls"].append(url)
257
+ add_pp(partie_prenante)
258
+
259
  # alphabet = [ pp[0] for pp in partie_prenante]
260
  # pouvoir = [ 50 for _ in range(len(partie_prenante))]
261
  # df = pd.DataFrame({'partie_prenante': partie_prenante, 'pouvoir': pouvoir, 'code couleur': partie_prenante})
 
272
 
273
  # disp_vertical_slider(partie_prenante)
274
  # st.altair_chart(c, use_container_width=True)
275
+
276
  display_list_urls()
277
  display_viz()
278
+ st.write(st.session_state["partie_prenante_grouped"])
279
 
280
 
281
 
pp_viz.py CHANGED
@@ -20,25 +20,25 @@ def display_viz():
20
  partie_prenante_non_filtre = [item.lower().capitalize() for sublist in parties_prenantes for item in sublist]
21
  partie_prenante = sorted(list(set(partie_prenante_non_filtre)))
22
  pouvoir = [ 50 for _ in range(len(partie_prenante))]
23
- df = pd.DataFrame({'partie_prenante': partie_prenante, 'pouvoir': pouvoir, 'Code couleur': partie_prenante})
24
  c = (
25
- alt.Chart(df)
26
  .mark_circle(size=800)
27
  .encode(x="partie_prenante", y=alt.Y("pouvoir",scale=alt.Scale(domain=[0,100])), color="Code couleur",tooltip=["partie_prenante","pouvoir"])
28
- ).configure_legend(orient='top',direction="vertical").properties(height=600)
29
 
30
  number_of_sliders = len(partie_prenante)
31
  st.write("Modifiez le pouvoir des parties prenantes en utilisant les sliders ci-dessous")
32
 
 
33
  bar = st.columns(number_of_sliders)
34
  for i in range(number_of_sliders):
35
  with bar[i]:
36
- temp = 50
37
- df["pouvoir"][i] = vertical_slider(
38
  label=partie_prenante[i],
39
  height=100,
40
  key=partie_prenante[i],
41
- default_value=temp,
42
  thumb_color= "orange", #Optional - Defaults to Streamlit Red
43
  step=1,
44
  min_value=0,
@@ -46,6 +46,6 @@ def display_viz():
46
  value_always_visible=False,
47
  )
48
  st.altair_chart(c, use_container_width=True)
49
- data = [{'id':partie_prenante[i], 'name':partie_prenante[i],'pouvoir':int(df["pouvoir"][i])} for i in range(len(partie_prenante))]
50
- slist = DraggableList(data)
51
- st.write(slist)
 
20
  partie_prenante_non_filtre = [item.lower().capitalize() for sublist in parties_prenantes for item in sublist]
21
  partie_prenante = sorted(list(set(partie_prenante_non_filtre)))
22
  pouvoir = [ 50 for _ in range(len(partie_prenante))]
23
+
24
  c = (
25
+ alt.Chart(st.session_state['partie_prenante_grouped'])
26
  .mark_circle(size=800)
27
  .encode(x="partie_prenante", y=alt.Y("pouvoir",scale=alt.Scale(domain=[0,100])), color="Code couleur",tooltip=["partie_prenante","pouvoir"])
28
+ ).configure_legend(orient='bottom',direction="vertical").properties(height=600)
29
 
30
  number_of_sliders = len(partie_prenante)
31
  st.write("Modifiez le pouvoir des parties prenantes en utilisant les sliders ci-dessous")
32
 
33
+
34
  bar = st.columns(number_of_sliders)
35
  for i in range(number_of_sliders):
36
  with bar[i]:
37
+ st.session_state['partie_prenante_grouped']['pouvoir'][i] = vertical_slider(
 
38
  label=partie_prenante[i],
39
  height=100,
40
  key=partie_prenante[i],
41
+ default_value=int(st.session_state['partie_prenante_grouped']['pouvoir'][i]),
42
  thumb_color= "orange", #Optional - Defaults to Streamlit Red
43
  step=1,
44
  min_value=0,
 
46
  value_always_visible=False,
47
  )
48
  st.altair_chart(c, use_container_width=True)
49
+ # data = [{'id':partie_prenante[i], 'name':partie_prenante[i],'pouvoir':int(df["pouvoir"][i])} for i in range(len(partie_prenante))]
50
+ # slist = DraggableList(data)
51
+ # st.write(slist)