File size: 5,665 Bytes
f585950
6723742
f585950
 
69ee3ba
6723742
69ee3ba
 
6723742
f585950
69ee3ba
6723742
 
f585950
69ee3ba
 
 
 
 
 
6723742
69ee3ba
f585950
6723742
69ee3ba
 
 
 
6723742
f585950
69ee3ba
f585950
69ee3ba
 
 
6723742
69ee3ba
 
6723742
f585950
6723742
 
69ee3ba
 
6723742
69ee3ba
 
 
 
 
 
 
 
 
f585950
69ee3ba
6723742
69ee3ba
 
 
 
 
 
6723742
69ee3ba
f585950
 
6723742
69ee3ba
6723742
f585950
69ee3ba
 
f585950
 
 
 
69ee3ba
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f585950
69ee3ba
f585950
69ee3ba
 
 
 
 
f585950
69ee3ba
f585950
69ee3ba
f585950
 
69ee3ba
 
 
f585950
 
69ee3ba
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6723742
 
f585950
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import os
import streamlit as st
from dotenv import load_dotenv

# Lector de PDFs
from PyPDF2 import PdfReader

# Fragmentador de texto
from langchain.text_splitter import RecursiveCharacterTextSplitter

# Embeddings y VectorStore
from langchain_community.embeddings.spacy_embeddings import SpacyEmbeddings
from langchain_community.vectorstores import FAISS

# Librer铆as de LangChain para RAG
from langchain.chains import ConversationalRetrievalChain
from langchain.chat_models import ChatOpenAI
from langchain.memory import ConversationBufferMemory
from mi_prompt import tu_prompt_personalizado


# Cargar .env si lo necesitas
load_dotenv()

# Ajuste puntual (opcional en ciertos entornos Windows)
os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"

# Embeddings con spaCy (puedes cambiarlo por OpenAIEmbeddings, etc.)
embeddings = SpacyEmbeddings(model_name="en_core_web_sm")

# ---------------------------------------------
# Funciones auxiliares
# ---------------------------------------------
def read_pdfs(pdf_files):
    """Lee cada PDF y concatena su texto."""
    text = ""
    for pdf_file in pdf_files:
        pdf_reader = PdfReader(pdf_file)
        for page in pdf_reader.pages:
            text += page.extract_text() or ""
    return text

def chunk_text(text):
    """Divide el texto en chunks."""
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
    chunks = text_splitter.split_text(text)
    return chunks

def create_vectorstore(chunks):
    """Crea el FAISS VectorStore a partir de la lista de chunks."""
    vectorstore = FAISS.from_texts(chunks, embedding=embeddings)
    return vectorstore

# ---------------------------------------------
# Aplicaci贸n principal
# ---------------------------------------------
def main():
    st.set_page_config(page_title="Chat PDF (RAG)", layout="wide")
    st.header("RAG-based Chat con PDFs")

    # Iniciamos el estado de la conversaci贸n en la app
    if "conversation_chain" not in st.session_state:
        st.session_state["conversation_chain"] = None

    # Guardamos el historial en session_state (para la UI)
    if "messages" not in st.session_state:
        st.session_state["messages"] = []

    # Barra lateral: subir PDFs y procesarlos
    with st.sidebar:
        st.title("Men煤:")
        uploaded_pdfs = st.file_uploader(
            "Sube tus PDFs y haz clic en 'Procesar PDFs'.",
            accept_multiple_files=True
        )

        if st.button("Procesar PDFs"):
            if uploaded_pdfs:
                with st.spinner("Procesando e indexando..."):
                    # 1) Leer PDFs
                    raw_text = read_pdfs(uploaded_pdfs)

                    # 2) Fragmentar texto
                    text_chunks = chunk_text(raw_text)

                    # 3) Crear FAISS VectorStore
                    vectorstore = create_vectorstore(text_chunks)

                    # 4) Crear la cadena conversacional con retrieval
                    #    - ConversationalRetrievalChain maneja preguntas + contexto
                    llm = ChatOpenAI(
                        model_name="gpt-4o-mini",  # o "gpt-4", seg煤n tu acceso
                        temperature=0
                    )

                    # Memoria para la conversaci贸n
                    memory = ConversationBufferMemory(
                        memory_key="chat_history", 
                        return_messages=True
                    )

                    # Creamos la cadena RAG:
                    conversation_chain = ConversationalRetrievalChain.from_llm(
                        llm=llm,
                        retriever=vectorstore.as_retriever(search_kwargs={"k": 6}),
                        memory=memory,
                        # Opcionalmente, ajusta c贸mo combinar la pregunta con los documentos:
                        combine_docs_chain_kwargs={"prompt": tu_prompt_personalizado},
                    )

                    # Guardamos la cadena en session_state
                    st.session_state["conversation_chain"] = conversation_chain
                st.success("隆PDFs procesados y VectorStore creado!")
            else:
                st.warning("No subiste ning煤n PDF")

        # Bot贸n para reiniciar
        if st.button("Reiniciar VectorStore"):
            st.session_state["conversation_chain"] = None
            st.session_state["messages"] = []
            st.info("Base vectorial reiniciada. Sube nuevos PDFs si lo deseas.")

    st.subheader("Chat con tus PDFs")

    # Mostrar historial previo
    for msg in st.session_state["messages"]:
        st.write(f"**{msg['role'].capitalize()}:** {msg['content']}")

    # Input del usuario
    user_input = st.text_input("Haz una pregunta sobre el/los PDF(s)...")

    if user_input:
        if st.session_state["conversation_chain"] is None:
            st.warning("No hay PDFs procesados. Sube y procesa al menos un PDF.")
        else:
            # Guardamos mensaje del usuario en el historial
            st.session_state["messages"].append({"role": "user", "content": user_input})

            # Usar la cadena conversacional para obtener respuesta
            response = st.session_state["conversation_chain"]({
                "question": user_input
            })

            # El output viene en la llave "answer" por defecto con ConversationalRetrievalChain
            answer = response["answer"]

            # A帽adir respuesta al historial
            st.session_state["messages"].append({"role": "assistant", "content": answer})

            # Mostrar la respuesta
            st.write(f"**Asistente:** {answer}")

if __name__ == "__main__":
    main()