Sumayyea's picture
Update app.py
3ccf82a verified
Raw History Blame Contribute Delete
5.66 kB
import numpy as np
import streamlit as st
from transformers import BartTokenizer, BartForConditionalGeneration
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans
from nltk.tokenize import sent_tokenize
import nltk
# Download required NLTK data
@st.cache_resource
def download_nltk_data():
try:
nltk.data.find('tokenizers/punkt')
except LookupError:
nltk.download('punkt', quiet=True)
nltk.download('punkt_tab', quiet=True)
download_nltk_data()
# Load BART model and tokenizer
@st.cache_resource
def load_model():
tokenizer = BartTokenizer.from_pretrained('facebook/bart-large-cnn')
model = BartForConditionalGeneration.from_pretrained('facebook/bart-large-cnn')
return tokenizer, model
tokenizer, model = load_model()
# Function for single document summarization
def summarize(text, max_length=150, min_length=50):
inputs = tokenizer([text], max_length=1024, truncation=True, return_tensors='pt')
summary_ids = model.generate(
inputs['input_ids'],
num_beams=4,
max_length=max_length,
min_length=min_length,
early_stopping=True
)
return tokenizer.decode(summary_ids[0], skip_special_tokens=True)
# Function for clustering documents
def cluster_documents(documents, n_clusters=3):
vectorizer = TfidfVectorizer(stop_words='english')
X = vectorizer.fit_transform(documents)
kmeans = KMeans(n_clusters=n_clusters, random_state=42).fit(X)
return kmeans.labels_
# Function to split long text into chunks
def chunk_text(text, max_words=1000):
if len(text.split()) <= max_words:
return [text]
sentences = sent_tokenize(text)
current_chunk = []
chunks = []
current_word_count = 0
for sentence in sentences:
sentence_words = len(sentence.split())
if current_word_count + sentence_words <= max_words:
current_chunk.append(sentence)
current_word_count += sentence_words
else:
chunks.append(" ".join(current_chunk))
current_chunk = [sentence]
current_word_count = sentence_words
if current_chunk:
chunks.append(" ".join(current_chunk))
return chunks
# Function for multi-document summarization
def multi_document_summarize(documents):
results = {
'individual_summaries': [],
'cluster_summaries': [],
'final_summary': None
}
# Generate individual document summaries
for doc in documents:
chunks = chunk_text(doc)
doc_summary = " ".join([summarize(chunk) for chunk in chunks])
results['individual_summaries'].append(doc_summary)
# Cluster documents if we have multiple
if len(documents) > 1:
n_clusters = min(3, len(documents))
clusters = cluster_documents(documents, n_clusters=n_clusters)
# Generate cluster summaries
for cluster_id in np.unique(clusters):
cluster_docs = [doc for doc, c in zip(documents, clusters) if c == cluster_id]
combined_text = " ".join(cluster_docs)
chunks = chunk_text(combined_text)
cluster_summary = " ".join([summarize(chunk) for chunk in chunks])
results['cluster_summaries'].append({
'doc_indices': [i for i, c in enumerate(clusters) if c == cluster_id],
'summary': cluster_summary
})
# Generate final comprehensive summary
all_summaries = results['individual_summaries'] + [cs['summary'] for cs in results['cluster_summaries']]
results['final_summary'] = summarize(" ".join(all_summaries), max_length=200, min_length=100)
else:
results['final_summary'] = results['individual_summaries'][0]
return results
# Streamlit UI
st.title("Multi-Document Summarization")
st.write("This system summarizes multiple related documents using clustering and BART.")
uploaded_files = st.file_uploader(
"Upload text files (one document per file)",
type=['txt'],
accept_multiple_files=True
)
if uploaded_files:
documents = []
for file in uploaded_files:
documents.append(file.read().decode("utf-8"))
if st.button("Generate Summary"):
with st.spinner("Processing documents..."):
try:
results = multi_document_summarize(documents)
# Display individual document summaries
st.subheader("Individual Document Summaries")
for i, (doc, summary) in enumerate(zip(documents, results['individual_summaries'])):
with st.expander(f"Document {i+1} Summary (First 200 chars: {doc[:200]}...)"):
st.write(summary)
# Display cluster summaries if we have multiple documents
if len(documents) > 1:
st.subheader("Cluster Summaries")
for i, cluster in enumerate(results['cluster_summaries']):
with st.expander(f"Cluster {i+1} Summary (Documents: {', '.join(str(x+1) for x in cluster['doc_indices'])}))"):
st.write(cluster['summary'])
# Display final summary
st.subheader("Final Comprehensive Summary")
st.write(results['final_summary'])
except Exception as e:
st.error(f"An error occurred: {str(e)}")
st.info("Please try again or upload different documents.")
else:
st.info("Please upload some text files to get started.")