File size: 5,810 Bytes
fe1fc2e
467c73a
3c4de7d
bd26a11
 
 
 
 
8356c3c
bd26a11
 
 
467c73a
fe1fc2e
644332a
8356c3c
dfb65c1
4f834c9
2390875
10edf7a
866a2b0
 
10edf7a
 
 
 
 
 
 
 
 
5401b17
 
 
10edf7a
 
 
 
 
 
d1e59aa
9f3b8b8
c4b7f37
 
d1e59aa
c4b7f37
d1e59aa
c4b7f37
d1e59aa
c4b7f37
d1e59aa
c4b7f37
d1e59aa
c4b7f37
d1e59aa
c4b7f37
4df9abe
26e268c
 
 
 
 
d1e59aa
 
 
 
 
 
f9723de
d1e59aa
55e669b
 
 
d1e59aa
55e669b
 
 
 
9f3b8b8
55e669b
 
 
f9723de
9f3b8b8
 
55e669b
b9e6b37
6eff0f4
44dbaf8
fe80a40
44dbaf8
 
 
 
81c159a
ba98772
 
55e669b
2f6f04b
ba98772
55e669b
2f6f04b
815187b
2f6f04b
55e669b
 
 
 
 
 
 
9f3b8b8
fd0bd52
c547536
05d1ad8
 
fe1fc2e
3c4de7d
c547536
8356c3c
9f3b8b8
8356c3c
 
 
 
 
 
 
 
 
fe1fc2e
c547536
 
3c4de7d
 
fe1fc2e
6c3e7c4
8f9bfd7
 
 
 
 
 
6c3e7c4
 
fe1fc2e
c547536
fe1fc2e
3c4de7d
 
 
 
 
 
 
c547536
3c4de7d
c547536
3c4de7d
c547536
81c159a
7b0e989
 
 
 
 
 
 
81c159a
7b0e989
5bd324a
815187b
10edf7a
815187b
c547536
f9723de
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import os
import streamlit as st
from dotenv import load_dotenv
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.llms import llamacpp
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.callbacks import CallbackManager, StreamingStdOutCallbackHandler
from langchain.chains import create_history_aware_retriever, create_retrieval_chain, ConversationalRetrievalChain
from langchain.document_loaders import TextLoader
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_community.chat_message_histories.streamlit import StreamlitChatMessageHistory
from langchain.prompts import PromptTemplate
from langchain.vectorstores import Chroma
from utills import load_txt_documents, split_docs, load_uploaded_documents, retriever_from_chroma
from langchain.text_splitter import TokenTextSplitter, RecursiveCharacterTextSplitter
from langchain_community.document_loaders.directory import DirectoryLoader
from HTML_templates import css, bot_template, user_template




def get_vectorstore(text_chunks):
    model_name = "sentence-transformers/all-mpnet-base-v2"
    model_kwargs = {'device': 'cpu'}
    encode_kwargs = {'normalize_embeddings': True}
    embeddings = HuggingFaceEmbeddings(
        model_name=model_name,
        model_kwargs=model_kwargs,
        encode_kwargs=encode_kwargs
    )
    vectorstore_path = "docs/chroma/"
    if not os.path.exists(vectorstore_path):
        os.makedirs(vectorstore_path)
    vectorstore = Chroma.from_documents(
        documents=text_chunks, embedding=embeddings, persist_directory="docs/chroma/")
    return vectorstore    



data_path = "data"


    
documents = []
    
for filename in os.listdir(data_path):

    if filename.endswith('.txt'):

        file_path = os.path.join(data_path, filename)

        documents = TextLoader(file_path).load()

        documents.extend(documents)
    



docs = split_docs(documents, 350, 40)

vectorstore = get_vectorstore(docs)






def main(vectorstore):

    st.set_page_config(page_title="Chat with multiple PDFs",
                       page_icon=":books:")
    st.write(css, unsafe_allow_html=True)

    if "conversation" not in st.session_state:
        st.session_state.conversation = None
    if "chat_history" not in st.session_state:
        st.session_state.chat_history = None

    st.header("Chat with multiple PDFs :books:")
    user_question = st.text_input("Ask a question about your documents:")
    if user_question:
        handle_userinput(user_question,vectorstore)


def handle_userinput(user_question,vectorstore):
    Rag_chain = create_conversational_rag_chain(vectorstore)
    msgs = StreamlitChatMessageHistory(key="special_app_key")
    response = Rag_chain.invoke(
    {"input": user_question},
    
    config={
        "configurable": {"session_id": "k"}
    }, 
    )["answer"]
    
    st.session_state.chat_history = response['chat_history']

    # Display messages in chat history
    for i, message in enumerate(st.session_state.chat_history):
        if i % 2 == 0:
            st.write(user_template.replace("{{MSG}}", message.content), unsafe_allow_html=True)
        else:
            st.write(bot_template.replace("{{MSG}}", message.content), unsafe_allow_html=True)

    if 'retrieved_documents' in response:
        st.subheader("Retrieved Documents")
        for doc in response['source_documents']:
            st.write(f"Document: {doc.metadata['source']}")
            st.write(doc.page_content)       



def create_conversational_rag_chain(vectorstore):
    
    model_path = ('qwen2-0_5b-instruct-q4_0.gguf')

    callback_manager = CallbackManager([StreamingStdOutCallbackHandler()])

    llm = llamacpp.LlamaCpp(
        model_path=model_path,
        n_gpu_layers=1,
        temperature=0.1,
        top_p=0.9,
        n_ctx=22000,
        max_tokens=200,
        repeat_penalty=1.7,
        callback_manager=callback_manager,
        verbose=False,
    )

    contextualize_q_system_prompt = """Given a context, chat history and the latest user question
    which maybe reference context in the chat history, formulate a standalone question
    which can be understood without the chat history. Do NOT answer the question,
    just reformulate it if needed and otherwise return it as is."""

    contextualize_q_prompt = ChatPromptTemplate.from_messages(
        [
            ("system", contextualize_q_system_prompt),
            MessagesPlaceholder("chat_history"),
            ("human", "{input}"),
        ]
    )

    ha_retriever = create_history_aware_retriever(llm, vectorstore.as_retriever(), contextualize_q_prompt)

    qa_system_prompt = """You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Be as informative as possible, be polite and formal.\n{context}"""

    qa_prompt = ChatPromptTemplate.from_messages(
        [
            ("system", qa_system_prompt),
            MessagesPlaceholder("chat_history"),
            ("human", "{input}"),
        ]
    )

    question_answer_chain = create_stuff_documents_chain(llm, qa_prompt)
    rag_chain = create_retrieval_chain(ha_retriever, question_answer_chain)
    msgs = StreamlitChatMessageHistory(key="special_app_key")

    conversational_rag_chain = RunnableWithMessageHistory(
        rag_chain,
        lambda session_id: msgs,
        input_messages_key="input",
        history_messages_key="chat_history",
        output_messages_key="answer",
        return_source_documents=True
    )

    return conversational_rag_chain


 

if __name__ == "__main__":
    main(vectorstore)