| import gradio as gr |
| from pathlib import Path |
| import sys |
|
|
| |
| PROJECT_ROOT = Path(__file__).resolve().parent |
| GENERATED_SCRIPT_PATH = PROJECT_ROOT / "generated" / "result_script.py" |
|
|
| |
| sys.path.insert(0, str(PROJECT_ROOT / "app")) |
|
|
| from app.process import main as generate_from_llm |
| from src.llm_client import reset_memory |
|
|
| def generate_new_part(description): |
| """ |
| Generates a completely new FreeCAD script (resets memory) and returns: |
| - The script text for preview |
| - The file path for download |
| """ |
| reset_memory() |
| return _generate_script(description) |
|
|
| def edit_existing_part(description): |
| """ |
| Edits the existing FreeCAD script using conversation context and returns: |
| - The updated script text for preview |
| - The file path for download |
| """ |
| return _generate_script(description) |
|
|
| def _generate_script(description): |
| """Helper to call process.py with given description.""" |
| import builtins |
| original_input = builtins.input |
| builtins.input = lambda _: description |
| try: |
| generate_from_llm() |
| finally: |
| builtins.input = original_input |
|
|
| if GENERATED_SCRIPT_PATH.exists(): |
| script_text = GENERATED_SCRIPT_PATH.read_text(encoding="utf-8") |
| return script_text, str(GENERATED_SCRIPT_PATH) |
| else: |
| return "Error: Script was not generated.", None |
|
|
|
|
| css = """ |
| body { background-color: #202020; color: white; margin: 0; padding: 0; } |
| .gradio-container { |
| max-width: 1400px; |
| width: 95vw; |
| margin: auto; |
| } |
| .title { text-align: center; font-size: 2.5em; margin-bottom: 0.1em; } |
| .description { text-align: center; font-size: 1.1em; margin-bottom: 1em; color: #ccc; } |
| .preview-box { |
| max-height: 400px; |
| background-color: #111; |
| border: 1px solid #444; |
| padding: 10px; |
| font-family: monospace; |
| white-space: pre-wrap; |
| color: #0f0; |
| } |
| .download-container { |
| display: flex; |
| flex-direction: column; |
| align-items: flex-start; |
| gap: 0.5em; |
| padding-left: 15px; |
| height: 400px; |
| justify-content: flex-start; |
| width: 500px; |
| } |
| .download-button { width: 100%; } |
| .instructions { |
| font-size: 0.9em; color: #aaa; |
| max-width: 300px; |
| white-space: pre-line; |
| } |
| .footer { |
| margin-top: 2em; |
| text-align: center; |
| font-size: 0.9em; |
| color: #888; |
| border-top: 1px solid #444; |
| padding-top: 1em; |
| } |
| .footer a { color: #6af; text-decoration: none; } |
| .footer a:hover { text-decoration: underline; } |
| """ |
|
|
| |
| cadomatic_description_md = """ |
| <div style="text-align: center;"> |
| |
| Seamlessly creating python scripts for FreeCAD — from prompt to model. |
| |
| CADomatic is a Python-powered tool that transforms prompts into **editable** parametric CAD scripts for FreeCAD. Rather than static models, it generates fully customizable Python code that programmatically builds CAD geometry — enabling engineers to define parts, reuse templates, and iterate rapidly.<br> |
| CADomatic primarily aims at **reducing product development time** by making a base design which can be modified to suit the designer's main goal.<br> |
| CADomatic creates native FreeCAD Python scripts for simple parts **with a complete design tree**.<br> |
| <br> |
| Explore [CADomatic on GitHub](https://github.com/yas1nsyed/CADomatic) and if you find it useful, please ⭐ star the repository! |
| """ |
|
|
| with gr.Blocks(css=css) as demo: |
| gr.Markdown("<div class='title'>CADomatic - AI powered CAD design generator</div>") |
| gr.Markdown(cadomatic_description_md) |
|
|
| description_input = gr.Textbox( |
| label="Describe your desired CAD model or modification below:", |
| lines=2, |
| placeholder="e.g., Create a flange with OD 100mm, bore size 50mm and 6 m8 holes at PCD 75mm..." |
| ) |
|
|
| with gr.Row(): |
| generate_new_btn = gr.Button("Generate New Part", variant="primary") |
| edit_existing_btn = gr.Button("Edit Existing Part", variant="secondary") |
|
|
| with gr.Row(): |
| with gr.Column(scale=1): |
| preview_output = gr.Code( |
| label="Generated Script Preview", |
| language="python", |
| elem_classes="preview-box" |
| ) |
| download_btn = gr.DownloadButton( |
| label="Download Python Script", |
| elem_classes="download-button" |
| ) |
| with gr.Column(scale=1): |
| gr.Markdown( |
| """ |
| <div class='instructions'> |
| <b>Instructions:</b><br> |
| - Enter the description for your desired CAD part or an edit instruction.<br> |
| - Click on "Generate New Part" to start fresh.<br> |
| - Click on "Edit Existing Part" to modify the last script.<br> |
| - Preview the generated Python code.<br> |
| - Paste the generated code into the python console of your FreeCAD app.<br> |
| - (or)<br> |
| - Download the script.<br> |
| - In your FreeCAD python console, paste - exec(open(r"path to your python script").read()) |
| </div> |
| """ |
| ) |
|
|
| |
| gr.Markdown( |
| """ |
| <div class='footer'> |
| CADomatic is still under development and may sometimes produce inaccurate results.<br> |
| <br> |
| Made with ❤️ by Yasin |
| </div> |
| """ |
| ) |
|
|
| generate_new_btn.click( |
| fn=generate_new_part, |
| inputs=description_input, |
| outputs=[preview_output, download_btn] |
| ) |
|
|
| edit_existing_btn.click( |
| fn=edit_existing_part, |
| inputs=description_input, |
| outputs=[preview_output, download_btn] |
| ) |
|
|
| if __name__ == "__main__": |
| demo.launch() |
|
|