| |
| |
|
|
| import gradio as gr |
| import os |
| import tempfile |
| from datetime import datetime |
| from weasyprint import HTML |
|
|
| |
| from extract import extract_pdf_text_with_easyocr |
| from parsepers import parse_full_kbis |
|
|
| |
| theme = gr.themes.Base( |
| primary_hue="violet", |
| secondary_hue="orange", |
| neutral_hue="gray", |
| ).set( |
| body_background_fill="#1a1a1a", |
| block_background_fill="#1e1e1e", |
| input_background_fill="#2d2d2d", |
| button_primary_background_fill="#f97316", |
| button_primary_background_fill_hover="#ea580c", |
| ) |
|
|
| css = """ |
| /* Full CSS from your original app — insert here */ |
| .gradio-container { |
| background: #1a1a1a !important; |
| color: #e4e4e7 !important; |
| font-family: 'Inter', system-ui, sans-serif; |
| font-size: 15px; |
| line-height: 1.6; |
| } |
| |
| /* Radio button and input visibility fixes */ |
| .radio label, .radio input[type="radio"] + span { |
| color: #ffffff !important; |
| background-color: rgb(45, 45, 45) !important; |
| } |
| .radio input[type="radio"]:checked + span { |
| background-color: #6d28d9 !important; |
| } |
| .radio label:hover { |
| background-color: #5b21b6 !important; |
| } |
| |
| input, textarea { |
| color: #ffffff !important; |
| } |
| """ |
|
|
| |
| EXPORT_DIR = "exports" |
| os.makedirs(EXPORT_DIR, exist_ok=True) |
|
|
| with gr.Blocks(theme=theme, css=css, title="K-bis Analyzer") as demo: |
| gr.HTML(""" |
| <div id="chat-header"> |
| <div class="brand"> |
| <div class="brand-icon">K-bis</div> |
| <div class="brand-text"> |
| <h1>K-bis Analyzer</h1> |
| <p>Automatic analysis of K-bis extracts via OCR and structured parsing</p> |
| <p>Jonathan Corke, all rights reserved</p> |
| </div> |
| </div> |
| </div> |
| """) |
|
|
| chatbot = gr.Chatbot(height=620, show_label=False) |
|
|
| pdf_upload = gr.File( |
| label="Upload a K-bis extract (PDF)", |
| file_types=[".pdf"], |
| container=False |
| ) |
|
|
| with gr.Row(): |
| submit = gr.Button("Analyze", variant="primary", elem_classes="button-primary") |
| summarize = gr.Button("Summarize Core Parts", variant="secondary") |
| export = gr.Button("Export to PDF", variant="secondary") |
|
|
| |
| state_report = gr.State("") |
|
|
|
|
| def analyze(pdf_file, history): |
| if pdf_file is None: |
| return history + [["User", "Please upload a K-bis PDF."]], "" |
|
|
| temp_extracted = tempfile.NamedTemporaryFile(mode="w+", suffix="_extracted.txt", delete=False, |
| encoding="utf-8").name |
| temp_analysis = tempfile.NamedTemporaryFile(mode='w', suffix="_analysis.txt", delete=False, |
| encoding="utf-8").name |
|
|
| try: |
| extract_pdf_text_with_easyocr(pdf_file.name, save_to_file=temp_extracted) |
|
|
| |
| with open(temp_extracted, "r", encoding="utf-8") as f: |
| extracted_text = f.read() |
| print("=== Extracted Text from OCR ===") |
| print(extracted_text) |
| print("=== End of Extracted Text ===") |
|
|
| parse_full_kbis(temp_extracted, output_file=temp_analysis) |
|
|
| with open(temp_analysis, "r", encoding="utf-8") as f: |
| report = f.read() |
|
|
| |
| full_report_md = f""" |
| <details> |
| <summary>Full Report (click to expand)</summary> |
| <pre>{report}</pre> |
| </summary> |
| </details> |
| """ |
|
|
| history.append([f"Analysis of {os.path.basename(pdf_file.name)}", full_report_md]) |
|
|
| except Exception as e: |
| history.append(["User", f"Error: {str(e)}"]) |
| report = "" |
|
|
| finally: |
| for path in [temp_extracted, temp_analysis]: |
| if os.path.exists(path): |
| os.unlink(path) |
|
|
| return history, report |
|
|
|
|
| def summarize_core(report, history): |
| if not report or "Error" in report: |
| history.append(["Summarize", "No valid report to summarize."]) |
| return history |
|
|
| |
| lines = report.split("\n") |
| core_keys = ["SIREN", "Dénomination", "Forme juridique", "Adresse", "Gérant(s)", "Associé(s)", |
| "Date de début d'activité"] |
| core_summary = "Core Parts Summary\n\n" |
| for line in lines: |
| for key in core_keys: |
| if line.startswith(key + ":"): |
| core_summary += line + "\n" |
| break |
|
|
| history.append(["Summarize Core Parts", core_summary]) |
| return history |
|
|
|
|
| def export_pdf(report, history): |
| if not report or "Error" in report: |
| history.append(["Export", "No valid report to export."]) |
| return history |
|
|
| timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") |
| pdf_path = os.path.join(EXPORT_DIR, f"kbis_report_{timestamp}.pdf") |
|
|
| html = f""" |
| <html> |
| <head><meta charset="utf-8"><title>K-bis Report</title></head> |
| <body style="font-family: Arial, sans-serif; padding: 40px; line-height: 1.6;"> |
| <h1 style="text-align: center; color: #6d28d9;">K-bis Analysis</h1> |
| <pre style="white-space: pre-wrap; font-size: 14px;">{report}</pre> |
| <footer style="margin-top: 50px; text-align: center; color: #666; font-size: 12px;"> |
| Generated by K-bis Analyzer — Jonathan Corke © 2025 |
| </footer> |
| </body> |
| </html> |
| """ |
|
|
| try: |
| HTML(string=html).write_pdf(pdf_path) |
| msg = f"Export successful: {pdf_path}" |
| except Exception as e: |
| msg = f"Export error: {str(e)}" |
|
|
| history.append(["Export PDF", msg]) |
| return history |
|
|
|
|
| submit.click(analyze, inputs=[pdf_upload, chatbot], outputs=[chatbot, state_report]) |
| summarize.click(summarize_core, inputs=[state_report, chatbot], outputs=chatbot) |
| export.click(export_pdf, inputs=[state_report, chatbot], outputs=chatbot) |
|
|
| if __name__ == "__main__": |
| demo.launch(server_name="0.0.0.0", server_port=7860, share=False) |