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() |