Spaces:
Sleeping
Sleeping
# Loading required libraries | |
import gradio as gr # Gradio: A library for building web interfaces | |
import requests # requests: A library for sending HTTP requests. | |
from openai import OpenAI # OpenAI: Clients compatible with the Upstage Solar API | |
# ------------------------------ | |
# π Defining a document parsing function | |
# ------------------------------ | |
def parse_document(file, api_key): | |
""" | |
Function to convert uploaded PDF document to HTML (using Upstage Document Parse API) | |
""" | |
url = "https://api.upstage.ai/v1/document-ai/document-parse" # API request URL | |
headers = {'Authorization': f'Bearer {api_key}'} # Authentication header settingsμ | |
files = {"document": open(file.name, "rb")} # read file | |
data = { | |
"base64_encoding": "['table']", # Table data is encoded in base64 | |
"model": "document-parse" # Specify usage model | |
} | |
response = requests.post(url, headers=headers, files=files, data=data) # POST request | |
result = response.json() # Parsing response results | |
html_text = result.get("content", {}).get("html", "") # HTML Extraction | |
return html_text | |
# ------------------------------ | |
# π¬ Defining a document-based Q&A function | |
# ------------------------------ | |
def chat_with_document(history, html_text, user_question, api_key): | |
""" | |
Solar LLM functions to answer user questions based on document content | |
""" | |
if not html_text.strip(): | |
return history, history, "β οΈ Please convert the document first." # Guidance if there is no document | |
# OpenAI client initialization (Upstage Solar LLM) | |
client = OpenAI( | |
api_key=api_key, | |
base_url="https://api.upstage.ai/v1" | |
) | |
# Reset previous conversation history | |
history = history or [] | |
# System prompt: Request a response based on the contents of the HTML document | |
system_prompt = f"""The following is a financial statement document extracted in HTML format. | |
Please answer user questions accurately and concisely in Korean, based on the text within HTML tags. | |
Document: | |
{html_text} | |
""" | |
# Message composition (System β User/bot conversation β Current question) | |
messages = [{"role": "system", "content": system_prompt}] | |
for user, bot in history: | |
messages.append({"role": "user", "content": user}) | |
messages.append({"role": "assistant", "content": bot}) | |
messages.append({"role": "user", "content": user_question}) | |
# Solar LLM Call | |
try: | |
response = client.chat.completions.create( | |
model="solar-pro", # Model name to use | |
messages=messages, # Deliver the entire message | |
temperature=0, # Minimize creativity | |
max_tokens=1024 # maximum response length | |
) | |
bot_reply = response.choices[0].message.content # Extract response message | |
except Exception as e: | |
bot_reply = f"β οΈ An error occurred: {str(e)}" # Error handling | |
# Return after updating conversation history | |
history.append((user_question, bot_reply)) | |
return history, history, "" | |
# ------------------------------ | |
# π HTML View Toggle Function | |
# ------------------------------ | |
def toggle_html_view(current_html, is_visible): | |
""" | |
Function to toggle the HTML view/hide state | |
""" | |
return ( | |
gr.update(value=current_html, visible=not is_visible), # Hide/Show Text Box | |
gr.update(value=current_html, visible=is_visible), # HTML rendering opposite behavior | |
not is_visible # state inversion | |
) | |
# ------------------------------ | |
# π¦ Gradio UI configuration | |
# ------------------------------ | |
with gr.Blocks() as demo: | |
# Show title and description | |
gr.Markdown("# π Financial Statement Analysis Chatbot") | |
gr.Markdown("1. Convert PDF documents to HTML using the Document Parse API.\n" | |
"2. Answer document-based questions with Solar LLM.") | |
# π API Key input window (entered directly by the user) | |
api_key_input = gr.Textbox(label="π Upstage API Key", type="password", placeholder="Paste your API key here") | |
# π File Upload + Document Conversion Button | |
with gr.Row(): | |
file_input = gr.File(label="π Upload financial statements") | |
parse_btn = gr.Button("Document HTML conversion") | |
# π HTML output area (text + HTML toggle view) | |
html_output = gr.Textbox(label="π document content", lines=10, visible=True, elem_id="scrollable-html") | |
html_display = gr.HTML(visible=False, elem_id="scrollable-html-display") | |
toggle_html_btn = gr.Button("π Switch HTML views") | |
html_visible_state = gr.State(False) # Save view state | |
# Click the Convert Document button β Generate HTML | |
parse_btn.click( | |
fn=parse_document, | |
inputs=[file_input, api_key_input], | |
outputs=html_output | |
) | |
# When clicking the HTML view switch button β Execute the toggle action | |
toggle_html_btn.click( | |
fn=toggle_html_view, | |
inputs=[html_output, html_visible_state], | |
outputs=[html_output, html_display, html_visible_state] | |
) | |
# π¬ Chatbot Interface | |
chatbot = gr.Chatbot(label="π¬ Document-based Q&A", height=400) | |
user_question = gr.Textbox(label="β Please enter your question", lines=2) | |
answer_btn = gr.Button("Generate Answer") | |
chat_state = gr.State([]) # Save conversation state | |
# π‘ Example Question Button Configuration | |
with gr.Row(): | |
gr.Markdown("π‘example questions:") | |
ex1 = gr.Button("Which company's financial statements are these?") | |
ex2 = gr.Button("What was the total net sales for the third quarter?") | |
# Click the example question button β Run question + answer | |
for btn, question in [(ex1, "Which company's financial statements are these?"), (ex2, "What was the total net sales for the first quarter?")]: | |
btn.click( | |
fn=lambda q=question: q, # Pass question text | |
inputs=[], | |
outputs=user_question | |
).then( | |
fn=chat_with_document, | |
inputs=[chat_state, html_output, user_question, api_key_input], | |
outputs=[chatbot, chat_state, user_question], | |
show_progress=True | |
) | |
# Submit a User Question β Solar LLM Answers | |
answer_btn.click( | |
fn=chat_with_document, | |
inputs=[chat_state, html_output, user_question, api_key_input], | |
outputs=[chatbot, chat_state, user_question], | |
show_progress=True | |
) | |
# ------------------------------ | |
# π¨ Styling a scrollable HTML box | |
# ------------------------------ | |
demo.css = """ | |
#scrollable-html, #scrollable-html-display { | |
max-height: 400px; | |
overflow: auto; | |
border: 1px solid #ccc; | |
padding: 10px; | |
} | |
""" | |
# π run app | |
if __name__ == "__main__": | |
demo.launch() |