Spaces:
Sleeping
Sleeping
| # #main.py | |
| # import sys | |
| # import os | |
| # import warnings | |
| # from crew import DocProcessing | |
| # import re | |
| # # Fix Unicode encoding issues on Windows | |
| # if sys.platform.startswith('win'): | |
| # import codecs | |
| # sys.stdout = codecs.getwriter('utf-8')(sys.stdout.detach()) | |
| # sys.stderr = codecs.getwriter('utf-8')(sys.stderr.detach()) | |
| # warnings.filterwarnings("ignore", category=SyntaxWarning, module="pysbd") | |
| # def determine_file_type(file_path): | |
| # """ | |
| # Determine the file type based on the file extension. | |
| # Args: | |
| # file_path (str): Path to the file | |
| # Returns: | |
| # str: 'pdf' if the file is a PDF, 'image' otherwise | |
| # """ | |
| # _, ext = os.path.splitext(file_path) | |
| # if ext.lower() == '.pdf': | |
| # return 'pdf' | |
| # return 'image' | |
| # def run(): | |
| # """ | |
| # Run the crew with file paths received from command line arguments. | |
| # """ | |
| # # Get file paths from command line arguments | |
| # file_paths = sys.argv[1:] if len(sys.argv) > 1 else [] | |
| # if not file_paths: | |
| # print("No file paths provided. Usage: python main.py <file_path1> <file_path2> ...") | |
| # return | |
| # # Process the first file (you can modify this to handle multiple files if needed) | |
| # file_path = file_paths[0] | |
| # file_type = determine_file_type(file_path) | |
| # # Prepare inputs for the CrewAI | |
| # inputs = { | |
| # "file_path": file_path, | |
| # "file_type": file_type, | |
| # } | |
| # try: | |
| # # Pass the inputs to the crew kickoff method | |
| # result = DocProcessing().crew().kickoff(inputs=inputs) | |
| # # Try to get the actual output content from CrewOutput | |
| # return result | |
| # except Exception as e: | |
| # error_msg = f"An error occurred while running the crew: {e}" | |
| # print(error_msg) | |
| # raise Exception(error_msg) | |
| # if __name__ == "__main__": | |
| # run() | |
| #&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& | |
| # import gradio as gr | |
| # import os | |
| # import tempfile | |
| # import shutil | |
| # from pathlib import Path | |
| # import warnings | |
| # from typing import Tuple, Optional | |
| # import sys | |
| # # Suppress warnings | |
| # warnings.filterwarnings("ignore", category=SyntaxWarning, module="pysbd") | |
| # # Import your existing modules | |
| # from crew import DocProcessing | |
| # from tools.custom_tool import landing_ai_document_analysis | |
| # def get_landing_ai_key(): | |
| # """Get Landing AI API key from environment (HF secrets or local .env)""" | |
| # # Try multiple environment variable names for flexibility | |
| # return ( | |
| # os.getenv("LANDING_AI_API_KEY") or # HuggingFace secrets or production | |
| # os.getenv("LANDING_AI_API_KEY_LOCAL") or # Local development alternative | |
| # os.getenv("LANDINGAI_API_KEY") or # Alternative naming | |
| # os.getenv("LANDING_API_KEY") # Another alternative | |
| # ) | |
| # def validate_api_key(api_key: str) -> bool: | |
| # """Validate Anthropic API key format""" | |
| # if not api_key: | |
| # return False | |
| # return api_key.startswith("sk-ant-") and len(api_key) > 20 | |
| # def determine_file_type(file_path: str) -> str: | |
| # """Determine file type based on extension""" | |
| # _, ext = os.path.splitext(file_path) | |
| # return 'pdf' if ext.lower() == '.pdf' else 'image' | |
| # def process_document(file, anthropic_api_key: str) -> Tuple[str, str]: | |
| # """ | |
| # Process the uploaded document and return analysis + generated code | |
| # Args: | |
| # file: Uploaded file object from Gradio | |
| # anthropic_api_key: User's Anthropic API key | |
| # Returns: | |
| # Tuple of (analysis_result, generated_code) | |
| # """ | |
| # try: | |
| # # Validate inputs | |
| # if not file: | |
| # return "β No file uploaded", "" | |
| # if not validate_api_key(anthropic_api_key): | |
| # return "β Invalid Anthropic API key. Please ensure it starts with 'sk-ant-' and is complete.", "" | |
| # # Check if Landing AI key is available | |
| # landing_ai_key = get_landing_ai_key() | |
| # if not landing_ai_key: | |
| # return "β Landing AI API key not configured. Please ensure LANDING_AI_API_KEY is set in environment variables or HuggingFace secrets.", "" | |
| # # Set environment variables securely | |
| # os.environ["ANTHROPIC_API_KEY"] = anthropic_api_key | |
| # os.environ["LANDING_AI_API_KEY"] = landing_ai_key | |
| # # Create temporary directory for processing | |
| # with tempfile.TemporaryDirectory() as temp_dir: | |
| # # Save uploaded file | |
| # file_extension = Path(file.name).suffix | |
| # temp_file_path = os.path.join(temp_dir, f"uploaded_file{file_extension}") | |
| # # Copy uploaded file to temp location | |
| # shutil.copy2(file.name, temp_file_path) | |
| # # Determine file type | |
| # file_type = determine_file_type(temp_file_path) | |
| # # Prepare inputs for CrewAI | |
| # inputs = { | |
| # "file_path": temp_file_path, | |
| # "file_type": file_type, | |
| # } | |
| # # Initialize and run the crew with the API key | |
| # doc_processing = DocProcessing(anthropic_api_key=anthropic_api_key) | |
| # result = doc_processing.crew().kickoff(inputs=inputs) | |
| # # Extract results from CrewOutput | |
| # if hasattr(result, 'tasks_output') and result.tasks_output: | |
| # analysis_result = "" | |
| # generated_code = "" | |
| # for i, task_output in enumerate(result.tasks_output): | |
| # if i == 0: # First task is document analysis | |
| # analysis_result = str(task_output.raw) if hasattr(task_output, 'raw') else str(task_output) | |
| # elif i == 1: # Second task is code implementation | |
| # generated_code = str(task_output.raw) if hasattr(task_output, 'raw') else str(task_output) | |
| # return analysis_result, generated_code | |
| # else: | |
| # # Fallback if structure is different | |
| # result_str = str(result) | |
| # return result_str, "Code generation completed. Check the analysis section for details." | |
| # except Exception as e: | |
| # error_msg = f"β Error processing document: {str(e)}" | |
| # return error_msg, "" | |
| # finally: | |
| # # Clean up environment variables for security | |
| # if "ANTHROPIC_API_KEY" in os.environ: | |
| # del os.environ["ANTHROPIC_API_KEY"] | |
| # def create_demo_interface(): | |
| # """Create the Gradio interface""" | |
| # # Custom CSS for better styling | |
| # custom_css = """ | |
| # .gradio-container { | |
| # max-width: 1200px !important; | |
| # margin: auto !important; | |
| # } | |
| # .header { | |
| # text-align: center; | |
| # margin-bottom: 2rem; | |
| # } | |
| # .api-key-input { | |
| # margin-bottom: 1rem; | |
| # } | |
| # .output-section { | |
| # margin-top: 2rem; | |
| # } | |
| # """ | |
| # with gr.Blocks(css=custom_css, title="Document to Code Converter") as demo: | |
| # gr.HTML(""" | |
| # <div class="header"> | |
| # <h1>π Document to Code Converter</h1> | |
| # <p>Upload your design documents (images/PDFs) and convert them to working HTML/CSS/JS code!</p> | |
| # </div> | |
| # """) | |
| # with gr.Row(): | |
| # with gr.Column(scale=1): | |
| # gr.HTML("<h3>π€ Upload & Configuration</h3>") | |
| # # API Key input | |
| # api_key_input = gr.Textbox( | |
| # label="π Anthropic API Key", | |
| # placeholder="sk-ant-...", | |
| # type="password", | |
| # info="Enter your Anthropic API key. It will be used securely and not stored.", | |
| # elem_classes=["api-key-input"] | |
| # ) | |
| # # File upload | |
| # file_input = gr.File( | |
| # label="π Upload Document", | |
| # file_types=[".pdf", ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff"], | |
| # ) | |
| # # Process button | |
| # process_btn = gr.Button( | |
| # "π Process Document", | |
| # variant="primary", | |
| # size="lg" | |
| # ) | |
| # # Status indicator | |
| # gr.HTML(""" | |
| # <div style="margin-top: 1rem; padding: 1rem; background: #f0f9ff; border-radius: 8px; border-left: 4px solid #0ea5e9;"> | |
| # <h4 style="margin: 0; color: #0c4a6e;">βΉοΈ How it works:</h4> | |
| # <ol style="margin: 0.5rem 0; color: #164e63;"> | |
| # <li>Upload your design document (image or PDF)</li> | |
| # <li>Enter your Anthropic API key</li> | |
| # <li>Click "Process Document" to analyze and generate code</li> | |
| # <li>Get detailed analysis and working HTML/CSS/JS code</li> | |
| # </ol> | |
| # </div> | |
| # """) | |
| # with gr.Row(): | |
| # with gr.Column(scale=1): | |
| # gr.HTML("<h3 class='output-section'>π Document Analysis</h3>") | |
| # analysis_output = gr.Textbox( | |
| # label="Analysis Results", | |
| # lines=15, | |
| # placeholder="Document analysis will appear here...", | |
| # show_copy_button=True | |
| # ) | |
| # with gr.Column(scale=1): | |
| # gr.HTML("<h3 class='output-section'>π» Generated Code</h3>") | |
| # code_output = gr.Textbox( | |
| # label="HTML/CSS/JS Code", | |
| # lines=15, | |
| # placeholder="Generated code will appear here...", | |
| # show_copy_button=True | |
| # ) | |
| # # Add examples section | |
| # gr.HTML(""" | |
| # <div style="margin-top: 2rem; padding: 1rem; background: #f8fafc; border-radius: 8px;"> | |
| # <h4>π― Best Results Tips:</h4> | |
| # <ul> | |
| # <li><strong>High Quality Images:</strong> Use clear, high-resolution images for better analysis</li> | |
| # <li><strong>Design Mockups:</strong> Website mockups, app designs, and UI sketches work great</li> | |
| # <li><strong>PDF Documents:</strong> Multi-page design documents are supported</li> | |
| # <li><strong>Clear Layouts:</strong> Well-organized designs produce better code structure</li> | |
| # </ul> | |
| # </div> | |
| # """) | |
| # # Set up the processing event | |
| # process_btn.click( | |
| # fn=process_document, | |
| # inputs=[file_input, api_key_input], | |
| # outputs=[analysis_output, code_output], | |
| # show_progress=True | |
| # ) | |
| # # Add footer | |
| # gr.HTML(""" | |
| # <div style="text-align: center; margin-top: 2rem; padding: 1rem; border-top: 1px solid #e2e8f0; color: #64748b;"> | |
| # <p>π Your API keys are handled securely and never stored. | |
| # <br>Built with CrewAI, LandingAI, and Anthropic Claude.</p> | |
| # </div> | |
| # """) | |
| # return demo | |
| # if __name__ == "__main__": | |
| # # Test Landing AI connection on startup | |
| # from tools.custom_tool import test_landing_ai_connection | |
| # print("π Testing API connections...") | |
| # landing_ai_available = test_landing_ai_connection() | |
| # if not landing_ai_available: | |
| # print("\nβ οΈ Warning: Landing AI API key not properly configured!") | |
| # print("For local development: Set LANDING_AI_API_KEY in your .env file") | |
| # print("For HuggingFace deployment: Add LANDING_AI_API_KEY to your Space secrets") | |
| # print("The app will still start, but document analysis will fail without the API key.\n") | |
| # else: | |
| # print("β Landing AI API key configured correctly!\n") | |
| # # Create and launch the demo | |
| # demo = create_demo_interface() | |
| # # Launch configuration | |
| # demo.launch( | |
| # server_name="0.0.0.0", # Required for HuggingFace deployment | |
| # server_port=7860, # Standard port for HuggingFace | |
| # share=False, # Set to True for temporary public link during development | |
| # debug=False, # Set to True for development | |
| # show_error=True, # Show errors in the interface | |
| # quiet=False # Set to True to reduce console output | |
| # ) | |
| import gradio as gr | |
| import os | |
| import tempfile | |
| import shutil | |
| from pathlib import Path | |
| import warnings | |
| from typing import Tuple, Optional | |
| import sys | |
| # Suppress warnings | |
| warnings.filterwarnings("ignore", category=SyntaxWarning, module="pysbd") | |
| # Import your existing modules | |
| from crew import DocProcessing | |
| from tools.custom_tool import landing_ai_document_analysis | |
| def get_landing_ai_key(): | |
| """Get Landing AI API key from environment (HF secrets or local .env)""" | |
| # Try multiple environment variable names for flexibility | |
| return ( | |
| os.getenv("LANDING_AI_API_KEY") or # HuggingFace secrets or production | |
| os.getenv("LANDING_AI_API_KEY_LOCAL") or # Local development alternative | |
| os.getenv("LANDINGAI_API_KEY") or # Alternative naming | |
| os.getenv("LANDING_API_KEY") # Another alternative | |
| ) | |
| def validate_api_key(api_key: str) -> bool: | |
| """Validate Anthropic API key format""" | |
| if not api_key: | |
| return False | |
| return api_key.startswith("sk-ant-") and len(api_key) > 20 | |
| def create_html_file(code_content: str, filename: str = "generated_page.html") -> str: | |
| """ | |
| Create an HTML file from the generated code | |
| Args: | |
| code_content: The HTML/CSS/JS code | |
| filename: Name for the HTML file | |
| Returns: | |
| str: Path to the created file | |
| """ | |
| try: | |
| # Create temporary file | |
| temp_dir = tempfile.gettempdir() | |
| file_path = os.path.join(temp_dir, filename) | |
| # Clean the code content - remove any markdown formatting if present | |
| cleaned_code = code_content.strip() | |
| if cleaned_code.startswith("```html"): | |
| cleaned_code = cleaned_code[7:] | |
| if cleaned_code.endswith("```"): | |
| cleaned_code = cleaned_code[:-3] | |
| cleaned_code = cleaned_code.strip() | |
| # Ensure it's a complete HTML document | |
| if not cleaned_code.lower().startswith('<!doctype') and not cleaned_code.lower().startswith('<html'): | |
| cleaned_code = f"""<!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Generated Page</title> | |
| </head> | |
| <body> | |
| {cleaned_code} | |
| </body> | |
| </html>""" | |
| # Write to file | |
| with open(file_path, 'w', encoding='utf-8') as f: | |
| f.write(cleaned_code) | |
| return file_path | |
| except Exception as e: | |
| print(f"Error creating HTML file: {e}") | |
| return None | |
| def determine_file_type(file_path: str) -> str: | |
| """Determine file type based on extension""" | |
| _, ext = os.path.splitext(file_path) | |
| return 'pdf' if ext.lower() == '.pdf' else 'image' | |
| def prepare_preview_content(code_content: str) -> str: | |
| """ | |
| Prepare code content for safe preview in iframe | |
| Args: | |
| code_content: The HTML/CSS/JS code | |
| Returns: | |
| str: Cleaned and safe HTML content for preview | |
| """ | |
| try: | |
| if not code_content or code_content.strip() == "": | |
| return "<div style='padding: 20px; text-align: center; color: #666;'>No code generated yet...</div>" | |
| # Clean the code content | |
| cleaned_code = code_content.strip() | |
| # Remove markdown formatting if present | |
| if cleaned_code.startswith("```html"): | |
| cleaned_code = cleaned_code[7:] | |
| if cleaned_code.startswith("```"): | |
| cleaned_code = cleaned_code[3:] | |
| if cleaned_code.endswith("```"): | |
| cleaned_code = cleaned_code[:-3] | |
| cleaned_code = cleaned_code.strip() | |
| # If it's not a complete HTML document, wrap it | |
| if not cleaned_code.lower().startswith('<!doctype') and not cleaned_code.lower().startswith('<html'): | |
| cleaned_code = f"""<!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Preview</title> | |
| <style> | |
| body {{ margin: 0; padding: 10px; font-family: Arial, sans-serif; }} | |
| * {{ box-sizing: border-box; }} | |
| </style> | |
| </head> | |
| <body> | |
| {cleaned_code} | |
| </body> | |
| </html>""" | |
| # Wrap in iframe for safe rendering | |
| iframe_content = f""" | |
| <iframe | |
| srcdoc="{cleaned_code.replace('"', '"')}" | |
| style="width: 100%; height: 400px; border: 1px solid #ddd; border-radius: 8px;" | |
| sandbox="allow-scripts allow-same-origin"> | |
| </iframe> | |
| """ | |
| return iframe_content | |
| except Exception as e: | |
| return f"<div style='padding: 20px; color: red;'>Error preparing preview: {str(e)}</div>" | |
| def toggle_to_code(): | |
| """Show code view and hide preview""" | |
| return ( | |
| gr.update(visible=True), # code_output | |
| gr.update(visible=False), # preview_output | |
| gr.update(variant="primary"), # code_view_btn | |
| gr.update(variant="secondary") # preview_btn | |
| ) | |
| def toggle_to_preview(code_content): | |
| """Show preview and hide code view""" | |
| preview_html = prepare_preview_content(code_content) | |
| return ( | |
| gr.update(visible=False), # code_output | |
| gr.update(visible=True, value=preview_html), # preview_output | |
| gr.update(variant="secondary"), # code_view_btn | |
| gr.update(variant="primary") # preview_btn | |
| ) | |
| # def download_html_file(code_content): | |
| # """Create downloadable HTML file""" | |
| # if not code_content or code_content.strip() == "": | |
| # return gr.update(visible=False) | |
| # file_path = create_html_file(code_content) | |
| # if file_path: | |
| # return gr.update(visible=True, value=file_path) | |
| # else: | |
| # return gr.update(visible=False) | |
| def process_document(file, anthropic_api_key: str) -> Tuple[str, str]: | |
| """ | |
| Process the uploaded document and return analysis + generated code | |
| Args: | |
| file: Uploaded file object from Gradio | |
| anthropic_api_key: User's Anthropic API key | |
| Returns: | |
| Tuple of (analysis_result, generated_code) | |
| """ | |
| try: | |
| # Validate inputs | |
| if not file: | |
| return "β No file uploaded", "" | |
| if not validate_api_key(anthropic_api_key): | |
| return "β Invalid Anthropic API key. Please ensure it starts with 'sk-ant-' and is complete.", "" | |
| # Check if Landing AI key is available | |
| landing_ai_key = get_landing_ai_key() | |
| if not landing_ai_key: | |
| return "β Landing AI API key not configured. Please ensure LANDING_AI_API_KEY is set in environment variables or HuggingFace secrets.", "" | |
| # Set environment variables securely | |
| os.environ["ANTHROPIC_API_KEY"] = anthropic_api_key | |
| os.environ["LANDING_AI_API_KEY"] = landing_ai_key | |
| # Create temporary directory for processing | |
| with tempfile.TemporaryDirectory() as temp_dir: | |
| # Save uploaded file | |
| file_extension = Path(file.name).suffix | |
| temp_file_path = os.path.join(temp_dir, f"uploaded_file{file_extension}") | |
| # Copy uploaded file to temp location | |
| shutil.copy2(file.name, temp_file_path) | |
| # Determine file type | |
| file_type = determine_file_type(temp_file_path) | |
| # Prepare inputs for CrewAI | |
| inputs = { | |
| "file_path": temp_file_path, | |
| "file_type": file_type, | |
| } | |
| # Initialize and run the crew with the API key | |
| doc_processing = DocProcessing(anthropic_api_key=anthropic_api_key) | |
| result = doc_processing.crew().kickoff(inputs=inputs) | |
| # Extract results from CrewOutput | |
| if hasattr(result, 'tasks_output') and result.tasks_output: | |
| analysis_result = "" | |
| generated_code = "" | |
| for i, task_output in enumerate(result.tasks_output): | |
| if i == 0: # First task is document analysis | |
| analysis_result = str(task_output.raw) if hasattr(task_output, 'raw') else str(task_output) | |
| elif i == 1: # Second task is code implementation | |
| generated_code = str(task_output.raw) if hasattr(task_output, 'raw') else str(task_output) | |
| return generated_code | |
| # analysis_result, | |
| else: | |
| # Fallback if structure is different | |
| result_str = str(result) | |
| return result_str, "Code generation completed. Check the analysis section for details." | |
| except Exception as e: | |
| error_msg = f"β Error processing document: {str(e)}" | |
| return error_msg, "" | |
| finally: | |
| # Clean up environment variables for security | |
| if "ANTHROPIC_API_KEY" in os.environ: | |
| del os.environ["ANTHROPIC_API_KEY"] | |
| def create_demo_interface(): | |
| """Create the Gradio interface""" | |
| # Custom CSS for better styling | |
| custom_css = """ | |
| .gradio-container { | |
| max-width: 1200px !important; | |
| margin: auto !important; | |
| } | |
| .header { | |
| text-align: center; | |
| margin-bottom: 2rem; | |
| } | |
| .api-key-input { | |
| margin-bottom: 1rem; | |
| } | |
| .output-section { | |
| margin-top: 2rem; | |
| } | |
| .toggle-buttons { | |
| margin-bottom: 1rem; | |
| } | |
| .preview-container { | |
| border: 1px solid #e2e8f0; | |
| border-radius: 8px; | |
| background: #f8fafc; | |
| min-height: 400px; | |
| } | |
| """ | |
| with gr.Blocks(css=custom_css, title="Document to Code Converter") as demo: | |
| gr.HTML(""" | |
| <div class="header"> | |
| <h1>π Document to Code Converter</h1> | |
| <p>Upload your design documents (images/PDFs) and convert them to working HTML/CSS/JS code!</p> | |
| </div> | |
| """) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| gr.HTML("<h3>π€ Upload & Configuration</h3>") | |
| # API Key input | |
| api_key_input = gr.Textbox( | |
| label="π Anthropic API Key", | |
| placeholder="sk-ant-...", | |
| type="password", | |
| info="Enter your Anthropic API key. It will be used securely and not stored.", | |
| elem_classes=["api-key-input"] | |
| ) | |
| # File upload | |
| file_input = gr.File( | |
| label="π Upload Document", | |
| file_types=[".pdf", ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff"], | |
| ) | |
| # Process button | |
| process_btn = gr.Button( | |
| "π Process Document", | |
| variant="primary", | |
| size="lg" | |
| ) | |
| # Status indicator | |
| gr.HTML(""" | |
| <div style="margin-top: 1rem; padding: 1rem; background: #f0f9ff; border-radius: 8px; border-left: 4px solid #0ea5e9;"> | |
| <h4 style="margin: 0; color: #0c4a6e;">βΉοΈ How it works:</h4> | |
| <ol style="margin: 0.5rem 0; color: #164e63;"> | |
| <li>Upload your design document (image or PDF)</li> | |
| <li>Enter your Anthropic API key</li> | |
| <li>Click "Process Document" to analyze and generate code</li> | |
| <li>Use toggle buttons to switch between code view and live preview</li> | |
| </ol> | |
| </div> | |
| """) | |
| gr.HTML("<h3 class='output-section'>π» Generated Code & Preview</h3>") | |
| # Toggle buttons for code/preview | |
| with gr.Row(): | |
| code_view_btn = gr.Button("π View Code", variant="primary", size="sm") | |
| preview_btn = gr.Button("ποΈ Preview Result", variant="secondary", size="sm") | |
| # Code output (visible by default) | |
| code_output = gr.Textbox( | |
| label="HTML/CSS/JS Code", | |
| lines=15, | |
| placeholder="Generated code will appear here...", | |
| show_copy_button=True, | |
| visible=True | |
| ) | |
| # Preview output (hidden by default) | |
| preview_output = gr.HTML( | |
| label="Live Preview", | |
| value="<div style='padding: 20px; text-align: center; color: #666;'>Preview will appear here after code generation...</div>", | |
| visible=False | |
| ) | |
| # with gr.Row(): | |
| # with gr.Column(scale=1): | |
| # gr.HTML("<h3 class='output-section'>π Document Analysis</h3>") | |
| # analysis_output = gr.Textbox( | |
| # label="Analysis Results", | |
| # lines=15, | |
| # placeholder="Document analysis will appear here...", | |
| # show_copy_button=True | |
| # ) | |
| # with gr.Column(scale=1): | |
| # Download file component (hidden) | |
| # download_file = gr.File( | |
| # label="Download", | |
| # visible=False | |
| # ) | |
| # Add examples section | |
| gr.HTML(""" | |
| <div style="margin-top: 2rem; padding: 1rem; background: #f8fafc; border-radius: 8px;"> | |
| <h4>π― New Features:</h4> | |
| <ul> | |
| <li><strong>π Code View:</strong> See the raw HTML/CSS/JS code generated from your design</li> | |
| <li><strong>ποΈ Live Preview:</strong> Toggle to see how your code will actually look when rendered</li> | |
| <li><strong>π Real-time Toggle:</strong> Switch between code and preview instantly</li> | |
| </ul> | |
| <h4>π― Best Results Tips:</h4> | |
| <ul> | |
| <li><strong>High Quality Images:</strong> Use clear, high-resolution images for better analysis</li> | |
| <li><strong>Design Mockups:</strong> Website mockups, app designs, and UI sketches work great</li> | |
| <li><strong>PDF Documents:</strong> Multi-page design documents are supported</li> | |
| <li><strong>Clear Layouts:</strong> Well-organized designs produce better code structure</li> | |
| </ul> | |
| </div> | |
| """) | |
| # Set up the processing event | |
| process_btn.click( | |
| fn=process_document, | |
| inputs=[file_input, api_key_input], | |
| outputs=[code_output], | |
| # analysis_output, | |
| show_progress=True | |
| ) | |
| # Set up toggle events | |
| code_view_btn.click( | |
| fn=toggle_to_code, | |
| inputs=[], | |
| outputs=[code_output, preview_output, code_view_btn, preview_btn] | |
| ) | |
| preview_btn.click( | |
| fn=toggle_to_preview, | |
| inputs=[code_output], | |
| outputs=[code_output, preview_output, code_view_btn, preview_btn] | |
| ) | |
| # Set up download event | |
| # download_btn.click( | |
| # fn=download_html_file, | |
| # inputs=[code_output], | |
| # outputs=[download_file] | |
| # ) | |
| # Add footer | |
| gr.HTML(""" | |
| <div style="text-align: center; margin-top: 2rem; padding: 1rem; border-top: 1px solid #e2e8f0; color: #64748b;"> | |
| <p>π Your API keys are handled securely and never stored. | |
| <br>Built with CrewAI, LandingAI, and Anthropic Claude.</p> | |
| </div> | |
| """) | |
| return demo | |
| if __name__ == "__main__": | |
| # Test Landing AI connection on startup | |
| from tools.custom_tool import test_landing_ai_connection | |
| print("π Testing API connections...") | |
| landing_ai_available = test_landing_ai_connection() | |
| if not landing_ai_available: | |
| print("\nβ οΈ Warning: Landing AI API key not properly configured!") | |
| print("For local development: Set LANDING_AI_API_KEY in your .env file") | |
| print("For HuggingFace deployment: Add LANDING_AI_API_KEY to your Space secrets") | |
| print("The app will still start, but document analysis will fail without the API key.\n") | |
| else: | |
| print("β Landing AI API key configured correctly!\n") | |
| # Create and launch the demo | |
| demo = create_demo_interface() | |
| # Launch configuration | |
| demo.launch( | |
| server_name="0.0.0.0", # Required for HuggingFace deployment | |
| server_port=7860, # Standard port for HuggingFace | |
| share=False, # Set to True for temporary public link during development | |
| debug=False, # Set to True for development | |
| show_error=True, # Show errors in the interface | |
| quiet=False # Set to True to reduce console output | |
| ) |