File size: 6,534 Bytes
ac0107c
11e4aa2
2762feb
 
5431ef4
2762feb
 
9dba011
2762feb
9dba011
2762feb
11e4aa2
 
2762feb
11e4aa2
 
2762feb
11e4aa2
9dba011
2762feb
9dba011
2762feb
 
609ec31
 
9dba011
609ec31
2762feb
63a104d
ac0107c
2762feb
ac0107c
 
 
 
 
 
 
 
 
 
 
11e4aa2
2762feb
 
11e4aa2
 
ac0107c
 
 
11e4aa2
 
ac0107c
 
63a104d
 
9dba011
 
11e4aa2
ac0107c
ce58fd6
2762feb
63a104d
9dba011
ac0107c
63a104d
9dba011
ac0107c
9dba011
ac0107c
 
 
 
 
63a104d
 
ac0107c
 
 
 
 
63a104d
ac0107c
 
 
 
 
 
 
 
 
 
 
 
 
 
2762feb
11e4aa2
63a104d
 
ac0107c
63a104d
2762feb
 
92bff3a
2762feb
ac0107c
11e4aa2
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# FILE: main_web.py (Hugging Face Demo - v1.0)

import gradio as gr
import asyncio
import logging
import os
import sys
from typing import Optional, Dict, Any

# --- Basic Setup ---
APP_TITLE = "ZOTHEOS - Ethical Fusion AI"
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
logger = logging.getLogger("ZOTHEOS_Interface_HF")

def get_asset_path(filename: str) -> str:
    return filename if os.path.exists(filename) else os.path.join('assets', filename)

logo_path_verified = get_asset_path("zotheos_logo.png")
GUMROAD_LINK = "https://zotheos.gumroad.com/l/jibfv"

# --- Core Logic Imports ---
try:
    from modules.main_fusion_public import MainFusionPublic
    ai_system = MainFusionPublic()
except Exception as e:
    logger.error(f"CRITICAL: Failed to initialize AI system: {e}")
    ai_system = None

# --- DEFINITIVE "OBSIDIAN PRO" CSS ---
zotheos_desktop_css = """
@import url('https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Inter:wght@400;600;700&display=swap');
body { background: linear-gradient(135deg, #000000, #1c1c1c) !important; background-attachment: fixed !important; color: #f0f0f0 !important; font-family: 'Inter', sans-serif !important; }
.gradio-container { background: transparent !important; max-width: 1100px !important; margin: 2rem auto !important; padding: 2rem !important; }
#header_logo img { max-height: 80px !important; filter: brightness(0) invert(1) !important; margin-bottom: 1rem !important; }
#header_subtitle { font-family: 'Bebas Neue', cursive !important; font-size: 2.2rem !important; text-transform: uppercase !important; letter-spacing: 3px !important; line-height: 1.2 !important; }
#header_tagline { color: #a0a0a0 !important; font-size: 1.1rem !important; margin-top: -5px !important; margin-bottom: 3rem !important; text-align: center; }
.gradio-textbox, .gradio-accordion { background-color: #121212 !important; border: 1px solid #333333 !important; border-radius: 12px !important;}
.gradio-textbox textarea { font-size: 1.1rem !important; color: #f0f0f0 !important; }
.result-box { background-color: rgba(18, 18, 18, 0.9) !important; border: 1px solid #333333 !important; border-radius: 12px !important; padding: 1.5rem 2rem !important; backdrop-filter: blur(5px); }
.result-box h2 { font-family: 'Bebas Neue', cursive !important; font-size: 1.7rem !important; color: white !important; border-bottom: 1px solid #333333; padding-bottom: 0.75rem; margin-bottom: 1.5rem; text-align: left; }
.cosmic-loading { padding: 3rem; text-align:center; } .orbital-spinner { width:40px;height:40px;border-radius:50%;animation:spin 1s linear infinite;margin:0 auto 15px auto; border: 4px solid #333; border-top-color: white;} @keyframes spin{to{transform:rotate(360deg)}}
.cta-button { background: #FFFFFF !important; color: #000000 !important; font-weight: bold !important; } .cta-button:hover { background: #e0e0e0 !important; }
footer { display: none !important; }
"""

# --- Build Gradio Interface ---
def build_interface():
    zotheos_theme = gr.themes.Base(primary_hue=gr.themes.colors.neutral, secondary_hue=gr.themes.colors.neutral).set(
        button_primary_background_fill="white", button_primary_background_fill_hover="#e0e0e0", button_primary_text_color="black",
        button_secondary_background_fill="#2C2C2C", button_secondary_text_color="white", block_radius="12px"
    )

    with gr.Blocks(theme=zotheos_theme, css=zotheos_desktop_css, title=APP_TITLE) as demo:
        with gr.Column(elem_classes="gradio-container"):
            gr.Image(value=logo_path_verified, elem_id="header_logo", show_label=False, container=False, interactive=False)
            gr.Markdown("<h1 id='header_subtitle' style='text-align:center;'>Ethical Fusion AI</h1>", elem_id="header-title-wrapper")
            gr.Markdown("<p id='header_tagline'>Fusing perspectives for deeper truth.</p>", elem_id="tagline-wrapper")
            
            with gr.Accordion("🔥 Get the Full Offline Desktop Version", open=True):
                gr.Markdown("This web demo uses smaller, slower models. For the full-power, GPU-accelerated, 100% private experience, download the ZOTHEOS Public Beta.")
                gr.Button("Download Full Version on Gumroad", link=GUMROAD_LINK, elem_classes="cta-button")
            
            gr.Markdown("---")
            
            query_input = gr.Textbox(label="Your Inquiry:", placeholder="e.g., What is universal peace?", lines=8)
            submit_button = gr.Button("Process Inquiry (Web Demo)", variant="primary")
            
            status_indicator = gr.HTML(visible=False)

            with gr.Column(elem_id="results_column", visible=False) as results_box:
                 with gr.Column(elem_classes="result-box"):
                    synthesized_summary_output = gr.Markdown()
                    fusion_output = gr.Markdown()
        
        # --- ✅ FAILSAFE EVENT HANDLER ---
        async def process_query_wrapper(query):
            # Stage 1: Show loading state
            loading_html = "<div class='cosmic-loading'><div class='orbital-spinner'></div></div>"
            yield { status_indicator: gr.update(value=loading_html, visible=True), results_box: gr.update(visible=False), submit_button: gr.update(interactive=False) }

            # Stage 2: Process the query
            if not ai_system:
                summary_text, perspectives_text = "## SYSTEM OFFLINE\n\n[The AI engine failed to load.]", ""
            else:
                response = await ai_system.process_query_with_fusion(query)
                summary_text = response.split("###")[0]
                perspectives_text = "###" + response.split("###", 1)[1] if "###" in response else ""

            # Stage 3: Show results
            yield {
                status_indicator: gr.update(visible=False),
                results_box: gr.update(visible=True),
                synthesized_summary_output: summary_text,
                fusion_output: perspectives_text,
                submit_button: gr.update(interactive=True)
            }

        submit_button.click(
            fn=process_query_wrapper,
            inputs=[query_input],
            outputs=[status_indicator, results_box, synthesized_summary_output, fusion_output, submit_button]
        )
    return demo

# --- Main Execution Block ---
if __name__ == "__main__":
    logger.info("--- Initializing ZOTHEOS Hugging Face Demo (v5.1 - Failsafe) ---")
    zotheos_interface = build_interface()
    zotheos_interface.queue().launch()