lei0lei commited on
Commit
82ad063
Β·
1 Parent(s): c9e149f
Files changed (4) hide show
  1. app.py +21 -20
  2. chain.py +131 -0
  3. interface.py +47 -0
  4. requirements.txt +3 -1
app.py CHANGED
@@ -2,26 +2,27 @@
2
 
3
  # Demo code for hugging face
4
  import gradio as gr
5
- import random
 
 
6
 
7
- def chat(message, history):
8
- history = history or []
9
- if message.startswith("How many"):
10
- response = random.randint(1, 10)
11
- elif message.startswith("How"):
12
- response = random.choice(["Great", "Good", "Okay", "Bad"])
13
- elif message.startswith("Where"):
14
- response = random.choice(["Here", "There", "Somewhere"])
15
- else:
16
- response = "I don't know"
17
- history.append((message, response))
18
- return history, history
19
 
 
 
 
 
20
 
21
- iface = gr.Interface(
22
- chat,
23
- ["text", "state"],
24
- ["chatbot", "state"],
25
- allow_flagging="never",
26
- )
27
- iface.launch()
 
 
 
 
 
 
 
2
 
3
  # Demo code for hugging face
4
  import gradio as gr
5
+ import os
6
+ from interface import create_demo
7
+ from chain import set_api_key, enable_api_box, add_text, generate_response, render_file
8
 
9
+ demo, api_key, change_api_key, chatbot, show_img, txt, submit_btn, btn = create_demo()
 
 
 
 
 
 
 
 
 
 
 
10
 
11
+ # Set up event handlers
12
+ with demo:
13
+ # Event handler for submitting the OpenAI API key
14
+ api_key.submit(set_api_key, inputs=[api_key], outputs=[api_key])
15
 
16
+ # Event handler for changing the API key
17
+ change_api_key.click(enable_api_box, outputs=[api_key])
18
+
19
+ # Event handler for uploading a PDF
20
+ btn.upload(render_file, inputs=[btn], outputs=[show_img])
21
+
22
+ # Event handler for submitting text and generating response
23
+ submit_btn.click(add_text, inputs=[chatbot, txt], outputs=[chatbot], queue=False).\
24
+ success(generate_response, inputs=[chatbot, txt, btn], outputs=[chatbot,txt]).\
25
+ success(render_file, inputs=[btn], outputs=[show_img])
26
+
27
+ if __name__ == "__main__":
28
+ demo.launch()
chain.py ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from langchain.embeddings.openai import OpenAIEmbeddings
3
+ from langchain.text_splitter import CharacterTextSplitter
4
+ from langchain.vectorstores import Chroma
5
+ from langchain.chains import ConversationalRetrievalChain
6
+ from langchain.chat_models import ChatOpenAI
7
+ from langchain.document_loaders import PyPDFLoader
8
+ import fitz
9
+ from PIL import Image
10
+ import gradio as gr
11
+
12
+ # Global variables
13
+ count = 0
14
+ n = 0
15
+ chat_history = []
16
+ chain = ''
17
+
18
+ # Function to set the OpenAI API key
19
+ def set_api_key(api_key):
20
+ """
21
+ Sets the OpenAI API key in the environment variable.
22
+
23
+ Args:
24
+ api_key (str): The OpenAI API key.
25
+
26
+ Returns:
27
+ str: Message indicating the API key is set.
28
+ """
29
+ os.environ['OPENAI_API_KEY'] = api_key
30
+ return 'OpenAI API key is set'
31
+
32
+ # Function to enable the API key input box
33
+ def enable_api_box():
34
+ """
35
+ Enables the API key input box.
36
+
37
+ Returns:
38
+ None
39
+ """
40
+ return
41
+
42
+ # Function to add text to the chat history
43
+ def add_text(history, text):
44
+ """
45
+ Adds the user's input text to the chat history.
46
+
47
+ Args:
48
+ history (list): List of tuples representing the chat history.
49
+ text (str): The user's input text.
50
+
51
+ Returns:
52
+ list: Updated chat history with the new user input.
53
+ """
54
+ if not text:
55
+ raise gr.Error('Enter text')
56
+ history.append((text, ''))
57
+ return history
58
+
59
+ # Function to process the PDF file and create a conversation chain
60
+ def process_file(file):
61
+ """
62
+ Processes the uploaded PDF file and creates a conversational retrieval chain.
63
+
64
+ Args:
65
+ file (FileStorage): The uploaded PDF file.
66
+
67
+ Returns:
68
+ ConversationalRetrievalChain: The created conversational retrieval chain.
69
+ """
70
+ if 'OPENAI_API_KEY' not in os.environ:
71
+ raise gr.Error('Upload your OpenAI API key')
72
+
73
+ loader = PyPDFLoader(file.name)
74
+ documents = loader.load()
75
+
76
+ embeddings = OpenAIEmbeddings()
77
+
78
+ pdf_search = Chroma.from_documents(documents, embeddings)
79
+
80
+ chain = ConversationalRetrievalChain.from_llm(ChatOpenAI(temperature=0.3),
81
+ retriever=pdf_search.as_retriever(search_kwargs={"k": 1}),
82
+ return_source_documents=True)
83
+ return chain
84
+
85
+ # Function to generate a response based on the chat history and query
86
+ def generate_response(history, query, btn):
87
+ """
88
+ Generates a response based on the chat history and user's query.
89
+
90
+ Args:
91
+ history (list): List of tuples representing the chat history.
92
+ query (str): The user's query.
93
+ btn (FileStorage): The uploaded PDF file.
94
+
95
+ Returns:
96
+ tuple: Updated chat history with the generated response and the next page number.
97
+ """
98
+ global count, n, chat_history, chain
99
+
100
+ if not btn:
101
+ raise gr.Error(message='Upload a PDF')
102
+ if count == 0:
103
+ chain = process_file(btn)
104
+ count += 1
105
+
106
+ result = chain({"question": query, 'chat_history': chat_history}, return_only_outputs=True)
107
+ chat_history.append((query, result["answer"]))
108
+ n = list(result['source_documents'][0])[1][1]['page']
109
+
110
+ for char in result['answer']:
111
+ history[-1][-1] += char
112
+ return history, " "
113
+
114
+ # Function to render a specific page of a PDF file as an image
115
+ def render_file(file):
116
+ """
117
+ Renders a specific page of a PDF file as an image.
118
+
119
+ Args:
120
+ file (FileStorage): The PDF file.
121
+
122
+ Returns:
123
+ PIL.Image.Image: The rendered page as an image.
124
+ """
125
+ global n
126
+ doc = fitz.open(file.name)
127
+ page = doc[n]
128
+ # Render the page as a PNG image with a resolution of 300 DPI
129
+ pix = page.get_pixmap(matrix=fitz.Matrix(300 / 72, 300 / 72))
130
+ image = Image.frombytes('RGB', [pix.width, pix.height], pix.samples)
131
+ return image
interface.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+
3
+ # Gradio application setup
4
+ def create_demo():
5
+ with gr.Blocks(title= " PDF Chatbot",
6
+ theme = "Soft" # Change the theme here
7
+ ) as demo:
8
+
9
+ # Create a Gradio block
10
+
11
+ with gr.Column():
12
+ with gr.Row():
13
+ with gr.Column(scale=0.8):
14
+ api_key = gr.Textbox(
15
+ placeholder='Enter your OpenAI API key',
16
+ show_label=False,
17
+ interactive=True,
18
+ container=False)
19
+
20
+ with gr.Column(scale=0.2):
21
+ change_api_key = gr.Button('Update API Key')
22
+
23
+ with gr.Row():
24
+ chatbot = gr.Chatbot(value=[], elem_id='chatbot', height=680)
25
+ show_img = gr.Image(label='PDF Preview', height=680)
26
+ # show_img = gr.Image(label='PDF Preview', tool='select', height=680)
27
+
28
+ with gr.Row():
29
+ with gr.Column(scale=0.60):
30
+ text_input = gr.Textbox(
31
+ show_label=False,
32
+ placeholder="Ask your pdf?",
33
+ container=False)
34
+
35
+ with gr.Column(scale=0.20):
36
+ submit_btn = gr.Button('Send')
37
+
38
+ with gr.Column(scale=0.20):
39
+ upload_btn = gr.UploadButton("πŸ“ Upload PDF", file_types=[".pdf"])
40
+
41
+
42
+ return demo, api_key, change_api_key, chatbot, show_img, text_input, submit_btn, upload_btn
43
+
44
+ if __name__ == '__main__':
45
+ demo, api_key, change_api_key, chatbot, show_img, text_input, submit_btn, upload_btn = create_demo()
46
+ demo.queue()
47
+ demo.launch()
requirements.txt CHANGED
@@ -5,4 +5,6 @@ pydantic
5
  duckduckgo-search
6
  docarray
7
  huggingface_hub
8
- gradio==4.7.1
 
 
 
5
  duckduckgo-search
6
  docarray
7
  huggingface_hub
8
+ gradio==4.7.1
9
+ pymupdf
10
+ uvicorn==0.24.0