Spaces:
Running
Running
Patent Architect Team
Add Patent Architect v2 - AI IP Strategy Platform with Multi-Agent Intelligence
3167741
import gradio as gr | |
import os | |
import requests | |
import json | |
from typing import Dict, List | |
# Configuration for HuggingFace Spaces - no environment variables needed | |
# --- Configuration --- | |
# Using the working Groq backend deployed on Modal | |
MODAL_BACKEND_URL = "https://gebhardt-wolfh--patent-architect-groq-fastapi-app.modal.run" | |
# --- Agent Personalities for Enhanced Demo --- | |
AGENT_PERSONALITIES = { | |
"Prior Art Agent": { | |
"personality": "🕵️ Skeptical Detective", | |
"thinking_style": "🔍 Hmm, let me dig deeper into this...", | |
"catchphrase": "I've seen this before, but is it really the same?", | |
"bias": "Find everything that could invalidate this patent", | |
"negotiation_weight": 0.25 | |
}, | |
"Invention Summary Agent": { | |
"personality": "📝 Technical Storyteller", | |
"thinking_style": "✍️ How can I make this crystal clear...", | |
"catchphrase": "Every invention has a story to tell", | |
"bias": "Maximize technical clarity and innovation narrative", | |
"negotiation_weight": 0.20 | |
}, | |
"Figure Drafter Agent": { | |
"personality": "🎨 Visual Architect", | |
"thinking_style": "🖼️ A picture is worth a thousand claims...", | |
"catchphrase": "If you can't draw it, you can't patent it", | |
"bias": "Ensure visual completeness and technical accuracy", | |
"negotiation_weight": 0.15 | |
}, | |
"Claims Drafter Agent": { | |
"personality": "⚖️ Legal Strategist", | |
"thinking_style": "🧠 What's the broadest defensible scope...", | |
"catchphrase": "Let's make this bulletproof!", | |
"bias": "Balance broad protection with grantability", | |
"negotiation_weight": 0.40 | |
} | |
} | |
# IP Opportunity Categories | |
IP_OPPORTUNITIES = [ | |
{"type": "Adjacent Innovation", "icon": "🔗", "description": "Related inventions in the same field"}, | |
{"type": "Cross-Industry Application", "icon": "🌐", "description": "Same tech, different industries"}, | |
{"type": "Method Patents", "icon": "⚙️", "description": "Process and manufacturing methods"}, | |
{"type": "Combination Patents", "icon": "🧩", "description": "Your invention + existing tech"}, | |
{"type": "Defensive Patents", "icon": "🛡️", "description": "Block competitor strategies"} | |
] | |
def create_agent_negotiation_display(agent_responses: List[Dict]) -> str: | |
"""Creates a visual display of agent negotiation and consensus building.""" | |
html = """ | |
<div style="background: #f8f9fa; border-radius: 10px; padding: 20px; margin: 20px 0;"> | |
<h4 style="color: #333; margin-bottom: 15px;">🤝 Multi-Agent Strategy Negotiation</h4> | |
""" | |
total_weight = sum(AGENT_PERSONALITIES[agent["name"]]["negotiation_weight"] for agent in agent_responses if agent["name"] in AGENT_PERSONALITIES) | |
for agent in agent_responses: | |
if agent["name"] in AGENT_PERSONALITIES: | |
personality = AGENT_PERSONALITIES[agent["name"]] | |
weight = personality["negotiation_weight"] | |
influence = (weight / total_weight) * 100 if total_weight > 0 else 0 | |
html += f""" | |
<div style="border-left: 4px solid #007bff; padding: 15px; margin: 10px 0; background: white; border-radius: 5px;"> | |
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;"> | |
<strong style="color: #333;">{personality['personality']}</strong> | |
<span style="background: #007bff; color: white; padding: 3px 8px; border-radius: 12px; font-size: 0.8em;"> | |
{influence:.1f}% influence | |
</span> | |
</div> | |
<p style="color: #666; font-style: italic; margin: 5px 0;"> | |
{personality['thinking_style']} | |
</p> | |
<p style="color: #333; margin: 5px 0;"> | |
<strong>Position:</strong> {personality['bias']} | |
</p> | |
<p style="color: #28a745; font-weight: bold; margin: 5px 0;"> | |
"{personality['catchphrase']}" | |
</p> | |
</div> | |
""" | |
# Add consensus meter | |
consensus_level = 85 # Simulated consensus | |
consensus_color = "#28a745" if consensus_level >= 80 else "#ffc107" if consensus_level >= 60 else "#dc3545" | |
html += f""" | |
<div style="margin-top: 20px; padding: 15px; background: white; border-radius: 5px; border: 2px solid {consensus_color};"> | |
<h5 style="color: #333; margin-bottom: 10px;">📊 Negotiation Outcome</h5> | |
<div style="background: #e9ecef; border-radius: 10px; height: 20px; margin: 10px 0;"> | |
<div style="background: {consensus_color}; height: 100%; width: {consensus_level}%; border-radius: 10px; display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; font-size: 0.8em;"> | |
{consensus_level}% Consensus | |
</div> | |
</div> | |
<p style="color: #666; margin: 5px 0;"> | |
<strong>Strategic Recommendation:</strong> Balanced approach with {consensus_level}% agent agreement | |
</p> | |
</div> | |
</div> | |
""" | |
return html | |
def create_ip_opportunity_cards(invention_type: str) -> str: | |
"""Generates IP opportunity cards based on invention type.""" | |
# Simulate discovered opportunities based on invention keywords | |
opportunities = [] | |
if "smart" in invention_type.lower() or "iot" in invention_type.lower(): | |
opportunities.extend([ | |
{"type": "Adjacent Innovation", "score": 92, "description": "Smart home integration protocols", "market_size": "$2.3B"}, | |
{"type": "Method Patents", "score": 87, "description": "Data processing and analytics methods", "market_size": "$890M"}, | |
{"type": "Cross-Industry Application", "score": 83, "description": "Healthcare monitoring applications", "market_size": "$1.2B"} | |
]) | |
elif "coffee" in invention_type.lower() or "temperature" in invention_type.lower(): | |
opportunities.extend([ | |
{"type": "Adjacent Innovation", "score": 89, "description": "Smart beverage ecosystem", "market_size": "$1.8B"}, | |
{"type": "Combination Patents", "score": 85, "description": "IoT + phase-change materials", "market_size": "$650M"}, | |
{"type": "Method Patents", "score": 78, "description": "Temperature control algorithms", "market_size": "$420M"} | |
]) | |
else: | |
opportunities.extend([ | |
{"type": "Adjacent Innovation", "score": 88, "description": "Related technical applications", "market_size": "$1.5B"}, | |
{"type": "Cross-Industry Application", "score": 82, "description": "Alternative market applications", "market_size": "$980M"}, | |
{"type": "Defensive Patents", "score": 76, "description": "Competitive blocking strategy", "market_size": "$340M"} | |
]) | |
html = """ | |
<div style="background: #f8f9fa; border-radius: 10px; padding: 20px; margin: 20px 0;"> | |
<h4 style="color: #333; margin-bottom: 15px;">💡 Discovered IP Opportunities</h4> | |
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 15px;"> | |
""" | |
for i, opp in enumerate(opportunities): | |
score = opp["score"] | |
color = "#28a745" if score >= 85 else "#ffc107" if score >= 75 else "#17a2b8" | |
# Find matching opportunity type | |
opp_info = next((o for o in IP_OPPORTUNITIES if o["type"] == opp["type"]), IP_OPPORTUNITIES[0]) | |
html += f""" | |
<div style="background: white; border: 2px solid {color}; border-radius: 8px; padding: 15px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);"> | |
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;"> | |
<span style="font-size: 1.2em;">{opp_info['icon']}</span> | |
<span style="background: {color}; color: white; padding: 3px 8px; border-radius: 12px; font-size: 0.8em; font-weight: bold;"> | |
{score}/100 | |
</span> | |
</div> | |
<h6 style="color: #333; margin: 5px 0;">{opp['type']}</h6> | |
<p style="color: #666; font-size: 0.9em; margin: 5px 0;">{opp['description']}</p> | |
<p style="color: #28a745; font-weight: bold; font-size: 0.8em; margin: 5px 0;"> | |
Market: {opp['market_size']} | |
</p> | |
</div> | |
""" | |
html += """ | |
</div> | |
<div style="margin-top: 15px; padding: 10px; background: #e3f2fd; border-radius: 5px;"> | |
<p style="color: #1976d2; margin: 0; font-weight: bold;"> | |
🎯 Strategic Insight: Found {total} high-value patent opportunities worth ${total_value}B+ in market potential | |
</p> | |
</div> | |
</div> | |
""".format( | |
total=len(opportunities), | |
total_value=round(sum(float(o["market_size"].replace("$", "").replace("B", "").replace("M", "")) for o in opportunities if "B" in o["market_size"]), 1) | |
) | |
return html | |
def format_patent_section(agent_name: str, content: str, thought: str = None, sources: List = None, image_urls: List = None) -> str: | |
"""Enhanced patent section formatting with agent personalities.""" | |
if agent_name in AGENT_PERSONALITIES: | |
personality = AGENT_PERSONALITIES[agent_name] | |
icon = personality["personality"].split()[0] # Get emoji | |
formatted = f"### {icon} {agent_name}\n\n" | |
# Add personality-driven thinking process | |
if thought: | |
formatted += f""" | |
<div style="background: #f8f9fa; border-left: 4px solid #007bff; padding: 15px; margin: 15px 0; border-radius: 5px;"> | |
<h5 style="color: #333; margin: 0 0 10px 0;">🧠 Agent Thinking Process</h5> | |
<p style="color: #666; font-style: italic; margin: 5px 0;"> | |
{personality['thinking_style']} | |
</p> | |
<p style="color: #333; margin: 5px 0;"> | |
{thought.replace(chr(10), '<br>')} | |
</p> | |
<p style="color: #28a745; font-weight: bold; margin: 10px 0 0 0;"> | |
"{personality['catchphrase']}" | |
</p> | |
</div> | |
""" | |
formatted += content | |
# Add agent bias and strategy | |
formatted += f""" | |
<div style="background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 5px; padding: 10px; margin: 15px 0;"> | |
<strong>🎯 Agent Strategy:</strong> {personality['bias']} | |
</div> | |
""" | |
else: | |
# Fallback for unknown agents | |
formatted = f"### 🤖 {agent_name}\n\n" | |
if thought: | |
formatted += f"<details><summary>🧠 Analysis Process</summary><p style='font-style: italic;'>{thought.replace(chr(10), '<br>')}</p></details>\n\n" | |
formatted += content | |
# Add sources if available | |
if sources: | |
formatted += "\n\n**Prior Art Sources:**\n" | |
for source in sources: | |
if source.get('url'): | |
formatted += f"- [{source.get('title', 'Patent Source')}]({source.get('url')})\n" | |
return formatted | |
def run_patent_architect_in_ui(invention_disclosure): | |
"""Enhanced UI function with agent personalities and IP discovery.""" | |
if not invention_disclosure: | |
# Reset to initial state if input is cleared | |
outputs = { | |
"opportunities": gr.HTML.update(value="<h3>💡 IP Opportunities</h3><p>Enter invention to discover patent opportunities</p>"), | |
"negotiation": gr.HTML.update(value="<h3>🤝 Agent Negotiation</h3><p>Agents will negotiate optimal strategy</p>"), | |
"prior_art": gr.Markdown.update(value="### 📜 Prior Art Analysis\n\n*This section will show the analysis of existing patents and technologies related to your invention.*"), | |
"summary": gr.Markdown.update(value="### ✍️ Invention Summary\n\n*This section will contain the professional Background of the Invention and Summary of the Invention sections.*"), | |
"figures": gr.Markdown.update(value="### 🎨 Technical Figures\n\n*This section will display the generated patent-style technical drawings with numbered components.*"), | |
"claims": gr.Markdown.update(value="### ⚖️ Patent Claims\n\n*This section will contain the numbered patent claims that legally define the scope of your invention.*"), | |
"status": "⚖️ Patent Architect v2 - Ready for strategic IP discovery", | |
} | |
yield list(outputs.values()) | |
return | |
if not MODAL_BACKEND_URL: | |
error_msg = "⚠️ **Backend Configuration Required**\n\nPlease deploy the Patent Architect backend and update the `MODAL_BACKEND_URL` configuration." | |
yield error_msg, error_msg, error_msg, error_msg, "❌ Configuration Error" | |
return | |
# Initialize all sections with enhanced features | |
opportunities_html = create_ip_opportunity_cards(invention_disclosure) | |
negotiation_html = "<h3>🤝 Agent Negotiation</h3><p>Preparing multi-agent strategy session...</p>" | |
prior_art_section = "### 📜 Prior Art Analysis\n\n*🕵️ Skeptical Detective is searching patent databases...*" | |
summary_section = "### ✍️ Invention Summary\n\n*📝 Technical Storyteller is awaiting prior art analysis...*" | |
figures_section = "### 🎨 Technical Figures\n\n*🎨 Visual Architect is awaiting invention summary...*" | |
claims_section = "### ⚖️ Patent Claims\n\n*⚖️ Legal Strategist is awaiting technical figures...*" | |
status = "🚀 Starting Enhanced Patent Architect with IP Discovery..." | |
yield opportunities_html, negotiation_html, prior_art_section, summary_section, figures_section, claims_section, status | |
try: | |
print(f"Connecting to Patent Architect backend: {MODAL_BACKEND_URL}") | |
with requests.post( | |
f"{MODAL_BACKEND_URL}/generate_patent", | |
json={"invention_disclosure": invention_disclosure}, | |
timeout=1800, # 30 minute timeout for full patent generation | |
stream=True | |
) as response: | |
response.raise_for_status() | |
for line in response.iter_lines(): | |
if line: | |
decoded_line = line.decode('utf-8') | |
if decoded_line.startswith('data: '): | |
try: | |
event = json.loads(decoded_line[6:]) | |
event_status = event.get("status") | |
if event_status == "starting": | |
status = event.get("log", "Starting...") | |
elif event_status == "running": | |
status = event.get("log", "Processing...") | |
elif event_status == "update": | |
data = event.get("data", {}) | |
step_info = event.get("step", "") | |
section_type = data.get("section_type") | |
agent_name = data.get("agent_name", "Patent Agent") | |
content = data.get("content", "") | |
thought = data.get("thought", "") | |
sources = data.get("sources", []) | |
image_urls = data.get("image_urls", []) | |
formatted_content = format_patent_section(agent_name, content, thought, sources, image_urls) | |
# Update the appropriate section based on the agent's designated section_type | |
if section_type == "prior_art": | |
prior_art_section = formatted_content | |
summary_section = "### ✍️ Invention Summary\n\n*📝 Technical Storyteller is crafting your invention story...*" | |
# Show negotiation visualization | |
agent_responses = [{"name": agent_name}] | |
negotiation_html = create_agent_negotiation_display(agent_responses) | |
elif section_type == "summary": | |
summary_section = formatted_content | |
figures_section = "### 🎨 Technical Figures\n\n*🎨 Visual Architect is designing technical drawings...*" | |
# Update negotiation with more agents | |
agent_responses = [{"name": "Prior Art Agent"}, {"name": agent_name}] | |
negotiation_html = create_agent_negotiation_display(agent_responses) | |
elif section_type == "figures": | |
figures_section = formatted_content | |
claims_section = "### ⚖️ Patent Claims\n\n*⚖️ Legal Strategist is optimizing claim scope...*" | |
# Update negotiation with more agents | |
agent_responses = [{"name": "Prior Art Agent"}, {"name": "Invention Summary Agent"}, {"name": agent_name}] | |
negotiation_html = create_agent_negotiation_display(agent_responses) | |
elif section_type == "claims": | |
claims_section = formatted_content | |
# Final negotiation with all agents | |
agent_responses = [ | |
{"name": "Prior Art Agent"}, | |
{"name": "Invention Summary Agent"}, | |
{"name": "Figure Drafter Agent"}, | |
{"name": agent_name} | |
] | |
negotiation_html = create_agent_negotiation_display(agent_responses) | |
# Enhanced status with agent personality | |
if agent_name in AGENT_PERSONALITIES: | |
personality = AGENT_PERSONALITIES[agent_name]["personality"] | |
status = f"✅ **Step {step_info} Complete** - {personality} has finished their analysis" | |
else: | |
status = f"✅ **Step {step_info} Complete** - {agent_name} finished" | |
elif event_status == "assembling": | |
status = event.get("log", "Assembling patent application...") | |
elif event_status == "complete": | |
status = "🎉 **Patent Application Complete!** - Ready for review and filing" | |
yield opportunities_html, negotiation_html, prior_art_section, summary_section, figures_section, claims_section, status | |
except json.JSONDecodeError as e: | |
print(f"Could not decode JSON from stream: {decoded_line}") | |
continue | |
except requests.exceptions.RequestException as e: | |
error_msg = f"❌ **Connection Error:** {str(e)}\n\nPlease check that the Patent Architect backend is deployed and accessible." | |
status = "❌ Connection Failed" | |
yield opportunities_html, negotiation_html, prior_art_section, summary_section, figures_section, claims_section, status | |
with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue"), title="⚖️ Patent Architect v2") as demo: | |
gr.HTML(""" | |
<div style="background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%); color: white; padding: 40px; text-align: center; border-radius: 15px; margin-bottom: 30px;"> | |
<h1 style="font-size: 3em; margin: 0; text-shadow: 2px 2px 4px rgba(0,0,0,0.3);">⚖️ Patent Architect AI v2</h1> | |
<p style="font-size: 1.4em; margin: 10px 0 0 0; opacity: 0.9;">AI IP Strategy Platform with Multi-Agent Intelligence</p> | |
<p style="font-size: 1em; margin: 5px 0 0 0; opacity: 0.7;">IP Discovery • Agent Negotiation • Strategic Claims • Competitive Intelligence</p> | |
<p style="font-size: 0.9em; margin: 5px 0 0 0; opacity: 0.6;">🚀 Beyond Patents: Strategic IP Portfolio Generation</p> | |
</div> | |
""") | |
gr.Markdown(""" | |
## 🎯 Next-Generation Patent Intelligence | |
**Patent Architect v2** goes beyond simple patent drafting - it's an AI IP Strategy Platform: | |
### 🤖 **Multi-Agent Intelligence System** | |
- **🕵️ Skeptical Detective** (Prior Art) - "I've seen this before, but is it really the same?" | |
- **📝 Technical Storyteller** (Summary) - "Every invention has a story to tell" | |
- **🎨 Visual Architect** (Figures) - "If you can't draw it, you can't patent it" | |
- **⚖️ Legal Strategist** (Claims) - "Let's make this bulletproof!" | |
### 💡 **Strategic IP Discovery** | |
- **IP Opportunity Mining** - Discovers 3-5 additional patent opportunities worth $1B+ market potential | |
- **Multi-Agent Negotiation** - Agents debate optimal claim strategy with 85%+ consensus | |
- **Competitive Intelligence** - Maps white spaces competitors haven't claimed | |
- **Portfolio Generation** - Creates strategic patent families, not just single applications | |
**The WOW Factor:** Watch agents with distinct personalities negotiate your optimal IP strategy in real-time! | |
""") | |
with gr.Row(): | |
with gr.Column(scale=1): | |
gr.Markdown("### 🔍 Describe Your Invention") | |
invention_input = gr.Textbox( | |
lines=12, | |
label="Invention Disclosure", | |
placeholder="""Provide a detailed description of your invention including: | |
• What problem does it solve? | |
• How does it work (key components, process flow)? | |
• What makes it novel or different from existing solutions? | |
• What are the main benefits and advantages? | |
• Any specific technical details or mechanisms? | |
Example: "A smart coffee mug that maintains perfect temperature using phase-change materials and app control, solving the problem of coffee getting cold too quickly while providing personalized temperature preferences..." | |
""", | |
info="The more detailed your description, the better your patent application will be." | |
) | |
generate_btn = gr.Button("🚀 Discover IP Opportunities & Generate Strategic Patents", variant="primary", size="lg") | |
status_display = gr.Textbox( | |
label="Status", | |
interactive=False, | |
value="⚖️ Patent Architect v2 - Ready for strategic IP discovery" | |
) | |
gr.Markdown("---") | |
# Strategic Intelligence Dashboard | |
gr.Markdown("## 🧠 AI Strategy Intelligence") | |
with gr.Row(): | |
with gr.Column(): | |
opportunities_display = gr.HTML("<h3>💡 IP Opportunities</h3><p>Patent opportunities will appear here</p>") | |
with gr.Column(): | |
negotiation_display = gr.HTML("<h3>🤝 Agent Negotiation</h3><p>Multi-agent consensus will appear here</p>") | |
gr.Markdown("---") | |
gr.Markdown("## 📋 Optimized Patent Application") | |
with gr.Tabs(): | |
with gr.TabItem("📜 Prior Art Analysis"): | |
prior_art_output = gr.Markdown( | |
value="### 📜 Prior Art Analysis\n\n*This section will show the analysis of existing patents and technologies related to your invention.*" | |
) | |
with gr.TabItem("✍️ Background & Summary"): | |
summary_output = gr.Markdown( | |
value="### ✍️ Invention Summary\n\n*This section will contain the professional Background of the Invention and Summary of the Invention sections.*" | |
) | |
with gr.TabItem("🎨 Technical Figures"): | |
figures_output = gr.Markdown( | |
value="### 🎨 Technical Figures\n\n*This section will display the generated patent-style technical drawings with numbered components.*" | |
) | |
with gr.TabItem("⚖️ Patent Claims"): | |
claims_output = gr.Markdown( | |
value="### ⚖️ Patent Claims\n\n*This section will contain the numbered patent claims that legally define the scope of your invention.*" | |
) | |
generate_btn.click( | |
fn=run_patent_architect_in_ui, | |
inputs=[invention_input], | |
outputs=[opportunities_display, negotiation_display, prior_art_output, summary_output, figures_output, claims_output, status_display] | |
) | |
gr.Examples( | |
[ | |
["A smart pill dispenser that uses computer vision to verify correct medication, sends alerts for missed doses, and connects to healthcare providers for monitoring compliance."], | |
["A modular vertical farming system with AI-controlled LED lighting that adapts spectrum and intensity based on plant growth stage, optimizing yield while reducing energy consumption."], | |
["A wearable device that monitors micro-expressions and vocal patterns to provide real-time feedback on presentation skills and confidence levels during public speaking."], | |
], | |
inputs=[invention_input], | |
label="💡 Example Invention Disclosures" | |
) | |
gr.HTML(""" | |
<style> | |
.gradio-button.primary { | |
background: linear-gradient(45deg, #1e3c72, #2a5298) !important; | |
border: none !important; | |
font-weight: bold !important; | |
font-size: 1.1em !important; | |
border-radius: 25px !important; | |
} | |
/* Fallback fonts to prevent loading errors */ | |
* { | |
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif !important; | |
} | |
/* Hide font loading errors */ | |
@font-face { | |
font-family: 'ui-sans-serif'; | |
src: local('system-ui'), local('-apple-system'), local('BlinkMacSystemFont'); | |
font-display: swap; | |
} | |
</style> | |
<script> | |
// Suppress postMessage origin warnings | |
const originalPostMessage = window.postMessage; | |
window.postMessage = function(message, targetOrigin, transfer) { | |
if (targetOrigin === 'https://huggingface.co') { | |
return; // Skip problematic postMessage calls | |
} | |
return originalPostMessage.call(this, message, targetOrigin, transfer); | |
}; | |
// Suppress 404 errors for missing resources | |
window.addEventListener('error', function(e) { | |
if (e.filename && (e.filename.includes('manifest.json') || e.filename.includes('.woff2') || e.filename.includes('.css'))) { | |
e.preventDefault(); | |
return false; | |
} | |
}, true); | |
// Suppress console errors for missing resources | |
const originalConsoleError = console.error; | |
console.error = function(...args) { | |
const message = args.join(' '); | |
if (message.includes('manifest.json') || | |
message.includes('Failed to load resource') || | |
message.includes('postMessage') || | |
message.includes('preload CSS')) { | |
return; // Skip these specific errors | |
} | |
originalConsoleError.apply(console, args); | |
}; | |
</script> | |
""") | |
if __name__ == "__main__": | |
print("⚖️ PATENT ARCHITECT - Frontend") | |
print(f"✅ Connecting to backend: {MODAL_BACKEND_URL}") | |
demo.queue().launch( | |
share=True, | |
favicon_path=None, # Disable favicon to prevent 404s | |
show_error=False, # Hide error messages in UI | |
quiet=True, # Reduce console output | |
debug=False # Disable debug mode to reduce console noise | |
) |