Spaces:
Sleeping
Sleeping
import os | |
import torch | |
import streamlit as st | |
from langchain_community.embeddings import HuggingFaceEmbeddings | |
from langchain_community.vectorstores import FAISS | |
from langchain_core.prompts import PromptTemplate | |
from langchain.chains import LLMChain | |
from langchain_community.llms import HuggingFacePipeline | |
from transformers import pipeline, AutoTokenizer, AutoModelForCausalLM | |
from dotenv import load_dotenv | |
from htmlTemplates import css | |
# Set Streamlit page configuration | |
st.set_page_config(page_title="Chat with Notes and AI", page_icon=":books:", layout="wide") | |
# Load environment variables | |
load_dotenv() | |
# Dolly-v2-3b model pipeline | |
def load_pipeline(): | |
# Use recommended settings for Dolly-v2-3b | |
model_name = "databricks/dolly-v2-3b" | |
tokenizer = AutoTokenizer.from_pretrained(model_name, padding_side="left", trust_remote_code=True) | |
model = AutoModelForCausalLM.from_pretrained( | |
model_name, | |
torch_dtype=torch.bfloat16 if torch.cuda.is_available() else torch.float32, # Use float16 for GPU, float32 for CPU | |
device_map="auto", # Automatically map model to available devices (e.g., GPU if available) | |
trust_remote_code=True | |
) | |
# Load the pipeline with required configurations | |
return pipeline( | |
task="text-generation", | |
model=model, | |
tokenizer=tokenizer, | |
torch_dtype=torch.bfloat16 if torch.cuda.is_available() else torch.float32, | |
device_map="auto", | |
return_full_text=True # Required for LangChain compatibility | |
) | |
# Initialize Dolly pipeline | |
generate_text = load_pipeline() | |
# Create a HuggingFace pipeline wrapper for LangChain | |
hf_pipeline = HuggingFacePipeline(pipeline=generate_text) | |
# Template for instruction-only prompts | |
prompt = PromptTemplate( | |
input_variables=["instruction"], | |
template="{instruction}" | |
) | |
# Template for prompts with context | |
prompt_with_context = PromptTemplate( | |
input_variables=["instruction", "context"], | |
template="{instruction}\n\nInput:\n{context}" | |
) | |
# Create LLM chains | |
llm_chain = LLMChain(llm=hf_pipeline, prompt=prompt) | |
llm_context_chain = LLMChain(llm=hf_pipeline, prompt=prompt_with_context) | |
# Extracting text from .txt files | |
def get_text_files_content(folder): | |
text = "" | |
for filename in os.listdir(folder): | |
if filename.endswith('.txt'): | |
with open(os.path.join(folder, filename), 'r', encoding='utf-8') as file: | |
text += file.read() + "\n" | |
return text | |
# Converting text to chunks | |
def get_chunks(raw_text): | |
from langchain.text_splitter import CharacterTextSplitter | |
text_splitter = CharacterTextSplitter( | |
separator="\n", | |
chunk_size=2000, | |
chunk_overlap=500, | |
length_function=len | |
) | |
chunks = text_splitter.split_text(raw_text) | |
return chunks | |
# Using Hugging Face embeddings model and FAISS to create vectorstore | |
def get_vectorstore(chunks): | |
embeddings = HuggingFaceEmbeddings( | |
model_name="sentence-transformers/all-MiniLM-L6-v2", | |
model_kwargs={'device': 'cpu'} # Ensure embeddings use CPU | |
) | |
vectorstore = FAISS.from_texts(texts=chunks, embedding=embeddings) | |
return vectorstore | |
# Generating response from user queries | |
def handle_question(question, vectorstore=None): | |
if vectorstore: | |
documents = vectorstore.similarity_search(question, k=3) | |
context = "\n".join([doc.page_content for doc in documents]) | |
if context: | |
result_with_context = llm_context_chain.invoke({"instruction": question, "context": context}) | |
return result_with_context | |
return llm_chain.invoke({"instruction": question}) | |
def main(): | |
st.write(css, unsafe_allow_html=True) | |
# Initialize session state | |
if "vectorstore" not in st.session_state: | |
st.session_state.vectorstore = None | |
st.header("Chat with Notes and AI :books:") | |
# Subject selection dropdown | |
subjects = [ | |
"A Trumped World", "Agri Tax in Punjab", "Assad's Fall in Syria", "Elusive National Unity", "Europe and Trump 2.0", | |
"Going Down with Democracy", "Indonesia's Pancasila Philosophy", "Pakistan in Choppy Waters", | |
"Pakistan's Semiconductor Ambitions", "Preserving Pakistan's Cultural Heritage", "Tackling Informal Economy", | |
"Technical Education in Pakistan", "The Case for Solidarity Levies", "The Decline of the Sole Superpower", | |
"The Power of Big Oil", "Trump 2.0 and Pakistan's Emerging Foreign Policy", "Trump and the World 2.0", | |
"Trump vs BRICS", "US-China Trade War", "War on Humanity", "Women's Suppression in Afghanistan" | |
] | |
data_folder = "data" | |
subject_folders = {subject: os.path.join(data_folder, subject.replace(' ', '_')) for subject in subjects} | |
selected_subject = st.sidebar.selectbox("Select a Subject:", subjects) | |
st.sidebar.info(f"You have selected: {selected_subject}") | |
# Process data folder for notes preview and question answering | |
subject_folder_path = subject_folders[selected_subject] | |
if os.path.exists(subject_folder_path): | |
raw_text = get_text_files_content(subject_folder_path) | |
if raw_text: | |
text_chunks = get_chunks(raw_text) | |
vectorstore = get_vectorstore(text_chunks) | |
st.session_state.vectorstore = vectorstore | |
# Display preview of notes | |
st.subheader("Preview of Notes") | |
st.text_area("Preview Content:", value=raw_text[:2000], height=300, disabled=True) # Show a snippet of the text | |
else: | |
st.error("No content found for the selected subject.") | |
else: | |
st.error(f"Folder not found for {selected_subject}.") | |
# Chat interface | |
st.subheader("Ask Your Question") | |
question = st.text_input("Ask a question about your selected subject:") | |
if question: | |
if st.session_state.vectorstore: | |
response = handle_question(question, st.session_state.vectorstore) | |
st.subheader("Response:") | |
st.write(response) | |
else: | |
st.warning("Please load the content for the selected subject before asking a question.") | |
if __name__ == '__main__': | |
main() | |