Spaces:
Running
Running
Demosthene-OR
commited on
Commit
•
6c15782
1
Parent(s):
44b1492
.....
Browse files- app.py +36 -10
- style.css +12 -0
- tabs/chatbot_tab.py +218 -131
- tabs/intro.py +6 -3
- translate_app.py +3 -1
app.py
CHANGED
@@ -17,6 +17,7 @@ else:
|
|
17 |
st.set_page_config (
|
18 |
page_title=config.TITLE,
|
19 |
page_icon= "assets/faviconV2.png",
|
|
|
20 |
initial_sidebar_state=st.session_state.sidebar_state
|
21 |
)
|
22 |
|
@@ -58,32 +59,40 @@ st.markdown(f"<style>{style}</style>", unsafe_allow_html=True)
|
|
58 |
TABS = OrderedDict(
|
59 |
[
|
60 |
(tr(intro.sidebar_name), intro),
|
61 |
-
(tr(sentence_similarity_tab.sidebar_name), sentence_similarity_tab),
|
62 |
-
(tr(speech2text_tab.sidebar_name), speech2text_tab),
|
63 |
(tr(chatbot_tab.sidebar_name), chatbot_tab),
|
|
|
|
|
64 |
]
|
65 |
)
|
66 |
|
67 |
-
# Utilisation du module translate
|
68 |
-
# lang_tgt = ['fr','en','af','ak','sq','de','am','en','ar','hy','as','az','ba','bm','eu','bn','be','my','bs','bg','ks','ca','ny','zh','si','ko','co','ht','hr','da','dz','gd','es','eo','et','ee','fo','fj','fi','fr','fy','gl','cy','lg','ka','el','gn','gu','ha','he','hi','hu','ig','id','iu','ga','is','it','ja','kn','kk','km','ki','rw','ky','rn','ku','lo','la','lv','li','ln','lt','lb','mk','ms','ml','dv','mg','mt','mi','mr','mn','nl','ne','no','nb','nn','oc','or','ug','ur','uz','ps','pa','fa','pl','pt','ro','ru','sm','sg','sa','sc','sr','sn','sd','sk','sl','so','st','su','sv','sw','ss','tg','tl','ty','ta','tt','cs','te','th','bo','ti','to','ts','tn','tr','tk','tw','uk','vi','wo','xh','yi']
|
69 |
-
# label_lang = ['Français', 'Anglais / English','Afrikaans','Akan','Albanais','Allemand / Deutsch','Amharique','Anglais','Arabe','Arménien','Assamais','Azéri','Bachkir','Bambara','Basque','Bengali','Biélorusse','Birman','Bosnien','Bulgare','Cachemiri','Catalan','Chichewa','Chinois','Cingalais','Coréen','Corse','Créolehaïtien','Croate','Danois','Dzongkha','Écossais','Espagnol / Español','Espéranto','Estonien','Ewe','Féroïen','Fidjien','Finnois','Français','Frisonoccidental','Galicien','Gallois','Ganda','Géorgien','Grecmoderne','Guarani','Gujarati','Haoussa','Hébreu','Hindi','Hongrois','Igbo','Indonésien','Inuktitut','Irlandais','Islandais','Italien / Italiano','Japonais','Kannada','Kazakh','Khmer','Kikuyu','Kinyarwanda','Kirghiz','Kirundi','Kurde','Lao','Latin','Letton','Limbourgeois','Lingala','Lituanien','Luxembourgeois','Macédonien','Malais','Malayalam','Maldivien','Malgache','Maltais','MaorideNouvelle-Zélande','Marathi','Mongol','Néerlandais / Nederlands','Népalais','Norvégien','Norvégienbokmål','Norvégiennynorsk','Occitan','Oriya','Ouïghour','Ourdou','Ouzbek','Pachto','Pendjabi','Persan','Polonais','Portugais','Roumain','Russe','Samoan','Sango','Sanskrit','Sarde','Serbe','Shona','Sindhi','Slovaque','Slovène','Somali','SothoduSud','Soundanais','Suédois','Swahili','Swati','Tadjik','Tagalog','Tahitien','Tamoul','Tatar','Tchèque','Télougou','Thaï','Tibétain','Tigrigna','Tongien','Tsonga','Tswana','Turc','Turkmène','Twi','Ukrainien','Vietnamien','Wolof','Xhosa','Yiddish']
|
70 |
-
|
71 |
# Utilisation du module deep_translator
|
72 |
-
lang_tgt = ['fr', 'en',
|
73 |
-
label_lang = ['Français',
|
|
|
74 |
|
75 |
-
@st.cache_data
|
76 |
def find_lang_label(lang_sel):
|
77 |
global lang_tgt, label_lang
|
78 |
return label_lang[lang_tgt.index(lang_sel)]
|
79 |
|
|
|
|
|
|
|
|
|
|
|
80 |
def run():
|
81 |
|
82 |
st.sidebar.image(
|
83 |
"assets/value_props_logo.png",
|
84 |
width=270,
|
85 |
)
|
|
|
|
|
|
|
|
|
|
|
86 |
with st.sidebar:
|
|
|
87 |
tab_name = option_menu(None, list(TABS.keys()),
|
88 |
# icons=['house', 'bi-binoculars', 'bi bi-graph-up', 'bi-chat-right-text','bi-book', 'bi-body-text'], menu_icon="cast", default_index=0,
|
89 |
icons=['house', 'binoculars', 'graph-up', 'search','book', 'chat-right-text','controller'], menu_icon="cast", default_index=0,
|
@@ -101,7 +110,24 @@ def run():
|
|
101 |
st.sidebar.markdown(member.sidebar_markdown(), unsafe_allow_html=True)
|
102 |
|
103 |
with st.sidebar:
|
104 |
-
st.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
105 |
|
106 |
tab = TABS[tab_name]
|
107 |
tab.run()
|
|
|
17 |
st.set_page_config (
|
18 |
page_title=config.TITLE,
|
19 |
page_icon= "assets/faviconV2.png",
|
20 |
+
layout="wide",
|
21 |
initial_sidebar_state=st.session_state.sidebar_state
|
22 |
)
|
23 |
|
|
|
59 |
TABS = OrderedDict(
|
60 |
[
|
61 |
(tr(intro.sidebar_name), intro),
|
|
|
|
|
62 |
(tr(chatbot_tab.sidebar_name), chatbot_tab),
|
63 |
+
(tr(sentence_similarity_tab.sidebar_name), sentence_similarity_tab),
|
64 |
+
# (tr(speech2text_tab.sidebar_name), speech2text_tab),
|
65 |
]
|
66 |
)
|
67 |
|
|
|
|
|
|
|
|
|
68 |
# Utilisation du module deep_translator
|
69 |
+
lang_tgt = ['fr', 'en','de','es', 'it', 'nl']
|
70 |
+
label_lang = ['Français','English','Deutsch','Español','Italiano','Nederlands']
|
71 |
+
label_lang_en = ['French', 'English', 'German', 'Spanish', 'Italian', 'Dutch']
|
72 |
|
73 |
+
# @st.cache_data
|
74 |
def find_lang_label(lang_sel):
|
75 |
global lang_tgt, label_lang
|
76 |
return label_lang[lang_tgt.index(lang_sel)]
|
77 |
|
78 |
+
# @st.cache_data
|
79 |
+
def find_lang_label_en(lang_sel):
|
80 |
+
global lang_tgt, label_lang_en
|
81 |
+
return label_lang_en[lang_tgt.index(lang_sel)]
|
82 |
+
|
83 |
def run():
|
84 |
|
85 |
st.sidebar.image(
|
86 |
"assets/value_props_logo.png",
|
87 |
width=270,
|
88 |
)
|
89 |
+
with st.sidebar.expander(tr("Développez moi")):
|
90 |
+
st.markdown(tr("""
|
91 |
+
Cette application vous permet de tester les futures fonctionnalités de la plateforme Value Props, et plus particulièrement « Sales Coaching ».
|
92 |
+
Amusez vous bien !
|
93 |
+
"""))
|
94 |
with st.sidebar:
|
95 |
+
|
96 |
tab_name = option_menu(None, list(TABS.keys()),
|
97 |
# icons=['house', 'bi-binoculars', 'bi bi-graph-up', 'bi-chat-right-text','bi-book', 'bi-body-text'], menu_icon="cast", default_index=0,
|
98 |
icons=['house', 'binoculars', 'graph-up', 'search','book', 'chat-right-text','controller'], menu_icon="cast", default_index=0,
|
|
|
110 |
st.sidebar.markdown(member.sidebar_markdown(), unsafe_allow_html=True)
|
111 |
|
112 |
with st.sidebar:
|
113 |
+
st.write("")
|
114 |
+
llm_choice = st.selectbox("LLM:",["Mistral large","OpenAI 3.5","OpenAI 4o"], label_visibility="visible")
|
115 |
+
if (llm_choice == "OpenAI 3.5") : st.session_state.model = "gpt-3.5-turbo"
|
116 |
+
elif (llm_choice == "OpenAI 4o") : st.session_state.model = "gpt-4o"
|
117 |
+
else: st.session_state.model = "mistral-large-latest"
|
118 |
+
|
119 |
+
if (llm_choice in ["OpenAI 3.5","OpenAI 4o"]) and ('OPENAI_API_KEY' not in st.session_state):
|
120 |
+
# Set OpenAI API key
|
121 |
+
st.sidebar.subheader("OpenAI API Key")
|
122 |
+
openai_api_key = st.sidebar.text_input("Enter your OpenAI API Key:", type='password')
|
123 |
+
if openai_api_key:
|
124 |
+
os.environ['OPENAI_API_KEY'] = openai_api_key
|
125 |
+
st.session_state['OPENAI_API_KEY'] = openai_api_key
|
126 |
+
st.sidebar.success("OpenAI API Key set successfully.")
|
127 |
+
|
128 |
+
with st.sidebar:
|
129 |
+
l = st.selectbox("langue:",lang_tgt, format_func = find_lang_label, key="Language", label_visibility="hidden")
|
130 |
+
st.session_state.language_label = find_lang_label_en(l)
|
131 |
|
132 |
tab = TABS[tab_name]
|
133 |
tab.run()
|
style.css
CHANGED
@@ -8,6 +8,11 @@ h2 {
|
|
8 |
padding-bottom: 0.5rem;
|
9 |
}
|
10 |
|
|
|
|
|
|
|
|
|
|
|
11 |
/* La ligne suivante est nécessaire à cause du module streamlit_option_menu qui "casse" les CSS suivants */
|
12 |
@media (prefers-color-scheme: dark) {
|
13 |
.st-cc {
|
@@ -99,6 +104,13 @@ section[data-testid="stSidebar"] .stSelectbox .st-bk {
|
|
99 |
background-color: #a0d3de;
|
100 |
}
|
101 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
section[data-testid="stSidebar"] .stSelectbox .st-cc {
|
103 |
color: rgb(255, 75, 75);
|
104 |
font-weight: bold;
|
|
|
8 |
padding-bottom: 0.5rem;
|
9 |
}
|
10 |
|
11 |
+
h3 {
|
12 |
+
padding-bottom: 0.0rem;
|
13 |
+
}
|
14 |
+
|
15 |
+
|
16 |
/* La ligne suivante est nécessaire à cause du module streamlit_option_menu qui "casse" les CSS suivants */
|
17 |
@media (prefers-color-scheme: dark) {
|
18 |
.st-cc {
|
|
|
104 |
background-color: #a0d3de;
|
105 |
}
|
106 |
|
107 |
+
.st-emotion-cache-1h9usn1{
|
108 |
+
font-weight: bold!important;
|
109 |
+
background-color: #a0d3de;
|
110 |
+
}
|
111 |
+
|
112 |
+
|
113 |
+
|
114 |
section[data-testid="stSidebar"] .stSelectbox .st-cc {
|
115 |
color: rgb(255, 75, 75);
|
116 |
font-weight: bold;
|
tabs/chatbot_tab.py
CHANGED
@@ -22,6 +22,7 @@ from langchain_core.messages import BaseMessage, SystemMessage, HumanMessage, AI
|
|
22 |
from langgraph.graph.message import add_messages
|
23 |
from typing_extensions import Annotated, TypedDict
|
24 |
from dotenv import load_dotenv
|
|
|
25 |
|
26 |
import warnings
|
27 |
warnings.filterwarnings('ignore')
|
@@ -38,21 +39,14 @@ if st.session_state.Cloud != 0:
|
|
38 |
load_dotenv()
|
39 |
os.getenv("LANGCHAIN_API_KEY")
|
40 |
os.getenv("MISTRAL_API_KEY")
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
model = ChatMistralAI(model="mistral-large-latest")
|
47 |
-
# model = ChatOpenAI(model="gpt-3.5-turbo")
|
48 |
|
49 |
|
50 |
-
language = "French"
|
51 |
prompt = ChatPromptTemplate.from_messages(
|
52 |
[
|
53 |
(
|
54 |
"system",
|
55 |
-
"Répond à toutes les questions du mieux possible
|
56 |
),
|
57 |
MessagesPlaceholder(variable_name="messages"),
|
58 |
]
|
@@ -81,51 +75,117 @@ app = workflow.compile(checkpointer=memory)
|
|
81 |
|
82 |
# @st.cache_data
|
83 |
def init():
|
84 |
-
global config,thread_id, context,human_message1,ai_message1,language, app, model_speech
|
85 |
|
86 |
thread_id = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
87 |
config = {"configurable": {"thread_id": thread_id}}
|
88 |
model_speech = whisper.load_model("base")
|
|
|
|
|
|
|
|
|
|
|
89 |
|
90 |
-
|
91 |
-
|
92 |
-
|
|
|
|
|
93 |
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
119 |
Répond à mes questions en tant que Directeur commercial désorganisé, connaissant mal le concept de proposition de valeur,
|
120 |
et mon équipe de vente n'est pas performante.
|
121 |
|
122 |
-
Attention: Ce n'est pas toi qui m'aide, c'est moi qui t'aide avec ma solution.
|
123 |
-
|
124 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
|
126 |
-
|
127 |
-
|
128 |
-
ai_message1 = st.text_area(label=tr("Réponse du prospect"), value=ai_message1)
|
129 |
messages = [
|
130 |
SystemMessage(content=context),
|
131 |
HumanMessage(content=human_message1),
|
@@ -134,19 +194,13 @@ Attention: Ce n'est pas toi qui m'aide, c'est moi qui t'aide avec ma solution.
|
|
134 |
]
|
135 |
|
136 |
|
137 |
-
|
138 |
app.invoke(
|
139 |
{"messages": messages, "language": language},
|
140 |
config,
|
141 |
)
|
142 |
-
|
143 |
-
st.write("**Contexte:** "+context)
|
144 |
-
st.write("")
|
145 |
-
st.write("**Human Message:** "+human_message1)
|
146 |
-
st.write("")
|
147 |
-
st.write("**AI Message:** "+ai_message1)
|
148 |
-
'''
|
149 |
st.write("")
|
|
|
150 |
return config, thread_id
|
151 |
|
152 |
# Fonction pour générer et jouer le texte en speech
|
@@ -175,24 +229,41 @@ def play_audio(custom_sentence, Lang_target, speed=1.0):
|
|
175 |
new_audio_stream_bytesio.seek(0)
|
176 |
|
177 |
# Lire l'audio dans Streamlit
|
178 |
-
|
|
|
179 |
|
180 |
|
181 |
|
182 |
def run():
|
183 |
-
global thread_id, config, model_speech
|
184 |
|
185 |
st.write("")
|
186 |
st.write("")
|
187 |
st.title(tr(title))
|
188 |
|
|
|
|
|
|
|
|
|
189 |
chosen_id = tab_bar(data=[
|
190 |
TabBarItemData(id="tab1", title=tr("Initialisation"), description=tr("d'une nouvelle conversation")),
|
191 |
-
TabBarItemData(id="tab2", title=tr("Conversation"), description=tr("avec le prospect"))
|
|
|
192 |
default="tab1")
|
193 |
|
194 |
|
195 |
if (chosen_id == "tab1"):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
196 |
config,thread_id = init()
|
197 |
query = ""
|
198 |
st.button(label=tr("Validez"), type="primary")
|
@@ -202,87 +273,103 @@ def run():
|
|
202 |
# On ne fait rien
|
203 |
except NameError:
|
204 |
config,thread_id = init()
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
#
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
# Read the WAV stream using wavio
|
223 |
-
wav = wavio.read(audio_stream_bytesio)
|
224 |
-
|
225 |
-
# Extract the audio data from the wavio.Wav object
|
226 |
-
audio_data = wav.data
|
227 |
-
|
228 |
-
# Convert the audio data to a NumPy array
|
229 |
-
audio_input = np.array(audio_data, dtype=np.float32)
|
230 |
-
audio_input = np.mean(audio_input, axis=1)/32768
|
231 |
-
|
232 |
-
result = model_speech.transcribe(audio_input)
|
233 |
-
Lang_detected = result["language"]
|
234 |
-
query = result["text"]
|
235 |
-
st.write(tr("Langue détectée")+" : "+Lang_detected)
|
236 |
-
|
237 |
-
else:
|
238 |
-
# Avec l'aide de la bibliothèque speech_recognition de Google
|
239 |
-
Lang_detected = "fr"
|
240 |
-
# Transcription google
|
241 |
-
audio_stream = sr.AudioData(audio_bytes, 32000, 2)
|
242 |
-
r = sr.Recognizer()
|
243 |
-
query = r.recognize_google(audio_stream, language = Lang_detected)
|
244 |
-
|
245 |
-
# Transcription
|
246 |
-
st.write("**Vendeur :** "+query)
|
247 |
-
st.write("")
|
248 |
|
249 |
-
if
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
# Joue l'audio
|
260 |
-
if language=="French": Lang_target = "fr" # Langue de la réponse
|
261 |
-
play_audio(custom_sentence, Lang_target, 1)
|
262 |
-
|
263 |
-
st.write("**Prospect :** "+custom_sentence)
|
264 |
-
|
265 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
266 |
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
271 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
272 |
|
273 |
-
'''
|
274 |
-
# Créer un espace réservé pour afficher les tokens
|
275 |
-
placeholder = st.empty()
|
276 |
-
|
277 |
-
for chunk, metadata in app.stream(
|
278 |
-
{"messages": input_messages, "language": language},
|
279 |
-
config,
|
280 |
-
stream_mode="messages",
|
281 |
-
):
|
282 |
-
if isinstance(chunk, AIMessage): # Filter to just model responses
|
283 |
-
# st.markdown("<span style='white-space: nowrap;'>"+"/"+chunk.content+"/"+"</span>", unsafe_allow_html=True)
|
284 |
-
placeholder.markdown(f"<p style='display: inline;'>{chunk.content}</p>", unsafe_allow_html=True)
|
285 |
-
'''
|
286 |
st.write("")
|
287 |
st.write("")
|
288 |
st.write("")
|
|
|
22 |
from langgraph.graph.message import add_messages
|
23 |
from typing_extensions import Annotated, TypedDict
|
24 |
from dotenv import load_dotenv
|
25 |
+
import time
|
26 |
|
27 |
import warnings
|
28 |
warnings.filterwarnings('ignore')
|
|
|
39 |
load_dotenv()
|
40 |
os.getenv("LANGCHAIN_API_KEY")
|
41 |
os.getenv("MISTRAL_API_KEY")
|
42 |
+
os.getenv("OPENAI_API_KEY")
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
|
44 |
|
|
|
45 |
prompt = ChatPromptTemplate.from_messages(
|
46 |
[
|
47 |
(
|
48 |
"system",
|
49 |
+
"Répond à toutes les questions du mieux possible dans la langue {language}, même si la question est posée dans une autre langue",
|
50 |
),
|
51 |
MessagesPlaceholder(variable_name="messages"),
|
52 |
]
|
|
|
75 |
|
76 |
# @st.cache_data
|
77 |
def init():
|
78 |
+
global config,thread_id, context,human_message1,ai_message1,language, app, model_speech,language,prompt,model
|
79 |
|
80 |
thread_id = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
81 |
config = {"configurable": {"thread_id": thread_id}}
|
82 |
model_speech = whisper.load_model("base")
|
83 |
+
|
84 |
+
options = ["Directeur Commercial", "Directeur Général", "Directeur Marketing"]
|
85 |
+
translated_options = [tr(o) for o in options]
|
86 |
+
selected_option = st.selectbox(tr("Interlocuteur"),translated_options)
|
87 |
+
selected_index = translated_options.index(selected_option)
|
88 |
|
89 |
+
options2 = ["Entreprise qui commercialise des solutions (produits et ou services) B2B innovantes avec une équipe commerciale de plus de 15 personnes",
|
90 |
+
"Entreprise qui commercialise des solutions (produits et ou services) B2B innovantes avec une équipe commerciale de plus de 100 personnes"]
|
91 |
+
translated_options2 = [tr(o) for o in options2]
|
92 |
+
selected_option2 = st.selectbox(tr("Activité"),translated_options2)
|
93 |
+
selected_index2 = translated_options2.index(selected_option2)
|
94 |
|
95 |
+
options3 = ["Logiciels informatiques et d’application SaaS",
|
96 |
+
"Équipements et solutions industrielles",
|
97 |
+
"Services et conseil spécialisés"]
|
98 |
+
translated_options3 = [tr(o) for o in options3]
|
99 |
+
selected_option3 = st.selectbox(tr("Domaine d'activité"),translated_options3)
|
100 |
+
selected_index3 = translated_options3.index(selected_option3)
|
101 |
+
|
102 |
+
context = tr(f"""Tu es un {options[selected_index]}, mal organisé, d'une {options2[selected_index2]}.
|
103 |
+
Cette entreprise propose des {options3[selected_index3]}.
|
104 |
+
""")
|
105 |
+
context = st.text_area(label=tr("Résumé du Contexte (modifiable):"), value=context)
|
106 |
+
st.markdown('''
|
107 |
+
------------------------------------------------------------------------------------
|
108 |
+
''')
|
109 |
+
|
110 |
+
options4 = ["Il est difficile pour les forces de vente d'articuler clairement les messages de la proposition de valeur",
|
111 |
+
"Il est difficile d’affiner une proposition de valeur unique et pertinente de l'offre face à la concurrence qui évolue rapidement",
|
112 |
+
"Il est chronophage de former les forces de ventes sur la proposition de valeur et ses évolutions"
|
113 |
+
]
|
114 |
+
selected_options4 = st.multiselect(tr("Problématiques"),[tr(o) for o in options4])
|
115 |
+
problematique = [tr(o) for o in selected_options4]
|
116 |
+
markdown_text4 = tr("""
|
117 |
+
Les problématiques rencontrés par notre prospect (problèmes à résoudre) sont:""")
|
118 |
+
markdown_text4 = markdown_text4+"".join(f"\n- {o}" for o in problematique)
|
119 |
+
st.write(markdown_text4)
|
120 |
+
|
121 |
+
options5 = ["Former la force de ventes sur l'articulation de la proposition de valeur",
|
122 |
+
"Aligner les messages marketing et commerciaux",
|
123 |
+
"Affiner et modéliser la proposition de valeur",
|
124 |
+
"Mettre en oeuvre des meilleures pratiques commerciales"
|
125 |
+
]
|
126 |
+
selected_options5 = st.multiselect(tr("Processus"),[tr(o) for o in options5])
|
127 |
+
processus = [tr(o) for o in selected_options5]
|
128 |
+
markdown_text5 = tr("""
|
129 |
+
\nLes processus adressés par le prospect (cas d’usages) sont:""")
|
130 |
+
markdown_text5 = markdown_text5+"".join(f"\n- {o}" for o in processus)
|
131 |
+
st.write(markdown_text5)
|
132 |
+
|
133 |
+
options6 = ["Augmenter les performances commerciales",
|
134 |
+
"Croissance du chiffre d’affaires",
|
135 |
+
"Réduire les cycles de vente",
|
136 |
+
"Augmenter taux de conversion d’affaires gagnées",
|
137 |
+
"Améliorer l’efficience et la confiance des forces de ventes",
|
138 |
+
"Réduire temps de monté en compétence des nouvelles embauches",
|
139 |
+
"Fidéliser les clients"
|
140 |
+
]
|
141 |
+
selected_options6 = st.multiselect(tr("Objectifs d'amélioration"),[tr(o) for o in options6])
|
142 |
+
objectifs = [tr(o) for o in selected_options6]
|
143 |
+
markdown_text6 = tr("""
|
144 |
+
\nLes objectifs d’amélioration opérationnelle du prospect (Valeur ajoutée) sont:""")
|
145 |
+
markdown_text6 = markdown_text6+"".join(f"\n- {o}" for o in objectifs)
|
146 |
+
st.write(markdown_text6)
|
147 |
+
|
148 |
+
options7 = ["Gestion de contenu commercial avec logiciel Microsoft sharePoint ou GoogleDrive",
|
149 |
+
"Playbook développé en interne sur outils génériques tels que logiciel Notion, Powerpoint, Excel, Word, Docs",
|
150 |
+
"Outils de sales enablement tels que application Seismic",
|
151 |
+
"Outils de gestion des présentations clients tels que Logiciel Powerpoint ou Google slide",
|
152 |
+
"Conseil externe en positionnement marché & produit",
|
153 |
+
"Services externes de formation des équipes commerciales"
|
154 |
+
]
|
155 |
+
selected_options7 = st.multiselect(tr("Solutions utilisées"),[tr(o) for o in options7])
|
156 |
+
solutions_utilisees = [tr(o) for o in selected_options7]
|
157 |
+
markdown_text7 = tr("""
|
158 |
+
\nLes principales Solutions utilisées par nos prospects pour traiter les cas d’usages (Catégories de solutions du marché) sont:""")
|
159 |
+
markdown_text7 = markdown_text7+"".join(f"\n- {o}" for o in solutions_utilisees)
|
160 |
+
st.write(markdown_text7)
|
161 |
+
st.write("")
|
162 |
+
col1, col2, col3 = st.columns(3)
|
163 |
+
with col1:
|
164 |
+
virulence = st.slider(tr("Virulence (choisissez une valeur entre 1 et 5)"), min_value=1, max_value=5, step=1)
|
165 |
+
markdown_text8 = tr(f"""\nTu vas utiliser une échelle de 1 à 5 de virulence. Pour cette simulation utilise le niveaux {virulence}""")
|
166 |
+
|
167 |
+
human_message1 = tr("""Je souhaites que nous ayons une conversation verbale entre un commercial de mon entreprise, et toi que je prospecte.
|
168 |
+
Mon entreprise propose une solution logicielle pour gérer la proposition de valeur d’entreprises B2B qui commercialises des solutions technologiques.
|
169 |
+
""")+markdown_text4+markdown_text5+markdown_text6+markdown_text7+tr("""
|
170 |
+
|
171 |
+
Je suis le vendeur.
|
172 |
Répond à mes questions en tant que Directeur commercial désorganisé, connaissant mal le concept de proposition de valeur,
|
173 |
et mon équipe de vente n'est pas performante.
|
174 |
|
175 |
+
Attention: Ce n'est pas toi qui m'aide, c'est moi qui t'aide avec ma solution.
|
176 |
+
|
177 |
+
""")+markdown_text8
|
178 |
+
|
179 |
+
human_message1 = st.text_area(label=tr("Consigne"), value=tr(human_message1),height=300)
|
180 |
+
st.markdown('''
|
181 |
+
------------------------------------------------------------------------------------
|
182 |
+
''')
|
183 |
+
|
184 |
+
ai_message1 = tr(f"J'ai bien compris, je suis un {options[selected_index]} prospecté et je réponds seulement à tes questions. Je réponds à une seule question à la fois, sans commencer mes réponses par 'En tant que {options[selected_index]}'")
|
185 |
|
186 |
+
|
187 |
+
|
188 |
+
# ai_message1 = st.text_area(label=tr("Réponse du prospect"), value=ai_message1)
|
189 |
messages = [
|
190 |
SystemMessage(content=context),
|
191 |
HumanMessage(content=human_message1),
|
|
|
194 |
]
|
195 |
|
196 |
|
|
|
197 |
app.invoke(
|
198 |
{"messages": messages, "language": language},
|
199 |
config,
|
200 |
)
|
201 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
202 |
st.write("")
|
203 |
+
st.session_state.messages = []
|
204 |
return config, thread_id
|
205 |
|
206 |
# Fonction pour générer et jouer le texte en speech
|
|
|
229 |
new_audio_stream_bytesio.seek(0)
|
230 |
|
231 |
# Lire l'audio dans Streamlit
|
232 |
+
time.sleep(2)
|
233 |
+
st.audio(new_audio_stream_bytesio, start_time=0, autoplay=True)
|
234 |
|
235 |
|
236 |
|
237 |
def run():
|
238 |
+
global thread_id, config, model_speech, language,prompt,model
|
239 |
|
240 |
st.write("")
|
241 |
st.write("")
|
242 |
st.title(tr(title))
|
243 |
|
244 |
+
if 'language_label' in st.session_state:
|
245 |
+
language = st.session_state['language_label']
|
246 |
+
else: language = "French"
|
247 |
+
|
248 |
chosen_id = tab_bar(data=[
|
249 |
TabBarItemData(id="tab1", title=tr("Initialisation"), description=tr("d'une nouvelle conversation")),
|
250 |
+
TabBarItemData(id="tab2", title=tr("Conversation"), description=tr("avec le prospect")),
|
251 |
+
TabBarItemData(id="tab3", title=tr("Evaluation"), description=tr("de l'acte de vente"))],
|
252 |
default="tab1")
|
253 |
|
254 |
|
255 |
if (chosen_id == "tab1"):
|
256 |
+
if 'model' in st.session_state and (st.session_state.model[:3]=="gpt") and ("OPENAI_API_KEY" in st.session_state):
|
257 |
+
model = ChatOpenAI(model=st.session_state.model,
|
258 |
+
temperature=0.8, # Adjust creativity level
|
259 |
+
max_tokens=150 # Define max output token limit
|
260 |
+
)
|
261 |
+
|
262 |
+
else:
|
263 |
+
st.session_state.model = "mistral-large-latest"
|
264 |
+
model = ChatMistralAI(model=st.session_state.model)
|
265 |
+
|
266 |
+
|
267 |
config,thread_id = init()
|
268 |
query = ""
|
269 |
st.button(label=tr("Validez"), type="primary")
|
|
|
273 |
# On ne fait rien
|
274 |
except NameError:
|
275 |
config,thread_id = init()
|
276 |
+
with st.container():
|
277 |
+
# Diviser l'écran en deux colonnes
|
278 |
+
col1, col2 = st.columns(2)
|
279 |
+
# with col1:
|
280 |
+
# st.markdown(
|
281 |
+
# """
|
282 |
+
# <div style="height: 400px;">
|
283 |
+
# </div>
|
284 |
+
# """,
|
285 |
+
# unsafe_allow_html=True,
|
286 |
+
# )
|
287 |
+
with col1:
|
288 |
+
st.write("**thread_id:** "+thread_id)
|
289 |
+
query = ""
|
290 |
+
audio_bytes = audio_recorder (pause_threshold=2.0, sample_rate=16000, auto_start=False, text=tr("Cliquez pour parler, puis attendre 2sec."), \
|
291 |
+
recording_color="#e8b62c", neutral_color="#1ec3bc", icon_size="6x",)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
292 |
|
293 |
+
if audio_bytes:
|
294 |
+
# st.write("**"+tr("Vendeur")+" :**\n")
|
295 |
+
# Fonction pour générer et jouer le texte en speech
|
296 |
+
st.audio(audio_bytes, format="audio/wav", autoplay=False)
|
297 |
+
try:
|
298 |
+
detection = False
|
299 |
+
if detection:
|
300 |
+
# Create a BytesIO object from the audio stream
|
301 |
+
audio_stream_bytesio = io.BytesIO(audio_bytes)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
302 |
|
303 |
+
# Read the WAV stream using wavio
|
304 |
+
wav = wavio.read(audio_stream_bytesio)
|
305 |
+
|
306 |
+
# Extract the audio data from the wavio.Wav object
|
307 |
+
audio_data = wav.data
|
308 |
+
|
309 |
+
# Convert the audio data to a NumPy array
|
310 |
+
audio_input = np.array(audio_data, dtype=np.float32)
|
311 |
+
audio_input = np.mean(audio_input, axis=1)/32768
|
312 |
+
|
313 |
+
result = model_speech.transcribe(audio_input)
|
314 |
+
Lang_detected = result["language"]
|
315 |
+
query = result["text"]
|
316 |
+
|
317 |
+
else:
|
318 |
+
# Avec l'aide de la bibliothèque speech_recognition de Google
|
319 |
+
Lang_detected = st.session_state['Language']
|
320 |
+
# Transcription google
|
321 |
+
audio_stream = sr.AudioData(audio_bytes, 32000, 2)
|
322 |
+
r = sr.Recognizer()
|
323 |
+
query = r.recognize_google(audio_stream, language = Lang_detected)
|
324 |
+
|
325 |
+
# Transcription
|
326 |
+
# st.write("**"+tr("Vendeur :")+"** "+query)
|
327 |
+
with st.chat_message("user"):
|
328 |
+
st.markdown(query)
|
329 |
+
st.write("")
|
330 |
|
331 |
+
if query != "":
|
332 |
+
input_messages = [HumanMessage(query)]
|
333 |
+
output = app.invoke(
|
334 |
+
{"messages": input_messages, "language": language},
|
335 |
+
config,
|
336 |
+
)
|
337 |
+
#with st.chat_message("user"):
|
338 |
+
# Add user message to chat history
|
339 |
+
st.session_state.messages.append({"role": "user", "content": query})
|
340 |
+
|
341 |
+
# Récupération de la réponse
|
342 |
+
custom_sentence = output["messages"][-1].content
|
343 |
+
|
344 |
+
# Joue l'audio
|
345 |
+
l = st.session_state['Language']
|
346 |
+
play_audio(custom_sentence,l , 1)
|
347 |
+
|
348 |
+
# st.write("**"+tr("Prospect :")+"** "+custom_sentence)
|
349 |
+
with st.chat_message("assistant"):
|
350 |
+
st.markdown(custom_sentence)
|
351 |
+
|
352 |
+
# Add user message to chat history
|
353 |
+
st.session_state.messages.append({"role": "assistant", "content": custom_sentence})
|
354 |
+
|
355 |
|
356 |
+
|
357 |
+
except KeyboardInterrupt:
|
358 |
+
st.write(tr("Arrêt de la reconnaissance vocale."))
|
359 |
+
except:
|
360 |
+
st.write(tr("Problème, essayer de nouveau.."))
|
361 |
+
st.write("")
|
362 |
+
# Ajouter un espace pour séparer les zones
|
363 |
+
# st.divider()
|
364 |
+
with col2:
|
365 |
+
# with st.container():
|
366 |
+
if query:
|
367 |
+
# Display chat messages from history on app rerun
|
368 |
+
|
369 |
+
for message in st.session_state.messages:
|
370 |
+
with st.chat_message(message["role"]):
|
371 |
+
st.markdown(message["content"])
|
372 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
373 |
st.write("")
|
374 |
st.write("")
|
375 |
st.write("")
|
tabs/intro.py
CHANGED
@@ -24,12 +24,15 @@ def run():
|
|
24 |
st.title(tr(title))
|
25 |
st.markdown('''
|
26 |
## **'''+tr("Système d'aide à la mise en oeuvre d'une Proposition de Valeur en entreprise")+'''**
|
27 |
-
|
28 |
''')
|
29 |
-
st.header("**"+tr("A propos")+"**")
|
30 |
st.markdown(tr(
|
31 |
"""
|
32 |
-
|
|
|
|
|
|
|
|
|
33 |
""")
|
34 |
, unsafe_allow_html=True)
|
35 |
|
|
|
24 |
st.title(tr(title))
|
25 |
st.markdown('''
|
26 |
## **'''+tr("Système d'aide à la mise en oeuvre d'une Proposition de Valeur en entreprise")+'''**
|
27 |
+
------------------------------------------------------------------------------------
|
28 |
''')
|
|
|
29 |
st.markdown(tr(
|
30 |
"""
|
31 |
+
<h4>
|
32 |
+
Bienvenue dans le fabuleux univers de Value Props.<br>
|
33 |
+
Decouvrez et testez ici les futures fonctionnalités que la plateforme souhaite vous proposer.<br>
|
34 |
+
N'hesitez pas à nous faire part de vos commentaires en les envoyant à m.h.vincent@icloud.com<br>
|
35 |
+
</h4>
|
36 |
""")
|
37 |
, unsafe_allow_html=True)
|
38 |
|
translate_app.py
CHANGED
@@ -18,7 +18,9 @@ def trad(message,l):
|
|
18 |
return "Problème de traduction.."
|
19 |
|
20 |
def tr(message):
|
21 |
-
if 'Language' not in st.session_state:
|
|
|
|
|
22 |
else: l= st.session_state['Language']
|
23 |
if l == 'fr': return message
|
24 |
else: message = message.replace(":red[**","").replace("**]","")
|
|
|
18 |
return "Problème de traduction.."
|
19 |
|
20 |
def tr(message):
|
21 |
+
if 'Language' not in st.session_state:
|
22 |
+
l = 'fr'
|
23 |
+
st.session_state['Language'] = l
|
24 |
else: l= st.session_state['Language']
|
25 |
if l == 'fr': return message
|
26 |
else: message = message.replace(":red[**","").replace("**]","")
|