Spaces:
Running
Running
Ilyas KHIAT
commited on
Commit
•
38cf0bb
1
Parent(s):
ce4fc2a
chatbot and bug fix
Browse files- app.py +6 -1
- chat_with_pps.py +75 -0
- partie_prenante_carte.py +64 -17
- 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
|
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 |
-
|
|
|
|
|
|
|
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 |
-
|
212 |
-
|
213 |
-
|
|
|
|
|
|
|
|
|
|
|
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 |
-
|
24 |
c = (
|
25 |
-
alt.Chart(
|
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='
|
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 |
-
|
37 |
-
df["pouvoir"][i] = vertical_slider(
|
38 |
label=partie_prenante[i],
|
39 |
height=100,
|
40 |
key=partie_prenante[i],
|
41 |
-
default_value=
|
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)
|