Yescia's picture
Update app.py
38a637f verified
# 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()