Spaces:
Running
Running
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) |