|
import os |
|
import shutil |
|
import streamlit as st |
|
from dotenv import load_dotenv |
|
from langchain.document_loaders import PyPDFLoader |
|
from langchain.embeddings import HuggingFaceEmbeddings |
|
from langchain.vectorstores import FAISS |
|
from langchain.storage import LocalFileStore |
|
from langchain.embeddings import CacheBackedEmbeddings |
|
from langchain_groq import ChatGroq |
|
from langchain_core.runnables import RunnablePassthrough |
|
from langchain_core.prompts import ChatPromptTemplate |
|
from langchain_core.output_parsers import StrOutputParser |
|
from streamlit_chat import message |
|
|
|
|
|
load_dotenv() |
|
os.environ['GROQ_API_KEY'] = os.getenv('GROQ_API') |
|
os.environ["LANGCHAIN_TRACING_V2"] = "true" |
|
os.environ["LANGCHAIN_API_KEY"] = os.getenv('LANGSMITH_API') |
|
|
|
UPLOAD_DIR = "uploaded_files" |
|
|
|
def cleanup_files(): |
|
if os.path.isdir(UPLOAD_DIR): |
|
shutil.rmtree(UPLOAD_DIR, ignore_errors=True) |
|
if 'file_handle' in st.session_state: |
|
st.session_state.file_handle.close() |
|
|
|
|
|
if 'cleanup_done' not in st.session_state: |
|
st.session_state.cleanup_done = False |
|
|
|
if not st.session_state.cleanup_done: |
|
cleanup_files() |
|
|
|
if not os.path.exists(UPLOAD_DIR): |
|
os.makedirs(UPLOAD_DIR, exist_ok=True) |
|
|
|
|
|
st.markdown( |
|
""" |
|
<style> |
|
body { |
|
margin: 0; |
|
padding: 0; |
|
font-family: 'Arial', sans-serif; |
|
color: #C9D1D9; |
|
} |
|
.main-bg { |
|
position: fixed; |
|
top: 0; |
|
left: 0; |
|
width: 100%; |
|
height: 100%; |
|
z-index: -1; |
|
overflow: hidden; |
|
} |
|
.main-bg video { |
|
position: absolute; |
|
top: 50%; |
|
left: 50%; |
|
transform: translate(-50%, -50%); |
|
width: 100%; |
|
height: 100%; |
|
object-fit: cover; |
|
} |
|
.stButton button { |
|
background-color: #1F6FEB; |
|
color: white; |
|
border-radius: 8px; |
|
border: none; |
|
padding: 10px 20px; |
|
font-weight: bold; |
|
font-size: 14px; |
|
} |
|
.stButton button:hover { |
|
background-color: #1A4FC5; |
|
} |
|
.stTextInput > div > input { |
|
border: 1px solid #30363D; |
|
background-color: #161B22; |
|
color: #C9D1D9; |
|
border-radius: 6px; |
|
padding: 10px; |
|
} |
|
.stFileUploader > div { |
|
border: 2px dashed #30363D; |
|
background-color: #161B22; |
|
color: #C9D1D9; |
|
border-radius: 6px; |
|
padding: 10px; |
|
} |
|
.header { |
|
display: flex; |
|
align-items: center; |
|
gap: 10px; |
|
padding-top: 50px; |
|
color: #58A6FF; |
|
} |
|
.response-box { |
|
background-color: #161B22; |
|
padding: 10px; |
|
border-radius: 6px; |
|
margin-bottom: 10px; |
|
color: #FFFFFF; |
|
} |
|
</style> |
|
""", |
|
unsafe_allow_html=True |
|
) |
|
|
|
|
|
st.markdown( |
|
""" |
|
<div class="main-bg"> |
|
<video autoplay loop muted> |
|
<source src="https://vimeo.com/464431550" type="video/mp4"> |
|
</video> |
|
</div> |
|
""", |
|
unsafe_allow_html=True |
|
) |
|
|
|
|
|
st.markdown( |
|
""" |
|
<div class="header" style="display: flex; align-items: center; gap: 10px;"> |
|
<h1 style="font-weight: bold;">Welcome to Xailor AI Chat!</h1> |
|
</div> |
|
""", |
|
unsafe_allow_html=True |
|
) |
|
|
|
|
|
st.write("<div style='height: 100px;'></div>", unsafe_allow_html=True) |
|
|
|
st.title("Chat with your PDF!!") |
|
|
|
uploaded_file = st.file_uploader("Upload a file") |
|
|
|
if uploaded_file is not None: |
|
file_path = os.path.join(UPLOAD_DIR, uploaded_file.name) |
|
file_path = os.path.abspath(file_path) |
|
|
|
with open(file_path, 'wb') as f: |
|
f.write(uploaded_file.getbuffer()) |
|
st.write("You're Ready For a Chat with your PDF") |
|
|
|
docs = PyPDFLoader(file_path).load_and_split() |
|
|
|
embedding = HuggingFaceEmbeddings( |
|
model_name='BAAI/llm-embedder', |
|
) |
|
|
|
store = LocalFileStore("./cache/") |
|
cached_embedder = CacheBackedEmbeddings.from_bytes_store( |
|
embedding, store, namespace='embeddings' |
|
) |
|
|
|
vector_base = FAISS.from_documents( |
|
docs, |
|
embedding |
|
) |
|
|
|
template = '''You are Xailor.AI's friendly chatbot assistant. Your role is to assist users with insightful answers about their pdf, creative writing, and using Xailor.AI . Answer the {question} based only on the provided {context}. After answering the question, recommend Xailor.AI services that may interest the user based on the content of the PDF or the question. Be friendly, creative, and concise. Use a maximum of three sentences for the answer, and add one or two relevant story recommendations with a brief description and a link. If you're unsure about the answer, respond with "I'm not sure about that, but feel free to explore more on Xailor.AI!"''' |
|
|
|
|
|
prompt = ChatPromptTemplate.from_template(template) |
|
retriever = vector_base.as_retriever() |
|
|
|
llm = ChatGroq( |
|
model='mixtral-8x7b-32768', |
|
temperature=0, |
|
) |
|
|
|
if 'history' not in st.session_state: |
|
st.session_state.history = [] |
|
|
|
query = st.text_input("Enter your question", placeholder="Ask something interesting...") |
|
|
|
if st.button("Submit!", key="submit_button"): |
|
if query: |
|
chain = ( |
|
{'context': retriever, 'question': RunnablePassthrough()} |
|
| prompt | llm | StrOutputParser() |
|
) |
|
answer = chain.invoke(query) |
|
st.session_state.history.append({'question': query, 'answer': answer}) |
|
|
|
if st.session_state.history: |
|
st.write("### Previous Questions and Answers") |
|
for idx, entry in enumerate(st.session_state.history): |
|
st.markdown( |
|
f""" |
|
<div class="response-box"> |
|
<p style="font-weight: bold; color: #58A6FF;">Q{idx + 1}: {entry['question']}</p> |
|
<p style="color: #FFFFFF;">A{idx + 1}: {entry['answer']}</p> |
|
</div> |
|
""", |
|
unsafe_allow_html=True |
|
) |
|
|
|
|
|
if st.button("Reset and Upload a New PDF"): |
|
st.session_state.clear() |
|
st.session_state.cleanup_done = False |
|
st.experimental_rerun() |
|
|
|
if st.session_state.cleanup_done: |
|
cleanup_files() |