@hybridlabor-api/bdb-hardware-pcb 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +116 -0
- package/config/mcp/antigravity.json +22 -0
- package/config/mcp/claude.json +22 -0
- package/config/mcp/codex.toml +25 -0
- package/docs/adr/ADR-001-KICAD-OPENSCAD-MCP-STRATEGY.md +334 -0
- package/docs/review_documentation.md +121 -0
- package/installer.js +358 -0
- package/mcp_servers/kicad-mcp-server/.env.example +22 -0
- package/mcp_servers/kicad-mcp-server/.github/workflows/ci.yml +36 -0
- package/mcp_servers/kicad-mcp-server/CLAUDE.md +487 -0
- package/mcp_servers/kicad-mcp-server/README.md +316 -0
- package/mcp_servers/kicad-mcp-server/docs/DEVICE_TREE.md +416 -0
- package/mcp_servers/kicad-mcp-server/docs/INSTALLATION.md +332 -0
- package/mcp_servers/kicad-mcp-server/docs/PIN_ANALYSIS.md +332 -0
- package/mcp_servers/kicad-mcp-server/docs/README.md +240 -0
- package/mcp_servers/kicad-mcp-server/docs/TESTING.md +613 -0
- package/mcp_servers/kicad-mcp-server/docs/VALIDATION.md +268 -0
- package/mcp_servers/kicad-mcp-server/pyproject.toml +96 -0
- package/mcp_servers/kicad-mcp-server/requirements-dev.txt +16 -0
- package/mcp_servers/kicad-mcp-server/requirements-test.txt +24 -0
- package/mcp_servers/kicad-mcp-server/requirements.txt +13 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/__init__.py +3 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/__main__.py +17 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/config.py +46 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/models/__init__.py +1 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/models/types.py +87 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/parsers/__init__.py +1 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/parsers/netlist_parser.py +234 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/parsers/pcb_parser.py +375 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/parsers/pcb_parser_kicad.py +327 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/parsers/schematic_parser.py +902 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/server.py +71 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/__init__.py +1 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/arduino/connectivity_test.cpp.j2 +189 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/device_tree/atmega.dts.j2 +77 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/device_tree/esp32.dts.j2 +77 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/device_tree/nrf52.dts.j2 +77 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/device_tree/stm32f4.dts.j2 +89 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/esp_idf/test_suite.c.j2 +340 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/pytest/test_connectivity.py.j2 +147 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/st_hal/hal_test.c.j2 +313 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/pytest_gpio_test.py.j2 +99 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/pytest_i2c_test.py.j2 +117 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/pytest_pinmux_test.py.j2 +43 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/pytest_spi_test.py.j2 +94 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/unity_gpio_test.c.j2 +113 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/unity_i2c_test.c.j2 +101 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/unity_spi_test.c.j2 +94 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/unittest/test_schematic.py.j2 +172 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/__init__.py +36 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/device_tree.py +1187 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/hierarchical_analysis.py +211 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/netlist.py +320 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/parts_registry.py +142 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/pcb.py +955 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/pcb_layout.py +308 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/pin_analysis.py +765 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/project.py +196 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/schematic.py +319 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/schematic_editor.py +674 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/schematic_search.py +158 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/validation.py +866 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/visualization.py +225 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/utils/__init__.py +1 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/utils/file_handlers.py +65 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/utils/kicad_cli.py +103 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/utils/kicad_version.py +103 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/utils/parts_registry.py +197 -0
- package/mcp_servers/kicad-mcp-server/tests/__init__.py +1 -0
- package/mcp_servers/kicad-mcp-server/tests/examples/ESP32S3_TEST.md +219 -0
- package/mcp_servers/kicad-mcp-server/tests/fixtures/README.md +65 -0
- package/mcp_servers/kicad-mcp-server/tests/fixtures/__init__.py +1 -0
- package/mcp_servers/kicad-mcp-server/tests/fixtures/example_pcb.kicad_pcb +177 -0
- package/mcp_servers/kicad-mcp-server/tests/fixtures/example_schematic.kicad_sch +145 -0
- package/mcp_servers/kicad-mcp-server/tests/fixtures/hier/child.kicad_sch +24 -0
- package/mcp_servers/kicad-mcp-server/tests/fixtures/hier/root.kicad_sch +38 -0
- package/mcp_servers/kicad-mcp-server/tests/test_tools/__init__.py +1 -0
- package/mcp_servers/kicad-mcp-server/tests/test_tools/test_hierarchical_labels.py +195 -0
- package/mcp_servers/kicad-mcp-server/tests/test_tools/test_kicad_cli.py +116 -0
- package/mcp_servers/kicad-mcp-server/tests/test_tools/test_netlist_cache_path.py +29 -0
- package/mcp_servers/kicad-mcp-server/tests/test_tools/test_schematic.py +189 -0
- package/mcp_servers/kicad-mcp-server/tests/test_tools/test_schematic_hierarchy.py +69 -0
- package/mcp_servers/kicad-mcp-server/tests/test_tools/test_visualization.py +136 -0
- package/mcp_servers/kicad-mcp-server/uv.lock +2873 -0
- package/mcp_servers/openscad-mcp-server/.dockerignore +9 -0
- package/mcp_servers/openscad-mcp-server/.github/workflows/test.yml +40 -0
- package/mcp_servers/openscad-mcp-server/Dockerfile +29 -0
- package/mcp_servers/openscad-mcp-server/LICENSE +21 -0
- package/mcp_servers/openscad-mcp-server/README.md +154 -0
- package/mcp_servers/openscad-mcp-server/docs/audit.md +56 -0
- package/mcp_servers/openscad-mcp-server/docs/docker.md +66 -0
- package/mcp_servers/openscad-mcp-server/docs/issue-followup.md +19 -0
- package/mcp_servers/openscad-mcp-server/docs/jetson.md +17 -0
- package/mcp_servers/openscad-mcp-server/glama.json +4 -0
- package/mcp_servers/openscad-mcp-server/legacy/README.md +15 -0
- package/mcp_servers/openscad-mcp-server/legacy/README.original.md +294 -0
- package/mcp_servers/openscad-mcp-server/legacy/implementation_plan.md +100 -0
- package/mcp_servers/openscad-mcp-server/legacy/old/download_sam2_checkpoint.py +115 -0
- package/mcp_servers/openscad-mcp-server/legacy/old/src/ai/sam_segmentation.py +209 -0
- package/mcp_servers/openscad-mcp-server/legacy/old/src/models/threestudio_generator.py +231 -0
- package/mcp_servers/openscad-mcp-server/legacy/old/src/workflow/image_to_model_pipeline.py +260 -0
- package/mcp_servers/openscad-mcp-server/legacy/old/test_sam2_segmentation.py +96 -0
- package/mcp_servers/openscad-mcp-server/legacy/requirements.txt +57 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/README.md +39 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/decisions/ai-driven-code-generation.md +122 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/decisions/export-formats.md +76 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/files/src/ai/ai_service.py.md +51 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/files/src/main.py.md +63 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/files/src/models/code_generator.py.md +63 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/files/src/nlp/parameter_extractor.py.md +63 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/knowledge/ai/natural-language-processing.md +78 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/knowledge/nlp/parameter-extraction.md +173 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/knowledge/openscad/export-formats.md +91 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/knowledge/openscad/openscad-basics.md +66 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/knowledge/openscad/primitive-testing.md +79 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/__init__.py +0 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/ai/ai_service.py +257 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/ai/gemini_api.py +161 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/ai/venice_api.py +203 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/config.py +121 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/main.py +1456 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/main.py.new +404 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/main_remote.py +401 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/models/__init__.py +0 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/models/code_generator.py +321 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/models/cuda_mvs.py +209 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/models/scad_templates/basic_shapes.scad +144 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/nlp/__init__.py +0 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/nlp/parameter_extractor.py +388 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/openscad_wrapper/__init__.py +0 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/openscad_wrapper/wrapper.py +418 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/printer_discovery/__init__.py +1 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/printer_discovery/printer_discovery.py +471 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/remote/connection_manager.py +537 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/remote/cuda_mvs_client.py +435 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/remote/cuda_mvs_server.py +787 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/remote/error_handling.py +415 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/testing/__init__.py +0 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/testing/primitive_tester.py +203 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/testing/test_primitives.py +98 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/utils/__init__.py +1 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/utils/cad_exporter.py +241 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/utils/format_validator.py +206 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/utils/stl_exporter.py +140 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/utils/stl_repair.py +91 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/utils/stl_validator.py +123 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/visualization/__init__.py +0 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/visualization/headless_renderer.py +52 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/visualization/renderer.py +177 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/visualization/web_interface.py +639 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/workflow/image_approval.py +148 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/workflow/multi_view_to_model_pipeline.py +338 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_complete_workflow.py +374 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_cuda_mvs.py +191 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_gemini_api.py +168 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_image_approval.py +192 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_image_approval_workflow.py +251 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_image_to_model_pipeline.py +145 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_model_selection.py +41 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_multi_view_pipeline.py +290 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_primitives.sh +13 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_rabbit_direct.py +71 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_remote_cuda_mvs.py +283 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_venice_example.py +69 -0
- package/mcp_servers/openscad-mcp-server/pyproject.toml +33 -0
- package/mcp_servers/openscad-mcp-server/requirements.txt +2 -0
- package/mcp_servers/openscad-mcp-server/scad/simple_cube.scad +2 -0
- package/mcp_servers/openscad-mcp-server/scripts/test_docker.py +220 -0
- package/mcp_servers/openscad-mcp-server/src/openscad_mcp/__init__.py +3 -0
- package/mcp_servers/openscad-mcp-server/src/openscad_mcp/__main__.py +3 -0
- package/mcp_servers/openscad-mcp-server/src/openscad_mcp/engine.py +94 -0
- package/mcp_servers/openscad-mcp-server/src/openscad_mcp/geometry.py +242 -0
- package/mcp_servers/openscad-mcp-server/src/openscad_mcp/server.py +245 -0
- package/mcp_servers/openscad-mcp-server/src/openscad_mcp/service.py +190 -0
- package/mcp_servers/openscad-mcp-server/tests/conftest.py +17 -0
- package/mcp_servers/openscad-mcp-server/tests/test_engine.py +37 -0
- package/mcp_servers/openscad-mcp-server/tests/test_geometry.py +106 -0
- package/mcp_servers/openscad-mcp-server/tests/test_integration.py +172 -0
- package/mcp_servers/openscad-mcp-server/tests/test_transports.py +314 -0
- package/mcp_servers/openscad-mcp-server/uv.lock +1123 -0
- package/package.json +44 -0
- package/scripts/install_mcps.sh +86 -0
- package/scripts/openscad_wrapper.sh +62 -0
- package/scripts/run_kicad_mcp.sh +25 -0
- package/scripts/run_openscad_mcp.sh +41 -0
- package/scripts/test_mcp_connection.py +626 -0
- package/scripts/test_mcp_connection.sh +168 -0
- package/skills/code-first-hardware-design/SKILL.md +260 -0
- package/skills/pcb-constraint-definition/SKILL.md +236 -0
- package/skills/pcb-layout-routing-automation/SKILL.md +153 -0
- package/skills/pcb-validation-dfm-signoff/SKILL.md +194 -0
- package/skills/schematic-datasheet-analysis/SKILL.md +202 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import logging
|
|
4
|
+
import argparse
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Dict, Any, List, Optional, Tuple
|
|
7
|
+
|
|
8
|
+
# Configure logging
|
|
9
|
+
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
# Add project root to path
|
|
13
|
+
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
14
|
+
|
|
15
|
+
# Import components
|
|
16
|
+
from src.ai.venice_api import VeniceImageGenerator
|
|
17
|
+
from src.ai.sam_segmentation import SAMSegmenter
|
|
18
|
+
from src.models.threestudio_generator import ThreeStudioGenerator
|
|
19
|
+
from src.openscad_wrapper.wrapper import OpenSCADWrapper
|
|
20
|
+
from src.workflow.image_to_model_pipeline import ImageToModelPipeline
|
|
21
|
+
from src.config import (
|
|
22
|
+
VENICE_API_KEY, IMAGES_DIR, MASKS_DIR, MODELS_DIR, SCAD_DIR,
|
|
23
|
+
SAM2_CHECKPOINT_PATH, SAM2_MODEL_TYPE, SAM2_USE_GPU, THREESTUDIO_PATH
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
def test_pipeline(prompt: str, output_dir: Optional[str] = None,
|
|
27
|
+
venice_model: str = "fluently-xl", skip_steps: List[str] = None):
|
|
28
|
+
"""
|
|
29
|
+
Test the full image-to-model pipeline.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
prompt: Text prompt for image generation
|
|
33
|
+
output_dir: Directory to save pipeline results
|
|
34
|
+
venice_model: Venice.ai model to use for image generation
|
|
35
|
+
skip_steps: List of steps to skip ('image', 'segment', 'model3d', 'openscad')
|
|
36
|
+
"""
|
|
37
|
+
# Use default output directory if not provided
|
|
38
|
+
if not output_dir:
|
|
39
|
+
output_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "output", "pipeline_test")
|
|
40
|
+
|
|
41
|
+
# Create output directory
|
|
42
|
+
os.makedirs(output_dir, exist_ok=True)
|
|
43
|
+
|
|
44
|
+
# Initialize skip_steps if None
|
|
45
|
+
skip_steps = skip_steps or []
|
|
46
|
+
|
|
47
|
+
logger.info(f"Testing image-to-model pipeline with prompt: {prompt}")
|
|
48
|
+
logger.info(f"Output directory: {output_dir}")
|
|
49
|
+
logger.info(f"Venice model: {venice_model}")
|
|
50
|
+
logger.info(f"Skipping steps: {skip_steps}")
|
|
51
|
+
|
|
52
|
+
try:
|
|
53
|
+
# Initialize components
|
|
54
|
+
logger.info("Initializing pipeline components...")
|
|
55
|
+
|
|
56
|
+
# Venice.ai image generator
|
|
57
|
+
venice_generator = VeniceImageGenerator(
|
|
58
|
+
api_key=VENICE_API_KEY,
|
|
59
|
+
output_dir=os.path.join(output_dir, "images")
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# SAM2 segmenter
|
|
63
|
+
sam_segmenter = SAMSegmenter(
|
|
64
|
+
model_type=SAM2_MODEL_TYPE,
|
|
65
|
+
checkpoint_path=SAM2_CHECKPOINT_PATH,
|
|
66
|
+
use_gpu=SAM2_USE_GPU,
|
|
67
|
+
output_dir=os.path.join(output_dir, "masks")
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
# ThreeStudio generator
|
|
71
|
+
threestudio_generator = ThreeStudioGenerator(
|
|
72
|
+
threestudio_path=THREESTUDIO_PATH,
|
|
73
|
+
output_dir=os.path.join(output_dir, "models")
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# OpenSCAD wrapper
|
|
77
|
+
openscad_wrapper = OpenSCADWrapper(
|
|
78
|
+
output_dir=os.path.join(output_dir, "scad")
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
# Initialize pipeline
|
|
82
|
+
pipeline = ImageToModelPipeline(
|
|
83
|
+
venice_generator=venice_generator,
|
|
84
|
+
sam_segmenter=sam_segmenter,
|
|
85
|
+
threestudio_generator=threestudio_generator,
|
|
86
|
+
openscad_wrapper=openscad_wrapper,
|
|
87
|
+
output_dir=output_dir
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
# Run pipeline with custom steps
|
|
91
|
+
if 'image' in skip_steps:
|
|
92
|
+
# Skip image generation, use a test image
|
|
93
|
+
logger.info("Skipping image generation, using test image")
|
|
94
|
+
image_path = os.path.join(IMAGES_DIR, "test_image.png")
|
|
95
|
+
if not os.path.exists(image_path):
|
|
96
|
+
logger.error(f"Test image not found: {image_path}")
|
|
97
|
+
return
|
|
98
|
+
|
|
99
|
+
# TODO: Implement custom pipeline execution with skipped steps
|
|
100
|
+
logger.info("Custom pipeline execution not implemented yet")
|
|
101
|
+
return
|
|
102
|
+
else:
|
|
103
|
+
# Run full pipeline
|
|
104
|
+
logger.info("Running full pipeline...")
|
|
105
|
+
result = pipeline.generate_model_from_text(
|
|
106
|
+
prompt=prompt,
|
|
107
|
+
venice_params={"model": venice_model},
|
|
108
|
+
sam_params={},
|
|
109
|
+
threestudio_params={}
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
# Print results
|
|
113
|
+
logger.info("Pipeline completed successfully")
|
|
114
|
+
logger.info(f"Pipeline ID: {result.get('pipeline_id')}")
|
|
115
|
+
logger.info(f"Image path: {result.get('image', {}).get('local_path')}")
|
|
116
|
+
logger.info(f"Mask count: {result.get('segmentation', {}).get('num_masks', 0)}")
|
|
117
|
+
logger.info(f"3D model path: {result.get('model_3d', {}).get('exported_files', [])}")
|
|
118
|
+
logger.info(f"OpenSCAD file: {result.get('openscad', {}).get('scad_file')}")
|
|
119
|
+
|
|
120
|
+
return result
|
|
121
|
+
|
|
122
|
+
except Exception as e:
|
|
123
|
+
logger.error(f"Error in pipeline: {str(e)}")
|
|
124
|
+
import traceback
|
|
125
|
+
traceback.print_exc()
|
|
126
|
+
return None
|
|
127
|
+
|
|
128
|
+
if __name__ == "__main__":
|
|
129
|
+
# Parse command line arguments
|
|
130
|
+
parser = argparse.ArgumentParser(description="Test image-to-model pipeline")
|
|
131
|
+
parser.add_argument("prompt", help="Text prompt for image generation")
|
|
132
|
+
parser.add_argument("--output-dir", help="Directory to save pipeline results")
|
|
133
|
+
parser.add_argument("--venice-model", default="fluently-xl", help="Venice.ai model to use")
|
|
134
|
+
parser.add_argument("--skip", nargs="+", choices=["image", "segment", "model3d", "openscad"],
|
|
135
|
+
help="Steps to skip in the pipeline")
|
|
136
|
+
|
|
137
|
+
args = parser.parse_args()
|
|
138
|
+
|
|
139
|
+
# Run test
|
|
140
|
+
test_pipeline(
|
|
141
|
+
args.prompt,
|
|
142
|
+
args.output_dir,
|
|
143
|
+
args.venice_model,
|
|
144
|
+
args.skip
|
|
145
|
+
)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import logging
|
|
3
|
+
from src.ai.venice_api import VeniceImageGenerator
|
|
4
|
+
|
|
5
|
+
# Configure logging
|
|
6
|
+
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
# Venice.ai API key (replace with your own or use environment variable)
|
|
10
|
+
VENICE_API_KEY = os.getenv("VENICE_API_KEY", "B9Y68yQgatQw8wmpmnIMYcGip1phCt-43CS0OktZU6")
|
|
11
|
+
OUTPUT_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "output", "images")
|
|
12
|
+
|
|
13
|
+
# Test natural language model selection
|
|
14
|
+
def test_model_selection():
|
|
15
|
+
"""Test the natural language model selection functionality."""
|
|
16
|
+
# Initialize the Venice API client
|
|
17
|
+
venice_generator = VeniceImageGenerator(VENICE_API_KEY, OUTPUT_DIR)
|
|
18
|
+
|
|
19
|
+
# Test cases - natural language preferences to expected model mappings
|
|
20
|
+
test_cases = [
|
|
21
|
+
("default", "fluently-xl"),
|
|
22
|
+
("fastest model please", "fluently-xl"),
|
|
23
|
+
("I need a high quality image", "flux-dev"),
|
|
24
|
+
("create an uncensored image", "flux-dev-uncensored"),
|
|
25
|
+
("make it realistic", "pony-realism"),
|
|
26
|
+
("I want something artistic", "lustify-sdxl"),
|
|
27
|
+
("use stable diffusion", "stable-diffusion-3.5"),
|
|
28
|
+
("invalid model name", "fluently-xl"), # Should default to fluently-xl
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
# Run tests
|
|
32
|
+
for preference, expected_model in test_cases:
|
|
33
|
+
mapped_model = venice_generator.map_model_preference(preference)
|
|
34
|
+
logger.info(f"Preference: '{preference}' -> Model: '{mapped_model}'")
|
|
35
|
+
assert mapped_model == expected_model, f"Expected {expected_model}, got {mapped_model}"
|
|
36
|
+
|
|
37
|
+
logger.info("All model preference mappings tests passed!")
|
|
38
|
+
|
|
39
|
+
if __name__ == "__main__":
|
|
40
|
+
logger.info("Starting Venice.ai model selection mapping tests")
|
|
41
|
+
test_model_selection()
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Test script for multi-view to model pipeline.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import sys
|
|
7
|
+
import logging
|
|
8
|
+
import unittest
|
|
9
|
+
from unittest.mock import patch, MagicMock
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
# Add the src directory to the path
|
|
13
|
+
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
14
|
+
|
|
15
|
+
from src.workflow.multi_view_to_model_pipeline import MultiViewToModelPipeline
|
|
16
|
+
from src.ai.gemini_api import GeminiImageGenerator
|
|
17
|
+
from src.models.cuda_mvs import CUDAMultiViewStereo
|
|
18
|
+
from src.workflow.image_approval import ImageApprovalTool
|
|
19
|
+
|
|
20
|
+
# Configure logging
|
|
21
|
+
logging.basicConfig(level=logging.INFO)
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
class TestMultiViewPipeline(unittest.TestCase):
|
|
25
|
+
"""
|
|
26
|
+
Test cases for multi-view to model pipeline.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
def setUp(self):
|
|
30
|
+
"""
|
|
31
|
+
Set up test environment.
|
|
32
|
+
"""
|
|
33
|
+
# Create test directories
|
|
34
|
+
self.test_output_dir = "output/test_pipeline"
|
|
35
|
+
self.test_images_dir = os.path.join(self.test_output_dir, "images")
|
|
36
|
+
self.test_models_dir = os.path.join(self.test_output_dir, "models")
|
|
37
|
+
|
|
38
|
+
for directory in [self.test_output_dir, self.test_images_dir, self.test_models_dir]:
|
|
39
|
+
os.makedirs(directory, exist_ok=True)
|
|
40
|
+
|
|
41
|
+
# Create mock CUDA MVS path
|
|
42
|
+
self.cuda_mvs_path = "mock_cuda_mvs"
|
|
43
|
+
os.makedirs(os.path.join(self.cuda_mvs_path, "build"), exist_ok=True)
|
|
44
|
+
|
|
45
|
+
# Create mock executable
|
|
46
|
+
with open(os.path.join(self.cuda_mvs_path, "build", "app_patch_match_mvs"), "w") as f:
|
|
47
|
+
f.write("#!/bin/bash\necho 'Mock CUDA MVS'\n")
|
|
48
|
+
os.chmod(os.path.join(self.cuda_mvs_path, "build", "app_patch_match_mvs"), 0o755)
|
|
49
|
+
|
|
50
|
+
# Create mock components
|
|
51
|
+
self.mock_gemini = MagicMock(spec=GeminiImageGenerator)
|
|
52
|
+
self.mock_cuda_mvs = MagicMock(spec=CUDAMultiViewStereo)
|
|
53
|
+
self.mock_approval = MagicMock(spec=ImageApprovalTool)
|
|
54
|
+
|
|
55
|
+
# Configure mock responses
|
|
56
|
+
self.configure_mocks()
|
|
57
|
+
|
|
58
|
+
# Create the pipeline with mock components
|
|
59
|
+
self.pipeline = MultiViewToModelPipeline(
|
|
60
|
+
gemini_generator=self.mock_gemini,
|
|
61
|
+
cuda_mvs=self.mock_cuda_mvs,
|
|
62
|
+
approval_tool=self.mock_approval,
|
|
63
|
+
output_dir=self.test_output_dir
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
def configure_mocks(self):
|
|
67
|
+
"""
|
|
68
|
+
Configure mock responses for components.
|
|
69
|
+
"""
|
|
70
|
+
# Mock Gemini image generation
|
|
71
|
+
def mock_generate_image(prompt, **kwargs):
|
|
72
|
+
image_path = os.path.join(self.test_images_dir, f"{prompt[:10].replace(' ', '_')}.png")
|
|
73
|
+
with open(image_path, "w") as f:
|
|
74
|
+
f.write(f"Mock image for {prompt}")
|
|
75
|
+
return {
|
|
76
|
+
"prompt": prompt,
|
|
77
|
+
"local_path": image_path,
|
|
78
|
+
"image_data": b"mock_image_data"
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
def mock_generate_multiple_views(prompt, num_views, **kwargs):
|
|
82
|
+
results = []
|
|
83
|
+
for i in range(num_views):
|
|
84
|
+
image_path = os.path.join(self.test_images_dir, f"view_{i}.png")
|
|
85
|
+
with open(image_path, "w") as f:
|
|
86
|
+
f.write(f"Mock image for {prompt} - view {i}")
|
|
87
|
+
results.append({
|
|
88
|
+
"prompt": f"{prompt} - view {i}",
|
|
89
|
+
"local_path": image_path,
|
|
90
|
+
"image_data": b"mock_image_data",
|
|
91
|
+
"view_direction": f"view {i}",
|
|
92
|
+
"view_index": i + 1
|
|
93
|
+
})
|
|
94
|
+
return results
|
|
95
|
+
|
|
96
|
+
self.mock_gemini.generate_image.side_effect = mock_generate_image
|
|
97
|
+
self.mock_gemini.generate_multiple_views.side_effect = mock_generate_multiple_views
|
|
98
|
+
|
|
99
|
+
# Mock CUDA MVS
|
|
100
|
+
def mock_generate_model(image_paths, **kwargs):
|
|
101
|
+
model_dir = os.path.join(self.test_models_dir, "mock_model")
|
|
102
|
+
os.makedirs(model_dir, exist_ok=True)
|
|
103
|
+
|
|
104
|
+
point_cloud_file = os.path.join(model_dir, "mock_model.ply")
|
|
105
|
+
with open(point_cloud_file, "w") as f:
|
|
106
|
+
f.write("Mock point cloud")
|
|
107
|
+
|
|
108
|
+
obj_file = os.path.join(model_dir, "mock_model.obj")
|
|
109
|
+
with open(obj_file, "w") as f:
|
|
110
|
+
f.write("Mock OBJ file")
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
"model_id": "mock_model",
|
|
114
|
+
"output_dir": model_dir,
|
|
115
|
+
"point_cloud_file": point_cloud_file,
|
|
116
|
+
"obj_file": obj_file,
|
|
117
|
+
"input_images": image_paths
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
self.mock_cuda_mvs.generate_model_from_images.side_effect = mock_generate_model
|
|
121
|
+
self.mock_cuda_mvs.convert_ply_to_obj.return_value = os.path.join(self.test_models_dir, "mock_model", "mock_model.obj")
|
|
122
|
+
|
|
123
|
+
# Mock approval tool
|
|
124
|
+
def mock_present_image(image_path, metadata):
|
|
125
|
+
return {
|
|
126
|
+
"approval_id": os.path.basename(image_path).split('.')[0],
|
|
127
|
+
"image_path": image_path,
|
|
128
|
+
"image_url": f"/images/{os.path.basename(image_path)}",
|
|
129
|
+
"metadata": metadata or {}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
def mock_process_approval(approval_id, approved, image_path):
|
|
133
|
+
if approved:
|
|
134
|
+
approved_path = os.path.join(self.test_output_dir, "approved", os.path.basename(image_path))
|
|
135
|
+
os.makedirs(os.path.dirname(approved_path), exist_ok=True)
|
|
136
|
+
with open(approved_path, "w") as f:
|
|
137
|
+
f.write(f"Approved image {approval_id}")
|
|
138
|
+
|
|
139
|
+
return {
|
|
140
|
+
"approval_id": approval_id,
|
|
141
|
+
"approved": True,
|
|
142
|
+
"original_path": image_path,
|
|
143
|
+
"approved_path": approved_path
|
|
144
|
+
}
|
|
145
|
+
else:
|
|
146
|
+
return {
|
|
147
|
+
"approval_id": approval_id,
|
|
148
|
+
"approved": False,
|
|
149
|
+
"original_path": image_path
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
self.mock_approval.present_image_for_approval.side_effect = mock_present_image
|
|
153
|
+
self.mock_approval.process_approval.side_effect = mock_process_approval
|
|
154
|
+
self.mock_approval.get_approved_images.return_value = [
|
|
155
|
+
os.path.join(self.test_output_dir, "approved", f"view_{i}.png") for i in range(3)
|
|
156
|
+
]
|
|
157
|
+
|
|
158
|
+
def test_generate_model_from_text(self):
|
|
159
|
+
"""
|
|
160
|
+
Test generating a 3D model from text prompt.
|
|
161
|
+
"""
|
|
162
|
+
# Test parameters
|
|
163
|
+
prompt = "A low-poly rabbit"
|
|
164
|
+
num_views = 3
|
|
165
|
+
|
|
166
|
+
# Mock approvals - approve all images
|
|
167
|
+
def mock_get_approval(approval_request):
|
|
168
|
+
return True
|
|
169
|
+
|
|
170
|
+
# Call the method
|
|
171
|
+
result = self.pipeline.generate_model_from_text(
|
|
172
|
+
prompt, num_views=num_views, get_approval_callback=mock_get_approval
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
# Verify the result
|
|
176
|
+
self.assertIsNotNone(result)
|
|
177
|
+
self.assertTrue("model_id" in result)
|
|
178
|
+
self.assertTrue("obj_file" in result)
|
|
179
|
+
self.assertTrue("point_cloud_file" in result)
|
|
180
|
+
|
|
181
|
+
# Verify component calls
|
|
182
|
+
self.mock_gemini.generate_multiple_views.assert_called_once_with(
|
|
183
|
+
prompt, num_views=num_views, output_dir=os.path.join(self.test_output_dir, "multi_view")
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
self.assertEqual(self.mock_approval.present_image_for_approval.call_count, num_views)
|
|
187
|
+
self.assertEqual(self.mock_approval.process_approval.call_count, num_views)
|
|
188
|
+
|
|
189
|
+
self.mock_cuda_mvs.generate_model_from_images.assert_called_once()
|
|
190
|
+
self.mock_cuda_mvs.convert_ply_to_obj.assert_called_once()
|
|
191
|
+
|
|
192
|
+
def test_generate_model_from_image(self):
|
|
193
|
+
"""
|
|
194
|
+
Test generating a 3D model from a base image.
|
|
195
|
+
"""
|
|
196
|
+
# Create a mock base image
|
|
197
|
+
base_image_path = os.path.join(self.test_images_dir, "base_image.png")
|
|
198
|
+
with open(base_image_path, "w") as f:
|
|
199
|
+
f.write("Mock base image")
|
|
200
|
+
|
|
201
|
+
# Test parameters
|
|
202
|
+
prompt = "A low-poly rabbit based on this image"
|
|
203
|
+
num_views = 3
|
|
204
|
+
|
|
205
|
+
# Mock approvals - approve all images
|
|
206
|
+
def mock_get_approval(approval_request):
|
|
207
|
+
return True
|
|
208
|
+
|
|
209
|
+
# Call the method
|
|
210
|
+
result = self.pipeline.generate_model_from_image(
|
|
211
|
+
base_image_path, prompt, num_views=num_views, get_approval_callback=mock_get_approval
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
# Verify the result
|
|
215
|
+
self.assertIsNotNone(result)
|
|
216
|
+
self.assertTrue("model_id" in result)
|
|
217
|
+
self.assertTrue("obj_file" in result)
|
|
218
|
+
self.assertTrue("point_cloud_file" in result)
|
|
219
|
+
|
|
220
|
+
# Verify component calls
|
|
221
|
+
self.mock_gemini.generate_multiple_views.assert_called_once_with(
|
|
222
|
+
prompt, num_views=num_views, base_image_path=base_image_path,
|
|
223
|
+
output_dir=os.path.join(self.test_output_dir, "multi_view")
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
self.assertEqual(self.mock_approval.present_image_for_approval.call_count, num_views)
|
|
227
|
+
self.assertEqual(self.mock_approval.process_approval.call_count, num_views)
|
|
228
|
+
|
|
229
|
+
self.mock_cuda_mvs.generate_model_from_images.assert_called_once()
|
|
230
|
+
self.mock_cuda_mvs.convert_ply_to_obj.assert_called_once()
|
|
231
|
+
|
|
232
|
+
def test_selective_approval(self):
|
|
233
|
+
"""
|
|
234
|
+
Test selective approval of generated images.
|
|
235
|
+
"""
|
|
236
|
+
# Test parameters
|
|
237
|
+
prompt = "A low-poly rabbit"
|
|
238
|
+
num_views = 4
|
|
239
|
+
|
|
240
|
+
# Mock approvals - only approve views 0 and 2
|
|
241
|
+
def mock_get_approval(approval_request):
|
|
242
|
+
view_index = int(approval_request["approval_id"].split('_')[1])
|
|
243
|
+
return view_index % 2 == 0 # Approve even-indexed views
|
|
244
|
+
|
|
245
|
+
# Call the method
|
|
246
|
+
result = self.pipeline.generate_model_from_text(
|
|
247
|
+
prompt, num_views=num_views, get_approval_callback=mock_get_approval
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
# Verify the result
|
|
251
|
+
self.assertIsNotNone(result)
|
|
252
|
+
|
|
253
|
+
# Verify component calls
|
|
254
|
+
self.assertEqual(self.mock_approval.present_image_for_approval.call_count, num_views)
|
|
255
|
+
self.assertEqual(self.mock_approval.process_approval.call_count, num_views)
|
|
256
|
+
|
|
257
|
+
# Only 2 images should be approved and used for model generation
|
|
258
|
+
approved_images = [call[0][0] for call in self.mock_cuda_mvs.generate_model_from_images.call_args_list]
|
|
259
|
+
if approved_images:
|
|
260
|
+
self.assertEqual(len(approved_images[0]), 2) # Only 2 images approved
|
|
261
|
+
|
|
262
|
+
def test_error_handling(self):
|
|
263
|
+
"""
|
|
264
|
+
Test error handling in the pipeline.
|
|
265
|
+
"""
|
|
266
|
+
# Test parameters
|
|
267
|
+
prompt = "A low-poly rabbit"
|
|
268
|
+
|
|
269
|
+
# Mock error in Gemini API
|
|
270
|
+
self.mock_gemini.generate_multiple_views.side_effect = Exception("Mock API error")
|
|
271
|
+
|
|
272
|
+
# Call the method and expect an exception
|
|
273
|
+
with self.assertRaises(Exception):
|
|
274
|
+
self.pipeline.generate_model_from_text(prompt)
|
|
275
|
+
|
|
276
|
+
def tearDown(self):
|
|
277
|
+
"""
|
|
278
|
+
Clean up after tests.
|
|
279
|
+
"""
|
|
280
|
+
# Clean up test output directory
|
|
281
|
+
import shutil
|
|
282
|
+
if os.path.exists(self.test_output_dir):
|
|
283
|
+
shutil.rmtree(self.test_output_dir)
|
|
284
|
+
|
|
285
|
+
# Clean up mock CUDA MVS path
|
|
286
|
+
if os.path.exists(self.cuda_mvs_path):
|
|
287
|
+
shutil.rmtree(self.cuda_mvs_path)
|
|
288
|
+
|
|
289
|
+
if __name__ == "__main__":
|
|
290
|
+
unittest.main()
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Test OpenSCAD primitives with different export formats
|
|
3
|
+
|
|
4
|
+
PYTHON="python"
|
|
5
|
+
OUTPUT_DIR="test_output"
|
|
6
|
+
|
|
7
|
+
# Create output directory
|
|
8
|
+
mkdir -p $OUTPUT_DIR
|
|
9
|
+
|
|
10
|
+
# Run the tests
|
|
11
|
+
$PYTHON -m src.testing.test_primitives --output-dir $OUTPUT_DIR --validate
|
|
12
|
+
|
|
13
|
+
echo "Tests completed. Results are in $OUTPUT_DIR"
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import json
|
|
4
|
+
import requests
|
|
5
|
+
import base64
|
|
6
|
+
import logging
|
|
7
|
+
|
|
8
|
+
# Configure logging
|
|
9
|
+
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
# Venice.ai API configuration
|
|
13
|
+
VENICE_API_KEY = os.getenv("VENICE_API_KEY", "B9Y68yQgatQw8wmpmnIMYcGip1phCt-43CS0OktZU6")
|
|
14
|
+
OUTPUT_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "output", "images")
|
|
15
|
+
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
|
16
|
+
|
|
17
|
+
# API configuration
|
|
18
|
+
url = "https://api.venice.ai/api/v1/image/generate"
|
|
19
|
+
headers = {
|
|
20
|
+
"Authorization": f"Bearer {VENICE_API_KEY}",
|
|
21
|
+
"Content-Type": "application/json"
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
# Payload for image generation
|
|
25
|
+
payload = {
|
|
26
|
+
"height": 1024,
|
|
27
|
+
"width": 1024,
|
|
28
|
+
"steps": 20,
|
|
29
|
+
"return_binary": True, # Request binary data directly
|
|
30
|
+
"hide_watermark": False,
|
|
31
|
+
"format": "png",
|
|
32
|
+
"embed_exif_metadata": False,
|
|
33
|
+
"model": "flux-dev",
|
|
34
|
+
"prompt": "A low-poly rabbit with black background. 3d file"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
def generate_image():
|
|
38
|
+
"""Generate image using Venice.ai API with the rabbit prompt."""
|
|
39
|
+
try:
|
|
40
|
+
logger.info(f"Sending request to {url} with prompt: '{payload['prompt']}'")
|
|
41
|
+
response = requests.post(url, json=payload, headers=headers)
|
|
42
|
+
|
|
43
|
+
logger.info(f"Response status: {response.status_code}")
|
|
44
|
+
|
|
45
|
+
if response.status_code == 200:
|
|
46
|
+
# Save the raw binary response
|
|
47
|
+
filename = "rabbit_low_poly_3d.png"
|
|
48
|
+
output_path = os.path.join(OUTPUT_DIR, filename)
|
|
49
|
+
|
|
50
|
+
with open(output_path, "wb") as f:
|
|
51
|
+
f.write(response.content)
|
|
52
|
+
|
|
53
|
+
logger.info(f"Image saved to {output_path}")
|
|
54
|
+
return output_path
|
|
55
|
+
else:
|
|
56
|
+
logger.error(f"Error: {response.status_code} - {response.text}")
|
|
57
|
+
|
|
58
|
+
return None
|
|
59
|
+
except Exception as e:
|
|
60
|
+
logger.error(f"Error: {str(e)}")
|
|
61
|
+
return None
|
|
62
|
+
|
|
63
|
+
if __name__ == "__main__":
|
|
64
|
+
logger.info("Starting Venice.ai image generation test with rabbit prompt")
|
|
65
|
+
image_path = generate_image()
|
|
66
|
+
|
|
67
|
+
if image_path:
|
|
68
|
+
logger.info(f"Successfully generated and saved image to {image_path}")
|
|
69
|
+
print(f"\nImage saved to: {image_path}")
|
|
70
|
+
else:
|
|
71
|
+
logger.error("Failed to generate image")
|