File size: 6,288 Bytes
f15d84d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
import pandas as pd
import streamlit as st
from langchain.docstore.document import Document
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
from langchain_community.llms import HuggingFaceHub
import os
from huggingface_hub import HfApi

# Configuration Streamlit
st.set_page_config(page_title="Assistant Support Client", page_icon="🤖", layout="wide")

# Récupération du token depuis les secrets de l'espace
HUGGINGFACE_API_TOKEN = st.secrets["HUGGINGFACE_API_TOKEN"]

# Création du dossier data s'il n'existe pas
DATA_DIR = "data"
os.makedirs(DATA_DIR, exist_ok=True)
EMBEDDINGS_FILE = os.path.join(DATA_DIR, "faq_embeddings.pkl")

# Configuration du client HF Hub
hf_api = HfApi(token=HUGGINGFACE_API_TOKEN)

@st.cache_resource
def load_faq_data():
    """Charge les données FAQ depuis un CSV"""
    try:
        df = pd.read_csv('data/customer_support_faq.csv')
        documents = []
        for _, row in df.iterrows():
            question = row['question']
            answer = row['answer']
            documents.append(Document(page_content=f"Q: {question} A: {answer}"))
        return documents
    except Exception as e:
        st.error(f"Erreur lors du chargement des données FAQ: {str(e)}")
        return []

@st.cache_resource
def initialize_embeddings(_documents):
    """Initialise ou charge les embeddings"""
    try:
        embeddings = HuggingFaceEmbeddings(
            model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"
        )
        vector_store = FAISS.from_documents(_documents, embeddings)
        return vector_store
    except Exception as e:
        st.error(f"Erreur lors de l'initialisation des embeddings: {str(e)}")
        return None

@st.cache_resource
def initialize_qa_chain(vector_store):
    """Initialise la chaîne de question-réponse"""
    try:
        # Initialisation du modèle
        llm = HuggingFaceHub(
            repo_id="bigscience/bloom",  # Vous pouvez changer le modèle
            huggingfacehub_api_token=HUGGINGFACE_API_TOKEN,
            model_kwargs={"temperature": 0.5, "max_length": 512}
        )

        # Template de prompt
        prompt_template = """Utilise le contexte suivant pour répondre à la question.
        Si la réponse n'est pas dans le contexte, réponds "Je ne sais pas."
        
        Contexte: {context}
        
        Question: {question}
        
        Réponse:"""

        PROMPT = PromptTemplate(
            template=prompt_template,
            input_variables=["context", "question"]
        )

        # Création de la chaîne QA
        qa_chain = RetrievalQA.from_chain_type(
            llm=llm,
            chain_type="stuff",
            retriever=vector_store.as_retriever(),
            chain_type_kwargs={"prompt": PROMPT},
            return_source_documents=False,
        )
        
        return qa_chain
    except Exception as e:
        st.error(f"Erreur lors de l'initialisation de la chaîne QA: {str(e)}")
        return None

# CSS personnalisé
st.markdown("""
    <style>
    .stApp {
        background-color: #1E1E1E;
    }
    .user_message {
        color: white;
        background-color: #F85046;
        padding: 10px;
        border-radius: 10px;
        margin: 10px 20px 10px auto;
        text-align: left;
        word-wrap: break-word;
        display: inline-block;
        max-width: 80%;
    }
    .bot_message {
        color: #1E1E1E;
        background-color: white;
        padding: 10px;
        border-radius: 10px;
        margin: 10px 20px;
        text-align: left;
        word-wrap: break-word;
        display: inline-block;
        max-width: 80%;
    }
    .header {
        font-size: 40px;
        color: white;
        padding: 20px;
        text-align: center;
        border-radius: 10px;
        font-weight: bold;
    }
    .the_text {
        color: #F9F8FD;
        font-size: 20px;
        margin-top: 20px;
    }
    .the_conv {
        color: #F9F8FD;
        font-size: 30px;
    }
    </style>
""", unsafe_allow_html=True)

# Interface utilisateur
st.markdown('<div class="header">Assistant Support Client</div>', unsafe_allow_html=True)
st.markdown('<div class="the_text">Posez votre question ci-dessous :</div>', unsafe_allow_html=True)

# Initialisation de la session state
if 'conversation' not in st.session_state:
    st.session_state.conversation = []

# Chargement des composants
documents = load_faq_data()
if documents:
    vector_store = initialize_embeddings(documents)
    if vector_store:
        qa_chain = initialize_qa_chain(vector_store)
        if qa_chain:
            # Champ de saisie
            user_query = st.text_input("", key="user_input")

            # Bouton pour obtenir la réponse
            if st.button("Obtenir une réponse", key="submit"):
                if user_query:
                    try:
                        # Obtention de la réponse
                        response = qa_chain({"query": user_query})
                        answer = response["result"]
                        
                        # Ajout à l'historique
                        st.session_state.conversation.append({
                            "user": user_query,
                            "bot": answer
                        })

                        # Affichage de la conversation
                        st.markdown('<div class="the_conv">Conversation :</div>', unsafe_allow_html=True)
                        for chat in st.session_state.conversation:
                            st.markdown(
                                f'<div class="user_message">🤵 : {chat["user"]}</div>',
                                unsafe_allow_html=True
                            )
                            st.markdown(
                                f'<div class="bot_message">🤖 : {chat["bot"]}</div>',
                                unsafe_allow_html=True
                            )
                    except Exception as e:
                        st.error(f"Erreur lors du traitement de la requête: {str(e)}")
                else:
                    st.warning("Veuillez entrer une question.")