File size: 5,207 Bytes
b2c2b10
 
 
 
 
 
 
 
 
0932db4
 
b2c2b10
 
 
 
 
 
6cf0632
 
b2c2b10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e23044e
b2c2b10
 
 
6cf0632
0932db4
 
e4655c8
0932db4
 
 
b2c2b10
0932db4
e23044e
0932db4
 
 
5425d90
e76890b
477daa4
0932db4
 
 
 
 
 
 
 
6cf0632
0932db4
b2c2b10
 
 
0932db4
 
 
b393081
 
0932db4
b2c2b10
 
 
0932db4
c00c3f0
e76890b
897ecbc
87209c8
b2c2b10
 
 
89f7900
f06a433
89f7900
0932db4
 
 
 
 
6cf0632
e23044e
0932db4
 
 
 
 
b2c2b10
 
 
 
 
6cf0632
e23044e
ce12e8f
b2c2b10
 
 
 
 
87209c8
b2c2b10
 
 
 
cfca8e6
 
b2c2b10
eb6129a
b2c2b10
 
b393081
9c8df4d
b2c2b10
 
534e71b
c00c3f0
9c8df4d
b2c2b10
 
 
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
from transformers import pipeline
import torch
import gradio as gr
import os
from PIL import Image
import pytesseract
import tempfile
import shutil
from pdf2image import convert_from_path
import json
import spaces

model_name = "deepset/roberta-base-squad2"

# Vision QnA requires: PyTesseract for OCR. Tesseract executable needs to be installed separately.
# sudo apt install tesseract-ocr (https://tesseract-ocr.github.io/tessdoc/Installation.html)

vision_qna = pipeline("document-question-answering", model="impira/layoutlm-document-qa", device=0)

def load_file(file_input, encoding = 'utf-8'):  
  if not os.path.exists(file_input):
    raise FileNotFoundError(f"The file does not exist.")

  with open(file_input, 'r', encoding=encoding) as file:
    try:
      content = file.read()
    except UnicodeDecodeError:
      # If a UnicodeDecodeError occurs, try reading with 'latin1' encoding
      with open(file_input, 'r', encoding='latin1') as file:
        content = file.read()

  return content

def save_image(file):
    try:
      temp_dir = tempfile.mkdtemp()
      file_path = os.path.join(temp_dir, os.path.basename(file.name))
      # Copy the file from the temporary Gradio directory to our temporary directory
      shutil.copyfile(file.name, file_path)
      # when working with saving image files through Gradio, 
      # using `shutil.copyfile` to handle `NamedString` objects for file uploads is the correct approach

      return file_path
    except Exception as e:
      print(e)


def save_pdf(file):
  temp_dir = tempfile.mkdtemp()
  pdf_path = os.path.join(temp_dir, os.path.basename(file.name))
  
  # Copy the file from the temporary Gradio directory to our temporary directory
  shutil.copyfile(file.name, pdf_path)
  
  # Convert PDF to images
  images = convert_from_path(pdf_path)
  
  image_paths = []
  for i, img in enumerate(images):
      image_path = os.path.join(temp_dir, f'page_{i}.png')
      img.save(image_path, 'PNG')
      image_paths.append(image_path)
  
  # print(image_paths)
  return image_paths


def qna_image_content(content, question):
    result = vision_qna(content, question)
    page_result = get_page_result(result, question)
    return get_result_json([page_result])
    
 
  

def get_page_result(raw_result, question):
    # print(raw_result[0]['answer'], raw_result[0]['score'])
    page_result = {
        "result": {
            "question": question,
            "answer": raw_result[0]['answer']
        },
        "confidence": raw_result[0]['score']
    }
    return page_result
    
def get_result_json(page_results):
    result = {
        "pages": page_results
    }
    return json.dumps(result)
def qna_pdf_content(image_paths, question, short_circuit_threshold):
  all_page_results = []
  try:
      for image_path in image_paths:
          result = vision_qna(image=image_path, question=question)
        
          page_result = get_page_result(result, question)
          all_page_results.append(page_result)
          if result[0]['score'] >= short_circuit_threshold:
              break
      return get_result_json(all_page_results)
  except Exception as e:
      return f"An error occurred during processing: {e}"

@spaces.GPU
def predict(doc, question, short_circuit_threshold):
 
  file_input = doc    
  if file_input is not None and question is not None:
    print(f"File type: {type(file_input)}")
    print(f"File name: {file_input.name}")

    filename_lower = file_input.name.lower()
    is_pdf = filename_lower.endswith('.pdf') or filename_lower.endswith("blob")
    if is_pdf:
        try:
            image_paths = save_pdf(file_input)
            
            if not question:
                return "Please provide a question."
            result = qna_pdf_content(image_paths, question, short_circuit_threshold)
            # print(result)
            return result
        except Exception as e:
            return f"An error occurred during vision processing: {e}" 

    else:
      try:
        img_file_path = save_image(file_input)
        
        if not question:
            return "Please provide a question."
        result = qna_image_content(img_file_path, question)
        # print(result)
        return result

      except Exception as e:
        return f"An error occurred during vision processing: {e}" 

  else:
      raise gr.Error("Provide both a document and a question")

gr.close_all()

with gr.Blocks() as demo:
    gr.Markdown("# LayoutLM Document QnA") 
    gr.Markdown("This app performs visual document QnA for docs in PDF or image formats.")

    file_input = gr.File(label="File Upload", file_types=['png', 'jpeg', 'jpg', 'bmp', 'gif', 'pdf'])

    question = gr.Textbox(label="Question", placeholder="Enter your question here...")
    threshold_input = gr.Number(label="Short-circuit threshold", value=0.97, minimum=0, maximum=1)
    output = gr.JSON(label="Answer")


    button = gr.Button("Run model")
    button.click(predict, inputs=[file_input, question, threshold_input], 
                outputs=output)
demo.launch()

# print(qna_image_content("https://gradientflow.com/wp-content/uploads/2023/10/newsletter87-RAG-simple.png", "What is the step prior to embedding?"))