|
import os |
|
import json |
|
import bcrypt |
|
import chainlit as cl |
|
from chainlit.input_widget import TextInput, Select, Switch, Slider |
|
from chainlit import user_session |
|
from literalai import LiteralClient |
|
literal_client = LiteralClient(api_key=os.getenv("LITERAL_API_KEY")) |
|
|
|
from operator import itemgetter |
|
from pinecone import Pinecone |
|
from langchain_community.embeddings import HuggingFaceEmbeddings |
|
from langchain_community.llms import HuggingFaceEndpoint |
|
from langchain.memory import ConversationBufferMemory |
|
from langchain.schema import StrOutputParser |
|
from langchain.schema.runnable import Runnable |
|
from langchain.schema.runnable.config import RunnableConfig |
|
from langchain.schema.runnable import Runnable, RunnablePassthrough, RunnableLambda |
|
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder |
|
from langchain_core.prompts import PromptTemplate |
|
|
|
@cl.password_auth_callback |
|
def auth_callback(username: str, password: str): |
|
auth = json.loads(os.environ['CHAINLIT_AUTH_LOGIN']) |
|
ident = next(d['ident'] for d in auth if d['ident'] == username) |
|
pwd = next(d['pwd'] for d in auth if d['ident'] == username) |
|
resultLogAdmin = bcrypt.checkpw(username.encode('utf-8'), bcrypt.hashpw(ident.encode('utf-8'), bcrypt.gensalt())) |
|
resultPwdAdmin = bcrypt.checkpw(password.encode('utf-8'), bcrypt.hashpw(pwd.encode('utf-8'), bcrypt.gensalt())) |
|
resultRole = next(d['role'] for d in auth if d['ident'] == username) |
|
if resultLogAdmin and resultPwdAdmin and resultRole == "admindatapcc": |
|
return cl.User( |
|
identifier=ident + " : 🧑💼 Admin Datapcc", metadata={"role": "admin", "provider": "credentials"} |
|
) |
|
elif resultLogAdmin and resultPwdAdmin and resultRole == "userdatapcc": |
|
return cl.User( |
|
identifier=ident + " : 🧑🎓 User Datapcc", metadata={"role": "user", "provider": "credentials"} |
|
) |
|
|
|
@cl.author_rename |
|
def rename(orig_author: str): |
|
rename_dict = {"LLMMathChain": "Albert Einstein", "Doc Chain Assistant": "Assistant Reviewstream"} |
|
return rename_dict.get(orig_author, orig_author) |
|
|
|
@cl.set_chat_profiles |
|
async def chat_profile(): |
|
return [ |
|
cl.ChatProfile(name="Reviewstream",markdown_description="Requêter sur les publications de recherche",icon="/public/logo-ofipe.jpg",), |
|
cl.ChatProfile(name="Imagestream",markdown_description="Requêter sur un ensemble d'images",icon="./public/logo-ofipe.jpg",), |
|
] |
|
|
|
@cl.on_chat_start |
|
async def start(): |
|
await cl.Message(f"> REVIEWSTREAM").send() |
|
await cl.Message(f"Nous avons le plaisir de vous accueillir dans l'application de recherche et d'analyse des publications.").send() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
settings = await cl.ChatSettings( |
|
[ |
|
Select( |
|
id="Model", |
|
label="Publications de recherche", |
|
values=["---", "HAL", "Persée"], |
|
initial_index=0, |
|
), |
|
] |
|
).send() |
|
|
|
cl.user_session.set("memory", ConversationBufferMemory(return_messages=True)) |
|
memory = cl.user_session.get("memory") |
|
template = """<s>[INST] Vous êtes un chercheur de l'enseignement supérieur et vous êtes doué pour faire des analyses d'articles de recherche sur les thématiques liées à la pédagogie, en fonction des critères définis ci-avant. |
|
|
|
En fonction des informations suivantes et du contexte suivant seulement et strictement, répondez en langue française strictement à la question ci-dessous à partir du contexte ci-dessous. Si vous ne pouvez pas répondre à la question sur la base des informations, dites que vous ne trouvez pas de réponse ou que vous ne parvenez pas à trouver de réponse. Essayez donc de comprendre en profondeur le contexte et répondez uniquement en vous basant sur les informations fournies. Ne générez pas de réponses non pertinentes. |
|
{context} |
|
{question} [/INST] </s> |
|
""" |
|
|
|
os.environ['HUGGINGFACEHUB_API_TOKEN'] = os.environ['HUGGINGFACEHUB_API_TOKEN'] |
|
repo_id = "mistralai/Mixtral-8x7B-Instruct-v0.1" |
|
|
|
model = HuggingFaceEndpoint( |
|
repo_id=repo_id, max_new_tokens=8000, temperature=1.0, task="text2text-generation", streaming=True |
|
) |
|
|
|
prompt = ChatPromptTemplate.from_messages( |
|
[ |
|
( |
|
"system", |
|
f"Contexte : Vous êtes un chercheur de l'enseignement supérieur et vous êtes doué pour faire des analyses d'articles de recherche sur les thématiques liées à la pédagogie. En fonction des informations suivantes et du contexte suivant seulement et strictement.", |
|
), |
|
MessagesPlaceholder(variable_name="history"), |
|
("human", "Contexte : {context}, réponds à la question suivante de la manière la plus pertinente, la plus exhaustive et la plus détaillée possible. {question}."), |
|
] |
|
) |
|
runnable = ( |
|
RunnablePassthrough.assign( |
|
history=RunnableLambda(memory.load_memory_variables) | itemgetter("history") |
|
) |
|
| prompt |
|
| model |
|
) |
|
cl.user_session.set("runnable", runnable) |
|
return runnable |
|
|
|
@cl.on_message |
|
async def main(message: cl.Message): |
|
os.environ['PINECONE_API_KEY'] = os.environ['PINECONE_API_KEY'] |
|
embeddings = HuggingFaceEmbeddings() |
|
index_name = "all-venus" |
|
pc = Pinecone( |
|
api_key=os.environ['PINECONE_API_KEY'] |
|
) |
|
index = pc.Index(index_name) |
|
xq = embeddings.embed_query(message.content) |
|
xc = index.query(vector=xq, filter={"categorie": {"$eq": "bibliographie-OPP-DGDIN"}},top_k=150, include_metadata=True) |
|
context_p = "" |
|
for result in xc['matches']: |
|
context_p = context_p + result['metadata']['text'] |
|
|
|
memory = cl.user_session.get("memory") |
|
runnable = cl.user_session.get("runnable") |
|
|
|
msg = cl.Message(author="Assistant Reviewstream",content="") |
|
async for chunk in runnable.astream({"question": message.content, "context":context_p}, |
|
config=RunnableConfig(callbacks=[cl.AsyncLangchainCallbackHandler(stream_final_answer=True)])): |
|
await msg.stream_token(chunk) |
|
|
|
await msg.send() |
|
memory.chat_memory.add_user_message(message.content) |
|
memory.chat_memory.add_ai_message(msg.content) |