File size: 6,657 Bytes
8cc9c71
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4ee0746
8cc9c71
 
 
 
 
 
 
 
4ee0746
8cc9c71
 
 
 
 
 
 
 
 
 
 
 
 
4ee0746
8cc9c71
 
 
4ee0746
8cc9c71
 
 
 
 
 
 
4ee0746
 
8cc9c71
 
 
 
 
4ee0746
8cc9c71
 
 
4ee0746
8cc9c71
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4ee0746
 
 
 
8cc9c71
 
 
4ee0746
8cc9c71
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4ee0746
 
8cc9c71
 
 
4ee0746
8cc9c71
 
 
4ee0746
8cc9c71
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80f27e2
 
 
8cc9c71
 
 
 
 
 
 
 
 
 
 
4ee0746
8cc9c71
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
import os
import json
from pathlib import Path
import asyncio
import base64
from openai import AsyncOpenAI
from dotenv import load_dotenv

load_dotenv()

VISION_MODEL = "gpt-4o-2024-08-06"

client = AsyncOpenAI()

async def analyze_screenshot(design_id: str, design_path: Path):
    """Analyze screenshots and return description, categories, and visual characteristics"""
    try:
        # Check files exist
        metadata_path = design_path / "metadata.json"
        desktop_img = design_path / "screenshot_desktop.png"
        mobile_img = design_path / "screenshot_mobile.png"
        
        if not all(f.exists() for f in [metadata_path, desktop_img, mobile_img]):
            print(f"Missing required files for design {design_id}")
            return design_id, None, None, None
        
        # Load existing metadata
        with open(metadata_path, "r") as f:
            metadata = json.load(f)
        
        # Read both images
        try:
            with open(desktop_img, "rb") as f:
                desktop_base64 = base64.b64encode(f.read()).decode('utf-8')
            with open(mobile_img, "rb") as f:
                mobile_base64 = base64.b64encode(f.read()).decode('utf-8')
        except Exception as e:
            print(f"Error reading images for design {design_id}: {str(e)}")
            return design_id, None, None, None
        
        print(f"Analyzing design {design_id}...")
        
        # Get response first
        response = await client.chat.completions.create(
            model=VISION_MODEL,
            messages=[
                {
                    "role": "system",
                    "content": """You are an expert graphic designer analyzing print and web designs for aesthetics, functionality, audience appeal, and potential applications.
                    
                    The design should be considered from a visual standpoint. Use chain of thought to consider color palette, visual layout, typography, artistic style, mood, and potential applications.
                    Consider gradients, texture, background effects, and the use of images.
                    
                    Treat all text content as placeholder Lorem Ipsum.
                    
                    Provide analysis in clean JSON format with these exact keys:
                    {
                        "description": "A one-paragraph summary highlighting exceptional features of the design",
                        "categories": ["category1", "category2"],
                        "visual_characteristics": ["characteristic1", "characteristic2"]
                    }
                    Provide 4-6 categories and 4-6 visual characteristics most relevant to the style and feel of the design. Do not reference css or web design directly because this analysis is primarily about design. These lists should describe the design to another LLM that will use this data to generate a UI.
                    """
                },
                {
                    "role": "user",
                    "content": [
                        {
                            "type": "text",
                            "text": "Analyze this visual design. Output only the JSON object."
                        },
                        {
                            "type": "image_url",
                            "image_url": {
                                "url": f"data:image/png;base64,{desktop_base64}",
                                "detail": "high"
                            }
                        },
                        {
                            "type": "image_url",
                            "image_url": {
                                "url": f"data:image/png;base64,{mobile_base64}",
                                "detail": "high"
                            }
                        }
                    ]
                }
            ],
            max_tokens=1000
        )
        
        # Then get the content
        response_content = response.choices[0].message.content.strip()
        
        # Ensure the response is not empty
        if not response_content:
            print(f"Empty response for design {design_id}")
            return design_id, None, None, None
        
        # Extract JSON content from markdown code block
        if "```json" in response_content:
            # Remove the ```json prefix and ``` suffix
            response_content = response_content.split("```json")[1].split("```")[0].strip()
        
        # Parse the JSON response
        try:
            analysis = json.loads(response_content)
            
            # Update metadata with all fields
            metadata.update(analysis)
            
            # Save updated metadata
            with open(metadata_path, "w") as f:
                json.dump(metadata, f, indent=2)
            
            print(f"Successfully analyzed design {design_id}")
            # Return visual_characteristics as fourth element
            return design_id, analysis["description"], analysis["categories"], analysis["visual_characteristics"]
            
        except json.JSONDecodeError as e:
            print(f"Error parsing JSON response for design {design_id}: {str(e)}")
            return design_id, None, None, None
        
    except Exception as e:
        print(f"Error processing design {design_id}: {str(e)}")
        return design_id, None, None, None

async def main():
    designs_dir = Path("designs")
    
    if not designs_dir.exists():
        print("Designs directory not found!")
        return
    
    # Get all design directories
    design_dirs = [d for d in designs_dir.iterdir() if d.is_dir()]
    
    if not design_dirs:
        print("No design directories found!")
        return
    
    print(f"Found {len(design_dirs)} designs to analyze")
    
    # Create list of design IDs to analyze (001-050)
    design_ids = [f"{i:03d}" for i in range(1, 51)]
    
    # Analyze all designs
    tasks = []
    for design_dir in design_dirs:
        design_id = design_dir.name
        tasks.append(analyze_screenshot(design_id, design_dir))
    
    # Run analyses concurrently
    results = await asyncio.gather(*tasks)
    
    # Print summary
    successful = 0
    for design_id, desc, cats, _ in results:
        if desc is not None:
            successful += 1
            print(f"\nDesign {design_id}:")
            print(f"Description: {desc}")
            print(f"Categories: {', '.join(cats)}")
    
    print(f"\nSuccessfully analyzed {successful} out of {len(design_dirs)} designs")

if __name__ == "__main__":
    asyncio.run(main())