Technologic101 commited on
Commit
8cc9c71
·
1 Parent(s): dcbd9eb

task: improves design analysis and formats json

Browse files
Files changed (6) hide show
  1. analyze_designs.py +171 -0
  2. notebook.ipynb +62 -27
  3. poetry.lock +125 -101
  4. pyproject.toml +1 -0
  5. test_scraper.ipynb +10 -8
  6. uv.lock +0 -0
analyze_designs.py ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ from pathlib import Path
4
+ import asyncio
5
+ import base64
6
+ from openai import AsyncOpenAI
7
+ from dotenv import load_dotenv
8
+
9
+ load_dotenv()
10
+
11
+ VISION_MODEL = "gpt-4o-2024-08-06"
12
+
13
+ client = AsyncOpenAI()
14
+
15
+ async def analyze_screenshot(design_id: str, design_path: Path):
16
+ """Analyze screenshots and return description and categories"""
17
+ try:
18
+ # Check files exist
19
+ metadata_path = design_path / "metadata.json"
20
+ desktop_img = design_path / "screenshot_desktop.png"
21
+ mobile_img = design_path / "screenshot_mobile.png"
22
+
23
+ if not all(f.exists() for f in [metadata_path, desktop_img, mobile_img]):
24
+ print(f"Missing required files for design {design_id}")
25
+ return design_id, None, None
26
+
27
+ # Load existing metadata
28
+ with open(metadata_path, "r") as f:
29
+ metadata = json.load(f)
30
+
31
+ # Read both images
32
+ try:
33
+ with open(desktop_img, "rb") as f:
34
+ desktop_base64 = base64.b64encode(f.read()).decode('utf-8')
35
+ with open(mobile_img, "rb") as f:
36
+ mobile_base64 = base64.b64encode(f.read()).decode('utf-8')
37
+ except Exception as e:
38
+ print(f"Error reading images for design {design_id}: {str(e)}")
39
+ return design_id, None, None
40
+
41
+ print(f"Analyzing design {design_id}...")
42
+
43
+ # Analyze both screenshots with GPT-4 Vision
44
+ response = await client.chat.completions.create(
45
+ model=VISION_MODEL,
46
+ messages=[
47
+ {
48
+ "role": "system",
49
+ "content": """You are an expert graphic designer analyzing print and web designs for aesthetics, functionality, audience appeal, and potential applications.
50
+
51
+ The design should be considered from a visual standpoint, ignoring web responsiveness. Use chain of thought to consider color palette, visual layout, typography, artistic style, mood, and potential applications.
52
+ Consider gradients, texture, background effects, and the use of images. Make a distinction between background visual elements and functional visual elements.
53
+
54
+ Treat all text content as placeholder Lorem Ipsum.
55
+
56
+ Provide analysis in clean JSON format with these exact keys:
57
+ {
58
+ "description": "Brief analysis focusing on standout features and potential use cases",
59
+ "categories": ["category1", "category2"],
60
+ "visual_characteristics": ["characteristic1", "characteristic2"]
61
+ }
62
+
63
+ Categories should only refer to categories of design styling.
64
+ """
65
+ },
66
+ {
67
+ "role": "user",
68
+ "content": [
69
+ {
70
+ "type": "text",
71
+ "text": "Analyze this visual design. Output only the JSON object."
72
+ },
73
+ {
74
+ "type": "image_url",
75
+ "image_url": {
76
+ "url": f"data:image/png;base64,{desktop_base64}",
77
+ "detail": "high"
78
+ }
79
+ },
80
+ {
81
+ "type": "image_url",
82
+ "image_url": {
83
+ "url": f"data:image/png;base64,{mobile_base64}",
84
+ "detail": "high"
85
+ }
86
+ }
87
+ ]
88
+ }
89
+ ],
90
+ max_tokens=1000
91
+ )
92
+
93
+ # Print the response content for debugging
94
+ response_content = response.choices[0].message.content.strip()
95
+
96
+ # Ensure the response is not empty
97
+ if not response_content:
98
+ print(f"Empty response for design {design_id}")
99
+ return design_id, None, None
100
+
101
+ # Log the type and length of the response content
102
+ print(f"Type of response content: {type(response_content)}")
103
+ print(f"Length of response content: {len(response_content)}")
104
+
105
+ # Extract JSON content from markdown code block
106
+ if "```json" in response_content:
107
+ # Remove the ```json prefix and ``` suffix
108
+ response_content = response_content.split("```json")[1].split("```")[0].strip()
109
+
110
+ # Parse the JSON response
111
+ try:
112
+ print(f"Cleaned response for design {design_id}: {response_content}")
113
+ analysis = json.loads(response_content)
114
+ print("JSON parsed")
115
+
116
+ # Update metadata with all fields
117
+ metadata.update(analysis)
118
+
119
+ # Save updated metadata
120
+ with open(metadata_path, "w") as f:
121
+ json.dump(metadata, f, indent=2)
122
+
123
+ print(f"Successfully analyzed design {design_id}")
124
+ return design_id, analysis["description"], analysis["categories"]
125
+
126
+ except json.JSONDecodeError as e:
127
+ print(f"Error parsing JSON response for design {design_id}: {str(e)}")
128
+ return design_id, None, None
129
+
130
+ except Exception as e:
131
+ print(f"Error processing design {design_id}: {str(e)}")
132
+ return design_id, None, None
133
+
134
+ async def main():
135
+ designs_dir = Path("designs")
136
+
137
+ if not designs_dir.exists():
138
+ print("Designs directory not found!")
139
+ return
140
+
141
+ # Get all design directories
142
+ design_dirs = [d for d in designs_dir.iterdir() if d.is_dir()]
143
+
144
+ if not design_dirs:
145
+ print("No design directories found!")
146
+ return
147
+
148
+ print(f"Found {len(design_dirs)} designs to analyze")
149
+
150
+ # Analyze all designs
151
+ tasks = []
152
+ for design_dir in design_dirs:
153
+ design_id = design_dir.name
154
+ tasks.append(analyze_screenshot(design_id, design_dir))
155
+
156
+ # Run analyses concurrently
157
+ results = await asyncio.gather(*tasks)
158
+
159
+ # Print summary
160
+ successful = 0
161
+ for design_id, desc, cats in results:
162
+ if desc is not None:
163
+ successful += 1
164
+ print(f"\nDesign {design_id}:")
165
+ print(f"Description: {desc}")
166
+ print(f"Categories: {', '.join(cats)}")
167
+
168
+ print(f"\nSuccessfully analyzed {successful} out of {len(design_dirs)} designs")
169
+
170
+ if __name__ == "__main__":
171
+ asyncio.run(main())
notebook.ipynb CHANGED
@@ -4,43 +4,78 @@
4
  "cell_type": "markdown",
5
  "metadata": {},
6
  "source": [
7
- "# CSS Zen Garden Scraper\n",
8
  "\n",
9
- "This notebook scrapes CSS Zen Garden designs and captures screenshots at different viewport sizes."
10
  ]
11
  },
12
  {
13
  "cell_type": "code",
14
  "execution_count": 1,
15
  "metadata": {},
16
- "outputs": [],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  "source": [
18
- "# Setup and imports\n",
19
- "import asyncio\n",
20
- "from playwright.async_api import async_playwright\n",
21
- "import os\n",
22
- "import json\n",
23
- "from bs4 import BeautifulSoup\n",
24
- "import requests\n",
25
  "from pathlib import Path\n",
26
- "import pandas as pd\n",
27
- "from typing import List, Dict, Any"
28
- ]
29
- },
30
- {
31
- "cell_type": "code",
32
- "execution_count": null,
33
- "metadata": {},
34
- "outputs": [],
35
- "source": [
36
- "# Create directories\n",
37
- "BASE_DIR = Path('zen_garden_data')\n",
38
- "SCREENSHOTS_DIR = BASE_DIR / 'screenshots'\n",
39
- "CSS_DIR = BASE_DIR / 'css'\n",
40
- "METADATA_DIR = BASE_DIR / 'metadata'\n",
41
  "\n",
42
- "for dir_path in [BASE_DIR, SCREENSHOTS_DIR, CSS_DIR, METADATA_DIR]:\n",
43
- " dir_path.mkdir(parents=True, exist_ok=True)"
44
  ]
45
  }
46
  ],
 
4
  "cell_type": "markdown",
5
  "metadata": {},
6
  "source": [
7
+ "# Test CSS Zen Garden Scraper and Analyzer\n",
8
  "\n",
9
+ "This notebook tests the scraper and design analyzer."
10
  ]
11
  },
12
  {
13
  "cell_type": "code",
14
  "execution_count": 1,
15
  "metadata": {},
16
+ "outputs": [
17
+ {
18
+ "name": "stdout",
19
+ "output_type": "stream",
20
+ "text": [
21
+ "Analyzing design 220...\n",
22
+ "Type of response content: <class 'str'>\n",
23
+ "Length of response content: 450\n",
24
+ "Cleaned response for design 220: {\n",
25
+ " \"description\": \"The design is minimalistic with a focus on typography, subtle background elements, and a neutral color palette. It emphasizes a clean and organized layout, suitable for showcasing content-heavy pages such as articles or educational materials.\",\n",
26
+ " \"categories\": [\"Minimalism\", \"Typography-focused\"],\n",
27
+ " \"visual_characteristics\": [\"Neutral color palette\", \"Clean layout\", \"Subtle typography\", \"Organized content\"]\n",
28
+ "}\n",
29
+ "JSON parsed\n",
30
+ "Successfully analyzed design 220\n",
31
+ "\n",
32
+ "Analysis for design 220:\n",
33
+ "Description: The design is minimalistic with a focus on typography, subtle background elements, and a neutral color palette. It emphasizes a clean and organized layout, suitable for showcasing content-heavy pages such as articles or educational materials.\n",
34
+ "Categories: Minimalism, Typography-focused\n",
35
+ "Analyzing design 221...\n",
36
+ "Type of response content: <class 'str'>\n",
37
+ "Length of response content: 680\n",
38
+ "Cleaned response for design 221: {\n",
39
+ " \"description\": \"The visual design features a bold, colorful layout with a mix of geometric shapes and high-contrast text blocks. It uses a playful color palette of purples, blues, oranges, and cream tones. The design is structured to guide the viewer's eye vertically and horizontally across sections with clear typography. It appears modern and suited for showcasing CSS design capabilities in a playful yet professional manner.\",\n",
40
+ " \"categories\": [\n",
41
+ " \"Modern\",\n",
42
+ " \"Playful\"\n",
43
+ " ],\n",
44
+ " \"visual_characteristics\": [\n",
45
+ " \"Bold colors\",\n",
46
+ " \"Geometric shapes\",\n",
47
+ " \"High-contrast typography\",\n",
48
+ " \"Vertical and horizontal layout\"\n",
49
+ " ]\n",
50
+ "}\n",
51
+ "JSON parsed\n",
52
+ "Successfully analyzed design 221\n",
53
+ "\n",
54
+ "Analysis for design 221:\n",
55
+ "Description: The visual design features a bold, colorful layout with a mix of geometric shapes and high-contrast text blocks. It uses a playful color palette of purples, blues, oranges, and cream tones. The design is structured to guide the viewer's eye vertically and horizontally across sections with clear typography. It appears modern and suited for showcasing CSS design capabilities in a playful yet professional manner.\n",
56
+ "Categories: Modern, Playful\n"
57
+ ]
58
+ }
59
+ ],
60
  "source": [
61
+ "from analyze_designs import analyze_screenshot\n",
 
 
 
 
 
 
62
  "from pathlib import Path\n",
63
+ "import asyncio\n",
64
+ "\n",
65
+ "# Test designs to analyze\n",
66
+ "test_design_ids = [\"220\", \"221\"]\n",
67
+ "\n",
68
+ "async def test_analyzer():\n",
69
+ " for design_id in test_design_ids:\n",
70
+ " design_path = Path(f\"designs/{design_id}\")\n",
71
+ " result = await analyze_screenshot(design_id, design_path)\n",
72
+ " \n",
73
+ " if result[1] is not None: # If analysis was successful\n",
74
+ " print(f\"\\nAnalysis for design {design_id}:\")\n",
75
+ " print(f\"Description: {result[1]}\")\n",
76
+ " print(f\"Categories: {', '.join(result[2])}\")\n",
 
77
  "\n",
78
+ "await test_analyzer()"
 
79
  ]
80
  }
81
  ],
poetry.lock CHANGED
@@ -934,6 +934,18 @@ files = [
934
  graph = ["objgraph (>=1.7.2)"]
935
  profile = ["gprof2dot (>=2022.7.29)"]
936
 
 
 
 
 
 
 
 
 
 
 
 
 
937
  [[package]]
938
  name = "executing"
939
  version = "2.2.0"
@@ -1691,6 +1703,92 @@ MarkupSafe = ">=2.0"
1691
  [package.extras]
1692
  i18n = ["Babel (>=2.7)"]
1693
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1694
  [[package]]
1695
  name = "jmespath"
1696
  version = "1.0.1"
@@ -3125,6 +3223,32 @@ files = [
3125
  {file = "nvidia_nvtx_cu12-12.1.105-py3-none-win_amd64.whl", hash = "sha256:65f4d98982b31b60026e0e6de73fbdfc09d08a96f4656dd3665ca616a11e1e82"},
3126
  ]
3127
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3128
  [[package]]
3129
  name = "opentelemetry-api"
3130
  version = "1.29.0"
@@ -3369,21 +3493,6 @@ files = [
3369
  {file = "orjson-3.10.15.tar.gz", hash = "sha256:05ca7fe452a2e9d8d9d706a2984c95b9c2ebc5db417ce0b7a49b91d50642a23e"},
3370
  ]
3371
 
3372
- [[package]]
3373
- name = "outcome"
3374
- version = "1.3.0.post0"
3375
- description = "Capture the outcome of Python function calls."
3376
- optional = false
3377
- python-versions = ">=3.7"
3378
- groups = ["main"]
3379
- files = [
3380
- {file = "outcome-1.3.0.post0-py2.py3-none-any.whl", hash = "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b"},
3381
- {file = "outcome-1.3.0.post0.tar.gz", hash = "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8"},
3382
- ]
3383
-
3384
- [package.dependencies]
3385
- attrs = ">=19.2.0"
3386
-
3387
  [[package]]
3388
  name = "overrides"
3389
  version = "7.7.0"
@@ -4231,19 +4340,6 @@ files = [
4231
  {file = "PyPyDispatcher-2.1.2.tar.gz", hash = "sha256:b6bec5dfcff9d2535bca2b23c80eae367b1ac250a645106948d315fcfa9130f2"},
4232
  ]
4233
 
4234
- [[package]]
4235
- name = "pysocks"
4236
- version = "1.7.1"
4237
- description = "A Python SOCKS client module. See https://github.com/Anorov/PySocks for more information."
4238
- optional = false
4239
- python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
4240
- groups = ["main"]
4241
- files = [
4242
- {file = "PySocks-1.7.1-py27-none-any.whl", hash = "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299"},
4243
- {file = "PySocks-1.7.1-py3-none-any.whl", hash = "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5"},
4244
- {file = "PySocks-1.7.1.tar.gz", hash = "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0"},
4245
- ]
4246
-
4247
  [[package]]
4248
  name = "python-dateutil"
4249
  version = "2.9.0.post0"
@@ -5100,26 +5196,6 @@ Twisted = ">=21.7.0"
5100
  w3lib = ">=1.17.0"
5101
  "zope.interface" = ">=5.1.0"
5102
 
5103
- [[package]]
5104
- name = "selenium"
5105
- version = "4.29.0"
5106
- description = "Official Python bindings for Selenium WebDriver"
5107
- optional = false
5108
- python-versions = ">=3.9"
5109
- groups = ["main"]
5110
- files = [
5111
- {file = "selenium-4.29.0-py3-none-any.whl", hash = "sha256:ce5d26f1ddc1111641113653af33694c13947dd36c2df09cdd33f554351d372e"},
5112
- {file = "selenium-4.29.0.tar.gz", hash = "sha256:3a62f7ec33e669364a6c0562a701deb69745b569c50d55f1a912bf8eb33358ba"},
5113
- ]
5114
-
5115
- [package.dependencies]
5116
- certifi = ">=2021.10.8"
5117
- trio = ">=0.17,<1.0"
5118
- trio-websocket = ">=0.9,<1.0"
5119
- typing_extensions = ">=4.9,<5.0"
5120
- urllib3 = {version = ">=1.26,<3", extras = ["socks"]}
5121
- websocket-client = ">=1.8,<2.0"
5122
-
5123
  [[package]]
5124
  name = "send2trash"
5125
  version = "1.8.3"
@@ -5254,18 +5330,6 @@ files = [
5254
  {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
5255
  ]
5256
 
5257
- [[package]]
5258
- name = "sortedcontainers"
5259
- version = "2.4.0"
5260
- description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set"
5261
- optional = false
5262
- python-versions = "*"
5263
- groups = ["main"]
5264
- files = [
5265
- {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"},
5266
- {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"},
5267
- ]
5268
-
5269
  [[package]]
5270
  name = "soupsieve"
5271
  version = "2.6"
@@ -5790,43 +5854,6 @@ torchhub = ["filelock", "huggingface-hub (>=0.26.0,<1.0)", "importlib-metadata",
5790
  video = ["av"]
5791
  vision = ["Pillow (>=10.0.1,<=15.0)"]
5792
 
5793
- [[package]]
5794
- name = "trio"
5795
- version = "0.29.0"
5796
- description = "A friendly Python library for async concurrency and I/O"
5797
- optional = false
5798
- python-versions = ">=3.9"
5799
- groups = ["main"]
5800
- files = [
5801
- {file = "trio-0.29.0-py3-none-any.whl", hash = "sha256:d8c463f1a9cc776ff63e331aba44c125f423a5a13c684307e828d930e625ba66"},
5802
- {file = "trio-0.29.0.tar.gz", hash = "sha256:ea0d3967159fc130acb6939a0be0e558e364fee26b5deeecc893a6b08c361bdf"},
5803
- ]
5804
-
5805
- [package.dependencies]
5806
- attrs = ">=23.2.0"
5807
- cffi = {version = ">=1.14", markers = "os_name == \"nt\" and implementation_name != \"pypy\""}
5808
- idna = "*"
5809
- outcome = "*"
5810
- sniffio = ">=1.3.0"
5811
- sortedcontainers = "*"
5812
-
5813
- [[package]]
5814
- name = "trio-websocket"
5815
- version = "0.12.1"
5816
- description = "WebSocket library for Trio"
5817
- optional = false
5818
- python-versions = ">=3.8"
5819
- groups = ["main"]
5820
- files = [
5821
- {file = "trio_websocket-0.12.1-py3-none-any.whl", hash = "sha256:608ec746bb287e5d5a66baf483e41194193c5cf05ffaad6240e7d1fcd80d1e6f"},
5822
- {file = "trio_websocket-0.12.1.tar.gz", hash = "sha256:d55ccd4d3eae27c494f3fdae14823317839bdcb8214d1173eacc4d42c69fc91b"},
5823
- ]
5824
-
5825
- [package.dependencies]
5826
- outcome = ">=1.2.0"
5827
- trio = ">=0.11"
5828
- wsproto = ">=0.14"
5829
-
5830
  [[package]]
5831
  name = "triton"
5832
  version = "2.1.0"
@@ -5987,9 +6014,6 @@ files = [
5987
  {file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"},
5988
  ]
5989
 
5990
- [package.dependencies]
5991
- pysocks = {version = ">=1.5.6,<1.5.7 || >1.5.7,<2.0", optional = true, markers = "extra == \"socks\""}
5992
-
5993
  [package.extras]
5994
  brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
5995
  h2 = ["h2 (>=4,<5)"]
@@ -6652,4 +6676,4 @@ cffi = ["cffi (>=1.11)"]
6652
  [metadata]
6653
  lock-version = "2.1"
6654
  python-versions = ">=3.11,<3.12"
6655
- content-hash = "7c96cf12452946942e8ae113f926274d74b1ac6d00682c1fc77807b22ff07f2f"
 
934
  graph = ["objgraph (>=1.7.2)"]
935
  profile = ["gprof2dot (>=2022.7.29)"]
936
 
937
+ [[package]]
938
+ name = "distro"
939
+ version = "1.9.0"
940
+ description = "Distro - an OS platform information API"
941
+ optional = false
942
+ python-versions = ">=3.6"
943
+ groups = ["main"]
944
+ files = [
945
+ {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"},
946
+ {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"},
947
+ ]
948
+
949
  [[package]]
950
  name = "executing"
951
  version = "2.2.0"
 
1703
  [package.extras]
1704
  i18n = ["Babel (>=2.7)"]
1705
 
1706
+ [[package]]
1707
+ name = "jiter"
1708
+ version = "0.8.2"
1709
+ description = "Fast iterable JSON parser."
1710
+ optional = false
1711
+ python-versions = ">=3.8"
1712
+ groups = ["main"]
1713
+ files = [
1714
+ {file = "jiter-0.8.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:ca8577f6a413abe29b079bc30f907894d7eb07a865c4df69475e868d73e71c7b"},
1715
+ {file = "jiter-0.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b25bd626bde7fb51534190c7e3cb97cee89ee76b76d7585580e22f34f5e3f393"},
1716
+ {file = "jiter-0.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5c826a221851a8dc028eb6d7d6429ba03184fa3c7e83ae01cd6d3bd1d4bd17d"},
1717
+ {file = "jiter-0.8.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d35c864c2dff13dfd79fb070fc4fc6235d7b9b359efe340e1261deb21b9fcb66"},
1718
+ {file = "jiter-0.8.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f557c55bc2b7676e74d39d19bcb8775ca295c7a028246175d6a8b431e70835e5"},
1719
+ {file = "jiter-0.8.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:580ccf358539153db147e40751a0b41688a5ceb275e6f3e93d91c9467f42b2e3"},
1720
+ {file = "jiter-0.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af102d3372e917cffce49b521e4c32c497515119dc7bd8a75665e90a718bbf08"},
1721
+ {file = "jiter-0.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cadcc978f82397d515bb2683fc0d50103acff2a180552654bb92d6045dec2c49"},
1722
+ {file = "jiter-0.8.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ba5bdf56969cad2019d4e8ffd3f879b5fdc792624129741d3d83fc832fef8c7d"},
1723
+ {file = "jiter-0.8.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3b94a33a241bee9e34b8481cdcaa3d5c2116f575e0226e421bed3f7a6ea71cff"},
1724
+ {file = "jiter-0.8.2-cp310-cp310-win32.whl", hash = "sha256:6e5337bf454abddd91bd048ce0dca5134056fc99ca0205258766db35d0a2ea43"},
1725
+ {file = "jiter-0.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:4a9220497ca0cb1fe94e3f334f65b9b5102a0b8147646118f020d8ce1de70105"},
1726
+ {file = "jiter-0.8.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:2dd61c5afc88a4fda7d8b2cf03ae5947c6ac7516d32b7a15bf4b49569a5c076b"},
1727
+ {file = "jiter-0.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a6c710d657c8d1d2adbbb5c0b0c6bfcec28fd35bd6b5f016395f9ac43e878a15"},
1728
+ {file = "jiter-0.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9584de0cd306072635fe4b89742bf26feae858a0683b399ad0c2509011b9dc0"},
1729
+ {file = "jiter-0.8.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5a90a923338531b7970abb063cfc087eebae6ef8ec8139762007188f6bc69a9f"},
1730
+ {file = "jiter-0.8.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d21974d246ed0181558087cd9f76e84e8321091ebfb3a93d4c341479a736f099"},
1731
+ {file = "jiter-0.8.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:32475a42b2ea7b344069dc1e81445cfc00b9d0e3ca837f0523072432332e9f74"},
1732
+ {file = "jiter-0.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b9931fd36ee513c26b5bf08c940b0ac875de175341cbdd4fa3be109f0492586"},
1733
+ {file = "jiter-0.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ce0820f4a3a59ddced7fce696d86a096d5cc48d32a4183483a17671a61edfddc"},
1734
+ {file = "jiter-0.8.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8ffc86ae5e3e6a93765d49d1ab47b6075a9c978a2b3b80f0f32628f39caa0c88"},
1735
+ {file = "jiter-0.8.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5127dc1abd809431172bc3fbe8168d6b90556a30bb10acd5ded41c3cfd6f43b6"},
1736
+ {file = "jiter-0.8.2-cp311-cp311-win32.whl", hash = "sha256:66227a2c7b575720c1871c8800d3a0122bb8ee94edb43a5685aa9aceb2782d44"},
1737
+ {file = "jiter-0.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:cde031d8413842a1e7501e9129b8e676e62a657f8ec8166e18a70d94d4682855"},
1738
+ {file = "jiter-0.8.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:e6ec2be506e7d6f9527dae9ff4b7f54e68ea44a0ef6b098256ddf895218a2f8f"},
1739
+ {file = "jiter-0.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76e324da7b5da060287c54f2fabd3db5f76468006c811831f051942bf68c9d44"},
1740
+ {file = "jiter-0.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:180a8aea058f7535d1c84183c0362c710f4750bef66630c05f40c93c2b152a0f"},
1741
+ {file = "jiter-0.8.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:025337859077b41548bdcbabe38698bcd93cfe10b06ff66617a48ff92c9aec60"},
1742
+ {file = "jiter-0.8.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ecff0dc14f409599bbcafa7e470c00b80f17abc14d1405d38ab02e4b42e55b57"},
1743
+ {file = "jiter-0.8.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffd9fee7d0775ebaba131f7ca2e2d83839a62ad65e8e02fe2bd8fc975cedeb9e"},
1744
+ {file = "jiter-0.8.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14601dcac4889e0a1c75ccf6a0e4baf70dbc75041e51bcf8d0e9274519df6887"},
1745
+ {file = "jiter-0.8.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:92249669925bc1c54fcd2ec73f70f2c1d6a817928480ee1c65af5f6b81cdf12d"},
1746
+ {file = "jiter-0.8.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e725edd0929fa79f8349ab4ec7f81c714df51dc4e991539a578e5018fa4a7152"},
1747
+ {file = "jiter-0.8.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bf55846c7b7a680eebaf9c3c48d630e1bf51bdf76c68a5f654b8524335b0ad29"},
1748
+ {file = "jiter-0.8.2-cp312-cp312-win32.whl", hash = "sha256:7efe4853ecd3d6110301665a5178b9856be7e2a9485f49d91aa4d737ad2ae49e"},
1749
+ {file = "jiter-0.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:83c0efd80b29695058d0fd2fa8a556490dbce9804eac3e281f373bbc99045f6c"},
1750
+ {file = "jiter-0.8.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:ca1f08b8e43dc3bd0594c992fb1fd2f7ce87f7bf0d44358198d6da8034afdf84"},
1751
+ {file = "jiter-0.8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5672a86d55416ccd214c778efccf3266b84f87b89063b582167d803246354be4"},
1752
+ {file = "jiter-0.8.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58dc9bc9767a1101f4e5e22db1b652161a225874d66f0e5cb8e2c7d1c438b587"},
1753
+ {file = "jiter-0.8.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:37b2998606d6dadbb5ccda959a33d6a5e853252d921fec1792fc902351bb4e2c"},
1754
+ {file = "jiter-0.8.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ab9a87f3784eb0e098f84a32670cfe4a79cb6512fd8f42ae3d0709f06405d18"},
1755
+ {file = "jiter-0.8.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:79aec8172b9e3c6d05fd4b219d5de1ac616bd8da934107325a6c0d0e866a21b6"},
1756
+ {file = "jiter-0.8.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:711e408732d4e9a0208008e5892c2966b485c783cd2d9a681f3eb147cf36c7ef"},
1757
+ {file = "jiter-0.8.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:653cf462db4e8c41995e33d865965e79641ef45369d8a11f54cd30888b7e6ff1"},
1758
+ {file = "jiter-0.8.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:9c63eaef32b7bebac8ebebf4dabebdbc6769a09c127294db6babee38e9f405b9"},
1759
+ {file = "jiter-0.8.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:eb21aaa9a200d0a80dacc7a81038d2e476ffe473ffdd9c91eb745d623561de05"},
1760
+ {file = "jiter-0.8.2-cp313-cp313-win32.whl", hash = "sha256:789361ed945d8d42850f919342a8665d2dc79e7e44ca1c97cc786966a21f627a"},
1761
+ {file = "jiter-0.8.2-cp313-cp313-win_amd64.whl", hash = "sha256:ab7f43235d71e03b941c1630f4b6e3055d46b6cb8728a17663eaac9d8e83a865"},
1762
+ {file = "jiter-0.8.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b426f72cd77da3fec300ed3bc990895e2dd6b49e3bfe6c438592a3ba660e41ca"},
1763
+ {file = "jiter-0.8.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2dd880785088ff2ad21ffee205e58a8c1ddabc63612444ae41e5e4b321b39c0"},
1764
+ {file = "jiter-0.8.2-cp313-cp313t-win_amd64.whl", hash = "sha256:3ac9f578c46f22405ff7f8b1f5848fb753cc4b8377fbec8470a7dc3997ca7566"},
1765
+ {file = "jiter-0.8.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:9e1fa156ee9454642adb7e7234a383884452532bc9d53d5af2d18d98ada1d79c"},
1766
+ {file = "jiter-0.8.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0cf5dfa9956d96ff2efb0f8e9c7d055904012c952539a774305aaaf3abdf3d6c"},
1767
+ {file = "jiter-0.8.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e52bf98c7e727dd44f7c4acb980cb988448faeafed8433c867888268899b298b"},
1768
+ {file = "jiter-0.8.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a2ecaa3c23e7a7cf86d00eda3390c232f4d533cd9ddea4b04f5d0644faf642c5"},
1769
+ {file = "jiter-0.8.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:08d4c92bf480e19fc3f2717c9ce2aa31dceaa9163839a311424b6862252c943e"},
1770
+ {file = "jiter-0.8.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99d9a1eded738299ba8e106c6779ce5c3893cffa0e32e4485d680588adae6db8"},
1771
+ {file = "jiter-0.8.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d20be8b7f606df096e08b0b1b4a3c6f0515e8dac296881fe7461dfa0fb5ec817"},
1772
+ {file = "jiter-0.8.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d33f94615fcaf872f7fd8cd98ac3b429e435c77619777e8a449d9d27e01134d1"},
1773
+ {file = "jiter-0.8.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:317b25e98a35ffec5c67efe56a4e9970852632c810d35b34ecdd70cc0e47b3b6"},
1774
+ {file = "jiter-0.8.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fc9043259ee430ecd71d178fccabd8c332a3bf1e81e50cae43cc2b28d19e4cb7"},
1775
+ {file = "jiter-0.8.2-cp38-cp38-win32.whl", hash = "sha256:fc5adda618205bd4678b146612ce44c3cbfdee9697951f2c0ffdef1f26d72b63"},
1776
+ {file = "jiter-0.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:cd646c827b4f85ef4a78e4e58f4f5854fae0caf3db91b59f0d73731448a970c6"},
1777
+ {file = "jiter-0.8.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:e41e75344acef3fc59ba4765df29f107f309ca9e8eace5baacabd9217e52a5ee"},
1778
+ {file = "jiter-0.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7f22b16b35d5c1df9dfd58843ab2cd25e6bf15191f5a236bed177afade507bfc"},
1779
+ {file = "jiter-0.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7200b8f7619d36aa51c803fd52020a2dfbea36ffec1b5e22cab11fd34d95a6d"},
1780
+ {file = "jiter-0.8.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:70bf4c43652cc294040dbb62256c83c8718370c8b93dd93d934b9a7bf6c4f53c"},
1781
+ {file = "jiter-0.8.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f9d471356dc16f84ed48768b8ee79f29514295c7295cb41e1133ec0b2b8d637d"},
1782
+ {file = "jiter-0.8.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:859e8eb3507894093d01929e12e267f83b1d5f6221099d3ec976f0c995cb6bd9"},
1783
+ {file = "jiter-0.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaa58399c01db555346647a907b4ef6d4f584b123943be6ed5588c3f2359c9f4"},
1784
+ {file = "jiter-0.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8f2d5ed877f089862f4c7aacf3a542627c1496f972a34d0474ce85ee7d939c27"},
1785
+ {file = "jiter-0.8.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:03c9df035d4f8d647f8c210ddc2ae0728387275340668fb30d2421e17d9a0841"},
1786
+ {file = "jiter-0.8.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8bd2a824d08d8977bb2794ea2682f898ad3d8837932e3a74937e93d62ecbb637"},
1787
+ {file = "jiter-0.8.2-cp39-cp39-win32.whl", hash = "sha256:ca29b6371ebc40e496995c94b988a101b9fbbed48a51190a4461fcb0a68b4a36"},
1788
+ {file = "jiter-0.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:1c0dfbd1be3cbefc7510102370d86e35d1d53e5a93d48519688b1bf0f761160a"},
1789
+ {file = "jiter-0.8.2.tar.gz", hash = "sha256:cd73d3e740666d0e639f678adb176fad25c1bcbdae88d8d7b857e1783bb4212d"},
1790
+ ]
1791
+
1792
  [[package]]
1793
  name = "jmespath"
1794
  version = "1.0.1"
 
3223
  {file = "nvidia_nvtx_cu12-12.1.105-py3-none-win_amd64.whl", hash = "sha256:65f4d98982b31b60026e0e6de73fbdfc09d08a96f4656dd3665ca616a11e1e82"},
3224
  ]
3225
 
3226
+ [[package]]
3227
+ name = "openai"
3228
+ version = "1.63.2"
3229
+ description = "The official Python library for the openai API"
3230
+ optional = false
3231
+ python-versions = ">=3.8"
3232
+ groups = ["main"]
3233
+ files = [
3234
+ {file = "openai-1.63.2-py3-none-any.whl", hash = "sha256:1f38b27b5a40814c2b7d8759ec78110df58c4a614c25f182809ca52b080ff4d4"},
3235
+ {file = "openai-1.63.2.tar.gz", hash = "sha256:aeabeec984a7d2957b4928ceaa339e2ead19c61cfcf35ae62b7c363368d26360"},
3236
+ ]
3237
+
3238
+ [package.dependencies]
3239
+ anyio = ">=3.5.0,<5"
3240
+ distro = ">=1.7.0,<2"
3241
+ httpx = ">=0.23.0,<1"
3242
+ jiter = ">=0.4.0,<1"
3243
+ pydantic = ">=1.9.0,<3"
3244
+ sniffio = "*"
3245
+ tqdm = ">4"
3246
+ typing-extensions = ">=4.11,<5"
3247
+
3248
+ [package.extras]
3249
+ datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"]
3250
+ realtime = ["websockets (>=13,<15)"]
3251
+
3252
  [[package]]
3253
  name = "opentelemetry-api"
3254
  version = "1.29.0"
 
3493
  {file = "orjson-3.10.15.tar.gz", hash = "sha256:05ca7fe452a2e9d8d9d706a2984c95b9c2ebc5db417ce0b7a49b91d50642a23e"},
3494
  ]
3495
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3496
  [[package]]
3497
  name = "overrides"
3498
  version = "7.7.0"
 
4340
  {file = "PyPyDispatcher-2.1.2.tar.gz", hash = "sha256:b6bec5dfcff9d2535bca2b23c80eae367b1ac250a645106948d315fcfa9130f2"},
4341
  ]
4342
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4343
  [[package]]
4344
  name = "python-dateutil"
4345
  version = "2.9.0.post0"
 
5196
  w3lib = ">=1.17.0"
5197
  "zope.interface" = ">=5.1.0"
5198
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5199
  [[package]]
5200
  name = "send2trash"
5201
  version = "1.8.3"
 
5330
  {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
5331
  ]
5332
 
 
 
 
 
 
 
 
 
 
 
 
 
5333
  [[package]]
5334
  name = "soupsieve"
5335
  version = "2.6"
 
5854
  video = ["av"]
5855
  vision = ["Pillow (>=10.0.1,<=15.0)"]
5856
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5857
  [[package]]
5858
  name = "triton"
5859
  version = "2.1.0"
 
6014
  {file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"},
6015
  ]
6016
 
 
 
 
6017
  [package.extras]
6018
  brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
6019
  h2 = ["h2 (>=4,<5)"]
 
6676
  [metadata]
6677
  lock-version = "2.1"
6678
  python-versions = ">=3.11,<3.12"
6679
+ content-hash = "2da765cfa2b176f01cd9cc8a4be268a6239ad3fe087e9082d68c486cf8f71357"
pyproject.toml CHANGED
@@ -24,6 +24,7 @@ dependencies = [
24
  "sentence-transformers>=2.5.0",
25
  "python-dotenv>=1.0.0",
26
  "requests>=2.28.1",
 
27
  ]
28
  requires-python = ">=3.11,<3.12"
29
 
 
24
  "sentence-transformers>=2.5.0",
25
  "python-dotenv>=1.0.0",
26
  "requests>=2.28.1",
27
+ "openai (>=1.63.2,<2.0.0)",
28
  ]
29
  requires-python = ">=3.11,<3.12"
30
 
test_scraper.ipynb CHANGED
@@ -89,15 +89,17 @@
89
  "import json\n",
90
  "import os\n",
91
  "\n",
92
- "design_dir = f\"designs/{test_design_id}\"\n",
93
- "print(\"Files created:\")\n",
94
- "print(os.listdir(design_dir))\n",
 
95
  "\n",
96
- "# Display metadata\n",
97
- "with open(f\"{design_dir}/metadata.json\") as f:\n",
98
- " metadata = json.load(f)\n",
99
- "print(\"\\nMetadata:\")\n",
100
- "print(json.dumps(metadata, indent=2))"
 
101
  ]
102
  }
103
  ],
 
89
  "import json\n",
90
  "import os\n",
91
  "\n",
92
+ "for id in test_design_ids:\n",
93
+ " design_dir = f\"designs/{id}\"\n",
94
+ " print(\"Files created:\")\n",
95
+ " print(os.listdir(design_dir))\n",
96
  "\n",
97
+ " # Display metadata\n",
98
+ " with open(f\"{design_dir}/metadata.json\") as f:\n",
99
+ " metadata = json.load(f)\n",
100
+ " print(\"\\nMetadata:\")\n",
101
+ " print(json.dumps(metadata, indent=2))\n",
102
+ "\n"
103
  ]
104
  }
105
  ],
uv.lock DELETED
The diff for this file is too large to render. See raw diff