|
import streamlit as st |
|
from dotenv import load_dotenv |
|
from PyPDF2 import PdfReader |
|
from langchain.text_splitter import CharacterTextSplitter |
|
from langchain_community.embeddings import OpenAIEmbeddings |
|
from langchain_community.vectorstores import FAISS |
|
from langchain_community.chat_models import ChatOpenAI |
|
from langchain.llms import HuggingFaceHub |
|
from langchain import hub |
|
from langchain_core.output_parsers import StrOutputParser |
|
from langchain_core.runnables import RunnablePassthrough |
|
from langchain_community.document_loaders import WebBaseLoader |
|
import os |
|
|
|
from session import set_rag |
|
from partie_prenante_carte import complete_and_verify_url |
|
|
|
def get_docs_from_website(urls): |
|
loader = WebBaseLoader(urls, header_template={ |
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36', |
|
}) |
|
docs = loader.load() |
|
return docs |
|
|
|
def get_pdf_text(pdf_docs): |
|
text = "" |
|
for pdf in pdf_docs: |
|
pdf_reader = PdfReader(pdf) |
|
for page in pdf_reader.pages: |
|
text += page.extract_text() |
|
return text |
|
|
|
def get_text_chunks(text): |
|
text_splitter = CharacterTextSplitter( |
|
separator="\n", |
|
chunk_size=1000, |
|
chunk_overlap=200, |
|
length_function=len |
|
) |
|
chunks = text_splitter.split_text(text) |
|
return chunks |
|
|
|
def get_doc_chunks(docs): |
|
|
|
text_splitter = CharacterTextSplitter(separator='\n', |
|
chunk_size=500, |
|
chunk_overlap=40) |
|
|
|
docs = text_splitter.split_documents(docs) |
|
return docs |
|
|
|
def get_vectorstore_from_docs(doc_chunks): |
|
embedding = OpenAIEmbeddings(model="text-embedding-3-small") |
|
vectorstore = FAISS.from_documents(documents=doc_chunks, embedding=embedding) |
|
return vectorstore |
|
|
|
def get_vectorstore(text_chunks): |
|
embedding = OpenAIEmbeddings(model="text-embedding-3-small") |
|
vectorstore = FAISS.from_texts(texts=text_chunks, embedding=embedding) |
|
return vectorstore |
|
|
|
def get_conversation_chain(vectorstore): |
|
llm = ChatOpenAI(model="gpt-3.5-turbo",temperature=0.5, max_tokens=2048) |
|
retriever=vectorstore.as_retriever() |
|
prompt = hub.pull("rlm/rag-prompt") |
|
|
|
|
|
rag_chain = ( |
|
{"context": retriever , "question": RunnablePassthrough()} |
|
| prompt |
|
| llm |
|
) |
|
return rag_chain |
|
|
|
def verify_and_complete_urls(urls): |
|
for i in range(len(urls)): |
|
is_valid, urls[i] = complete_and_verify_url(urls[i]) |
|
return urls |
|
|
|
def rag_pdf_web(): |
|
|
|
load_dotenv() |
|
st.header("INDIQUEZ VOS PAGES WEB ET/OU DOCUMENTS D’ENTREPRISE POUR AUDITER LE CONTENU RSE") |
|
|
|
option = st.radio("Source", ("A partir de votre site web", "A partir de vos documents entreprise")) |
|
|
|
vectorstore = None |
|
chain = None |
|
|
|
if option == "A partir de votre site web": |
|
url1 = st.text_input("URL 1") |
|
url2 = st.text_input("URL 2") |
|
url3 = st.text_input("URL 3") |
|
|
|
sous_options = st.radio("Choisissez votre sous-section", ("Ambition, Vision, Missions, Valeurs", "3 piliers de la démarche RSE")) |
|
try: |
|
if st.button("Process"): |
|
with st.spinner("Processing..."): |
|
|
|
urls = [url1, url2, url3] |
|
filtered_urls = [url for url in urls if url] |
|
|
|
|
|
filtered_urls = verify_and_complete_urls(filtered_urls) |
|
|
|
|
|
docs = get_docs_from_website(filtered_urls) |
|
|
|
|
|
text_chunks = get_doc_chunks(docs) |
|
|
|
|
|
vectorstore = get_vectorstore_from_docs(text_chunks) |
|
|
|
chain = get_conversation_chain(vectorstore) |
|
|
|
if sous_options == "Ambition, Vision, Missions, Valeurs": |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ambition = chain.invoke("Quelle est l'ambition de l'entreprise ? (répondre avec maximum 250 caractères)") |
|
st.markdown("### Ambition :") |
|
st.markdown(ambition.content) |
|
|
|
|
|
ambition = chain.invoke(" Quelle est la vision de l'entreprise ? (répondre avec maximum 250 caractères)") |
|
st.markdown("### Vision :") |
|
st.markdown(ambition.content) |
|
|
|
|
|
ambition = chain.invoke(" Quelle est la vision de l'entreprise ? (répondre avec maximum 250 caractères)") |
|
st.markdown("### Mission :") |
|
st.markdown(ambition.content) |
|
|
|
|
|
values = chain.invoke("Quels sont les valeurs de l'entreprise ? (répondre avec 10 mots maximum en bullet points)") |
|
st.markdown("### Valeurs :") |
|
st.markdown(values.content) |
|
|
|
elif sous_options == "3 piliers de la démarche RSE": |
|
question = ''' suggère nous les 3 piliers principaux de la démarche RSE pour cette entreprise. N'oublie aucun pilier RSE , ca doit avoir ce format : |
|
\n |
|
### le titre du pilier numero 1 \n |
|
-la description du pilier (répondre avec maximum 250 caractères) |
|
\n |
|
- 2 indicateurs cibles pertinents à atteindre avec suggestion de valeur cible min, max |
|
\n |
|
### le titre du pilier numero 2 \n |
|
-la description du pilier (répondre avec maximum 250 caractères) |
|
\n |
|
- 2 indicateurs cibles pertinents à atteindre avec suggestion de valeur cible min, max |
|
\n |
|
### le titre du pilier numero 3 \n |
|
-la description du pilier (répondre avec maximum 250 caractères) |
|
\n |
|
- 2 indicateurs cibles pertinents à atteindre avec suggestion de valeur cible min, max |
|
\n |
|
renvoie ta réponse en markdown et bien formatée |
|
''' |
|
response = chain.invoke(question) |
|
st.markdown(response.content) |
|
except Exception as e: |
|
st.error(f"Une erreur s'est produite : Url non valide ou problème de connexion à internet. Veuillez réessayer.") |
|
|
|
if option == "A partir de vos documents entreprise": |
|
pdf_docs = st.file_uploader("Upload les documents concernant la marque (maximum 3 fichiers de taille max de 5 Mo)", type="pdf", accept_multiple_files=True) |
|
|
|
sous_options = st.radio("Choisissez votre sous-section", ("Ambition, Vision, Missions, Valeurs", "3 piliers de la démarche RSE")) |
|
try: |
|
if st.button("Process"): |
|
with st.spinner("Processing..."): |
|
|
|
raw_text = get_pdf_text(pdf_docs) |
|
|
|
|
|
text_chunks = get_text_chunks(raw_text) |
|
|
|
|
|
vectorstore = get_vectorstore(text_chunks) |
|
|
|
chain = get_conversation_chain(vectorstore) |
|
|
|
if sous_options == "Ambition, Vision, Missions, Valeurs": |
|
|
|
|
|
ambition = chain.invoke("Quelle est l'ambition de l'entreprise ? (répondre avec maximum 250 caractères)") |
|
st.markdown("### Ambition :") |
|
st.markdown(ambition.content) |
|
|
|
|
|
ambition = chain.invoke(" Quelle est la vision de l'entreprise ? (répondre avec maximum 250 caractères)") |
|
st.markdown("### Vision :") |
|
st.markdown(ambition.content) |
|
|
|
|
|
ambition = chain.invoke(" Quelle est la vision de l'entreprise ? (répondre avec maximum 250 caractères)") |
|
st.markdown("### Mission :") |
|
st.markdown(ambition.content) |
|
|
|
|
|
values = chain.invoke("Quels sont les valeurs de l'entreprise ? (répondre avec 10 mots maximum en bullet points)") |
|
st.markdown("### Valeurs :") |
|
st.markdown(values.content) |
|
|
|
elif sous_options == "3 piliers de la démarche RSE": |
|
question = ''' suggère nous les 3 piliers principaux de la démarche RSE pour cette entreprise. Pour chaque pilier RSE doit avoir ce format : |
|
\n |
|
### le titre du ieme pilier \n |
|
-la description du pilier (répondre avec maximum 250 caractères) |
|
\n |
|
- 2 indicateurs cibles pertinents à atteindre avec suggestion de valeur cible min, max |
|
\n |
|
renvoie ta réponse en markdown et bien formatée |
|
''' |
|
response = chain.invoke(question) |
|
st.markdown(response.content) |
|
except Exception as e: |
|
st.error(f"Une erreur s'est produite : Pdf non valide ou problème de connexion à internet. Veuillez réessayer.") |
|
|
|
if vectorstore and chain: |
|
set_rag(vectorstore, chain) |