Spaces:
Running
Running
Upload rag.py
#5
by
AwaMbaye
- opened
- .dockerignore +0 -11
- .gitattributes +0 -3
- .gitignore +2 -3
- .streamlit/.env +1 -0
- .streamlit/config.toml +0 -8
- AnalyseActionsRSE.py +33 -102
- DATA_bziiit/vectorstore_op/index.faiss +0 -3
- DATA_bziiit/vectorstore_op/index.pkl +0 -3
- Dockerfile +0 -34
- ODD.py +0 -90
- RAG_PDF.py +0 -77
- RAG_PDF_WEB.py +0 -234
- README.md +6 -5
- app.py +15 -80
- chart.png +0 -0
- chat_te.py +0 -127
- chat_with_pps.py +0 -437
- collaborons.py +0 -1
- comparateur.py +0 -54
- data_manager_bziiit.py +0 -16
- documentations.py +2 -2
- download_chart.py +0 -124
- emissions.csv +0 -0
- empreinte_carbone.py +0 -120
- empreinte_export.py +0 -172
- export_doc.py +0 -242
- feuille.svg +0 -3
- footer.html +0 -59
- high_chart.py +0 -201
- htmlTemplates.py +0 -44
- packages.txt +0 -2
- partie_prenante_carte.py +0 -490
- partiesprenantes.py +0 -1
- prompt.py +0 -135
- rag.py +0 -0
- rag_funcs.py +0 -14
- requirements.txt +1 -31
- session.py +0 -31
- st_hc/__init__.py +0 -2562
- st_hc/frontend/index.html +0 -36
- st_hc/frontend/main.js +0 -42
- st_hc/frontend/streamlit-component-lib.js +0 -34
- st_hc/frontend/style.css +0 -9
- temp.html +0 -310
.dockerignore
DELETED
@@ -1,11 +0,0 @@
|
|
1 |
-
__pycache__/
|
2 |
-
*.pyc
|
3 |
-
*.pyo
|
4 |
-
*.pyd
|
5 |
-
.Python
|
6 |
-
env/
|
7 |
-
venv/
|
8 |
-
.git
|
9 |
-
.dockerignore
|
10 |
-
Dockerfile
|
11 |
-
*.md
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.gitattributes
CHANGED
@@ -33,6 +33,3 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
-
DATA_bziiit/op.pdf filter=lfs diff=lfs merge=lfs -text
|
37 |
-
DATA_bziiit/vectorstore_op/index.faiss filter=lfs diff=lfs merge=lfs -text
|
38 |
-
*.pdf filter=lfs diff=lfs merge=lfs -text
|
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
.gitignore
CHANGED
@@ -1,4 +1,3 @@
|
|
1 |
__pycache__/
|
2 |
-
.streamlit
|
3 |
-
|
4 |
-
.env
|
|
|
1 |
__pycache__/
|
2 |
+
.streamlit/secrets.toml
|
3 |
+
.streamlit/.env
|
|
.streamlit/.env
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
API_TOKEN_PERPLEXITYAI = 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
|
.streamlit/config.toml
DELETED
@@ -1,8 +0,0 @@
|
|
1 |
-
[server]
|
2 |
-
maxUploadSize = 5
|
3 |
-
|
4 |
-
[theme]
|
5 |
-
base="light"
|
6 |
-
primaryColor="#63abdf"
|
7 |
-
secondaryBackgroundColor="#fbf7f1"
|
8 |
-
textColor="#011166"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AnalyseActionsRSE.py
CHANGED
@@ -1,7 +1,5 @@
|
|
1 |
import streamlit as st
|
2 |
from ISO26000 import classify_actions_rse_ISO26000 as classify_iso26000
|
3 |
-
from ODD import classify_actions_rse_ODD as classify_odd
|
4 |
-
from impactscore import classify_actions_rse_IMPACTSCORE as classify_impactscore
|
5 |
from impactscore import classify_actions_rse_IMPACTSCORE as classify_impactscore
|
6 |
from data_manager import get_data
|
7 |
|
@@ -81,8 +79,39 @@ def display_analyse_actions_rse():
|
|
81 |
st.markdown("""<hr style='border-color: darkgrey;'>""", unsafe_allow_html=True)
|
82 |
st.markdown(f"**Total des actions RSE :** {total_actions}")
|
83 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
elif approach == "ODD Objectifs de Développement Durable (en cours de développement)":
|
85 |
-
|
86 |
data, total_hits = get_data()
|
87 |
|
88 |
st.markdown("""<hr style='border-color: darkgrey;'>""", unsafe_allow_html=True)
|
@@ -117,95 +146,11 @@ def display_analyse_actions_rse():
|
|
117 |
|
118 |
st.markdown("""<small>Source AGENDA 2030 EN FRANCE : <a href="https://www.agenda-2030.fr/17-objectifs-de-developpement-durable/?" target="_blank">https://impactscore.fr/comprendre-limpact-score/</a></small>""", unsafe_allow_html=True)
|
119 |
|
120 |
-
st.markdown("""<hr style='border-color: darkgrey;'>""", unsafe_allow_html=True)
|
121 |
-
|
122 |
-
pictograms = {
|
123 |
-
"Pas de pauvreté": "🏚️",
|
124 |
-
"Faim « Zéro »": "🌾",
|
125 |
-
"Bonne santé et bien-être": "🏥",
|
126 |
-
"Éducation de qualité": "🎓",
|
127 |
-
"Égalité entre les sexes": "⚧️",
|
128 |
-
"Eau propre et assainissement": "💧",
|
129 |
-
"Énergie propre et d'un coût abordable": "⚡",
|
130 |
-
"Travail décent et croissance économique": "👷",
|
131 |
-
"Industrie, innovation et infrastructure": "🏭",
|
132 |
-
"Inégalités réduites": "⚖️",
|
133 |
-
"Villes et communautés durables": "🏙️",
|
134 |
-
"Consommation et production responsables": "♻️",
|
135 |
-
"Lutte contre les changements climatiques": "🌍",
|
136 |
-
"Vie aquatique": "🐟",
|
137 |
-
"Vie terrestre": "🌳",
|
138 |
-
"Paix, justice et institutions efficaces": "⚖️",
|
139 |
-
"Partenariats pour la réalisation des objectifs": "🤝",
|
140 |
-
"Autres": "❓"
|
141 |
-
}
|
142 |
-
|
143 |
-
|
144 |
-
criteria_counts = classify_odd(data)
|
145 |
-
|
146 |
-
total_actions = 0
|
147 |
-
|
148 |
-
for category, actions in criteria_counts.items():
|
149 |
-
if category in pictograms:
|
150 |
-
st.subheader(f"{pictograms[category]} {category}")
|
151 |
-
else:
|
152 |
-
st.subheader(f"{pictograms['Autres']} Autres")
|
153 |
-
total_actions += len(actions)
|
154 |
-
for action in actions:
|
155 |
-
nom_entreprise = action.get('nom_courant_denomination', 'Information non disponible')
|
156 |
-
st.write(f"Entreprise : {action.get('name','N/A')}, Action RSE : {action.get('action_rse', 'N/A')}, Activité : {action.get('activity', 'N/A')}, Ville : {action.get('city', 'N/A')}")
|
157 |
-
|
158 |
-
st.markdown("""<hr style='border-color: darkgrey;'>""", unsafe_allow_html=True)
|
159 |
-
st.markdown(f"**Total des actions RSE :** {total_actions}")
|
160 |
-
|
161 |
-
### OBJECTIF DE DEVELOPPEMENT DURABLE ###
|
162 |
-
elif approach == "Impact Score (en cours de développement)":
|
163 |
-
# Récupérer les données depuis data_manager.py
|
164 |
-
data, total_hits = get_data()
|
165 |
-
|
166 |
st.markdown("""<hr style='border-color: darkgrey;'>""", unsafe_allow_html=True)
|
167 |
|
168 |
-
st.markdown("""
|
169 |
-
🌳 **QU'EST-CE QUE L'IMPACT SCORE ?**
|
170 |
-
|
171 |
-
Ce référentiel commun et unique a été co-construit par 30 réseaux d’entreprises afin de publier en transparence leurs données d’impact, exigence européenne depuis 2024.
|
172 |
-
|
173 |
-
**COMMENT EST-IL STRUCTURÉE ?**
|
174 |
-
|
175 |
-
IMPACT SCORE repose sur 3 piliers essentiels :
|
176 |
-
|
177 |
-
- 🚫 LIMITATION DES EXTERNALITÉS NÉGATIVES
|
178 |
-
- 💡 PARTAGE DU POUVOIR ET DE LA VALEUR
|
179 |
-
- 🎯 STRATÉGIE À IMPACT
|
180 |
-
""")
|
181 |
-
|
182 |
-
|
183 |
-
st.markdown("""<small>Source MOUVEMENT IMPACT FRANCE : <a href="https://impactscore.fr/comprendre-limpact-score/" target="_blank">https://impactscore.fr/comprendre-limpact-score/</a></small>""", unsafe_allow_html=True)
|
184 |
-
|
185 |
-
st.markdown("""<hr style='border-color: darkgrey;'>""", unsafe_allow_html=True)
|
186 |
-
|
187 |
-
pictograms = {
|
188 |
-
"Initiatives pour réduire l'empreinte carbone": "🌍",
|
189 |
-
"Amélioration des conditions de travail": "👷",
|
190 |
-
"Promotion du recyclage": "♻️",
|
191 |
-
"Autres": "❓"
|
192 |
-
}
|
193 |
-
|
194 |
criteria_counts = classify_impactscore(data)
|
195 |
|
196 |
-
total_actions =
|
197 |
-
|
198 |
-
for category, actions in criteria_counts.items():
|
199 |
-
if category in pictograms:
|
200 |
-
st.subheader(f"{pictograms[category]} {category}")
|
201 |
-
else:
|
202 |
-
st.subheader(f"{pictograms['Autres']} Autres")
|
203 |
-
total_actions += len(actions)
|
204 |
-
for action in actions:
|
205 |
-
nom_entreprise = action.get('nom_courant_denomination', 'Information non disponible')
|
206 |
-
st.write(f"Entreprise : {action.get('name','N/A')}, Action RSE : {action.get('action_rse', 'N/A')}, Activité : {action.get('activity', 'N/A')}, Ville : {action.get('city', 'N/A')}")
|
207 |
-
|
208 |
-
st.markdown("""<hr style='border-color: darkgrey;'>""", unsafe_allow_html=True)
|
209 |
st.markdown(f"**Total des actions RSE :** {total_actions}")
|
210 |
|
211 |
if approach == "Norme ISO 26000":
|
@@ -215,19 +160,5 @@ def display_analyse_actions_rse():
|
|
215 |
for category, count in synthesis_sorted.items():
|
216 |
st.write(f"{category}: {count} action(s) RSE")
|
217 |
|
218 |
-
if approach == "ODD Objectifs de Développement Durable (en cours de développement)":
|
219 |
-
st.subheader("Synthèse par catégorie ODD")
|
220 |
-
synthesis = {category: len(actions) for category, actions in criteria_counts.items()}
|
221 |
-
synthesis_sorted = dict(sorted(synthesis.items(), key=lambda item: item[1], reverse=True))
|
222 |
-
for category, count in synthesis_sorted.items():
|
223 |
-
st.write(f"{category}: {count} action(s) RSE")
|
224 |
-
|
225 |
-
if approach == "Impact Score (en cours de développement)":
|
226 |
-
st.subheader("Synthèse par catégorie ODD")
|
227 |
-
synthesis = {category: len(actions) for category, actions in criteria_counts.items()}
|
228 |
-
synthesis_sorted = dict(sorted(synthesis.items(), key=lambda item: item[1], reverse=True))
|
229 |
-
for category, count in synthesis_sorted.items():
|
230 |
-
st.write(f"{category}: {count} action(s) RSE")
|
231 |
-
|
232 |
if __name__ == "__main__":
|
233 |
display_analyse_actions_rse()
|
|
|
1 |
import streamlit as st
|
2 |
from ISO26000 import classify_actions_rse_ISO26000 as classify_iso26000
|
|
|
|
|
3 |
from impactscore import classify_actions_rse_IMPACTSCORE as classify_impactscore
|
4 |
from data_manager import get_data
|
5 |
|
|
|
79 |
st.markdown("""<hr style='border-color: darkgrey;'>""", unsafe_allow_html=True)
|
80 |
st.markdown(f"**Total des actions RSE :** {total_actions}")
|
81 |
|
82 |
+
elif approach == "Impact Score (en cours de développement)":
|
83 |
+
# Récupérer les données depuis data_manager.py
|
84 |
+
data, total_hits = get_data()
|
85 |
+
|
86 |
+
st.markdown("""<hr style='border-color: darkgrey;'>""", unsafe_allow_html=True)
|
87 |
+
|
88 |
+
st.markdown("""
|
89 |
+
🌳 **QU'EST-CE QUE L'IMPACT SCORE ?**
|
90 |
+
|
91 |
+
Ce référentiel commun et unique a été co-construit par 30 réseaux d’entreprises afin de publier en transparence leurs données d’impact, exigence européenne depuis 2024.
|
92 |
+
|
93 |
+
**COMMENT EST-IL STRUCTURÉE ?**
|
94 |
+
|
95 |
+
IMPACT SCORE repose sur 3 piliers essentiels :
|
96 |
+
|
97 |
+
- 🚫 LIMITATION DES EXTERNALITÉS NÉGATIVES
|
98 |
+
- 💡 PARTAGE DU POUVOIR ET DE LA VALEUR
|
99 |
+
- 🎯 STRATÉGIE À IMPACT
|
100 |
+
""")
|
101 |
+
|
102 |
+
|
103 |
+
st.markdown("""<small>Source MOUVEMENT IMPACT FRANCE : <a href="https://impactscore.fr/comprendre-limpact-score/" target="_blank">https://impactscore.fr/comprendre-limpact-score/</a></small>""", unsafe_allow_html=True)
|
104 |
+
|
105 |
+
st.markdown("""<hr style='border-color: darkgrey;'>""", unsafe_allow_html=True)
|
106 |
+
|
107 |
+
criteria_counts = classify_impactscore(data)
|
108 |
+
|
109 |
+
total_actions = sum([len(actions) for actions in criteria_counts.values()])
|
110 |
+
st.markdown(f"**Total des actions RSE :** {total_actions}")
|
111 |
+
|
112 |
+
### OBJECTIF DE DEVELOPPEMENT DURABLE ###
|
113 |
elif approach == "ODD Objectifs de Développement Durable (en cours de développement)":
|
114 |
+
# Récupérer les données depuis data_manager.py
|
115 |
data, total_hits = get_data()
|
116 |
|
117 |
st.markdown("""<hr style='border-color: darkgrey;'>""", unsafe_allow_html=True)
|
|
|
146 |
|
147 |
st.markdown("""<small>Source AGENDA 2030 EN FRANCE : <a href="https://www.agenda-2030.fr/17-objectifs-de-developpement-durable/?" target="_blank">https://impactscore.fr/comprendre-limpact-score/</a></small>""", unsafe_allow_html=True)
|
148 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
149 |
st.markdown("""<hr style='border-color: darkgrey;'>""", unsafe_allow_html=True)
|
150 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
151 |
criteria_counts = classify_impactscore(data)
|
152 |
|
153 |
+
total_actions = sum([len(actions) for actions in criteria_counts.values()])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
154 |
st.markdown(f"**Total des actions RSE :** {total_actions}")
|
155 |
|
156 |
if approach == "Norme ISO 26000":
|
|
|
160 |
for category, count in synthesis_sorted.items():
|
161 |
st.write(f"{category}: {count} action(s) RSE")
|
162 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
if __name__ == "__main__":
|
164 |
display_analyse_actions_rse()
|
DATA_bziiit/vectorstore_op/index.faiss
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:0d308f98f3798328b0c1efdfb5ab5ade0e8b7b93f7f32ee439b54aa060879067
|
3 |
-
size 1228845
|
|
|
|
|
|
|
|
DATA_bziiit/vectorstore_op/index.pkl
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:7b492225278bd4ba23d11fe72fa16f8abd9a023babcc6734901740ba34fd0ba7
|
3 |
-
size 106874
|
|
|
|
|
|
|
|
Dockerfile
DELETED
@@ -1,34 +0,0 @@
|
|
1 |
-
# Use the official lightweight Python image.
|
2 |
-
# https://hub.docker.com/_/python
|
3 |
-
FROM python:3.9-slim
|
4 |
-
|
5 |
-
# Set environment variables
|
6 |
-
ENV PYTHONDONTWRITEBYTECODE 1
|
7 |
-
ENV PYTHONUNBUFFERED 1
|
8 |
-
|
9 |
-
# Create and set working directory
|
10 |
-
WORKDIR /app
|
11 |
-
|
12 |
-
RUN apt-get update \
|
13 |
-
&& apt-get install wkhtmltopdf -y \
|
14 |
-
&& mv /usr/bin/wkhtmltopdf /usr/local/bin/.
|
15 |
-
|
16 |
-
# Copy system package requirements file
|
17 |
-
COPY packages.txt .
|
18 |
-
|
19 |
-
RUN apt-get update
|
20 |
-
|
21 |
-
# Copy the application requirements file
|
22 |
-
COPY requirements.txt .
|
23 |
-
|
24 |
-
# Install Python dependencies
|
25 |
-
RUN pip install --no-cache-dir -r requirements.txt
|
26 |
-
|
27 |
-
# Copy the application code
|
28 |
-
COPY . .
|
29 |
-
|
30 |
-
# Expose the Streamlit port
|
31 |
-
EXPOSE 8501
|
32 |
-
|
33 |
-
# Run Streamlit app
|
34 |
-
CMD ["streamlit", "run", "app.py"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ODD.py
DELETED
@@ -1,90 +0,0 @@
|
|
1 |
-
from data_manager import get_data
|
2 |
-
|
3 |
-
def classify_actions_rse_ODD(data):
|
4 |
-
data, _ = get_data() # Récupérer les données depuis data_manager.py
|
5 |
-
|
6 |
-
criteria = {
|
7 |
-
"Pas de pauvreté": [],
|
8 |
-
"Faim « Zéro »": [],
|
9 |
-
"Bonne santé et bien-être": [],
|
10 |
-
"Éducation de qualité": [],
|
11 |
-
"Égalité entre les sexes": [],
|
12 |
-
"Eau propre et assainissement": [],
|
13 |
-
"Énergie propre et d'un coût abordable": [],
|
14 |
-
"Travail décent et croissance économique": [],
|
15 |
-
"Industrie, innovation et infrastructure": [],
|
16 |
-
"Inégalités réduites": [],
|
17 |
-
"Villes et communautés durables": [],
|
18 |
-
"Consommation et production responsables": [],
|
19 |
-
"Lutte contre les changements climatiques": [],
|
20 |
-
"Vie aquatique": [],
|
21 |
-
"Vie terrestre": [],
|
22 |
-
"Paix, justice et institutions efficaces": [],
|
23 |
-
"Partenariats pour la réalisation des objectifs": [],
|
24 |
-
"Autres": []
|
25 |
-
}
|
26 |
-
|
27 |
-
|
28 |
-
# Keywords for each ISO 26000 category to help in classifying the actions
|
29 |
-
keywords = {
|
30 |
-
"Pas de pauvreté": ["pauvreté", "aide financière", "microcrédit", "inclusion financière", "projets anti-pauvreté", "programmes de soutien", "subventions sociales", "initiatives d'entreprenariat"],
|
31 |
-
"Faim « Zéro »": ["faim", "sécurité alimentaire", "nutrition", "agriculture durable", "programmes de nutrition", "alimentation scolaire", "agroécologie", "technologies agricoles"],
|
32 |
-
"Bonne santé et bien-être": ["santé", "bien-être", "vaccination", "hôpitaux", "soins médicaux", "prévention des maladies", "santé mentale", "accès aux soins"],
|
33 |
-
"Éducation de qualité": ["éducation", "scolarisation", "formation", "alphabétisation", "éducation pour tous", "technologie éducative", "programmes éducatifs", "qualité de l'enseignement"],
|
34 |
-
"Égalité entre les sexes": ["égalité des sexes", "droits des femmes", "empowerment des femmes", "lutte contre les violences de genre", "participation des femmes", "leadership féminin", "éducation des filles", "santé reproductive"],
|
35 |
-
"Eau propre et assainissement": ["eau propre", "assainissement", "accès à l'eau", "traitement de l'eau", "gestion des ressources en eau", "sanitation", "qualité de l'eau", "hygiène"],
|
36 |
-
"Énergie propre et d'un coût abordable": ["énergie renouvelable", "énergie propre", "efficacité énergétique", "technologies énergétiques", "accès à l'énergie", "énergie solaire", "énergie éolienne", "infrastructures énergétiques"],
|
37 |
-
"Travail décent et croissance économique": ["emploi", "droits du travail", "croissance économique", "entreprise responsable", "économie inclusive", "emploi de qualité", "conditions de travail équitables", "sécurité de l'emploi"],
|
38 |
-
"Industrie, innovation et infrastructure": ["industrie", "innovation", "infrastructure", "technologie", "recherche et développement", "industrialisation durable", "innovation technologique", "infrastructures résilientes"],
|
39 |
-
"Inégalités réduites": ["réduction des inégalités", "inclusion sociale", "équité", "justice sociale", "accès équitable", "droits de l'homme", "intégration sociale", "lutte contre la discrimination"],
|
40 |
-
"Villes et communautés durables": ["urbanisme durable", "communautés résilientes", "transports publics", "éco-quartiers", "développement urbain", "mobilité urbaine", "gestion urbaine", "logement abordable"],
|
41 |
-
"Consommation et production responsables": ["consommation durable", "production durable", "économie circulaire", "recyclage", "gestion des déchets", "consommation éthique", "réduction de l'empreinte écologique", "sourcing responsable"],
|
42 |
-
"Lutte contre les changements climatiques": ["changements climatiques", "atténuation", "adaptation au climat", "réduction des émissions", "politiques climatiques", "énergies vertes", "carboneutralité", "initiatives climatiques"],
|
43 |
-
"Vie aquatique": ["océans", "mers", "conservation marine", "pêche durable", "biodiversité marine", "écosystèmes marins", "protection des habitats marins", "lutte contre la pollution marine"],
|
44 |
-
"Vie terrestre": ["biodiversité terrestre", "conservation des forêts", "reforestation", "lutte contre la désertification", "protection de la faune", "aires protégées", "gestion durable des terres", "restauration des habitats"],
|
45 |
-
"Paix, justice et institutions efficaces": ["paix", "justice", "lutte contre la corruption", "institutions solides", "état de droit", "droits humains", "transparence gouvernementale", "accès à la justice"],
|
46 |
-
"Partenariats pour la réalisation des objectifs": ["partenariats mondiaux", "coopération internationale", "mobilisation des ressources", "alignement des politiques", "collaboration multisectorielle", "coopération transfrontalière", "engagement des parties prenantes", "synergies globales"]
|
47 |
-
}
|
48 |
-
|
49 |
-
keywords = {
|
50 |
-
"Pas de pauvreté": ["pauvreté", "aide financière", "microcrédit", "inclusion financière", "soutien économique", "subventions", "réduction de la pauvreté"],
|
51 |
-
"Faim « Zéro »": ["faim", "sécurité alimentaire", "nutrition", "agriculture durable", "aide alimentaire", "cultures résilientes"],
|
52 |
-
"Bonne santé et bien-être": ["santé", "bien-être", "vaccination", "hôpitaux", "soins médicaux", "prévention des maladies", "santé publique", "accès aux soins"],
|
53 |
-
"Éducation de qualité": ["éducation", "scolarisation", "formation", "alphabétisation", "accès à l'éducation", "qualité de l'enseignement"],
|
54 |
-
"Égalité entre les sexes": ["égalité des sexes", "droits des femmes", "empowerment des femmes", "égalité de genre", "lutte contre les discriminations de genre", "participation des femmes", "leadership féminin", "éducation des filles", "santé reproductive", "violences de genre","leadership féminin", "parité", "lutte contre le harcèlement sexuel", "programmes de mentorat pour femmes", "initiatives pour l'équité salariale", "soutien à l'entrepreneuriat féminin", "formation sur la diversité", "sensibilisation au genre", "promotion de la diversité", "inclusion de genre"],
|
55 |
-
"Eau propre et assainissement": ["eau propre", "assainissement", "accès à l'eau", "traitement de l'eau", "gestion durable de l'eau"],
|
56 |
-
"Énergie propre et d'un coût abordable": ["énergie renouvelable", "énergie propre", "efficacité énergétique", "énergie solaire", "énergie éolienne", "réduction de la consommation énergétique"],
|
57 |
-
"Travail décent et croissance économique": ["emploi", "droits du travail", "croissance économique", "entreprise responsable", "travail décent", "conditions de travail", "économie inclusive"],
|
58 |
-
"Industrie, innovation et infrastructure": ["industrie", "innovation", "infrastructure", "technologie", "innovation industrielle", "développement durable industriel"],
|
59 |
-
"Inégalités réduites": ["réduction des inégalités", "inclusion sociale", "équité", "justice sociale", "égalité des chances"],
|
60 |
-
"Villes et communautés durables": ["urbanisme durable", "communautés résilientes", "transports publics", "développement urbain durable", "mobilité urbaine"],
|
61 |
-
"Consommation et production responsables": ["consommation durable", "production durable", "économie circulaire", "recyclage", "gestion des déchets", "réduction de l'empreinte carbone"],
|
62 |
-
"Lutte contre les changements climatiques": ["changements climatiques", "atténuation", "adaptation au climat", "réduction des émissions", "initiatives climatiques", "sobriété carbone"],
|
63 |
-
"Vie aquatique": ["océans", "mers", "conservation marine", "pêche durable", "biodiversité aquatique", "protection des écosystèmes marins"],
|
64 |
-
"Vie terrestre": ["biodiversité terrestre", "conservation des forêts", "reforestation", "protection des écosystèmes terrestres", "lutte contre la désertification"],
|
65 |
-
"Paix, justice et institutions efficaces": ["paix", "justice", "lutte contre la corruption", "institutions solides", "état de droit", "transparence", "accessibilité de la justice"],
|
66 |
-
"Partenariats pour la réalisation des objectifs": ["partenariats mondiaux", "coopération internationale", "engagement multi-acteurs", "collaboration stratégique", "synergie"]
|
67 |
-
}
|
68 |
-
|
69 |
-
#keywords.update(keywords_sdg)
|
70 |
-
|
71 |
-
for record in data:
|
72 |
-
action_rse = record.get("action_rse", "").lower()
|
73 |
-
company_info = {
|
74 |
-
"name": record.get("nom_courant_denomination", "N/A"),
|
75 |
-
"action_rse": action_rse,
|
76 |
-
"activity": record.get("libelle_section_naf", "N/A"),
|
77 |
-
"city": record.get("commune", "N/A")
|
78 |
-
}
|
79 |
-
found_category = False
|
80 |
-
for criterion, key_phrases in keywords.items():
|
81 |
-
if any(key_phrase in action_rse for key_phrase in key_phrases):
|
82 |
-
criteria[criterion].append(company_info)
|
83 |
-
found_category = True
|
84 |
-
break # Assuming each action belongs to one category only
|
85 |
-
|
86 |
-
# Si l'action n'a pas été classifiée dans une catégorie existante, la placer dans "Autres"
|
87 |
-
if not found_category:
|
88 |
-
criteria["Autres"].append(company_info)
|
89 |
-
|
90 |
-
return criteria
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RAG_PDF.py
DELETED
@@ -1,77 +0,0 @@
|
|
1 |
-
import streamlit as st
|
2 |
-
from dotenv import load_dotenv
|
3 |
-
from PyPDF2 import PdfReader
|
4 |
-
from langchain.text_splitter import CharacterTextSplitter
|
5 |
-
from langchain_community.embeddings import HuggingFaceInstructEmbeddings
|
6 |
-
from langchain_community.vectorstores import FAISS
|
7 |
-
from langchain_community.chat_models import ChatOpenAI
|
8 |
-
from langchain.llms import HuggingFaceHub
|
9 |
-
from langchain import hub
|
10 |
-
from langchain_core.output_parsers import StrOutputParser
|
11 |
-
from langchain_core.runnables import RunnablePassthrough
|
12 |
-
import os
|
13 |
-
|
14 |
-
|
15 |
-
def get_pdf_text(pdf_docs):
|
16 |
-
text = ""
|
17 |
-
for pdf in pdf_docs:
|
18 |
-
pdf_reader = PdfReader(pdf)
|
19 |
-
for page in pdf_reader.pages:
|
20 |
-
text += page.extract_text()
|
21 |
-
return text
|
22 |
-
|
23 |
-
def get_text_chunks(text):
|
24 |
-
text_splitter = CharacterTextSplitter(
|
25 |
-
separator="\n",
|
26 |
-
chunk_size=500, # the character length of the chunck
|
27 |
-
chunk_overlap=100, # the character length of the overlap between chuncks
|
28 |
-
length_function=len # the length function - in this case, character length (aka the python len() fn.)
|
29 |
-
)
|
30 |
-
chunks = text_splitter.split_text(text)
|
31 |
-
return chunks
|
32 |
-
|
33 |
-
def get_vectorstore(text_chunks):
|
34 |
-
model_name = "hkunlp/instructor-xl"
|
35 |
-
hf = HuggingFaceInstructEmbeddings(model_name=model_name)
|
36 |
-
vectorstore = FAISS.from_texts(texts=text_chunks, embedding=hf)
|
37 |
-
return vectorstore
|
38 |
-
|
39 |
-
def get_conversation_chain(vectorstore):
|
40 |
-
llm = HuggingFaceHub(repo_id="mistralai/Mistral-7B-Instruct-v0.2",model_kwargs={"Temperature": 0.5, "MaxTokens": 1024})
|
41 |
-
retriever=vectorstore.as_retriever()
|
42 |
-
prompt = hub.pull("rlm/rag-prompt")
|
43 |
-
# Chain
|
44 |
-
rag_chain = (
|
45 |
-
{"context": retriever, "question": RunnablePassthrough()}
|
46 |
-
| prompt
|
47 |
-
| llm
|
48 |
-
)
|
49 |
-
response = rag_chain.invoke("A partir de documents PDF, concernant la transition écologique en France, proposer un plan de transition en fonction de la marque").split("\nAnswer:")[-1]
|
50 |
-
return response
|
51 |
-
|
52 |
-
def rag_pdf():
|
53 |
-
load_dotenv()
|
54 |
-
st.header("Utiliser l’IA pour générer un plan RSE simplifié")
|
55 |
-
|
56 |
-
if "conversation" not in st.session_state:
|
57 |
-
st.session_state.conversation = None
|
58 |
-
|
59 |
-
|
60 |
-
with st.sidebar:
|
61 |
-
st.subheader("INFOS SUR LA MARQUE")
|
62 |
-
pdf_docs = st.file_uploader("Upload les documents concerant la marque et clique sur process", type="pdf",accept_multiple_files=True)
|
63 |
-
if st.button("Process"):
|
64 |
-
with st.spinner("Processing..."):#loading bar to enhance user experience
|
65 |
-
#get pdf text in raw format
|
66 |
-
raw_text = get_pdf_text(pdf_docs)
|
67 |
-
|
68 |
-
#get text chunks
|
69 |
-
text_chunks = get_text_chunks(raw_text)
|
70 |
-
|
71 |
-
#create vectorstore
|
72 |
-
vectorstore = get_vectorstore(text_chunks)
|
73 |
-
|
74 |
-
#create conversation chain
|
75 |
-
st.session_state.conversation = get_conversation_chain(vectorstore)
|
76 |
-
|
77 |
-
st.write(st.session_state.conversation)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RAG_PDF_WEB.py
DELETED
@@ -1,234 +0,0 @@
|
|
1 |
-
import streamlit as st
|
2 |
-
from dotenv import load_dotenv
|
3 |
-
from PyPDF2 import PdfReader
|
4 |
-
from langchain.text_splitter import CharacterTextSplitter
|
5 |
-
from langchain_community.embeddings import OpenAIEmbeddings
|
6 |
-
from langchain_community.vectorstores import FAISS
|
7 |
-
from langchain_community.chat_models import ChatOpenAI
|
8 |
-
from langchain.llms import HuggingFaceHub
|
9 |
-
from langchain import hub
|
10 |
-
from langchain_core.output_parsers import StrOutputParser
|
11 |
-
from langchain_core.runnables import RunnablePassthrough
|
12 |
-
from langchain_community.document_loaders import WebBaseLoader
|
13 |
-
import os
|
14 |
-
|
15 |
-
from session import set_rag
|
16 |
-
from partie_prenante_carte import complete_and_verify_url
|
17 |
-
|
18 |
-
def get_docs_from_website(urls):
|
19 |
-
loader = WebBaseLoader(urls, header_template={
|
20 |
-
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36',
|
21 |
-
})
|
22 |
-
docs = loader.load()
|
23 |
-
return docs
|
24 |
-
|
25 |
-
def get_pdf_text(pdf_docs):
|
26 |
-
text = ""
|
27 |
-
for pdf in pdf_docs:
|
28 |
-
pdf_reader = PdfReader(pdf)
|
29 |
-
for page in pdf_reader.pages:
|
30 |
-
text += page.extract_text()
|
31 |
-
return text
|
32 |
-
|
33 |
-
def get_text_chunks(text):
|
34 |
-
text_splitter = CharacterTextSplitter(
|
35 |
-
separator="\n",
|
36 |
-
chunk_size=1000, # the character length of the chunck
|
37 |
-
chunk_overlap=200, # the character length of the overlap between chuncks
|
38 |
-
length_function=len # the length function - in this case, character length (aka the python len() fn.)
|
39 |
-
)
|
40 |
-
chunks = text_splitter.split_text(text)
|
41 |
-
return chunks
|
42 |
-
|
43 |
-
def get_doc_chunks(docs):
|
44 |
-
# Split the loaded data
|
45 |
-
text_splitter = CharacterTextSplitter(separator='\n',
|
46 |
-
chunk_size=500,
|
47 |
-
chunk_overlap=40)
|
48 |
-
|
49 |
-
docs = text_splitter.split_documents(docs)
|
50 |
-
return docs
|
51 |
-
|
52 |
-
def get_vectorstore_from_docs(doc_chunks):
|
53 |
-
embedding = OpenAIEmbeddings(model="text-embedding-3-small")
|
54 |
-
vectorstore = FAISS.from_documents(documents=doc_chunks, embedding=embedding)
|
55 |
-
return vectorstore
|
56 |
-
|
57 |
-
def get_vectorstore(text_chunks):
|
58 |
-
embedding = OpenAIEmbeddings(model="text-embedding-3-small")
|
59 |
-
vectorstore = FAISS.from_texts(texts=text_chunks, embedding=embedding)
|
60 |
-
return vectorstore
|
61 |
-
|
62 |
-
def get_conversation_chain(vectorstore):
|
63 |
-
llm = ChatOpenAI(model="gpt-3.5-turbo",temperature=0.5, max_tokens=2048)
|
64 |
-
retriever=vectorstore.as_retriever()
|
65 |
-
prompt = hub.pull("rlm/rag-prompt")
|
66 |
-
|
67 |
-
# Chain
|
68 |
-
rag_chain = (
|
69 |
-
{"context": retriever , "question": RunnablePassthrough()}
|
70 |
-
| prompt
|
71 |
-
| llm
|
72 |
-
)
|
73 |
-
return rag_chain
|
74 |
-
|
75 |
-
def verify_and_complete_urls(urls):
|
76 |
-
for i in range(len(urls)):
|
77 |
-
is_valid, urls[i] = complete_and_verify_url(urls[i])
|
78 |
-
return urls
|
79 |
-
|
80 |
-
def rag_pdf_web():
|
81 |
-
|
82 |
-
load_dotenv()
|
83 |
-
st.header("INDIQUEZ VOS PAGES WEB ET/OU DOCUMENTS D’ENTREPRISE POUR AUDITER LE CONTENU RSE")
|
84 |
-
|
85 |
-
option = st.radio("Source", ("A partir de votre site web", "A partir de vos documents entreprise"))
|
86 |
-
|
87 |
-
vectorstore = None
|
88 |
-
chain = None
|
89 |
-
|
90 |
-
if option == "A partir de votre site web":
|
91 |
-
url1 = st.text_input("URL 1")
|
92 |
-
url2 = st.text_input("URL 2")
|
93 |
-
url3 = st.text_input("URL 3")
|
94 |
-
# Process the URLs
|
95 |
-
sous_options = st.radio("Choisissez votre sous-section", ("Ambition, Vision, Missions, Valeurs", "3 piliers de la démarche RSE"))
|
96 |
-
try:
|
97 |
-
if st.button("Process"):
|
98 |
-
with st.spinner("Processing..."):
|
99 |
-
#get text from the website
|
100 |
-
urls = [url1, url2, url3]
|
101 |
-
filtered_urls = [url for url in urls if url]
|
102 |
-
|
103 |
-
#verify and complete urls
|
104 |
-
filtered_urls = verify_and_complete_urls(filtered_urls)
|
105 |
-
|
106 |
-
#get text from the website
|
107 |
-
docs = get_docs_from_website(filtered_urls)
|
108 |
-
|
109 |
-
#get text chunks
|
110 |
-
text_chunks = get_doc_chunks(docs)
|
111 |
-
|
112 |
-
#create vectorstore
|
113 |
-
vectorstore = get_vectorstore_from_docs(text_chunks)
|
114 |
-
|
115 |
-
chain = get_conversation_chain(vectorstore)
|
116 |
-
|
117 |
-
if sous_options == "Ambition, Vision, Missions, Valeurs":
|
118 |
-
# question = '''voici les 4 points à génerer absolument, pas de reponse comme je ne sais pas; et n'oublie aucun des points , chaque paragraphe doit être de minimum 150 caractères:
|
119 |
-
# \n
|
120 |
-
# ### Ambition : \n
|
121 |
-
# Quelle est l'ambition de l'entreprise ? (répondre avec maximum 250 caractères)
|
122 |
-
# \n
|
123 |
-
# ### Vision : \n
|
124 |
-
# Quelle est la vision de l'entreprise ? (répondre avec maximum 250 caractères)
|
125 |
-
# \n
|
126 |
-
# ### Missions : \n
|
127 |
-
# Quelles sont les missions de l'entreprise ? (répondre avec maximum 250 caractères)
|
128 |
-
# \n
|
129 |
-
# renvoie ta réponse en markdown et bien formatée'''
|
130 |
-
# response = chain.invoke(question)
|
131 |
-
# st.markdown(response.content)
|
132 |
-
|
133 |
-
#ambition
|
134 |
-
ambition = chain.invoke("Quelle est l'ambition de l'entreprise ? (répondre avec maximum 250 caractères)")
|
135 |
-
st.markdown("### Ambition :")
|
136 |
-
st.markdown(ambition.content)
|
137 |
-
|
138 |
-
#vision
|
139 |
-
ambition = chain.invoke(" Quelle est la vision de l'entreprise ? (répondre avec maximum 250 caractères)")
|
140 |
-
st.markdown("### Vision :")
|
141 |
-
st.markdown(ambition.content)
|
142 |
-
|
143 |
-
#Mission
|
144 |
-
ambition = chain.invoke(" Quelle est la vision de l'entreprise ? (répondre avec maximum 250 caractères)")
|
145 |
-
st.markdown("### Mission :")
|
146 |
-
st.markdown(ambition.content)
|
147 |
-
|
148 |
-
#values
|
149 |
-
values = chain.invoke("Quels sont les valeurs de l'entreprise ? (répondre avec 10 mots maximum en bullet points)")
|
150 |
-
st.markdown("### Valeurs :")
|
151 |
-
st.markdown(values.content)
|
152 |
-
|
153 |
-
elif sous_options == "3 piliers de la démarche RSE":
|
154 |
-
question = ''' suggère nous les 3 piliers principaux de la démarche RSE pour cette entreprise. N'oublie aucun pilier RSE , ca doit avoir ce format :
|
155 |
-
\n
|
156 |
-
### le titre du pilier numero 1 \n
|
157 |
-
-la description du pilier (répondre avec maximum 250 caractères)
|
158 |
-
\n
|
159 |
-
- 2 indicateurs cibles pertinents à atteindre avec suggestion de valeur cible min, max
|
160 |
-
\n
|
161 |
-
### le titre du pilier numero 2 \n
|
162 |
-
-la description du pilier (répondre avec maximum 250 caractères)
|
163 |
-
\n
|
164 |
-
- 2 indicateurs cibles pertinents à atteindre avec suggestion de valeur cible min, max
|
165 |
-
\n
|
166 |
-
### le titre du pilier numero 3 \n
|
167 |
-
-la description du pilier (répondre avec maximum 250 caractères)
|
168 |
-
\n
|
169 |
-
- 2 indicateurs cibles pertinents à atteindre avec suggestion de valeur cible min, max
|
170 |
-
\n
|
171 |
-
renvoie ta réponse en markdown et bien formatée
|
172 |
-
'''
|
173 |
-
response = chain.invoke(question)
|
174 |
-
st.markdown(response.content)
|
175 |
-
except Exception as e:
|
176 |
-
st.error(f"Une erreur s'est produite : Url non valide ou problème de connexion à internet. Veuillez réessayer.")
|
177 |
-
|
178 |
-
if option == "A partir de vos documents entreprise":
|
179 |
-
pdf_docs = st.file_uploader("Upload les documents concernant la marque (maximum 3 fichiers de taille max de 5 Mo)", type="pdf", accept_multiple_files=True)
|
180 |
-
# Process the PDF documents
|
181 |
-
sous_options = st.radio("Choisissez votre sous-section", ("Ambition, Vision, Missions, Valeurs", "3 piliers de la démarche RSE"))
|
182 |
-
try:
|
183 |
-
if st.button("Process"):
|
184 |
-
with st.spinner("Processing..."):
|
185 |
-
#get pdf text in raw format
|
186 |
-
raw_text = get_pdf_text(pdf_docs)
|
187 |
-
|
188 |
-
#get text chunks
|
189 |
-
text_chunks = get_text_chunks(raw_text)
|
190 |
-
|
191 |
-
#create vectorstore
|
192 |
-
vectorstore = get_vectorstore(text_chunks)
|
193 |
-
|
194 |
-
chain = get_conversation_chain(vectorstore)
|
195 |
-
|
196 |
-
if sous_options == "Ambition, Vision, Missions, Valeurs":
|
197 |
-
|
198 |
-
#ambition
|
199 |
-
ambition = chain.invoke("Quelle est l'ambition de l'entreprise ? (répondre avec maximum 250 caractères)")
|
200 |
-
st.markdown("### Ambition :")
|
201 |
-
st.markdown(ambition.content)
|
202 |
-
|
203 |
-
#vision
|
204 |
-
ambition = chain.invoke(" Quelle est la vision de l'entreprise ? (répondre avec maximum 250 caractères)")
|
205 |
-
st.markdown("### Vision :")
|
206 |
-
st.markdown(ambition.content)
|
207 |
-
|
208 |
-
#Mission
|
209 |
-
ambition = chain.invoke(" Quelle est la vision de l'entreprise ? (répondre avec maximum 250 caractères)")
|
210 |
-
st.markdown("### Mission :")
|
211 |
-
st.markdown(ambition.content)
|
212 |
-
|
213 |
-
#values
|
214 |
-
values = chain.invoke("Quels sont les valeurs de l'entreprise ? (répondre avec 10 mots maximum en bullet points)")
|
215 |
-
st.markdown("### Valeurs :")
|
216 |
-
st.markdown(values.content)
|
217 |
-
|
218 |
-
elif sous_options == "3 piliers de la démarche RSE":
|
219 |
-
question = ''' suggère nous les 3 piliers principaux de la démarche RSE pour cette entreprise. Pour chaque pilier RSE doit avoir ce format :
|
220 |
-
\n
|
221 |
-
### le titre du ieme pilier \n
|
222 |
-
-la description du pilier (répondre avec maximum 250 caractères)
|
223 |
-
\n
|
224 |
-
- 2 indicateurs cibles pertinents à atteindre avec suggestion de valeur cible min, max
|
225 |
-
\n
|
226 |
-
renvoie ta réponse en markdown et bien formatée
|
227 |
-
'''
|
228 |
-
response = chain.invoke(question)
|
229 |
-
st.markdown(response.content)
|
230 |
-
except Exception as e:
|
231 |
-
st.error(f"Une erreur s'est produite : Pdf non valide ou problème de connexion à internet. Veuillez réessayer.")
|
232 |
-
|
233 |
-
if vectorstore and chain:
|
234 |
-
set_rag(vectorstore, chain)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
README.md
CHANGED
@@ -1,12 +1,13 @@
|
|
1 |
---
|
2 |
-
title:
|
3 |
-
emoji:
|
4 |
-
colorFrom:
|
5 |
-
colorTo:
|
6 |
sdk: streamlit
|
7 |
-
sdk_version: 1.
|
8 |
app_file: app.py
|
9 |
pinned: false
|
|
|
10 |
---
|
11 |
|
12 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
1 |
---
|
2 |
+
title: OpenData Projet RSE
|
3 |
+
emoji: 📈
|
4 |
+
colorFrom: red
|
5 |
+
colorTo: yellow
|
6 |
sdk: streamlit
|
7 |
+
sdk_version: 1.32.2
|
8 |
app_file: app.py
|
9 |
pinned: false
|
10 |
+
license: mit
|
11 |
---
|
12 |
|
13 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
app.py
CHANGED
@@ -8,9 +8,6 @@ from statistiques import main as display_statistics
|
|
8 |
from ActionsRSE import display_actions_rse
|
9 |
from AnalyseActionsRSE import display_analyse_actions_rse
|
10 |
from partiesprenantes import display_materiality_partiesprenantes
|
11 |
-
from partie_prenante_carte import display_pp
|
12 |
-
from codecarbon import EmissionsTracker
|
13 |
-
|
14 |
|
15 |
# Import modifiédes fonctions liées aux scripts
|
16 |
from projetRSE import display_rse_projects
|
@@ -19,44 +16,14 @@ from entreprises_labellisees import display_labelled_companies
|
|
19 |
from inspirezvous import *
|
20 |
from collaborons import display_company_selection_for_materiality,display_materiality_matrix
|
21 |
from documentations import display_documentation
|
22 |
-
from RAG_PDF_WEB import rag_pdf_web
|
23 |
-
from prompt import get_prompts_list,prompt_execution,execute_prompt
|
24 |
-
from chat_with_pps import display_chat
|
25 |
-
from high_chart import test_chart
|
26 |
-
from chat_te import display_chat_te
|
27 |
-
from empreinte_carbone import *
|
28 |
-
from comparateur import *
|
29 |
-
import base64
|
30 |
-
import pandas as pd
|
31 |
-
|
32 |
-
|
33 |
-
# Function to read and encode an SVG file to Base64
|
34 |
-
def load_svg_as_base64(file_path):
|
35 |
-
with open(file_path, "rb") as f:
|
36 |
-
svg_data = f.read()
|
37 |
-
return base64.b64encode(svg_data).decode()
|
38 |
|
39 |
def main():
|
40 |
-
|
41 |
-
if "emission" not in st.session_state:
|
42 |
-
tracker = EmissionsTracker()
|
43 |
-
tracker.start()
|
44 |
-
st.session_state["emission"] = tracker
|
45 |
-
|
46 |
-
if "partial_emissions" not in st.session_state:
|
47 |
-
st.session_state["partial_emissions"] = {
|
48 |
-
"Scrapping": {"cc": 0, "el": 0}, #cc for codecarbon , el for ecologits
|
49 |
-
"extraction_pp": {"cc": 0, "el": 0},
|
50 |
-
"cartographie": {"cc": 0, "el": 0},
|
51 |
-
"chatbot": {"cc": 0, "el": 0},
|
52 |
-
"download_rapport": {"cc": 0, "el": 0},
|
53 |
-
}
|
54 |
|
55 |
st.sidebar.title("OPEN DATA & IA au service de la RSE")
|
56 |
section_principale = st.sidebar.radio(
|
57 |
"Choisissez votre section",
|
58 |
-
["Data Bordeaux métropole", "Data bziiit","IA RSE","Documentation"]
|
59 |
-
index=2
|
60 |
)
|
61 |
|
62 |
if section_principale == "Data Bordeaux métropole":
|
@@ -93,62 +60,30 @@ def main():
|
|
93 |
elif section_principale == "IA RSE":
|
94 |
ia_mode = st.sidebar.radio(
|
95 |
"Choisissez votre sous-section",
|
96 |
-
[
|
97 |
-
"Audit flash RSE de vos contenus",
|
98 |
-
"Parties prenantes",
|
99 |
-
"Chatbot Parties Prenantes",
|
100 |
-
"Empreinte carbone détaillée",
|
101 |
-
# "Prompts RSE - TE",
|
102 |
-
# "Chatbot RSE - TE",
|
103 |
-
],
|
104 |
-
index=1
|
105 |
)
|
106 |
-
|
107 |
if ia_mode == "Parties prenantes":
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
# if selected_company:
|
118 |
-
# display_materiality_matrix(selected_company, data, bziiit_data)
|
119 |
-
|
120 |
-
elif ia_mode == "Chatbot Parties Prenantes":
|
121 |
-
display_chat()
|
122 |
-
|
123 |
-
elif ia_mode == "Audit flash RSE de vos contenus":
|
124 |
-
rag_pdf_web()
|
125 |
-
|
126 |
-
elif ia_mode == "Prompts RSE - TE":
|
127 |
-
get_prompts_list()
|
128 |
-
|
129 |
-
# elif ia_mode == "Générations de contenus RSE":
|
130 |
-
# st.header("Exécutez un prompt")
|
131 |
|
132 |
-
# selected_prompt = prompt_execution()
|
133 |
-
# if selected_prompt:
|
134 |
-
# execute_prompt(selected_prompt)
|
135 |
-
elif ia_mode == "Chatbot RSE - TE":
|
136 |
-
display_chat_te()
|
137 |
-
|
138 |
-
elif ia_mode == "Empreinte carbone détaillée":
|
139 |
-
display_carbon_footprint()
|
140 |
|
141 |
elif section_principale == "Documentation":
|
142 |
display_documentation()
|
143 |
|
144 |
-
|
145 |
-
st.sidebar.markdown("---")
|
146 |
-
display_cf_comparison(st.sidebar)
|
147 |
# Instructions communes à toutes les sections
|
148 |
st.sidebar.markdown("---")
|
149 |
st.sidebar.markdown("Powered by **bziiit IA RSE**")
|
150 |
st.sidebar.markdown("2024 : Open source en Licence MIT")
|
151 |
st.sidebar.markdown("[email protected]")
|
152 |
-
|
|
|
153 |
if __name__ == "__main__":
|
154 |
main()
|
|
|
8 |
from ActionsRSE import display_actions_rse
|
9 |
from AnalyseActionsRSE import display_analyse_actions_rse
|
10 |
from partiesprenantes import display_materiality_partiesprenantes
|
|
|
|
|
|
|
11 |
|
12 |
# Import modifiédes fonctions liées aux scripts
|
13 |
from projetRSE import display_rse_projects
|
|
|
16 |
from inspirezvous import *
|
17 |
from collaborons import display_company_selection_for_materiality,display_materiality_matrix
|
18 |
from documentations import display_documentation
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
|
20 |
def main():
|
21 |
+
st.markdown(":point_left: Cliquez pour vous inspirer", unsafe_allow_html=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
|
23 |
st.sidebar.title("OPEN DATA & IA au service de la RSE")
|
24 |
section_principale = st.sidebar.radio(
|
25 |
"Choisissez votre section",
|
26 |
+
["Data Bordeaux métropole", "Data bziiit","IA RSE","Documentation"]
|
|
|
27 |
)
|
28 |
|
29 |
if section_principale == "Data Bordeaux métropole":
|
|
|
60 |
elif section_principale == "IA RSE":
|
61 |
ia_mode = st.sidebar.radio(
|
62 |
"Choisissez votre sous-section",
|
63 |
+
["Parties prenantes", "Matrice de matérialité"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
)
|
|
|
65 |
if ia_mode == "Parties prenantes":
|
66 |
+
data, bziiit_data = fetch_data()
|
67 |
+
selected_company = display_company_selection_for_materiality(data)
|
68 |
+
if selected_company:
|
69 |
+
display_materiality_partiesprenantes(selected_company, data, bziiit_data)
|
70 |
+
elif ia_mode == "Matrice de matérialité":
|
71 |
+
data, bziiit_data = fetch_data()
|
72 |
+
selected_company = display_company_selection_for_materiality(data)
|
73 |
+
if selected_company:
|
74 |
+
display_materiality_matrix(selected_company, data, bziiit_data)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
|
77 |
elif section_principale == "Documentation":
|
78 |
display_documentation()
|
79 |
|
80 |
+
|
|
|
|
|
81 |
# Instructions communes à toutes les sections
|
82 |
st.sidebar.markdown("---")
|
83 |
st.sidebar.markdown("Powered by **bziiit IA RSE**")
|
84 |
st.sidebar.markdown("2024 : Open source en Licence MIT")
|
85 |
st.sidebar.markdown("[email protected]")
|
86 |
+
st.sidebar.markdown("---")
|
87 |
+
|
88 |
if __name__ == "__main__":
|
89 |
main()
|
chart.png
DELETED
Binary file (22.5 kB)
|
|
chat_te.py
DELETED
@@ -1,127 +0,0 @@
|
|
1 |
-
import streamlit as st
|
2 |
-
from langchain_core.messages import AIMessage, HumanMessage
|
3 |
-
from langchain_community.chat_models import ChatOpenAI
|
4 |
-
from dotenv import load_dotenv
|
5 |
-
from langchain_core.output_parsers import StrOutputParser
|
6 |
-
from langchain_core.prompts import ChatPromptTemplate
|
7 |
-
from download_chart import construct_plot
|
8 |
-
from langchain_core.runnables import RunnablePassthrough
|
9 |
-
from langchain import hub
|
10 |
-
from langchain_core.prompts.prompt import PromptTemplate
|
11 |
-
from langchain_community.vectorstores import FAISS
|
12 |
-
from langchain_community.embeddings import OpenAIEmbeddings
|
13 |
-
from langchain_community.document_loaders import PyPDFLoader
|
14 |
-
from langchain_experimental.text_splitter import SemanticChunker
|
15 |
-
load_dotenv()
|
16 |
-
|
17 |
-
def get_docs_from_pdf(file):
|
18 |
-
loader = PyPDFLoader(file)
|
19 |
-
docs = loader.load_and_split()
|
20 |
-
return docs
|
21 |
-
|
22 |
-
def get_doc_chunks(docs):
|
23 |
-
text_splitter = SemanticChunker(OpenAIEmbeddings(model="text-embedding-3-small"))
|
24 |
-
chunks = text_splitter.split_documents(docs)
|
25 |
-
return chunks
|
26 |
-
|
27 |
-
def get_vectorstore_from_docs(doc_chunks):
|
28 |
-
embedding = OpenAIEmbeddings(model="text-embedding-3-small")
|
29 |
-
vectorstore = FAISS.from_documents(documents=doc_chunks, embedding=embedding)
|
30 |
-
return vectorstore
|
31 |
-
|
32 |
-
def get_conversation_chain(vectorstore):
|
33 |
-
llm = ChatOpenAI(model="gpt-4o",temperature=0.5, max_tokens=2048)
|
34 |
-
retriever=vectorstore.as_retriever()
|
35 |
-
|
36 |
-
prompt = hub.pull("rlm/rag-prompt")
|
37 |
-
# Chain
|
38 |
-
rag_chain = (
|
39 |
-
{"context": retriever , "question": RunnablePassthrough()}
|
40 |
-
| prompt
|
41 |
-
| llm
|
42 |
-
| StrOutputParser()
|
43 |
-
)
|
44 |
-
return rag_chain
|
45 |
-
|
46 |
-
def create_db(file):
|
47 |
-
# docs = get_docs_from_pdf(file)
|
48 |
-
# doc_chunks = get_doc_chunks(docs)
|
49 |
-
# vectorstore = get_vectorstore_from_docs(doc_chunks)
|
50 |
-
vectorstore = FAISS.load_local(file, OpenAIEmbeddings(model="text-embedding-3-small"),allow_dangerous_deserialization= True)
|
51 |
-
return vectorstore
|
52 |
-
|
53 |
-
def get_response(chain,user_query, chat_history):
|
54 |
-
|
55 |
-
template = """
|
56 |
-
Chat history: {chat_history}
|
57 |
-
User question: {user_question}
|
58 |
-
"""
|
59 |
-
|
60 |
-
|
61 |
-
question = ChatPromptTemplate.from_template(template)
|
62 |
-
question = question.format(chat_history=chat_history, user_question=user_query)
|
63 |
-
|
64 |
-
return chain.stream(question)
|
65 |
-
|
66 |
-
|
67 |
-
@st.dialog("Cast your vote")
|
68 |
-
def vote(item):
|
69 |
-
st.write(f"Why is {item} your favorite?")
|
70 |
-
reason = st.text_input("Because...")
|
71 |
-
if st.button("Submit"):
|
72 |
-
st.rerun()
|
73 |
-
|
74 |
-
def display_chat_te():
|
75 |
-
# app config
|
76 |
-
st.title("Chatbot")
|
77 |
-
|
78 |
-
# session state
|
79 |
-
if "chat_history_te" not in st.session_state:
|
80 |
-
st.session_state.chat_history_te = [
|
81 |
-
AIMessage(content="Salut, posez-moi vos question sur la transistion ecologique."),
|
82 |
-
]
|
83 |
-
if "chain" not in st.session_state:
|
84 |
-
db=create_db("./DATA_bziiit/vectorstore_op")
|
85 |
-
chain = get_conversation_chain(db)
|
86 |
-
st.session_state.chain = chain
|
87 |
-
|
88 |
-
# conversation
|
89 |
-
for message in st.session_state.chat_history_te:
|
90 |
-
if isinstance(message, AIMessage):
|
91 |
-
with st.chat_message("AI"):
|
92 |
-
st.write(message.content)
|
93 |
-
elif isinstance(message, HumanMessage):
|
94 |
-
with st.chat_message("Moi"):
|
95 |
-
st.write(message.content)
|
96 |
-
|
97 |
-
style = """
|
98 |
-
<style>
|
99 |
-
.css-ocqkz7 {
|
100 |
-
position: fixed;
|
101 |
-
bottom: 0;
|
102 |
-
width: 50%;
|
103 |
-
justify-content: center;
|
104 |
-
align-items: end;
|
105 |
-
margin-bottom: 0.5rem;
|
106 |
-
}
|
107 |
-
</style>
|
108 |
-
"""
|
109 |
-
# Inject the styling code for both elements
|
110 |
-
# st.markdown(style, unsafe_allow_html=True)
|
111 |
-
|
112 |
-
# # user input
|
113 |
-
# col1 , col2 = st.columns([1,8])
|
114 |
-
# if col1.button("chatbot"):
|
115 |
-
# vote("chatbot")
|
116 |
-
# with col2:
|
117 |
-
user_query = st.chat_input(placeholder="c'est quoi la transition écologique ?")
|
118 |
-
if user_query is not None and user_query != "":
|
119 |
-
st.session_state.chat_history_te.append(HumanMessage(content=user_query))
|
120 |
-
|
121 |
-
with st.chat_message("Moi"):
|
122 |
-
st.markdown(user_query)
|
123 |
-
|
124 |
-
with st.chat_message("AI"):
|
125 |
-
response = st.write_stream(get_response(st.session_state.chain,user_query, st.session_state.chat_history_te))
|
126 |
-
|
127 |
-
st.session_state.chat_history_te.append(AIMessage(content=response))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
chat_with_pps.py
DELETED
@@ -1,437 +0,0 @@
|
|
1 |
-
import streamlit as st
|
2 |
-
from langchain_core.messages import AIMessage, HumanMessage
|
3 |
-
from langchain_community.chat_models import ChatOpenAI
|
4 |
-
from dotenv import load_dotenv
|
5 |
-
from langchain_core.output_parsers import StrOutputParser
|
6 |
-
from langchain_core.prompts import ChatPromptTemplate
|
7 |
-
from langchain_mistralai.chat_models import ChatMistralAI
|
8 |
-
from download_chart import construct_plot
|
9 |
-
from prompt import get_prompts_list
|
10 |
-
from high_chart import test_chart
|
11 |
-
from export_doc import export_conversation,convert_pp_to_csv,get_conversation
|
12 |
-
import random
|
13 |
-
import pandas as pd
|
14 |
-
from codecarbon import EmissionsTracker
|
15 |
-
|
16 |
-
from ecologits.tracers.utils import compute_llm_impacts
|
17 |
-
import time
|
18 |
-
import itertools
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
load_dotenv()
|
23 |
-
def generate_random_color():
|
24 |
-
# Generate random RGB values
|
25 |
-
r = random.randint(0, 255)
|
26 |
-
g = random.randint(0, 255)
|
27 |
-
b = random.randint(0, 255)
|
28 |
-
|
29 |
-
# Convert RGB to hexadecimal
|
30 |
-
color_hex = '#{:02x}{:02x}{:02x}'.format(r, g, b)
|
31 |
-
|
32 |
-
return color_hex
|
33 |
-
|
34 |
-
def format_pp_add_viz(pp):
|
35 |
-
y = 50
|
36 |
-
x = 50
|
37 |
-
for i in range(len(st.session_state['pp_grouped'])):
|
38 |
-
if st.session_state['pp_grouped'][i]['y'] == y and st.session_state['pp_grouped'][i]['x'] == x:
|
39 |
-
y += 5
|
40 |
-
if y > 95:
|
41 |
-
y = 50
|
42 |
-
x += 5
|
43 |
-
if st.session_state['pp_grouped'][i]['name'] == pp:
|
44 |
-
return None
|
45 |
-
else:
|
46 |
-
st.session_state['pp_grouped'].append({'name':pp, 'x':x,'y':y, 'color':generate_random_color()})
|
47 |
-
|
48 |
-
|
49 |
-
def format_context(partie_prenante_grouped,marque):
|
50 |
-
context = "la marque est " + marque + ".\n"
|
51 |
-
context += f"Le nombre de parties prenantes est {len(partie_prenante_grouped)} et ils sont les suivantes:\n"
|
52 |
-
for i,partie_prenante in enumerate(partie_prenante_grouped):
|
53 |
-
context += f"{i}.{partie_prenante['name']} est une partie prenante de {marque} et a un pouvoir de {partie_prenante['y']}% et une influence de {partie_prenante['x']}%.\n"
|
54 |
-
|
55 |
-
segmentation = '''
|
56 |
-
Les parties prenantes sont segmentées en 4 catégories:
|
57 |
-
- Rendre satisfait: le pouvoir est entre 50 et 100 et l'influence est entre 0 et 50
|
58 |
-
- Gérer étroitement: le pouvoir est entre 50 et 100 et l'influence est entre 50 et 100
|
59 |
-
- Suivre de près: le pouvoir est entre 0 et 50 et l'influence est entre 0 et 50
|
60 |
-
- Tenir informé: le pouvoir est entre 0 et 50 et l'influence est entre 50 et 100
|
61 |
-
'''
|
62 |
-
|
63 |
-
context += segmentation
|
64 |
-
return context
|
65 |
-
|
66 |
-
|
67 |
-
def get_response(user_query, chat_history, context,llm=None,history_limit=5,stream=True):
|
68 |
-
|
69 |
-
template = """
|
70 |
-
Fournir des réponses, en francais, précises et contextuelles en agissant comme un expert en affaires, en utilisant le contexte des parties prenantes et leur pouvoir en pourcentage et leur influence 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.
|
71 |
-
|
72 |
-
Contexte: {context}
|
73 |
-
|
74 |
-
Chat history: {chat_history}
|
75 |
-
|
76 |
-
User question: {user_question}
|
77 |
-
"""
|
78 |
-
|
79 |
-
prompt = ChatPromptTemplate.from_template(template)
|
80 |
-
|
81 |
-
#llm = ChatOpenAI(model="gpt-4o")
|
82 |
-
if not llm:
|
83 |
-
llm = ChatOpenAI(model="gpt-4o")
|
84 |
-
elif llm == "GPT-4o":
|
85 |
-
llm = ChatOpenAI(model="gpt-4o")
|
86 |
-
elif llm == "Mistral (FR)":
|
87 |
-
llm = ChatMistralAI(model_name="mistral-large-latest")
|
88 |
-
|
89 |
-
chain = prompt | llm
|
90 |
-
|
91 |
-
if not stream:
|
92 |
-
return chain.invoke({
|
93 |
-
"context": context,
|
94 |
-
"chat_history": chat_history[-history_limit:],
|
95 |
-
"user_question": user_query,
|
96 |
-
})
|
97 |
-
|
98 |
-
chain = chain | StrOutputParser()
|
99 |
-
|
100 |
-
if history_limit:
|
101 |
-
return chain.stream({
|
102 |
-
"context": context,
|
103 |
-
"chat_history": chat_history[-history_limit:],
|
104 |
-
"user_question": user_query,
|
105 |
-
})
|
106 |
-
|
107 |
-
return chain.stream({
|
108 |
-
"context": context,
|
109 |
-
"chat_history": chat_history,
|
110 |
-
"user_question": user_query,
|
111 |
-
})
|
112 |
-
|
113 |
-
|
114 |
-
def get_response_with_impact(user_query, chat_history, context,llm=None,history_limit=5,stream=True):
|
115 |
-
model_vs_provider = {
|
116 |
-
"Mistral (FR)": ["mistral-large-latest","mistralai"],
|
117 |
-
"GPT-4o": ["gpt-4o","openai"]
|
118 |
-
}
|
119 |
-
|
120 |
-
if not stream:
|
121 |
-
|
122 |
-
start = time.perf_counter()
|
123 |
-
response = get_response(user_query, chat_history, context,llm,history_limit,stream)
|
124 |
-
request_latency = time.perf_counter() - start
|
125 |
-
token_count = response.response_metadata["token_usage"]["completion_tokens"]
|
126 |
-
|
127 |
-
nbre_out_tokens = token_count
|
128 |
-
model_name = model_vs_provider[st.session_state.model][0]
|
129 |
-
model_provider = model_vs_provider[st.session_state.model][1]
|
130 |
-
|
131 |
-
impact = compute_llm_impacts(
|
132 |
-
provider=model_provider,
|
133 |
-
model_name=model_name,
|
134 |
-
output_token_count=nbre_out_tokens,
|
135 |
-
request_latency=request_latency,
|
136 |
-
)
|
137 |
-
|
138 |
-
print(f"Request latency: {request_latency:.3f} s")
|
139 |
-
print(f"Output token count: {nbre_out_tokens}")
|
140 |
-
print(f"Impact: {impact.gwp.value} {impact.gwp.unit}")
|
141 |
-
|
142 |
-
st.session_state["partial_emissions"]["chatbot"]["el"] += impact.gwp.value
|
143 |
-
|
144 |
-
return response.content
|
145 |
-
|
146 |
-
else:
|
147 |
-
start = time.perf_counter()
|
148 |
-
response_generator = get_response(user_query, chat_history, context,llm,history_limit,stream)
|
149 |
-
wrapped_response_generator, token_count_generator = itertools.tee(response_generator)
|
150 |
-
token_count = 0
|
151 |
-
|
152 |
-
final_response = st.write_stream(wrapped_response_generator)
|
153 |
-
|
154 |
-
request_latency = time.perf_counter() - start
|
155 |
-
|
156 |
-
for _ in token_count_generator:
|
157 |
-
token_count += 1
|
158 |
-
|
159 |
-
nbre_out_tokens = token_count
|
160 |
-
model_name = model_vs_provider[st.session_state.model][0]
|
161 |
-
model_provider = model_vs_provider[st.session_state.model][1]
|
162 |
-
|
163 |
-
|
164 |
-
impact = compute_llm_impacts(
|
165 |
-
provider=model_provider,
|
166 |
-
model_name=model_name,
|
167 |
-
output_token_count=nbre_out_tokens,
|
168 |
-
request_latency=request_latency,
|
169 |
-
)
|
170 |
-
|
171 |
-
print(f"Request latency: {request_latency:.3f} s")
|
172 |
-
print(f"Output token count: {nbre_out_tokens}")
|
173 |
-
print(f"Impact: {impact.gwp.value} {impact.gwp.unit}")
|
174 |
-
|
175 |
-
st.session_state["partial_emissions"]["chatbot"]["el"] += impact.gwp.value
|
176 |
-
|
177 |
-
return final_response
|
178 |
-
|
179 |
-
|
180 |
-
def display_chart():
|
181 |
-
if "pp_grouped" not in st.session_state or st.session_state['pp_grouped'] is None or len(st.session_state['pp_grouped']) == 0:
|
182 |
-
st.warning("Aucune partie prenante n'a été définie")
|
183 |
-
return None
|
184 |
-
plot = construct_plot()
|
185 |
-
st.plotly_chart(plot)
|
186 |
-
|
187 |
-
@st.dialog("Choisissez un prompt",width="large")
|
188 |
-
def show_prompts():
|
189 |
-
get_prompts_list()
|
190 |
-
if st.button("Fermer"):
|
191 |
-
st.rerun()
|
192 |
-
|
193 |
-
@st.dialog("Choisissez votre IA",width="small")
|
194 |
-
def choose_model(index):
|
195 |
-
|
196 |
-
model = st.radio("Choisissez votre IA", ["(US) ChatGpt 4.o","(FR) Mistral AI - Large (open source)"],index=index)
|
197 |
-
if model == "(FR) Mistral AI - Large (open source)":
|
198 |
-
st.session_state.model = "Mistral (FR)"
|
199 |
-
if model == "(US) ChatGpt 4.o":
|
200 |
-
st.session_state.model = "GPT-4o"
|
201 |
-
if st.button("Valider"):
|
202 |
-
st.rerun()
|
203 |
-
|
204 |
-
@st.dialog("Ma cartographie",width="large")
|
205 |
-
def disp_carto_in_chat():
|
206 |
-
if test_chart() == "saved":
|
207 |
-
st.rerun()
|
208 |
-
|
209 |
-
@st.dialog("Télécharger",width="small")
|
210 |
-
def dowmload_history(used_models=None):
|
211 |
-
brand_name = st.session_state['Nom de la marque']
|
212 |
-
|
213 |
-
format = st.radio("Choisissez le document à télécharger",[f"Rapport des parties prenantes (PDF)",f"Tableau des parties prenantes (CSV)",f"Historique de conversation (Fichier Texte)"],index=None)
|
214 |
-
if format == f"Rapport des parties prenantes (PDF)":
|
215 |
-
with st.spinner("Generation en cours..."):
|
216 |
-
summary = get_response("Donne moi un RESUME de la Conversation", st.session_state.chat_history,format_context(st.session_state['pp_grouped'],st.session_state['Nom de la marque']),st.session_state.model)
|
217 |
-
summary = ''.join(summary)
|
218 |
-
pdf = export_conversation(AIMessage(content=summary).content,used_models=used_models)
|
219 |
-
|
220 |
-
st.session_state["partial_emissions"]["download_rapport"]["cc"] = st.session_state["emission"].stop()
|
221 |
-
|
222 |
-
if pdf:
|
223 |
-
st.download_button("Télécharger le PDF", data=pdf, file_name=f"Cartographie {brand_name}.pdf", mime="application/pdf")
|
224 |
-
|
225 |
-
if format == f"Tableau des parties prenantes (CSV)":
|
226 |
-
csv = convert_pp_to_csv(st.session_state['pp_grouped'])
|
227 |
-
if csv:
|
228 |
-
st.download_button("Télécharger le CSV", data=csv, file_name=f"parties_prenantes -{brand_name}-.csv", mime="application/vnd.ms-excel")
|
229 |
-
|
230 |
-
if format == f"Historique de conversation (Fichier Texte)":
|
231 |
-
conv = get_conversation()
|
232 |
-
if not conv:
|
233 |
-
st.error("Une erreur s'est produite lors de la récupération de l'historique de conversation")
|
234 |
-
return None
|
235 |
-
else:
|
236 |
-
conversation = "\n".join([f"{entry['speaker']}:\n{entry['text']}\n" for entry in conv])
|
237 |
-
st.download_button("Télécharger l'historique de conversation", data=conversation, file_name=f"conversation {brand_name}.txt", mime="text/plain")
|
238 |
-
|
239 |
-
if st.button("Fermer"):
|
240 |
-
st.rerun()
|
241 |
-
|
242 |
-
def add_existing_pps(pp,pouvoir,influence):
|
243 |
-
for i in range(len(st.session_state['pp_grouped'])):
|
244 |
-
if st.session_state['pp_grouped'][i]['name'] == pp:
|
245 |
-
st.session_state['pp_grouped'][i]['x'] = influence
|
246 |
-
st.session_state['pp_grouped'][i]['y'] = pouvoir
|
247 |
-
return None
|
248 |
-
st.session_state['pp_grouped'].append({'name':pp, 'x':influence,'y':pouvoir, 'color':generate_random_color()})
|
249 |
-
|
250 |
-
|
251 |
-
def load_csv(file):
|
252 |
-
df = pd.read_csv(file)
|
253 |
-
for index, row in df.iterrows():
|
254 |
-
add_existing_pps(row['parties prenantes'],row['pouvoir'],row['influence'])
|
255 |
-
|
256 |
-
|
257 |
-
@st.dialog("Importer",width="small")
|
258 |
-
def import_conversation():
|
259 |
-
uploaded_file = st.file_uploader("Télécharger le fichier CSV", type="csv")
|
260 |
-
if uploaded_file is not None:
|
261 |
-
file_name = uploaded_file.name
|
262 |
-
try:
|
263 |
-
load_csv(file_name)
|
264 |
-
brand_name_from_csv = file_name.split("-")[1]
|
265 |
-
st.session_state["Nom de la marque"] = brand_name_from_csv
|
266 |
-
st.rerun()
|
267 |
-
except Exception as e:
|
268 |
-
st.error("Erreur lors de la lecture du fichier")
|
269 |
-
|
270 |
-
def extract_format_prompts_from_response(response):
|
271 |
-
st.markdown("---")
|
272 |
-
st.markdown("**En découvrir plus avec l'IA RSE bziiit**")
|
273 |
-
prompts = response.split("\n")
|
274 |
-
prompts = [prompt.strip() for prompt in prompts if prompt.strip() != ""]
|
275 |
-
prompts_container = st.container()
|
276 |
-
with prompts_container:
|
277 |
-
for i,prompt in enumerate(prompts):
|
278 |
-
|
279 |
-
temp_p = f"{prompt} ➡️"
|
280 |
-
st.button(temp_p,key=f"exec_{i}",on_click=lambda i=i: st.session_state.chat_history.append(HumanMessage(content=prompts[i])))
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
def extract_pp_from_query(query):
|
285 |
-
return " ".join(query.split(" ")[1:])
|
286 |
-
|
287 |
-
def display_prompts(prompts):
|
288 |
-
for i,prompt in enumerate(prompts):
|
289 |
-
col1,col2 = st.columns([9,1])
|
290 |
-
col1.markdown(f"{prompt}")
|
291 |
-
col2.button("➡️",key=f"execf_{i}",on_click=lambda i=i: st.session_state.chat_history.append(HumanMessage(content=prompts[i])))
|
292 |
-
|
293 |
-
|
294 |
-
def display_chat():
|
295 |
-
|
296 |
-
if "emission" not in st.session_state:
|
297 |
-
tracker = EmissionsTracker()
|
298 |
-
tracker.start()
|
299 |
-
st.session_state["emission"] = tracker
|
300 |
-
# app config
|
301 |
-
st.title("CHATBOT")
|
302 |
-
models_name = {
|
303 |
-
"Mistral (FR)":1,
|
304 |
-
"GPT-4o":0
|
305 |
-
}
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
generated_prompt_question = '''En fonction de l'historique, proposez trois prompts pour continuer la conversation. Utilisez les informations fournies et les implications discutées:
|
310 |
-
|
311 |
-
- Prompt 1 : [Premier prompt suggéré]
|
312 |
-
- Prompt 2 : [Deuxième prompt suggéré]
|
313 |
-
- Prompt 3 : [Troisième prompt suggéré]
|
314 |
-
|
315 |
-
LA LISTE DOIT ETRE EN FRANCAIS CHAQUE LIGNE SANS LE NUMERO DE PROMPT SEULEMENT LE TEXTE DE LA QUESTION
|
316 |
-
'''
|
317 |
-
|
318 |
-
# session state
|
319 |
-
if "chat_history" not in st.session_state:
|
320 |
-
st.session_state.chat_history = [
|
321 |
-
AIMessage(content="Salut, voici votre cartographie des parties prenantes. Que puis-je faire pour vous ?"),
|
322 |
-
]
|
323 |
-
|
324 |
-
if "model" not in st.session_state:
|
325 |
-
st.session_state.model = "GPT-4o"
|
326 |
-
|
327 |
-
if "used_models" not in st.session_state:
|
328 |
-
st.session_state.used_models = []
|
329 |
-
|
330 |
-
#sticky bar at the top
|
331 |
-
header = st.container()
|
332 |
-
col1,col2,col3, col4,col5,col6 = header.columns([2,3,2,3,2,1])
|
333 |
-
|
334 |
-
if col1.button("Prompts"):
|
335 |
-
show_prompts()
|
336 |
-
if col2.button(f"Modèle: {st.session_state.model}"):
|
337 |
-
index = models_name[st.session_state.model]
|
338 |
-
choose_model(index)
|
339 |
-
if col3.button("Ma Carto"):
|
340 |
-
disp_carto_in_chat()
|
341 |
-
if col4.button("Télécharger"):
|
342 |
-
dowmload_history(st.session_state.used_models)
|
343 |
-
header.write("""<div class='fixed-header'/>""", unsafe_allow_html=True)
|
344 |
-
|
345 |
-
# Custom CSS for the sticky header
|
346 |
-
st.markdown(
|
347 |
-
"""
|
348 |
-
<style>
|
349 |
-
div[data-testid="stVerticalBlock"] div:has(div.fixed-header) {
|
350 |
-
position: sticky;
|
351 |
-
top: 2.875rem;
|
352 |
-
background-color: white;
|
353 |
-
z-index: 999;
|
354 |
-
}
|
355 |
-
.fixed-header {
|
356 |
-
border-bottom: 0px solid black;
|
357 |
-
}
|
358 |
-
</style>
|
359 |
-
""",
|
360 |
-
unsafe_allow_html=True
|
361 |
-
)
|
362 |
-
|
363 |
-
# conversation
|
364 |
-
for message in st.session_state.chat_history:
|
365 |
-
if isinstance(message, AIMessage):
|
366 |
-
with st.chat_message("AI"):
|
367 |
-
st.write(message.content)
|
368 |
-
if "cartographie" in message.content:
|
369 |
-
st.markdown("\n")
|
370 |
-
display_chart()
|
371 |
-
if message.content == st.session_state.chat_history[0].content:
|
372 |
-
st.markdown("---")
|
373 |
-
st.markdown("**En découvrir plus avec l'IA RSE bziiit**")
|
374 |
-
first_prompts = ["En plus des parties prenantes déjà identifiées que tu peux consulter, quels groupes ou individus, impactés par les activités de mon organisation, devrais-je ajouter dans notre cartographie des parties prenantes ?",
|
375 |
-
"Quels sont les principaux acteurs internes et externes qui influencent ou sont influencés par mon organisation, et comment leurs intérêts ou préoccupations peuvent varier selon les différents domaines d'activité ?",
|
376 |
-
"En tenant compte de ma chaîne de valeur complète, quels sont les différentes parties prenantes stratégiques, incluant les partenaires commerciaux, les régulateurs, les groupes de pression, et la communauté, et comment leurs rôles et influences interagissent pour affecter les objectifs à court et long terme de mon organisation ?"]
|
377 |
-
display_prompts(first_prompts)
|
378 |
-
elif isinstance(message, HumanMessage):
|
379 |
-
with st.chat_message("Moi"):
|
380 |
-
st.write(message.content)
|
381 |
-
|
382 |
-
#check if the last message is from the user , that means execute button has been clicked in the prompts
|
383 |
-
last_message = st.session_state.chat_history[-1]
|
384 |
-
if isinstance(last_message, HumanMessage):
|
385 |
-
with st.chat_message("AI"):
|
386 |
-
if last_message.content.startswith("/rajoute"):
|
387 |
-
response = "Partie prenante ajoutée"
|
388 |
-
st.write(response)
|
389 |
-
st.session_state.chat_history.append(AIMessage(content=response))
|
390 |
-
else:
|
391 |
-
st.markdown(f"**{st.session_state.model}**")
|
392 |
-
if st.session_state.model not in st.session_state.used_models:
|
393 |
-
st.session_state.used_models.append(st.session_state.model)
|
394 |
-
response = get_response_with_impact(last_message.content, st.session_state.chat_history,format_context(st.session_state['pp_grouped'],st.session_state['Nom de la marque']),st.session_state.model)
|
395 |
-
st.session_state.chat_history.append(AIMessage(content=response))
|
396 |
-
with st.spinner("Proposition de prompts..."):
|
397 |
-
propositions_prompts = get_response_with_impact(generated_prompt_question, st.session_state.chat_history,format_context(st.session_state['pp_grouped'],st.session_state['Nom de la marque']),st.session_state.model,history_limit=1,stream=False)
|
398 |
-
extract_format_prompts_from_response(propositions_prompts)
|
399 |
-
st.session_state["partial_emissions"]["chatbot"]["cc"] = st.session_state["emission"].stop()
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
if "pp_grouped" not in st.session_state or st.session_state['pp_grouped'] is None or len(st.session_state['pp_grouped']) == 0:
|
404 |
-
st.session_state['pp_grouped'] = []
|
405 |
-
if "Nom de la marque" not in st.session_state:
|
406 |
-
st.session_state["Nom de la marque"] = ""
|
407 |
-
|
408 |
-
# user input
|
409 |
-
user_query = st.chat_input("Par ici...")
|
410 |
-
if user_query is not None and user_query != "":
|
411 |
-
st.session_state.chat_history.append(HumanMessage(content=user_query))
|
412 |
-
|
413 |
-
with st.chat_message("Moi"):
|
414 |
-
st.markdown(user_query)
|
415 |
-
with st.chat_message("AI"):
|
416 |
-
st.markdown(f"**{st.session_state.model}**")
|
417 |
-
if st.session_state.model not in st.session_state.used_models:
|
418 |
-
st.session_state.used_models.append(st.session_state.model)
|
419 |
-
if user_query.startswith("/rajoute"):
|
420 |
-
partie_prenante = extract_pp_from_query(user_query)
|
421 |
-
format_pp_add_viz(partie_prenante)
|
422 |
-
disp_carto_in_chat()
|
423 |
-
else:
|
424 |
-
#response = st.write_stream(get_response(user_query, st.session_state.chat_history,format_context(st.session_state['pp_grouped'],st.session_state['Nom de la marque']),st.session_state.model))
|
425 |
-
response = get_response_with_impact(user_query, st.session_state.chat_history,format_context(st.session_state['pp_grouped'],st.session_state['Nom de la marque']),st.session_state.model)
|
426 |
-
|
427 |
-
st.session_state.chat_history.append(AIMessage(content=response))
|
428 |
-
|
429 |
-
with st.spinner("Proposition de prompts..."):
|
430 |
-
propositions_prompts = get_response_with_impact(generated_prompt_question, st.session_state.chat_history,format_context(st.session_state['pp_grouped'],st.session_state['Nom de la marque']),st.session_state.model,history_limit=1,stream=False)
|
431 |
-
extract_format_prompts_from_response(propositions_prompts)
|
432 |
-
st.session_state["partial_emissions"]["chatbot"]["cc"] = st.session_state["emission"].stop()
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
collaborons.py
CHANGED
@@ -59,7 +59,6 @@ def perform_chat(messages):
|
|
59 |
client = openai.OpenAI(api_key=YOUR_API_KEY, base_url="https://api.perplexity.ai")
|
60 |
|
61 |
response_stream = client.chat.completions.create(
|
62 |
-
|
63 |
model="sonar-medium-online",
|
64 |
messages=messages,
|
65 |
stream=True
|
|
|
59 |
client = openai.OpenAI(api_key=YOUR_API_KEY, base_url="https://api.perplexity.ai")
|
60 |
|
61 |
response_stream = client.chat.completions.create(
|
|
|
62 |
model="sonar-medium-online",
|
63 |
messages=messages,
|
64 |
stream=True
|
comparateur.py
DELETED
@@ -1,54 +0,0 @@
|
|
1 |
-
|
2 |
-
import streamlit as st
|
3 |
-
import pandas as pd
|
4 |
-
|
5 |
-
dict_comparaison_1kgCO2 = {
|
6 |
-
"eau en litre":[374/100,"https://impactco2.fr/icons/eauenbouteille.svg"],
|
7 |
-
"smartphones": [1.16/100,"https://impactco2.fr/icons/smartphone.svg"],
|
8 |
-
"voiture en km": [460/100,"https://impactco2.fr/icons/voiturethermique.svg"],
|
9 |
-
"tgv en km":[34130/100,"https://impactco2.fr/icons/tgv.svg"],
|
10 |
-
}
|
11 |
-
|
12 |
-
def compare(value_init, ratio_equivalent):
|
13 |
-
return ratio_equivalent * value_init if ratio_equivalent else None
|
14 |
-
|
15 |
-
def display_comparaison(container,value_init, ratio_equivalent,icon, unit):
|
16 |
-
#value_init must be in kgCO2
|
17 |
-
link_url = f"https://impactco2.fr/outils/comparateur?value={value_init}&comparisons=tgv,eauenbouteille,voiturethermique"
|
18 |
-
container.markdown(f"<div style='text-align: center;'><a href='{link_url}' target='_blank'><img src='{icon}' alt='{unit}' width='50'></div>", unsafe_allow_html=True)
|
19 |
-
container.markdown(f"<div style='text-align: center;'><b>{compare(value_init, ratio_equivalent):.2f}</b> {unit}</div>", unsafe_allow_html=True)
|
20 |
-
|
21 |
-
def custom_cumsum(ecologits_series, codecarbon_series):
|
22 |
-
cumsum = 0
|
23 |
-
result = []
|
24 |
-
for eco, code in zip(ecologits_series, codecarbon_series):
|
25 |
-
if code == 0:
|
26 |
-
result.append(0)
|
27 |
-
else:
|
28 |
-
cumsum += eco
|
29 |
-
result.append(cumsum)
|
30 |
-
return pd.Series(result, index=ecologits_series.index)
|
31 |
-
|
32 |
-
|
33 |
-
def get_table_empreintes_detailed() -> pd.DataFrame:
|
34 |
-
emissions_data = st.session_state["partial_emissions"]
|
35 |
-
emissions_df = pd.DataFrame(emissions_data).T # Transpose to match the desired format
|
36 |
-
|
37 |
-
# Rename columns and index values
|
38 |
-
emissions_df = emissions_df.rename(columns={"cc": "CodeCarbon (Cumulative)", "el": "EcoLogits (par requete)"})
|
39 |
-
emissions_df = emissions_df.applymap(lambda x: x * 1000)
|
40 |
-
emissions_df = emissions_df.round(2)
|
41 |
-
emissions_df = emissions_df.rename(index={
|
42 |
-
"Scrapping": "Collecte de documents et scrapping",
|
43 |
-
"extraction_pp": "Extraction des parties prenantes (serveur et IA)",
|
44 |
-
"cartographie": "Sauvegarde de la cartographie",
|
45 |
-
"chatbot": "Dialogue avec chatBot IA",
|
46 |
-
"download_rapport": "Téléchargement cartographie"
|
47 |
-
})
|
48 |
-
|
49 |
-
# Make Ecologits column cumulative
|
50 |
-
emissions_df["EcoLogits (Cumulative)"] = custom_cumsum(emissions_df["EcoLogits (par requete)"], emissions_df["CodeCarbon (Cumulative)"])
|
51 |
-
|
52 |
-
emissions_df['Consommation Totale'] = emissions_df["CodeCarbon (Cumulative)"] + emissions_df["EcoLogits (Cumulative)"]
|
53 |
-
emissions_df = emissions_df.round(2)
|
54 |
-
return emissions_df
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data_manager_bziiit.py
CHANGED
@@ -34,22 +34,6 @@ def get_engaged_brands():
|
|
34 |
st.error(f"Échec de récupération des marques engagées: {response.text}")
|
35 |
return []
|
36 |
|
37 |
-
# Fonction de récupération des prompts
|
38 |
-
def get_prompts():
|
39 |
-
url = f"{BASE_URL}/opendata/prompts"
|
40 |
-
response = requests.get(url)
|
41 |
-
if response.status_code == 200:
|
42 |
-
return response.json()["response"]
|
43 |
-
else:
|
44 |
-
st.error(f"Échec de récupération des marques engagées: {response.text}")
|
45 |
-
return []
|
46 |
-
|
47 |
-
def get_prompt_by_id(id):
|
48 |
-
prompts = get_prompts()
|
49 |
-
for prompt in prompts:
|
50 |
-
if prompt.get('id') == id:
|
51 |
-
return prompt
|
52 |
-
|
53 |
# Fonction consolidant les données labels + projets RSE + marques
|
54 |
def get_bziiit_data():
|
55 |
labels = get_labels()
|
|
|
34 |
st.error(f"Échec de récupération des marques engagées: {response.text}")
|
35 |
return []
|
36 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
# Fonction consolidant les données labels + projets RSE + marques
|
38 |
def get_bziiit_data():
|
39 |
labels = get_labels()
|
documentations.py
CHANGED
@@ -1,12 +1,10 @@
|
|
1 |
import streamlit as st
|
2 |
-
from comparateur import get_table_empreintes_detailed
|
3 |
|
4 |
def display_documentation():
|
5 |
|
6 |
st.markdown("<hr style='border-color: darkgrey;'>", unsafe_allow_html=True) # Add this line
|
7 |
|
8 |
st.title("OPEN DATA IA RSE Bordeaux Métropole")
|
9 |
-
|
10 |
st.markdown("## La Data et l'IA au service des démarches RSE (Economie, Social, Environnemental)")
|
11 |
|
12 |
st.image("DATA IA RSE Bordeaux Metropole.png", caption="Data IA RSE Bordeaux Metropole")
|
@@ -26,3 +24,5 @@ def display_documentation():
|
|
26 |
</div>
|
27 |
""", unsafe_allow_html=True)
|
28 |
|
|
|
|
|
|
1 |
import streamlit as st
|
|
|
2 |
|
3 |
def display_documentation():
|
4 |
|
5 |
st.markdown("<hr style='border-color: darkgrey;'>", unsafe_allow_html=True) # Add this line
|
6 |
|
7 |
st.title("OPEN DATA IA RSE Bordeaux Métropole")
|
|
|
8 |
st.markdown("## La Data et l'IA au service des démarches RSE (Economie, Social, Environnemental)")
|
9 |
|
10 |
st.image("DATA IA RSE Bordeaux Metropole.png", caption="Data IA RSE Bordeaux Metropole")
|
|
|
24 |
</div>
|
25 |
""", unsafe_allow_html=True)
|
26 |
|
27 |
+
if __name__ == "__main__":
|
28 |
+
main()
|
download_chart.py
DELETED
@@ -1,124 +0,0 @@
|
|
1 |
-
import streamlit as st
|
2 |
-
import plotly.graph_objects as go
|
3 |
-
import plotly.express as px
|
4 |
-
|
5 |
-
from PIL import Image
|
6 |
-
import pdfkit
|
7 |
-
import pandas as pd
|
8 |
-
import plotly.io as pio
|
9 |
-
import tempfile
|
10 |
-
|
11 |
-
|
12 |
-
def construct_plot():
|
13 |
-
# Define data
|
14 |
-
stakeholders = st.session_state['pp_grouped']
|
15 |
-
|
16 |
-
if stakeholders is None or len(stakeholders) == 0:
|
17 |
-
st.error("Aucune partie prenante n'a été définie")
|
18 |
-
return None
|
19 |
-
# Create plot
|
20 |
-
fig = go.Figure()
|
21 |
-
|
22 |
-
# Add category areas
|
23 |
-
fig.add_shape(type="rect", x0=0, y0=50, x1=50, y1=100, fillcolor="lightblue", opacity=0.2, line_width=0)
|
24 |
-
fig.add_shape(type="rect", x0=50, y0=50, x1=100, y1=100, fillcolor="lightyellow", opacity=0.2, line_width=0)
|
25 |
-
fig.add_shape(type="rect", x0=0, y0=0, x1=50, y1=50, fillcolor="lightcoral", opacity=0.2, line_width=0)
|
26 |
-
fig.add_shape(type="rect", x0=50, y0=0, x1=100, y1=50, fillcolor="lightcyan", opacity=0.2, line_width=0)
|
27 |
-
|
28 |
-
# Add category titles
|
29 |
-
fig.add_annotation(x=10, y=90, text="Rendre satisfait", showarrow=False)
|
30 |
-
fig.add_annotation(x=60, y=90, text="Gérer étroitement", showarrow=False)
|
31 |
-
fig.add_annotation(x=10, y=40, text="Suivre de près", showarrow=False)
|
32 |
-
fig.add_annotation(x=60, y=40, text="Tenir informé", showarrow=False)
|
33 |
-
|
34 |
-
x_array = [stakeholder['x'] for stakeholder in stakeholders]
|
35 |
-
y_array = [stakeholder['y'] for stakeholder in stakeholders]
|
36 |
-
name_array = [stakeholder['name'] for stakeholder in stakeholders]
|
37 |
-
|
38 |
-
#color_sequence = px.colors.qualitative.Plotly
|
39 |
-
# Add stakeholders to plot
|
40 |
-
for i,stakeholder in enumerate(stakeholders):
|
41 |
-
fig.add_trace(go.Scatter(
|
42 |
-
x=[stakeholder['x']],
|
43 |
-
y=[stakeholder['y']],
|
44 |
-
mode='markers+text',
|
45 |
-
marker=dict(color=stakeholder['color'],size=33),
|
46 |
-
textposition="top center",
|
47 |
-
name=stakeholder['name']
|
48 |
-
))
|
49 |
-
|
50 |
-
# Update layout
|
51 |
-
fig.update_layout(
|
52 |
-
legend=dict( orientation="h", yanchor="bottom",y=1.02,title="Parties prenantes"),
|
53 |
-
height=600,
|
54 |
-
title=dict(text="Cartographie des parties prenantes", x=0.5, y=1, xanchor="center", yanchor="top"),
|
55 |
-
xaxis=dict(title="Influence", range=[0, 100]),
|
56 |
-
yaxis=dict(title="Pouvoir", range=[0, 100]),
|
57 |
-
showlegend=True
|
58 |
-
)
|
59 |
-
|
60 |
-
# Display plot in Streamlit
|
61 |
-
return fig
|
62 |
-
|
63 |
-
def save_plot_as_pdf(fig, logo_path, title):
|
64 |
-
st.write("saving plot as pdf")
|
65 |
-
|
66 |
-
with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as tmpfile:
|
67 |
-
st.write("tmpfile created")
|
68 |
-
image_bytes = pio.to_image(fig, format='png')
|
69 |
-
st.write("image_bytes")
|
70 |
-
|
71 |
-
tmpfile.write(image_bytes)
|
72 |
-
tmpfile.close()
|
73 |
-
plot_image_path = tmpfile.name
|
74 |
-
|
75 |
-
st.write(plot_image_path)
|
76 |
-
|
77 |
-
html_content = f"""
|
78 |
-
<!DOCTYPE html>
|
79 |
-
<html lang="en">
|
80 |
-
<head>
|
81 |
-
<meta charset="UTF-8">
|
82 |
-
<title>{title}</title>
|
83 |
-
<style>
|
84 |
-
body {{ font-family: Arial, sans-serif; text-align: center; }}
|
85 |
-
.logo {{ width: 100px; margin-top: 20px; }}
|
86 |
-
.title {{ font-size: 24px; margin-top: 20px; }}
|
87 |
-
.plot-image {{ width: 80%; margin-top: 20px; }}
|
88 |
-
</style>
|
89 |
-
</head>
|
90 |
-
<body>
|
91 |
-
{"<img src='" + logo_path + "' class='logo'>" if logo_path else ""}
|
92 |
-
<div class="title">{title}</div>
|
93 |
-
<img src="{plot_image_path}" class="plot-image">
|
94 |
-
</body>
|
95 |
-
</html>
|
96 |
-
"""
|
97 |
-
|
98 |
-
with tempfile.NamedTemporaryFile(delete=False, suffix=".html") as tmpfile:
|
99 |
-
tmpfile.write(html_content.encode('utf-8'))
|
100 |
-
tmpfile.close()
|
101 |
-
html_path = tmpfile.name
|
102 |
-
|
103 |
-
pdf_path = html_path.replace('figure.html', '.pdf')
|
104 |
-
st.write(pdf_path)
|
105 |
-
pdfkit.from_file(html_path, pdf_path)
|
106 |
-
return pdf_path
|
107 |
-
|
108 |
-
def download_pdf():
|
109 |
-
# Construct plot
|
110 |
-
fig = construct_plot()
|
111 |
-
|
112 |
-
if fig is None:
|
113 |
-
return None
|
114 |
-
st.write("fig constructed")
|
115 |
-
|
116 |
-
logo_path = "https://static.wixstatic.com/media/d7d3da_b69e03ae99224f7d8b6e358918e60071~mv2.png/v1/crop/x_173,y_0,w_1906,h_938/fill/w_242,h_119,al_c,q_85,usm_0.66_1.00_0.01,enc_auto/BZIIIT_LOGO-HORIZ-COULEUR.png"
|
117 |
-
pdf_title = "Cartographie des parties prenantes"
|
118 |
-
# Button to download PDF
|
119 |
-
pdf_path = save_plot_as_pdf(fig, logo_path, pdf_title)
|
120 |
-
|
121 |
-
st.write("pdf saved")
|
122 |
-
with open(pdf_path, "rb") as pdf_file:
|
123 |
-
st.download_button(label="Download PDF", data=pdf_file, file_name="stakeholder_analysis.pdf")
|
124 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
emissions.csv
DELETED
The diff for this file is too large to render.
See raw diff
|
|
empreinte_carbone.py
DELETED
@@ -1,120 +0,0 @@
|
|
1 |
-
import streamlit as st
|
2 |
-
from comparateur import get_table_empreintes_detailed
|
3 |
-
from comparateur import *
|
4 |
-
import base64
|
5 |
-
import pandas as pd
|
6 |
-
import altair as alt
|
7 |
-
|
8 |
-
# Function to read and encode an SVG file to Base64
|
9 |
-
def load_svg_as_base64(file_path):
|
10 |
-
with open(file_path, "rb") as f:
|
11 |
-
svg_data = f.read()
|
12 |
-
return base64.b64encode(svg_data).decode()
|
13 |
-
|
14 |
-
def color_scale(val):
|
15 |
-
if val == '-':
|
16 |
-
return 'background-color: {color}'
|
17 |
-
elif val <= 1:
|
18 |
-
color = '#008571' #'rgba(0,238,0,0.5)' # green with opacity
|
19 |
-
elif val <= 10:
|
20 |
-
color = '#83c2b8' # light green with opacity
|
21 |
-
elif val <= 50:
|
22 |
-
color = '#efcd82' # light yellow with opacity
|
23 |
-
elif val <= 100:
|
24 |
-
color = '#f2aa56' # light orange with opacity
|
25 |
-
else:
|
26 |
-
color = '#e87a58' # light red with opacity
|
27 |
-
return f'background-color: {color};color:white'
|
28 |
-
|
29 |
-
def display_cf_comparison(stm: st):
|
30 |
-
svg_file_path = "feuille.svg"
|
31 |
-
svg_base64 = load_svg_as_base64(svg_file_path)
|
32 |
-
stm.markdown(
|
33 |
-
f"""
|
34 |
-
**Votre consommation carbone**
|
35 |
-
<img src='data:image/svg+xml;base64,{svg_base64}' alt='svg' width='15' height='15' style='margin-left: 10px;'>
|
36 |
-
""",
|
37 |
-
unsafe_allow_html=True
|
38 |
-
)
|
39 |
-
|
40 |
-
serveur_emission = st.session_state['emission'].stop()
|
41 |
-
emission_api = sum([value["el"] for value in st.session_state["partial_emissions"].values()])
|
42 |
-
|
43 |
-
if serveur_emission is None :
|
44 |
-
serveur_emission = 0
|
45 |
-
if emission_api is None :
|
46 |
-
emission_api = 0
|
47 |
-
total_emission = serveur_emission + emission_api
|
48 |
-
|
49 |
-
pourcentage_api = emission_api / total_emission
|
50 |
-
|
51 |
-
pourcentage_serveur = serveur_emission / total_emission
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
stm.markdown(f"<div style='text-align: center; margin-bottom: 10px;'><b>{total_emission*1000:.2f}</b> g eq. CO2</div>", unsafe_allow_html=True)
|
56 |
-
stm.markdown("Dont :")
|
57 |
-
stm.markdown(f"- Empreinte serveur (via CodeCarbon) : **{serveur_emission*1000:.2f}** g eq. CO2 ({pourcentage_serveur:.2%})")
|
58 |
-
stm.write(f"- Empreinte IA (via EcoLogits) : **{emission_api*1000:.2f}** g eq. CO2 ({pourcentage_api:.2%})")
|
59 |
-
# stm.markdown("(avec l'outil CodeCarbon)")
|
60 |
-
c1,c2,c3 = stm.columns([1,1,1])
|
61 |
-
|
62 |
-
c2.write("---")
|
63 |
-
|
64 |
-
stm.markdown("**Votre équivalence**")
|
65 |
-
col1,col2,col3 = stm.columns([1,1,1])
|
66 |
-
display_comparaison(col1,total_emission,dict_comparaison_1kgCO2["eau en litre"][0]*1000,dict_comparaison_1kgCO2["eau en litre"][1],"ml")
|
67 |
-
display_comparaison(col2,total_emission,dict_comparaison_1kgCO2["tgv en km"][0],dict_comparaison_1kgCO2["tgv en km"][1],"km")
|
68 |
-
display_comparaison(col3,total_emission,dict_comparaison_1kgCO2["voiture en km"][0]*1000,dict_comparaison_1kgCO2["voiture en km"][1],"m")
|
69 |
-
stm.markdown("\n")
|
70 |
-
stm.markdown(
|
71 |
-
f"""
|
72 |
-
Powered by **ADEME**
|
73 |
-
<a href='https://www.ademe.fr' target='_blank'><img src='https://www.ademe.fr/wp-content/uploads/2022/11/ademe-logo-2022-1.svg' alt='svg' width='30' height='30' style='margin-left: 10px;'>
|
74 |
-
""",
|
75 |
-
unsafe_allow_html=True
|
76 |
-
)
|
77 |
-
|
78 |
-
def display_carbon_footprint():
|
79 |
-
st.title("EMPREINTE ÉNERGÉTIQUE DE L'APPLICATION IA CARTO RSE")
|
80 |
-
display_cf_comparison(st)
|
81 |
-
table = get_table_empreintes_detailed()
|
82 |
-
# table[['Consommation Totale']] = table[['Consommation Totale']].map('${:,.2f}'.format)
|
83 |
-
|
84 |
-
table.replace({0.00: '-'}, inplace=True)
|
85 |
-
#just 2 digits after the comma
|
86 |
-
styled_df = table[['Consommation Totale']].rename(columns={'Consommation Totale': 'Consommation totale (g eqCo2)'})
|
87 |
-
styled_df = styled_df.round(2)
|
88 |
-
|
89 |
-
styled_df = styled_df.style.applymap(color_scale, subset=['Consommation totale (g eqCo2)'])
|
90 |
-
st.markdown("---")
|
91 |
-
st.markdown("### DÉTAIL PAR TÂCHE")
|
92 |
-
st.table(styled_df)
|
93 |
-
with st.expander("Plus de détails"):
|
94 |
-
st.table(table)
|
95 |
-
|
96 |
-
st.markdown("### SYNTHESE (Dialogue IA et non IA)")
|
97 |
-
|
98 |
-
serveur_emission = st.session_state['emission'].stop()
|
99 |
-
emission_api = sum([value["el"] for value in st.session_state["partial_emissions"].values()])
|
100 |
-
print(serveur_emission, emission_api)
|
101 |
-
total_emission = serveur_emission + emission_api
|
102 |
-
|
103 |
-
pourcentage_api = emission_api / total_emission
|
104 |
-
pourcentage_serveur = serveur_emission / total_emission
|
105 |
-
|
106 |
-
df = pd.DataFrame({"Catégorie": ["Identification + dessin","IA (extraction pp + dialogue)"], "valeur": [pourcentage_serveur, pourcentage_api]})
|
107 |
-
color_scale_alt = alt.Scale(domain=['Identification + dessin', 'IA (extraction pp + dialogue)'], range=['#011166', '#63abdf'])
|
108 |
-
|
109 |
-
base=alt.Chart(df).encode(
|
110 |
-
theta=alt.Theta(field="valeur", type="quantitative", stack=True),
|
111 |
-
color=alt.Color(field="Catégorie", type="nominal", scale=color_scale_alt),
|
112 |
-
)
|
113 |
-
|
114 |
-
|
115 |
-
pie = base.mark_arc(outerRadius=100)
|
116 |
-
text = base.mark_text(radius=150,fill= "black",align='center', baseline='middle',fontSize=20).encode(alt.Text(field="valeur", type="quantitative", format=".2%"))
|
117 |
-
|
118 |
-
chart = alt.layer(pie, text, data=df).resolve_scale(theta="independent")
|
119 |
-
st.altair_chart(chart, use_container_width=True)
|
120 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
empreinte_export.py
DELETED
@@ -1,172 +0,0 @@
|
|
1 |
-
import streamlit as st
|
2 |
-
import pandas as pd
|
3 |
-
import altair as alt
|
4 |
-
import base64
|
5 |
-
import pdfkit
|
6 |
-
import io
|
7 |
-
from comparateur import *
|
8 |
-
|
9 |
-
def load_svg_as_base64(svg_file_path):
|
10 |
-
with open(svg_file_path, "rb") as svg_file:
|
11 |
-
return base64.b64encode(svg_file.read()).decode()
|
12 |
-
|
13 |
-
def save_pdf(html_content):
|
14 |
-
pdf = pdfkit.from_string(html_content, False)
|
15 |
-
return pdf
|
16 |
-
|
17 |
-
def display_comparaison_html(value_init, ratio_equivalent, icon, unit):
|
18 |
-
link_url = f"https://impactco2.fr/outils/comparateur?value={value_init}&comparisons=tgv,eauenbouteille,voiturethermique"
|
19 |
-
html = f"""
|
20 |
-
<div style='text-align: center;'>
|
21 |
-
<a href='{link_url}' target='_blank'><img src='{icon}' alt='{unit}' width='50'></a>
|
22 |
-
</div>
|
23 |
-
<div style='text-align: center;'>
|
24 |
-
<b>{compare(value_init, ratio_equivalent):.2f}</b> {unit}
|
25 |
-
</div>
|
26 |
-
"""
|
27 |
-
return html
|
28 |
-
|
29 |
-
def display_cf_comparison():
|
30 |
-
svg_file_path = "feuille.svg"
|
31 |
-
svg_base64 = load_svg_as_base64(svg_file_path)
|
32 |
-
|
33 |
-
html_content = f"""
|
34 |
-
<div style='display: flex; align-items: center;'>
|
35 |
-
<h4 style='margin: 0;'>Votre consommation Carbone</h4>
|
36 |
-
<img src='data:image/svg+xml;base64,{svg_base64}' alt='svg' width='15' height='15' style='margin-left: 10px;'>
|
37 |
-
</div>
|
38 |
-
<br>
|
39 |
-
"""
|
40 |
-
|
41 |
-
serveur_emission = st.session_state['emission'].stop()
|
42 |
-
emission_api = sum([value["el"] for value in st.session_state["partial_emissions"].values()])
|
43 |
-
|
44 |
-
total_emission = serveur_emission + emission_api
|
45 |
-
|
46 |
-
pourcentage_api = emission_api / total_emission
|
47 |
-
pourcentage_serveur = serveur_emission / total_emission
|
48 |
-
|
49 |
-
html_content += f"<div style='text-align: center; margin-bottom: 10px;'><b>{total_emission*1000:.3f}</b> g eq. CO2</div>"
|
50 |
-
html_content += f"<p>Dont :</p>"
|
51 |
-
html_content += f"<p>- Empreinte serveur (via CodeCarbon) : <b>{serveur_emission*1000:.3f}</b> g eq. CO2 ({pourcentage_serveur:.2%})</p>"
|
52 |
-
html_content += f"<p>- Empreinte IA (via EcoLogits) : <b>{emission_api*1000:.3f}</b> g eq. CO2 ({pourcentage_api:.2%})</p>"
|
53 |
-
|
54 |
-
html_content += "<h4>Votre équivalence</h4>"
|
55 |
-
html_content += """
|
56 |
-
<div style='display: flex; justify-content: space-around;'>
|
57 |
-
"""
|
58 |
-
|
59 |
-
html_content += f"""
|
60 |
-
<div>
|
61 |
-
{display_comparaison_html(total_emission, dict_comparaison_1kgCO2["eau en litre"][0]*1000, dict_comparaison_1kgCO2["eau en litre"][1], "ml")}
|
62 |
-
</div>
|
63 |
-
<div>
|
64 |
-
{display_comparaison_html(total_emission, dict_comparaison_1kgCO2["tgv en km"][0], dict_comparaison_1kgCO2["tgv en km"][1], "km")}
|
65 |
-
</div>
|
66 |
-
<div>
|
67 |
-
{display_comparaison_html(total_emission, dict_comparaison_1kgCO2["voiture en km"][0]*1000, dict_comparaison_1kgCO2["voiture en km"][1], "m")}
|
68 |
-
</div>
|
69 |
-
"""
|
70 |
-
|
71 |
-
html_content += "</div><br>"
|
72 |
-
|
73 |
-
|
74 |
-
html_content += f"""
|
75 |
-
<br>
|
76 |
-
<div style='display: flex; align-items: center;'>
|
77 |
-
<p>Powered by <b>ADEME</b></p>
|
78 |
-
<a href='https://www.ademe.fr' target='_blank'><img src='https://www.ademe.fr/wp-content/uploads/2022/11/ademe-logo-2022-1.svg' alt='svg' width='30' height='30' style='margin-left: 10px;'></a>
|
79 |
-
</div>
|
80 |
-
<br>
|
81 |
-
"""
|
82 |
-
|
83 |
-
#st.markdown(html_content, unsafe_allow_html=True)
|
84 |
-
return html_content
|
85 |
-
|
86 |
-
def color_scale(val):
|
87 |
-
if val == '-':
|
88 |
-
return 'background-color: white'
|
89 |
-
elif val <= 1:
|
90 |
-
return 'background-color: rgba(0,100,0,0.5)' # dark green with opacity
|
91 |
-
elif val <= 10:
|
92 |
-
return 'background-color: rgba(0,128,0,0.5)' # green with opacity
|
93 |
-
elif val <= 50:
|
94 |
-
return 'background-color: rgba(255,255,0,0.5)' # yellow with opacity
|
95 |
-
elif val <= 100:
|
96 |
-
return 'background-color: rgba(255,165,0,0.5)' # orange with opacity
|
97 |
-
else:
|
98 |
-
return 'background-color: rgba(255,0,0,0.5)' # red with opacity
|
99 |
-
|
100 |
-
|
101 |
-
def get_carbon_footprint_html():
|
102 |
-
|
103 |
-
html_content = "<h2>EMPREINTE ÉNERGÉTIQUE DE L'APPLICATION IA CARTO RSE</h2>"
|
104 |
-
html_content += display_cf_comparison()
|
105 |
-
|
106 |
-
table = get_table_empreintes_detailed()
|
107 |
-
table.replace({0.00: '-'}, inplace=True)
|
108 |
-
styled_df = table[['Consommation Totale']].rename(columns={'Consommation Totale': 'Consommation totale (g eqCo2)'})
|
109 |
-
styled_df = styled_df.style.applymap(color_scale, subset=['Consommation totale (g eqCo2)'])
|
110 |
-
|
111 |
-
html_content += """
|
112 |
-
<style>
|
113 |
-
.centered-table {
|
114 |
-
margin-left: auto;
|
115 |
-
margin-right: auto;
|
116 |
-
border-collapse: collapse;
|
117 |
-
width: 80%;
|
118 |
-
}
|
119 |
-
.centered-table th, .centered-table td {
|
120 |
-
border: 1px solid #ddd;
|
121 |
-
padding: 8px;
|
122 |
-
text-align: left;
|
123 |
-
}
|
124 |
-
.centered-table th {
|
125 |
-
background-color: #f2f2f2;
|
126 |
-
}
|
127 |
-
</style>
|
128 |
-
"""
|
129 |
-
|
130 |
-
html_content += """
|
131 |
-
<h2>DÉTAIL PAR TÂCHE</h2>
|
132 |
-
<div style="overflow-x:auto;">
|
133 |
-
"""
|
134 |
-
|
135 |
-
html_content += styled_df.set_table_attributes('class="centered-table"').to_html()
|
136 |
-
|
137 |
-
html_content += """
|
138 |
-
</div>
|
139 |
-
"""
|
140 |
-
|
141 |
-
serveur_emission = st.session_state['emission'].stop()
|
142 |
-
emission_api = sum([value["el"] for value in st.session_state["partial_emissions"].values()])
|
143 |
-
|
144 |
-
total_emission = serveur_emission + emission_api
|
145 |
-
|
146 |
-
pourcentage_api = emission_api / total_emission
|
147 |
-
pourcentage_serveur = serveur_emission / total_emission
|
148 |
-
|
149 |
-
df = pd.DataFrame({"Catégorie": ["Identification + dessin", "IA (extraction pp + dialogue)"], "valeur": [pourcentage_serveur, pourcentage_api]})
|
150 |
-
color_scale_alt = alt.Scale(domain=['Identification + dessin', 'IA (extraction pp + dialogue)'], range=['#011166', '#63abdf'])
|
151 |
-
|
152 |
-
base = alt.Chart(df).encode(
|
153 |
-
theta=alt.Theta(field="valeur", type="quantitative", stack=True),
|
154 |
-
color=alt.Color(field="Catégorie", type="nominal",scale=color_scale_alt)
|
155 |
-
)
|
156 |
-
|
157 |
-
pie = base.mark_arc(outerRadius=100)
|
158 |
-
text = base.mark_text(radius=150, fill="black",align='center', baseline='middle',fontSize=14).encode(alt.Text(field="valeur", type="quantitative", format=".2%"))
|
159 |
-
|
160 |
-
chart = alt.layer(pie, text, data=df).resolve_scale(theta="independent")
|
161 |
-
|
162 |
-
html_content += """
|
163 |
-
<h2>SYNTHESE (Dialogue IA et non IA)</h2>
|
164 |
-
"""
|
165 |
-
chart.save("chart.png")
|
166 |
-
with open("chart.png", "rb") as image_file:
|
167 |
-
encoded_image = base64.b64encode(image_file.read()).decode()
|
168 |
-
|
169 |
-
html_content += f'<div style="text-align:center;"><img src="data:image/png;base64,{encoded_image}" alt="Pie chart"></div>'
|
170 |
-
|
171 |
-
return html_content
|
172 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export_doc.py
DELETED
@@ -1,242 +0,0 @@
|
|
1 |
-
import streamlit as st
|
2 |
-
import markdown2
|
3 |
-
import pdfkit
|
4 |
-
from io import BytesIO
|
5 |
-
from IPython.display import display, FileLink
|
6 |
-
import base64
|
7 |
-
from langchain_core.messages import AIMessage, HumanMessage
|
8 |
-
from datetime import datetime
|
9 |
-
from download_chart import construct_plot
|
10 |
-
from kaleido.scopes.plotly import PlotlyScope
|
11 |
-
import pandas as pd
|
12 |
-
import markdown
|
13 |
-
from comparateur import get_table_empreintes_detailed
|
14 |
-
from empreinte_export import get_carbon_footprint_html
|
15 |
-
|
16 |
-
def colored_circle(color):
|
17 |
-
return f'<span style="display: inline-block; width: 15px; height: 15px; border-radius: 50%; background-color: {color};"></span>'
|
18 |
-
|
19 |
-
def list_to_markdown(lst):
|
20 |
-
return "\n".join([f'<p>{colored_circle(item["color"])} <b>{item["name"]}</b>: Pouvoir:{item["y"]}% Influence:{item["x"]}%</p>' for item in lst[:20]])
|
21 |
-
|
22 |
-
def categorize(row):
|
23 |
-
if 50 <= row['pouvoir'] <= 100 and 0 <= row['influence'] < 50:
|
24 |
-
return 'Rendre satisfait'
|
25 |
-
elif 50 <= row['pouvoir'] <= 100 and 50 <= row['influence'] <= 100:
|
26 |
-
return 'Gérer étroitement'
|
27 |
-
elif 0 <= row['pouvoir'] < 50 and 0 <= row['influence'] < 50:
|
28 |
-
return 'Suivre de près'
|
29 |
-
elif 0 <= row['pouvoir'] < 50 and 50 <= row['influence'] <= 100:
|
30 |
-
return 'Tenir informé'
|
31 |
-
else:
|
32 |
-
return 'Non catégorisé'
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
@st.cache_data
|
37 |
-
def convert_pp_to_csv(pp_grouped):
|
38 |
-
if pp_grouped is None or len(pp_grouped) == 0:
|
39 |
-
st.error("Aucune partie prenante n'a été définie")
|
40 |
-
return None
|
41 |
-
pp_df = pd.DataFrame(pp_grouped)
|
42 |
-
pp_df.index.name = 'N°'
|
43 |
-
pp_df.rename(columns={"name": "parties prenantes", "x": "influence", "y": "pouvoir"}, inplace=True)
|
44 |
-
pp_df.drop(columns=['color'], inplace=True)
|
45 |
-
# Apply the function to the DataFrame to create a new column 'categorie'
|
46 |
-
pp_df['categorie'] = pp_df.apply(categorize, axis=1)
|
47 |
-
pp_df = pp_df[["parties prenantes","categorie", "pouvoir", "influence"]]
|
48 |
-
pp_df.rename_axis('N°', axis=1)
|
49 |
-
return pp_df.to_csv(index=True,encoding="utf-8")
|
50 |
-
|
51 |
-
@st.cache_data
|
52 |
-
def create_pdf_from_markdown(logo_path, conversation,summary,brand_name,graph_html,app_url,list_pps,used_models=None):
|
53 |
-
# Convertir la conversation en markdown
|
54 |
-
markdown_text = "\n".join([f"### {entry['speaker']}:\n {entry['text']}\n ---" for entry in conversation])
|
55 |
-
|
56 |
-
if not used_models:
|
57 |
-
used_models = ["Aucun modèle IA n'a été utilisé"]
|
58 |
-
html_used_models = "".join([f"<p>{model}</p>" for model in used_models])
|
59 |
-
|
60 |
-
markdown_summary = f"{summary}\n --- \n ---"
|
61 |
-
markdown_list_pps = list_to_markdown(list_pps)
|
62 |
-
# Convertir le markdown en HTML
|
63 |
-
html_content = markdown.markdown(markdown_text,extensions=['markdown.extensions.tables'])
|
64 |
-
html_summary = markdown2.markdown(markdown_summary)
|
65 |
-
html_list_pps = markdown2.markdown(markdown_list_pps)
|
66 |
-
|
67 |
-
analysis_date = datetime.now().strftime("%Y-%m-%d")
|
68 |
-
# image_base64 = base64.b64encode(image_path).decode('utf-8')
|
69 |
-
graph_html.update_layout(showlegend=False)
|
70 |
-
img_bytes = PlotlyScope().transform(
|
71 |
-
figure=graph_html,
|
72 |
-
format="png",
|
73 |
-
)
|
74 |
-
fig1 = f"data:image/png;base64,{base64.b64encode(img_bytes).decode('utf8')}"
|
75 |
-
# Créer le HTML complet avec les images et le texte
|
76 |
-
|
77 |
-
html_template = f"""
|
78 |
-
<!DOCTYPE html>
|
79 |
-
<html lang="en">
|
80 |
-
<head>
|
81 |
-
<meta charset="UTF-8">
|
82 |
-
<title>Cartographie des parties prenantes {brand_name}</title>
|
83 |
-
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
|
84 |
-
<style>
|
85 |
-
body {{
|
86 |
-
font-family: 'Roboto', sans-serif;
|
87 |
-
margin: 20px;
|
88 |
-
}}
|
89 |
-
h1, h2, h3, h4, h5, h6 {{
|
90 |
-
font-weight: bold;
|
91 |
-
}}
|
92 |
-
.page-break {{
|
93 |
-
page-break-before: always;
|
94 |
-
margin: 50px;
|
95 |
-
height: 50px;
|
96 |
-
}}
|
97 |
-
</style>
|
98 |
-
</head>
|
99 |
-
<body>
|
100 |
-
<div style="text-align: center;">
|
101 |
-
<h1>Cartographie des parties prenantes "{brand_name}"</h1>
|
102 |
-
<p>Date de l'analyse IA RSE : {analysis_date}</p>
|
103 |
-
<p>IA utilisées :</p>
|
104 |
-
{html_used_models}
|
105 |
-
<img src="{logo_path}" alt="Logo" style="width: 150px;"/>
|
106 |
-
</div>
|
107 |
-
<div class="page-break"></div>
|
108 |
-
<div style="text-align: center; margin-top: 20px;">
|
109 |
-
<img src="{fig1}">
|
110 |
-
</div>
|
111 |
-
{html_list_pps}
|
112 |
-
<div class="page-break"></div>
|
113 |
-
<h2>RESUME</h2>
|
114 |
-
{html_summary}
|
115 |
-
<div class="page-break"></div>
|
116 |
-
<h2>Historique de la Conversation</h2>
|
117 |
-
{html_content}
|
118 |
-
<div class="page-break"></div>
|
119 |
-
{get_carbon_footprint_html()}
|
120 |
-
</body>
|
121 |
-
</html>
|
122 |
-
"""
|
123 |
-
|
124 |
-
with open("temp.html", "w",encoding="utf-8") as f:
|
125 |
-
f.write(html_template)
|
126 |
-
|
127 |
-
# Create the footer HTML with the logo and app_url
|
128 |
-
footer_html = f"""
|
129 |
-
<!DOCTYPE html>
|
130 |
-
<html lang="en">
|
131 |
-
<head>
|
132 |
-
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
|
133 |
-
<meta charset="UTF-8">
|
134 |
-
<style>
|
135 |
-
body {{
|
136 |
-
font-family: 'Roboto', sans-serif;
|
137 |
-
margin-top: 20px;
|
138 |
-
}}
|
139 |
-
.footer {{
|
140 |
-
width: 100%;
|
141 |
-
font-size: 16px;
|
142 |
-
display: flex;
|
143 |
-
align-items: center;
|
144 |
-
justify-content: space-between;
|
145 |
-
padding: 10px 20px;
|
146 |
-
}}
|
147 |
-
.footer img {{
|
148 |
-
width: 100px;
|
149 |
-
vertical-align: middle;
|
150 |
-
margin-bottom: 0px;
|
151 |
-
padding-bottom: 0px;
|
152 |
-
|
153 |
-
}}
|
154 |
-
.footer .center-text {{
|
155 |
-
text-align: center;
|
156 |
-
|
157 |
-
}}
|
158 |
-
.footer .page-number {{
|
159 |
-
text-align: right;
|
160 |
-
}}
|
161 |
-
.footer a {{
|
162 |
-
color: #0000EE;
|
163 |
-
text-decoration: none;
|
164 |
-
}}
|
165 |
-
.page {{
|
166 |
-
font-weight: bold;
|
167 |
-
font-size: 10px;
|
168 |
-
margin-bottom: 0px;
|
169 |
-
padding-bottom: 0px;
|
170 |
-
}}
|
171 |
-
|
172 |
-
</style>
|
173 |
-
</head>
|
174 |
-
<body>
|
175 |
-
<div class="footer">
|
176 |
-
<img src="{logo_path}" alt="Logo" />
|
177 |
-
<div class="center-text">
|
178 |
-
bziiit | Open data & IA RSE | <a href="{app_url}">{app_url}</a>
|
179 |
-
</div>
|
180 |
-
<div class="page-number">
|
181 |
-
<span class="page"></span>
|
182 |
-
</div>
|
183 |
-
</div>
|
184 |
-
</body>
|
185 |
-
</html>
|
186 |
-
"""
|
187 |
-
|
188 |
-
|
189 |
-
# Save the footer HTML to a temporary file
|
190 |
-
with open("footer.html", "w",encoding="utf-8") as f:
|
191 |
-
f.write(footer_html)
|
192 |
-
|
193 |
-
|
194 |
-
# Convert HTML to PDF with header and footer
|
195 |
-
pdf = pdfkit.from_file("temp.html", options={
|
196 |
-
'footer-html': 'footer.html',
|
197 |
-
'footer-right': '[page]/[toPage]',
|
198 |
-
'footer-font-size': '10',
|
199 |
-
'footer-spacing': '5',
|
200 |
-
'footer-line': True,
|
201 |
-
'margin-top': '5',
|
202 |
-
})
|
203 |
-
return pdf
|
204 |
-
|
205 |
-
def get_conversation():
|
206 |
-
conversation = []
|
207 |
-
for message in st.session_state.chat_history:
|
208 |
-
if isinstance(message, AIMessage):
|
209 |
-
conversation.append({"speaker": "AI", "text": message.content})
|
210 |
-
elif isinstance(message, HumanMessage):
|
211 |
-
conversation.append({"speaker": "Moi", "text": message.content})
|
212 |
-
return conversation
|
213 |
-
|
214 |
-
|
215 |
-
def export_conversation(summary,used_models=None):
|
216 |
-
brand_name = st.session_state["Nom de la marque"]
|
217 |
-
app_url = "https://huggingface.co/spaces/bziiit/OpenData-Bordeaux-RSE"
|
218 |
-
logo_path = "https://static.wixstatic.com/media/d7d3da_b69e03ae99224f7d8b6e358918e60071~mv2.png/v1/crop/x_173,y_0,w_1906,h_938/fill/w_242,h_119,al_c,q_85,usm_0.66_1.00_0.01,enc_auto/BZIIIT_LOGO-HORIZ-COULEUR.png" # Replace with your image path
|
219 |
-
list_pps = st.session_state['pp_grouped']
|
220 |
-
|
221 |
-
with st.spinner("Génération du PDF..."):
|
222 |
-
conversation = get_conversation()
|
223 |
-
image_path = "newplot.png"
|
224 |
-
try:
|
225 |
-
graph = construct_plot()
|
226 |
-
# graph = graph.to_html(full_html=False, include_plotlyjs='cdn')
|
227 |
-
except Exception as e:
|
228 |
-
st.error("Erreur lors de la génération de la cartographie")
|
229 |
-
graph = ""
|
230 |
-
try:
|
231 |
-
pdf = create_pdf_from_markdown(logo_path=logo_path, conversation=conversation,summary=summary,brand_name=brand_name,graph_html=graph,app_url=app_url,list_pps=list_pps,used_models=used_models)
|
232 |
-
except Exception as e:
|
233 |
-
pdf = None
|
234 |
-
|
235 |
-
if pdf:
|
236 |
-
st.success("PDF généré avec succès!}")
|
237 |
-
else:
|
238 |
-
st.error("Erreur lors de la génération du PDF")
|
239 |
-
|
240 |
-
return pdf
|
241 |
-
|
242 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
feuille.svg
DELETED
footer.html
DELETED
@@ -1,59 +0,0 @@
|
|
1 |
-
|
2 |
-
<!DOCTYPE html>
|
3 |
-
<html lang="en">
|
4 |
-
<head>
|
5 |
-
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
|
6 |
-
<meta charset="UTF-8">
|
7 |
-
<style>
|
8 |
-
body {
|
9 |
-
font-family: 'Roboto', sans-serif;
|
10 |
-
margin-top: 20px;
|
11 |
-
}
|
12 |
-
.footer {
|
13 |
-
width: 100%;
|
14 |
-
font-size: 16px;
|
15 |
-
display: flex;
|
16 |
-
align-items: center;
|
17 |
-
justify-content: space-between;
|
18 |
-
padding: 10px 20px;
|
19 |
-
}
|
20 |
-
.footer img {
|
21 |
-
width: 100px;
|
22 |
-
vertical-align: middle;
|
23 |
-
margin-bottom: 0px;
|
24 |
-
padding-bottom: 0px;
|
25 |
-
|
26 |
-
}
|
27 |
-
.footer .center-text {
|
28 |
-
text-align: center;
|
29 |
-
|
30 |
-
}
|
31 |
-
.footer .page-number {
|
32 |
-
text-align: right;
|
33 |
-
}
|
34 |
-
.footer a {
|
35 |
-
color: #0000EE;
|
36 |
-
text-decoration: none;
|
37 |
-
}
|
38 |
-
.page {
|
39 |
-
font-weight: bold;
|
40 |
-
font-size: 10px;
|
41 |
-
margin-bottom: 0px;
|
42 |
-
padding-bottom: 0px;
|
43 |
-
}
|
44 |
-
|
45 |
-
</style>
|
46 |
-
</head>
|
47 |
-
<body>
|
48 |
-
<div class="footer">
|
49 |
-
<img src="https://static.wixstatic.com/media/d7d3da_b69e03ae99224f7d8b6e358918e60071~mv2.png/v1/crop/x_173,y_0,w_1906,h_938/fill/w_242,h_119,al_c,q_85,usm_0.66_1.00_0.01,enc_auto/BZIIIT_LOGO-HORIZ-COULEUR.png" alt="Logo" />
|
50 |
-
<div class="center-text">
|
51 |
-
bziiit | Open data & IA RSE | <a href="https://huggingface.co/spaces/bziiit/OpenData-Bordeaux-RSE">https://huggingface.co/spaces/bziiit/OpenData-Bordeaux-RSE</a>
|
52 |
-
</div>
|
53 |
-
<div class="page-number">
|
54 |
-
<span class="page"></span>
|
55 |
-
</div>
|
56 |
-
</div>
|
57 |
-
</body>
|
58 |
-
</html>
|
59 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
high_chart.py
DELETED
@@ -1,201 +0,0 @@
|
|
1 |
-
import streamlit as st
|
2 |
-
import st_hc as hct
|
3 |
-
import download_chart as dc
|
4 |
-
from export_doc import convert_pp_to_csv
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
# Define the highchart definition
|
9 |
-
cd2 = {
|
10 |
-
"chart":{
|
11 |
-
"animation":False
|
12 |
-
},
|
13 |
-
"title":{
|
14 |
-
"text":"Cartographie des parties prenantes"
|
15 |
-
},
|
16 |
-
"tooltip":{
|
17 |
-
"valueDecimals":0
|
18 |
-
},
|
19 |
-
"xAxis":{
|
20 |
-
"title":{
|
21 |
-
"text":"Influence"
|
22 |
-
},
|
23 |
-
"min":0,
|
24 |
-
"max":100,
|
25 |
-
"plotLines":[
|
26 |
-
{
|
27 |
-
"color":"gray",
|
28 |
-
"dashStyle":"LongDash",
|
29 |
-
"width":1,
|
30 |
-
"value":50,
|
31 |
-
"label":{
|
32 |
-
"rotation":0,
|
33 |
-
"y":290,
|
34 |
-
"style":{
|
35 |
-
"color":"blue",
|
36 |
-
"font-size": "20px"
|
37 |
-
},
|
38 |
-
"text":"Tenir informé",
|
39 |
-
},
|
40 |
-
"zIndex":3
|
41 |
-
},
|
42 |
-
{
|
43 |
-
"color":"gray",
|
44 |
-
"dashStyle":"LongDash",
|
45 |
-
"width":1,
|
46 |
-
"value":50,
|
47 |
-
"label":{
|
48 |
-
"rotation":0,
|
49 |
-
"y":25,
|
50 |
-
"style":{
|
51 |
-
"color":"orange",
|
52 |
-
"font-size": "20px"
|
53 |
-
},
|
54 |
-
"text":"Gérer étroitement",
|
55 |
-
},
|
56 |
-
"zIndex":3
|
57 |
-
},
|
58 |
-
{
|
59 |
-
"color":"gray",
|
60 |
-
"dashStyle":"LongDash",
|
61 |
-
"width":1,
|
62 |
-
"value":0,
|
63 |
-
"label":{
|
64 |
-
"rotation":0,
|
65 |
-
"y":25,
|
66 |
-
"style":{
|
67 |
-
"color":"green",
|
68 |
-
"font-size": "20px"
|
69 |
-
},
|
70 |
-
"text":"Rendre satisfait",
|
71 |
-
},
|
72 |
-
"zIndex":3
|
73 |
-
},
|
74 |
-
{
|
75 |
-
"color":"gray",
|
76 |
-
"dashStyle":"LongDash",
|
77 |
-
"width":1,
|
78 |
-
"value":0,
|
79 |
-
"label":{
|
80 |
-
"rotation":0,
|
81 |
-
"y":290,
|
82 |
-
"style":{
|
83 |
-
"color":"red",
|
84 |
-
"font-size": "20px"
|
85 |
-
},
|
86 |
-
"text":"Suivre de près",
|
87 |
-
},
|
88 |
-
"zIndex":3
|
89 |
-
},
|
90 |
-
{
|
91 |
-
"color":"gray",
|
92 |
-
"dashStyle":"LongDash",
|
93 |
-
"width":1,
|
94 |
-
"value":100,
|
95 |
-
"zIndex":3
|
96 |
-
|
97 |
-
}
|
98 |
-
]
|
99 |
-
},
|
100 |
-
"yAxis":{
|
101 |
-
"title":{
|
102 |
-
"text":"Pouvoir"
|
103 |
-
},
|
104 |
-
"min":0,
|
105 |
-
"max":100,
|
106 |
-
"plotLines":[
|
107 |
-
{
|
108 |
-
"color":"gray",
|
109 |
-
"dashStyle":"LongDash",
|
110 |
-
"width":1,
|
111 |
-
"value":50,
|
112 |
-
"zIndex":3
|
113 |
-
|
114 |
-
},
|
115 |
-
{
|
116 |
-
"color":"gray",
|
117 |
-
"dashStyle":"LongDash",
|
118 |
-
"width":1,
|
119 |
-
"value":100,
|
120 |
-
"zIndex":3
|
121 |
-
},
|
122 |
-
{
|
123 |
-
"color":"gray",
|
124 |
-
"dashStyle":"LongDash",
|
125 |
-
"width":1,
|
126 |
-
"value":0,
|
127 |
-
"zIndex":3
|
128 |
-
}
|
129 |
-
],
|
130 |
-
},
|
131 |
-
"tooltip":{
|
132 |
-
"headerFormat":"",
|
133 |
-
"pointFormat":"{point.name}",
|
134 |
-
"valueDecimals":0
|
135 |
-
},
|
136 |
-
"series":[
|
137 |
-
{
|
138 |
-
"type":"bubble",
|
139 |
-
"maxSize":50,
|
140 |
-
"cursor":"move",
|
141 |
-
"name":"Influence",
|
142 |
-
"pointformat":"{point.name}",
|
143 |
-
"dragDrop":{
|
144 |
-
"draggableX":True,
|
145 |
-
"draggableY":True,
|
146 |
-
"dragMinY":0,
|
147 |
-
"dragMaxY":100,
|
148 |
-
"dragMinX":0,
|
149 |
-
"dragMaxX":100,
|
150 |
-
"dragPrecisionX":1,
|
151 |
-
"dragPrecisionY":1,
|
152 |
-
"dragSensitivity":0
|
153 |
-
},
|
154 |
-
"data":[],
|
155 |
-
"colorByPoint":True,
|
156 |
-
|
157 |
-
}
|
158 |
-
],
|
159 |
-
"exporting": {
|
160 |
-
"enabled": True
|
161 |
-
|
162 |
-
},
|
163 |
-
"legend":{
|
164 |
-
"enabled":False
|
165 |
-
}
|
166 |
-
}
|
167 |
-
|
168 |
-
|
169 |
-
def construct_data():
|
170 |
-
data = []
|
171 |
-
for i in range(10):
|
172 |
-
object = {
|
173 |
-
"x": 50+i*5,
|
174 |
-
"y": 50,
|
175 |
-
"name": f"Point{i}",
|
176 |
-
|
177 |
-
}
|
178 |
-
data.append(object)
|
179 |
-
|
180 |
-
return data
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
def test_chart():
|
186 |
-
#The component can render any highchart definition
|
187 |
-
if "pp_grouped" not in st.session_state or len(st.session_state['pp_grouped']) == 0:
|
188 |
-
return None
|
189 |
-
|
190 |
-
points = st.session_state['pp_grouped']
|
191 |
-
cd2["series"][0]["data"] = points
|
192 |
-
chart = hct.streamlit_highcharts(cd2,640) #640 is the chart height
|
193 |
-
# if chart:
|
194 |
-
# st.session_state['pp_grouped'] = chart
|
195 |
-
|
196 |
-
col0,col1,col2 = st.columns([1,1,1])
|
197 |
-
|
198 |
-
if col1.button("Sauvegarder",key="save"):
|
199 |
-
st.session_state['pp_grouped'] = chart.copy()
|
200 |
-
st.session_state["partial_emissions"]["cartographie"]["cc"] = st.session_state["emission"].stop()
|
201 |
-
return "saved"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
htmlTemplates.py
DELETED
@@ -1,44 +0,0 @@
|
|
1 |
-
css = '''
|
2 |
-
<style>
|
3 |
-
.chat-message {
|
4 |
-
padding: 1.5rem; border-radius: 0.5rem; margin-bottom: 1rem; display: flex
|
5 |
-
}
|
6 |
-
.chat-message.user {
|
7 |
-
background-color: #2b313e
|
8 |
-
}
|
9 |
-
.chat-message.bot {
|
10 |
-
background-color: #475063
|
11 |
-
}
|
12 |
-
.chat-message .avatar {
|
13 |
-
width: 20%;
|
14 |
-
}
|
15 |
-
.chat-message .avatar img {
|
16 |
-
max-width: 78px;
|
17 |
-
max-height: 78px;
|
18 |
-
border-radius: 50%;
|
19 |
-
object-fit: cover;
|
20 |
-
}
|
21 |
-
.chat-message .message {
|
22 |
-
width: 80%;
|
23 |
-
padding: 0 1.5rem;
|
24 |
-
color: #fff;
|
25 |
-
}
|
26 |
-
'''
|
27 |
-
|
28 |
-
bot_template = '''
|
29 |
-
<div class="chat-message bot">
|
30 |
-
<div class="avatar">
|
31 |
-
<img src="data:image/png;base64,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" style="max-height: 78px; max-width: 78px; border-radius: 50%; object-fit: cover;">
|
32 |
-
</div>
|
33 |
-
<div class="message">{{MSG}}</div>
|
34 |
-
</div>
|
35 |
-
'''
|
36 |
-
|
37 |
-
user_template = '''
|
38 |
-
<div class="chat-message user">
|
39 |
-
<div class="avatar">
|
40 |
-
<img src="https://media.licdn.com/dms/image/C4E03AQGvvkYN1sbUbA/profile-displayphoto-shrink_400_400/0/1588147295529?e=1714003200&v=beta&t=pAlX20zTPhqbi7ipYCkj_oUOhOgtvsy5TuJFikbH-f4">
|
41 |
-
</div>
|
42 |
-
<div class="message">{{MSG}}</div>
|
43 |
-
</div>
|
44 |
-
'''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
packages.txt
DELETED
@@ -1,2 +0,0 @@
|
|
1 |
-
wkhtmltopdf
|
2 |
-
xfonts-75dpi
|
|
|
|
|
|
partie_prenante_carte.py
DELETED
@@ -1,490 +0,0 @@
|
|
1 |
-
import streamlit as st
|
2 |
-
import pandas as pd
|
3 |
-
import numpy as np
|
4 |
-
import re
|
5 |
-
import random
|
6 |
-
import time
|
7 |
-
|
8 |
-
import streamlit as st
|
9 |
-
from dotenv import load_dotenv
|
10 |
-
from langchain_experimental.text_splitter import SemanticChunker
|
11 |
-
from langchain_community.embeddings import OpenAIEmbeddings
|
12 |
-
from langchain_community.vectorstores import FAISS
|
13 |
-
from langchain_community.chat_models import ChatOpenAI
|
14 |
-
from langchain import hub
|
15 |
-
from langchain_core.runnables import RunnablePassthrough
|
16 |
-
from langchain_community.document_loaders import WebBaseLoader,FireCrawlLoader,PyPDFLoader
|
17 |
-
from langchain_core.prompts.prompt import PromptTemplate
|
18 |
-
import os
|
19 |
-
from high_chart import test_chart
|
20 |
-
from chat_with_pps import get_response
|
21 |
-
from ecologits.tracers.utils import compute_llm_impacts
|
22 |
-
from codecarbon import EmissionsTracker
|
23 |
-
|
24 |
-
load_dotenv()
|
25 |
-
|
26 |
-
def get_docs_from_website(urls):
|
27 |
-
loader = WebBaseLoader(urls, header_template={
|
28 |
-
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36',
|
29 |
-
})
|
30 |
-
try:
|
31 |
-
docs = loader.load()
|
32 |
-
return docs
|
33 |
-
except Exception as e:
|
34 |
-
return None
|
35 |
-
|
36 |
-
|
37 |
-
def get_docs_from_website_fc(urls,firecrawl_api_key):
|
38 |
-
docs = []
|
39 |
-
try:
|
40 |
-
for url in urls:
|
41 |
-
loader = FireCrawlLoader(api_key=firecrawl_api_key, url = url,mode="scrape")
|
42 |
-
docs+=loader.load()
|
43 |
-
return docs
|
44 |
-
except Exception as e:
|
45 |
-
return None
|
46 |
-
|
47 |
-
|
48 |
-
def get_doc_chunks(docs):
|
49 |
-
# Split the loaded data
|
50 |
-
# text_splitter = RecursiveCharacterTextSplitter(
|
51 |
-
# chunk_size=500,
|
52 |
-
# chunk_overlap=100)
|
53 |
-
|
54 |
-
text_splitter = SemanticChunker(OpenAIEmbeddings(model="text-embedding-3-small"))
|
55 |
-
|
56 |
-
docs = text_splitter.split_documents(docs)
|
57 |
-
return docs
|
58 |
-
|
59 |
-
def get_doc_chunks_fc(docs):
|
60 |
-
# Split the loaded data
|
61 |
-
# text_splitter = RecursiveCharacterTextSplitter(
|
62 |
-
# chunk_size=500,
|
63 |
-
# chunk_overlap=100)
|
64 |
-
|
65 |
-
text_splitter = SemanticChunker(OpenAIEmbeddings(model="text-embedding-3-small"))
|
66 |
-
docs_splitted = []
|
67 |
-
for text in docs:
|
68 |
-
text_splitted = text_splitter.split_text(text)
|
69 |
-
docs_splitted+=text_splitted
|
70 |
-
return docs_splitted
|
71 |
-
|
72 |
-
|
73 |
-
def get_vectorstore_from_docs(doc_chunks):
|
74 |
-
embedding = OpenAIEmbeddings(model="text-embedding-3-small")
|
75 |
-
vectorstore = FAISS.from_documents(documents=doc_chunks, embedding=embedding)
|
76 |
-
return vectorstore
|
77 |
-
|
78 |
-
def get_vectorstore_from_text(texts):
|
79 |
-
embedding = OpenAIEmbeddings(model="text-embedding-3-small")
|
80 |
-
vectorstore = FAISS.from_texts(texts=texts, embedding=embedding)
|
81 |
-
return vectorstore
|
82 |
-
|
83 |
-
def get_conversation_chain(vectorstore):
|
84 |
-
llm = ChatOpenAI(model="gpt-4o",temperature=0.5, max_tokens=2048)
|
85 |
-
|
86 |
-
retriever=vectorstore.as_retriever()
|
87 |
-
|
88 |
-
prompt = hub.pull("rlm/rag-prompt")
|
89 |
-
# Chain
|
90 |
-
rag_chain = (
|
91 |
-
{"context": retriever , "question": RunnablePassthrough()}
|
92 |
-
| prompt
|
93 |
-
| llm
|
94 |
-
)
|
95 |
-
return rag_chain
|
96 |
-
|
97 |
-
# FILL THE PROMPT FOR THE QUESTION VARIABLE THAT WILL BE USED IN THE RAG PROMPT, ATTENTION NOT CONFUSE WITH THE RAG PROMPT
|
98 |
-
def fill_promptQ_template(input_variables, template):
|
99 |
-
prompt = PromptTemplate(input_variables=["BRAND_NAME","BRAND_DESCRIPTION"], template=template)
|
100 |
-
return prompt.format(BRAND_NAME=input_variables["BRAND_NAME"], BRAND_DESCRIPTION=input_variables["BRAND_DESCRIPTION"])
|
101 |
-
|
102 |
-
def text_to_list(text):
|
103 |
-
lines = text.replace("- ","").split('\n')
|
104 |
-
|
105 |
-
lines = [line.split() for line in lines]
|
106 |
-
items = [[' '.join(line[:-1]),line[-1]] for line in lines]
|
107 |
-
|
108 |
-
# Assuming `items` is the list of items
|
109 |
-
for item in items:
|
110 |
-
item[1] = re.sub(r'\D', '', item[1])
|
111 |
-
return items
|
112 |
-
|
113 |
-
def delete_pp(pps):
|
114 |
-
for pp in pps:
|
115 |
-
for i in range(len(st.session_state['pp_grouped'])):
|
116 |
-
if st.session_state['pp_grouped'][i]['name'] == pp:
|
117 |
-
del st.session_state['pp_grouped'][i]
|
118 |
-
break
|
119 |
-
|
120 |
-
def display_list_urls():
|
121 |
-
for index, item in enumerate(st.session_state["urls"]):
|
122 |
-
emp = st.empty() # Create an empty placeholder
|
123 |
-
col1, col2 = emp.columns([7, 3]) # Divide the space into two columns
|
124 |
-
|
125 |
-
# Button to delete the entry, placed in the second column
|
126 |
-
if col2.button("❌", key=f"but{index}"):
|
127 |
-
temp = st.session_state['parties_prenantes'][index]
|
128 |
-
delete_pp(temp)
|
129 |
-
del st.session_state.urls[index]
|
130 |
-
del st.session_state["parties_prenantes"][index]
|
131 |
-
st.rerun() # Rerun the app to update the display
|
132 |
-
|
133 |
-
if len(st.session_state.urls) > index:
|
134 |
-
# Instead of using markdown, use an expander in the first column
|
135 |
-
with col1.expander(f"Source {index+1}: {item}"):
|
136 |
-
pp = st.session_state["parties_prenantes"][index]
|
137 |
-
st.write(pd.DataFrame(pp, columns=["Partie prenante"]))
|
138 |
-
else:
|
139 |
-
emp.empty() # Clear the placeholder if the index exceeds the list
|
140 |
-
|
141 |
-
def colored_circle(color):
|
142 |
-
return f'<span style="display: inline-block; width: 15px; height: 15px; border-radius: 50%; background-color: {color};"></span>'
|
143 |
-
|
144 |
-
def display_list_pps():
|
145 |
-
for index, item in enumerate(st.session_state["pp_grouped"]):
|
146 |
-
emp = st.empty()
|
147 |
-
col1, col2 = emp.columns([7, 3])
|
148 |
-
|
149 |
-
if col2.button("❌", key=f"butp{index}"):
|
150 |
-
|
151 |
-
del st.session_state["pp_grouped"][index]
|
152 |
-
st.rerun()
|
153 |
-
|
154 |
-
if len(st.session_state["pp_grouped"]) > index:
|
155 |
-
name = st.session_state["pp_grouped"][index]["name"]
|
156 |
-
col1.markdown(f'<p>{colored_circle(st.session_state["pp_grouped"][index]["color"])} {st.session_state["pp_grouped"][index]["name"]}</p>',
|
157 |
-
unsafe_allow_html=True
|
158 |
-
)
|
159 |
-
else:
|
160 |
-
emp.empty()
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
def extract_pp(docs,input_variables):
|
165 |
-
template_extraction_PP = """
|
166 |
-
Objectif : Identifiez toutes les parties prenantes de la marque suivante :
|
167 |
-
|
168 |
-
Le nom de la marque de référence est le suivant : {BRAND_NAME}
|
169 |
-
|
170 |
-
TA RÉPONSE DOIT ÊTRE SOUS FORME DE LISTE DE NOMS DE MARQUES, CHAQUE NOM SUR UNE LIGNE SÉPARÉE.
|
171 |
-
|
172 |
-
"""
|
173 |
-
#don't forget to add the input variables from the maim function
|
174 |
-
|
175 |
-
if docs == None:
|
176 |
-
return "445"
|
177 |
-
|
178 |
-
#get text chunks
|
179 |
-
text_chunks = get_doc_chunks(docs)
|
180 |
-
|
181 |
-
#create vectorstore
|
182 |
-
vectorstore = get_vectorstore_from_docs(text_chunks)
|
183 |
-
|
184 |
-
chain = get_conversation_chain(vectorstore)
|
185 |
-
|
186 |
-
question = fill_promptQ_template(input_variables, template_extraction_PP)
|
187 |
-
|
188 |
-
start = time.perf_counter()
|
189 |
-
response = chain.invoke(question)
|
190 |
-
|
191 |
-
response_latency = time.perf_counter() - start
|
192 |
-
# version plus poussée a considérer
|
193 |
-
# each item in the list is a list with the name of the brand and the similarity percentage
|
194 |
-
# partie_prenante = text_to_list(response.content)
|
195 |
-
if "ne sais pas" in response.content:
|
196 |
-
return "444"
|
197 |
-
|
198 |
-
#calculate impact
|
199 |
-
nbre_out_tokens = response.response_metadata["token_usage"]["completion_tokens"]
|
200 |
-
provider = "openai"
|
201 |
-
model = "gpt-4o"
|
202 |
-
impact = compute_llm_impacts(
|
203 |
-
provider=provider,
|
204 |
-
model_name=model,
|
205 |
-
output_token_count=nbre_out_tokens,
|
206 |
-
request_latency=response_latency,
|
207 |
-
)
|
208 |
-
|
209 |
-
st.session_state["partial_emissions"]["extraction_pp"]["el"] += impact.gwp.value
|
210 |
-
#version simple
|
211 |
-
partie_prenante = response.content.replace("- ","").split('\n')
|
212 |
-
partie_prenante = [item.strip() for item in partie_prenante]
|
213 |
-
|
214 |
-
return partie_prenante
|
215 |
-
|
216 |
-
def generate_random_color():
|
217 |
-
# Generate random RGB values
|
218 |
-
r = random.randint(0, 255)
|
219 |
-
g = random.randint(0, 255)
|
220 |
-
b = random.randint(0, 255)
|
221 |
-
|
222 |
-
# Convert RGB to hexadecimal
|
223 |
-
color_hex = '#{:02x}{:02x}{:02x}'.format(r, g, b)
|
224 |
-
|
225 |
-
return color_hex
|
226 |
-
|
227 |
-
|
228 |
-
def format_pp_add_viz(pp):
|
229 |
-
y = 50
|
230 |
-
x = 50
|
231 |
-
for i in range(len(st.session_state['pp_grouped'])):
|
232 |
-
if st.session_state['pp_grouped'][i]['y'] == y and st.session_state['pp_grouped'][i]['x'] == x:
|
233 |
-
y += 5
|
234 |
-
if y > 95:
|
235 |
-
y = 50
|
236 |
-
x += 5
|
237 |
-
if st.session_state['pp_grouped'][i]['name'] == pp:
|
238 |
-
return None
|
239 |
-
else:
|
240 |
-
st.session_state['pp_grouped'].append({'name':pp, 'x':x,'y':y, 'color':generate_random_color()})
|
241 |
-
|
242 |
-
def add_pp(new_pp, default_value=50):
|
243 |
-
new_pp = sorted(new_pp)
|
244 |
-
new_pp = [item.lower().capitalize().strip() for item in new_pp]
|
245 |
-
st.session_state['parties_prenantes'].append(new_pp)
|
246 |
-
for pp in new_pp:
|
247 |
-
format_pp_add_viz(pp)
|
248 |
-
|
249 |
-
def add_existing_pps(pp,pouvoir,influence):
|
250 |
-
for i in range(len(st.session_state['pp_grouped'])):
|
251 |
-
if st.session_state['pp_grouped'][i]['name'] == pp:
|
252 |
-
st.session_state['pp_grouped'][i]['x'] = influence
|
253 |
-
st.session_state['pp_grouped'][i]['y'] = pouvoir
|
254 |
-
return None
|
255 |
-
st.session_state['pp_grouped'].append({'name':pp, 'x':influence,'y':pouvoir, 'color':generate_random_color()})
|
256 |
-
|
257 |
-
def load_csv(file):
|
258 |
-
df = pd.read_csv(file)
|
259 |
-
for index, row in df.iterrows():
|
260 |
-
add_existing_pps(row['parties prenantes'],row['pouvoir'],row['influence'])
|
261 |
-
|
262 |
-
|
263 |
-
def add_pp_input_text():
|
264 |
-
new_pp = st.text_input("Ajouter une partie prenante")
|
265 |
-
if st.button("Ajouter",key="add_single_pp"):
|
266 |
-
format_pp_add_viz(new_pp)
|
267 |
-
|
268 |
-
|
269 |
-
def complete_and_verify_url(partial_url):
|
270 |
-
# Regex pattern for validating a URL
|
271 |
-
regex = re.compile(
|
272 |
-
r'^(?:http|ftp)s?://' # http:// or https://
|
273 |
-
r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,8}\.?|' # domain
|
274 |
-
r'localhost|' # localhost...
|
275 |
-
r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip
|
276 |
-
r'(?::\d+)?' # optional port
|
277 |
-
r'(?:/?|[/?]\S+)$', re.IGNORECASE)
|
278 |
-
|
279 |
-
regex = re.compile(
|
280 |
-
r'^(?:http|ftp)s?://' # http:// or https://
|
281 |
-
r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,8}\.?|' # domain name
|
282 |
-
r'localhost|' # or localhost
|
283 |
-
r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # or IPv4 address
|
284 |
-
r'(?::\d+)?' # optional port
|
285 |
-
r'(?:[/?#][^\s]*)?$', # optional path, query, or fragment
|
286 |
-
re.IGNORECASE)
|
287 |
-
|
288 |
-
# Complete the URL if it doesn't have http:// or https://
|
289 |
-
if not partial_url.startswith(('http://', 'https://', 'www.')):
|
290 |
-
if not partial_url.startswith('www.'):
|
291 |
-
complete_url = 'https://www.' + partial_url
|
292 |
-
else:
|
293 |
-
complete_url = 'https://' + partial_url
|
294 |
-
|
295 |
-
elif partial_url.startswith('www.'):
|
296 |
-
complete_url = 'https://' + partial_url
|
297 |
-
|
298 |
-
else:
|
299 |
-
complete_url = partial_url
|
300 |
-
|
301 |
-
# Check if the URL is valid
|
302 |
-
if re.match(regex, complete_url):
|
303 |
-
return (True, complete_url)
|
304 |
-
else:
|
305 |
-
return (False, complete_url)
|
306 |
-
|
307 |
-
@st.dialog("Conseil IA",width="large")
|
308 |
-
def show_conseil_ia():
|
309 |
-
prompt = "Prenant compte les données de l'entreprise (activité, produits, services ...), quelles sont les principales parties prenantes à animer pour une démarche RSE réussie ?"
|
310 |
-
st.markdown(f"**{prompt}**")
|
311 |
-
response = st.write_stream(get_response(prompt, "",st.session_state["latest_doc"][0].page_content))
|
312 |
-
st.warning("Quittez et saisissez une autre URL")
|
313 |
-
|
314 |
-
def display_pp():
|
315 |
-
if "emission" not in st.session_state:
|
316 |
-
tracker = EmissionsTracker()
|
317 |
-
tracker.start()
|
318 |
-
st.session_state["emission"] = tracker
|
319 |
-
|
320 |
-
load_dotenv()
|
321 |
-
fire_crawl_api_key = os.getenv("FIRECRAWL_API_KEY")
|
322 |
-
|
323 |
-
#check if brand name and description are already set
|
324 |
-
if "Nom de la marque" not in st.session_state:
|
325 |
-
st.session_state["Nom de la marque"] = ""
|
326 |
-
|
327 |
-
#check if urls and partie prenante are already set
|
328 |
-
if "urls" not in st.session_state:
|
329 |
-
st.session_state["urls"] = []
|
330 |
-
if "parties_prenantes" not in st.session_state:
|
331 |
-
st.session_state['parties_prenantes'] = []
|
332 |
-
if "pp_grouped" not in st.session_state: #servira pour le plot et la cartographie des parties prenantes, regroupe sans doublons
|
333 |
-
st.session_state['pp_grouped'] = []
|
334 |
-
if "latest_doc" not in st.session_state:
|
335 |
-
st.session_state['latest_doc'] = ""
|
336 |
-
if "not_pp" not in st.session_state:
|
337 |
-
st.session_state["not_pp"] = ""
|
338 |
-
|
339 |
-
|
340 |
-
st.title("IDENTIFIER ET ANIMER VOS PARTIES PRENANTES")
|
341 |
-
#set brand name and description
|
342 |
-
brand_name = st.text_input("Nom de la marque", st.session_state["Nom de la marque"])
|
343 |
-
st.session_state["Nom de la marque"] = brand_name
|
344 |
-
|
345 |
-
option = st.radio("Source", ("A partir de votre site web", "A partir de vos documents entreprise","A partir de cartographie existante"))
|
346 |
-
|
347 |
-
#if the user chooses to extract from website
|
348 |
-
if option == "A partir de votre site web":
|
349 |
-
|
350 |
-
url = st.text_input("Ajouter une URL")
|
351 |
-
|
352 |
-
captions = ["L’IA prend en compte uniquement les textes contenus dans les pages web analysées","L’IA prend en compte les textes, les images et les liens URL contenus dans les pages web analysées"]
|
353 |
-
scraping_option = st.radio("Mode", ("Analyse rapide", "Analyse profonde"),horizontal=True,captions = captions)
|
354 |
-
#if the user clicks on the button
|
355 |
-
if st.button("ajouter",key="add_pp"):
|
356 |
-
st.session_state["not_pp"] = ""
|
357 |
-
#complete and verify the url
|
358 |
-
is_valid,url = complete_and_verify_url(url)
|
359 |
-
if not is_valid:
|
360 |
-
st.error("URL invalide")
|
361 |
-
elif url in st.session_state["urls"] :
|
362 |
-
st.error("URL déjà ajoutée")
|
363 |
-
|
364 |
-
else:
|
365 |
-
if scraping_option == "Analyse profonde":
|
366 |
-
with st.spinner("Collecte des données..."):
|
367 |
-
docs = get_docs_from_website_fc([url],fire_crawl_api_key)
|
368 |
-
if docs is None:
|
369 |
-
st.warning("Erreur lors de la collecte des données, 2eme essai avec collecte rapide...")
|
370 |
-
with st.spinner("2eme essai, collecte rapide..."):
|
371 |
-
docs = get_docs_from_website([url])
|
372 |
-
|
373 |
-
if scraping_option == "Analyse rapide":
|
374 |
-
with st.spinner("Collecte des données..."):
|
375 |
-
docs = get_docs_from_website([url])
|
376 |
-
|
377 |
-
if docs is None:
|
378 |
-
st.error("Erreur lors de la collecte des données, URL unvalide")
|
379 |
-
st.session_state["latest_doc"] = ""
|
380 |
-
else:
|
381 |
-
# Création de l'expander
|
382 |
-
st.session_state["partial_emissions"]["Scrapping"]["cc"] = st.session_state["emission"].stop()
|
383 |
-
st.session_state["latest_doc"] = docs
|
384 |
-
|
385 |
-
with st.spinner("Processing..."):
|
386 |
-
|
387 |
-
#handle the extraction
|
388 |
-
input_variables = {"BRAND_NAME": brand_name, "BRAND_DESCRIPTION": ""}
|
389 |
-
partie_prenante = extract_pp(docs, input_variables)
|
390 |
-
|
391 |
-
if "444" in partie_prenante: #444 is the code for no brand found , chosen
|
392 |
-
st.session_state["not_pp"] = "444"
|
393 |
-
|
394 |
-
elif "445" in partie_prenante: #445 is the code for no website found with the given url
|
395 |
-
st.error("Aucun site web trouvé avec l'url donnée")
|
396 |
-
st.session_state["not_pp"] = ""
|
397 |
-
else:
|
398 |
-
st.session_state["not_pp"] = ""
|
399 |
-
partie_prenante = sorted(partie_prenante)
|
400 |
-
st.session_state["urls"].append(url)
|
401 |
-
add_pp(partie_prenante)
|
402 |
-
st.session_state["partial_emissions"]["extraction_pp"]["cc"] = st.session_state["emission"].stop()
|
403 |
-
|
404 |
-
|
405 |
-
# alphabet = [ pp[0] for pp in partie_prenante]
|
406 |
-
# pouvoir = [ 50 for _ in range(len(partie_prenante))]
|
407 |
-
# df = pd.DataFrame({'partie_prenante': partie_prenante, 'pouvoir': pouvoir, 'code couleur': partie_prenante})
|
408 |
-
# st.write(df)
|
409 |
-
|
410 |
-
# c = (
|
411 |
-
# alt.Chart(df)
|
412 |
-
# .mark_circle(size=300)
|
413 |
-
# .encode(x="partie_prenante", y=alt.Y("pouvoir",scale=alt.Scale(domain=[0,100])), color="code couleur")
|
414 |
-
# )
|
415 |
-
# st.subheader("Vertical Slider")
|
416 |
-
# age = st.slider("How old are you?", 0, 130, 25)
|
417 |
-
# st.write("I'm ", age, "years old")
|
418 |
-
|
419 |
-
# disp_vertical_slider(partie_prenante)
|
420 |
-
# st.altair_chart(c, use_container_width=True)
|
421 |
-
if option =="A partir de vos documents entreprise":
|
422 |
-
|
423 |
-
uploaded_file = st.file_uploader("Télécharger le fichier PDF", type="pdf")
|
424 |
-
if uploaded_file is not None:
|
425 |
-
|
426 |
-
if st.button("ajouter",key="add_pp_pdf"):
|
427 |
-
st.session_state["not_pp"] = ""
|
428 |
-
|
429 |
-
with st.spinner("Processing..."):
|
430 |
-
file_name = uploaded_file.name
|
431 |
-
with open(file_name, mode='wb') as w:
|
432 |
-
w.write(uploaded_file.getvalue())
|
433 |
-
pdf = PyPDFLoader(file_name)
|
434 |
-
text = pdf.load()
|
435 |
-
st.session_state["latest_doc"] = text
|
436 |
-
input_variables = {"BRAND_NAME": brand_name, "BRAND_DESCRIPTION": ""}
|
437 |
-
partie_prenante = extract_pp(text, input_variables)
|
438 |
-
|
439 |
-
if "444" in partie_prenante: #444 is the code for no brand found , chosen
|
440 |
-
st.session_state["not_pp"] = "444"
|
441 |
-
|
442 |
-
elif "445" in partie_prenante: #445 is the code for no website found with the given url
|
443 |
-
st.error("Aucun site web trouvé avec l'url donnée")
|
444 |
-
st.session_state["not_pp"] = ""
|
445 |
-
|
446 |
-
else:
|
447 |
-
st.session_state["not_pp"] = ""
|
448 |
-
partie_prenante = sorted(partie_prenante)
|
449 |
-
st.session_state["urls"].append(file_name)
|
450 |
-
add_pp(partie_prenante)
|
451 |
-
|
452 |
-
if option == "A partir de cartographie existante":
|
453 |
-
uploaded_file = st.file_uploader("Télécharger le fichier CSV", type="csv")
|
454 |
-
if uploaded_file is not None:
|
455 |
-
if st.button("ajouter",key="add_pp_csv"):
|
456 |
-
file_name = uploaded_file.name
|
457 |
-
with open(file_name, mode='wb') as w:
|
458 |
-
w.write(uploaded_file.getvalue())
|
459 |
-
|
460 |
-
try:
|
461 |
-
load_csv(file_name)
|
462 |
-
brand_name_from_csv = file_name.split("-")[1]
|
463 |
-
st.session_state["Nom de la marque"] = brand_name_from_csv
|
464 |
-
except Exception as e:
|
465 |
-
st.error("Erreur lors de la lecture du fichier")
|
466 |
-
|
467 |
-
|
468 |
-
if st.session_state["not_pp"] == "444":
|
469 |
-
st.warning("Aucune parties prenantes n'est identifiable sur l'URL fournie. Fournissez une autre URL ou bien cliquez sur le boutton ci-dessous pour un Conseils IA")
|
470 |
-
|
471 |
-
if st.button("Conseil IA"):
|
472 |
-
show_conseil_ia()
|
473 |
-
#display docs
|
474 |
-
if st.session_state["latest_doc"] != "":
|
475 |
-
with st.expander("Cliquez ici pour éditer et voir le document"):
|
476 |
-
docs = st.session_state["latest_doc"]
|
477 |
-
cleaned_text = re.sub(r'\n\n+', '\n\n', docs[0].page_content.strip())
|
478 |
-
text_value = st.text_area("Modifier le texte ci-dessous:", value=cleaned_text, height=300)
|
479 |
-
if st.button('Sauvegarder',key="save_doc_fake"):
|
480 |
-
st.success("Texte sauvegardé avec succès!")
|
481 |
-
|
482 |
-
display_list_urls()
|
483 |
-
with st.expander("Liste des parties prenantes"):
|
484 |
-
add_pp_input_text()
|
485 |
-
display_list_pps()
|
486 |
-
test_chart()
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
partiesprenantes.py
CHANGED
@@ -30,7 +30,6 @@ def display_company_selection_for_materiality(data):
|
|
30 |
|
31 |
selected_company = st.selectbox('Sélectionnez une entreprise', companies, index=0)
|
32 |
|
33 |
-
|
34 |
# If the default selection is still selected, return None
|
35 |
if selected_company == "Sélectionner l'entreprise engagée à découvrir":
|
36 |
return None
|
|
|
30 |
|
31 |
selected_company = st.selectbox('Sélectionnez une entreprise', companies, index=0)
|
32 |
|
|
|
33 |
# If the default selection is still selected, return None
|
34 |
if selected_company == "Sélectionner l'entreprise engagée à découvrir":
|
35 |
return None
|
prompt.py
DELETED
@@ -1,135 +0,0 @@
|
|
1 |
-
import streamlit as st
|
2 |
-
from st_copy_to_clipboard import st_copy_to_clipboard
|
3 |
-
import pandas as pd
|
4 |
-
from data_manager_bziiit import get_prompts
|
5 |
-
from langchain_core.messages import AIMessage, HumanMessage
|
6 |
-
from session import get_rag
|
7 |
-
|
8 |
-
prompts = []
|
9 |
-
def get_prompts_list():
|
10 |
-
st.header("Prompts")
|
11 |
-
prompts = get_prompts()
|
12 |
-
|
13 |
-
# Check if prompts is a list of dictionaries
|
14 |
-
if isinstance(prompts, list) and all(isinstance(i, dict) for i in prompts):
|
15 |
-
# Create a DataFrame
|
16 |
-
df = pd.DataFrame(prompts)
|
17 |
-
# Check if 'name', 'context', and 'text' are in df columns
|
18 |
-
if 'name' in df.columns and 'context' in df.columns and 'text' in df.columns:
|
19 |
-
# Filter prompts with id_context as 'rse' or 'transition'
|
20 |
-
df = df[df['id_context'].isin([
|
21 |
-
'identifier-parties-prenantes-organisation',
|
22 |
-
'animer-parties-prenantes-organisation',
|
23 |
-
'pour-accelerer-la-demarche-rse',
|
24 |
-
'pour-accelerer-la-demarche-transition-ecologique',
|
25 |
-
'ressources-humaines'
|
26 |
-
])]
|
27 |
-
|
28 |
-
# Extract 'name' from 'context' dictionary
|
29 |
-
df['context'] = df['context'].apply(lambda x: x.get('name') if isinstance(x, dict) else x)
|
30 |
-
|
31 |
-
# Get first 50 characters from 'text' and add "..." at the end
|
32 |
-
df['text'] = df['text'].apply(lambda x: x[:50] + "..." if isinstance(x, str) else x)
|
33 |
-
|
34 |
-
# Group by 'context'
|
35 |
-
grouped = df.groupby('context')
|
36 |
-
|
37 |
-
|
38 |
-
for name, group in grouped:
|
39 |
-
num = 1
|
40 |
-
|
41 |
-
with st.expander(name):
|
42 |
-
for i, row in group.iterrows():
|
43 |
-
col1, col3, col4 = st.columns((0.4, 4, 2))
|
44 |
-
col1.write(num) # index
|
45 |
-
# col2.write(row['name']) # name
|
46 |
-
col3.write(row['text']) # text
|
47 |
-
num += 1
|
48 |
-
|
49 |
-
button_phold = col4.empty() # create a placeholder
|
50 |
-
but1, but2 = button_phold.columns(2)
|
51 |
-
|
52 |
-
do_action = but1.button('Voir plus', key=f"v{i}")
|
53 |
-
execute = but2.button('Executer', key=f"e{i}")
|
54 |
-
|
55 |
-
if execute:
|
56 |
-
st.session_state.chat_history.append(HumanMessage(content=prompts[i]['text']))
|
57 |
-
st.rerun()
|
58 |
-
if do_action:
|
59 |
-
prompt_html = prompts[i]['text'].replace('\n', '<br>')
|
60 |
-
prompt_metadata = extract_metadata(prompts[i])
|
61 |
-
|
62 |
-
for text in prompt_metadata:
|
63 |
-
prompt_html = prompt_html.replace(f"{text}", f"<span style='font-weight:bold'>{text}</span>")
|
64 |
-
|
65 |
-
st.html(prompt_html)
|
66 |
-
|
67 |
-
else:
|
68 |
-
st.write("Data does not contain 'name', 'context', and 'text' fields.")
|
69 |
-
else:
|
70 |
-
st.write("Data is not in the expected format (list of dictionaries).")
|
71 |
-
|
72 |
-
|
73 |
-
def prompt_execution():
|
74 |
-
prompts = get_prompts()
|
75 |
-
|
76 |
-
selected_prompt = st.selectbox("Choisissez un prompt", prompts, index=None, format_func=lambda prompt: prompt['name'])
|
77 |
-
if selected_prompt:
|
78 |
-
return selected_prompt
|
79 |
-
|
80 |
-
return None
|
81 |
-
|
82 |
-
|
83 |
-
def execute_prompt(prompt):
|
84 |
-
# Initialiser les composants
|
85 |
-
vectorstore, chain = get_rag()
|
86 |
-
|
87 |
-
prompt_metadata = extract_metadata(prompt)
|
88 |
-
|
89 |
-
prompt['metadata'] = prompt['text']
|
90 |
-
prompt['html'] = prompt['text'].replace('\n', '<br>')
|
91 |
-
|
92 |
-
if prompt_metadata:
|
93 |
-
st.info("Données à compléter")
|
94 |
-
|
95 |
-
# Demander à l'utilisateur de fournir des valeurs pour chaque métadonnée extraite
|
96 |
-
user_inputs = {}
|
97 |
-
for text in prompt_metadata:
|
98 |
-
prompt['html'] = prompt['html'].replace(f"{text}", f"<span style='font-weight:bold'>{text}</span>")
|
99 |
-
|
100 |
-
user_input = st.text_input(f"{text}")
|
101 |
-
user_inputs[text] = user_input # Stocker la valeur de l'entrée utilisateur
|
102 |
-
|
103 |
-
# Remplacer les valeurs par le texte correspondant dans prompt['text']
|
104 |
-
for key, value in user_inputs.items():
|
105 |
-
if value:
|
106 |
-
prompt['html'] = prompt['html'].replace(f"{key}", f"<span style='color:#63ABDF;font-weight:bold' title='{key}'>{value}</span>")
|
107 |
-
prompt['metadata'] = prompt['metadata'].replace(f"{key}", f"{value}")
|
108 |
-
|
109 |
-
# Afficher les informations du prompt
|
110 |
-
if prompt_metadata:
|
111 |
-
st.markdown("---")
|
112 |
-
|
113 |
-
st.html(prompt.get('html', 'No Text Provided'))
|
114 |
-
|
115 |
-
if vectorstore and chain:
|
116 |
-
|
117 |
-
if st.button("Exécuter le prompt"):
|
118 |
-
with st.spinner("Processing..."):
|
119 |
-
ambition = chain.invoke(prompt['metadata'])
|
120 |
-
st.markdown("### Réponse :")
|
121 |
-
st.markdown(ambition.content)
|
122 |
-
else:
|
123 |
-
st.error("RAG non configuré. Veuillez configurer votre RAG pour exécuter le prompt.")
|
124 |
-
|
125 |
-
# Extraire le texte entre crochets dans le prompt
|
126 |
-
def extract_metadata(prompt):
|
127 |
-
extracted_text = []
|
128 |
-
if 'text' in prompt:
|
129 |
-
extracted_text = [word for word in prompt['text'].split() if word.startswith("[") and word.endswith("]")]
|
130 |
-
|
131 |
-
# Supprimer les doublons et trier les métadonnées extraites
|
132 |
-
prompt_metadata = list(set(extracted_text))
|
133 |
-
prompt_metadata.sort(key=extracted_text.index) # Conserver l'ordre d'apparition initial
|
134 |
-
|
135 |
-
return prompt_metadata
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rag.py
ADDED
File without changes
|
rag_funcs.py
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
from firecrawl import FireCrawl
|
2 |
-
|
3 |
-
|
4 |
-
def get_docs_from_website_fc(urls):
|
5 |
-
app = FireCrawl()
|
6 |
-
docs = []
|
7 |
-
try:
|
8 |
-
for url in urls:
|
9 |
-
content = app.scrape_url(url)
|
10 |
-
docs.append(content["markdown"])
|
11 |
-
return docs
|
12 |
-
except Exception as e:
|
13 |
-
return None
|
14 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
requirements.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
streamlit
|
2 |
pandas
|
3 |
requests
|
4 |
folium
|
@@ -12,33 +12,3 @@ plotly
|
|
12 |
matplotlib
|
13 |
openai
|
14 |
beautifulsoup4
|
15 |
-
python-dotenv
|
16 |
-
faiss-cpu
|
17 |
-
langchain
|
18 |
-
huggingface-hub
|
19 |
-
PyPDF2
|
20 |
-
pypdf
|
21 |
-
tiktoken
|
22 |
-
openai
|
23 |
-
InstructorEmbedding
|
24 |
-
sentence-transformers==2.2.2
|
25 |
-
langchainhub
|
26 |
-
plotly==5.22.0
|
27 |
-
altair
|
28 |
-
altair[all]
|
29 |
-
streamlit-vertical-slider
|
30 |
-
streamlit_toggle
|
31 |
-
langchain_experimental
|
32 |
-
streamlit_draggable_list
|
33 |
-
streamlit-highcharts
|
34 |
-
pdfkit
|
35 |
-
kaleido
|
36 |
-
langchain-core
|
37 |
-
langchain-mistralai
|
38 |
-
firecrawl-py
|
39 |
-
st_copy_to_clipboard
|
40 |
-
fpdf2
|
41 |
-
markdown2
|
42 |
-
markdown
|
43 |
-
codecarbon
|
44 |
-
ecologits==0.1.7
|
|
|
1 |
+
streamlit
|
2 |
pandas
|
3 |
requests
|
4 |
folium
|
|
|
12 |
matplotlib
|
13 |
openai
|
14 |
beautifulsoup4
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
session.py
DELETED
@@ -1,31 +0,0 @@
|
|
1 |
-
import streamlit as st
|
2 |
-
|
3 |
-
def get_rag():
|
4 |
-
if 'vectorstore' in st.session_state and 'chain' in st.session_state:
|
5 |
-
vectorstore = st.session_state['vectorstore']
|
6 |
-
chain = st.session_state['chain']
|
7 |
-
|
8 |
-
return vectorstore, chain
|
9 |
-
else:
|
10 |
-
return None, None
|
11 |
-
|
12 |
-
def set_rag(vectorstore, chain):
|
13 |
-
st.session_state['vectorstore'] = vectorstore
|
14 |
-
st.session_state['chain'] = chain
|
15 |
-
|
16 |
-
def set_partie_prenante(partie_prenante):
|
17 |
-
if "partie_prenante" not in st.session_state:
|
18 |
-
st.session_state['partie_prenante'] = []
|
19 |
-
st.session_state['partie_prenante'] = partie_prenante
|
20 |
-
|
21 |
-
def get_partie_prenante():
|
22 |
-
if 'parties_prenante' in st.session_state:
|
23 |
-
return st.session_state['partie_prenante']
|
24 |
-
else:
|
25 |
-
return None
|
26 |
-
|
27 |
-
def get_parties_prenantes():
|
28 |
-
if 'parties_prenantes' in st.session_state:
|
29 |
-
return st.session_state['parties_prenantes']
|
30 |
-
else:
|
31 |
-
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
st_hc/__init__.py
DELETED
@@ -1,2562 +0,0 @@
|
|
1 |
-
from pathlib import Path
|
2 |
-
from typing import Optional
|
3 |
-
|
4 |
-
import streamlit as st
|
5 |
-
import streamlit.components.v1 as components
|
6 |
-
|
7 |
-
SAMPLE={
|
8 |
-
|
9 |
-
"title": {
|
10 |
-
"text": 'U.S Solar Employment Growth by Job Category, 2010-2020'
|
11 |
-
},
|
12 |
-
|
13 |
-
"subtitle": {
|
14 |
-
"text": 'Source: <a href="https://irecusa.org/programs/solar-jobs-census/" target="_blank">IREC</a>'
|
15 |
-
},
|
16 |
-
|
17 |
-
"yAxis": {
|
18 |
-
"title": {
|
19 |
-
"text": 'Number of Employees'
|
20 |
-
}
|
21 |
-
},
|
22 |
-
|
23 |
-
"xAxis": {
|
24 |
-
"accessibility": {
|
25 |
-
"rangeDescription": 'Range: 2010 to 2020'
|
26 |
-
}
|
27 |
-
},
|
28 |
-
|
29 |
-
"legend": {
|
30 |
-
"layout": 'vertical',
|
31 |
-
"align": 'right',
|
32 |
-
"verticalAlign": 'middle'
|
33 |
-
},
|
34 |
-
|
35 |
-
"plotOptions": {
|
36 |
-
"series": {
|
37 |
-
"label": {
|
38 |
-
"connectorAllowed": False
|
39 |
-
},
|
40 |
-
"pointStart": 2010
|
41 |
-
}
|
42 |
-
},
|
43 |
-
|
44 |
-
"series": [{
|
45 |
-
"name": 'Installation & Developers',
|
46 |
-
"data": [43934, 48656, 65165, 81827, 112143, 142383,
|
47 |
-
171533, 165174, 155157, 161454, 154610]
|
48 |
-
}, {
|
49 |
-
"name": 'Manufacturing',
|
50 |
-
"data": [24916, 37941, 29742, 29851, 32490, 30282,
|
51 |
-
38121, 36885, 33726, 34243, 31050]
|
52 |
-
}, {
|
53 |
-
"name": 'Sales & Distribution',
|
54 |
-
"data": [11744, 30000, 16005, 19771, 20185, 24377,
|
55 |
-
32147, 30912, 29243, 29213, 25663]
|
56 |
-
}, {
|
57 |
-
"name": 'Operations & Maintenance',
|
58 |
-
"data": ["null", "null", "null", "null", "null", "null", "null",
|
59 |
-
"null", 11164, 11218, 10077]
|
60 |
-
}, {
|
61 |
-
"name": 'Other',
|
62 |
-
"data": [21908, 5548, 8105, 11248, 8989, 11816, 18274,
|
63 |
-
17300, 13053, 11906, 10073]
|
64 |
-
}],
|
65 |
-
|
66 |
-
"responsive": {
|
67 |
-
"rules": [{
|
68 |
-
"condition": {
|
69 |
-
"maxWidth": 500
|
70 |
-
},
|
71 |
-
"chartOptions": {
|
72 |
-
"legend": {
|
73 |
-
"layout": 'horizontal',
|
74 |
-
"align": 'center',
|
75 |
-
"verticalAlign": 'bottom'
|
76 |
-
}
|
77 |
-
}
|
78 |
-
}]
|
79 |
-
}
|
80 |
-
|
81 |
-
}
|
82 |
-
SAMPLE2={
|
83 |
-
|
84 |
-
"chart": {
|
85 |
-
"type": 'streamgraph',
|
86 |
-
"marginBottom": 30,
|
87 |
-
"zoomType": 'x'
|
88 |
-
},
|
89 |
-
|
90 |
-
"title": {
|
91 |
-
"floating": True,
|
92 |
-
"align": 'left',
|
93 |
-
"text": 'Winter Olympic Medal Wins'
|
94 |
-
},
|
95 |
-
"subtitle": {
|
96 |
-
"floating": True,
|
97 |
-
"align": 'left',
|
98 |
-
"y": 30,
|
99 |
-
"text": 'Source: <a href="https://www.sports-reference.com/olympics/winter/1924/">sports-reference.com</a>'
|
100 |
-
},
|
101 |
-
|
102 |
-
"xAxis": {
|
103 |
-
"maxPadding": 0,
|
104 |
-
"type": 'category',
|
105 |
-
"crosshair": True,
|
106 |
-
"categories": [
|
107 |
-
'',
|
108 |
-
'1924 Chamonix',
|
109 |
-
'1928 St. Moritz',
|
110 |
-
'1932 Lake Placid',
|
111 |
-
'1936 Garmisch-Partenkirchen',
|
112 |
-
'1940 <i>Cancelled (Sapporo)</i>',
|
113 |
-
'1944 <i>Cancelled (Cortina d\'Ampezzo)</i>',
|
114 |
-
'1948 St. Moritz',
|
115 |
-
'1952 Oslo',
|
116 |
-
'1956 Cortina d\'Ampezzo',
|
117 |
-
'1960 Squaw Valley',
|
118 |
-
'1964 Innsbruck',
|
119 |
-
'1968 Grenoble',
|
120 |
-
'1972 Sapporo',
|
121 |
-
'1976 Innsbruck',
|
122 |
-
'1980 Lake Placid',
|
123 |
-
'1984 Sarajevo',
|
124 |
-
'1988 Calgary',
|
125 |
-
'1992 Albertville',
|
126 |
-
'1994 Lillehammer',
|
127 |
-
'1998 Nagano',
|
128 |
-
'2002 Salt Lake City',
|
129 |
-
'2006 Turin',
|
130 |
-
'2010 Vancouver',
|
131 |
-
'2014 Sochi'
|
132 |
-
],
|
133 |
-
"labels": {
|
134 |
-
"align": 'left',
|
135 |
-
"reserveSpace": False,
|
136 |
-
"rotation": 270
|
137 |
-
},
|
138 |
-
"lineWidth": 0,
|
139 |
-
"margin": 20,
|
140 |
-
"tickWidth": 0
|
141 |
-
},
|
142 |
-
|
143 |
-
"yAxis": {
|
144 |
-
"visible": False,
|
145 |
-
"startOnTick": False,
|
146 |
-
"endOnTick": False
|
147 |
-
},
|
148 |
-
|
149 |
-
"legend": {
|
150 |
-
"enabled": False
|
151 |
-
},
|
152 |
-
|
153 |
-
"annotations": [{
|
154 |
-
"labels": [{
|
155 |
-
"point": {
|
156 |
-
"x": 5.5,
|
157 |
-
"xAxis": 0,
|
158 |
-
"y": 30,
|
159 |
-
"yAxis": 0
|
160 |
-
},
|
161 |
-
"text": 'Cancelled<br>during<br>World War II'
|
162 |
-
}, {
|
163 |
-
"point": {
|
164 |
-
"x": 18,
|
165 |
-
"xAxis": 0,
|
166 |
-
"y": 90,
|
167 |
-
"yAxis": 0
|
168 |
-
},
|
169 |
-
"text": 'Soviet Union fell,<br>Germany united'
|
170 |
-
}],
|
171 |
-
"labelOptions": {
|
172 |
-
"backgroundColor": 'rgba(255,255,255,0.5)',
|
173 |
-
"borderColor": 'silver'
|
174 |
-
}
|
175 |
-
}],
|
176 |
-
|
177 |
-
"plotOptions": {
|
178 |
-
"series": {
|
179 |
-
"label": {
|
180 |
-
"minFontSize": 5,
|
181 |
-
"maxFontSize": 15,
|
182 |
-
"style": {
|
183 |
-
"color": 'rgba(255,255,255,0.75)'
|
184 |
-
}
|
185 |
-
},
|
186 |
-
"accessibility": {
|
187 |
-
"exposeAsGroupOnly": True
|
188 |
-
}
|
189 |
-
}
|
190 |
-
},
|
191 |
-
"series": [{
|
192 |
-
"name": "Finland",
|
193 |
-
"data": [
|
194 |
-
0, 11, 4, 3, 6, 0, 0, 6, 9, 7, 8, 10, 5, 5, 7, 9, 13, 7,
|
195 |
-
7, 6, 12, 7, 9, 5, 5
|
196 |
-
]
|
197 |
-
}, {
|
198 |
-
"name": "Austria",
|
199 |
-
"data": [
|
200 |
-
0, 3, 4, 2, 4, 0, 0, 8, 8, 11, 6, 12, 11, 5, 6, 7, 1, 10,
|
201 |
-
21, 9, 17, 17, 23, 16, 17
|
202 |
-
]
|
203 |
-
}, {
|
204 |
-
"name": "Sweden",
|
205 |
-
"data": [
|
206 |
-
0, 2, 5, 3, 7, 0, 0, 10, 4, 10, 7, 7, 8, 4, 2, 4, 8, 6, 4,
|
207 |
-
3, 3, 7, 14, 11, 15
|
208 |
-
]
|
209 |
-
}, {
|
210 |
-
"name": "Norway",
|
211 |
-
"data": [
|
212 |
-
0, 17, 15, 10, 15, 0, 0, 10, 16, 4, 6, 15, 14, 12, 7, 10,
|
213 |
-
9, 5, 20, 26, 25, 25, 19, 23, 26
|
214 |
-
]
|
215 |
-
}, {
|
216 |
-
"name": "U.S.",
|
217 |
-
"data": [
|
218 |
-
0, 4, 6, 12, 4, 0, 0, 9, 11, 7, 10, 7, 7, 8, 10, 12, 8, 6,
|
219 |
-
11, 13, 13, 34, 25, 37, 28
|
220 |
-
]
|
221 |
-
}, {
|
222 |
-
"name": "East Germany",
|
223 |
-
"data": [
|
224 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 14, 19, 23, 24, 25,
|
225 |
-
0, 0, 0, 0, 0, 0, 0
|
226 |
-
]
|
227 |
-
}, {
|
228 |
-
"name": "West Germany",
|
229 |
-
"data": [
|
230 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 5, 10, 5, 4, 8, 0,
|
231 |
-
0, 0, 0, 0, 0, 0
|
232 |
-
]
|
233 |
-
}, {
|
234 |
-
"name": "Germany",
|
235 |
-
"data": [
|
236 |
-
0, 0, 1, 2, 6, 0, 0, 0, 7, 2, 8, 9, 0, 0, 0, 0, 0, 0, 26,
|
237 |
-
24, 29, 36, 29, 30, 19
|
238 |
-
]
|
239 |
-
}, {
|
240 |
-
"name": "Netherlands",
|
241 |
-
"data": [
|
242 |
-
0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 2, 2, 9, 9, 6, 4, 0, 7, 4,
|
243 |
-
4, 11, 8, 9, 8, 24
|
244 |
-
]
|
245 |
-
}, {
|
246 |
-
"name": "Italy",
|
247 |
-
"data": [
|
248 |
-
0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 1, 4, 4, 5, 4, 2, 2, 5, 14,
|
249 |
-
20, 10, 13, 11, 5, 8
|
250 |
-
]
|
251 |
-
}, {
|
252 |
-
"name": "Canada",
|
253 |
-
"data": [
|
254 |
-
0, 1, 1, 7, 1, 0, 0, 3, 2, 3, 4, 3, 3, 1, 3, 2, 4, 5, 7,
|
255 |
-
13, 15, 17, 24, 26, 25
|
256 |
-
]
|
257 |
-
}, {
|
258 |
-
"name": "Switzerland",
|
259 |
-
"data": [
|
260 |
-
0, 3, 1, 1, 3, 0, 0, 10, 2, 6, 2, 0, 6, 10, 5, 5, 5, 15,
|
261 |
-
3, 9, 7, 11, 14, 9, 11
|
262 |
-
]
|
263 |
-
}, {
|
264 |
-
"name": "Great Britain",
|
265 |
-
"data": [
|
266 |
-
0, 4, 1, 0, 3, 0, 0, 2, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0,
|
267 |
-
2, 1, 2, 1, 1, 4
|
268 |
-
]
|
269 |
-
}, {
|
270 |
-
"name": "France",
|
271 |
-
"data": [
|
272 |
-
0, 3, 1, 1, 1, 0, 0, 5, 1, 0, 3, 7, 9, 3, 1, 1, 3, 2, 9,
|
273 |
-
5, 8, 11, 9, 11, 15
|
274 |
-
]
|
275 |
-
}, {
|
276 |
-
"name": "Hungary",
|
277 |
-
"data": [
|
278 |
-
0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0,
|
279 |
-
0, 0, 0, 0, 0, 0
|
280 |
-
]
|
281 |
-
}, {
|
282 |
-
"name": "Unified Team",
|
283 |
-
"data": [
|
284 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23,
|
285 |
-
0, 0, 0, 0, 0, 0
|
286 |
-
]
|
287 |
-
}, {
|
288 |
-
"name": "Soviet Union",
|
289 |
-
"data": [
|
290 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 21, 25, 13, 16, 27, 22, 25,
|
291 |
-
29, 0, 0, 0, 0, 0, 0, 0
|
292 |
-
]
|
293 |
-
}, {
|
294 |
-
"name": "Russia",
|
295 |
-
"data": [
|
296 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
297 |
-
23, 18, 13, 22, 15, 33
|
298 |
-
]
|
299 |
-
}, {
|
300 |
-
"name": "Japan",
|
301 |
-
"data": [
|
302 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 1, 1, 1, 7,
|
303 |
-
5, 10, 2, 1, 5, 8
|
304 |
-
]
|
305 |
-
}, {
|
306 |
-
"name": "Czechoslovakia",
|
307 |
-
"data": [
|
308 |
-
0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 4, 3, 1, 1, 6, 3, 3,
|
309 |
-
0, 0, 0, 0, 0, 0
|
310 |
-
]
|
311 |
-
}, {
|
312 |
-
"name": "Poland",
|
313 |
-
"data": [
|
314 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 0, 0,
|
315 |
-
0, 0, 2, 2, 6, 6
|
316 |
-
]
|
317 |
-
}, {
|
318 |
-
"name": "Spain",
|
319 |
-
"data": [
|
320 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
|
321 |
-
0, 0, 0, 0, 0, 0
|
322 |
-
]
|
323 |
-
}, {
|
324 |
-
"name": "China",
|
325 |
-
"data": [
|
326 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
|
327 |
-
3, 8, 8, 11, 11, 9
|
328 |
-
]
|
329 |
-
}, {
|
330 |
-
"name": "South Korea",
|
331 |
-
"data": [
|
332 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,
|
333 |
-
6, 6, 4, 11, 14, 8
|
334 |
-
]
|
335 |
-
}, {
|
336 |
-
"name": "Czech Republic",
|
337 |
-
"data": [
|
338 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
339 |
-
0, 3, 3, 4, 6, 8
|
340 |
-
]
|
341 |
-
}, {
|
342 |
-
"name": "Belarus",
|
343 |
-
"data": [
|
344 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
345 |
-
2, 2, 1, 1, 3, 6
|
346 |
-
]
|
347 |
-
}, {
|
348 |
-
"name": "Kazakhstan",
|
349 |
-
"data": [
|
350 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
351 |
-
3, 2, 0, 0, 1, 1
|
352 |
-
]
|
353 |
-
}, {
|
354 |
-
"name": "Bulgaria",
|
355 |
-
"data": [
|
356 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
|
357 |
-
0, 1, 3, 1, 0, 0
|
358 |
-
]
|
359 |
-
}, {
|
360 |
-
"name": "Denmark",
|
361 |
-
"data": [
|
362 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
363 |
-
0, 1, 0, 0, 0, 0
|
364 |
-
]
|
365 |
-
}, {
|
366 |
-
"name": "Ukraine",
|
367 |
-
"data": [
|
368 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
369 |
-
2, 1, 0, 2, 0, 2
|
370 |
-
]
|
371 |
-
}, {
|
372 |
-
"name": "Australia",
|
373 |
-
"data": [
|
374 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
375 |
-
1, 1, 2, 2, 3, 3
|
376 |
-
]
|
377 |
-
}, {
|
378 |
-
"name": "Belgium",
|
379 |
-
"data": [
|
380 |
-
0, 1, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
381 |
-
0, 1, 0, 0, 0, 0
|
382 |
-
]
|
383 |
-
}, {
|
384 |
-
"name": "Romania",
|
385 |
-
"data": [
|
386 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
|
387 |
-
0, 0, 0, 0, 0, 0
|
388 |
-
]
|
389 |
-
}, {
|
390 |
-
"name": "Liechtenstein",
|
391 |
-
"data": [
|
392 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 2, 1, 0,
|
393 |
-
0, 0, 0, 0, 0, 0
|
394 |
-
]
|
395 |
-
}, {
|
396 |
-
"name": "Yugoslavia",
|
397 |
-
"data": [
|
398 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 0,
|
399 |
-
0, 0, 0, 0, 0, 0
|
400 |
-
]
|
401 |
-
}, {
|
402 |
-
"name": "Luxembourg",
|
403 |
-
"data": [
|
404 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
|
405 |
-
0, 0, 0, 0, 0, 0
|
406 |
-
]
|
407 |
-
}, {
|
408 |
-
"name": "New Zealand",
|
409 |
-
"data": [
|
410 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
|
411 |
-
0, 0, 0, 0, 0, 0
|
412 |
-
]
|
413 |
-
}, {
|
414 |
-
"name": "North Korea",
|
415 |
-
"data": [
|
416 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1,
|
417 |
-
0, 0, 0, 0, 0, 0
|
418 |
-
]
|
419 |
-
}, {
|
420 |
-
"name": "Slovakia",
|
421 |
-
"data": [
|
422 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
423 |
-
0, 0, 0, 1, 3, 1
|
424 |
-
]
|
425 |
-
}, {
|
426 |
-
"name": "Croatia",
|
427 |
-
"data": [
|
428 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
429 |
-
0, 0, 4, 3, 3, 1
|
430 |
-
]
|
431 |
-
}, {
|
432 |
-
"name": "Slovenia",
|
433 |
-
"data": [
|
434 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
435 |
-
3, 0, 1, 0, 3, 8
|
436 |
-
]
|
437 |
-
}, {
|
438 |
-
"name": "Latvia",
|
439 |
-
"data": [
|
440 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
441 |
-
0, 0, 0, 1, 2, 4
|
442 |
-
]
|
443 |
-
}, {
|
444 |
-
"name": "Estonia",
|
445 |
-
"data": [
|
446 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
447 |
-
0, 0, 3, 3, 1, 0
|
448 |
-
]
|
449 |
-
}, {
|
450 |
-
"name": "Uzbekistan",
|
451 |
-
"data": [
|
452 |
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
453 |
-
1, 0, 0, 0, 0, 0
|
454 |
-
]
|
455 |
-
}],
|
456 |
-
|
457 |
-
"exporting": {
|
458 |
-
"sourceWidth": 800,
|
459 |
-
"sourceHeight": 600
|
460 |
-
}
|
461 |
-
|
462 |
-
}
|
463 |
-
SAMPLE3={
|
464 |
-
|
465 |
-
"chart": {
|
466 |
-
"type": 'bubble',
|
467 |
-
"plotBorderWidth": 1,
|
468 |
-
"zoomType": 'xy'
|
469 |
-
},
|
470 |
-
|
471 |
-
"title": {
|
472 |
-
"text": 'Highcharts bubbles with radial gradient fill'
|
473 |
-
},
|
474 |
-
|
475 |
-
"xAxis": {
|
476 |
-
"gridLineWidth": 1,
|
477 |
-
"accessibility": {
|
478 |
-
"rangeDescription": 'Range: 0 to 100.'
|
479 |
-
}
|
480 |
-
},
|
481 |
-
|
482 |
-
"yAxis": {
|
483 |
-
"startOnTick": False,
|
484 |
-
"endOnTick": False,
|
485 |
-
"accessibility": {
|
486 |
-
"rangeDescription": 'Range: 0 to 100.'
|
487 |
-
}
|
488 |
-
},
|
489 |
-
|
490 |
-
"series": [{
|
491 |
-
"data": [
|
492 |
-
[9, 81, 63],
|
493 |
-
[98, 5, 89],
|
494 |
-
[51, 50, 73],
|
495 |
-
[41, 22, 14],
|
496 |
-
[58, 24, 20],
|
497 |
-
[78, 37, 34],
|
498 |
-
[55, 56, 53],
|
499 |
-
[18, 45, 70],
|
500 |
-
[42, 44, 28],
|
501 |
-
[3, 52, 59],
|
502 |
-
[31, 18, 97],
|
503 |
-
[79, 91, 63],
|
504 |
-
[93, 23, 23],
|
505 |
-
[44, 83, 22]
|
506 |
-
],
|
507 |
-
"marker": {
|
508 |
-
"fillColor": {
|
509 |
-
"radialGradient": { "cx": 0.4, "cy": 0.3, "r": 0.7 },
|
510 |
-
"stops": [
|
511 |
-
[0, 'rgba(255,255,255,0.5)'],
|
512 |
-
[1, 'rgba(124,181,236,0.5)']
|
513 |
-
]
|
514 |
-
}
|
515 |
-
}
|
516 |
-
}, {
|
517 |
-
"data": [
|
518 |
-
[42, 38, 20],
|
519 |
-
[6, 18, 1],
|
520 |
-
[1, 93, 55],
|
521 |
-
[57, 2, 90],
|
522 |
-
[80, 76, 22],
|
523 |
-
[11, 74, 96],
|
524 |
-
[88, 56, 10],
|
525 |
-
[30, 47, 49],
|
526 |
-
[57, 62, 98],
|
527 |
-
[4, 16, 16],
|
528 |
-
[46, 10, 11],
|
529 |
-
[22, 87, 89],
|
530 |
-
[57, 91, 82],
|
531 |
-
[45, 15, 98]
|
532 |
-
],
|
533 |
-
"marker": {
|
534 |
-
"fillColor": {
|
535 |
-
"radialGradient": { "cx": 0.4, "cy": 0.3, "r": 0.7 },
|
536 |
-
"stops": [
|
537 |
-
[0, 'rgba(255,255,255,0.5)'],
|
538 |
-
[1, 'rgba(67,67,72,0.5)']
|
539 |
-
]
|
540 |
-
}
|
541 |
-
}
|
542 |
-
}]
|
543 |
-
|
544 |
-
}
|
545 |
-
SAMPLE4={
|
546 |
-
|
547 |
-
"chart":{
|
548 |
-
"type":"packedbubble",
|
549 |
-
"height":"100%"
|
550 |
-
},
|
551 |
-
"title":{
|
552 |
-
"text":"Carbon emissions around the world (2014)"
|
553 |
-
},
|
554 |
-
"tooltip":{
|
555 |
-
"useHTML":True,
|
556 |
-
"pointFormat":"<b>{point.name}:</b> {point.value}m CO<sub>2</sub>"
|
557 |
-
},
|
558 |
-
"plotOptions":{
|
559 |
-
"packedbubble":{
|
560 |
-
"minSize":"20%",
|
561 |
-
"maxSize":"100%",
|
562 |
-
"zMin":0,
|
563 |
-
"zMax":1000,
|
564 |
-
"layoutAlgorithm":{
|
565 |
-
"gravitationalConstant":0.05,
|
566 |
-
"splitSeries":True,
|
567 |
-
"seriesInteraction":False,
|
568 |
-
"dragBetweenSeries":True,
|
569 |
-
"parentNodeLimit":True
|
570 |
-
},
|
571 |
-
"dataLabels":{
|
572 |
-
"enabled":True,
|
573 |
-
"format":"{point.name}",
|
574 |
-
"filter":{
|
575 |
-
"property":"y",
|
576 |
-
"operator":">",
|
577 |
-
"value":250
|
578 |
-
},
|
579 |
-
"style":{
|
580 |
-
"color":"black",
|
581 |
-
"textOutline":"none",
|
582 |
-
"fontWeight":"normal"
|
583 |
-
}
|
584 |
-
}
|
585 |
-
}
|
586 |
-
},
|
587 |
-
"series":[
|
588 |
-
{
|
589 |
-
"name":"Europe",
|
590 |
-
"data":[
|
591 |
-
{
|
592 |
-
"name":"Germany",
|
593 |
-
"value":767.1
|
594 |
-
},
|
595 |
-
{
|
596 |
-
"name":"Croatia",
|
597 |
-
"value":20.7
|
598 |
-
},
|
599 |
-
{
|
600 |
-
"name":"Belgium",
|
601 |
-
"value":97.2
|
602 |
-
},
|
603 |
-
{
|
604 |
-
"name":"Czech Republic",
|
605 |
-
"value":111.7
|
606 |
-
},
|
607 |
-
{
|
608 |
-
"name":"Netherlands",
|
609 |
-
"value":158.1
|
610 |
-
},
|
611 |
-
{
|
612 |
-
"name":"Spain",
|
613 |
-
"value":241.6
|
614 |
-
},
|
615 |
-
{
|
616 |
-
"name":"Ukraine",
|
617 |
-
"value":249.1
|
618 |
-
},
|
619 |
-
{
|
620 |
-
"name":"Poland",
|
621 |
-
"value":298.1
|
622 |
-
},
|
623 |
-
{
|
624 |
-
"name":"France",
|
625 |
-
"value":323.7
|
626 |
-
},
|
627 |
-
{
|
628 |
-
"name":"Romania",
|
629 |
-
"value":78.3
|
630 |
-
},
|
631 |
-
{
|
632 |
-
"name":"United Kingdom",
|
633 |
-
"value":415.4
|
634 |
-
},
|
635 |
-
{
|
636 |
-
"name":"Turkey",
|
637 |
-
"value":353.2
|
638 |
-
},
|
639 |
-
{
|
640 |
-
"name":"Italy",
|
641 |
-
"value":337.6
|
642 |
-
},
|
643 |
-
{
|
644 |
-
"name":"Greece",
|
645 |
-
"value":71.1
|
646 |
-
},
|
647 |
-
{
|
648 |
-
"name":"Austria",
|
649 |
-
"value":69.8
|
650 |
-
},
|
651 |
-
{
|
652 |
-
"name":"Belarus",
|
653 |
-
"value":67.7
|
654 |
-
},
|
655 |
-
{
|
656 |
-
"name":"Serbia",
|
657 |
-
"value":59.3
|
658 |
-
},
|
659 |
-
{
|
660 |
-
"name":"Finland",
|
661 |
-
"value":54.8
|
662 |
-
},
|
663 |
-
{
|
664 |
-
"name":"Bulgaria",
|
665 |
-
"value":51.2
|
666 |
-
},
|
667 |
-
{
|
668 |
-
"name":"Portugal",
|
669 |
-
"value":48.3
|
670 |
-
},
|
671 |
-
{
|
672 |
-
"name":"Norway",
|
673 |
-
"value":44.4
|
674 |
-
},
|
675 |
-
{
|
676 |
-
"name":"Sweden",
|
677 |
-
"value":44.3
|
678 |
-
},
|
679 |
-
{
|
680 |
-
"name":"Hungary",
|
681 |
-
"value":43.7
|
682 |
-
},
|
683 |
-
{
|
684 |
-
"name":"Switzerland",
|
685 |
-
"value":40.2
|
686 |
-
},
|
687 |
-
{
|
688 |
-
"name":"Denmark",
|
689 |
-
"value":40
|
690 |
-
},
|
691 |
-
{
|
692 |
-
"name":"Slovakia",
|
693 |
-
"value":34.7
|
694 |
-
},
|
695 |
-
{
|
696 |
-
"name":"Ireland",
|
697 |
-
"value":34.6
|
698 |
-
},
|
699 |
-
{
|
700 |
-
"name":"Croatia",
|
701 |
-
"value":20.7
|
702 |
-
},
|
703 |
-
{
|
704 |
-
"name":"Estonia",
|
705 |
-
"value":19.4
|
706 |
-
},
|
707 |
-
{
|
708 |
-
"name":"Slovenia",
|
709 |
-
"value":16.7
|
710 |
-
},
|
711 |
-
{
|
712 |
-
"name":"Lithuania",
|
713 |
-
"value":12.3
|
714 |
-
},
|
715 |
-
{
|
716 |
-
"name":"Luxembourg",
|
717 |
-
"value":10.4
|
718 |
-
},
|
719 |
-
{
|
720 |
-
"name":"Macedonia",
|
721 |
-
"value":9.5
|
722 |
-
},
|
723 |
-
{
|
724 |
-
"name":"Moldova",
|
725 |
-
"value":7.8
|
726 |
-
},
|
727 |
-
{
|
728 |
-
"name":"Latvia",
|
729 |
-
"value":7.5
|
730 |
-
},
|
731 |
-
{
|
732 |
-
"name":"Cyprus",
|
733 |
-
"value":7.2
|
734 |
-
}
|
735 |
-
]
|
736 |
-
},
|
737 |
-
{
|
738 |
-
"name":"Africa",
|
739 |
-
"data":[
|
740 |
-
{
|
741 |
-
"name":"Senegal",
|
742 |
-
"value":8.2
|
743 |
-
},
|
744 |
-
{
|
745 |
-
"name":"Cameroon",
|
746 |
-
"value":9.2
|
747 |
-
},
|
748 |
-
{
|
749 |
-
"name":"Zimbabwe",
|
750 |
-
"value":13.1
|
751 |
-
},
|
752 |
-
{
|
753 |
-
"name":"Ghana",
|
754 |
-
"value":14.1
|
755 |
-
},
|
756 |
-
{
|
757 |
-
"name":"Kenya",
|
758 |
-
"value":14.1
|
759 |
-
},
|
760 |
-
{
|
761 |
-
"name":"Sudan",
|
762 |
-
"value":17.3
|
763 |
-
},
|
764 |
-
{
|
765 |
-
"name":"Tunisia",
|
766 |
-
"value":24.3
|
767 |
-
},
|
768 |
-
{
|
769 |
-
"name":"Angola",
|
770 |
-
"value":25
|
771 |
-
},
|
772 |
-
{
|
773 |
-
"name":"Libya",
|
774 |
-
"value":50.6
|
775 |
-
},
|
776 |
-
{
|
777 |
-
"name":"Ivory Coast",
|
778 |
-
"value":7.3
|
779 |
-
},
|
780 |
-
{
|
781 |
-
"name":"Morocco",
|
782 |
-
"value":60.7
|
783 |
-
},
|
784 |
-
{
|
785 |
-
"name":"Ethiopia",
|
786 |
-
"value":8.9
|
787 |
-
},
|
788 |
-
{
|
789 |
-
"name":"United Republic of Tanzania",
|
790 |
-
"value":9.1
|
791 |
-
},
|
792 |
-
{
|
793 |
-
"name":"Nigeria",
|
794 |
-
"value":93.9
|
795 |
-
},
|
796 |
-
{
|
797 |
-
"name":"South Africa",
|
798 |
-
"value":392.7
|
799 |
-
},
|
800 |
-
{
|
801 |
-
"name":"Egypt",
|
802 |
-
"value":225.1
|
803 |
-
},
|
804 |
-
{
|
805 |
-
"name":"Algeria",
|
806 |
-
"value":141.5
|
807 |
-
}
|
808 |
-
]
|
809 |
-
},
|
810 |
-
{
|
811 |
-
"name":"Oceania",
|
812 |
-
"data":[
|
813 |
-
{
|
814 |
-
"name":"Australia",
|
815 |
-
"value":409.4
|
816 |
-
},
|
817 |
-
{
|
818 |
-
"name":"New Zealand",
|
819 |
-
"value":34.1
|
820 |
-
},
|
821 |
-
{
|
822 |
-
"name":"Papua New Guinea",
|
823 |
-
"value":7.1
|
824 |
-
}
|
825 |
-
]
|
826 |
-
},
|
827 |
-
{
|
828 |
-
"name":"North America",
|
829 |
-
"data":[
|
830 |
-
{
|
831 |
-
"name":"Costa Rica",
|
832 |
-
"value":7.6
|
833 |
-
},
|
834 |
-
{
|
835 |
-
"name":"Honduras",
|
836 |
-
"value":8.4
|
837 |
-
},
|
838 |
-
{
|
839 |
-
"name":"Jamaica",
|
840 |
-
"value":8.3
|
841 |
-
},
|
842 |
-
{
|
843 |
-
"name":"Panama",
|
844 |
-
"value":10.2
|
845 |
-
},
|
846 |
-
{
|
847 |
-
"name":"Guatemala",
|
848 |
-
"value":12
|
849 |
-
},
|
850 |
-
{
|
851 |
-
"name":"Dominican Republic",
|
852 |
-
"value":23.4
|
853 |
-
},
|
854 |
-
{
|
855 |
-
"name":"Cuba",
|
856 |
-
"value":30.2
|
857 |
-
},
|
858 |
-
{
|
859 |
-
"name":"USA",
|
860 |
-
"value":5334.5
|
861 |
-
},
|
862 |
-
{
|
863 |
-
"name":"Canada",
|
864 |
-
"value":566
|
865 |
-
},
|
866 |
-
{
|
867 |
-
"name":"Mexico",
|
868 |
-
"value":456.3
|
869 |
-
}
|
870 |
-
]
|
871 |
-
},
|
872 |
-
{
|
873 |
-
"name":"South America",
|
874 |
-
"data":[
|
875 |
-
{
|
876 |
-
"name":"El Salvador",
|
877 |
-
"value":7.2
|
878 |
-
},
|
879 |
-
{
|
880 |
-
"name":"Uruguay",
|
881 |
-
"value":8.1
|
882 |
-
},
|
883 |
-
{
|
884 |
-
"name":"Bolivia",
|
885 |
-
"value":17.8
|
886 |
-
},
|
887 |
-
{
|
888 |
-
"name":"Trinidad and Tobago",
|
889 |
-
"value":34
|
890 |
-
},
|
891 |
-
{
|
892 |
-
"name":"Ecuador",
|
893 |
-
"value":43
|
894 |
-
},
|
895 |
-
{
|
896 |
-
"name":"Chile",
|
897 |
-
"value":78.6
|
898 |
-
},
|
899 |
-
{
|
900 |
-
"name":"Peru",
|
901 |
-
"value":52
|
902 |
-
},
|
903 |
-
{
|
904 |
-
"name":"Colombia",
|
905 |
-
"value":74.1
|
906 |
-
},
|
907 |
-
{
|
908 |
-
"name":"Brazil",
|
909 |
-
"value":501.1
|
910 |
-
},
|
911 |
-
{
|
912 |
-
"name":"Argentina",
|
913 |
-
"value":199
|
914 |
-
},
|
915 |
-
{
|
916 |
-
"name":"Venezuela",
|
917 |
-
"value":195.2
|
918 |
-
}
|
919 |
-
]
|
920 |
-
},
|
921 |
-
{
|
922 |
-
"name":"Asia",
|
923 |
-
"data":[
|
924 |
-
{
|
925 |
-
"name":"Nepal",
|
926 |
-
"value":6.5
|
927 |
-
},
|
928 |
-
{
|
929 |
-
"name":"Georgia",
|
930 |
-
"value":6.5
|
931 |
-
},
|
932 |
-
{
|
933 |
-
"name":"Brunei Darussalam",
|
934 |
-
"value":7.4
|
935 |
-
},
|
936 |
-
{
|
937 |
-
"name":"Kyrgyzstan",
|
938 |
-
"value":7.4
|
939 |
-
},
|
940 |
-
{
|
941 |
-
"name":"Afghanistan",
|
942 |
-
"value":7.9
|
943 |
-
},
|
944 |
-
{
|
945 |
-
"name":"Myanmar",
|
946 |
-
"value":9.1
|
947 |
-
},
|
948 |
-
{
|
949 |
-
"name":"Mongolia",
|
950 |
-
"value":14.7
|
951 |
-
},
|
952 |
-
{
|
953 |
-
"name":"Sri Lanka",
|
954 |
-
"value":16.6
|
955 |
-
},
|
956 |
-
{
|
957 |
-
"name":"Bahrain",
|
958 |
-
"value":20.5
|
959 |
-
},
|
960 |
-
{
|
961 |
-
"name":"Yemen",
|
962 |
-
"value":22.6
|
963 |
-
},
|
964 |
-
{
|
965 |
-
"name":"Jordan",
|
966 |
-
"value":22.3
|
967 |
-
},
|
968 |
-
{
|
969 |
-
"name":"Lebanon",
|
970 |
-
"value":21.1
|
971 |
-
},
|
972 |
-
{
|
973 |
-
"name":"Azerbaijan",
|
974 |
-
"value":31.7
|
975 |
-
},
|
976 |
-
{
|
977 |
-
"name":"Singapore",
|
978 |
-
"value":47.8
|
979 |
-
},
|
980 |
-
{
|
981 |
-
"name":"Hong Kong",
|
982 |
-
"value":49.9
|
983 |
-
},
|
984 |
-
{
|
985 |
-
"name":"Syria",
|
986 |
-
"value":52.7
|
987 |
-
},
|
988 |
-
{
|
989 |
-
"name":"DPR Korea",
|
990 |
-
"value":59.9
|
991 |
-
},
|
992 |
-
{
|
993 |
-
"name":"Israel",
|
994 |
-
"value":64.8
|
995 |
-
},
|
996 |
-
{
|
997 |
-
"name":"Turkmenistan",
|
998 |
-
"value":70.6
|
999 |
-
},
|
1000 |
-
{
|
1001 |
-
"name":"Oman",
|
1002 |
-
"value":74.3
|
1003 |
-
},
|
1004 |
-
{
|
1005 |
-
"name":"Qatar",
|
1006 |
-
"value":88.8
|
1007 |
-
},
|
1008 |
-
{
|
1009 |
-
"name":"Philippines",
|
1010 |
-
"value":96.9
|
1011 |
-
},
|
1012 |
-
{
|
1013 |
-
"name":"Kuwait",
|
1014 |
-
"value":98.6
|
1015 |
-
},
|
1016 |
-
{
|
1017 |
-
"name":"Uzbekistan",
|
1018 |
-
"value":122.6
|
1019 |
-
},
|
1020 |
-
{
|
1021 |
-
"name":"Iraq",
|
1022 |
-
"value":139.9
|
1023 |
-
},
|
1024 |
-
{
|
1025 |
-
"name":"Pakistan",
|
1026 |
-
"value":158.1
|
1027 |
-
},
|
1028 |
-
{
|
1029 |
-
"name":"Vietnam",
|
1030 |
-
"value":190.2
|
1031 |
-
},
|
1032 |
-
{
|
1033 |
-
"name":"United Arab Emirates",
|
1034 |
-
"value":201.1
|
1035 |
-
},
|
1036 |
-
{
|
1037 |
-
"name":"Malaysia",
|
1038 |
-
"value":227.5
|
1039 |
-
},
|
1040 |
-
{
|
1041 |
-
"name":"Kazakhstan",
|
1042 |
-
"value":236.2
|
1043 |
-
},
|
1044 |
-
{
|
1045 |
-
"name":"Thailand",
|
1046 |
-
"value":272
|
1047 |
-
},
|
1048 |
-
{
|
1049 |
-
"name":"Taiwan",
|
1050 |
-
"value":276.7
|
1051 |
-
},
|
1052 |
-
{
|
1053 |
-
"name":"Indonesia",
|
1054 |
-
"value":453
|
1055 |
-
},
|
1056 |
-
{
|
1057 |
-
"name":"Saudi Arabia",
|
1058 |
-
"value":494.8
|
1059 |
-
},
|
1060 |
-
{
|
1061 |
-
"name":"Japan",
|
1062 |
-
"value":1278.9
|
1063 |
-
},
|
1064 |
-
{
|
1065 |
-
"name":"China",
|
1066 |
-
"value":10540.8
|
1067 |
-
},
|
1068 |
-
{
|
1069 |
-
"name":"India",
|
1070 |
-
"value":2341.9
|
1071 |
-
},
|
1072 |
-
{
|
1073 |
-
"name":"Russia",
|
1074 |
-
"value":1766.4
|
1075 |
-
},
|
1076 |
-
{
|
1077 |
-
"name":"Iran",
|
1078 |
-
"value":618.2
|
1079 |
-
},
|
1080 |
-
{
|
1081 |
-
"name":"Korea",
|
1082 |
-
"value":610.1
|
1083 |
-
}
|
1084 |
-
]
|
1085 |
-
}
|
1086 |
-
]
|
1087 |
-
}
|
1088 |
-
SAMPLE5={
|
1089 |
-
"chart":{
|
1090 |
-
"type":"column"
|
1091 |
-
},
|
1092 |
-
"title":{
|
1093 |
-
"align":"left",
|
1094 |
-
"text":"Browser market shares. January, 2022"
|
1095 |
-
},
|
1096 |
-
"subtitle":{
|
1097 |
-
"align":"left",
|
1098 |
-
"text":"Click the columns to view versions. Source: <a href=\"http://statcounter.com\" target=\"_blank\">statcounter.com</a>"
|
1099 |
-
},
|
1100 |
-
"accessibility":{
|
1101 |
-
"announceNewData":{
|
1102 |
-
"enabled":True
|
1103 |
-
}
|
1104 |
-
},
|
1105 |
-
"xAxis":{
|
1106 |
-
"type":"category"
|
1107 |
-
},
|
1108 |
-
"yAxis":{
|
1109 |
-
"title":{
|
1110 |
-
"text":"Total percent market share"
|
1111 |
-
}
|
1112 |
-
},
|
1113 |
-
"legend":{
|
1114 |
-
"enabled":False
|
1115 |
-
},
|
1116 |
-
"plotOptions":{
|
1117 |
-
"series":{
|
1118 |
-
"borderWidth":0,
|
1119 |
-
"dataLabels":{
|
1120 |
-
"enabled":True,
|
1121 |
-
"format":"{point.y:.1f}%"
|
1122 |
-
}
|
1123 |
-
}
|
1124 |
-
},
|
1125 |
-
"tooltip":{
|
1126 |
-
"headerFormat":"<span style=\"font-size:11px\">{series.name}</span><br>",
|
1127 |
-
"pointFormat":"<span style=\"color:{point.color}\">{point.name}</span>: <b>{point.y:.2f}%</b> of total<br/>"
|
1128 |
-
},
|
1129 |
-
"series":[
|
1130 |
-
{
|
1131 |
-
"name":"Browsers",
|
1132 |
-
"colorByPoint":True,
|
1133 |
-
"data":[
|
1134 |
-
{
|
1135 |
-
"name":"Chrome",
|
1136 |
-
"y":63.06,
|
1137 |
-
"drilldown":"Chrome"
|
1138 |
-
},
|
1139 |
-
{
|
1140 |
-
"name":"Safari",
|
1141 |
-
"y":19.84,
|
1142 |
-
"drilldown":"Safari"
|
1143 |
-
},
|
1144 |
-
{
|
1145 |
-
"name":"Firefox",
|
1146 |
-
"y":4.18,
|
1147 |
-
"drilldown":"Firefox"
|
1148 |
-
},
|
1149 |
-
{
|
1150 |
-
"name":"Edge",
|
1151 |
-
"y":4.12,
|
1152 |
-
"drilldown":"Edge"
|
1153 |
-
},
|
1154 |
-
{
|
1155 |
-
"name":"Opera",
|
1156 |
-
"y":2.33,
|
1157 |
-
"drilldown":"Opera"
|
1158 |
-
},
|
1159 |
-
{
|
1160 |
-
"name":"Internet Explorer",
|
1161 |
-
"y":0.45,
|
1162 |
-
"drilldown":"Internet Explorer"
|
1163 |
-
},
|
1164 |
-
{
|
1165 |
-
"name":"Other",
|
1166 |
-
"y":1.582,
|
1167 |
-
"drilldown":"null"
|
1168 |
-
}
|
1169 |
-
]
|
1170 |
-
}
|
1171 |
-
],
|
1172 |
-
"drilldown":{
|
1173 |
-
"breadcrumbs":{
|
1174 |
-
"position":{
|
1175 |
-
"align":"right"
|
1176 |
-
}
|
1177 |
-
},
|
1178 |
-
"series":[
|
1179 |
-
{
|
1180 |
-
"name":"Chrome",
|
1181 |
-
"id":"Chrome",
|
1182 |
-
"data":[
|
1183 |
-
[
|
1184 |
-
"v65.0",
|
1185 |
-
0.1
|
1186 |
-
],
|
1187 |
-
[
|
1188 |
-
"v64.0",
|
1189 |
-
1.3
|
1190 |
-
],
|
1191 |
-
[
|
1192 |
-
"v63.0",
|
1193 |
-
53.02
|
1194 |
-
],
|
1195 |
-
[
|
1196 |
-
"v62.0",
|
1197 |
-
1.4
|
1198 |
-
],
|
1199 |
-
[
|
1200 |
-
"v61.0",
|
1201 |
-
0.88
|
1202 |
-
],
|
1203 |
-
[
|
1204 |
-
"v60.0",
|
1205 |
-
0.56
|
1206 |
-
],
|
1207 |
-
[
|
1208 |
-
"v59.0",
|
1209 |
-
0.45
|
1210 |
-
],
|
1211 |
-
[
|
1212 |
-
"v58.0",
|
1213 |
-
0.49
|
1214 |
-
],
|
1215 |
-
[
|
1216 |
-
"v57.0",
|
1217 |
-
0.32
|
1218 |
-
],
|
1219 |
-
[
|
1220 |
-
"v56.0",
|
1221 |
-
0.29
|
1222 |
-
],
|
1223 |
-
[
|
1224 |
-
"v55.0",
|
1225 |
-
0.79
|
1226 |
-
],
|
1227 |
-
[
|
1228 |
-
"v54.0",
|
1229 |
-
0.18
|
1230 |
-
],
|
1231 |
-
[
|
1232 |
-
"v51.0",
|
1233 |
-
0.13
|
1234 |
-
],
|
1235 |
-
[
|
1236 |
-
"v49.0",
|
1237 |
-
2.16
|
1238 |
-
],
|
1239 |
-
[
|
1240 |
-
"v48.0",
|
1241 |
-
0.13
|
1242 |
-
],
|
1243 |
-
[
|
1244 |
-
"v47.0",
|
1245 |
-
0.11
|
1246 |
-
],
|
1247 |
-
[
|
1248 |
-
"v43.0",
|
1249 |
-
0.17
|
1250 |
-
],
|
1251 |
-
[
|
1252 |
-
"v29.0",
|
1253 |
-
0.26
|
1254 |
-
]
|
1255 |
-
]
|
1256 |
-
},
|
1257 |
-
{
|
1258 |
-
"name":"Firefox",
|
1259 |
-
"id":"Firefox",
|
1260 |
-
"data":[
|
1261 |
-
[
|
1262 |
-
"v58.0",
|
1263 |
-
1.02
|
1264 |
-
],
|
1265 |
-
[
|
1266 |
-
"v57.0",
|
1267 |
-
7.36
|
1268 |
-
],
|
1269 |
-
[
|
1270 |
-
"v56.0",
|
1271 |
-
0.35
|
1272 |
-
],
|
1273 |
-
[
|
1274 |
-
"v55.0",
|
1275 |
-
0.11
|
1276 |
-
],
|
1277 |
-
[
|
1278 |
-
"v54.0",
|
1279 |
-
0.1
|
1280 |
-
],
|
1281 |
-
[
|
1282 |
-
"v52.0",
|
1283 |
-
0.95
|
1284 |
-
],
|
1285 |
-
[
|
1286 |
-
"v51.0",
|
1287 |
-
0.15
|
1288 |
-
],
|
1289 |
-
[
|
1290 |
-
"v50.0",
|
1291 |
-
0.1
|
1292 |
-
],
|
1293 |
-
[
|
1294 |
-
"v48.0",
|
1295 |
-
0.31
|
1296 |
-
],
|
1297 |
-
[
|
1298 |
-
"v47.0",
|
1299 |
-
0.12
|
1300 |
-
]
|
1301 |
-
]
|
1302 |
-
},
|
1303 |
-
{
|
1304 |
-
"name":"Internet Explorer",
|
1305 |
-
"id":"Internet Explorer",
|
1306 |
-
"data":[
|
1307 |
-
[
|
1308 |
-
"v11.0",
|
1309 |
-
6.2
|
1310 |
-
],
|
1311 |
-
[
|
1312 |
-
"v10.0",
|
1313 |
-
0.29
|
1314 |
-
],
|
1315 |
-
[
|
1316 |
-
"v9.0",
|
1317 |
-
0.27
|
1318 |
-
],
|
1319 |
-
[
|
1320 |
-
"v8.0",
|
1321 |
-
0.47
|
1322 |
-
]
|
1323 |
-
]
|
1324 |
-
},
|
1325 |
-
{
|
1326 |
-
"name":"Safari",
|
1327 |
-
"id":"Safari",
|
1328 |
-
"data":[
|
1329 |
-
[
|
1330 |
-
"v11.0",
|
1331 |
-
3.39
|
1332 |
-
],
|
1333 |
-
[
|
1334 |
-
"v10.1",
|
1335 |
-
0.96
|
1336 |
-
],
|
1337 |
-
[
|
1338 |
-
"v10.0",
|
1339 |
-
0.36
|
1340 |
-
],
|
1341 |
-
[
|
1342 |
-
"v9.1",
|
1343 |
-
0.54
|
1344 |
-
],
|
1345 |
-
[
|
1346 |
-
"v9.0",
|
1347 |
-
0.13
|
1348 |
-
],
|
1349 |
-
[
|
1350 |
-
"v5.1",
|
1351 |
-
0.2
|
1352 |
-
]
|
1353 |
-
]
|
1354 |
-
},
|
1355 |
-
{
|
1356 |
-
"name":"Edge",
|
1357 |
-
"id":"Edge",
|
1358 |
-
"data":[
|
1359 |
-
[
|
1360 |
-
"v16",
|
1361 |
-
2.6
|
1362 |
-
],
|
1363 |
-
[
|
1364 |
-
"v15",
|
1365 |
-
0.92
|
1366 |
-
],
|
1367 |
-
[
|
1368 |
-
"v14",
|
1369 |
-
0.4
|
1370 |
-
],
|
1371 |
-
[
|
1372 |
-
"v13",
|
1373 |
-
0.1
|
1374 |
-
]
|
1375 |
-
]
|
1376 |
-
},
|
1377 |
-
{
|
1378 |
-
"name":"Opera",
|
1379 |
-
"id":"Opera",
|
1380 |
-
"data":[
|
1381 |
-
[
|
1382 |
-
"v50.0",
|
1383 |
-
0.96
|
1384 |
-
],
|
1385 |
-
[
|
1386 |
-
"v49.0",
|
1387 |
-
0.82
|
1388 |
-
],
|
1389 |
-
[
|
1390 |
-
"v12.1",
|
1391 |
-
0.14
|
1392 |
-
]
|
1393 |
-
]
|
1394 |
-
}
|
1395 |
-
]
|
1396 |
-
}
|
1397 |
-
}
|
1398 |
-
SAMPLE6={
|
1399 |
-
"chart":{
|
1400 |
-
"type":"tilemap",
|
1401 |
-
"inverted":True,
|
1402 |
-
"height":"80%"
|
1403 |
-
},
|
1404 |
-
"accessibility":{
|
1405 |
-
"description":"A tile map represents the states of the USA by population in 2016. The hexagonal tiles are positioned to geographically echo the map of the USA. A color-coded legend states the population levels as below 1 million (beige), 1 to 5 million (orange), 5 to 20 million (pink) and above 20 million (hot pink). The chart is interactive, and the individual state data points are displayed upon hovering. Three states have a population of above 20 million: California (39.3 million), Texas (27.9 million) and Florida (20.6 million). The northern US region from Massachusetts in the Northwest to Illinois in the Midwest contains the highest concentration of states with a population of 5 to 20 million people. The southern US region from South Carolina in the Southeast to New Mexico in the Southwest contains the highest concentration of states with a population of 1 to 5 million people. 6 states have a population of less than 1 million people; these include Alaska, Delaware, Wyoming, North Dakota, South Dakota and Vermont. The state with the lowest population is Wyoming in the Northwest with 584,153 people.",
|
1406 |
-
"screenReaderSection":{
|
1407 |
-
"beforeChartFormat":"<h5>{chartTitle}</h5>""+""<div>{chartSubtitle}</div>""+""<div>{chartLongdesc}</div>""+""<div>{viewTableButton}</div>"
|
1408 |
-
},
|
1409 |
-
"point":{
|
1410 |
-
"valueDescriptionFormat":"{index}. {xDescription}, {point.value}."
|
1411 |
-
}
|
1412 |
-
},
|
1413 |
-
"title":{
|
1414 |
-
"text":"U.S. states by population in 2016"
|
1415 |
-
},
|
1416 |
-
"subtitle":{
|
1417 |
-
"text":"Source:<a href=\"https://simple.wikipedia.org/wiki/List_of_U.S._states_by_population\">Wikipedia</a>"
|
1418 |
-
},
|
1419 |
-
"xAxis":{
|
1420 |
-
"visible":False
|
1421 |
-
},
|
1422 |
-
"yAxis":{
|
1423 |
-
"visible":False
|
1424 |
-
},
|
1425 |
-
"colorAxis":{
|
1426 |
-
"dataClasses":[
|
1427 |
-
{
|
1428 |
-
"from":0,
|
1429 |
-
"to":1000000,
|
1430 |
-
"color":"#F9EDB3",
|
1431 |
-
"name":"< 1M"
|
1432 |
-
},
|
1433 |
-
{
|
1434 |
-
"from":1000000,
|
1435 |
-
"to":5000000,
|
1436 |
-
"color":"#FFC428",
|
1437 |
-
"name":"1M - 5M"
|
1438 |
-
},
|
1439 |
-
{
|
1440 |
-
"from":5000000,
|
1441 |
-
"to":20000000,
|
1442 |
-
"color":"#FF7987",
|
1443 |
-
"name":"5M - 20M"
|
1444 |
-
},
|
1445 |
-
{
|
1446 |
-
"from":20000000,
|
1447 |
-
"color":"#FF2371",
|
1448 |
-
"name":"> 20M"
|
1449 |
-
}
|
1450 |
-
]
|
1451 |
-
},
|
1452 |
-
"tooltip":{
|
1453 |
-
"headerFormat":"",
|
1454 |
-
"pointFormat":"The population of <b> {point.name}</b> is <b>{point.value}</b>"
|
1455 |
-
},
|
1456 |
-
"plotOptions":{
|
1457 |
-
"series":{
|
1458 |
-
"dataLabels":{
|
1459 |
-
"enabled":True,
|
1460 |
-
"format":"{point.hc-a2}",
|
1461 |
-
"color":"#000000",
|
1462 |
-
"style":{
|
1463 |
-
"textOutline":False
|
1464 |
-
}
|
1465 |
-
}
|
1466 |
-
}
|
1467 |
-
},
|
1468 |
-
"series":[
|
1469 |
-
{
|
1470 |
-
"name":"",
|
1471 |
-
"data":[
|
1472 |
-
{
|
1473 |
-
"hc-a2":"AL",
|
1474 |
-
"name":"Alabama",
|
1475 |
-
"region":"South",
|
1476 |
-
"x":6,
|
1477 |
-
"y":7,
|
1478 |
-
"value":4849377
|
1479 |
-
},
|
1480 |
-
{
|
1481 |
-
"hc-a2":"AK",
|
1482 |
-
"name":"Alaska",
|
1483 |
-
"region":"West",
|
1484 |
-
"x":0,
|
1485 |
-
"y":0,
|
1486 |
-
"value":737732
|
1487 |
-
},
|
1488 |
-
{
|
1489 |
-
"hc-a2":"AZ",
|
1490 |
-
"name":"Arizona",
|
1491 |
-
"region":"West",
|
1492 |
-
"x":5,
|
1493 |
-
"y":3,
|
1494 |
-
"value":6745408
|
1495 |
-
},
|
1496 |
-
{
|
1497 |
-
"hc-a2":"AR",
|
1498 |
-
"name":"Arkansas",
|
1499 |
-
"region":"South",
|
1500 |
-
"x":5,
|
1501 |
-
"y":6,
|
1502 |
-
"value":2994079
|
1503 |
-
},
|
1504 |
-
{
|
1505 |
-
"hc-a2":"CA",
|
1506 |
-
"name":"California",
|
1507 |
-
"region":"West",
|
1508 |
-
"x":5,
|
1509 |
-
"y":2,
|
1510 |
-
"value":39250017
|
1511 |
-
},
|
1512 |
-
{
|
1513 |
-
"hc-a2":"CO",
|
1514 |
-
"name":"Colorado",
|
1515 |
-
"region":"West",
|
1516 |
-
"x":4,
|
1517 |
-
"y":3,
|
1518 |
-
"value":5540545
|
1519 |
-
},
|
1520 |
-
{
|
1521 |
-
"hc-a2":"CT",
|
1522 |
-
"name":"Connecticut",
|
1523 |
-
"region":"Northeast",
|
1524 |
-
"x":3,
|
1525 |
-
"y":11,
|
1526 |
-
"value":3596677
|
1527 |
-
},
|
1528 |
-
{
|
1529 |
-
"hc-a2":"DE",
|
1530 |
-
"name":"Delaware",
|
1531 |
-
"region":"South",
|
1532 |
-
"x":4,
|
1533 |
-
"y":9,
|
1534 |
-
"value":935614
|
1535 |
-
},
|
1536 |
-
{
|
1537 |
-
"hc-a2":"DC",
|
1538 |
-
"name":"District of Columbia",
|
1539 |
-
"region":"South",
|
1540 |
-
"x":4,
|
1541 |
-
"y":10,
|
1542 |
-
"value":7288000
|
1543 |
-
},
|
1544 |
-
{
|
1545 |
-
"hc-a2":"FL",
|
1546 |
-
"name":"Florida",
|
1547 |
-
"region":"South",
|
1548 |
-
"x":8,
|
1549 |
-
"y":8,
|
1550 |
-
"value":20612439
|
1551 |
-
},
|
1552 |
-
{
|
1553 |
-
"hc-a2":"GA",
|
1554 |
-
"name":"Georgia",
|
1555 |
-
"region":"South",
|
1556 |
-
"x":7,
|
1557 |
-
"y":8,
|
1558 |
-
"value":10310371
|
1559 |
-
},
|
1560 |
-
{
|
1561 |
-
"hc-a2":"HI",
|
1562 |
-
"name":"Hawaii",
|
1563 |
-
"region":"West",
|
1564 |
-
"x":8,
|
1565 |
-
"y":0,
|
1566 |
-
"value":1419561
|
1567 |
-
},
|
1568 |
-
{
|
1569 |
-
"hc-a2":"ID",
|
1570 |
-
"name":"Idaho",
|
1571 |
-
"region":"West",
|
1572 |
-
"x":3,
|
1573 |
-
"y":2,
|
1574 |
-
"value":1634464
|
1575 |
-
},
|
1576 |
-
{
|
1577 |
-
"hc-a2":"IL",
|
1578 |
-
"name":"Illinois",
|
1579 |
-
"region":"Midwest",
|
1580 |
-
"x":3,
|
1581 |
-
"y":6,
|
1582 |
-
"value":12801539
|
1583 |
-
},
|
1584 |
-
{
|
1585 |
-
"hc-a2":"IN",
|
1586 |
-
"name":"Indiana",
|
1587 |
-
"region":"Midwest",
|
1588 |
-
"x":3,
|
1589 |
-
"y":7,
|
1590 |
-
"value":6596855
|
1591 |
-
},
|
1592 |
-
{
|
1593 |
-
"hc-a2":"IA",
|
1594 |
-
"name":"Iowa",
|
1595 |
-
"region":"Midwest",
|
1596 |
-
"x":3,
|
1597 |
-
"y":5,
|
1598 |
-
"value":3107126
|
1599 |
-
},
|
1600 |
-
{
|
1601 |
-
"hc-a2":"KS",
|
1602 |
-
"name":"Kansas",
|
1603 |
-
"region":"Midwest",
|
1604 |
-
"x":5,
|
1605 |
-
"y":5,
|
1606 |
-
"value":2904021
|
1607 |
-
},
|
1608 |
-
{
|
1609 |
-
"hc-a2":"KY",
|
1610 |
-
"name":"Kentucky",
|
1611 |
-
"region":"South",
|
1612 |
-
"x":4,
|
1613 |
-
"y":6,
|
1614 |
-
"value":4413457
|
1615 |
-
},
|
1616 |
-
{
|
1617 |
-
"hc-a2":"LA",
|
1618 |
-
"name":"Louisiana",
|
1619 |
-
"region":"South",
|
1620 |
-
"x":6,
|
1621 |
-
"y":5,
|
1622 |
-
"value":4649676
|
1623 |
-
},
|
1624 |
-
{
|
1625 |
-
"hc-a2":"ME",
|
1626 |
-
"name":"Maine",
|
1627 |
-
"region":"Northeast",
|
1628 |
-
"x":0,
|
1629 |
-
"y":11,
|
1630 |
-
"value":1330089
|
1631 |
-
},
|
1632 |
-
{
|
1633 |
-
"hc-a2":"MD",
|
1634 |
-
"name":"Maryland",
|
1635 |
-
"region":"South",
|
1636 |
-
"x":4,
|
1637 |
-
"y":8,
|
1638 |
-
"value":6016447
|
1639 |
-
},
|
1640 |
-
{
|
1641 |
-
"hc-a2":"MA",
|
1642 |
-
"name":"Massachusetts",
|
1643 |
-
"region":"Northeast",
|
1644 |
-
"x":2,
|
1645 |
-
"y":10,
|
1646 |
-
"value":6811779
|
1647 |
-
},
|
1648 |
-
{
|
1649 |
-
"hc-a2":"MI",
|
1650 |
-
"name":"Michigan",
|
1651 |
-
"region":"Midwest",
|
1652 |
-
"x":2,
|
1653 |
-
"y":7,
|
1654 |
-
"value":9928301
|
1655 |
-
},
|
1656 |
-
{
|
1657 |
-
"hc-a2":"MN",
|
1658 |
-
"name":"Minnesota",
|
1659 |
-
"region":"Midwest",
|
1660 |
-
"x":2,
|
1661 |
-
"y":4,
|
1662 |
-
"value":5519952
|
1663 |
-
},
|
1664 |
-
{
|
1665 |
-
"hc-a2":"MS",
|
1666 |
-
"name":"Mississippi",
|
1667 |
-
"region":"South",
|
1668 |
-
"x":6,
|
1669 |
-
"y":6,
|
1670 |
-
"value":2984926
|
1671 |
-
},
|
1672 |
-
{
|
1673 |
-
"hc-a2":"MO",
|
1674 |
-
"name":"Missouri",
|
1675 |
-
"region":"Midwest",
|
1676 |
-
"x":4,
|
1677 |
-
"y":5,
|
1678 |
-
"value":6093000
|
1679 |
-
},
|
1680 |
-
{
|
1681 |
-
"hc-a2":"MT",
|
1682 |
-
"name":"Montana",
|
1683 |
-
"region":"West",
|
1684 |
-
"x":2,
|
1685 |
-
"y":2,
|
1686 |
-
"value":1023579
|
1687 |
-
},
|
1688 |
-
{
|
1689 |
-
"hc-a2":"NE",
|
1690 |
-
"name":"Nebraska",
|
1691 |
-
"region":"Midwest",
|
1692 |
-
"x":4,
|
1693 |
-
"y":4,
|
1694 |
-
"value":1881503
|
1695 |
-
},
|
1696 |
-
{
|
1697 |
-
"hc-a2":"NV",
|
1698 |
-
"name":"Nevada",
|
1699 |
-
"region":"West",
|
1700 |
-
"x":4,
|
1701 |
-
"y":2,
|
1702 |
-
"value":2839099
|
1703 |
-
},
|
1704 |
-
{
|
1705 |
-
"hc-a2":"NH",
|
1706 |
-
"name":"New Hampshire",
|
1707 |
-
"region":"Northeast",
|
1708 |
-
"x":1,
|
1709 |
-
"y":11,
|
1710 |
-
"value":1326813
|
1711 |
-
},
|
1712 |
-
{
|
1713 |
-
"hc-a2":"NJ",
|
1714 |
-
"name":"New Jersey",
|
1715 |
-
"region":"Northeast",
|
1716 |
-
"x":3,
|
1717 |
-
"y":10,
|
1718 |
-
"value":8944469
|
1719 |
-
},
|
1720 |
-
{
|
1721 |
-
"hc-a2":"NM",
|
1722 |
-
"name":"New Mexico",
|
1723 |
-
"region":"West",
|
1724 |
-
"x":6,
|
1725 |
-
"y":3,
|
1726 |
-
"value":2085572
|
1727 |
-
},
|
1728 |
-
{
|
1729 |
-
"hc-a2":"NY",
|
1730 |
-
"name":"New York",
|
1731 |
-
"region":"Northeast",
|
1732 |
-
"x":2,
|
1733 |
-
"y":9,
|
1734 |
-
"value":19745289
|
1735 |
-
},
|
1736 |
-
{
|
1737 |
-
"hc-a2":"NC",
|
1738 |
-
"name":"North Carolina",
|
1739 |
-
"region":"South",
|
1740 |
-
"x":5,
|
1741 |
-
"y":9,
|
1742 |
-
"value":10146788
|
1743 |
-
},
|
1744 |
-
{
|
1745 |
-
"hc-a2":"ND",
|
1746 |
-
"name":"North Dakota",
|
1747 |
-
"region":"Midwest",
|
1748 |
-
"x":2,
|
1749 |
-
"y":3,
|
1750 |
-
"value":739482
|
1751 |
-
},
|
1752 |
-
{
|
1753 |
-
"hc-a2":"OH",
|
1754 |
-
"name":"Ohio",
|
1755 |
-
"region":"Midwest",
|
1756 |
-
"x":3,
|
1757 |
-
"y":8,
|
1758 |
-
"value":11614373
|
1759 |
-
},
|
1760 |
-
{
|
1761 |
-
"hc-a2":"OK",
|
1762 |
-
"name":"Oklahoma",
|
1763 |
-
"region":"South",
|
1764 |
-
"x":6,
|
1765 |
-
"y":4,
|
1766 |
-
"value":3878051
|
1767 |
-
},
|
1768 |
-
{
|
1769 |
-
"hc-a2":"OR",
|
1770 |
-
"name":"Oregon",
|
1771 |
-
"region":"West",
|
1772 |
-
"x":4,
|
1773 |
-
"y":1,
|
1774 |
-
"value":3970239
|
1775 |
-
},
|
1776 |
-
{
|
1777 |
-
"hc-a2":"PA",
|
1778 |
-
"name":"Pennsylvania",
|
1779 |
-
"region":"Northeast",
|
1780 |
-
"x":3,
|
1781 |
-
"y":9,
|
1782 |
-
"value":12784227
|
1783 |
-
},
|
1784 |
-
{
|
1785 |
-
"hc-a2":"RI",
|
1786 |
-
"name":"Rhode Island",
|
1787 |
-
"region":"Northeast",
|
1788 |
-
"x":2,
|
1789 |
-
"y":11,
|
1790 |
-
"value":1055173
|
1791 |
-
},
|
1792 |
-
{
|
1793 |
-
"hc-a2":"SC",
|
1794 |
-
"name":"South Carolina",
|
1795 |
-
"region":"South",
|
1796 |
-
"x":6,
|
1797 |
-
"y":8,
|
1798 |
-
"value":4832482
|
1799 |
-
},
|
1800 |
-
{
|
1801 |
-
"hc-a2":"SD",
|
1802 |
-
"name":"South Dakota",
|
1803 |
-
"region":"Midwest",
|
1804 |
-
"x":3,
|
1805 |
-
"y":4,
|
1806 |
-
"value":853175
|
1807 |
-
},
|
1808 |
-
{
|
1809 |
-
"hc-a2":"TN",
|
1810 |
-
"name":"Tennessee",
|
1811 |
-
"region":"South",
|
1812 |
-
"x":5,
|
1813 |
-
"y":7,
|
1814 |
-
"value":6651194
|
1815 |
-
},
|
1816 |
-
{
|
1817 |
-
"hc-a2":"TX",
|
1818 |
-
"name":"Texas",
|
1819 |
-
"region":"South",
|
1820 |
-
"x":7,
|
1821 |
-
"y":4,
|
1822 |
-
"value":27862596
|
1823 |
-
},
|
1824 |
-
{
|
1825 |
-
"hc-a2":"UT",
|
1826 |
-
"name":"Utah",
|
1827 |
-
"region":"West",
|
1828 |
-
"x":5,
|
1829 |
-
"y":4,
|
1830 |
-
"value":2942902
|
1831 |
-
},
|
1832 |
-
{
|
1833 |
-
"hc-a2":"VT",
|
1834 |
-
"name":"Vermont",
|
1835 |
-
"region":"Northeast",
|
1836 |
-
"x":1,
|
1837 |
-
"y":10,
|
1838 |
-
"value":626011
|
1839 |
-
},
|
1840 |
-
{
|
1841 |
-
"hc-a2":"VA",
|
1842 |
-
"name":"Virginia",
|
1843 |
-
"region":"South",
|
1844 |
-
"x":5,
|
1845 |
-
"y":8,
|
1846 |
-
"value":8411808
|
1847 |
-
},
|
1848 |
-
{
|
1849 |
-
"hc-a2":"WA",
|
1850 |
-
"name":"Washington",
|
1851 |
-
"region":"West",
|
1852 |
-
"x":2,
|
1853 |
-
"y":1,
|
1854 |
-
"value":7288000
|
1855 |
-
},
|
1856 |
-
{
|
1857 |
-
"hc-a2":"WV",
|
1858 |
-
"name":"West Virginia",
|
1859 |
-
"region":"South",
|
1860 |
-
"x":4,
|
1861 |
-
"y":7,
|
1862 |
-
"value":1850326
|
1863 |
-
},
|
1864 |
-
{
|
1865 |
-
"hc-a2":"WI",
|
1866 |
-
"name":"Wisconsin",
|
1867 |
-
"region":"Midwest",
|
1868 |
-
"x":2,
|
1869 |
-
"y":5,
|
1870 |
-
"value":5778708
|
1871 |
-
},
|
1872 |
-
{
|
1873 |
-
"hc-a2":"WY",
|
1874 |
-
"name":"Wyoming",
|
1875 |
-
"region":"West",
|
1876 |
-
"x":3,
|
1877 |
-
"y":3,
|
1878 |
-
"value":584153
|
1879 |
-
}
|
1880 |
-
]
|
1881 |
-
}
|
1882 |
-
]
|
1883 |
-
}
|
1884 |
-
SAMPLE7={
|
1885 |
-
"chart":{
|
1886 |
-
"type":"pie"
|
1887 |
-
},
|
1888 |
-
"title":{
|
1889 |
-
"text":"Browser market shares. January, 2022"
|
1890 |
-
},
|
1891 |
-
"subtitle":{
|
1892 |
-
"text":"Click the slices to view versions. Source: <a href=\"http://statcounter.com\" target=\"_blank\">statcounter.com</a>"
|
1893 |
-
},
|
1894 |
-
"accessibility":{
|
1895 |
-
"announceNewData":{
|
1896 |
-
"enabled":True
|
1897 |
-
},
|
1898 |
-
"point":{
|
1899 |
-
"valueSuffix":"%"
|
1900 |
-
}
|
1901 |
-
},
|
1902 |
-
"plotOptions":{
|
1903 |
-
"series":{
|
1904 |
-
"dataLabels":{
|
1905 |
-
"enabled":True,
|
1906 |
-
"format":"{point.name}: {point.y:.1f}%"
|
1907 |
-
}
|
1908 |
-
}
|
1909 |
-
},
|
1910 |
-
"tooltip":{
|
1911 |
-
"headerFormat":"<span style=\"font-size:11px\">{series.name}</span><br>",
|
1912 |
-
"pointFormat":"<span style=\"color:{point.color}\">{point.name}</span>: <b>{point.y:.2f}%</b> of total<br/>"
|
1913 |
-
},
|
1914 |
-
"series":[
|
1915 |
-
{
|
1916 |
-
"name":"Browsers",
|
1917 |
-
"colorByPoint":True,
|
1918 |
-
"data":[
|
1919 |
-
{
|
1920 |
-
"name":"Chrome",
|
1921 |
-
"y":61.04,
|
1922 |
-
"drilldown":"Chrome"
|
1923 |
-
},
|
1924 |
-
{
|
1925 |
-
"name":"Safari",
|
1926 |
-
"y":9.47,
|
1927 |
-
"drilldown":"Safari"
|
1928 |
-
},
|
1929 |
-
{
|
1930 |
-
"name":"Edge",
|
1931 |
-
"y":9.32,
|
1932 |
-
"drilldown":"Edge"
|
1933 |
-
},
|
1934 |
-
{
|
1935 |
-
"name":"Firefox",
|
1936 |
-
"y":8.15,
|
1937 |
-
"drilldown":"Firefox"
|
1938 |
-
},
|
1939 |
-
{
|
1940 |
-
"name":"Other",
|
1941 |
-
"y":11.02,
|
1942 |
-
"drilldown":"null"
|
1943 |
-
}
|
1944 |
-
]
|
1945 |
-
}
|
1946 |
-
],
|
1947 |
-
"drilldown":{
|
1948 |
-
"series":[
|
1949 |
-
{
|
1950 |
-
"name":"Chrome",
|
1951 |
-
"id":"Chrome",
|
1952 |
-
"data":[
|
1953 |
-
[
|
1954 |
-
"v97.0",
|
1955 |
-
36.89
|
1956 |
-
],
|
1957 |
-
[
|
1958 |
-
"v96.0",
|
1959 |
-
18.16
|
1960 |
-
],
|
1961 |
-
[
|
1962 |
-
"v95.0",
|
1963 |
-
0.54
|
1964 |
-
],
|
1965 |
-
[
|
1966 |
-
"v94.0",
|
1967 |
-
0.7
|
1968 |
-
],
|
1969 |
-
[
|
1970 |
-
"v93.0",
|
1971 |
-
0.8
|
1972 |
-
],
|
1973 |
-
[
|
1974 |
-
"v92.0",
|
1975 |
-
0.41
|
1976 |
-
],
|
1977 |
-
[
|
1978 |
-
"v91.0",
|
1979 |
-
0.31
|
1980 |
-
],
|
1981 |
-
[
|
1982 |
-
"v90.0",
|
1983 |
-
0.13
|
1984 |
-
],
|
1985 |
-
[
|
1986 |
-
"v89.0",
|
1987 |
-
0.14
|
1988 |
-
],
|
1989 |
-
[
|
1990 |
-
"v88.0",
|
1991 |
-
0.1
|
1992 |
-
],
|
1993 |
-
[
|
1994 |
-
"v87.0",
|
1995 |
-
0.35
|
1996 |
-
],
|
1997 |
-
[
|
1998 |
-
"v86.0",
|
1999 |
-
0.17
|
2000 |
-
],
|
2001 |
-
[
|
2002 |
-
"v85.0",
|
2003 |
-
0.18
|
2004 |
-
],
|
2005 |
-
[
|
2006 |
-
"v84.0",
|
2007 |
-
0.17
|
2008 |
-
],
|
2009 |
-
[
|
2010 |
-
"v83.0",
|
2011 |
-
0.21
|
2012 |
-
],
|
2013 |
-
[
|
2014 |
-
"v81.0",
|
2015 |
-
0.1
|
2016 |
-
],
|
2017 |
-
[
|
2018 |
-
"v80.0",
|
2019 |
-
0.16
|
2020 |
-
],
|
2021 |
-
[
|
2022 |
-
"v79.0",
|
2023 |
-
0.43
|
2024 |
-
],
|
2025 |
-
[
|
2026 |
-
"v78.0",
|
2027 |
-
0.11
|
2028 |
-
],
|
2029 |
-
[
|
2030 |
-
"v76.0",
|
2031 |
-
0.16
|
2032 |
-
],
|
2033 |
-
[
|
2034 |
-
"v75.0",
|
2035 |
-
0.15
|
2036 |
-
],
|
2037 |
-
[
|
2038 |
-
"v72.0",
|
2039 |
-
0.14
|
2040 |
-
],
|
2041 |
-
[
|
2042 |
-
"v70.0",
|
2043 |
-
0.11
|
2044 |
-
],
|
2045 |
-
[
|
2046 |
-
"v69.0",
|
2047 |
-
0.13
|
2048 |
-
],
|
2049 |
-
[
|
2050 |
-
"v56.0",
|
2051 |
-
0.12
|
2052 |
-
],
|
2053 |
-
[
|
2054 |
-
"v49.0",
|
2055 |
-
0.17
|
2056 |
-
]
|
2057 |
-
]
|
2058 |
-
},
|
2059 |
-
{
|
2060 |
-
"name":"Safari",
|
2061 |
-
"id":"Safari",
|
2062 |
-
"data":[
|
2063 |
-
[
|
2064 |
-
"v15.3",
|
2065 |
-
0.1
|
2066 |
-
],
|
2067 |
-
[
|
2068 |
-
"v15.2",
|
2069 |
-
2.01
|
2070 |
-
],
|
2071 |
-
[
|
2072 |
-
"v15.1",
|
2073 |
-
2.29
|
2074 |
-
],
|
2075 |
-
[
|
2076 |
-
"v15.0",
|
2077 |
-
0.49
|
2078 |
-
],
|
2079 |
-
[
|
2080 |
-
"v14.1",
|
2081 |
-
2.48
|
2082 |
-
],
|
2083 |
-
[
|
2084 |
-
"v14.0",
|
2085 |
-
0.64
|
2086 |
-
],
|
2087 |
-
[
|
2088 |
-
"v13.1",
|
2089 |
-
1.17
|
2090 |
-
],
|
2091 |
-
[
|
2092 |
-
"v13.0",
|
2093 |
-
0.13
|
2094 |
-
],
|
2095 |
-
[
|
2096 |
-
"v12.1",
|
2097 |
-
0.16
|
2098 |
-
]
|
2099 |
-
]
|
2100 |
-
},
|
2101 |
-
{
|
2102 |
-
"name":"Edge",
|
2103 |
-
"id":"Edge",
|
2104 |
-
"data":[
|
2105 |
-
[
|
2106 |
-
"v97",
|
2107 |
-
6.62
|
2108 |
-
],
|
2109 |
-
[
|
2110 |
-
"v96",
|
2111 |
-
2.55
|
2112 |
-
],
|
2113 |
-
[
|
2114 |
-
"v95",
|
2115 |
-
0.15
|
2116 |
-
]
|
2117 |
-
]
|
2118 |
-
},
|
2119 |
-
{
|
2120 |
-
"name":"Firefox",
|
2121 |
-
"id":"Firefox",
|
2122 |
-
"data":[
|
2123 |
-
[
|
2124 |
-
"v96.0",
|
2125 |
-
4.17
|
2126 |
-
],
|
2127 |
-
[
|
2128 |
-
"v95.0",
|
2129 |
-
3.33
|
2130 |
-
],
|
2131 |
-
[
|
2132 |
-
"v94.0",
|
2133 |
-
0.11
|
2134 |
-
],
|
2135 |
-
[
|
2136 |
-
"v91.0",
|
2137 |
-
0.23
|
2138 |
-
],
|
2139 |
-
[
|
2140 |
-
"v78.0",
|
2141 |
-
0.16
|
2142 |
-
],
|
2143 |
-
[
|
2144 |
-
"v52.0",
|
2145 |
-
0.15
|
2146 |
-
]
|
2147 |
-
]
|
2148 |
-
}
|
2149 |
-
]
|
2150 |
-
}
|
2151 |
-
}
|
2152 |
-
SAMPLE8={
|
2153 |
-
"title":{
|
2154 |
-
"text":"Sales of petroleum products March, Norway",
|
2155 |
-
"align":"left"
|
2156 |
-
},
|
2157 |
-
"xAxis":{
|
2158 |
-
"categories":[
|
2159 |
-
"Jet fuel",
|
2160 |
-
"Duty-free diesel",
|
2161 |
-
"Petrol",
|
2162 |
-
"Diesel",
|
2163 |
-
"Gas oil"
|
2164 |
-
]
|
2165 |
-
},
|
2166 |
-
"yAxis":{
|
2167 |
-
"title":{
|
2168 |
-
"text":"Million liter"
|
2169 |
-
}
|
2170 |
-
},
|
2171 |
-
"labels":{
|
2172 |
-
"items":[
|
2173 |
-
{
|
2174 |
-
"html":"Total liter",
|
2175 |
-
"style":{
|
2176 |
-
"left":"50px",
|
2177 |
-
"top":"18px",
|
2178 |
-
"color":"black"
|
2179 |
-
}
|
2180 |
-
}
|
2181 |
-
]
|
2182 |
-
},
|
2183 |
-
"series":[
|
2184 |
-
{
|
2185 |
-
"type":"column",
|
2186 |
-
"name":"2020",
|
2187 |
-
"data":[
|
2188 |
-
59,
|
2189 |
-
83,
|
2190 |
-
65,
|
2191 |
-
228,
|
2192 |
-
184
|
2193 |
-
]
|
2194 |
-
},
|
2195 |
-
{
|
2196 |
-
"type":"column",
|
2197 |
-
"name":"2021",
|
2198 |
-
"data":[
|
2199 |
-
24,
|
2200 |
-
79,
|
2201 |
-
72,
|
2202 |
-
240,
|
2203 |
-
167
|
2204 |
-
]
|
2205 |
-
},
|
2206 |
-
{
|
2207 |
-
"type":"column",
|
2208 |
-
"name":"2022",
|
2209 |
-
"data":[
|
2210 |
-
58,
|
2211 |
-
88,
|
2212 |
-
75,
|
2213 |
-
250,
|
2214 |
-
176
|
2215 |
-
]
|
2216 |
-
},
|
2217 |
-
{
|
2218 |
-
"type":"spline",
|
2219 |
-
"name":"Average",
|
2220 |
-
"data":[
|
2221 |
-
47,
|
2222 |
-
83.33,
|
2223 |
-
70.66,
|
2224 |
-
239.33,
|
2225 |
-
175.66
|
2226 |
-
],
|
2227 |
-
"marker":{
|
2228 |
-
"lineWidth":2,
|
2229 |
-
"fillColor":"black",
|
2230 |
-
}
|
2231 |
-
},
|
2232 |
-
{
|
2233 |
-
"type":"pie",
|
2234 |
-
"name":"Liter",
|
2235 |
-
"data":[
|
2236 |
-
{
|
2237 |
-
"name":"2020",
|
2238 |
-
"y":619,
|
2239 |
-
"color": "#7cb4ec"
|
2240 |
-
|
2241 |
-
},
|
2242 |
-
{
|
2243 |
-
"name":"2021",
|
2244 |
-
"y":586,
|
2245 |
-
"color": "#434348"
|
2246 |
-
},
|
2247 |
-
{
|
2248 |
-
"name":"2022",
|
2249 |
-
"y":647,
|
2250 |
-
"color":"#90ed7d"
|
2251 |
-
}
|
2252 |
-
],
|
2253 |
-
"center":[
|
2254 |
-
80,
|
2255 |
-
70
|
2256 |
-
],
|
2257 |
-
"size":100,
|
2258 |
-
"showInLegend":False,
|
2259 |
-
"dataLabels":{
|
2260 |
-
"enabled":False
|
2261 |
-
}
|
2262 |
-
}
|
2263 |
-
]
|
2264 |
-
}
|
2265 |
-
SAMPLE9={
|
2266 |
-
"chart":{
|
2267 |
-
"type":"solidgauge",
|
2268 |
-
"height":"90%"
|
2269 |
-
},
|
2270 |
-
"title":{
|
2271 |
-
"text":"Activity",
|
2272 |
-
"style":{
|
2273 |
-
"fontSize":"24px"
|
2274 |
-
}
|
2275 |
-
},
|
2276 |
-
"tooltip":{
|
2277 |
-
"borderWidth":0,
|
2278 |
-
"backgroundColor":"none",
|
2279 |
-
"shadow":False,
|
2280 |
-
"style":{
|
2281 |
-
"fontSize":"16px"
|
2282 |
-
},
|
2283 |
-
"valueSuffix":"%",
|
2284 |
-
"pointFormat":"{series.name}<br><span style=\"font-size:2em; color: {point.color}; font-weight: bold\">{point.y}</span>",
|
2285 |
-
"positioner":{
|
2286 |
-
"x":"50px",
|
2287 |
-
"y":100
|
2288 |
-
}
|
2289 |
-
},
|
2290 |
-
"pane":{
|
2291 |
-
"startAngle":0,
|
2292 |
-
"endAngle":360,
|
2293 |
-
"background":[
|
2294 |
-
{
|
2295 |
-
"radius":"112%",
|
2296 |
-
"innerRadius":"88%",
|
2297 |
-
"borderWidth":0
|
2298 |
-
},
|
2299 |
-
{
|
2300 |
-
"radius":"87%",
|
2301 |
-
"innerRadius":"63%",
|
2302 |
-
"borderWidth":0
|
2303 |
-
},
|
2304 |
-
{
|
2305 |
-
"radius":"62%",
|
2306 |
-
"innerRadius":"38%",
|
2307 |
-
"borderWidth":0
|
2308 |
-
}
|
2309 |
-
]
|
2310 |
-
},
|
2311 |
-
"yAxis":{
|
2312 |
-
"min":0,
|
2313 |
-
"max":100,
|
2314 |
-
"lineWidth":0,
|
2315 |
-
"tickPositions":[
|
2316 |
-
|
2317 |
-
]
|
2318 |
-
},
|
2319 |
-
"plotOptions":{
|
2320 |
-
"solidgauge":{
|
2321 |
-
"dataLabels":{
|
2322 |
-
"enabled":False
|
2323 |
-
},
|
2324 |
-
"linecap":"round",
|
2325 |
-
"stickyTracking":False,
|
2326 |
-
"rounded":True
|
2327 |
-
}
|
2328 |
-
},
|
2329 |
-
"series":[
|
2330 |
-
{
|
2331 |
-
"name":"Move",
|
2332 |
-
"data":[
|
2333 |
-
{
|
2334 |
-
"color":"lightgreen",
|
2335 |
-
"radius":"112%",
|
2336 |
-
"innerRadius":"88%",
|
2337 |
-
"y":80
|
2338 |
-
}
|
2339 |
-
]
|
2340 |
-
},
|
2341 |
-
{
|
2342 |
-
"name":"Exercise",
|
2343 |
-
"data":[
|
2344 |
-
{
|
2345 |
-
"color":"red",
|
2346 |
-
"radius":"87%",
|
2347 |
-
"innerRadius":"63%",
|
2348 |
-
"y":65
|
2349 |
-
}
|
2350 |
-
]
|
2351 |
-
},
|
2352 |
-
{
|
2353 |
-
"name":"Stand",
|
2354 |
-
"data":[
|
2355 |
-
{
|
2356 |
-
"color":"blue",
|
2357 |
-
"radius":"62%",
|
2358 |
-
"innerRadius":"38%",
|
2359 |
-
"y":50
|
2360 |
-
}
|
2361 |
-
]
|
2362 |
-
}
|
2363 |
-
]
|
2364 |
-
}
|
2365 |
-
SAMPLE10={
|
2366 |
-
|
2367 |
-
"chart": {
|
2368 |
-
"type": 'gauge',
|
2369 |
-
"plotBackgroundColor": "white",
|
2370 |
-
"plotBackgroundImage": "white",
|
2371 |
-
"plotBorderWidth": 0,
|
2372 |
-
"plotShadow": False,
|
2373 |
-
"height": '80%'
|
2374 |
-
},
|
2375 |
-
|
2376 |
-
"title": {
|
2377 |
-
"text": 'Speedometer'
|
2378 |
-
},
|
2379 |
-
|
2380 |
-
"pane": {
|
2381 |
-
"startAngle": -90,
|
2382 |
-
"endAngle": 89.9,
|
2383 |
-
"background": "null",
|
2384 |
-
"center": ['50%', '75%'],
|
2385 |
-
"size": '110%'
|
2386 |
-
},
|
2387 |
-
|
2388 |
-
"yAxis": {
|
2389 |
-
"min": 0,
|
2390 |
-
"max": 200,
|
2391 |
-
"tickPixelInterval": 72,
|
2392 |
-
"tickPosition": 'inside',
|
2393 |
-
"tickColor": '#FFFFFF',
|
2394 |
-
"tickLength": 20,
|
2395 |
-
"tickWidth": 2,
|
2396 |
-
"minorTickInterval": "null",
|
2397 |
-
"labels": {
|
2398 |
-
"distance": 20,
|
2399 |
-
"style": {
|
2400 |
-
"fontSize": '14px'
|
2401 |
-
}
|
2402 |
-
},
|
2403 |
-
"plotBands": [{
|
2404 |
-
"from": 0,
|
2405 |
-
"to": 120,
|
2406 |
-
"color": '#55BF3B',
|
2407 |
-
"thickness": 20
|
2408 |
-
}, {
|
2409 |
-
"from": 120,
|
2410 |
-
"to": 160,
|
2411 |
-
"color": '#DDDF0D',
|
2412 |
-
"thickness": 20
|
2413 |
-
}, {
|
2414 |
-
"from": 160,
|
2415 |
-
"to": 200,
|
2416 |
-
"color": '#DF5353',
|
2417 |
-
"thickness": 20
|
2418 |
-
}]
|
2419 |
-
},
|
2420 |
-
|
2421 |
-
"series": [{
|
2422 |
-
"name": 'Speed',
|
2423 |
-
"data": [80],
|
2424 |
-
"tooltip": {
|
2425 |
-
"valueSuffix": ' km/h'
|
2426 |
-
},
|
2427 |
-
"dataLabels": {
|
2428 |
-
"format": '{y} km/h',
|
2429 |
-
"borderWidth": 0,
|
2430 |
-
"color": '#333333',
|
2431 |
-
"style": {
|
2432 |
-
"fontSize": '16px'
|
2433 |
-
}
|
2434 |
-
},
|
2435 |
-
"dial": {
|
2436 |
-
"radius": '80%',
|
2437 |
-
"backgroundColor": 'gray',
|
2438 |
-
"baseWidth": 12,
|
2439 |
-
"baseLength": '0%',
|
2440 |
-
"rearLength": '0%'
|
2441 |
-
},
|
2442 |
-
"pivot": {
|
2443 |
-
"backgroundColor": 'gray',
|
2444 |
-
"radius": 6
|
2445 |
-
}
|
2446 |
-
}]
|
2447 |
-
|
2448 |
-
}
|
2449 |
-
SAMPLE11={
|
2450 |
-
|
2451 |
-
"title": {
|
2452 |
-
"text": 'Highcharts Dependency Wheel'
|
2453 |
-
},
|
2454 |
-
|
2455 |
-
"accessibility": {
|
2456 |
-
"point": {
|
2457 |
-
"valueDescriptionFormat": '{index}. From {point.from} to {point.to}: {point.weight}.'
|
2458 |
-
}
|
2459 |
-
},
|
2460 |
-
|
2461 |
-
"series": [{
|
2462 |
-
"keys": ['from', 'to', 'weight'],
|
2463 |
-
"data": [
|
2464 |
-
['Brazil', 'Portugal', 5],
|
2465 |
-
['Brazil', 'France', 1],
|
2466 |
-
['Brazil', 'Spain', 1],
|
2467 |
-
['Brazil', 'England', 1],
|
2468 |
-
['Canada', 'Portugal', 1],
|
2469 |
-
['Canada', 'France', 5],
|
2470 |
-
['Canada', 'England', 1],
|
2471 |
-
['Mexico', 'Portugal', 1],
|
2472 |
-
['Mexico', 'France', 1],
|
2473 |
-
['Mexico', 'Spain', 5],
|
2474 |
-
['Mexico', 'England', 1],
|
2475 |
-
['USA', 'Portugal', 1],
|
2476 |
-
['USA', 'France', 1],
|
2477 |
-
['USA', 'Spain', 1],
|
2478 |
-
['USA', 'England', 5],
|
2479 |
-
['Portugal', 'Angola', 2],
|
2480 |
-
['Portugal', 'Senegal', 1],
|
2481 |
-
['Portugal', 'Morocco', 1],
|
2482 |
-
['Portugal', 'South Africa', 3],
|
2483 |
-
['France', 'Angola', 1],
|
2484 |
-
['France', 'Senegal', 3],
|
2485 |
-
['France', 'Mali', 3],
|
2486 |
-
['France', 'Morocco', 3],
|
2487 |
-
['France', 'South Africa', 1],
|
2488 |
-
['Spain', 'Senegal', 1],
|
2489 |
-
['Spain', 'Morocco', 3],
|
2490 |
-
['Spain', 'South Africa', 1],
|
2491 |
-
['England', 'Angola', 1],
|
2492 |
-
['England', 'Senegal', 1],
|
2493 |
-
['England', 'Morocco', 2],
|
2494 |
-
['England', 'South Africa', 7],
|
2495 |
-
['South Africa', 'China', 5],
|
2496 |
-
['South Africa', 'India', 1],
|
2497 |
-
['South Africa', 'Japan', 3],
|
2498 |
-
['Angola', 'China', 5],
|
2499 |
-
['Angola', 'India', 1],
|
2500 |
-
['Angola', 'Japan', 3],
|
2501 |
-
['Senegal', 'China', 5],
|
2502 |
-
['Senegal', 'India', 1],
|
2503 |
-
['Senegal', 'Japan', 3],
|
2504 |
-
['Mali', 'China', 5],
|
2505 |
-
['Mali', 'India', 1],
|
2506 |
-
['Mali', 'Japan', 3],
|
2507 |
-
['Morocco', 'China', 5],
|
2508 |
-
['Morocco', 'India', 1],
|
2509 |
-
['Morocco', 'Japan', 3],
|
2510 |
-
['Japan', 'Brazil', 1]
|
2511 |
-
],
|
2512 |
-
"type": 'dependencywheel',
|
2513 |
-
"name": 'Dependency wheel series',
|
2514 |
-
"dataLabels": {
|
2515 |
-
"color": '#333',
|
2516 |
-
"style": {
|
2517 |
-
"textOutline": 'none'
|
2518 |
-
},
|
2519 |
-
"textPath": {
|
2520 |
-
"enabled": True,
|
2521 |
-
"attributes": {
|
2522 |
-
"dy": 5
|
2523 |
-
}
|
2524 |
-
},
|
2525 |
-
"distance": 10
|
2526 |
-
},
|
2527 |
-
"size": '95%'
|
2528 |
-
}]
|
2529 |
-
|
2530 |
-
}
|
2531 |
-
frontend_dir = (Path(__file__).parent / "frontend").absolute()
|
2532 |
-
_component_func = components.declare_component(
|
2533 |
-
"streamlit_highcharts", path=str(frontend_dir)
|
2534 |
-
)
|
2535 |
-
|
2536 |
-
def streamlit_highcharts(
|
2537 |
-
options=SAMPLE,
|
2538 |
-
height=410,
|
2539 |
-
key: Optional[str] = None,
|
2540 |
-
):
|
2541 |
-
"""
|
2542 |
-
Add a descriptive docstring
|
2543 |
-
"""
|
2544 |
-
component_value = _component_func(
|
2545 |
-
options=options,key=key,height=height
|
2546 |
-
)
|
2547 |
-
|
2548 |
-
return component_value
|
2549 |
-
|
2550 |
-
|
2551 |
-
# def main():
|
2552 |
-
# st.write("## Example")
|
2553 |
-
# selSample=st.selectbox("Choose a sample",[SAMPLE,SAMPLE2,SAMPLE3,SAMPLE4,SAMPLE5,SAMPLE6,SAMPLE7,SAMPLE8,SAMPLE9,SAMPLE10],format_func=lambda x: str(x["title"]["text"])
|
2554 |
-
# )
|
2555 |
-
# value = streamlit_highcharts(selSample,640)
|
2556 |
-
# with st.expander("Show code...",expanded=False):
|
2557 |
-
# st.code(str(selSample).replace("},","},\r\n"),language="python")
|
2558 |
-
|
2559 |
-
|
2560 |
-
|
2561 |
-
# if __name__ == "__main__":
|
2562 |
-
# main()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
st_hc/frontend/index.html
DELETED
@@ -1,36 +0,0 @@
|
|
1 |
-
<!DOCTYPE html>
|
2 |
-
<html lang="en">
|
3 |
-
<head>
|
4 |
-
<meta charset="UTF-8" />
|
5 |
-
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
6 |
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
7 |
-
<title>streamlit-highcharts</title>
|
8 |
-
<script src="https://code.highcharts.com/stock/highstock.js"></script>
|
9 |
-
<script src="https://code.highcharts.com/highcharts-more.js"></script>
|
10 |
-
<script src="https://code.highcharts.com/modules/heatmap.js"></script>
|
11 |
-
<script src="https://code.highcharts.com/modules/tilemap.js"></script>
|
12 |
-
<script src="https://code.highcharts.com/modules/streamgraph.js"></script>
|
13 |
-
<script src="https://code.highcharts.com/modules/solid-gauge.js"></script>
|
14 |
-
<script src="https://code.highcharts.com/modules/series-label.js"></script>
|
15 |
-
<script src="https://code.highcharts.com/modules/data.js"></script>
|
16 |
-
<script src="https://code.highcharts.com/modules/drilldown.js"></script>
|
17 |
-
<script src="https://code.highcharts.com/modules/sankey.js"></script>
|
18 |
-
<script src="https://code.highcharts.com/modules/dependency-wheel.js"></script>
|
19 |
-
<script src="https://code.highcharts.com/modules/annotations.js"></script>
|
20 |
-
<script src="https://code.highcharts.com/modules/exporting.js"></script>
|
21 |
-
<script src="https://code.highcharts.com/modules/export-data.js"></script>
|
22 |
-
<script src="https://code.highcharts.com/modules/accessibility.js"></script>
|
23 |
-
<script src="https://github.highcharts.com/modules/parallel-coordinates.js"></script>
|
24 |
-
<script src="https://code.highcharts.com/modules/draggable-points.js"></script>
|
25 |
-
<script src="https://code.highcharts.com/modules/exporting.js"></script>
|
26 |
-
<script src="https://code.highcharts.com/modules/export-data.js"></script>
|
27 |
-
<script src="./streamlit-component-lib.js"></script>
|
28 |
-
<script src="./main.js"></script>
|
29 |
-
<link rel="stylesheet" href="./style.css" />
|
30 |
-
</head>
|
31 |
-
<body>
|
32 |
-
<div id="root">
|
33 |
-
<div id="container" ></div>
|
34 |
-
</div>
|
35 |
-
</body>
|
36 |
-
</html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
st_hc/frontend/main.js
DELETED
@@ -1,42 +0,0 @@
|
|
1 |
-
function sendValue(value) {
|
2 |
-
Streamlit.setComponentValue(value)
|
3 |
-
}
|
4 |
-
|
5 |
-
|
6 |
-
function onRender(event) {
|
7 |
-
if (true) {
|
8 |
-
const {options,height} = event.detail.args
|
9 |
-
Streamlit.setFrameHeight(height+20)
|
10 |
-
document.getElementById("container").style.height=height+"px"
|
11 |
-
let c = Highcharts.chart('container', options);
|
12 |
-
|
13 |
-
let points = c.series[0].data.map((p) =>
|
14 |
-
({ x: Math.round(p.x),
|
15 |
-
y: Math.round(p.y),
|
16 |
-
color:p.color,
|
17 |
-
name:p.name} ));
|
18 |
-
sendValue(points);
|
19 |
-
|
20 |
-
console.log(c.series[0].data);
|
21 |
-
|
22 |
-
c.series[0].data.forEach((point, i) => {
|
23 |
-
|
24 |
-
point.graphic.element.onclick = () => {
|
25 |
-
|
26 |
-
let points = c.series[0].data.map((p) =>
|
27 |
-
({ x: Math.round(p.x),
|
28 |
-
y: Math.round(p.y),
|
29 |
-
color:p.color,
|
30 |
-
name:p.name} ));
|
31 |
-
|
32 |
-
console.log(points);
|
33 |
-
sendValue(points);
|
34 |
-
|
35 |
-
}
|
36 |
-
})
|
37 |
-
window.rendered = true
|
38 |
-
}
|
39 |
-
}
|
40 |
-
|
41 |
-
Streamlit.events.addEventListener(Streamlit.RENDER_EVENT, onRender)
|
42 |
-
Streamlit.setComponentReady()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
st_hc/frontend/streamlit-component-lib.js
DELETED
@@ -1,34 +0,0 @@
|
|
1 |
-
|
2 |
-
// Borrowed minimalistic Streamlit API from Thiago
|
3 |
-
// https://discuss.streamlit.io/t/code-snippet-create-components-without-any-frontend-tooling-no-react-babel-webpack-etc/13064
|
4 |
-
function sendMessageToStreamlitClient(type, data) {
|
5 |
-
console.log(type, data)
|
6 |
-
const outData = Object.assign({
|
7 |
-
isStreamlitMessage: true,
|
8 |
-
type: type,
|
9 |
-
}, data);
|
10 |
-
window.parent.postMessage(outData, "*");
|
11 |
-
}
|
12 |
-
|
13 |
-
const Streamlit = {
|
14 |
-
setComponentReady: function() {
|
15 |
-
sendMessageToStreamlitClient("streamlit:componentReady", {apiVersion: 1});
|
16 |
-
},
|
17 |
-
setFrameHeight: function(height) {
|
18 |
-
sendMessageToStreamlitClient("streamlit:setFrameHeight", {height: height});
|
19 |
-
},
|
20 |
-
setComponentValue: function(value) {
|
21 |
-
sendMessageToStreamlitClient("streamlit:setComponentValue", {value: value});
|
22 |
-
},
|
23 |
-
RENDER_EVENT: "streamlit:render",
|
24 |
-
events: {
|
25 |
-
addEventListener: function(type, callback) {
|
26 |
-
window.addEventListener("message", function(event) {
|
27 |
-
if (event.data.type === type) {
|
28 |
-
event.detail = event.data
|
29 |
-
callback(event);
|
30 |
-
}
|
31 |
-
});
|
32 |
-
}
|
33 |
-
}
|
34 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
st_hc/frontend/style.css
DELETED
@@ -1,9 +0,0 @@
|
|
1 |
-
text.highcharts-credits {
|
2 |
-
display: none;
|
3 |
-
}
|
4 |
-
.highcharts-exporting-group {
|
5 |
-
display: none;
|
6 |
-
}
|
7 |
-
div[class*="chartMenu"] {
|
8 |
-
display: none;
|
9 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
temp.html
DELETED
@@ -1,310 +0,0 @@
|
|
1 |
-
|
2 |
-
<!DOCTYPE html>
|
3 |
-
<html lang="en">
|
4 |
-
<head>
|
5 |
-
<meta charset="UTF-8">
|
6 |
-
<title>Cartographie des parties prenantes bziiit</title>
|
7 |
-
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
|
8 |
-
<style>
|
9 |
-
body {
|
10 |
-
font-family: 'Roboto', sans-serif;
|
11 |
-
margin: 20px;
|
12 |
-
}
|
13 |
-
h1, h2, h3, h4, h5, h6 {
|
14 |
-
font-weight: bold;
|
15 |
-
}
|
16 |
-
.page-break {
|
17 |
-
page-break-before: always;
|
18 |
-
margin: 50px;
|
19 |
-
height: 50px;
|
20 |
-
}
|
21 |
-
</style>
|
22 |
-
</head>
|
23 |
-
<body>
|
24 |
-
<div style="text-align: center;">
|
25 |
-
<h1>Cartographie des parties prenantes "bziiit"</h1>
|
26 |
-
<p>Date de l'analyse IA RSE : 2024-07-19</p>
|
27 |
-
<p>IA utilisées :</p>
|
28 |
-
<p>GPT-4o</p>
|
29 |
-
<img src="https://static.wixstatic.com/media/d7d3da_b69e03ae99224f7d8b6e358918e60071~mv2.png/v1/crop/x_173,y_0,w_1906,h_938/fill/w_242,h_119,al_c,q_85,usm_0.66_1.00_0.01,enc_auto/BZIIIT_LOGO-HORIZ-COULEUR.png" alt="Logo" style="width: 150px;"/>
|
30 |
-
</div>
|
31 |
-
<div class="page-break"></div>
|
32 |
-
<div style="text-align: center; margin-top: 20px;">
|
33 |
-
<img src="data:image/png;base64,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VXjvP/Jk99Qz3l6pj7ovbkpedXOJtT/yijWZTuNCeJXUEF6BHsIrwDMoZYM3gC502YS8bh7e7jY+dI876avvdJPvu6303VYR3vv3Pcx954Vvd7P22t89fWCf0n3UfWET8qqbScz9kVfM6Yw1NoRXSQ3hFeghvAI8g1I2eAPoQpex5/XA737r/uPeX43c4dEbP+oO++X3St1xWeG97Q//2N0065Ujbf7pfoe7SU/YvVQfdV8Ue15184i9P/KKPaF240N4ldQQXoEewivAMyhlgzeALnQZe17XPnCX2/TIA6Pu8A9/drV72g/+vetddxPe3+4x0W06eo775VNOG9XWjAmT3CmTDuzavsUFsedlwSTmPskr5nR4wtuPdBBegSrCK8AzKGWDN4AudBlzXsWnu/nbnPjg3e7Im77Q8WlvJ+H1T3VvPXqO27H3AW3pxfqUN+a8hGmYbCl5NTFanvAqqSG8Aj2EV4BnUMoGbwBd6DLmvH6w4173wx33drw7L76H/OK77om3/XCX871F4fXndH992HHujiP+z5iim3UW61nemPMSpmGypeTVxGgRXiU1hPdxekNDQ27x4sWtP02bNs2tXr3aTZkypfXndevWucHBwdb/P2vWLLd06VI3MDDgEF5l6tVfywZfP3Olx5jzuvK+2909jz1S+va8/E588B63+6M73KR7tzgvvA/sN835ows79t6/q+TmO9p/twnu7H0PLd13XRfGnFddDJrUD3k1Ka1srAivkhrC65zzsuuFNi+5GdTi99asWdP61oIFCxBeZeYZ1LLBG0AXuow1r07HGcrebrczvN3aifFYQ6x5dWM5Xr9PXk1MHuFVUhv3wrtt2za3bNkyd8EFF7gZM2bswtIL7vTp0928efNa38sL8Pr1690T9prs5syZo2RAbU0E2OBrAh2om1jzuvPRYfeV+++U7lIV3jMnH+wO3mNAGkPo4ljzCn2fqbRHXk1MEuFVUhv3wrtp0ya3aNEit3379hGOc+fObT3BHR4edsuXL3czZ84cEV5//YoVK9ySJUvchg0bEF5l9tVcywZfM3Cxu1jz2vLoDveN+38t3Z0qvM+f/EQ3bY+J0hhCF8eaV+j7TKU98mpikgivktq4F17/xNaf0c3O5fonvgsXLnRnn322O+uss1rC65/ueun1X0Xh3bnnXm727NlKBtTWROCxxx5r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ZcK7adMmt2LFCrdkyRK3YcOG0sK76Ze/dCsvvdQtfsMbxpRb/0TTf73pVa9q/V//VPezX/1q6wnwTT/96ciRhv/63vda38v/c3++1v//Dz70kHtwxw73/R/+sHUUwUu2b8sfi/Bf3Z4s+/Eufve73fYHHhiZYZe85S0jRxrKtuWv82Pde+JE983vfrfVVtZOJtKnPfvZ7rNf+Urreyvf+tYWn7HaL45rzvOfP8Kr21JIWaC63XsTv59yXv0S3vzRAZ95/omvl84HH3yw9T9/tGCfffZxl6xa5Y6cMaP19DV/pKF4bbsnx3mJvXXTptaRheeedpr75ON7zIvmzm09VfXXfXH9+pEpmLXln7xe9vhRsfwxB9/Wu1ascM8//XT3scsvd4dPm9Z6Muzbf8Zxx4205WvOffnL3fK//3u3ffv2XY5KFJ+GX7xyZRR/MYhlLaa8vmJhHHocCK9GdNwLrxfczZs3O39EwX+1E14vu156/VdReCc99JCbPXt21xS83F30nve4gw86yC36m79pey518GMfa7Uz/y//svV/r//Rj9z6r3+9df2Pf/Yz9y+f+lRLFltiODjo/uYVr3BHTp/ufNv5P/t2Nlx3nbv4zW9ufd9/Xfm1r7kvffObrXp/BthfM+2QQ9zZp5++y9izsZ71vOe1vp/9+a//4i/cCcccU6kt3++HPvUpt+xv/7ZV6+8pfx/tmIw11jOe8xy36p//2c19wQtabfmn5p+76ir34jPOKHXO97HHHmvd62677dY1Ly6wJ5ByXiGE995t29ySt73N/dXrXueOP/FE52X3vStXugOnTnV/84Y3OP/9d19yifNPgJ905JHuny+91G249lr3D5dc0vrz+s9/3v3guuvchYsXu5tvusn96wc/6Fa8611uvylTdrm23Wzw7fkv39fPb73VveOii9xJz362e/2b3tTqOz+2/LW+5obrrtulv7u2bm2N5Y7bb2+19exTTmm17b+y9o55xjNG7s23f/DBB7dqhnfsGNVfdv3sOXPc3HPOaY3PC/1bL7qodX98OZfy+ko130kTUF4l23EvvP7prj+aUPzyH057y1ve4t7znvd0fMLrhffMM88slYEXxyXvfa/71Z13jlzvJfLsF7yg9ed/evzJyOvPO6/15xtuusld6YX3/PPdzbfc0hLFFRde2BJWf+3hXlhf8IJR1/kP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">
|
34 |
-
</div>
|
35 |
-
<p><span style="display: inline-block; width: 15px; height: 15px; border-radius: 50%; background-color: #830c5d;"></span> <b>Adetem</b>: Pouvoir:50% Influence:50%</p>
|
36 |
-
|
37 |
-
<p><span style="display: inline-block; width: 15px; height: 15px; border-radius: 50%; background-color: #4e2834;"></span> <b>Bordeaux technowest</b>: Pouvoir:55% Influence:50%</p>
|
38 |
-
|
39 |
-
<p><span style="display: inline-block; width: 15px; height: 15px; border-radius: 50%; background-color: #88e8d7;"></span> <b>Digital aquitaine</b>: Pouvoir:60% Influence:50%</p>
|
40 |
-
|
41 |
-
<p><span style="display: inline-block; width: 15px; height: 15px; border-radius: 50%; background-color: #e07e1d;"></span> <b>Hub france ia</b>: Pouvoir:65% Influence:50%</p>
|
42 |
-
|
43 |
-
<p><span style="display: inline-block; width: 15px; height: 15px; border-radius: 50%; background-color: #797e1a;"></span> <b>La french tech bordeaux</b>: Pouvoir:71% Influence:26%</p>
|
44 |
-
|
45 |
-
<p><span style="display: inline-block; width: 15px; height: 15px; border-radius: 50%; background-color: #4a3a56;"></span> <b>Mouvement impact france</b>: Pouvoir:75% Influence:50%</p>
|
46 |
-
|
47 |
-
<p><span style="display: inline-block; width: 15px; height: 15px; border-radius: 50%; background-color: #b08d0b;"></span> <b>Vivexalto</b>: Pouvoir:77% Influence:82%</p>
|
48 |
-
|
49 |
-
<div class="page-break"></div>
|
50 |
-
<h2>RESUME</h2>
|
51 |
-
<p>Dans cette conversation, nous avons discuté de la cartographie des parties prenantes de la marque bziiit. Voici un résumé des points clés :</p>
|
52 |
-
|
53 |
-
<ol>
|
54 |
-
<li><p><strong>Parties Prenantes Actuellement Identifiées</strong> : La marque bziiit a déjà identifié sept parties prenantes principales avec des niveaux de pouvoir et d'influence variés :</p>
|
55 |
-
|
56 |
-
<ul>
|
57 |
-
<li>Adetem (Pouvoir : 50%, Influence : 50%)</li>
|
58 |
-
<li>Bordeaux Technowest (Pouvoir : 55%, Influence : 50%)</li>
|
59 |
-
<li>Digital Aquitaine (Pouvoir : 60%, Influence : 50%)</li>
|
60 |
-
<li>Hub France IA (Pouvoir : 65%, Influence : 50%)</li>
|
61 |
-
<li>La French Tech Bordeaux (Pouvoir : 71%, Influence : 26%)</li>
|
62 |
-
<li>Mouvement Impact France (Pouvoir : 75%, Influence : 50%)</li>
|
63 |
-
<li>Vivexalto (Pouvoir : 77%, Influence : 82%)</li>
|
64 |
-
</ul></li>
|
65 |
-
<li><p><strong>Catégorisation des Parties Prenantes</strong> : Les parties prenantes sont segmentées en quatre catégories selon leur pouvoir et influence :</p>
|
66 |
-
|
67 |
-
<ul>
|
68 |
-
<li>Rendre satisfait : Pouvoir 50-100, Influence 0-50</li>
|
69 |
-
<li>Gérer étroitement : Pouvoir 50-100, Influence 50-100</li>
|
70 |
-
<li>Suivre de près : Pouvoir 0-50, Influence 0-50</li>
|
71 |
-
<li>Tenir informé : Pouvoir 0-50, Influence 50-100</li>
|
72 |
-
</ul></li>
|
73 |
-
<li><p><strong>Suggestions pour Ajouter d'Autres Parties Prenantes</strong> : </p>
|
74 |
-
|
75 |
-
<ul>
|
76 |
-
<li>Clients et Utilisateurs Finaux : Pouvoir 40%, Influence 60% (Tenir informé)</li>
|
77 |
-
<li>Investisseurs et Actionnaires : Pouvoir 85%, Influence 70% (Gérer étroitement)</li>
|
78 |
-
<li>Fournisseurs et Partenaires Technologiques : Pouvoir 60%, Influence 55% (Gérer étroitement)</li>
|
79 |
-
<li>Gouvernements et Régulateurs : Pouvoir 70%, Influence 80% (Gérer étroitement)</li>
|
80 |
-
<li>Communautés Locales : Pouvoir 30%, Influence 40% (Suivre de près)</li>
|
81 |
-
<li>Médias et Influenceurs : Pouvoir 45%, Influence 70% (Tenir informé)</li>
|
82 |
-
</ul></li>
|
83 |
-
</ol>
|
84 |
-
|
85 |
-
<p>En intégrant ces groupes supplémentaires dans la cartographie des parties prenantes, bziiit pourrait mieux gérer ses relations et élaborer des stratégies plus efficaces pour atteindre ses objectifs organisationnels.</p>
|
86 |
-
|
87 |
-
<hr />
|
88 |
-
|
89 |
-
<hr />
|
90 |
-
|
91 |
-
<div class="page-break"></div>
|
92 |
-
<h2>Historique de la Conversation</h2>
|
93 |
-
<h3>AI:</h3>
|
94 |
-
<p>Salut, voici votre cartographie des parties prenantes. Que puis-je faire pour vous ?</p>
|
95 |
-
<hr />
|
96 |
-
<h3>Moi:</h3>
|
97 |
-
<p>En plus des parties prenantes déjà identifiées que tu peux consulter, quels groupes ou individus, impactés par les activités de mon organisation, devrais-je ajouter dans notre cartographie des parties prenantes ?</p>
|
98 |
-
<hr />
|
99 |
-
<h3>AI:</h3>
|
100 |
-
<p>Pour compléter la cartographie des parties prenantes de bziiit, il est crucial d'identifier et d'intégrer d'autres groupes ou individus qui sont impactés par les activités de l'organisation et qui pourraient influencer sa réussite ou son développement. Voici quelques suggestions basées sur le contexte de votre entreprise et les catégories de parties prenantes existantes :</p>
|
101 |
-
<ol>
|
102 |
-
<li><strong>Clients et Utilisateurs Finaux</strong> :</li>
|
103 |
-
<li><strong>Pouvoir</strong> : 40%</li>
|
104 |
-
<li><strong>Influence</strong> : 60%</li>
|
105 |
-
<li><strong>Catégorie</strong> : Tenir informé</li>
|
106 |
-
</ol>
|
107 |
-
<p>Les clients et utilisateurs finaux sont essentiels car ils sont les destinataires directs des produits et services de bziiit. Bien qu'ils aient un pouvoir limité individuellement, leur influence collective peut être significative à travers les retours et la fidélité.</p>
|
108 |
-
<ol>
|
109 |
-
<li><strong>Investisseurs et Actionnaires</strong> :</li>
|
110 |
-
<li><strong>Pouvoir</strong> : 85%</li>
|
111 |
-
<li><strong>Influence</strong> : 70%</li>
|
112 |
-
<li><strong>Catégorie</strong> : Gérer étroitement</li>
|
113 |
-
</ol>
|
114 |
-
<p>Les investisseurs et actionnaires ont un pouvoir et une influence importants en raison de leurs apports financiers et de leur intérêt direct dans la rentabilité de bziiit. Ils peuvent fortement influencer les décisions stratégiques de l'entreprise.</p>
|
115 |
-
<ol>
|
116 |
-
<li><strong>Fournisseurs et Partenaires Technologiques</strong> :</li>
|
117 |
-
<li><strong>Pouvoir</strong> : 60%</li>
|
118 |
-
<li><strong>Influence</strong> : 55%</li>
|
119 |
-
<li><strong>Catégorie</strong> : Gérer étroitement</li>
|
120 |
-
</ol>
|
121 |
-
<p>Les fournisseurs et partenaires technologiques jouent un rôle crucial dans la chaîne d'approvisionnement et la capacité d'innovation de bziiit. Une gestion étroite de cette relation est nécessaire pour assurer la qualité et la continuité des opérations.</p>
|
122 |
-
<ol>
|
123 |
-
<li><strong>Gouvernements et Régulateurs</strong> :</li>
|
124 |
-
<li><strong>Pouvoir</strong> : 70%</li>
|
125 |
-
<li><strong>Influence</strong> : 80%</li>
|
126 |
-
<li><strong>Catégorie</strong> : Gérer étroitement</li>
|
127 |
-
</ol>
|
128 |
-
<p>Les autorités gouvernementales et les organismes de régulation ont un pouvoir et une influence significatifs en raison de leur capacité à imposer des lois, des règlements et des politiques qui peuvent impacter directement les opérations de bziiit.</p>
|
129 |
-
<ol>
|
130 |
-
<li><strong>Communautés Locales</strong> :</li>
|
131 |
-
<li><strong>Pouvoir</strong> : 30%</li>
|
132 |
-
<li><strong>Influence</strong> : 40%</li>
|
133 |
-
<li><strong>Catégorie</strong> : Suivre de près</li>
|
134 |
-
</ol>
|
135 |
-
<p>Les communautés locales où bziiit opère peuvent être affectées par ses activités, notamment en termes d'emploi, d'environnement et de responsabilité sociale. Bien que leur pouvoir soit limité, leur influence sur la perception publique de l'entreprise peut être importante.</p>
|
136 |
-
<ol>
|
137 |
-
<li><strong>Médias et Influenceurs</strong> :</li>
|
138 |
-
<li><strong>Pouvoir</strong> : 45%</li>
|
139 |
-
<li><strong>Influence</strong> : 70%</li>
|
140 |
-
<li><strong>Catégorie</strong> : Tenir informé</li>
|
141 |
-
</ol>
|
142 |
-
<p>Les médias et les influenceurs peuvent fortement influencer l'image de marque de bziiit. Bien que leur pouvoir direct soit modéré, leur capacité à façonner l'opinion publique leur confère une influence significative.</p>
|
143 |
-
<p>En ajoutant ces groupes à votre cartographie des parties prenantes, vous obtiendrez une vision plus complète des acteurs qui peuvent influencer ou être influencés par les activités de bziiit. Cela vous permettra de mieux gérer vos relations et de développer des stratégies plus robustes pour atteindre vos objectifs organisationnels.</p>
|
144 |
-
<hr />
|
145 |
-
<div class="page-break"></div>
|
146 |
-
<h2>Emission de CO2</h2>
|
147 |
-
<table border="1" class="dataframe">
|
148 |
-
<thead>
|
149 |
-
<tr style="text-align: right;">
|
150 |
-
<th></th>
|
151 |
-
<th>CodeCarbon (Cumulative)</th>
|
152 |
-
<th>EcoLogits (par requete)</th>
|
153 |
-
<th>EcoLogits (Cumulative)</th>
|
154 |
-
<th>Consommation Totale</th>
|
155 |
-
</tr>
|
156 |
-
</thead>
|
157 |
-
<tbody>
|
158 |
-
<tr>
|
159 |
-
<th>Collecte de documents et scrapping</th>
|
160 |
-
<td>$2.61</td>
|
161 |
-
<td>$0.00</td>
|
162 |
-
<td>$0.00</td>
|
163 |
-
<td>$2.61</td>
|
164 |
-
</tr>
|
165 |
-
<tr>
|
166 |
-
<th>Extraction des parties prenantes (serveur et IA)</th>
|
167 |
-
<td>$2.66</td>
|
168 |
-
<td>$1.56</td>
|
169 |
-
<td>$1.56</td>
|
170 |
-
<td>$4.22</td>
|
171 |
-
</tr>
|
172 |
-
<tr>
|
173 |
-
<th>Sauvegarde de la cartographie</th>
|
174 |
-
<td>$7.64</td>
|
175 |
-
<td>$0.00</td>
|
176 |
-
<td>$1.56</td>
|
177 |
-
<td>$9.20</td>
|
178 |
-
</tr>
|
179 |
-
<tr>
|
180 |
-
<th>Dialogue avec chatBot IA</th>
|
181 |
-
<td>$7.48</td>
|
182 |
-
<td>$31.63</td>
|
183 |
-
<td>$33.19</td>
|
184 |
-
<td>$40.67</td>
|
185 |
-
</tr>
|
186 |
-
<tr>
|
187 |
-
<th>Téléchargement cartographie</th>
|
188 |
-
<td>$0.00</td>
|
189 |
-
<td>$0.00</td>
|
190 |
-
<td>$0.00</td>
|
191 |
-
<td>$0.00</td>
|
192 |
-
</tr>
|
193 |
-
</tbody>
|
194 |
-
</table>
|
195 |
-
<div class="page-break"></div>
|
196 |
-
|
197 |
-
<div style='display: flex; align-items: center;'>
|
198 |
-
<h2 style='margin: 0;'>Votre consommation Carbone</h2>
|
199 |
-
<img src='data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjYiIGhlaWdodD0iMjYiIHZpZXdCb3g9IjAgMCAyNiAyNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4NCjxwYXRoIGQ9Ik0zLjMzMTI2IDYuNTgxMjVDLTEuMTA0OTkgMTEuMDE3NSAtMS4xMDQ5OSAxOC4yIDMuMjk4NzYgMjIuNjM2M0M1LjY4NzUxIDE3LjExMTMgOS45NDUwMSAxMi40OTYzIDE1LjI1ODggOS43NUMxMC43NTc1IDEzLjU1MjUgNy42MDUwMSAxOC44NjYzIDYuNTAwMDEgMjQuODk1QzEwLjcyNSAyNi44OTM4IDE1LjkyNSAyNi4xNjI1IDE5LjQxODggMjIuNjY4OEMyNS4wNzM4IDE3LjAxMzggMjYgMCAyNiAwQzI2IDAgOC45ODYyNiAwLjkyNjI1IDMuMzMxMjYgNi41ODEyNVoiIGZpbGw9IiMxMjlDNzMiLz4NCjwvc3ZnPg0K' alt='svg' width='15' height='15' style='margin-left: 10px;'>
|
200 |
-
</div>
|
201 |
-
<br>
|
202 |
-
<div style='text-align: center; margin-bottom: 10px;'><b>42.520</b> g eq. CO2</div><p>Dont :</p><p>- Empreinte serveur (via CodeCarbon) : <b>9.333</b> g eq. CO2 (21.95%)</p><p>- Empreinte IA (via EcoLogits) : <b>33.187</b> g eq. CO2 (78.05%)</p><h2>Votre équivalence</h2>
|
203 |
-
<div style='display: flex; justify-content: space-around;'>
|
204 |
-
|
205 |
-
<div>
|
206 |
-
|
207 |
-
<div style='text-align: center;'>
|
208 |
-
<a href='https://impactco2.fr/outils/comparateur?value=0.042520378554370936&comparisons=tgv,eauenbouteille,voiturethermique' target='_blank'><img src='https://impactco2.fr/icons/eauenbouteille.svg' alt='ml' width='50'></a>
|
209 |
-
</div>
|
210 |
-
<div style='text-align: center;'>
|
211 |
-
<b>159.03</b> ml
|
212 |
-
</div>
|
213 |
-
|
214 |
-
</div>
|
215 |
-
<div>
|
216 |
-
|
217 |
-
<div style='text-align: center;'>
|
218 |
-
<a href='https://impactco2.fr/outils/comparateur?value=0.042520378554370936&comparisons=tgv,eauenbouteille,voiturethermique' target='_blank'><img src='https://impactco2.fr/icons/tgv.svg' alt='km' width='50'></a>
|
219 |
-
</div>
|
220 |
-
<div style='text-align: center;'>
|
221 |
-
<b>14.51</b> km
|
222 |
-
</div>
|
223 |
-
|
224 |
-
</div>
|
225 |
-
<div>
|
226 |
-
|
227 |
-
<div style='text-align: center;'>
|
228 |
-
<a href='https://impactco2.fr/outils/comparateur?value=0.042520378554370936&comparisons=tgv,eauenbouteille,voiturethermique' target='_blank'><img src='https://impactco2.fr/icons/voiturethermique.svg' alt='m' width='50'></a>
|
229 |
-
</div>
|
230 |
-
<div style='text-align: center;'>
|
231 |
-
<b>195.59</b> m
|
232 |
-
</div>
|
233 |
-
|
234 |
-
</div>
|
235 |
-
</div><br>
|
236 |
-
<br>
|
237 |
-
<div style='display: flex; align-items: center;'>
|
238 |
-
<p>Powered by <b>ADEME</b></p>
|
239 |
-
<a href='https://www.ademe.fr' target='_blank'><img src='https://www.ademe.fr/wp-content/uploads/2022/11/ademe-logo-2022-1.svg' alt='svg' width='30' height='30' style='margin-left: 10px;'></a>
|
240 |
-
</div>
|
241 |
-
<br>
|
242 |
-
|
243 |
-
<style>
|
244 |
-
.centered-table {
|
245 |
-
margin-left: auto;
|
246 |
-
margin-right: auto;
|
247 |
-
border-collapse: collapse;
|
248 |
-
width: 50%;
|
249 |
-
}
|
250 |
-
.centered-table th, .centered-table td {
|
251 |
-
border: 1px solid #ddd;
|
252 |
-
padding: 8px;
|
253 |
-
text-align: center;
|
254 |
-
}
|
255 |
-
.centered-table th {
|
256 |
-
background-color: #f2f2f2;
|
257 |
-
}
|
258 |
-
</style>
|
259 |
-
|
260 |
-
<h2 style="text-align:center;">DÉTAIL PAR TÂCHE</h2>
|
261 |
-
<div style="overflow-x:auto;">
|
262 |
-
<style type="text/css">
|
263 |
-
#T_ce1ea_row0_col0, #T_ce1ea_row1_col0, #T_ce1ea_row2_col0 {
|
264 |
-
background-color: rgba(0,128,0,0.5);
|
265 |
-
}
|
266 |
-
#T_ce1ea_row3_col0 {
|
267 |
-
background-color: rgba(255,255,0,0.5);
|
268 |
-
}
|
269 |
-
#T_ce1ea_row4_col0 {
|
270 |
-
background-color: white;
|
271 |
-
}
|
272 |
-
</style>
|
273 |
-
<table id="T_ce1ea" class="centered-table">
|
274 |
-
<thead>
|
275 |
-
<tr>
|
276 |
-
<th class="blank level0" > </th>
|
277 |
-
<th id="T_ce1ea_level0_col0" class="col_heading level0 col0" >Consommation totale (g eqCo2)</th>
|
278 |
-
</tr>
|
279 |
-
</thead>
|
280 |
-
<tbody>
|
281 |
-
<tr>
|
282 |
-
<th id="T_ce1ea_level0_row0" class="row_heading level0 row0" >Collecte de documents et scrapping</th>
|
283 |
-
<td id="T_ce1ea_row0_col0" class="data row0 col0" >2.610000</td>
|
284 |
-
</tr>
|
285 |
-
<tr>
|
286 |
-
<th id="T_ce1ea_level0_row1" class="row_heading level0 row1" >Extraction des parties prenantes (serveur et IA)</th>
|
287 |
-
<td id="T_ce1ea_row1_col0" class="data row1 col0" >4.220000</td>
|
288 |
-
</tr>
|
289 |
-
<tr>
|
290 |
-
<th id="T_ce1ea_level0_row2" class="row_heading level0 row2" >Sauvegarde de la cartographie</th>
|
291 |
-
<td id="T_ce1ea_row2_col0" class="data row2 col0" >9.200000</td>
|
292 |
-
</tr>
|
293 |
-
<tr>
|
294 |
-
<th id="T_ce1ea_level0_row3" class="row_heading level0 row3" >Dialogue avec chatBot IA</th>
|
295 |
-
<td id="T_ce1ea_row3_col0" class="data row3 col0" >40.670000</td>
|
296 |
-
</tr>
|
297 |
-
<tr>
|
298 |
-
<th id="T_ce1ea_level0_row4" class="row_heading level0 row4" >Téléchargement cartographie</th>
|
299 |
-
<td id="T_ce1ea_row4_col0" class="data row4 col0" >-</td>
|
300 |
-
</tr>
|
301 |
-
</tbody>
|
302 |
-
</table>
|
303 |
-
|
304 |
-
</div>
|
305 |
-
|
306 |
-
<h2>SYNTHESE (Dialogue IA et non IA)</h2>
|
307 |
-
<div style="text-align:center;"><img src="data:image/png;base64,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uuo/3Vd/9VfzMR/zMXzWZ30Wn/3Zn80L8t3f/d28z/u8D8ePH+e93/u9OX78ON/93d/Nrbfeylu91Vvx0z/909zvsz/7s/mcz/kcPuuzPovP/uzP5n4//dM/zdu8zdvw4Ac/mLd+67fm1ltv5ad/+qd50IMexF//9V9z/PhxXhhJvNZrvRa//du/zQvy27/927zO67wOT3/603nwgx/M/T77sz+br/mar+G3fuu3ePCDH8zLvMzL8FIv9VL89E//NFdd9X8YALJtrrrqqv903/3d3813f/d389Vf/dW89Eu/NC/MX//1X/PZn/3Z3Hrrrdx666289Eu/NO/93u/Ne7/3e/NA3/3d3813f/d3897v/d6893u/Nw/013/913z2Z382f/3Xf83x48d56Zd+aT77sz+bBz/4wfxLXvu1X5uXfumX5qu/+qt5QV7mZV6Gl3qpl+K7v/u7eaDd3V3e+q3fmt/5nd8B4KVe6qX47d/+bY4fP85VV/0fBoBsm6uuuuqqf4Xd3V3++q//mpd+6Zfm+PHjPD+33norAA9+8IO56qr/BwCQbXPVVVddddVVV/17ACDb5qqrrrrqqquu+vcAQLbNVVddddVVV1317wGAbJurrrrqqquuuurfAwDZNlddddVVV1111b8HALJtrrrqqquuuuqqfw8AZNtcddVVV1111VX/HgDItrnqqquuuuqqq/49AJBtc9VVV1111VVX/XsAINvmqquuuuqqq6769wBAts1VV1111VVXXfXvAYBsm6uuuuqqq6666t8DANk2V1111VVXXXXVvwcAsm2uuuqqq6666qp/DwBk21x11VVXXXXVVf8eAMi2ueqqq6666qqr/j0AkG1z1VVXXXXVVVf9ewAg2+aqq6666qqrrvr3AEC2zVVXXXXVVVdd9e8BgGybq6666qqrrrrq3wMA2TZXXXXVVVddddW/BwCyba666qqrrrrqqn8PAGTbXHXVVVddddVV/x4AyLa56qqrrrrqqqv+PQCQbXPVVVddddVVV/17ACDb5qqrrrrqqquu+vcAQLbNVVddddVVV1317wGAbJurrrrqqquuuurfAwDZNlddddVVV1111b8HALJtrrrqqquuuuqqfw8AZNtcddVVV1111VX/HgDItrnqqquuuuqqq/49APhH8sbK5fnKHNUAAAAASUVORK5CYII=" alt="Pie chart"></div>
|
308 |
-
</body>
|
309 |
-
</html>
|
310 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|