File size: 4,460 Bytes
da0b26a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
# βœ… Install dependencies

# πŸ“š Imports
import fitz  # PyMuPDF
import requests
import gradio as gr
import tempfile
import os
import io

# πŸ”‘ Enter your OpenRouter API key here
OPENROUTER_API_KEY = "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"  

# Global variable to store the extracted text
pdf_text = ""

# πŸ“„ Extract text from PDF
def extract_text_from_pdf(file_obj):
    global pdf_text
    
    if file_obj is None:
        return "Please upload a PDF file first."
    
    try:
        # Get the file path from the file object
        # In Gradio, the file object has a name attribute that contains the path
        file_path = file_obj.name
        
        # Now open the file with PyMuPDF
        doc = fitz.open(file_path)
        text = ""
        for page in doc:
            text += page.get_text()
        doc.close()
        
        # Store the text for later use
        pdf_text = text
        
        # Return preview of the extracted text
        preview = text[:500] + "..." if len(text) > 500 else text
        return f"βœ… PDF uploaded and processed successfully. Preview:\n\n{preview}"
    
    except Exception as e:
        return f"❌ Error processing PDF: {str(e)}"

# πŸ’¬ Ask the open-source LLM (Mistral-7B via OpenRouter)
def ask_open_source_llm(question, model_choice="nvidia/llama-3.1-nemotron-nano-8b-v1:free"):
    global pdf_text
    
    if not pdf_text:
        return "⚠️ Please upload a PDF document first."
    
    # Limit text to prevent token overflow
    limited_text = pdf_text[:3000]  # First 3000 characters
    
    # Create prompt based on question
    if not question:
        prompt = f"Summarize the following document:\n\n{limited_text}"
    else:
        prompt = f"The document says:\n\n{limited_text}\n\nNow answer this: {question}"
    
    # Call the API
    url = "https://openrouter.ai/api/v1/chat/completions"
    headers = {
        "Authorization": f"Bearer {OPENROUTER_API_KEY}",
        "Content-Type": "application/json"
    }
    
    data = {
        "model": model_choice,
        "messages": [{"role": "user", "content": prompt}]
    }
    
    try:
        response = requests.post(url, headers=headers, json=data)
        if response.status_code == 200:
            return response.json()["choices"][0]["message"]["content"]
        else:
            return f"❌ Error: {response.text}"
    except Exception as e:
        return f"❌ An error occurred: {str(e)}"

# Gradio app function
def process_query(pdf_file, question, model_choice):
    # First extract text if a PDF is uploaded
    if pdf_file is not None:
        result = extract_text_from_pdf(pdf_file)
        if result.startswith("❌ Error"):
            return result
    
    # Then process the question
    if question:
        return ask_open_source_llm(question, model_choice)
    else:
        return ask_open_source_llm("Please summarize this document.", model_choice)

# Create Gradio interface
with gr.Blocks(title="PDF Document Analysis") as app:
    gr.Markdown("# πŸ“š PDF Document Analysis with LLM")
    gr.Markdown("Upload a PDF document and ask questions about its content.")
    
    with gr.Row():
        with gr.Column(scale=1):
            pdf_input = gr.File(label="Upload PDF Document", file_types=[".pdf"])
            model_choice = gr.Dropdown(
                choices=[
                    "nvidia/llama-3.1-nemotron-nano-8b-v1:free",
                    "mistralai/mistral-7b-instruct-v0.1:free",
                    "meta-llama/llama-2-13b-chat:free"
                ],
                label="LLM Model",
                value="nvidia/llama-3.1-nemotron-nano-8b-v1:free"
            )
            question_input = gr.Textbox(label="Ask a question (or leave empty for summary)", lines=2)
            submit_btn = gr.Button("Process", variant="primary")
        
        with gr.Column(scale=2):
            output = gr.Textbox(label="Response", lines=15)
    
    # Set up event handlers
    submit_btn.click(
        fn=process_query,
        inputs=[pdf_input, question_input, model_choice],
        outputs=output
    )
    
    gr.Markdown("### πŸ“ Notes")
    gr.Markdown("- For large documents, only the first 3000 characters are analyzed")
    gr.Markdown("- You can change the LLM model from the dropdown menu")
    gr.Markdown("- Leave the question field empty to get a general summary")

# Launch the app
app.launch(debug=True, share=True)