Ludovicollin commited on
Commit
29b90eb
·
verified ·
1 Parent(s): 5758054

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +61 -162
main.py CHANGED
@@ -1,178 +1,77 @@
1
- import os
2
- import time
3
- from operator import itemgetter
4
- from collections import Counter
5
  from langchain.schema.runnable import Runnable, RunnablePassthrough, RunnableLambda
6
  from langchain.schema.runnable.config import RunnableConfig
7
- from langchain.embeddings import HuggingFaceEmbeddings
8
- from langchain.chains import ConversationalRetrievalChain
9
- from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
10
- from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
11
  from langchain.schema import StrOutputParser
12
- from langchain.chains.qa_with_sources import load_qa_with_sources_chain
13
- from langchain_pinecone import PineconeVectorStore
14
-
15
- from pinecone import Pinecone
16
- from langchain.memory import ChatMessageHistory, ConversationBufferMemory
17
  import pandas as pd
18
  import numpy as np
19
- from langchain_core.messages import HumanMessage, SystemMessage
20
- from langchain_core.prompts.chat import (
21
- ChatPromptTemplate,
22
- HumanMessagePromptTemplate,
23
- SystemMessagePromptTemplate,
24
- )
25
- from langchain_openai import ChatOpenAI
26
  import chainlit as cl
27
- from chainlit.input_widget import TextInput
28
- from chainlit import user_session
29
- from offres_emploi import Api
30
- from offres_emploi.utils import dt_to_str_iso
31
- import datetime
32
- import bcrypt
33
- import json
34
 
35
- @cl.password_auth_callback
36
- def auth_callback(username: str, password: str):
37
- auth = json.loads(os.environ['CHAINLIT_AUTH_LOGIN'])
38
- ident = next(d['ident'] for d in auth if d['ident'] == username)
39
- pwd = next(d['pwd'] for d in auth if d['ident'] == username)
40
- resultLogAdmin = bcrypt.checkpw(username.encode('utf-8'), bcrypt.hashpw(ident.encode('utf-8'), bcrypt.gensalt()))
41
- resultPwdAdmin = bcrypt.checkpw(password.encode('utf-8'), bcrypt.hashpw(pwd.encode('utf-8'), bcrypt.gensalt()))
42
- resultRole = next(d['role'] for d in auth if d['ident'] == username)
43
- if resultLogAdmin and resultPwdAdmin and resultRole == "admindatapcc":
44
- return cl.User(
45
- identifier=ident + " : 🧑‍💼 Admin Datapcc", metadata={"role": "admin", "provider": "credentials"}
46
- )
47
- elif resultLogAdmin and resultPwdAdmin and resultRole == "userdatapcc":
48
- return cl.User(
49
- identifier=ident + " : 🧑‍🎓 User Datapcc", metadata={"role": "user", "provider": "credentials"}
50
- )
51
-
52
- os.environ["TOKENIZERS_PARALLELISM"] = os.environ["TOKENIZERS_PARALLELISM"]
53
- os.environ['OPENAI_API_KEY'] = os.environ['OPENAI_API_KEY']
54
 
 
 
55
  @cl.author_rename
56
  def rename(orig_author: str):
57
- rename_dict = {"DatapccSkillStream": "Datapcc", "ConversationalRetrievalChain": "Assistant conversationnel 💬", "Retriever": "Agent conversationnel", "StuffDocumentsChain": "Chaîne de documents", "LLMChain": "Agent", "ChatOpenAI": "IA🤖"}
58
  return rename_dict.get(orig_author, orig_author)
59
 
60
- @cl.action_callback("download")
61
- async def on_action(action):
62
- content = []
63
- content.append(action.value)
64
- arrayContent = np.array(content)
65
- df = pd.DataFrame(arrayContent)
66
- with open('./' + action.description + '.txt', 'wb') as csv_file:
67
- df.to_csv(path_or_buf=csv_file, index=False,header=False, encoding='utf-8')
68
- elements = [
69
- cl.File(
70
- name= action.description + ".txt",
71
- path="./" + action.description + ".txt",
72
- display="inline",
73
- ),
74
- ]
75
- await cl.Message(
76
- author="Datapcc 🌐🌐🌐", content="[Lien] 🔗", elements=elements
77
- ).send()
78
- await action.remove()
79
-
80
- def retriever_to_cache():
81
- os.environ['PINECONE_API_KEY'] = os.environ['PINECONE_API_KEY']
82
- os.environ['PINECONE_ENVIRONMENT'] = "us-west4-gcp-free"
83
- index_name = os.environ['PINECONE_INDEX_NAME']
84
- embeddings = HuggingFaceEmbeddings()
85
- vectorstore = PineconeVectorStore(
86
- index_name=index_name, embedding=embeddings
87
- )
88
- retriever = vectorstore.as_retriever(search_type="similarity_score_threshold", search_kwargs={"score_threshold": .7, "k": 30,"filter": {'categorie': {'$eq': 'OF'}}})
89
- return retriever
90
-
91
- @cl.set_chat_profiles
92
- async def chat_profile():
93
- return [
94
- cl.ChatProfile(name="OF - Offre de formation",markdown_description="Requêter sur l'offre de formation - OF",icon="./public/favicon.png",),
95
- ]
96
  @cl.on_chat_start
97
- async def start():
98
- chat_profile = cl.user_session.get("chat_profile")
99
- chatProfile = chat_profile.split(' - ')
100
-
101
- if chatProfile[0] == 'OF':
102
- app_user = cl.user_session.get("user")
103
- welcomeUser = app_user.identifier
104
- welcomeUserArray = welcomeUser.split('@')
105
- welcomeUserStr = welcomeUserArray[0].replace('.',' ')
106
- await cl.Message(f"> Bonjour {welcomeUserStr}").send()
107
- await cl.Message(
108
- author="Datapcc 🌐🌐🌐",content=f"✨ Commencez à poser vos questions sur les données \"{chat_profile}\"\n- Création de BCC à partir d'une liste de savoirs ou d'objectifs pédagogiques\n- Création du tableau de la version n°1 de la maquette de formation"
109
- ).send()
110
 
111
- from langchain_core.prompts.prompt import PromptTemplate
112
-
113
- _template = """Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question, in its original language.
 
 
 
 
114
 
115
- Chat History:
116
- {chat_history}
117
- Follow Up Input: {question}
118
- Standalone question:"""
119
- CONDENSE_QUESTION_PROMPT = PromptTemplate.from_template(_template)
120
-
121
- ########## Chain with streaming ##########
122
- message_history = ChatMessageHistory()
123
- memory = ConversationBufferMemory(
124
- memory_key="chat_history",
125
- output_key="answer",
126
- chat_memory=message_history,
127
- return_messages=True,
128
- )
129
- streaming_llm = ChatOpenAI(
130
- model_name = "gpt-4-1106-preview",
131
- streaming=True,
132
- temperature=1
133
- )
134
- qa = ConversationalRetrievalChain.from_llm(
135
- streaming_llm,
136
- memory=memory,
137
- chain_type="stuff",
138
- return_source_documents=True,
139
- verbose=False,
140
- retriever=retriever_to_cache()
141
- )
142
- cl.user_session.set("conversation_chain", qa)
143
-
144
  @cl.on_message
145
- async def main(message: cl.Message):
146
- chat_profile = cl.user_session.get("chat_profile")
147
- chatProfile = chat_profile.split(' - ')
148
- if chatProfile[0] == "OF":
149
- chain = cl.user_session.get("conversation_chain")
150
- cb = cl.AsyncLangchainCallbackHandler()
151
- res = await chain.acall("Contexte : Réponds à la question suivante de la manière la plus pertinente, la plus exhaustive et la plus détaillée possible, dans le contexte et les informations fournies. Question : " + message.content, callbacks=[cb])
152
- answer = res["answer"]
153
- source_documents = res["source_documents"]
154
-
155
- text_elements = []
156
- metadatas = ''
157
- if source_documents:
158
- for source_idx, source_doc in enumerate(source_documents):
159
- numSource = source_idx + 1
160
- source_name = f"Source n°{numSource}"
161
- text_elements.append(
162
- cl.Text(content="Formations : " + source_doc.metadata['ABREGE_LIBELLES'] + " " + source_doc.metadata['INTITULE'] + "\n\nROME : " + source_doc.metadata['CODES_ROME'] + "\nLibellés ROME : " + source_doc.metadata['LIBELLES_ROME'] + "\n\nActivités : " + source_doc.metadata['ACTIVITES_VISEES'].replace('œ','oe') + "\n\nEmplois accessibles : " + source_doc.metadata['TYPE_EMPLOI_ACCESSIBLES'] + "\n\nCompétences : " + source_doc.metadata['CAPACITES_ATTESTEES'].replace('œ','oe').replace('…','oe'), name=source_name)
163
- )
164
- source_names = [text_el.name for countMetadata, text_el in enumerate(text_elements) if countMetadata < 10]
165
- if source_names:
166
- metadatas += ', '.join(source_names)
167
- else:
168
- metadatas += "\n\nPas de source trouvée!"
169
-
170
- actions = [
171
- cl.Action(name="download", value="Question : " + message.content + "\n\nRéponse : " + answer, description="download_offre_formation")
172
- ]
173
-
174
- await cl.Message(author="Datapcc 🌐🌐🌐",content=answer).send()
175
- await cl.Message(author="Datapcc 🌐🌐🌐",content="Download", actions=actions).send()
176
-
177
- if metadatas:
178
- await cl.Message(author="Datapcc 🌐🌐🌐",content="Sources : " + metadatas, elements=text_elements).send()
 
1
+ from langchain_anthropic import ChatAnthropic
2
+ from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
3
+ from langchain.memory import ChatMessageHistory, ConversationBufferMemory
4
+ from langchain.schema import StrOutputParser
5
  from langchain.schema.runnable import Runnable, RunnablePassthrough, RunnableLambda
6
  from langchain.schema.runnable.config import RunnableConfig
 
 
 
 
7
  from langchain.schema import StrOutputParser
8
+ import os
 
 
 
 
9
  import pandas as pd
10
  import numpy as np
11
+
12
+ from langchain.agents.agent_types import AgentType
13
+ from langchain_experimental.agents.agent_toolkits import create_csv_agent
14
+
 
 
 
15
  import chainlit as cl
 
 
 
 
 
 
 
16
 
17
+ os.environ["ANTHROPIC_API_KEY"] = os.environ["ANTHROPIC_API_KEY"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
+ def library():
20
+ return "Exemple de requêtes sur les données de l'enquête.\n\nQ1 : Quels sont les équipements préférentiels des étudiant.e.s?\nQ2 : Quels sont les 3 outils numériques principaux de l'université pour le travail universitaire?\nQ3 : Quels sont les outils numériques de l'université préférés des étudiant.e.s?\nQ4 : Quels sont les réseaux sociaux préférés des étudiant.e.s?\nQ5 : Quels sont les outils numériques de l'université préférés des étudiant.e.s pour communiquer?\nQ6 : Quels sont les outils numériques de l'université préférés des étudiant.e.s pour le travail universitaire?\nQ7 : Quel est l'usage du mail de l'université?\nQ8 : Quel est l'usage de l'ENT de l'université?\nQ9 : Donne le pourcentage d'étudiant.e.s en licence3 qui utilise souvent Moodle?\nQ10 : Donne le pourcentage d'étudiant.e.s en licence1 qui utilise souvent le mail?\nQ11 : Donne le pourcentage d'étudiant.e.s en licence1 de la filière Sciences économiques qui utilise souvent le mail?\nQ12 : Pourquoi les étudiants utilisent WhatsApp?\nQ13 : Pourquoi les étudiants utilisent Discord?\nQ14 : Quels avantages représentent les outils numériques?\nQ15 : Quelles sont les principales difficultés?"
21
  @cl.author_rename
22
  def rename(orig_author: str):
23
+ rename_dict = {"AgentExecutor": "Agent conversationnel", "Error": "Réponse de l'assistant", "Datapcc Chain": "Copilot", "load_memory_variables": "Historique de conversation 💬", "Retriever": "Agent conversationnel", "StuffDocumentsChain": "Chaîne de documents", "LLMChain": "Agent", "ChatAnthropic": "Réponse de l'IA 🤖"}
24
  return rename_dict.get(orig_author, orig_author)
25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  @cl.on_chat_start
27
+ async def on_chat_start():
28
+ await cl.Message(f"> Votre assistant conversationnel vous permet d'analyser les données de l'enquête sur les usages du numérique par les étudiant.e.s Licence").send()
29
+ listPrompts_name = f"Liste des requêtes"
30
+ prompt_elements = []
31
+ prompt_elements.append(
32
+ cl.Text(content=library(), name=listPrompts_name)
33
+ )
34
+ await cl.Message(content="📚 Bibliothèque de questions : " + listPrompts_name, elements=prompt_elements).send()
35
+ await cl.Avatar(
36
+ name="You",
37
+ path="./logo-ofipe.jpg",
38
+ ).send()
 
39
 
40
+ agent = create_csv_agent(
41
+ ChatAnthropic(temperature=1,model_name="claude-3-sonnet-20240229"),
42
+ "./enquete.csv",
43
+ verbose=False,
44
+ agent_type=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
45
+ )
46
+ cl.user_session.set("runnable", agent)
47
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  @cl.on_message
49
+ async def on_message(message: cl.Message):
50
+ memory= cl.user_session.get("memory")
51
+ runnable = cl.user_session.get("runnable") # type: Runnable
52
+ cb = cl.AsyncLangchainCallbackHandler()
53
+ try:
54
+ res = await runnable.acall("Réponds en langue française à la question suivante :\n" + message.content + "\nDétaille la réponse en faisant une analyse complète.", callbacks=[cb])
55
+ await cl.Message(author="COPILOT",content=res['output']).send()
56
+ listPrompts_name = f"Liste des requêtes"
57
+ prompt_elements = []
58
+ prompt_elements.append(
59
+ cl.Text(content=library(), name=listPrompts_name)
60
+ )
61
+ await cl.Message(content="📚 Bibliothèque de questions : " + listPrompts_name, elements=prompt_elements).send()
62
+ except ValueError as e:
63
+ res = str(e)
64
+ resArray = res.split(":")
65
+ ans = ''
66
+ if str(res).find('parsing') != -1:
67
+ for i in range(2,len(resArray)):
68
+ ans += resArray[i]
69
+ await cl.Message(author="COPILOT",content=ans.replace("`","")).send()
70
+ listPrompts_name = f"Liste des requêtes"
71
+ prompt_elements = []
72
+ prompt_elements.append(
73
+ cl.Text(content=library(), name=listPrompts_name)
74
+ )
75
+ await cl.Message(content="📚 Bibliothèque de questions : " + listPrompts_name, elements=prompt_elements).send()
76
+ else:
77
+ await cl.Message(author="COPILOT",content="Reformulez votre requête, s'il vous plait 😃").send()