File size: 4,109 Bytes
d3a1193
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import os
import torch
import whisper
import PyPDF2
import gradio as gr
from transformers import BertTokenizerFast, BertForQuestionAnswering, pipeline
from torch.nn.functional import softmax
from docx import Document

device = "cuda" if torch.cuda.is_available() else "cpu"

qa_model = BertForQuestionAnswering.from_pretrained("deepset/bert-base-cased-squad2").to(device)
tokenizer = BertTokenizerFast.from_pretrained("deepset/bert-base-cased-squad2")
summarizer = pipeline("summarization", model="facebook/bart-large-cnn")
whisper_model = whisper.load_model("base")


def extract_text(file_obj):
    ext = os.path.splitext(file_obj.name)[1].lower()
    if ext == ".pdf":
        reader = PyPDF2.PdfReader(file_obj)
        return "\n".join([p.extract_text() for p in reader.pages if p.extract_text()])
    elif ext == ".docx":
        doc = Document(file_obj)
        return "\n".join([p.text for p in doc.paragraphs])
    elif ext == ".txt":
        return file_obj.read().decode("utf-8")
    return ""


def summarize_text(text):
    if len(text) < 50:
        return "Text too short to summarize."
    if len(text) > 1000:
        text = text[:1000]
    summary = summarizer(text, max_length=120, min_length=30, do_sample=False)
    return summary[0]['summary_text']


def ask_question(question, context):
    inputs = tokenizer.encode_plus(question, context, return_tensors="pt", truncation=True, max_length=512).to(device)
    with torch.no_grad():
        outputs = qa_model(**inputs)
    start_idx = torch.argmax(outputs.start_logits)
    end_idx = torch.argmax(outputs.end_logits) + 1
    score = softmax(outputs.start_logits, dim=1)[0][start_idx] * softmax(outputs.end_logits, dim=1)[0][end_idx - 1]
    answer = tokenizer.decode(inputs["input_ids"][0][start_idx:end_idx])
    return f"Answer: {answer.strip()}\nConfidence: {round(score.item()*100, 2)}%"


def transcribe(audio_path):
    result = whisper_model.transcribe(audio_path)
    return result["text"]


with gr.Blocks() as demo:
    gr.Markdown("# πŸŽ™οΈπŸ“„ LexPilot: Voice + Document Q&A Assistant")
    gr.Markdown("Upload a document or paste content. Ask questions by typing or using your voice.")

    with gr.Tab("Question Answering"):
        with gr.Row():
            uploaded_file = gr.File(label="Upload .pdf / .docx / .txt", file_types=[".pdf", ".docx", ".txt"])
            pasted_text = gr.Textbox(label="Paste text manually", lines=10)
        with gr.Row():
            typed_question = gr.Textbox(label="Type your question")
            audio_input = gr.Audio(source="microphone",type="filepath", label="Or speak your question")
        qa_btn = gr.Button("Get Answer")
        qa_output = gr.Textbox(label="Answer and Confidence", lines=3)

        def handle_qa(file, text, typed, audio):
            context = ""
            if file:
                context = extract_text(file)
            elif text:
                context = text
            else:
                return "❗ Please upload or paste content."

            if typed:
                question = typed
            elif audio:
                question = transcribe(audio)
            else:
                return "❗ Please speak or type a question."

            return ask_question(question, context)

        qa_btn.click(handle_qa, inputs=[uploaded_file, pasted_text, typed_question, audio_input], outputs=qa_output)

    with gr.Tab("Summarization"):
        with gr.Row():
            sum_file = gr.File(label="Upload .pdf / .docx / .txt", file_types=[".pdf", ".docx", ".txt"])
            sum_text = gr.Textbox(label="Or paste content", lines=10)
        sum_btn = gr.Button("Summarize")
        sum_output = gr.Textbox(label="Summary", lines=4)

        def handle_summary(file, text):
            if file:
                context = extract_text(file)
            elif text:
                context = text
            else:
                return "❗ Please upload or paste content to summarize."
            return summarize_text(context)

        sum_btn.click(handle_summary, inputs=[sum_file, sum_text], outputs=sum_output)

demo.launch()