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, # the character length of the chunck chunk_overlap=200, # the character length of the overlap between chuncks length_function=len # the length function - in this case, character length (aka the python len() fn.) ) chunks = text_splitter.split_text(text) return chunks def get_doc_chunks(docs): # Split the loaded data 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") # Chain 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") # Process the URLs 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..."): #get text from the website urls = [url1, url2, url3] filtered_urls = [url for url in urls if url] #verify and complete urls filtered_urls = verify_and_complete_urls(filtered_urls) #get text from the website docs = get_docs_from_website(filtered_urls) #get text chunks text_chunks = get_doc_chunks(docs) #create vectorstore vectorstore = get_vectorstore_from_docs(text_chunks) chain = get_conversation_chain(vectorstore) if sous_options == "Ambition, Vision, Missions, Valeurs": # question = '''voici les 4 points à génerer absolument, pas de reponse comme je ne sais pas; et n'oublie aucun des points , chaque paragraphe doit être de minimum 150 caractères: # \n # ### Ambition : \n # Quelle est l'ambition de l'entreprise ? (répondre avec maximum 250 caractères) # \n # ### Vision : \n # Quelle est la vision de l'entreprise ? (répondre avec maximum 250 caractères) # \n # ### Missions : \n # Quelles sont les missions de l'entreprise ? (répondre avec maximum 250 caractères) # \n # renvoie ta réponse en markdown et bien formatée''' # response = chain.invoke(question) # st.markdown(response.content) #ambition ambition = chain.invoke("Quelle est l'ambition de l'entreprise ? (répondre avec maximum 250 caractères)") st.markdown("### Ambition :") st.markdown(ambition.content) #vision ambition = chain.invoke(" Quelle est la vision de l'entreprise ? (répondre avec maximum 250 caractères)") st.markdown("### Vision :") st.markdown(ambition.content) #Mission 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 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) # Process the PDF documents 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..."): #get pdf text in raw format raw_text = get_pdf_text(pdf_docs) #get text chunks text_chunks = get_text_chunks(raw_text) #create vectorstore vectorstore = get_vectorstore(text_chunks) chain = get_conversation_chain(vectorstore) if sous_options == "Ambition, Vision, Missions, Valeurs": #ambition ambition = chain.invoke("Quelle est l'ambition de l'entreprise ? (répondre avec maximum 250 caractères)") st.markdown("### Ambition :") st.markdown(ambition.content) #vision ambition = chain.invoke(" Quelle est la vision de l'entreprise ? (répondre avec maximum 250 caractères)") st.markdown("### Vision :") st.markdown(ambition.content) #Mission 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 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)