cdupland commited on
Commit
fc3050e
·
1 Parent(s): d7edfc3

Add dotenv support and enhance agent selection in app.py; refactor get_retreive_answer to handle multiple namespaces in vectore_store.py

Browse files
Files changed (2) hide show
  1. app.py +82 -14
  2. vectore_store.py +81 -20
app.py CHANGED
@@ -7,11 +7,14 @@ from langchain.prompts import PromptTemplate
7
  from pinecone import Pinecone, ServerlessSpec
8
 
9
  from vectore_store import get_retreive_answer
 
10
 
 
11
 
12
  PINECONE_API_KEY = os.environ.get("PINECONE_API_KEY")
13
  index_name = os.environ.get("PINECONE_INDEX_NAME")
14
 
 
15
  pc = Pinecone(api_key=PINECONE_API_KEY)
16
 
17
 
@@ -29,18 +32,6 @@ if index_name not in existing_indexes:
29
 
30
  index = pc.Index(index_name)
31
 
32
- # Créez un modèle OpenAI
33
- llm = ChatOpenAI(model="gpt-4o-mini")
34
-
35
- # Créez un template de prompt pour l'IA
36
- prompt = PromptTemplate(
37
- input_variables=["question"],
38
- template="Voici une question : {question}. Réponds de manière concise et claire."
39
- )
40
-
41
- # Chaîne qui combine le modèle LLM et le prompt
42
- llm_chain = prompt | llm # Nouvelle façon d'utiliser LLMChain
43
-
44
  # Initialiser l'historique s'il n'existe pas déjà
45
  if "history" not in st.session_state:
46
  st.session_state["history"] = []
@@ -49,6 +40,79 @@ if "history" not in st.session_state:
49
  st.title("Application LLM avec LangChain")
50
  st.write("Posez une question au modèle de langage et obtenez une réponse.")
51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  # Champ pour entrer la question
53
  question = st.text_input("Votre question :")
54
 
@@ -56,7 +120,7 @@ question = st.text_input("Votre question :")
56
  if st.button("Envoyer"):
57
  if question:
58
 
59
- context = get_retreive_answer(index, namespace="chat", prompt=question)
60
  if not context:
61
  print("no context found for prompt reormatting")
62
 
@@ -64,9 +128,13 @@ if st.button("Envoyer"):
64
  print(chunk.metadata)
65
  chunk_name = chunk.metadata["filename"]
66
 
 
 
 
 
67
 
68
  # Utilisation de la chaîne pour obtenir une réponse
69
- response = llm_chain.invoke({"question": question, "context": context}) # Utilisation de invoke() au lieu de run()
70
 
71
  # Ajouter la question et la réponse à l'historique
72
  st.session_state["history"].append({"question": question, "response": response.content})
 
7
  from pinecone import Pinecone, ServerlessSpec
8
 
9
  from vectore_store import get_retreive_answer
10
+ from dotenv import load_dotenv
11
 
12
+ load_dotenv()
13
 
14
  PINECONE_API_KEY = os.environ.get("PINECONE_API_KEY")
15
  index_name = os.environ.get("PINECONE_INDEX_NAME")
16
 
17
+ print(PINECONE_API_KEY)
18
  pc = Pinecone(api_key=PINECONE_API_KEY)
19
 
20
 
 
32
 
33
  index = pc.Index(index_name)
34
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  # Initialiser l'historique s'il n'existe pas déjà
36
  if "history" not in st.session_state:
37
  st.session_state["history"] = []
 
40
  st.title("Application LLM avec LangChain")
41
  st.write("Posez une question au modèle de langage et obtenez une réponse.")
42
 
43
+ # Sélectionnez l'agent via un bouton radio
44
+ # Sélectionnez le type d'agent via un bouton radio
45
+ agent_type = st.radio(
46
+ "Choisissez le type d'agent :",
47
+ ("Agent IA Service Client Augmenté", "Agent IA Produit Augmenté", "Agent Campaign Marketing"), # "Agent IA Commercial Augmenté",
48
+ index=0 # "Agent IA Service Client Augmenté" est sélectionné par défaut
49
+ )
50
+
51
+ # Configuration des templates et namespaces en fonction de l'agent sélectionné
52
+ # Configuration des templates et namespaces en fonction de l'agent sélectionné
53
+ if agent_type == "Agent IA Service Client Augmenté":
54
+ namespaces = ["chat","tic_email"]
55
+ prompt_template = PromptTemplate(
56
+ input_variables=["question","context","messages"],
57
+ template=(
58
+ "Votre rôle est d’agir comme un Agent IA de Service Client Augmenté. Vous devez :\n\n"
59
+ "1. Anticiper les besoins et insatisfactions des clients :\n"
60
+ " - Identifiez les questions et préoccupations potentielles des clients avant même qu’ils ne les expriment.\n\n"
61
+ "2. Pré-générer des réponses adaptées :\n"
62
+ " - En fonction des questions les plus fréquentes et des problèmes courants, proposez des réponses prédéfinies qui peuvent être facilement adaptées aux situations spécifiques.\n\n"
63
+ "3. Améliorer les processus et formations internes :\n"
64
+ " - Fournissez des suggestions basées sur les retours clients pour optimiser les processus internes de service client et améliorer les formations des agents.\n\n"
65
+ "### Objectif :\n"
66
+ "Fournir des réponses réactives et de qualité, afin d’accroître la satisfaction client et d’optimiser les performances du service.\n"
67
+ "Sachant le context suivant: {context}, et l'historique de la conversation: {messages}, {question}\n"
68
+ )
69
+ )
70
+ elif agent_type == "Agent IA Produit Augmenté":
71
+ namespaces = ["chat","tic_email"]
72
+ prompt_template = PromptTemplate(
73
+ input_variables=["question","context","messages"],
74
+ template=(
75
+ "Votre rôle est d’agir comme un Agent IA Produit Augmenté et responsable du service Produit :\n\n"
76
+ "1. Fournir des données objectives pour les réunions de feedback :\n"
77
+ " - Catégorisation, Quantification et Reporting des données liées à nos produits et services.\n\n"
78
+ "2. Identifier rapidement les tendances et opportunités :\n"
79
+ " - Analysez les données pour déceler les tendances et proposer des améliorations.\n\n"
80
+ "3. Détecter et résoudre les problèmes en temps réel :\n"
81
+ " - Surveillez en continu la satisfaction des clients et identifiez les problèmes potentiels.\n\n"
82
+ "### Objectif :\n"
83
+ "Aider à prioriser les actions basées sur des données, gagner du temps, et améliorer la satisfaction client.\n"
84
+ "Sachant le context suivant: {context}, et l'historique de la conversation: {messages}, {question}\n"
85
+ )
86
+ )
87
+ # elif agent_type == "Agent IA Commercial Augmenté":
88
+ # namespaces = ["chat","tic_email"]
89
+ # prompt_template = PromptTemplate(
90
+ # input_variables=["question"],
91
+ # template=(
92
+ # "Votre rôle est d’agir comme un Agent IA Commercial Augmenté. Vous devez :\n\n"
93
+ # "1. Détection de pistes business dans le CRM :\n"
94
+ # " - Analysez les données du CRM pour identifier les opportunités de vente qui sont actuellement détectées manuellement.\n\n"
95
+ # "### Objectif :\n"
96
+ # "Automatiser la détection des pistes commerciales et augmenter l'efficacité des processus de vente."
97
+ # )
98
+ # )
99
+ elif agent_type == "Agent Campaign Marketing":
100
+ namespaces = ["campaigns"]
101
+ prompt_template = PromptTemplate(
102
+ input_variables=["question","context","messages"],
103
+ template=(
104
+ "Votre rôle est d’agir comme un Agent IA de Campaign Marketing.\n\n"
105
+ "Proposes des campagnes marketing qualitatives, ciblées et efficace.\n"
106
+ "Sachant le context suivant: {context}, et l'historique de la conversation: {messages}, {question}\n"
107
+ )
108
+ )
109
+
110
+ # Créez un modèle OpenAI
111
+ llm = ChatOpenAI(model="gpt-4o-mini")
112
+
113
+ # Chaîne qui combine le modèle LLM et le prompt
114
+ llm_chain = prompt_template | llm # Nouvelle façon d'utiliser LLMChain
115
+
116
  # Champ pour entrer la question
117
  question = st.text_input("Votre question :")
118
 
 
120
  if st.button("Envoyer"):
121
  if question:
122
 
123
+ context = get_retreive_answer(index, namespaces=namespaces, prompt=question)
124
  if not context:
125
  print("no context found for prompt reormatting")
126
 
 
128
  print(chunk.metadata)
129
  chunk_name = chunk.metadata["filename"]
130
 
131
+ if st.session_state["history"]:
132
+ messages = st.session_state["history"]
133
+ else:
134
+ messages = []
135
 
136
  # Utilisation de la chaîne pour obtenir une réponse
137
+ response = llm_chain.invoke({"question": question, "context": context, "messages": messages}) # Utilisation de invoke() au lieu de run()
138
 
139
  # Ajouter la question et la réponse à l'historique
140
  st.session_state["history"].append({"question": question, "response": response.content})
vectore_store.py CHANGED
@@ -172,35 +172,96 @@ def get_vectorstore_from_json(json_file, namespace, index):
172
  except Exception as e:
173
  print(f"Error: {e}")
174
  return False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
 
176
 
177
- def get_retreive_answer(index,namespace,prompt):
178
  try:
179
-
180
  embedding = OpenAIEmbeddings(model="text-embedding-3-large")
181
- vector_store_chat = PineconeVectorStore(index=index, embedding=embedding,namespace=namespace)
182
 
183
- retriever_chat = vector_store_chat.as_retriever(
184
- search_type="similarity_score_threshold",
185
- search_kwargs={"k": 3, "score_threshold": 0.6},
186
- )
187
-
188
- vector_store_tic = PineconeVectorStore(index=index, embedding=embedding,namespace=namespace)
 
 
 
 
 
189
 
190
- retriever_tic = vector_store_tic.as_retriever(
191
- search_type="similarity_score_threshold",
192
- search_kwargs={"k": 3, "score_threshold": 0.6},
193
- )
194
 
195
- response = retriever_chat.invoke(prompt) + retriever_tic.invoke(prompt)
 
 
 
 
196
 
197
- if response:
198
- print("found enterprise context")
199
  else:
200
- print("no enterprise context")
 
201
 
202
- return response
203
-
204
  except Exception as e:
205
  print(e)
206
- return False
 
172
  except Exception as e:
173
  print(f"Error: {e}")
174
  return False
175
+
176
+
177
+ def get_vectorstore_from_json_data(json_data, namespace, index):
178
+ """
179
+ Fonction pour traiter un fichier JSON et insérer les embeddings dans Pinecone.
180
+
181
+ Parameters:
182
+ - json_data: Chemin vers le fichier JSON.
183
+ - namespace: Namespace Pinecone pour stocker les vecteurs.
184
+ - index: Objet d'index Pinecone.
185
+
186
+ Returns:
187
+ - dict avec filename_id en cas de succès ou False en cas d'échec.
188
+ """
189
+ try:
190
+ # Initialiser le modèle d'embeddings OpenAI
191
+ embedding = OpenAIEmbeddings(model="text-embedding-3-large") # Remplacez par votre choix de modèle
192
+ vector_store = PineconeVectorStore(index=index, embedding=embedding, namespace=namespace)
193
+
194
+ # Nettoyer le nom de fichier (pour des IDs uniques)
195
+ filename = json_data['_id']
196
+ # clean_filename = filename.replace(" ", "_").replace("-", "_").replace(".", "_").replace("/", "_").replace("\\", "_").strip()
197
+
198
+ # Préparer les documents et UUIDs
199
+ documents = []
200
+ uuids = []
201
+
202
+ # # Itérer à travers chaque entrée du JSON
203
+ # for i, entry in enumerate(data):
204
+ # # Concaténer toutes les propriétés de l'entrée
205
+ # combined_text = " ".join(str(value) for value in entry.values())
206
+
207
+ text_chunks = get_text_chunks(json.dumps(json_data, indent=4))
208
+
209
+ for j, chunk in enumerate(text_chunks):
210
+ # Créer un objet Document pour chaque morceau de texte combiné
211
+ document = Document(
212
+ page_content=chunk,
213
+ metadata={"filename": filename, "filename_id": filename, "chunk_index": j} # Ajout de toutes les propriétés de l'entrée
214
+ )
215
+
216
+ # Générer un ID unique pour chaque document (entrée)
217
+ uuid = f"{filename}_{j}" # Ajouter l'index à l'ID unique
218
+ print(uuid)
219
+ uuids.append(uuid)
220
+ documents.append(document)
221
+
222
+ # Insérer les documents dans Pinecone
223
+ vector_store.add_documents(documents=documents, ids=uuids)
224
+
225
+ # Retourner l'ID de fichier après insertion réussie
226
+ return {"filename_id": filename}
227
+
228
+ except Exception as e:
229
+ print(f"Error: {e}")
230
+ return False
231
 
232
 
233
+ def get_retreive_answer(index, namespaces, prompt):
234
  try:
 
235
  embedding = OpenAIEmbeddings(model="text-embedding-3-large")
236
+ responses = []
237
 
238
+ for namespace in namespaces:
239
+ print(f"Searching for context in namespace '{namespace}'")
240
+
241
+ # Initialiser le vector store avec le namespace courant
242
+ vector_store = PineconeVectorStore(index=index, embedding=embedding, namespace=namespace)
243
+
244
+ # Configurer le retriever
245
+ retriever = vector_store.as_retriever(
246
+ search_type="similarity_score_threshold",
247
+ search_kwargs={"k": 20, "score_threshold": 0.6},
248
+ )
249
 
250
+ # Récupérer la réponse pour le namespace courant
251
+ response = retriever.invoke(prompt)
 
 
252
 
253
+ if response:
254
+ print(f"Found context in namespace '{namespace}'")
255
+ responses += response
256
+ else:
257
+ print(f"No context found in namespace '{namespace}'")
258
 
259
+ if responses:
260
+ return responses
261
  else:
262
+ print("No context found in any namespace")
263
+ return []
264
 
 
 
265
  except Exception as e:
266
  print(e)
267
+ return False