Spaces:
Runtime error
Runtime error
Commit
·
d84cc75
1
Parent(s):
7697a39
Update app.py
Browse files
app.py
CHANGED
@@ -1,9 +1,3 @@
|
|
1 |
-
"""
|
2 |
-
This module provides functions for working with PDF files and URLs. It uses the urllib.request library
|
3 |
-
to download files from URLs, and the fitz library to extract text from PDF files. And GPT3 modules to generate
|
4 |
-
text completions.
|
5 |
-
"""
|
6 |
-
|
7 |
import urllib.request
|
8 |
import fitz
|
9 |
import re
|
@@ -13,55 +7,18 @@ import openai
|
|
13 |
import gradio as gr
|
14 |
import os
|
15 |
from sklearn.neighbors import NearestNeighbors
|
16 |
-
from typing import Optional, Union, IO
|
17 |
-
|
18 |
-
|
19 |
-
def download_pdf(url: str, output_path: str) -> None:
|
20 |
-
"""
|
21 |
-
Downloads a PDF file from the given URL and saves it to the specified output path.
|
22 |
|
23 |
-
|
24 |
-
url (str): The URL of the PDF file to be downloaded.
|
25 |
-
output_path (str): The file path where the downloaded PDF file will be saved.
|
26 |
-
|
27 |
-
Returns:
|
28 |
-
None
|
29 |
-
"""
|
30 |
urllib.request.urlretrieve(url, output_path)
|
31 |
|
32 |
|
33 |
-
def preprocess(text
|
34 |
-
"""
|
35 |
-
Preprocesses the given text by replacing newline characters with spaces and removing extra whitespaces.
|
36 |
-
|
37 |
-
Args:
|
38 |
-
text (str): The input text to be preprocessed.
|
39 |
-
|
40 |
-
Returns:
|
41 |
-
str: The preprocessed text with newline characters replaced by spaces and extra whitespaces removed.
|
42 |
-
|
43 |
-
Example:
|
44 |
-
>>> preprocess("Hello\\n world!")
|
45 |
-
'Hello world!'
|
46 |
-
"""
|
47 |
text = text.replace('\n', ' ')
|
48 |
-
text = re.sub(
|
49 |
return text
|
50 |
|
51 |
|
52 |
-
def pdf_to_text(path
|
53 |
-
"""
|
54 |
-
Converts a PDF file to a list of text strings.
|
55 |
-
|
56 |
-
Args:
|
57 |
-
path (str): The path to the PDF file.
|
58 |
-
start_page (int): The page number to start extracting text from (default is 1).
|
59 |
-
end_page (int): Page number to stop extracting text at (default is None, which means extract text from all ]
|
60 |
-
pages)
|
61 |
-
|
62 |
-
Returns:
|
63 |
-
list: A list of text strings extracted from the PDF file.
|
64 |
-
"""
|
65 |
doc = fitz.open(path)
|
66 |
total_pages = doc.page_count
|
67 |
|
@@ -79,33 +36,16 @@ def pdf_to_text(path: str, start_page: int = 1, end_page: Optional[int] = None)
|
|
79 |
return text_list
|
80 |
|
81 |
|
82 |
-
def text_to_chunks(texts
|
83 |
-
"""
|
84 |
-
Splits a list of texts into chunks of specified length and formats them as strings.
|
85 |
-
|
86 |
-
Args:
|
87 |
-
- texts: A list of strings to be split into chunks.
|
88 |
-
- word_length: An integer representing the maximum number of words in each chunk. Default is 150.
|
89 |
-
- start_page: An integer representing the starting page number. Default is 1.
|
90 |
-
|
91 |
-
Returns:
|
92 |
-
- A list of formatted string chunks, where each chunk contains a page number, enclosed in square brackets,
|
93 |
-
followed by the chunk of text enclosed in double quotes.
|
94 |
-
|
95 |
-
Example:
|
96 |
-
>>> texts = ['This is a sample text for testing the function.', 'It should split the text into chunks of 5 words.']
|
97 |
-
>>> text_to_chunks(texts, word_length=5, start_page=3)
|
98 |
-
['[3] "This is a sample text for"', '[3] "testing the function. It should"',
|
99 |
-
'[4] "split the text into chunks of"','[4] "5 words."']
|
100 |
-
"""
|
101 |
text_toks = [t.split(' ') for t in texts]
|
|
|
102 |
chunks = []
|
103 |
-
|
104 |
for idx, words in enumerate(text_toks):
|
105 |
for i in range(0, len(words), word_length):
|
106 |
chunk = words[i:i+word_length]
|
107 |
if (i+word_length) > len(words) and (len(chunk) < word_length) and (
|
108 |
-
|
109 |
text_toks[idx+1] = chunk + text_toks[idx+1]
|
110 |
continue
|
111 |
chunk = ' '.join(chunk).strip()
|
@@ -114,78 +54,33 @@ def text_to_chunks(texts: list[str], word_length: int = 150, start_page: int = 1
|
|
114 |
return chunks
|
115 |
|
116 |
|
117 |
-
class SemanticSearch
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
def __init__(self) -> None:
|
123 |
-
"""
|
124 |
-
Initializes an instance of the class.
|
125 |
-
|
126 |
-
Attributes:
|
127 |
-
-----------
|
128 |
-
use : tensorflow_hub.KerasLayer
|
129 |
-
A pre-trained Universal Sentence Encoder model from TensorFlow Hub.
|
130 |
-
fitted : bool
|
131 |
-
A flag indicating whether the model has been fitted to data or not.
|
132 |
-
"""
|
133 |
-
self.use = hub.load(
|
134 |
-
'https://tfhub.dev/google/universal-sentence-encoder/4')
|
135 |
self.fitted = False
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
Fits the nearest neighbor model to the given data.
|
140 |
-
|
141 |
-
Args:
|
142 |
-
data (list[str]): A list of strings to fit the model on.
|
143 |
-
batch (int): The batch size to use when computing text embeddings. Defaults to 1000.
|
144 |
-
n_neighbors (int): The number of nearest neighbors to find for each query. Defaults to 5.
|
145 |
-
|
146 |
-
Returns:
|
147 |
-
None
|
148 |
-
"""
|
149 |
self.data = data
|
150 |
self.embeddings = self.get_text_embedding(data, batch=batch)
|
151 |
n_neighbors = min(n_neighbors, len(self.embeddings))
|
152 |
self.nn = NearestNeighbors(n_neighbors=n_neighbors)
|
153 |
self.nn.fit(self.embeddings)
|
154 |
self.fitted = True
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
Finds nearest neighbors to a given text in the embedding space.
|
159 |
-
|
160 |
-
Args:
|
161 |
-
text (str): The input text to find nearest neighbors for.
|
162 |
-
return_data (bool): Whether to return the actual data points corresponding to the nearest neighbors.
|
163 |
-
If False, returns only the indices of the nearest neighbors. Defaults to True.
|
164 |
-
|
165 |
-
Returns:
|
166 |
-
Union[List[str], np.ndarray]: If return_data is True, returns a list of strings representing the
|
167 |
-
nearest neighbors. If return_data is False, returns a numpy array of shape (n_neighbors,)
|
168 |
-
containing the indices of the nearest neighbors.
|
169 |
-
"""
|
170 |
inp_emb = self.use([text])
|
171 |
neighbors = self.nn.kneighbors(inp_emb, return_distance=False)[0]
|
172 |
-
|
173 |
if return_data:
|
174 |
return [self.data[i] for i in neighbors]
|
175 |
else:
|
176 |
return neighbors
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
Generates embeddings for a list of texts using the Universal Sentence Encoder.
|
181 |
-
|
182 |
-
Args:
|
183 |
-
texts (List[str]): A list of strings to generate embeddings for.
|
184 |
-
batch (int): The batch size to use when generating embeddings. Defaults to 1000.
|
185 |
-
|
186 |
-
Returns:
|
187 |
-
np.ndarray: An array of shape (n_texts, embedding_size) containing the embeddings for each text.
|
188 |
-
"""
|
189 |
embeddings = []
|
190 |
for i in range(0, len(texts), batch):
|
191 |
text_batch = texts[i:(i+batch)]
|
@@ -195,47 +90,16 @@ class SemanticSearch(object):
|
|
195 |
return embeddings
|
196 |
|
197 |
|
198 |
-
def load_recommender(path: str, start_page: int = 1) -> str:
|
199 |
-
"""
|
200 |
-
Loads embeddings from file if available, otherwise generates embeddings and saves them to file.
|
201 |
-
|
202 |
-
Args:
|
203 |
-
path (str): The path of the PDF file.
|
204 |
-
start_page (int): The page number to start generating embeddings from. Default is 1.
|
205 |
|
206 |
-
|
207 |
-
str: A message indicating whether embeddings were loaded from file or generated and saved to file.
|
208 |
-
"""
|
209 |
global recommender
|
210 |
-
pdf_file = os.path.basename(path)
|
211 |
-
embeddings_file = f"{pdf_file}_{start_page}.npy"
|
212 |
-
|
213 |
-
if os.path.isfile(embeddings_file):
|
214 |
-
embeddings = np.load(embeddings_file)
|
215 |
-
recommender.embeddings = embeddings
|
216 |
-
recommender.fitted = True
|
217 |
-
return "Embeddings loaded from file"
|
218 |
-
|
219 |
texts = pdf_to_text(path, start_page=start_page)
|
220 |
chunks = text_to_chunks(texts, start_page=start_page)
|
221 |
recommender.fit(chunks)
|
222 |
-
np.save(embeddings_file, recommender.embeddings)
|
223 |
return 'Corpus Loaded.'
|
224 |
|
225 |
-
|
226 |
-
|
227 |
-
"""
|
228 |
-
Generates text using OpenAI's GPT-3 language model.
|
229 |
-
|
230 |
-
Parameters:
|
231 |
-
openai_key (str): The API key for accessing OpenAI's API.
|
232 |
-
prompt (str): The starting text prompt to generate the text from.
|
233 |
-
engine (str): The ID of the language model to use. Defaults to "text-davinci-003".
|
234 |
-
|
235 |
-
Returns:
|
236 |
-
str: The generated text based on the given prompt.
|
237 |
-
"""
|
238 |
-
openai.api_key = openai_key
|
239 |
completions = openai.Completion.create(
|
240 |
engine=engine,
|
241 |
prompt=prompt,
|
@@ -247,101 +111,35 @@ def generate_text(openai_key: str, prompt: str, engine: str = "text-davinci-003"
|
|
247 |
message = completions.choices[0].text
|
248 |
return message
|
249 |
|
250 |
-
|
251 |
-
def generate_text2(openai_key: str, prompt: str, engine: str = "gpt-3.5-turbo-0301") -> str:
|
252 |
-
"""
|
253 |
-
Generates text using OpenAI's GPT-3 language model.
|
254 |
-
|
255 |
-
Args:
|
256 |
-
openai_key (str): The API key for accessing OpenAI's GPT-3 language model.
|
257 |
-
prompt (str): The user's prompt to generate a response to.
|
258 |
-
engine (str, optional): The name of the GPT-3 engine to use. Defaults to "gpt-3.5-turbo-0301".
|
259 |
-
|
260 |
-
Returns:
|
261 |
-
str: The generated text response from the GPT-3 language model.
|
262 |
-
"""
|
263 |
-
openai.api_key = openai_key
|
264 |
-
messages = [{'role': 'system', 'content': 'You are a helpful assistant.'},
|
265 |
-
{'role': 'user', 'content': prompt}]
|
266 |
-
|
267 |
-
completions = openai.ChatCompletion.create(
|
268 |
-
model=engine,
|
269 |
-
messages=messages,
|
270 |
-
max_tokens=512,
|
271 |
-
n=1,
|
272 |
-
stop=None,
|
273 |
-
temperature=0.7,
|
274 |
-
)
|
275 |
-
message = completions.choices[0].message['content']
|
276 |
-
return message
|
277 |
-
|
278 |
-
|
279 |
-
def generate_answer(question: str, openai_key: str) -> str:
|
280 |
-
"""
|
281 |
-
Generates an answer to the given question using OpenAI's GPT-3 language model.
|
282 |
-
|
283 |
-
Args:
|
284 |
-
question (str): The question to answer.
|
285 |
-
openai_key (str): The API key for accessing OpenAI's GPT-3 API.
|
286 |
-
|
287 |
-
Returns:
|
288 |
-
str: The generated answer to the question.
|
289 |
-
"""
|
290 |
topn_chunks = recommender(question)
|
291 |
prompt = ""
|
292 |
prompt += 'search results:\n\n'
|
293 |
for c in topn_chunks:
|
294 |
prompt += c + '\n\n'
|
295 |
-
|
296 |
prompt += "Instructions: Compose a comprehensive reply to the query using the search results given. "\
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
prompt += f"Query: {question}\nAnswer:"
|
306 |
-
answer = generate_text(
|
307 |
return answer
|
308 |
|
309 |
|
310 |
-
def question_answer(url
|
311 |
-
|
312 |
-
Generates an answer to a given question using OpenAI's GPT-3 model.
|
313 |
-
|
314 |
-
Parameters:
|
315 |
-
-----------
|
316 |
-
url : str
|
317 |
-
The URL of a webpage to extract text from. If provided, the text will be saved as a PDF and used
|
318 |
-
as input for the model.
|
319 |
-
file : file-like object
|
320 |
-
A file object containing a PDF document to use as input for the model. If provided, the text will
|
321 |
-
be extracted from the PDF and used as input for the model.
|
322 |
-
question : str
|
323 |
-
The question to generate an answer for.
|
324 |
-
openai_key : str
|
325 |
-
An API key for accessing OpenAI's GPT-3 model.
|
326 |
-
|
327 |
-
Returns:
|
328 |
-
--------
|
329 |
-
str
|
330 |
-
The generated answer to the given question.
|
331 |
-
|
332 |
-
Raises:
|
333 |
-
-------
|
334 |
-
ValueError
|
335 |
-
If both `url` and `file` are empty or if both are provided.
|
336 |
-
If `question` is empty.
|
337 |
-
"""
|
338 |
-
if openai_key.strip() == '':
|
339 |
return '[ERROR]: Please enter you Open AI Key. Get your key here : https://platform.openai.com/account/api-keys'
|
340 |
if url.strip() == '' and file == None:
|
341 |
-
return '[ERROR]: Both URL and PDF is empty. Provide
|
342 |
-
|
343 |
if url.strip() != '' and file != None:
|
344 |
-
return '[ERROR]: Both URL and PDF is provided. Please provide only one (
|
345 |
|
346 |
if url.strip() != '':
|
347 |
glob_url = url
|
@@ -358,22 +156,13 @@ def question_answer(url: str, file: IO[str], question: str, openai_key: str) ->
|
|
358 |
if question.strip() == '':
|
359 |
return '[ERROR]: Question field is empty'
|
360 |
|
361 |
-
return generate_answer(question,
|
362 |
|
363 |
|
364 |
recommender = SemanticSearch()
|
365 |
|
366 |
title = 'PDF GPT'
|
367 |
-
description = """
|
368 |
-
1. The problem is that Open AI has a 4K token limit and cannot take an entire PDF file as input. Additionally,
|
369 |
-
it sometimes returns irrelevant responses due to poor embeddings. ChatGPT cannot directly talk to external data.
|
370 |
-
The solution is PDF GPT, which allows you to chat with an uploaded PDF file using GPT functionalities.
|
371 |
-
The application breaks the document into smaller chunks and generates embeddings using a powerful Deep Averaging
|
372 |
-
Network Encoder. A semantic search is performed on your query, and the top relevant chunks are used to generate a
|
373 |
-
response.
|
374 |
-
2. The returned response can even cite the page number in square brackets([]) where the information is located,
|
375 |
-
adding credibility to the responses and helping to locate pertinent information quickly. The Responses are much
|
376 |
-
better than the naive responses by Open AI."""
|
377 |
|
378 |
with gr.Blocks() as demo:
|
379 |
|
@@ -381,18 +170,13 @@ with gr.Blocks() as demo:
|
|
381 |
gr.Markdown(description)
|
382 |
|
383 |
with gr.Row():
|
384 |
-
|
385 |
with gr.Group():
|
386 |
-
gr.Markdown(
|
387 |
-
|
388 |
-
'Get your Open AI API key <a href="https://platform.openai.com/account/api-keys">here</a>'
|
389 |
-
'</p>'
|
390 |
-
)
|
391 |
-
openAI_key = gr.Textbox(label='Enter your OpenAI API key here')
|
392 |
url = gr.Textbox(label='Enter PDF URL here')
|
393 |
gr.Markdown("<center><h4>OR<h4></center>")
|
394 |
-
file = gr.File(
|
395 |
-
label='Upload your PDF/ Research Paper / Book here', file_types=['.pdf'])
|
396 |
question = gr.Textbox(label='Enter your question here')
|
397 |
btn = gr.Button(value='Submit')
|
398 |
btn.style(full_width=True)
|
@@ -400,7 +184,6 @@ with gr.Blocks() as demo:
|
|
400 |
with gr.Group():
|
401 |
answer = gr.Textbox(label='The answer to your question is :')
|
402 |
|
403 |
-
btn.click(question_answer, inputs=[
|
404 |
-
|
405 |
-
|
406 |
demo.launch()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import urllib.request
|
2 |
import fitz
|
3 |
import re
|
|
|
7 |
import gradio as gr
|
8 |
import os
|
9 |
from sklearn.neighbors import NearestNeighbors
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
|
11 |
+
def download_pdf(url, output_path):
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
urllib.request.urlretrieve(url, output_path)
|
13 |
|
14 |
|
15 |
+
def preprocess(text):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
text = text.replace('\n', ' ')
|
17 |
+
text = re.sub('\s+', ' ', text)
|
18 |
return text
|
19 |
|
20 |
|
21 |
+
def pdf_to_text(path, start_page=1, end_page=None):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
doc = fitz.open(path)
|
23 |
total_pages = doc.page_count
|
24 |
|
|
|
36 |
return text_list
|
37 |
|
38 |
|
39 |
+
def text_to_chunks(texts, word_length=150, start_page=1):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
text_toks = [t.split(' ') for t in texts]
|
41 |
+
page_nums = []
|
42 |
chunks = []
|
43 |
+
|
44 |
for idx, words in enumerate(text_toks):
|
45 |
for i in range(0, len(words), word_length):
|
46 |
chunk = words[i:i+word_length]
|
47 |
if (i+word_length) > len(words) and (len(chunk) < word_length) and (
|
48 |
+
len(text_toks) != (idx+1)):
|
49 |
text_toks[idx+1] = chunk + text_toks[idx+1]
|
50 |
continue
|
51 |
chunk = ' '.join(chunk).strip()
|
|
|
54 |
return chunks
|
55 |
|
56 |
|
57 |
+
class SemanticSearch:
|
58 |
+
|
59 |
+
def __init__(self):
|
60 |
+
self.use = hub.load('https://tfhub.dev/google/universal-sentence-encoder/4')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
self.fitted = False
|
62 |
+
|
63 |
+
|
64 |
+
def fit(self, data, batch=1000, n_neighbors=5):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
self.data = data
|
66 |
self.embeddings = self.get_text_embedding(data, batch=batch)
|
67 |
n_neighbors = min(n_neighbors, len(self.embeddings))
|
68 |
self.nn = NearestNeighbors(n_neighbors=n_neighbors)
|
69 |
self.nn.fit(self.embeddings)
|
70 |
self.fitted = True
|
71 |
+
|
72 |
+
|
73 |
+
def __call__(self, text, return_data=True):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
inp_emb = self.use([text])
|
75 |
neighbors = self.nn.kneighbors(inp_emb, return_distance=False)[0]
|
76 |
+
|
77 |
if return_data:
|
78 |
return [self.data[i] for i in neighbors]
|
79 |
else:
|
80 |
return neighbors
|
81 |
+
|
82 |
+
|
83 |
+
def get_text_embedding(self, texts, batch=1000):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
embeddings = []
|
85 |
for i in range(0, len(texts), batch):
|
86 |
text_batch = texts[i:(i+batch)]
|
|
|
90 |
return embeddings
|
91 |
|
92 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
|
94 |
+
def load_recommender(path, start_page=1):
|
|
|
|
|
95 |
global recommender
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
texts = pdf_to_text(path, start_page=start_page)
|
97 |
chunks = text_to_chunks(texts, start_page=start_page)
|
98 |
recommender.fit(chunks)
|
|
|
99 |
return 'Corpus Loaded.'
|
100 |
|
101 |
+
def generate_text(openAI_key,prompt, engine="text-davinci-003"):
|
102 |
+
openai.api_key = openAI_key
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
completions = openai.Completion.create(
|
104 |
engine=engine,
|
105 |
prompt=prompt,
|
|
|
111 |
message = completions.choices[0].text
|
112 |
return message
|
113 |
|
114 |
+
def generate_answer(question,openAI_key):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
115 |
topn_chunks = recommender(question)
|
116 |
prompt = ""
|
117 |
prompt += 'search results:\n\n'
|
118 |
for c in topn_chunks:
|
119 |
prompt += c + '\n\n'
|
120 |
+
|
121 |
prompt += "Instructions: Compose a comprehensive reply to the query using the search results given. "\
|
122 |
+
"Cite each reference using [ Page Number] notation (every result has this number at the beginning). "\
|
123 |
+
"Citation should be done at the end of each sentence. If the search results mention multiple subjects "\
|
124 |
+
"with the same name, create separate answers for each. Only include information found in the results and "\
|
125 |
+
"don't add any additional information. Make sure the answer is correct and don't output false content. "\
|
126 |
+
"If the text does not relate to the query, simply state 'Text Not Found in PDF'. Ignore outlier "\
|
127 |
+
"search results which has nothing to do with the question. Only answer what is asked. The "\
|
128 |
+
"answer should be short and concise. Answer step-by-step. \n\nQuery: {question}\nAnswer: "
|
129 |
+
|
130 |
prompt += f"Query: {question}\nAnswer:"
|
131 |
+
answer = generate_text(openAI_key, prompt,"text-davinci-003")
|
132 |
return answer
|
133 |
|
134 |
|
135 |
+
def question_answer(url, file, question,openAI_key):
|
136 |
+
if openAI_key.strip()=='':
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
137 |
return '[ERROR]: Please enter you Open AI Key. Get your key here : https://platform.openai.com/account/api-keys'
|
138 |
if url.strip() == '' and file == None:
|
139 |
+
return '[ERROR]: Both URL and PDF is empty. Provide atleast one.'
|
140 |
+
|
141 |
if url.strip() != '' and file != None:
|
142 |
+
return '[ERROR]: Both URL and PDF is provided. Please provide only one (eiter URL or PDF).'
|
143 |
|
144 |
if url.strip() != '':
|
145 |
glob_url = url
|
|
|
156 |
if question.strip() == '':
|
157 |
return '[ERROR]: Question field is empty'
|
158 |
|
159 |
+
return generate_answer(question,openAI_key)
|
160 |
|
161 |
|
162 |
recommender = SemanticSearch()
|
163 |
|
164 |
title = 'PDF GPT'
|
165 |
+
description = """ PDF GPT allows you to chat with your PDF file using Universal Sentence Encoder and Open AI. It gives hallucination free response than other tools as the embeddings are better than OpenAI. The returned response can even cite the page number in square brackets([]) where the information is located, adding credibility to the responses and helping to locate pertinent information quickly."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
|
167 |
with gr.Blocks() as demo:
|
168 |
|
|
|
170 |
gr.Markdown(description)
|
171 |
|
172 |
with gr.Row():
|
173 |
+
|
174 |
with gr.Group():
|
175 |
+
gr.Markdown(f'<p style="text-align:center">Get your Open AI API key <a href="https://platform.openai.com/account/api-keys">here</a></p>')
|
176 |
+
openAI_key=gr.Textbox(label='Enter your OpenAI API key here')
|
|
|
|
|
|
|
|
|
177 |
url = gr.Textbox(label='Enter PDF URL here')
|
178 |
gr.Markdown("<center><h4>OR<h4></center>")
|
179 |
+
file = gr.File(label='Upload your PDF/ Research Paper / Book here', file_types=['.pdf'])
|
|
|
180 |
question = gr.Textbox(label='Enter your question here')
|
181 |
btn = gr.Button(value='Submit')
|
182 |
btn.style(full_width=True)
|
|
|
184 |
with gr.Group():
|
185 |
answer = gr.Textbox(label='The answer to your question is :')
|
186 |
|
187 |
+
btn.click(question_answer, inputs=[url, file, question,openAI_key], outputs=[answer])
|
188 |
+
#openai.api_key = os.getenv('Your_Key_Here')
|
|
|
189 |
demo.launch()
|