Technologic101 commited on
Commit
ab1d8bc
·
1 Parent(s): 41422db

task: add fine-tuning and evaluation

Browse files
pyproject.toml CHANGED
@@ -35,6 +35,8 @@ dependencies = [
35
  "websockets>=11.0.3",
36
  "langsmith>=0.3.11",
37
  "matplotlib>=3.10.0",
 
 
38
  ]
39
 
40
  [build-system]
 
35
  "websockets>=11.0.3",
36
  "langsmith>=0.3.11",
37
  "matplotlib>=3.10.0",
38
+ "accelerate>=0.26.0",
39
+ "nest-asyncio>=1.6.0",
40
  ]
41
 
42
  [build-system]
src/fine_tune_embeddings.ipynb ADDED
@@ -0,0 +1,903 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {},
6
+ "source": [
7
+ "# Fine-tuning Embeddings for Design Data"
8
+ ]
9
+ },
10
+ {
11
+ "cell_type": "markdown",
12
+ "metadata": {},
13
+ "source": [
14
+ "Let's see if we can improve the quality of our returned results using a fine-tuned embedding model trained on our designs!\n",
15
+ "\n",
16
+ "We'll use SentenceTransformers to fine-tune our embedding model, as it provides a straightforward approach for adapting models to specific domains."
17
+ ]
18
+ },
19
+ {
20
+ "cell_type": "code",
21
+ "execution_count": 1,
22
+ "metadata": {},
23
+ "outputs": [],
24
+ "source": [
25
+ "# Install required packages if needed\n",
26
+ "# !pip install sentence-transformers datasets torch matplotlib"
27
+ ]
28
+ },
29
+ {
30
+ "cell_type": "code",
31
+ "execution_count": 2,
32
+ "metadata": {},
33
+ "outputs": [],
34
+ "source": [
35
+ "import json\n",
36
+ "import os\n",
37
+ "import pandas as pd\n",
38
+ "import numpy as np\n",
39
+ "import torch\n",
40
+ "import matplotlib.pyplot as plt\n",
41
+ "from pathlib import Path\n",
42
+ "from sentence_transformers import SentenceTransformer, InputExample, losses\n",
43
+ "from sentence_transformers.evaluation import EmbeddingSimilarityEvaluator\n",
44
+ "from torch.utils.data import DataLoader"
45
+ ]
46
+ },
47
+ {
48
+ "cell_type": "markdown",
49
+ "metadata": {},
50
+ "source": [
51
+ "## 1. Load Design Data\n",
52
+ "\n",
53
+ "First, we'll load the design data from our existing dataset."
54
+ ]
55
+ },
56
+ {
57
+ "cell_type": "code",
58
+ "execution_count": 3,
59
+ "metadata": {},
60
+ "outputs": [
61
+ {
62
+ "name": "stdout",
63
+ "output_type": "stream",
64
+ "text": [
65
+ "/Users/owner/Desktop/Projects/ai-maker-space/code/ImagineUI/src/data/designs\n",
66
+ "Loaded 141 designs\n"
67
+ ]
68
+ },
69
+ {
70
+ "data": {
71
+ "text/html": [
72
+ "<div>\n",
73
+ "<style scoped>\n",
74
+ " .dataframe tbody tr th:only-of-type {\n",
75
+ " vertical-align: middle;\n",
76
+ " }\n",
77
+ "\n",
78
+ " .dataframe tbody tr th {\n",
79
+ " vertical-align: top;\n",
80
+ " }\n",
81
+ "\n",
82
+ " .dataframe thead th {\n",
83
+ " text-align: right;\n",
84
+ " }\n",
85
+ "</style>\n",
86
+ "<table border=\"1\" class=\"dataframe\">\n",
87
+ " <thead>\n",
88
+ " <tr style=\"text-align: right;\">\n",
89
+ " <th></th>\n",
90
+ " <th>id</th>\n",
91
+ " <th>text</th>\n",
92
+ " <th>categories</th>\n",
93
+ " <th>visual_characteristics</th>\n",
94
+ " </tr>\n",
95
+ " </thead>\n",
96
+ " <tbody>\n",
97
+ " <tr>\n",
98
+ " <th>0</th>\n",
99
+ " <td>135</td>\n",
100
+ " <td>Design 135:\\n Description: This des...</td>\n",
101
+ " <td>[Traditional, Elegant, Text-Heavy, Classic]</td>\n",
102
+ " <td>[Muted Color Palette, Vertical Layout, Serif T...</td>\n",
103
+ " </tr>\n",
104
+ " <tr>\n",
105
+ " <th>1</th>\n",
106
+ " <td>132</td>\n",
107
+ " <td>Design 132:\\n Description: This des...</td>\n",
108
+ " <td>[minimalist, nature-inspired, modern, zen-them...</td>\n",
109
+ " <td>[white background, green accents, illustrative...</td>\n",
110
+ " </tr>\n",
111
+ " <tr>\n",
112
+ " <th>2</th>\n",
113
+ " <td>104</td>\n",
114
+ " <td>Design 104:\\n Description: The CSS ...</td>\n",
115
+ " <td>[minimalism, elegance, typography, web design ...</td>\n",
116
+ " <td>[subtle color palette, classic serif fonts, cl...</td>\n",
117
+ " </tr>\n",
118
+ " <tr>\n",
119
+ " <th>3</th>\n",
120
+ " <td>103</td>\n",
121
+ " <td>Design 103:\\n Description: This des...</td>\n",
122
+ " <td>[vintage, classical, dramatic, ornate, elegant]</td>\n",
123
+ " <td>[dark color palette, gold accents, traditional...</td>\n",
124
+ " </tr>\n",
125
+ " <tr>\n",
126
+ " <th>4</th>\n",
127
+ " <td>168</td>\n",
128
+ " <td>Design 168:\\n Description: This des...</td>\n",
129
+ " <td>[Humorous, Educational, Whimsical, Nature-them...</td>\n",
130
+ " <td>[Vibrant color palette, Whimsical illustration...</td>\n",
131
+ " </tr>\n",
132
+ " </tbody>\n",
133
+ "</table>\n",
134
+ "</div>"
135
+ ],
136
+ "text/plain": [
137
+ " id text \\\n",
138
+ "0 135 Design 135:\\n Description: This des... \n",
139
+ "1 132 Design 132:\\n Description: This des... \n",
140
+ "2 104 Design 104:\\n Description: The CSS ... \n",
141
+ "3 103 Design 103:\\n Description: This des... \n",
142
+ "4 168 Design 168:\\n Description: This des... \n",
143
+ "\n",
144
+ " categories \\\n",
145
+ "0 [Traditional, Elegant, Text-Heavy, Classic] \n",
146
+ "1 [minimalist, nature-inspired, modern, zen-them... \n",
147
+ "2 [minimalism, elegance, typography, web design ... \n",
148
+ "3 [vintage, classical, dramatic, ornate, elegant] \n",
149
+ "4 [Humorous, Educational, Whimsical, Nature-them... \n",
150
+ "\n",
151
+ " visual_characteristics \n",
152
+ "0 [Muted Color Palette, Vertical Layout, Serif T... \n",
153
+ "1 [white background, green accents, illustrative... \n",
154
+ "2 [subtle color palette, classic serif fonts, cl... \n",
155
+ "3 [dark color palette, gold accents, traditional... \n",
156
+ "4 [Vibrant color palette, Whimsical illustration... "
157
+ ]
158
+ },
159
+ "execution_count": 3,
160
+ "metadata": {},
161
+ "output_type": "execute_result"
162
+ }
163
+ ],
164
+ "source": [
165
+ "def load_design_data():\n",
166
+ " \"\"\"Load design data from the metadata files\"\"\"\n",
167
+ " designs_dir = Path.cwd().parent / \"src\" / \"data\" / \"designs\"\n",
168
+ " print(designs_dir)\n",
169
+ " designs = []\n",
170
+ " \n",
171
+ " # Load all metadata files\n",
172
+ " for design_dir in designs_dir.glob(\"**/metadata.json\"):\n",
173
+ " try:\n",
174
+ " with open(design_dir, \"r\") as f:\n",
175
+ " metadata = json.load(f)\n",
176
+ " \n",
177
+ " # Create a text representation of the design\n",
178
+ " text = f\"\"\"Design {metadata.get('id', 'unknown')}:\n",
179
+ " Description: {metadata.get('description', 'No description available')}\n",
180
+ " Categories: {', '.join(metadata.get('categories', []))}\n",
181
+ " Visual Characteristics: {', '.join(metadata.get('visual_characteristics', []))}\n",
182
+ " \"\"\"\n",
183
+ " \n",
184
+ " designs.append({\n",
185
+ " 'id': metadata.get('id', 'unknown'),\n",
186
+ " 'text': text.strip(),\n",
187
+ " 'categories': metadata.get('categories', []),\n",
188
+ " 'visual_characteristics': metadata.get('visual_characteristics', [])\n",
189
+ " })\n",
190
+ " except Exception as e:\n",
191
+ " print(f\"Error processing design {design_dir}: {e}\")\n",
192
+ " continue\n",
193
+ " \n",
194
+ " print(f\"Loaded {len(designs)} designs\")\n",
195
+ " return designs\n",
196
+ "\n",
197
+ "designs = load_design_data()\n",
198
+ "designs_df = pd.DataFrame(designs)\n",
199
+ "designs_df.head()"
200
+ ]
201
+ },
202
+ {
203
+ "cell_type": "markdown",
204
+ "metadata": {},
205
+ "source": [
206
+ "## 2. Create Training Pairs\n",
207
+ "\n",
208
+ "For fine-tuning, we need to create positive pairs (similar designs) and negative pairs (dissimilar designs). We'll use categories and visual characteristics to determine similarity."
209
+ ]
210
+ },
211
+ {
212
+ "cell_type": "code",
213
+ "execution_count": 8,
214
+ "metadata": {},
215
+ "outputs": [
216
+ {
217
+ "name": "stdout",
218
+ "output_type": "stream",
219
+ "text": [
220
+ "Creating training pairs...\n",
221
+ "Created 95 training examples and 27 evaluation examples\n"
222
+ ]
223
+ }
224
+ ],
225
+ "source": [
226
+ "from sentence_transformers import InputExample\n",
227
+ "def create_training_pairs(designs_df, num_pairs=5000):\n",
228
+ " \"\"\"Create training pairs for fine-tuning\"\"\"\n",
229
+ " training_pairs = []\n",
230
+ " design_ids = designs_df['id'].tolist()\n",
231
+ " \n",
232
+ " # Calculate similarity between designs based on categories and characteristics\n",
233
+ " def calculate_similarity(design1, design2):\n",
234
+ " # Get categories and characteristics for both designs\n",
235
+ " cats1 = set(design1['categories'])\n",
236
+ " cats2 = set(design2['categories'])\n",
237
+ " chars1 = set(design1['visual_characteristics'])\n",
238
+ " chars2 = set(design2['visual_characteristics'])\n",
239
+ " \n",
240
+ " # Calculate Jaccard similarity for categories and characteristics\n",
241
+ " cat_sim = len(cats1.intersection(cats2)) / max(1, len(cats1.union(cats2)))\n",
242
+ " char_sim = len(chars1.intersection(chars2)) / max(1, len(chars1.union(chars2)))\n",
243
+ " \n",
244
+ " # Weighted similarity\n",
245
+ " return 0.5 * cat_sim + 0.5 * char_sim\n",
246
+ " \n",
247
+ " # Create similarity matrix\n",
248
+ " import random\n",
249
+ " train_examples = []\n",
250
+ " eval_examples = []\n",
251
+ " \n",
252
+ " # Create positive pairs (similar designs)\n",
253
+ " for i in range(len(designs_df)):\n",
254
+ " design1 = designs_df.iloc[i].to_dict()\n",
255
+ " similarities = []\n",
256
+ " \n",
257
+ " for j in range(len(designs_df)):\n",
258
+ " if i != j:\n",
259
+ " design2 = designs_df.iloc[j].to_dict()\n",
260
+ " sim = calculate_similarity(design1, design2)\n",
261
+ " similarities.append((j, sim))\n",
262
+ " \n",
263
+ " # Sort by similarity\n",
264
+ " similarities.sort(key=lambda x: x[1], reverse=True)\n",
265
+ " \n",
266
+ " # Add top similar designs as positive pairs\n",
267
+ " for j, sim in similarities[:3]: # Top 3 most similar\n",
268
+ " if sim > 0.2: # Only if they're somewhat similar\n",
269
+ " design2 = designs_df.iloc[j].to_dict()\n",
270
+ " # Create InputExample with texts and similarity score\n",
271
+ " example = InputExample(texts=[design1['text'], design2['text']], label=float(sim))\n",
272
+ " \n",
273
+ " # 80% for training, 20% for evaluation\n",
274
+ " if random.random() < 0.8:\n",
275
+ " train_examples.append(example)\n",
276
+ " else:\n",
277
+ " eval_examples.append(example)\n",
278
+ " \n",
279
+ " print(f\"Created {len(train_examples)} training examples and {len(eval_examples)} evaluation examples\")\n",
280
+ " return train_examples, eval_examples\n",
281
+ "\n",
282
+ "print(\"Creating training pairs...\")\n",
283
+ "train_examples, eval_examples = create_training_pairs(designs_df) "
284
+ ]
285
+ },
286
+ {
287
+ "cell_type": "markdown",
288
+ "metadata": {},
289
+ "source": [
290
+ "## 3. Fine-tune the Model\n",
291
+ "\n",
292
+ "The model I've selected here is the distilbert-base-nli-stsb-mean-tokens model, chosen as a comparison because its BERT training is effective at semantic similarity. Performance isn't too important here, since we have one design per query and we want to return the best match."
293
+ ]
294
+ },
295
+ {
296
+ "cell_type": "code",
297
+ "execution_count": 10,
298
+ "metadata": {},
299
+ "outputs": [
300
+ {
301
+ "name": "stdout",
302
+ "output_type": "stream",
303
+ "text": [
304
+ "Starting model fine-tuning...\n",
305
+ "Loading base model: sentence-transformers/distilbert-base-nli-stsb-mean-tokens\n",
306
+ "\n",
307
+ "Training configuration:\n",
308
+ "- Training examples: 95\n",
309
+ "- Evaluation examples: 27\n",
310
+ "- Batch size: 16\n",
311
+ "- Warmup steps: 0\n",
312
+ "- Using GPU: False\n",
313
+ "- Model will be saved to: /Users/owner/Desktop/Projects/ai-maker-space/code/ImagineUI/src/fine_tuned_design_embeddings_20250225_161918\n"
314
+ ]
315
+ },
316
+ {
317
+ "data": {
318
+ "application/vnd.jupyter.widget-view+json": {
319
+ "model_id": "e4315da477764680aaacae97230e6409",
320
+ "version_major": 2,
321
+ "version_minor": 0
322
+ },
323
+ "text/plain": [
324
+ "Computing widget examples: 0%| | 0/1 [00:00<?, ?example/s]"
325
+ ]
326
+ },
327
+ "metadata": {},
328
+ "output_type": "display_data"
329
+ },
330
+ {
331
+ "data": {
332
+ "text/html": [
333
+ "\n",
334
+ " <div>\n",
335
+ " \n",
336
+ " <progress value='6' max='6' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
337
+ " [6/6 00:36, Epoch 1/1]\n",
338
+ " </div>\n",
339
+ " <table border=\"1\" class=\"dataframe\">\n",
340
+ " <thead>\n",
341
+ " <tr style=\"text-align: left;\">\n",
342
+ " <th>Step</th>\n",
343
+ " <th>Training Loss</th>\n",
344
+ " <th>Validation Loss</th>\n",
345
+ " <th>Pearson Cosine</th>\n",
346
+ " <th>Spearman Cosine</th>\n",
347
+ " </tr>\n",
348
+ " </thead>\n",
349
+ " <tbody>\n",
350
+ " <tr>\n",
351
+ " <td>6</td>\n",
352
+ " <td>No log</td>\n",
353
+ " <td>No log</td>\n",
354
+ " <td>-0.139605</td>\n",
355
+ " <td>-0.068639</td>\n",
356
+ " </tr>\n",
357
+ " </tbody>\n",
358
+ "</table><p>"
359
+ ],
360
+ "text/plain": [
361
+ "<IPython.core.display.HTML object>"
362
+ ]
363
+ },
364
+ "metadata": {},
365
+ "output_type": "display_data"
366
+ },
367
+ {
368
+ "name": "stdout",
369
+ "output_type": "stream",
370
+ "text": [
371
+ "\n",
372
+ "Training complete!\n",
373
+ "Model saved to /Users/owner/Desktop/Projects/ai-maker-space/code/ImagineUI/src/fine_tuned_design_embeddings_20250225_161918\n"
374
+ ]
375
+ }
376
+ ],
377
+ "source": [
378
+ "def fine_tune_model_simple(train_examples, eval_examples, base_model=\"sentence-transformers/distilbert-base-nli-stsb-mean-tokens\"):\n",
379
+ " \"\"\"Fine-tune a SentenceTransformer model\"\"\"\n",
380
+ " import os\n",
381
+ " import torch\n",
382
+ " from datetime import datetime\n",
383
+ " from sentence_transformers import SentenceTransformer, losses\n",
384
+ " from sentence_transformers.evaluation import EmbeddingSimilarityEvaluator\n",
385
+ " from torch.utils.data import DataLoader\n",
386
+ " \n",
387
+ " # Load the base model\n",
388
+ " print(f\"Loading base model: {base_model}\")\n",
389
+ " model = SentenceTransformer(base_model)\n",
390
+ " \n",
391
+ " # Create training dataloader\n",
392
+ " train_dataloader = DataLoader(train_examples, shuffle=True, batch_size=16)\n",
393
+ " \n",
394
+ " # Use CosineSimilarityLoss for fine-tuning\n",
395
+ " train_loss = losses.CosineSimilarityLoss(model)\n",
396
+ " \n",
397
+ " # Create evaluator\n",
398
+ " evaluator = EmbeddingSimilarityEvaluator.from_input_examples(eval_examples)\n",
399
+ " \n",
400
+ " # Create timestamped model save path\n",
401
+ " timestamp = datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n",
402
+ " model_save_path = os.path.join(os.getcwd(), \"fine_tuned_design_embeddings_\" + timestamp)\n",
403
+ " \n",
404
+ " # Set up warm-up steps\n",
405
+ " warmup_steps = int(len(train_dataloader) * 0.1)\n",
406
+ "\n",
407
+ " print(f\"\\nTraining configuration:\")\n",
408
+ " print(f\"- Training examples: {len(train_examples)}\")\n",
409
+ " print(f\"- Evaluation examples: {len(eval_examples)}\")\n",
410
+ " print(f\"- Batch size: 16\")\n",
411
+ " print(f\"- Warmup steps: {warmup_steps}\")\n",
412
+ " print(f\"- Using GPU: {torch.cuda.is_available()}\")\n",
413
+ " print(f\"- Model will be saved to: {model_save_path}\")\n",
414
+ " \n",
415
+ " # Train the model\n",
416
+ " model.fit(\n",
417
+ " train_objectives=[(train_dataloader, train_loss)],\n",
418
+ " evaluator=evaluator,\n",
419
+ " epochs=1, # Start with just 1 epoch to test\n",
420
+ " warmup_steps=warmup_steps,\n",
421
+ " output_path=model_save_path,\n",
422
+ " show_progress_bar=True\n",
423
+ " )\n",
424
+ " \n",
425
+ " print(f\"\\nTraining complete!\")\n",
426
+ " print(f\"Model saved to {model_save_path}\")\n",
427
+ " \n",
428
+ " return model, model_save_path\n",
429
+ "\n",
430
+ "print(\"Starting model fine-tuning...\")\n",
431
+ "fine_tuned_model, model_path = fine_tune_model_simple(train_examples, eval_examples)\n"
432
+ ]
433
+ },
434
+ {
435
+ "cell_type": "markdown",
436
+ "metadata": {},
437
+ "source": [
438
+ "## 4. Evaluate Fine-tuned Model vs Base Model"
439
+ ]
440
+ },
441
+ {
442
+ "cell_type": "markdown",
443
+ "metadata": {},
444
+ "source": [
445
+ "We'll need nest_asyncio to run the async evaluation inside a Jupyter notebook."
446
+ ]
447
+ },
448
+ {
449
+ "cell_type": "code",
450
+ "execution_count": 14,
451
+ "metadata": {},
452
+ "outputs": [],
453
+ "source": [
454
+ "import nest_asyncio\n",
455
+ "nest_asyncio.apply()"
456
+ ]
457
+ },
458
+ {
459
+ "cell_type": "code",
460
+ "execution_count": 16,
461
+ "metadata": {},
462
+ "outputs": [],
463
+ "source": [
464
+ "# Now define a synchronous wrapper for our comparison function\n",
465
+ "def compare_models_sync(base_model_name, fine_tuned_model_path, test_queries):\n",
466
+ " \"\"\"Synchronous wrapper for compare_models\"\"\"\n",
467
+ " import asyncio\n",
468
+ " from langchain_openai import ChatOpenAI\n",
469
+ " import json\n",
470
+ " \n",
471
+ " # Load models\n",
472
+ " print(f\"Loading base model: {base_model_name}\")\n",
473
+ " base_model = SentenceTransformer(base_model_name)\n",
474
+ " \n",
475
+ " print(f\"Loading fine-tuned model from: {fine_tuned_model_path}\")\n",
476
+ " fine_tuned_model = SentenceTransformer(fine_tuned_model_path)\n",
477
+ " \n",
478
+ " # Initialize evaluator\n",
479
+ " llm = ChatOpenAI(model=\"gpt-4\", temperature=0)\n",
480
+ " \n",
481
+ " # Create a retrieval function using each model\n",
482
+ " def retrieve_with_model(model, query, k=1):\n",
483
+ " # Get embeddings for designs\n",
484
+ " design_texts = designs_df['text'].tolist()\n",
485
+ " design_embeddings = model.encode(design_texts, convert_to_tensor=True)\n",
486
+ " \n",
487
+ " # Get query embedding\n",
488
+ " query_embedding = model.encode(query, convert_to_tensor=True)\n",
489
+ " \n",
490
+ " # Calculate cosine similarities\n",
491
+ " cos_scores = torch.nn.functional.cosine_similarity(query_embedding.unsqueeze(0), design_embeddings)\n",
492
+ " \n",
493
+ " # Get top k designs\n",
494
+ " top_k_indices = torch.topk(cos_scores, k=k).indices.tolist()\n",
495
+ " \n",
496
+ " # Return top k designs\n",
497
+ " return [designs_df.iloc[i] for i in top_k_indices]\n",
498
+ " \n",
499
+ " # Evaluate a design match\n",
500
+ " async def evaluate_match(query, design):\n",
501
+ " prompt = f\"\"\"You are evaluating a design recommendation system.\n",
502
+ " \n",
503
+ " USER REQUIREMENTS:\n",
504
+ " {query}\n",
505
+ " \n",
506
+ " RECOMMENDED DESIGN:\n",
507
+ " {design['text']}\n",
508
+ " \n",
509
+ " Score how well the recommended design matches the user's requirements on a scale of 0-10.\n",
510
+ " Provide your score and brief explanation in JSON format exactly like this:\n",
511
+ " {{\n",
512
+ " \"score\": 7,\n",
513
+ " \"reason\": \"The design aligns with the requirements because...\"\n",
514
+ " }}\n",
515
+ " \n",
516
+ " Return only valid JSON, nothing else.\n",
517
+ " \"\"\"\n",
518
+ " \n",
519
+ " try:\n",
520
+ " response = await llm.ainvoke(prompt)\n",
521
+ " result = json.loads(response.content)\n",
522
+ " return result\n",
523
+ " except Exception as e:\n",
524
+ " print(f\"Error evaluating match: {e}\")\n",
525
+ " return {\"score\": 0, \"reason\": f\"Error parsing evaluation: {e}\"}\n",
526
+ " \n",
527
+ " # Test with both models\n",
528
+ " results = []\n",
529
+ " \n",
530
+ " # Define the evaluation function\n",
531
+ " async def evaluate_all_queries():\n",
532
+ " for i, query in enumerate(test_queries):\n",
533
+ " print(f\"Evaluating query {i+1}/{len(test_queries)}: {query[:50]}...\")\n",
534
+ " \n",
535
+ " # Get top result from each model\n",
536
+ " base_result = retrieve_with_model(base_model, query)[0]\n",
537
+ " fine_tuned_result = retrieve_with_model(fine_tuned_model, query)[0]\n",
538
+ " \n",
539
+ " # Evaluate matches\n",
540
+ " base_eval = await evaluate_match(query, base_result)\n",
541
+ " fine_tuned_eval = await evaluate_match(query, fine_tuned_result)\n",
542
+ " \n",
543
+ " # Store results\n",
544
+ " results.append({\n",
545
+ " \"query\": query,\n",
546
+ " \"base_model_id\": base_result['id'],\n",
547
+ " \"fine_tuned_model_id\": fine_tuned_result['id'],\n",
548
+ " \"base_score\": base_eval.get(\"score\", 0),\n",
549
+ " \"base_reason\": base_eval.get(\"reason\", \"Error\"),\n",
550
+ " \"fine_tuned_score\": fine_tuned_eval.get(\"score\", 0),\n",
551
+ " \"fine_tuned_reason\": fine_tuned_eval.get(\"reason\", \"Error\"),\n",
552
+ " \"models_differ\": base_result['id'] != fine_tuned_result['id']\n",
553
+ " })\n",
554
+ " \n",
555
+ " print(f\" Base model: Design {base_result['id']} - Score: {base_eval.get('score', 0)}\")\n",
556
+ " print(f\" Fine-tuned: Design {fine_tuned_result['id']} - Score: {fine_tuned_eval.get('score', 0)}\")\n",
557
+ " \n",
558
+ " # Run the async evaluation using the event loop\n",
559
+ " loop = asyncio.get_event_loop()\n",
560
+ " loop.run_until_complete(evaluate_all_queries())\n",
561
+ " \n",
562
+ " return pd.DataFrame(results)"
563
+ ]
564
+ },
565
+ {
566
+ "cell_type": "code",
567
+ "execution_count": 17,
568
+ "metadata": {},
569
+ "outputs": [
570
+ {
571
+ "name": "stdout",
572
+ "output_type": "stream",
573
+ "text": [
574
+ "Loading base model: sentence-transformers/distilbert-base-nli-stsb-mean-tokens\n",
575
+ "Loading fine-tuned model from: /Users/owner/Desktop/Projects/ai-maker-space/code/ImagineUI/src/fine_tuned_design_embeddings_20250225_161918\n",
576
+ "Evaluating query 1/8: I need a minimalist design with lots of whitespace...\n",
577
+ " Base model: Design 220 - Score: 8\n",
578
+ " Fine-tuned: Design 144 - Score: 9\n",
579
+ "Evaluating query 2/8: Looking for a playful, colorful design with rounde...\n",
580
+ " Base model: Design 129 - Score: 8\n",
581
+ " Fine-tuned: Design 129 - Score: 8\n",
582
+ "Evaluating query 3/8: Need a professional business design with a dark th...\n",
583
+ " Base model: Design 204 - Score: 8\n",
584
+ " Fine-tuned: Design 204 - Score: 8\n",
585
+ "Evaluating query 4/8: Want a nature-inspired design with organic shapes...\n",
586
+ " Base model: Design 190 - Score: 8\n",
587
+ " Fine-tuned: Design 215 - Score: 0\n",
588
+ "Evaluating query 5/8: Looking for a tech-focused design with a futuristi...\n",
589
+ " Base model: Design 012 - Score: 9\n",
590
+ " Fine-tuned: Design 012 - Score: 9\n",
591
+ "Evaluating query 6/8: I want the craziest design you can find...\n",
592
+ " Base model: Design 008 - Score: 8\n",
593
+ " Fine-tuned: Design 008 - Score: 8\n",
594
+ "Evaluating query 7/8: I'd like an eye-catching design for a small busine...\n",
595
+ " Base model: Design 006 - Score: 8\n",
596
+ " Fine-tuned: Design 006 - Score: 8\n",
597
+ "Evaluating query 8/8: I want something clinical and informative...\n",
598
+ " Base model: Design 130 - Score: 8\n",
599
+ " Fine-tuned: Design 004 - Score: 8\n"
600
+ ]
601
+ },
602
+ {
603
+ "data": {
604
+ "text/html": [
605
+ "<div>\n",
606
+ "<style scoped>\n",
607
+ " .dataframe tbody tr th:only-of-type {\n",
608
+ " vertical-align: middle;\n",
609
+ " }\n",
610
+ "\n",
611
+ " .dataframe tbody tr th {\n",
612
+ " vertical-align: top;\n",
613
+ " }\n",
614
+ "\n",
615
+ " .dataframe thead th {\n",
616
+ " text-align: right;\n",
617
+ " }\n",
618
+ "</style>\n",
619
+ "<table border=\"1\" class=\"dataframe\">\n",
620
+ " <thead>\n",
621
+ " <tr style=\"text-align: right;\">\n",
622
+ " <th></th>\n",
623
+ " <th>query</th>\n",
624
+ " <th>base_model_id</th>\n",
625
+ " <th>fine_tuned_model_id</th>\n",
626
+ " <th>base_score</th>\n",
627
+ " <th>base_reason</th>\n",
628
+ " <th>fine_tuned_score</th>\n",
629
+ " <th>fine_tuned_reason</th>\n",
630
+ " <th>models_differ</th>\n",
631
+ " </tr>\n",
632
+ " </thead>\n",
633
+ " <tbody>\n",
634
+ " <tr>\n",
635
+ " <th>0</th>\n",
636
+ " <td>I need a minimalist design with lots of whites...</td>\n",
637
+ " <td>220</td>\n",
638
+ " <td>144</td>\n",
639
+ " <td>8</td>\n",
640
+ " <td>The design aligns with the user's requirements...</td>\n",
641
+ " <td>9</td>\n",
642
+ " <td>The recommended design matches the user's requ...</td>\n",
643
+ " <td>True</td>\n",
644
+ " </tr>\n",
645
+ " <tr>\n",
646
+ " <th>1</th>\n",
647
+ " <td>Looking for a playful, colorful design with ro...</td>\n",
648
+ " <td>129</td>\n",
649
+ " <td>129</td>\n",
650
+ " <td>8</td>\n",
651
+ " <td>The design aligns with the user's requirements...</td>\n",
652
+ " <td>8</td>\n",
653
+ " <td>The design aligns with the user's requirements...</td>\n",
654
+ " <td>False</td>\n",
655
+ " </tr>\n",
656
+ " <tr>\n",
657
+ " <th>2</th>\n",
658
+ " <td>Need a professional business design with a dar...</td>\n",
659
+ " <td>204</td>\n",
660
+ " <td>204</td>\n",
661
+ " <td>8</td>\n",
662
+ " <td>The design aligns with the user's requirements...</td>\n",
663
+ " <td>8</td>\n",
664
+ " <td>The design aligns with the user's requirements...</td>\n",
665
+ " <td>False</td>\n",
666
+ " </tr>\n",
667
+ " <tr>\n",
668
+ " <th>3</th>\n",
669
+ " <td>Want a nature-inspired design with organic shapes</td>\n",
670
+ " <td>190</td>\n",
671
+ " <td>215</td>\n",
672
+ " <td>8</td>\n",
673
+ " <td>The design aligns with the user's requirements...</td>\n",
674
+ " <td>0</td>\n",
675
+ " <td>The recommended design does not match the user...</td>\n",
676
+ " <td>True</td>\n",
677
+ " </tr>\n",
678
+ " <tr>\n",
679
+ " <th>4</th>\n",
680
+ " <td>Looking for a tech-focused design with a futur...</td>\n",
681
+ " <td>012</td>\n",
682
+ " <td>012</td>\n",
683
+ " <td>9</td>\n",
684
+ " <td>The recommended design aligns very well with t...</td>\n",
685
+ " <td>9</td>\n",
686
+ " <td>The recommended design aligns very well with t...</td>\n",
687
+ " <td>False</td>\n",
688
+ " </tr>\n",
689
+ " <tr>\n",
690
+ " <th>5</th>\n",
691
+ " <td>I want the craziest design you can find</td>\n",
692
+ " <td>008</td>\n",
693
+ " <td>008</td>\n",
694
+ " <td>8</td>\n",
695
+ " <td>The design aligns with the user's requirements...</td>\n",
696
+ " <td>8</td>\n",
697
+ " <td>The recommended design matches the user's requ...</td>\n",
698
+ " <td>False</td>\n",
699
+ " </tr>\n",
700
+ " <tr>\n",
701
+ " <th>6</th>\n",
702
+ " <td>I'd like an eye-catching design for a small bu...</td>\n",
703
+ " <td>006</td>\n",
704
+ " <td>006</td>\n",
705
+ " <td>8</td>\n",
706
+ " <td>The recommended design matches the user's requ...</td>\n",
707
+ " <td>8</td>\n",
708
+ " <td>The recommended design matches the user's requ...</td>\n",
709
+ " <td>False</td>\n",
710
+ " </tr>\n",
711
+ " <tr>\n",
712
+ " <th>7</th>\n",
713
+ " <td>I want something clinical and informative</td>\n",
714
+ " <td>130</td>\n",
715
+ " <td>004</td>\n",
716
+ " <td>8</td>\n",
717
+ " <td>The recommended design matches the user's requ...</td>\n",
718
+ " <td>8</td>\n",
719
+ " <td>The design aligns with the user's requirements...</td>\n",
720
+ " <td>True</td>\n",
721
+ " </tr>\n",
722
+ " </tbody>\n",
723
+ "</table>\n",
724
+ "</div>"
725
+ ],
726
+ "text/plain": [
727
+ " query base_model_id \\\n",
728
+ "0 I need a minimalist design with lots of whites... 220 \n",
729
+ "1 Looking for a playful, colorful design with ro... 129 \n",
730
+ "2 Need a professional business design with a dar... 204 \n",
731
+ "3 Want a nature-inspired design with organic shapes 190 \n",
732
+ "4 Looking for a tech-focused design with a futur... 012 \n",
733
+ "5 I want the craziest design you can find 008 \n",
734
+ "6 I'd like an eye-catching design for a small bu... 006 \n",
735
+ "7 I want something clinical and informative 130 \n",
736
+ "\n",
737
+ " fine_tuned_model_id base_score \\\n",
738
+ "0 144 8 \n",
739
+ "1 129 8 \n",
740
+ "2 204 8 \n",
741
+ "3 215 8 \n",
742
+ "4 012 9 \n",
743
+ "5 008 8 \n",
744
+ "6 006 8 \n",
745
+ "7 004 8 \n",
746
+ "\n",
747
+ " base_reason fine_tuned_score \\\n",
748
+ "0 The design aligns with the user's requirements... 9 \n",
749
+ "1 The design aligns with the user's requirements... 8 \n",
750
+ "2 The design aligns with the user's requirements... 8 \n",
751
+ "3 The design aligns with the user's requirements... 0 \n",
752
+ "4 The recommended design aligns very well with t... 9 \n",
753
+ "5 The design aligns with the user's requirements... 8 \n",
754
+ "6 The recommended design matches the user's requ... 8 \n",
755
+ "7 The recommended design matches the user's requ... 8 \n",
756
+ "\n",
757
+ " fine_tuned_reason models_differ \n",
758
+ "0 The recommended design matches the user's requ... True \n",
759
+ "1 The design aligns with the user's requirements... False \n",
760
+ "2 The design aligns with the user's requirements... False \n",
761
+ "3 The recommended design does not match the user... True \n",
762
+ "4 The recommended design aligns very well with t... False \n",
763
+ "5 The recommended design matches the user's requ... False \n",
764
+ "6 The recommended design matches the user's requ... False \n",
765
+ "7 The design aligns with the user's requirements... True "
766
+ ]
767
+ },
768
+ "execution_count": 17,
769
+ "metadata": {},
770
+ "output_type": "execute_result"
771
+ }
772
+ ],
773
+ "source": [
774
+ "\n",
775
+ "test_queries = [\n",
776
+ " \"I need a minimalist design with lots of whitespace\",\n",
777
+ " \"Looking for a playful, colorful design with rounded elements\",\n",
778
+ " \"Need a professional business design with a dark theme\",\n",
779
+ " \"Want a nature-inspired design with organic shapes\",\n",
780
+ " \"Looking for a tech-focused design with a futuristic feel\",\n",
781
+ " \"I want the craziest design you can find\",\n",
782
+ " \"I'd like an eye-catching design for a small business\",\n",
783
+ " \"I want something clinical and informative\"\n",
784
+ "]\n",
785
+ "\n",
786
+ "comparison_results = compare_models_sync(\"sentence-transformers/distilbert-base-nli-stsb-mean-tokens\", model_path, test_queries)\n",
787
+ "comparison_results"
788
+ ]
789
+ },
790
+ {
791
+ "cell_type": "markdown",
792
+ "metadata": {},
793
+ "source": [
794
+ "Using this, we can verify the returned design of each model and query. A standout element is the \"0\" scored by the fine-tuned model for query #3. Checking the returned design, it's definitely not the nature-inspired design we were looking for. The model without fine-tuning hasn't missed a query that badly, so it's unclear why the training moved in the wrong direction."
795
+ ]
796
+ },
797
+ {
798
+ "cell_type": "markdown",
799
+ "metadata": {},
800
+ "source": [
801
+ "## 5. Visualize Comparison Results"
802
+ ]
803
+ },
804
+ {
805
+ "cell_type": "code",
806
+ "execution_count": 18,
807
+ "metadata": {},
808
+ "outputs": [
809
+ {
810
+ "data": {
811
+ "image/png": "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166lN998s2bd+PHj8/rzzz+/Zt1+++1XWnjhhUuffvppndfvvvvupd69ezc4x/XdcMMNeZ8PPPBAg+difaStvsUWW6wm7bU/98033zyfz7Ijjzyy1KlTp9J//vOf/PiLL74ozTvvvKX999+/zv4mTJiQ01p7/SqrrJKPq/zacM899+T3ifdvyjlffvnl8/9XX331fJ7C559/ns/ruHHj8jHH/uIclA0dOjQ//9Zbb9Ws++CDD0o9e/YsbbjhhjXrjjjiiPzaJ554ombdxx9/nI8j1r/zzjvNPubGvgeNiXM/99xz599ELPEdOfXUU0sdOnQorbTSSs3+TcTj2Pbll19u8F5xrrfddts6684555z8mquvvrrOb3edddYpzTPPPKVJkybldXEOYrtevXrlc1Nb+VgPOOCAmnXffvttadFFF83Hcdppp9Wsj8+se/fudb5zse2UKVPq7DO2W3DBBUv77rtvzbpyGvr06VP67LPPatbfeuutef2f/vSnmnXx+cbn/I9//KPOfmt/p7/r7w2YvfuI8rWx/JuO7cri2hDrTj755Dr7WnXVVUtDhgypeRzXw9ju97//fZ3t7rrrrkbXNyauvbWvRbXT0FjeNCfy9/I1Oe5byr766qvSUkstNcP8vbFzHvc3v/71r/N1sLzvH/zgB6VNNtmk0fzglltuya/7+c9/Xmd///M//5Ov4+Xje/755/N2Bx10UJ3t9thjjwb3GU095sa+B41pLJ//rvlPeZ9x71jO72rfN5577rkN7v8i752dfPTuu+9ukFeFbbbZprTkkkvWPG5unh/35eX7lHDRRRfl9QsttFCdYzr++OPr3NNEfrj00kuXttxyyzp5Y3wuSyyxROn73/9+g/NcO08OO+20U86Tm/K7onI0L68SUXMczZNiiZLNqBGMUqz6tcK1SwKjRC1KU6OmKUrCyqJGOdx6660zbLobpYNRqrfsssvmkvHyUq7ZrN/ktLYopYwa7j//+c+5Nr4samcXWWSRmgFFyumIWvho8tNcUYJcPiflJUoUZyZKTGuX9kVtf9TARu1ciGtn9Enefvvt8/9rH3uU+Mf5rH0uixYllLWb0cVnGbUP//jHP/LjOOYowY3aydppjZYEUTtR/pw+/PDDXFIctcPRFKns+9///mz1L46S9fjulZvJxftF6XF9kdaoYY8meksuuWTN+qj1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9tknLbvssunvf/97neduuOGGtOuuu6bFFlssvfvuuxVLIwBANVHTDVAhW221Vfrwww/zcv/996fOnTun7bbbrtLJSnPPPXcebfvxxx+vs/53v/tdGjhwYMXSBQBQjQTdABXSrVu3tNBCC+VllVVWSSNHjkzvv/9++uSTT2q2Oe6449L3vve9PAL2kksumUaNGlVnFOzx48enTTbZJPXs2TP16tUrDRkyJD399NM1zz/66KNpgw02yFNXDRgwIB122GHpq6++mmm6IvjfY4890mWXXVaz7p///Gd68MEH8/r6LrjggjRo0KDUtWvXtMwyy6SrrrqqzvNvvPFG2nDDDdNcc82VBg8enO69994G+4jjjlr0eeedN9f677jjjmrTAYA2QdAN0Ap8+eWX6eqrr05LLbVUnTnHI5iOJt+vvPJKOvfcc9Mll1ySzj777Jrn99xzz7Toooump556Kj3zzDM5cO/SpUt+7q233sq16bvsskt64YUX0nXXXZeD8EMOOWSW6dl3333T9ddfnyZPnpwfRxpiXwsuuGCd7W6++eZ0+OGHp6OOOiq99NJL6Sc/+Ulunv7AAw/k56dPn5523nnnHJA/8cQT6cILL8wFCbVFIcKWW26Zj/WRRx5Jjz32WJpnnnny+02dOvU7nlkAgMrSpxugQm6//fYcXIaofV544YXzuo4d/1956Iknnljz/8UXXzwdffTR6dprr03HHntsXvfee++lY445JvfBDksvvXTN9mPHjs1B+RFHHFHz3HnnnZc22mijXDsdNc8zsuqqq+aa9T/+8Y9pr732ykH3WWedld5+++0625155pm5f/pBBx2UH48YMSL97W9/y+ujBv6+++5Lr776arr77rtT//798zannnpq2nrrrWv2EYUBEZxfeumlNdNrXX755bnWO2rXt9hii+90ngEAKklNN0CFRFD6/PPP5+XJJ5/Mtb0RjP7jH/+oE5Cut956uQl6BOgRhEegXRZB7o9//OO0+eabp9NOOy3Xbtdueh7BcryuvMR7RID7zjvvNKm2O4Lfhx56KBcKbLPNNg22icHWIn21xePyIGzxN5q1lwPusM4669TZPtL55ptv5prucjqjifl///vfOscDAFCNBN0AFRywLJqTxxIjl0dNbwS30YQ8xEBmUVMdwW7UgD/33HPphBNOqNPkesyYMenll19O2267bfrLX/6S+0xHk+9yk/Vo7l0O7GOJADf6WEcf7FmJ945a63iPqO2Ovt5FiHRGX/Ta6Yzl9ddfb7QPOQBANdG8HKCViKbV0bT866+/zo//+te/5um5ItAuq10LXhYDrcVy5JFHph/+8Ie5dnqnnXZKq622Wu4LHkH97Ija5h122CH37Y6+2I1Zbrnlch/sYcOG1ayLxxH8l5+PQdJihPZoPh8ikK8t0hk1+v369cuDwQEAtCVqugEqZMqUKWnChAl5iWbYhx56aK713X777Wv6YEdT8ujDHc2soz92uRY7RHAeg6JFv+cIxiPYjQHVItANMWBZBO6xTdQcRw33rbfe2qSB1Mqiefqnn35a02e8vuhPHttEH/HYf/T7vummm3Lf8xDN3qNAIILyqGWPgdJqFyKUa9T79u2bRyyP56PpexxTjLQeo6YDAFQzNd0AFXLXXXfV1P5Gf+YIbG+44Ya08cYb53VRyxy11xEkR4AeTchjyrBo7h06deqU/v3vf6e99947ffTRRzlwjZHCTzrppPz8SiutlPtjR5Ab04aVSqXcrHy33XZrchpjqrFYZmTo0KF5VPUYOC1GMV9iiSVyTXv5GKLmPgoK9ttvv7TmmmvmweCi8CBGJi+L6dAefvjhXEgQ6f/iiy/SIosskjbbbDM13zRbh5P+bzC+1qw0ulTpJAAwB3UoxV1YlZo0aVLq3bt3mjhxYuu7MRvTu4X2M7Fl9gMFWXzkHS2yn3fnan7f3f/OMyC9s96v0hKLLJDm6twhpf6rtkhaoCXFgHBRex8FEvVHjG/V+dgcUMTxC7oBaG35mOblAAAAUBBBNwAAABRE0A0AAAAFEXQDAABAQQTdAAAAUBBBNwAAABRE0A0AAAAFEXQDAABAQQTdAAAAUBBBN0Ars/HGG6cjjjgitTcPPvhg6tChQ/rPf/5T0XSMGTMmrbLKKk3e/t13383pfv755wtNFwBQnTpXOgEAhRjTew6/38RmbT58+PA0bty4BuvfeOONdNNNN6UuXbqkORHcR3B5zjnnpGqx+OKLp3/84x/pmmuuSbvvvnud55Zffvn0yiuvpMsvvzyfXwCA1kBNN0CFbLXVVunDDz+ssyyxxBJp/vnnTz179qx08lqtAQMG5MC6tr/97W9pwoQJae65565YugAAGiPoBqiQbt26pYUWWqjO0qlTpwbNy6N299RTT0377rtvDsYHDhyYLr744jr7ev/999Ouu+6a5p133hy077jjjrnZ84xETfBDDz2Uzj333Nw0OpbY/oorrsj7qO2WW27Jz9dvfn3VVVfltPXu3TvXOn/xxRc120yfPj2NHTs2FyJ07949rbzyyumPf/xjnf3++c9/Tt/73vfy85tssslM01vbnnvumdMex1x22WWX5fWdO9dtwPXee+/lczHPPPOkXr165XP00Ucf1dnmtNNOSwsuuGA+t/vtt1/673//2+A9L7300rTccsulueaaKy277LLpt7/9bZPSCgAg6AaoAr/61a/S6quvnp577rl00EEHpf/93/9Nr732Wn7um2++SVtuuWUOGh955JH02GOP5SAzatKnTp3a6P4i2F5nnXXS/vvvX1PLHjXITfXWW2/lYPz222/PSwTBEbyWRcB95ZVXpgsvvDC9/PLL6cgjj0w/+tGP8nYhAuadd945bb/99rkv9I9//OM0cuTIJr13BMhxvOXm+ZMnT07XXXddLpSoLQL/CLg/++yz/L733ntvevvtt9Nuu+1Ws83111+fCxGiUOPpp59OCy+8cIOA+ve//3362c9+ln7xi1+kv//973nbUaNGNdo9AACgPn26ASokgtUIjsu23nrrdMMNNzS67TbbbJOD7XDcccels88+Oz3wwANpmWWWyQFnBJhRG1uukY7m11FjHYOTbbHFFg32F7XTXbt2TT169Mg17M0V7xe14uVm8HvttVe6//77c2A6ZcqUHJjed999ObAPSy65ZHr00UfTRRddlDbaaKN0wQUXpEGDBuXChBDH8eKLL6bTTz+9Se8fAfZRRx2VTjjhhFyDHvuqP/hZpCf2+c4779QUKERBQPT9fuqpp9Iaa6yR+7NH7XYs4ec//3lOd+3a7tGjR+d0RiFBiNr76DsexzJs2LBmnzsAoH1R0w1QIdGkOmp5y8t55503w21XWmmlmv9HYB2B8scff5wfjx8/Pr355ps5AI4gPpZoYh6BY9RIR+13eX0sUXP7XUWz8tr9zqOGuJyeSEvUPn//+9+v874R8EZ6QtQYr7XWWnX2WQ7Qm2LbbbdNX375ZXr44Ydz0/L6tdzl94hgu3YN/uDBg3NhRDzXlHR89dVXOc0RlNc+lgjOy8cCADAzaroBKiQG/VpqqaWatG390cwj8I7a5hDB55AhQxoNphdYYIFco117Oqtonj0jHTt2TKVSqc66aL7e3PSEO+64Iy2yyCIN+rG3hOi7HbXrUQv9xBNPpJtvvjkVoXwsl1xySYPgPPrfAwDMiqAboMqtttpquYl5v3798mBhjWksuI9gfNq0aQ2C9BgQLWp4yyOBN3f+6ahNjuA6BjGLpuSNiUHJbrvttgYjkDdH1G6feeaZuY/2fPPN1+h7RN/xWMq13dEsPOYBjzSWt4mgfe+99240HVFA0b9//9wXPAZqAwBoLkE3QJWLYPCMM87Ig4adfPLJadFFF81zWcd838cee2x+PKMm4hFwxqjh5SbpUZsb/bx/+tOfpsMOOyw/H323myOanR999NF58LSo/V5//fXTxIkT8wBvUSgQ/aAPPPDA3E/6mGOOyYOoPfPMM81+nwiYP/3005zexmy++eZpxRVXzOcn+m5/++23uV98FATEoHTh8MMPzyO5x+P11lsvtxaIgd+iD3rZSSedlM9F9IOPwemiz3oMuvb555+nESNGNCvNAED7o083QJWLoDP6NsdUYjHYVwSj5amvZlTzHSIwjibSUesbNdxRMx2B99VXX52n84qA9ZprrsmjezfXKaeckkf4jlHMIz0RrEZz8xiELERab7zxxjwCekwnFqOcx+BrzdWnT5885Vhjosn7rbfemmvBN9xwwxyERzAdrQLKopY80hmFE9FEPworYmT42qJQIAapi8Hp4pxE0B4FBOVjAQCYmQ6l+p33qsikSZNyzUPUoMzsxrIixvRuof1MbJn9QEEWH3lHi+zn3bn2aPZr/jvPgPTOer9KSyyyQJqrc4eU+q/aImmBlhSFHzGCegTpMc931eRjc0ARx9/hpP83p3xrVRpdtbdeAMxGPqamGwAAAAoi6AYAAICCCLoBAACgIIJuAAAAKIigGwAAAAoi6AaqV2l6/JOmGwiYVizmKgcA2q/OlU4AwOzqOvmj1PHrz9IHn/dKC/SeK3X9+us8NzO0BjEj59SpU9Mnn3ySOnbsmLp27VrpJAEAFSDoBqpWx9K3aYknR6UPl903fbDAKin9t3ulkwQN9OjRIw0cODAH3gBA+yPoBqpa1/9+mgY+f0b6tmuvNG3E65VODtTRqVOn1LlzZy0wAKAdE3QDVa9DKqUuUyemLnPNVemkAABAHdq6AQAAQEEE3QAAAFAQQTcAAAAURNANAAAABRF0AwAAQEEE3QAAAFAQQTcAAAAURNANAAAABRF0AwAAQEEE3QAAAFAQQTcAAAAURNANAAAABRF0AwAAQEEE3QAAAFAQQTcA8J385je/SYsvvniaa6650lprrZWefPLJSicJAFoNQTcAMNuuu+66NGLEiDR69Oj07LPPppVXXjltueWW6eOPP6500gCgVehc6QQAANXrrLPOSvvvv3/aZ5998uMLL7ww3XHHHemyyy5LI0eObNI+pk2blpcWMT21ei12rABUxfW8c6UTOWbMmHT11VenCRMmpP79+6fhw4enE088MXXo0KGSSQMAZmHq1KnpmWeeSccff3zNuo4dO6bNN988Pf744w22nzJlSl7KJk2alP/ec889qUePHi2TqDdSq/fnP/+50kkAoAVMnjy59Qfdp59+errgggvSuHHj0vLLL5+efvrpXFLeu3fvdNhhh1UyaQDALHz66ae5AH3BBRessz4ev/rqqw22Hzt2bDrppJMKTdNtP7yt0P3Tzu2wQ2rVbvP9h9aookH3X//617TjjjumbbfdNj+OQViuueYaA7AAQBsUNeLR/7t2TfeAAQPSFltskXr16lXRtEGbsM02lU4BtCuT/v8WW6066F533XXTxRdfnF5//fX0ve99L40fPz49+uijuX8YANC69e3bN3Xq1Cl99NFHddbH44UWWqjB9t26dctLfbGPWIDvyO8I5qim5l0VDbpjgJUoHVh22WVzgqOJ2i9+8Yu05557Nrr9jPqCAQBzXteuXdOQIUPS/fffn4YOHZrXTZ8+PT8+5JBDKp08AGgVKhp0X3/99en3v/99+sMf/pD7dD///PPpiCOOyAOqDRs2rCJ9wRYfeUeL7OfduVLFtdyx7NEi+0ljJs72Sx1LQ++e9n/dMmg5vmcNOZaWPZa2KJqLR569+uqrpzXXXDOdc8456auvvqoZzRwA2ruKBt3HHHNMru3efffd8+MVV1wx/eMf/8jBdWNB94z6ggEAlbHbbrulTz75JP3sZz/LM5Gsssoq6a677mowuBoAtFedKz3EekwtUls0M4+maY2ZUV8wAKByoim55uQA0AqD7u233z734R44cGBuXv7cc8/lQdT23XffSiYLAAAAqj/oPv/889OoUaPSQQcdlD7++OPcl/snP/lJbqIGAAAA1a6iQXfPnj3zgCuxAAAAQFtTt0M1AAAA0GIE3QAAAFAQQTcAAAAURNANAAAABRF0AwAAQEEE3QAAAFAQQTcAAAAURNANAAAABRF0AwAAQEEE3QAAAFAQQTcAAAAURNANAAAABRF0AwAAQEEE3QAAAFAQQTcAAAAURNANAAAABRF0AwAAQEEE3QAAAFAQQTcAAAAURNANAAAABRF0AwAAQEEE3QAAAFAQQTcAAAAURNANAAAABRF0AwAAQEEE3QAAAFAQQTcAAAAURNANAAAABRF0AwAAQEEE3QAAAFAQQTcAAAAURNANAAAABRF0AwAAQEEE3QAAAFAQQTcAAAAURNANAAAABRF0AwAAQEEE3QAAAFAQQTcAAAAURNANAAAABRF0AwAAQEEE3QAAAFAQQTcAAAAURNANAAAABRF0AwAAQEEE3QAAAFAQQTcAAAAURNANAAAABRF0AwAAQEEE3QAAAFAQQTcAAAAURNANAAAABRF0AwAAQEEE3QAAAFAQQTcAAAAURNANAAAABRF0AwAAQEEE3QAAAFAQQTcAAAAURNANAAAABRF0AwAAQEEE3QAAAFAQQTcAAAAURNANAAAABRF0AwAAQEEE3QAAAFAQQTcAAAAURNANAAAABRF0AwAAQEEE3QAAAFAQQTcAAAAURNANAAAABRF0AwAAQEEE3QAAAFAQQTcAAAAURNANAAAABRF0AwAAQEEE3QAAAFAQQTcAAAAURNANAAAABRF0AwAAQEEE3QAAAFAQQTcAAAAURNANAAAABRF0AwAAQEEE3QAAAFAQQTcAAAAURNANAAAABRF0AwDN9u6776b99tsvLbHEEql79+5p0KBBafTo0Wnq1KmVThoAtCqdK50AAKD6vPrqq2n69OnpoosuSksttVR66aWX0v7775+++uqrdOaZZ1Y6eQDQagi6AYBm22qrrfJStuSSS6bXXnstXXDBBYJuAKhF0A0AtIiJEyem+eeff4bPT5kyJS9lkyZNmkMpA4DK0acbAPjO3nzzzXT++eenn/zkJzPcZuzYsal37941y4ABA+ZoGgGgEgTdAECNkSNHpg4dOsx0if7ctf3rX//KTc1/8IMf5H7dM3L88cfn2vDy8v7778+BIwKAytK8HACocdRRR6Xhw4fPdJvov132wQcfpE022SStu+666eKLL57p67p165YXAGhPBN0AQI0FFlggL00RNdwRcA8ZMiRdfvnlqWNHDegAoL6K546RYf/oRz9Kffr0yfN8rrjiiunpp5+udLIAgFnk3xtvvHEaOHBgHq38k08+SRMmTMgLANBKaro///zztN566+VS8jvvvDOXrL/xxhtpvvnmq2SyAIBZuPfee/PgabEsuuiidZ4rlUoVSxcAtDYVDbpPP/30PHJpNEkrW2KJJSqZJACgCaLf96z6fgMAFW5eftttt6XVV189j3bar1+/tOqqq6ZLLrlkhtvH3J4xp2ftBQAAAFqrigbdb7/9drrgggvS0ksvne6+++70v//7v+mwww5L48aNa3R783sCAABQTSoadE+fPj2tttpq6dRTT8213AcccECe3/PCCy9sdHvzewJAQw8//HD69ttvG6yPdfEcANBOg+6FF144DR48uM665ZZbLr333nuNbh9ze/bq1avOAgDtXQxI+tlnnzVYHwXU8RwA0E6D7hi5/LXXXquz7vXXX0+LLbZYxdIEANUmRgvv0KFDg/X//ve/09xzz12RNAEArWD08iOPPDKtu+66uXn5rrvump588sl08cUX5wUAmLmdd945/42AO0YSjxZhZdOmTUsvvPBCzmcBgHYadK+xxhrp5ptvzn21Tz755Dxd2DnnnJP23HPPSiYLAKpCDCparunu2bNn6t69e81zXbt2TWuvvXYeKwUAaKdBd9huu+3yAgA0z+WXX57/Lr744unoo4/WlBwAWqGKB90AwHczevToSicBAGiNA6kBAN/dRx99lPbaa6/Uv3//1Llz59SpU6c6CwBQOWq6AaDKxSBqMd3mqFGj8nScjY1kDgBUhqAbAKrco48+mh555JG0yiqrVDopAEA9mpcDQJUbMGBAHsEcAGh9BN0AUOVius2RI0emd999t9JJAQDq0bwcAKrcbrvtliZPnpwGDRqUevTokbp06VLn+c8++6xiaQOA9k7QDQBtoKYbAGidBN0AUOWGDRtW6SQAADOgTzcAtAFvvfVWOvHEE9MPf/jD9PHHH+d1d955Z3r55ZcrnTQAaNcE3QBQ5R566KG04oorpieeeCLddNNN6csvv8zrx48fn0aPHl3p5AFAuyboBoAqFyOX//znP0/33ntv6tq1a836TTfdNP3tb3+raNoAoL0TdANAlXvxxRfTTjvt1GB9v3790qefflqRNAEA/0fQDQBVbt55500ffvhhg/XPPfdcWmSRRSqSJgDg/wi6AaDK7b777um4445LEyZMSB06dEjTp09Pjz32WDr66KPT3nvvXenkAUC7JugGgCp36qmnpmWXXTYNGDAgD6I2ePDgtOGGG6Z11103j2gOAFSOeboBoMrF4GmXXHJJGjVqVHrppZdy4L3qqqumpZdeutJJA4B2T9ANAG3EwIED8wIAtB6CbgCocqVSKf3xj39MDzzwQPr4449zn+7aYu5uAKAyBN0AUOWOOOKIdNFFF6VNNtkkLbjggnkwNQCgioPub775Jo+QOnny5LTAAguk+eefv+VTBgA0yVVXXZVrs7fZZptKJwUAmN3Ry7/44ot0wQUXpI022ij16tUrLb744mm55ZbLQfdiiy2W9t9///TUU081dXcAQAvp3bt3WnLJJSudDABgdoPus846KwfZl19+edp8883TLbfckp5//vn0+uuvp8cffzyNHj06ffvtt2mLLbZIW221VXrjjTeaslsAoAWMGTMmnXTSSenrr7+udFIAgNlpXh412A8//HBafvnlG31+zTXXTPvuu2+68MILc2D+yCOPmKYEAOaQXXfdNV1zzTWpX79+uZC8S5cudZ5/9tlnK5Y2AGjvmhR0R0beFN26dUsHHnjgd00TANAMw4YNS88880z60Y9+ZCA1AGgro5dPmTKlJtAGACrnjjvuSHfffXdaf/31K50UAGB2B1IL9957bx4Zdb755ks9evTIS/w/1t13333N2RUA0EIGDBiQBzkFAKo46B43blwOrmOE1LPPPjvdfvvteYn/zzvvvPm5mLIEAJizfvWrX6Vjjz02vfvuu5VOCgAwu83Lf/GLX6RzzjknHXzwwQ2eGz58eG7SdvLJJ6e99tqrqbsEAFpA9OWePHlyGjRoUG6FVn8gtc8++6xiaQOA9q7JQfd7772Xpwubkc022ywdddRRLZUuAKCJolAcAKjyoDumC/vd736XfvnLXzb6/GWXXZYGDx7ckmkDAJo4ejkAUOVBd/QX22677dJdd92Va7xjSpLw0Ucfpfvvvz+9/fbbefRUAGDOe+utt9Lll1+e/5577rl5zu4777wzDRw4MBecAwCtfCC1jTfeOL300ktp6623znOBRs12LPH/WPfiiy+mDTfcsNjUAgANPPTQQ2nFFVdMTzzxRLrpppvSl19+mdePHz8+jR49utLJA4B2rVnzdC+++OLp9NNPLy41AECzjRw5Mv385z9PI0aMSD179qxZv+mmm6Zf//rXFU0bALR3zZqnGwBofaK12U477dRgfTQx//TTTyuSJgCghYPuaMLWqVOnltodANBE8847b/rwww8brH/uuefSIossUpE0AQAF1HSXSqWW3B0A0AS77757Ou6449KECRNShw4d0vTp09Njjz2Wjj766LT33ntXOnkA0K41uU/3zjvvPNPnJ06cmDN6AGDOOvXUU9PBBx+cBgwYkKZNm5an8Iy/e+yxRzrxxBMrnTwAaNeaHHT/6U9/St///vdrpgqrLzJ3AGDO69q1a7rkkkvSqFGj8kwjMXr5qquumpZeeulKJw0A2r0mB93LLbdc2mWXXdJ+++3X6PPPP/98uv3221sybQBAEzz66KNp/fXXz3NyxwIAVGGf7iFDhqRnn312hs9369ZNRg8AFRBTgy2xxBLppz/9aXrllVcqnRwAYHaC7gsvvDCdccYZM60Jf+edd5q6OwCghXzwwQfpqKOOSg899FBaYYUV0iqrrJLz7H/+85+VThoAtHtNDrqjJrtHjx7FpgYAaLa+ffumQw45JI9Y/tZbb6Uf/OAHady4cWnxxRfPteAAQJVOGbbttts2Oi8oAFAZ0cx85MiR6bTTTksrrrhirv0GAKo06H744YfT119/3XKpAQBmW9R0H3TQQWnhhRfO04VFU/M77rij0skCgHatyaOXAwCt0/HHH5+uvfba3Lc7pvc899xz04477qhbGABUe9C92GKLpS5durRcagCA2Wp5dswxx6Rdd9019+8GANpI0P3SSy+1XEoAgNluVg4AtJGg+8knn0yPP/54mjBhQn680EILpXXWWSetueaaRaQPAGiCGLX8nHPOSX//+9/z48GDB6fDDz88DRo0qNJJA4B2rclB98cff5x22WWXXJo+cODAtOCCC+b1H330UTryyCPTeuutl2688cbUr1+/ItMLANRz9913px122CHPzx35cYj8evnll09/+tOfcj9vAKCVB90xGuq0adNyCfoyyyxT57nXXnst7bvvvunggw9ON9xwQxHpBABmIKYIiwLwmCas/vrjjjtO0A0A1TBlWJSi/+Y3v2kQcIdYd95556W77rqrpdMHAMxCFIjvt99+DdZHgfgrr7xSkTQBAM0Murt165YmTZo0w+e/+OKLvA0AMGctsMAC6fnnn2+wPtbp9gUAVdK8fLfddkvDhg1LZ599dtpss81Sr1698voIxO+///40YsSI9MMf/rDItAIAjdh///3TAQcckN5+++207rrr1vTpPv3003P+DABUQdB91llnpenTp6fdd989ffvtt6lr1655/dSpU1Pnzp1zs7YzzzyzyLQCAI0YNWpU6tmzZ/rVr36Vjj/++Lyuf//+acyYMemwww6rdPIAoF1rctAdTccvuOCCXGr+zDPP1JkybMiQITU13wDAnBMF4X/4wx/SHnvskQdTi+5eIYJwAKAK5+mO4HqTTTYpJjUAQLNEa7MDDzywZn5uwTYAVOFAatdee22Td/j+++/nfmQAwJyx5pprpueee67SyQAAZjfojmblyy23XPrlL39ZU5Je28SJE9Of//zn3LRttdVWS//+97+bslsAoAUcdNBB6aijjkq//vWv0+OPP55eeOGFOgsA0Mqblz/00EPptttuS+eff34eoGXuuedOCy64YJprrrnS559/nvt39+3bNw0fPjy99NJL+TkAYM6IQU5D7UHTOnTokEqlUv47bdq0CqYOANq3Jvfp3mGHHfLy6aefpkcffTT94x//SF9//XUOtlddddW8dOzY5Gm/AYAW8s4771Q6CQBASw2kFkH20KFDm/syAKAgiy22WKWTAAC0VNANALQ+r732Wu4GVh57JcZiOfTQQ9MyyyxT6aQBQLumPTgAVLkbb7wxrbDCCumZZ55JK6+8cl6effbZvC6eAwAqR003AFS5Y489Ng90evLJJ9dZP3r06PzcLrvsUrG0AUB7p6YbAKrchx9+mPbee+8G63/0ox/l5wCAKgy6p06dmvuPffvtty2bIgCgWTbeeOP0yCOPNFgfs41ssMEGFUkTADCbzcsnT56cB2YZN25cfvz666+nJZdcMq9bZJFF0siRI5u7SwDgO4gpPY877rjcp3vttdfO6/72t7+lG264IZ100knptttuq7MtANCKg+7oMzZ+/Pj04IMPpq222qpm/eabb57GjBkj6AaAOeyggw7Kf3/729/mpbHnQocOHdK0adPmePoAoD1rdtB9yy23pOuuuy6XpEfmXbb88sunt956q6XTBwDMwvTp0yudBACgpfp0f/LJJ6lfv34N1n/11Vd1gnAAAABo75pd07366qunO+64I/fhDuVA+9JLL03rrLNOy6cQAJilp556Kj3wwAPp448/blDzfdZZZ1UsXQDQ3jU76D711FPT1ltvnV555ZU8cvm5556b///Xv/41PfTQQ8WkEgCYad584oknpmWWWSYtuOCCdVqeaYUGAFUWdK+//vp5ILWxY8emFVdcMd1zzz1ptdVWS48//nh+DADMWVEAftlll6Xhw4dXOikAwHcJur/55pv0k5/8JI0aNSpdcsklzXkpAFCQjh07pvXWW6/SyQAAvutAal26dEk33nhjc14CABTsyCOPTL/5zW8qnQwAoCWalw8dOjRPGxYZPABQeUcffXTadttt06BBg9LgwYNzIXltN910U8XSBgDtXbOD7qWXXjqdfPLJ6bHHHktDhgxJc889d53nDzvssJZMHwAwC5H3xsjlm2yySerTp4/B0wCgmoPu3/3ud2neeedNzzzzTF5qi0xe0A0Ac9a4ceNy96+o7QYAqjzofuedd4pJCQAwW+aff/7ctBwAqPKB1OorlUp5AQAqZ8yYMWn06NFp8uTJlU4KANASQfeVV16Z5+Tu3r17XlZaaaV01VVXzc6uAIDv6Lzzzkt33nlnWnDBBXP+vNpqq9VZAIAqal5+1lln5Xm6DznkkJo5QR999NF04IEHpk8//dSo5gAwh8XMIgBAGwm6zz///HTBBRekvffeu2bdDjvskJZffvncvE3QDQBzVjQtr6QpU6aktdZaK40fPz4999xzaZVVVqloegCgqpuXf/jhh2nddddtsD7WxXMAQPty7LHHpv79+1c6GQDQNoLupZZaKl1//fUN1l933XV5Dm8AYM6Yb7758sjls1qKFH3J77nnnnTmmWcW+j4A0G6al5900klpt912Sw8//HBNn+7HHnss3X///Y0G4wBAMc4555yKvv9HH32U9t9//3TLLbekHj16NKkZeixlkyZNKjiFAFCFQfcuu+ySnnjiiXT22WfnTDYst9xy6cknn0yrrrpqEWkEABoxbNiwir13TBk6fPjwPJDq6quvnt59991Zvmbs2LG58B4A2pNmB91hyJAh6eqrr2751AAAFTVy5Mh0+umnz3Sbv//977lJ+RdffJGOP/74Ju87th0xYkSdmu4BAwZ8p/QCQJsLuv/85z+nTp06pS233LLO+rvvvjtNnz49bb311i2ZPgBgDjrqqKNyDfbMLLnkkukvf/lLevzxx1O3bt3qPBe13nvuuWcaN25cg9fFtvW3B4C2rvPslICfdtppjTYzi+cE3QBQvRZYYIG8zMp5552Xfv7zn9c8/uCDD3KBfAysGtOHAQCzGXS/8cYbafDgwQ3WL7vssunNN99s7u4AgCo0cODAOo/nmWee/HfQoEFp0UUXrVCqAKANTBnWu3fv9PbbbzdYHwH33HPP3VLpAgCaaerUqem1115L3377baWTAgDMbtC94447piOOOCK99dZbdQLu6AO2ww47NHd3AMB3NHny5LTffvvlabuWX3759N577+X1hx56aKNdwoqw+OKL565mq6yyyhx5PwBos0H3L3/5y1yjHc3Jl1hiibzElGF9+vRJZ555ZjGpBABmOir4+PHj04MPPpjmmmuumvWbb7557mMNAFRRn+5oXv7Xv/413XvvvTmD7969e1pppZXShhtuWEwKAYCZuuWWW3Jwvfbaa6cOHTrUrI9a79ot0wCAKqjpDpGhb7HFFumYY45JhxxySIsE3NH8LfYbTdcBgKb75JNPUr9+/Rqs/+qrr+oE4QBAKw66Yy7O22+/vc66K6+8Mjcvj4z+gAMOSFOmTJmtRDz11FPpoosuyjXmAEDzxNzYd9xxR83jcqB96aWXpnXWWaeCKQMAmty8/OSTT04bb7xx2m677fLjF198MQ/aMnz48Nyn+4wzzkj9+/dPY8aMaVYCvvzyy7TnnnumSy65pM58nwBA05x66qlp6623Tq+88koeufzcc8/N/4/uYA899FClkwcA7VqTa7qff/75tNlmm9U8vvbaa9Naa62Vg+URI0ak8847L11//fXNTsDBBx+ctt122zzYy6xETfqkSZPqLADQ3q2//vp5nJUIuFdcccV0zz335FZo0UptyJAhlU4eALRrTa7p/vzzz9OCCy5Y8zhKzqNUvWyNNdZI77//frPePAL3Z599Njcvb4qxY8emk046qVnvAQBt2TfffJN+8pOfpFGjRuWCcACgSmu6I+B+55138v+nTp2ag+UYJbXsiy++SF26dGnyG0eAfvjhh6ff//73daY3mdWUKBMnTqxZmhvkA0BbE3nvjTfeWOlkAADfNejeZptt0siRI9MjjzySg98ePXqkDTbYoOb5F154IQ0aNKipu0vPPPNM+vjjj9Nqq62WOnfunJeoPY9m6vH/adOmNXhNt27dUq9eveosANDeDR06NE8bBgBUcfPyU045Je28885po402SvPMM08aN25c6tq1a83zl112WZ5GrKmif3gMxlbbPvvsk5Zddtl03HHHpU6dOjV5XwDQni299NJ5wNPHHnss9+Gee+656zx/2GGHVSxtANDeNTno7tu3b3r44Ydzs+4IuusHxTfccENe31Q9e/ZMK6ywQp11cZPQp0+fBusBgBn73e9+l+add97ciiyW2mL6MEE3AFRB0F3Wu3fvRtfPP//8LZEeAKCZymOuAABtIOgu0oMPPljpJABAVSuVSjU13ABAFQ2kBgC0XldeeWWeo7t79+55WWmlldJVV11V6WQBQLvXqmq6AYDmO+uss/I83Yccckhab7318rpHH300HXjggenTTz9NRx55ZKWTCADtlqAbAKrc+eefny644IK0995716zbYYcd0vLLL5/GjBkj6AaACtK8HACq3IcffpjWXXfdButjXTwHAFSOoBsAqtxSSy2Vrr/++gbrr7vuujyHNwBQOZqXA0CVO+mkk9Juu+2WHn744Zo+3Y899li6//77Gw3GAYA5R003AFS5XXbZJT3xxBOpb9++6ZZbbslL/P/JJ59MO+20U6WTBwDtmppuAGgDhgwZkq6++upKJwMAqEdNNwBUuT//+c/p7rvvbrA+1t15550VSRMA8H8E3QBQ5UaOHJmmTZvWYH2pVMrPAQCVI+gGgCr3xhtvpMGDBzdYv+yyy6Y333yzImkCAP6PoBsAqlzv3r3T22+/3WB9BNxzzz13RdIEAPwfQTcAVLkdd9wxHXHEEemtt96qE3AfddRRaYcddqho2gCgvRN0A0CV++Uvf5lrtKM5+RJLLJGX5ZZbLvXp0yedeeaZlU4eALRrpgwDgDbQvPyvf/1ruvfee9P48eNT9+7d00orrZQ23HDDSicNANo9QTcAtAEdOnRIW2yxRV4AgNZD83IAqFKPP/54uv322+usu/LKK3Pz8n79+qUDDjggTZkypWLpAwAE3QBQtU4++eT08ssv1zx+8cUX03777Zc233zzPD/3n/70pzR27NiKphEA2jtBNwBUqeeffz5tttlmNY+vvfbatNZaa6VLLrkkjRgxIp133nnp+uuvr2gaAaC9E3QDQJX6/PPP04ILLljz+KGHHkpbb711zeM11lgjvf/++xVKHQAQBN0AUKUi4H7nnXfy/6dOnZqeffbZtPbaa9c8/8UXX6QuXbpUMIUAgKAbAKrUNttsk/tuP/LII+n4449PPXr0SBtssEHN8y+88EIaNGhQRdMIAO2dKcMAoEqdcsopaeedd04bbbRRmmeeedK4ceNS165da56/7LLLTCEGABUm6AaAKtW3b9/08MMPp4kTJ+agu1OnTnWev+GGG/J6AKByBN0AUOV69+7d6Pr5559/jqcFAKhLn24AAAAoiKAbAAAACiLoBgAAgIIIugEAAKAggm4AAAAoiKAbAAAACiLoBgAAgIIIugEAAKAggm4AAAAoiKAbAAAACiLoBgAAgIIIugEAAKAggm4AAAAoiKAbAAAACiLoBgAAgIIIugEAAKAggm4AAAAoiKAbAAAACiLoBgAAgIIIugEAAKAggm4AAAAoiKAbAAAACiLoBgAAgIIIugEAAKAggm4AAAAoiKAbAAAACiLoBgAAgIIIugEAAKAggm4AAAAoiKAbAAAACiLoBgAAgIIIugEAAKAggm4AAAAoiKAbAAAACiLoBgAAgIIIugEAAKAggm4AAAAoiKAbAAAACiLoBgAAgIIIugEAAKAggm4AAAAoiKAbAAAACiLoBgAAgIIIugEAAKAggm4AAAAoiKAbAAAACiLoBgAAgIIIugEAAKAggm4AAAAoiKAbAAAACiLoBgAAgIIIugEAAKAggm4AYLbdcccdaa211krdu3dP8803Xxo6dGilkwQArUrnSicAAKhON954Y9p///3TqaeemjbddNP07bffppdeeqnSyQKAVkXQDQA0WwTYhx9+eDrjjDPSfvvtV7N+8ODBFU0XALQ2mpcDAM327LPPpn/961+pY8eOadVVV00LL7xw2nrrrdV0A0A9gm4AoNnefvvt/HfMmDHpxBNPTLfffnvu073xxhunzz77rNHXTJkyJU2aNKnOAgBtnaAbAKgxcuTI1KFDh5kur776apo+fXre/oQTTki77LJLGjJkSLr88svz8zfccEOj+x47dmzq3bt3zTJgwIA5fHQAMOfp0w0A1DjqqKPS8OHDZ7rNkksumT788MMGfbi7deuWn3vvvfcafd3xxx+fRowYUfM4aroF3gC0dYJuAKDGAgsskJdZiZrtCLJfe+21tP766+d133zzTXr33XfTYost1uhrYvtYAKA9EXQDAM3Wq1evdOCBB6bRo0fn2uoItGMk8/CDH/yg0skDgFZD0A0AzJYIsjt37pz22muv9PXXX6e11lor/eUvf8kDqgEA/0fQDQDMli5duqQzzzwzLwBA44xeDgAAAAURdAMAAEBBBN0AAABQEEE3AAAAFETQDQAAAAURdAMAAEBBBN0AAADQFoPusWPHpjXWWCP17Nkz9evXLw0dOjS99tprlUwSAAAAtI2g+6GHHkoHH3xw+tvf/pbuvffe9M0336QtttgiffXVV5VMFgAAALSIzqmC7rrrrjqPr7jiilzj/cwzz6QNN9ywYukCAACANtene+LEifnv/PPPX+mkAAAAQHXXdNc2ffr0dMQRR6T11lsvrbDCCo1uM2XKlLyUTZo0aQ6mEAAAAKq0pjv6dr/00kvp2muvnenAa717965ZBgwYMEfTCAAAAFUXdB9yyCHp9ttvTw888EBadNFFZ7jd8ccfn5ugl5f3339/jqYTAAAAqqZ5ealUSoceemi6+eab04MPPpiWWGKJmW7frVu3vAAAAEA16FzpJuV/+MMf0q233prn6p4wYUJeH03Hu3fvXsmkAQAAQHU3L7/gggtyM/GNN944LbzwwjXLddddV8lkAQAAQNtoXg4AAABtVasYSA0AAADaIkE3AAAAFETQDQAAAAURdAMAAEBBBN0AAABQEEE3AAAAFETQDQAAAAURdAMAAEBBBN0AAABQEEE3AAAAFETQDQAAAAURdAMAAEBBBN0AAABQEEE3AAAAFETQDQAAAAURdAMAAEBBBN0AAABQEEE3AAAAFETQDQAAAAURdAMAAEBBBN0AAABQEEE3AAAAFETQDQAAAAURdAMAAEBBBN0AAABQEEE3AAAAFETQDQAAAAURdAMAAEBBBN0AAABQEEE3AAAAFETQDQAAAAURdAMAAEBBBN0AAABQEEE3AAAAFETQDQAAAAURdAMAAEBBBN0AAABQEEE3AAAAFETQDQAAAAURdAMAAEBBBN0AAABQEEE3AAAAFETQDQAAAAURdAMAAEBBBN0AAABQEEE3AAAAFETQDQAAAAURdAMAAEBBBN0AAABQEEE3AAAAFETQDQAAAAURdAMAAEBBBN0AAABQEEE3AAAAFETQDQAAAAURdAMAAEBBBN0AAABQEEE3AAAAFETQDQAAAAURdAMAAEBBBN0AAABQEEE3AAAAFETQDQAAAAURdAMAAEBBBN0AAABQEEE3AAAAFETQDQAAAAURdAMAAEBBBN0AAABQEEE3AAAAFETQDQAAAAURdAMAAEBBBN0AAABQEEE3ADBbXn/99bTjjjumvn37pl69eqX1118/PfDAA5VOFgC0KoJuAGC2bLfddunbb79Nf/nLX9IzzzyTVl555bxuwoQJlU4aALQagm4AoNk+/fTT9MYbb6SRI0emlVZaKS299NLptNNOS5MnT04vvfRSpZMHAK2GoBsAaLY+ffqkZZZZJl155ZXpq6++yjXeF110UerXr18aMmRIpZMHAK1G50onAACoPh06dEj33XdfGjp0aOrZs2fq2LFjDrjvuuuuNN988zX6milTpuSlbNKkSXMwxQBQGWq6AYAa0Vw8AuqZLa+++moqlUrp4IMPzoH2I488kp588skcgG+//fbpww8/bHTfY8eOTb17965ZBgwYMMePD76TUql1L0CrpKYbAKhx1FFHpeHDh890myWXXDIPnnb77benzz//PI9cHn7729+me++9N40bNy4H7/Udf/zxacSIEXVqugXeALR1gm4AoMYCCyyQl1mJAdNCNCuvLR5Pnz690dd069YtLwDQnmheDgA02zrrrJP7bg8bNiyNHz8+z9l9zDHHpHfeeSdtu+22lU4eALQagm4AoNn69u2bB0378ssv06abbppWX3319Oijj6Zbb701z9cNAPwfzcsBgNkSgfbdd99d6WQAQKumphsAAAAKIugGAACAggi6AQAAoCCCbgAAACiIoBsAAAAKIugGAACAggi6AQAAoCCCbgAAACiIoBsAAAAKIugGAACAggi6AQAAoCCCbgAAAGjLQfdvfvObtPjii6e55porrbXWWunJJ5+sdJIAAACg+oPu6667Lo0YMSKNHj06Pfvss2nllVdOW265Zfr4448rnTQAAACo7qD7rLPOSvvvv3/aZ5990uDBg9OFF16YevTokS677LJKJw0AAACqN+ieOnVqeuaZZ9Lmm2/+/xLUsWN+/Pjjj1cyaQAAAPCddU4V9Omnn6Zp06alBRdcsM76ePzqq6822H7KlCl5KZs4cWL+O2nSpBZL0/Qpk1tkP5M6lFpkP+k7HJtjaePH0oLf+++iVX023/GctKpjaS3fM8fSyI5a7rdX/h2XSi2UtipTPu7Wcj0DgCLy8YoG3c01duzYdNJJJzVYP2DAgNTa9G6pHZ3WYnuabY6llR7LOalN6d1GPpc29z1rqR05lpn64osvUu/elT9Hc1ocd2vNxwGgpfLxigbdffv2TZ06dUofffRRnfXxeKGFFmqw/fHHH58HXSubPn16+uyzz1KfPn1Shw4dUmsq8YgbiPfffz/16tUrVTPH0jq1pWNpa8fjWFqn1nosUTIeGXX//v1TexTHHZ9Jz549W1U+3tq/N+35WNrKcbSlY2krxxEcS+szqZUfR1Pz8YoG3V27dk1DhgxJ999/fxo6dGhNIB2PDznkkAbbd+vWLS+1zTvvvKm1ii9Ga/xyzA7H0jq1pWNpa8fjWFqn1ngs7bGGu/Y4Losuumhq7Vrj96a9H0tbOY62dCxt5TiCY2l9erXi42hKPl7x5uVRcz1s2LC0+uqrpzXXXDOdc8456auvvsqjmQMAAEA1q3jQvdtuu6VPPvkk/exnP0sTJkxIq6yySrrrrrsaDK4GAAAA1abiQXeIpuSNNSevVtEEfvTo0Q2awlcjx9I6taVjaWvH41hap7Z0LMw5bel701aOpa0cR1s6lrZyHMGxtD7d2shxdCi113lKAAAAoGAdi34DAAAAaK8E3QAAAFAQQTcAAAAURNDdgh5++OG0/fbb58nRO3TokG655ZZUrcaOHZvWWGON1LNnz9SvX788j/prr72WqtEFF1yQVlpppZr5/dZZZ5105513prbgtNNOy9+1I444IlWbMWPG5LTXXpZddtlUrf71r3+lH/3oR6lPnz6pe/fuacUVV0xPP/10qkaLL754g88mloMPPjhVm2nTpqVRo0alJZZYIn8ugwYNSqecckoynAntJU9vK/l5W83L5eOtR1vIx+XfrVerGL28rYj5xVdeeeW07777pp133jlVs4ceeij/QCOj/vbbb9NPf/rTtMUWW6RXXnklzT333KmaLLroojlTW3rppfMPddy4cWnHHXdMzz33XFp++eVTtXrqqafSRRddlG9CqlWc//vuu6/mcefO1XlJ+vzzz9N6662XNtlkk3wTuMACC6Q33ngjzTfffKlav1uR2ZW99NJL6fvf/376wQ9+kKrN6aefnm/W43cf37e4gdpnn31S796902GHHVbp5NGKtZU8va3k520xL5ePtx5tJR+Xf7diMXo5LS9O7c0331xqKz7++ON8TA899FCpLZhvvvlKl156aalaffHFF6Wll166dO+995Y22mij0uGHH16qNqNHjy6tvPLKpbbguOOOK62//vqltiq+X4MGDSpNnz69VG223Xbb0r777ltn3c4771zac889K5Ymqk9bytPbUn5ezXm5fLx1aav5uPy79dC8nCaZOHFi/jv//POnahalf9dee22uwYimadUqai223XbbtPnmm6dqFqXI0XRzySWXTHvuuWd67733UjW67bbb0uqrr55LkqP55qqrrpouueSS1BZMnTo1XX311bm2L5qoVZt111033X///en111/Pj8ePH58effTRtPXWW1c6aVARbSE/bwt5uXy8dWmL+bj8u3WpzjYgzFHTp0/PfY2i2c0KK6yQqtGLL76YM+b//ve/aZ555kk333xzGjx4cKpGcaPx7LPP5iZE1WyttdZKV1xxRVpmmWXShx9+mE466aS0wQYb5KZQ0fewmrz99tu5CdSIESNy0834bKLpU9euXdOwYcNSNYt+rP/5z3/S8OHDUzUaOXJkmjRpUu5n2KlTp3yz/otf/CLfHEJ7U+35eVvJy+XjrU9bzMfl361Mpava26q21BTtwAMPLC222GKl999/v1StpkyZUnrjjTdKTz/9dGnkyJGlvn37ll5++eVStXnvvfdK/fr1K40fP75mXbU2S6vv888/L/Xq1asqmwp26dKltM4669RZd+ihh5bWXnvtUrXbYostStttt12pWl1zzTWlRRddNP994YUXSldeeWVp/vnnL11xxRWVThpVpK3k6dWen7eFvFw+3jq1xXxc/t26CLoL0lYy6IMPPjh/4d9+++1SW7LZZpuVDjjggFK1ie9UfLc6depUs8TjDh065P9/++23pWq2+uqr5xupajNw4MDSfvvtV2fdb3/721L//v1L1ezdd98tdezYsXTLLbeUqlVcv37961/XWXfKKaeUlllmmYqlierTFvL0tpifV2NeLh9vndpaPi7/bn00L6dRcY9x6KGH5qZbDz74YB6uv601sZsyZUqqNptttlluXldbjOQYTW+OO+643PymWn355ZfprbfeSnvttVeqNtFUs/4UPNEHabHFFkvV7PLLL89926LfYbWaPHly6tix7vAl8TuJawC0B205P6/GvFw+3jq1tXxc/t36CLpb+GLz5ptv1jx+55130vPPP58HKxk4cGCqtgE+/vCHP6Rbb70198uZMGFCXh/D9MdcedXk+OOPz4MuxGfwxRdf5OOKG4+77747VZv4LOr3w4spX2JOyWrrn3f00UfnOXAjQ/vggw/S6NGj88X0hz/8Yao2Rx55ZB7w49RTT0277rprevLJJ9PFF1+cl2oVmVpk2tGXrVqngAnxHYs+YPH7jylHYnqhs846Kw8sA+0hT28r+Xlbycvl461TW8rH5d+tVKWr2tuSBx54IDcRqr8MGzasVG0aO45YLr/88lK1iekGog9b165dSwsssEBujnbPPfeU2opq7Qu22267lRZeeOH8uSyyyCL58ZtvvlmqVn/6059KK6ywQqlbt26lZZddtnTxxReXqtndd9+df/OvvfZaqZpNmjQp/z6i6eBcc81VWnLJJUsnnHBC7hsK7SFPbyv5eVvOy+XjrUNbycfl361Th/in0oE/AAAAtEXm6QYAAICCCLoBAACgIIJuAAAAKIigGwAAAAoi6AYAAICCCLoBAACgIIJuAAAAKIigGwAAAAoi6AYAAICCCLqhjXr//ffTvvvum/r375+6du2aFltssXT44Yenf//735VOGgAwC/JxaDsE3dAGvf3222n11VdPb7zxRrrmmmvSm2++mS688MJ0//33p3XWWSd99tlnhb331KlTC9s3ALQH8nFoWwTd0AYdfPDBuVT8nnvuSRtttFEaOHBg2nrrrdN9992X/vWvf6UTTjghb9ehQ4d0yy231HntvPPOm6644oo6Je277rprXj///POnHXfcMb377rs1zw8fPjwNHTo0/eIXv8il8csss0w6+eST0worrNAgXausskoaNWpUoccOANVOPg5ti6Ab2pgo/b777rvTQQcdlLp3717nuYUWWijtueee6brrrkulUmmW+/rmm2/SlltumXr27JkeeeSR9Nhjj6V55pknbbXVVnVKwqPk/bXXXkv33ntvuv3223NzuL///e/pqaeeqtnmueeeSy+88ELaZ599WviIAaDtkI9D29O50gkAWlY0RYuMeLnllmv0+Vj/+eefp08++WSW+4pMffr06enSSy/Npenh8ssvz6XlDz74YNpiiy3yurnnnjtvE6XyZZHJx7ZrrLFGzeuitH7JJZdsoSMFgLZHPg5tj5puaKNmVQJeO2OdkfHjx+d+ZFFCHiXjsUTTtP/+97/prbfeqtluxRVXbLC//fffP/dDi22jNP0Pf/hDLjkHAGZNPg5th5puaGOWWmqpXJodzcJ22mmnBs/H+gUWWCCXcsd29TP1aIpW9uWXX6YhQ4ak3//+9w32E/soixLy+rbffvvUrVu3dPPNN+eMPPb7P//zPy1whADQdsnHoe0RdEMb06dPn/T9738//fa3v01HHnlknf5gEyZMyBlvDNBSznA//PDDOk3aJk+eXPN4tdVWy03T+vXrl3r16tWsdHTu3DkNGzYsN0eLzHr33Xdv0DcNAKhLPg5tj+bl0Ab9+te/TlOmTMn9sR5++OE8culdd92VM/Hvfe976Wc/+1nebtNNN83bxuAoTz/9dDrwwANTly5davYTg7X07ds3j3QaA7C88847uQ/YYYcdlv75z3/OMh0//vGP01/+8pf83pqkAUDTyMehbRF0Qxu09NJL5xFHY7CTmCZkscUWy1ONREZdHrk0/OpXv0oDBgxIG2ywQdpjjz3S0UcfnXr06FGzn/h/ZPYxVcnOO++cB2/Zb7/9cv+uppSYRzrWXXfdtOyyy6a11lqr0GMGgLZCPg5tS4dSU+YbAKre6NGj01lnnZWnA1l77bXnyHvG5SUy7Jj2ZMSIEXPkPQGgLZKPQ/USdEM7Ev2yJk6cmJuVdexYbEOXmMrk2muvTccff3xuFjfffPMV+n4A0NbJx6E6CbqBQsSIqtGP7Nxzz81N3gCA6iEfh5Yj6AYAAICCGEgNAAAACiLoBgAAgIIIugEAAKAggm4AAAAoiKAbAAAACiLoBgAAgIIIugEAAKAggm4AAAAoiKAbAAAAUjH+P8sbCa8div6lAAAAAElFTkSuQmCC",
812
+ "text/plain": [
813
+ "<Figure size 1000x600 with 2 Axes>"
814
+ ]
815
+ },
816
+ "metadata": {},
817
+ "output_type": "display_data"
818
+ },
819
+ {
820
+ "name": "stdout",
821
+ "output_type": "stream",
822
+ "text": [
823
+ "Average Base Model Score: 8.12\n",
824
+ "Average Fine-tuned Model Score: 7.25\n",
825
+ "Average Improvement: -0.88 (-10.8%)\n"
826
+ ]
827
+ }
828
+ ],
829
+ "source": [
830
+ "# Visualize comparison results\n",
831
+ "plt.figure(figsize=(10, 6))\n",
832
+ "\n",
833
+ "# Calculate improvement\n",
834
+ "comparison_results['improvement'] = comparison_results['fine_tuned_score'] - comparison_results['base_score']\n",
835
+ "\n",
836
+ "# Bar chart comparing scores\n",
837
+ "plt.subplot(1, 2, 1)\n",
838
+ "x = np.arange(len(comparison_results))\n",
839
+ "width = 0.35\n",
840
+ "\n",
841
+ "plt.bar(x - width/2, comparison_results['base_score'], width, label='Base Model')\n",
842
+ "plt.bar(x + width/2, comparison_results['fine_tuned_score'], width, label='Fine-tuned Model')\n",
843
+ "\n",
844
+ "plt.xlabel('Query')\n",
845
+ "plt.ylabel('Score (0-10)')\n",
846
+ "plt.title('Base vs Fine-tuned Model Performance')\n",
847
+ "plt.xticks(x, range(1, len(comparison_results) + 1))\n",
848
+ "plt.legend()\n",
849
+ "\n",
850
+ "# Improvement chart\n",
851
+ "plt.subplot(1, 2, 2)\n",
852
+ "colors = ['green' if x > 0 else 'red' for x in comparison_results['improvement']]\n",
853
+ "plt.bar(range(1, len(comparison_results) + 1), comparison_results['improvement'], color=colors)\n",
854
+ "plt.axhline(y=0, color='k', linestyle='-', alpha=0.3)\n",
855
+ "plt.xlabel('Query')\n",
856
+ "plt.ylabel('Score Improvement')\n",
857
+ "plt.title('Fine-tuned Model Improvement')\n",
858
+ "\n",
859
+ "plt.tight_layout()\n",
860
+ "plt.show()\n",
861
+ "\n",
862
+ "# Show overall improvement\n",
863
+ "avg_base_score = comparison_results['base_score'].mean()\n",
864
+ "avg_fine_tuned_score = comparison_results['fine_tuned_score'].mean()\n",
865
+ "avg_improvement = avg_fine_tuned_score - avg_base_score\n",
866
+ "\n",
867
+ "print(f\"Average Base Model Score: {avg_base_score:.2f}\")\n",
868
+ "print(f\"Average Fine-tuned Model Score: {avg_fine_tuned_score:.2f}\")\n",
869
+ "print(f\"Average Improvement: {avg_improvement:.2f} ({avg_improvement/avg_base_score*100:.1f}%)\")"
870
+ ]
871
+ },
872
+ {
873
+ "cell_type": "markdown",
874
+ "metadata": {},
875
+ "source": [
876
+ "## Conclusion\n",
877
+ "\n",
878
+ "We were able to train a fine-tuned model on our queries and designs, but the results were disappointing. We don't want to launch an embedding model that hurts our performance so we'll stick with the existing rag agent. But with more queries, more data, and testing more models, there may be a way to find improvements."
879
+ ]
880
+ }
881
+ ],
882
+ "metadata": {
883
+ "kernelspec": {
884
+ "display_name": ".venv",
885
+ "language": "python",
886
+ "name": "python3"
887
+ },
888
+ "language_info": {
889
+ "codemirror_mode": {
890
+ "name": "ipython",
891
+ "version": 3
892
+ },
893
+ "file_extension": ".py",
894
+ "mimetype": "text/x-python",
895
+ "name": "python",
896
+ "nbconvert_exporter": "python",
897
+ "pygments_lexer": "ipython3",
898
+ "version": "3.11.11"
899
+ }
900
+ },
901
+ "nbformat": 4,
902
+ "nbformat_minor": 4
903
+ }
src/fine_tuned_design_embeddings_20250225_161918/1_Pooling/config.json ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "word_embedding_dimension": 768,
3
+ "pooling_mode_cls_token": false,
4
+ "pooling_mode_mean_tokens": true,
5
+ "pooling_mode_max_tokens": false,
6
+ "pooling_mode_mean_sqrt_len_tokens": false,
7
+ "pooling_mode_weightedmean_tokens": false,
8
+ "pooling_mode_lasttoken": false,
9
+ "include_prompt": true
10
+ }
src/fine_tuned_design_embeddings_20250225_161918/README.md ADDED
@@ -0,0 +1,533 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ tags:
3
+ - sentence-transformers
4
+ - sentence-similarity
5
+ - feature-extraction
6
+ - generated_from_trainer
7
+ - dataset_size:95
8
+ - loss:CosineSimilarityLoss
9
+ base_model: sentence-transformers/distilbert-base-nli-stsb-mean-tokens
10
+ widget:
11
+ - source_sentence: "Design 115:\n Description: The design utilizes a dramatic\
12
+ \ red and black color palette, creating a high contrast and visually striking\
13
+ \ interface that emphasizes boldness and clarity. The layout is structured with\
14
+ \ a central column for main content and a sidebar for navigation, enhancing usability.\
15
+ \ Typography is classic and easy to read, using white text for legibility against\
16
+ \ dark backgrounds. The design features subtle gradient backgrounds and occasional\
17
+ \ fiery imagery, contributing to a dynamic and modern aesthetic.\n \
18
+ \ Categories: Web Design, Minimalist, Modern, Typography\n Visual Characteristics:\
19
+ \ High Contrast, Central Column Layout, Bold Typography, Red and Black Palette,\
20
+ \ Gradient Background"
21
+ sentences:
22
+ - "Design 185:\n Description: The design features a bold contrast between\
23
+ \ a bright blue header and a predominantly black background, creating a modern\
24
+ \ and striking visual impact. The use of crisp typography in white enhances readability\
25
+ \ against the dark backdrop, while an accent of orange in a sidebar provides additional\
26
+ \ contrast and attention-grabbing potential. The layout follows a structured and\
27
+ \ logical arrangement, guiding the viewer's eye through a series of selectable\
28
+ \ design options and resource links, creating a user-friendly and engaging experience.\n\
29
+ \ Categories: Modern, Typography, Web Design, Classic, User Friendly\n\
30
+ \ Visual Characteristics: High Contrast, Bold Colors, Structured Layout,\
31
+ \ Readable Typography, Accent Highlights"
32
+ - "Design 002:\n Description: The design embodies a serene and focused\
33
+ \ aesthetic with a soft, warm color scheme and straightforward typography. A prominent\
34
+ \ header creates an inviting entry point, while the balanced layout effectively\
35
+ \ organizes the content. Subtle shadows and borders provide depth, enhancing visual\
36
+ \ appeal without overwhelming the viewer.\n Categories: Web Design,\
37
+ \ Minimalism, Typography, Navigation\n Visual Characteristics: Warm\
38
+ \ color palette, Minimalistic layout, Simplicity, Balanced whitespace"
39
+ - "Design 200:\n Description: The design features a vibrant blue color\
40
+ \ scheme complemented by white and black typography, creating a striking contrast.\
41
+ \ The use of textured borders and background effects adds depth and visual interest.\
42
+ \ The layout is organized, with distinct sections for text content that enhance\
43
+ \ readability. The design reflects a modern and clean aesthetic, offering a sense\
44
+ \ of technological advancement and innovation.\n Categories: Modern,\
45
+ \ Typography, Web Design, Colorful\n Visual Characteristics: Vibrant\
46
+ \ Color, Textured Background, High Contrast, Organized Layout"
47
+ - source_sentence: "Design 142:\n Description: The design effortlessly\
48
+ \ combines a dark, textured background with bold, contrasting typography, creating\
49
+ \ a visually striking and modern aesthetic. The use of minimalist elements and\
50
+ \ a focused color palette emphasizes the central text, while the overall layout\
51
+ \ feels balanced and sophisticated.\n Categories: Modern, Minimalist,\
52
+ \ Typography-focused, Dark theme\n Visual Characteristics: Textured\
53
+ \ background, Contrasting colors, Bold typography, Sophisticated layout"
54
+ sentences:
55
+ - "Design 106:\n Description: This design features a minimalist and retro\
56
+ \ aesthetic with a muted color palette predominantly composed of olive green and\
57
+ \ subtle contrasts. The layout utilizes clean, sans-serif typography and a straightforward\
58
+ \ column format to present information in a clear and organized manner. The overall\
59
+ \ style evokes a calm and contemplative mood, reminiscent of classic web designs,\
60
+ \ with an emphasis on simplicity and readability.\n Categories: Minimalism,\
61
+ \ Retro, Web Design, Typography, Information Design\n Visual Characteristics:\
62
+ \ Muted color palette, Clean typography, Column layout, Simple navigation, Classic\
63
+ \ aesthetic"
64
+ - "Design 009:\n Description: This design features a clean and organized\
65
+ \ layout with a classic monochrome color palette, emphasizing the elegance of\
66
+ \ CSS design. It uses serif typography for a traditional feel, with strong visual\
67
+ \ separation of sections, enhancing readability. The design incorporates ornamental\
68
+ \ graphics at the top and bottom, adding a touch of sophistication. The ample\
69
+ \ use of whitespace contributes to a serene and uncluttered experience, inviting\
70
+ \ users to engage with the content.\n Categories: Web Design, Typography,\
71
+ \ Minimalism, Ornamental Design, Monochrome\n Visual Characteristics:\
72
+ \ Serif Typography, Monochromatic Palette, Ornamental Graphics, Whitespace Usage,\
73
+ \ Classic Layout"
74
+ - "Design 184:\n Description: The design features a subtle and harmonious\
75
+ \ aesthetic using a pastel green color scheme that evokes tranquility and balance.\
76
+ \ The layout is clean and structured, with a mix of serif and sans-serif typography\
77
+ \ that enhances readability. Decorative elements like the zen-like symbol and\
78
+ \ soft imagery provide an abstract, soothing quality, contributing to the theme\
79
+ \ of enlightenment and calm. This design is suited for audiences interested in\
80
+ \ modern CSS design principles and invites exploration and participation.\n \
81
+ \ Categories: Minimalist, Modern, Educational, Web-focused\n \
82
+ \ Visual Characteristics: Subtle color palette, Sophisticated typography, Clean\
83
+ \ layout, Zen imagery, Textured background"
84
+ - source_sentence: "Design 122:\n Description: The design features a minimalist\
85
+ \ aesthetic with a dominant white space, paired with subtle green accents and\
86
+ \ a hint of red, creating a clean and sophisticated look. The layout is vertical\
87
+ \ and structured, highlighting content purposefully with ample spacing, making\
88
+ \ it easy to read and navigate. The typography is elegant, using a serif font\
89
+ \ for headings to contrast with a simpler body text, supporting a Zen-like theme\
90
+ \ that embodies simplicity and clarity.\n Categories: minimalist, sophisticated,\
91
+ \ text-focused, zen-inspired\n Visual Characteristics: vertical layout,\
92
+ \ white space, green and red accents, serif typography"
93
+ sentences:
94
+ - "Design 195:\n Description: The design exemplifies a clean and minimalistic\
95
+ \ style, highlighting simplicity and readability through a dominance of white\
96
+ \ space and light, pastel background textures. It integrates a single-column layout\
97
+ \ with a sidebar for easy navigation, using a consistent and harmonious color\
98
+ \ palette composed mainly of soft greens, oranges, and muted text colors to ensure\
99
+ \ a smooth visual experience.\n Categories: Minimalist, Web Design,\
100
+ \ Modern, Typography\n Visual Characteristics: Simple Layout, Light\
101
+ \ Color Palette, Ample White Space, Readable Typography"
102
+ - "Design 187:\n Description: The design features a mystical, nature-inspired\
103
+ \ theme with a rustic color palette of dark greens and earthy reds. Intricate\
104
+ \ textures and foliage imagery offer a sense of depth, complemented by elegant\
105
+ \ serif typography that conveys a classic and sophisticated mood. The layout uses\
106
+ \ clear sections for content, enhancing readability and user engagement.\n \
107
+ \ Categories: Nature, Mystical, Classic, Rustic, Elegant\n \
108
+ \ Visual Characteristics: Dark Green Palette, Earthy Red Accents, Serif Typography,\
109
+ \ Textured Background, Nature Imagery"
110
+ - "Design 162:\n Description: The design embodies a classic, elegant\
111
+ \ style with a warm color palette dominated by earthy tones, enhanced by an ornate\
112
+ \ decorative header image. It uses a narrow column layout that focuses attention\
113
+ \ on the textual content, which is complemented by a textured background, adding\
114
+ \ depth and sophistication. The typography combines bold headings with a serif\
115
+ \ font, lending an old-world charm that aligns with the historical and sophisticated\
116
+ \ mood.\n Categories: classic, elegant, historical, sophisticated,\
117
+ \ text-focused\n Visual Characteristics: earthy color palette, ornate\
118
+ \ header, textured background, serif typography, narrow column layout"
119
+ - source_sentence: "Design 137:\n Description: The design presents a sleek,\
120
+ \ unified aesthetic utilizing a blue monochromatic color palette, giving it a\
121
+ \ modern and tech-centric appeal. Clean, crisp typography paired with visually\
122
+ \ engaging graphics contribute to its overall appeal, while the structured layout\
123
+ \ effectively organizes content for easy navigation and readability.\n \
124
+ \ Categories: Modern, Tech, Minimalist, Corporate, Professional\n \
125
+ \ Visual Characteristics: Monochromatic color scheme, Structured layout, Modern\
126
+ \ typography, High contrast, Tech-inspired graphics"
127
+ sentences:
128
+ - "Design 184:\n Description: The design features a subtle and harmonious\
129
+ \ aesthetic using a pastel green color scheme that evokes tranquility and balance.\
130
+ \ The layout is clean and structured, with a mix of serif and sans-serif typography\
131
+ \ that enhances readability. Decorative elements like the zen-like symbol and\
132
+ \ soft imagery provide an abstract, soothing quality, contributing to the theme\
133
+ \ of enlightenment and calm. This design is suited for audiences interested in\
134
+ \ modern CSS design principles and invites exploration and participation.\n \
135
+ \ Categories: Minimalist, Modern, Educational, Web-focused\n \
136
+ \ Visual Characteristics: Subtle color palette, Sophisticated typography, Clean\
137
+ \ layout, Zen imagery, Textured background"
138
+ - "Design 175:\n Description: The design showcases a balanced layout\
139
+ \ with a minimalist aesthetic, focused on demonstrating the power of CSS-based\
140
+ \ design. It features a clean and organized structure with a dominant use of blues\
141
+ \ and whites, complemented by modern, sans-serif typography. Silhouetted figures\
142
+ \ add a visual interest while maintaining a professional tone, making the page\
143
+ \ feel sophisticated and informative. The layout is well-suited for showcasing\
144
+ \ text content effectively, facilitating easy navigation through clear hierarchy.\n\
145
+ \ Categories: Minimalist, Technology, Informational, Professional,\
146
+ \ Modern\n Visual Characteristics: Clean layout, Balanced color palette,\
147
+ \ Silhouette imagery, Sans-serif typography, Organized structure"
148
+ - "Design 009:\n Description: This design features a clean and organized\
149
+ \ layout with a classic monochrome color palette, emphasizing the elegance of\
150
+ \ CSS design. It uses serif typography for a traditional feel, with strong visual\
151
+ \ separation of sections, enhancing readability. The design incorporates ornamental\
152
+ \ graphics at the top and bottom, adding a touch of sophistication. The ample\
153
+ \ use of whitespace contributes to a serene and uncluttered experience, inviting\
154
+ \ users to engage with the content.\n Categories: Web Design, Typography,\
155
+ \ Minimalism, Ornamental Design, Monochrome\n Visual Characteristics:\
156
+ \ Serif Typography, Monochromatic Palette, Ornamental Graphics, Whitespace Usage,\
157
+ \ Classic Layout"
158
+ - source_sentence: "Design 170:\n Description: The design of the CSS Zen\
159
+ \ Garden is exemplary with its soothing blue tones, providing a calm and professional\
160
+ \ aesthetic. The heart icons add a touch of creativity and warmth. The layout\
161
+ \ is clean and well-structured with clear navigation on the right-hand side, providing\
162
+ \ users easy access to additional information and style sheets. The typography\
163
+ \ varies, highlighting key sections and maintaining readability throughout.\n\
164
+ \ Categories: Web Design, CSS Showcase, Typography, User Interface,\
165
+ \ Aesthetic\n Visual Characteristics: Soothing Color Palette, Structured\
166
+ \ Layout, Iconography, Hierarchical Typography, Calming Aesthetic"
167
+ sentences:
168
+ - "Design 122:\n Description: The design features a minimalist aesthetic\
169
+ \ with a dominant white space, paired with subtle green accents and a hint of\
170
+ \ red, creating a clean and sophisticated look. The layout is vertical and structured,\
171
+ \ highlighting content purposefully with ample spacing, making it easy to read\
172
+ \ and navigate. The typography is elegant, using a serif font for headings to\
173
+ \ contrast with a simpler body text, supporting a Zen-like theme that embodies\
174
+ \ simplicity and clarity.\n Categories: minimalist, sophisticated,\
175
+ \ text-focused, zen-inspired\n Visual Characteristics: vertical layout,\
176
+ \ white space, green and red accents, serif typography"
177
+ - "Design 194:\n Description: This design exudes a minimalist elegance\
178
+ \ with a muted, earthy color palette and a clean layout, embodying a sense of\
179
+ \ calm and sophistication. The subtle use of textures and classic serif typography\
180
+ \ enhances the refined aesthetic, while the centered alignment and generous spacing\
181
+ \ contribute to a relaxed readability. The incorporation of a delicate floral\
182
+ \ illustration adds a touch of organic charm, making the design feel both timeless\
183
+ \ and inviting.\n Categories: Minimalism, Elegant, Organic, Sophisticated,\
184
+ \ Classic\n Visual Characteristics: Muted Color Palette, Serif Typography,\
185
+ \ Centered Layout, Generous Spacing, Floral Illustration"
186
+ - "Design 143:\n Description: This design features a clean and structured\
187
+ \ layout with a monochromatic color scheme, highlighting text content with clear\
188
+ \ typographic hierarchy. A combination of minimalist aesthetic and functional\
189
+ \ design elements ensures readability and visual interest, while the central image\
190
+ \ adds a focal point. The use of borders and shadow effects provide depth to the\
191
+ \ overall design.\n Categories: Minimalism, Monochrome, Typography,\
192
+ \ Web Design, User Interface\n Visual Characteristics: Clear typographic\
193
+ \ hierarchy, Grid alignment, Monochromatic color scheme, Minimalist style, Use\
194
+ \ of borders, Shadow effects"
195
+ pipeline_tag: sentence-similarity
196
+ library_name: sentence-transformers
197
+ metrics:
198
+ - pearson_cosine
199
+ - spearman_cosine
200
+ model-index:
201
+ - name: SentenceTransformer based on sentence-transformers/distilbert-base-nli-stsb-mean-tokens
202
+ results:
203
+ - task:
204
+ type: semantic-similarity
205
+ name: Semantic Similarity
206
+ dataset:
207
+ name: Unknown
208
+ type: unknown
209
+ metrics:
210
+ - type: pearson_cosine
211
+ value: -0.13960523700017818
212
+ name: Pearson Cosine
213
+ - type: spearman_cosine
214
+ value: -0.06863870136546027
215
+ name: Spearman Cosine
216
+ ---
217
+
218
+ # SentenceTransformer based on sentence-transformers/distilbert-base-nli-stsb-mean-tokens
219
+
220
+ This is a [sentence-transformers](https://www.SBERT.net) model finetuned from [sentence-transformers/distilbert-base-nli-stsb-mean-tokens](https://huggingface.co/sentence-transformers/distilbert-base-nli-stsb-mean-tokens). It maps sentences & paragraphs to a 768-dimensional dense vector space and can be used for semantic textual similarity, semantic search, paraphrase mining, text classification, clustering, and more.
221
+
222
+ ## Model Details
223
+
224
+ ### Model Description
225
+ - **Model Type:** Sentence Transformer
226
+ - **Base model:** [sentence-transformers/distilbert-base-nli-stsb-mean-tokens](https://huggingface.co/sentence-transformers/distilbert-base-nli-stsb-mean-tokens) <!-- at revision cb8a28f4e13e28fde6137942584fc8a4ec701060 -->
227
+ - **Maximum Sequence Length:** 128 tokens
228
+ - **Output Dimensionality:** 768 dimensions
229
+ - **Similarity Function:** Cosine Similarity
230
+ <!-- - **Training Dataset:** Unknown -->
231
+ <!-- - **Language:** Unknown -->
232
+ <!-- - **License:** Unknown -->
233
+
234
+ ### Model Sources
235
+
236
+ - **Documentation:** [Sentence Transformers Documentation](https://sbert.net)
237
+ - **Repository:** [Sentence Transformers on GitHub](https://github.com/UKPLab/sentence-transformers)
238
+ - **Hugging Face:** [Sentence Transformers on Hugging Face](https://huggingface.co/models?library=sentence-transformers)
239
+
240
+ ### Full Model Architecture
241
+
242
+ ```
243
+ SentenceTransformer(
244
+ (0): Transformer({'max_seq_length': 128, 'do_lower_case': False}) with Transformer model: DistilBertModel
245
+ (1): Pooling({'word_embedding_dimension': 768, 'pooling_mode_cls_token': False, 'pooling_mode_mean_tokens': True, 'pooling_mode_max_tokens': False, 'pooling_mode_mean_sqrt_len_tokens': False, 'pooling_mode_weightedmean_tokens': False, 'pooling_mode_lasttoken': False, 'include_prompt': True})
246
+ )
247
+ ```
248
+
249
+ ## Usage
250
+
251
+ ### Direct Usage (Sentence Transformers)
252
+
253
+ First install the Sentence Transformers library:
254
+
255
+ ```bash
256
+ pip install -U sentence-transformers
257
+ ```
258
+
259
+ Then you can load this model and run inference.
260
+ ```python
261
+ from sentence_transformers import SentenceTransformer
262
+
263
+ # Download from the 🤗 Hub
264
+ model = SentenceTransformer("sentence_transformers_model_id")
265
+ # Run inference
266
+ sentences = [
267
+ 'Design 170:\n Description: The design of the CSS Zen Garden is exemplary with its soothing blue tones, providing a calm and professional aesthetic. The heart icons add a touch of creativity and warmth. The layout is clean and well-structured with clear navigation on the right-hand side, providing users easy access to additional information and style sheets. The typography varies, highlighting key sections and maintaining readability throughout.\n Categories: Web Design, CSS Showcase, Typography, User Interface, Aesthetic\n Visual Characteristics: Soothing Color Palette, Structured Layout, Iconography, Hierarchical Typography, Calming Aesthetic',
268
+ 'Design 143:\n Description: This design features a clean and structured layout with a monochromatic color scheme, highlighting text content with clear typographic hierarchy. A combination of minimalist aesthetic and functional design elements ensures readability and visual interest, while the central image adds a focal point. The use of borders and shadow effects provide depth to the overall design.\n Categories: Minimalism, Monochrome, Typography, Web Design, User Interface\n Visual Characteristics: Clear typographic hierarchy, Grid alignment, Monochromatic color scheme, Minimalist style, Use of borders, Shadow effects',
269
+ 'Design 194:\n Description: This design exudes a minimalist elegance with a muted, earthy color palette and a clean layout, embodying a sense of calm and sophistication. The subtle use of textures and classic serif typography enhances the refined aesthetic, while the centered alignment and generous spacing contribute to a relaxed readability. The incorporation of a delicate floral illustration adds a touch of organic charm, making the design feel both timeless and inviting.\n Categories: Minimalism, Elegant, Organic, Sophisticated, Classic\n Visual Characteristics: Muted Color Palette, Serif Typography, Centered Layout, Generous Spacing, Floral Illustration',
270
+ ]
271
+ embeddings = model.encode(sentences)
272
+ print(embeddings.shape)
273
+ # [3, 768]
274
+
275
+ # Get the similarity scores for the embeddings
276
+ similarities = model.similarity(embeddings, embeddings)
277
+ print(similarities.shape)
278
+ # [3, 3]
279
+ ```
280
+
281
+ <!--
282
+ ### Direct Usage (Transformers)
283
+
284
+ <details><summary>Click to see the direct usage in Transformers</summary>
285
+
286
+ </details>
287
+ -->
288
+
289
+ <!--
290
+ ### Downstream Usage (Sentence Transformers)
291
+
292
+ You can finetune this model on your own dataset.
293
+
294
+ <details><summary>Click to expand</summary>
295
+
296
+ </details>
297
+ -->
298
+
299
+ <!--
300
+ ### Out-of-Scope Use
301
+
302
+ *List how the model may foreseeably be misused and address what users ought not to do with the model.*
303
+ -->
304
+
305
+ ## Evaluation
306
+
307
+ ### Metrics
308
+
309
+ #### Semantic Similarity
310
+
311
+ * Evaluated with [<code>EmbeddingSimilarityEvaluator</code>](https://sbert.net/docs/package_reference/sentence_transformer/evaluation.html#sentence_transformers.evaluation.EmbeddingSimilarityEvaluator)
312
+
313
+ | Metric | Value |
314
+ |:--------------------|:------------|
315
+ | pearson_cosine | -0.1396 |
316
+ | **spearman_cosine** | **-0.0686** |
317
+
318
+ <!--
319
+ ## Bias, Risks and Limitations
320
+
321
+ *What are the known or foreseeable issues stemming from this model? You could also flag here known failure cases or weaknesses of the model.*
322
+ -->
323
+
324
+ <!--
325
+ ### Recommendations
326
+
327
+ *What are recommendations with respect to the foreseeable issues? For example, filtering explicit content.*
328
+ -->
329
+
330
+ ## Training Details
331
+
332
+ ### Training Dataset
333
+
334
+ #### Unnamed Dataset
335
+
336
+ * Size: 95 training samples
337
+ * Columns: <code>sentence_0</code>, <code>sentence_1</code>, and <code>label</code>
338
+ * Approximate statistics based on the first 95 samples:
339
+ | | sentence_0 | sentence_1 | label |
340
+ |:--------|:-------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------|:----------------------------------------------------------------|
341
+ | type | string | string | float |
342
+ | details | <ul><li>min: 90 tokens</li><li>mean: 116.28 tokens</li><li>max: 128 tokens</li></ul> | <ul><li>min: 90 tokens</li><li>mean: 115.79 tokens</li><li>max: 128 tokens</li></ul> | <ul><li>min: 0.21</li><li>mean: 0.26</li><li>max: 0.5</li></ul> |
343
+ * Samples:
344
+ | sentence_0 | sentence_1 | label |
345
+ |:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:---------------------------------|
346
+ | <code>Design 148:<br> Description: This visual design features a clean and minimalistic layout with an emphasis on typography and balanced spacing. The dark gray background contrasts with the white text elements, providing a modern and sophisticated look. The design also includes vertical lines and a sidebar to separate different sections, adding structure without cluttering the visual flow.<br> Categories: minimalism, typography, contrast, layout design, modern aesthetics<br> Visual Characteristics: high contrast, monochromatic palette, well-defined spacing, balanced composition, structured layout</code> | <code>Design 156:<br> Description: The design uses a bold, contrasting color palette dominated by red, black, and white, highlighting a silhouetted figure against a background with traditional Japanese elements. The typography is clear and has a balance between serif and sans-serif fonts, adding to the mix of modern and traditional aesthetics. The layout is clean, with sections distinctly separated by subtle gradients, providing a sense of order and cohesiveness. The overall tone is a blend of contemporary design with cultural nuances, making it both engaging and visually striking.<br> Categories: modern design, cultural elements, typography, minimalism, contrast<br> Visual Characteristics: bold color palette, silhouette, gradients, clean layout, traditional motifs</code> | <code>0.21428571428571427</code> |
347
+ | <code>Design 135:<br> Description: This design uses an elegant and traditional aesthetic, with a muted color palette featuring cream and terracotta tones. The use of a patterned background adds texture, while the vertical layout and serif typography provide a classic and sophisticated feel. The design balances text-heavy content with organized sections, making information easily accessible, and its ornate flourishes add a touch of refinement.<br> Categories: Traditional, Elegant, Text-Heavy, Classic<br> Visual Characteristics: Muted Color Palette, Vertical Layout, Serif Typography, Textured Background, Ornate Flourishes</code> | <code>Design 194:<br> Description: This design exudes a minimalist elegance with a muted, earthy color palette and a clean layout, embodying a sense of calm and sophistication. The subtle use of textures and classic serif typography enhances the refined aesthetic, while the centered alignment and generous spacing contribute to a relaxed readability. The incorporation of a delicate floral illustration adds a touch of organic charm, making the design feel both timeless and inviting.<br> Categories: Minimalism, Elegant, Organic, Sophisticated, Classic<br> Visual Characteristics: Muted Color Palette, Serif Typography, Centered Layout, Generous Spacing, Floral Illustration</code> | <code>0.26785714285714285</code> |
348
+ | <code>Design 130:<br> Description: The visual design features a clean and structured layout with a calming color palette of beige and blue, enhancing readability and ease of navigation. The use of different font styles for headings and body text provides a clear hierarchy, while the sidebar offers easy access to additional resources and options. This design exudes professionalism, making it suitable for educational or informational purposes.<br> Categories: Informational, Educational, Professional, Web Design, User Interface<br> Visual Characteristics: Calming color palette, Structured layout, Clear typography, Sidebar navigation, Minimalist design</code> | <code>Design 215:<br> Description: The CSS Zen Garden design showcases a clean, structured layout aimed at demonstrating the possibilities of CSS styling. It uses a primarily blue and white color palette with red accents to draw attention to headings and separators. The design incorporates a formal serif and a modern sans-serif typography, creating an elegant and readable interface. The use of graphical illustrations adds visual interest and helps convey the collaborative and creative theme. The overall aesthetic balance, combined with functional elements like navigation, ensures a clear and engaging user experience.<br> Categories: Typography, User Interface, Minimalist Design, Educational, Professional, Web Design<br> Visual Characteristics: Blue and White Palette, Elegant Typography, Illustrative Graphics, Clean Layout, Contrasting Accents, Symmetry</code> | <code>0.2857142857142857</code> |
349
+ * Loss: [<code>CosineSimilarityLoss</code>](https://sbert.net/docs/package_reference/sentence_transformer/losses.html#cosinesimilarityloss) with these parameters:
350
+ ```json
351
+ {
352
+ "loss_fct": "torch.nn.modules.loss.MSELoss"
353
+ }
354
+ ```
355
+
356
+ ### Training Hyperparameters
357
+ #### Non-Default Hyperparameters
358
+
359
+ - `per_device_train_batch_size`: 16
360
+ - `per_device_eval_batch_size`: 16
361
+ - `num_train_epochs`: 1
362
+ - `multi_dataset_batch_sampler`: round_robin
363
+
364
+ #### All Hyperparameters
365
+ <details><summary>Click to expand</summary>
366
+
367
+ - `overwrite_output_dir`: False
368
+ - `do_predict`: False
369
+ - `eval_strategy`: no
370
+ - `prediction_loss_only`: True
371
+ - `per_device_train_batch_size`: 16
372
+ - `per_device_eval_batch_size`: 16
373
+ - `per_gpu_train_batch_size`: None
374
+ - `per_gpu_eval_batch_size`: None
375
+ - `gradient_accumulation_steps`: 1
376
+ - `eval_accumulation_steps`: None
377
+ - `torch_empty_cache_steps`: None
378
+ - `learning_rate`: 5e-05
379
+ - `weight_decay`: 0.0
380
+ - `adam_beta1`: 0.9
381
+ - `adam_beta2`: 0.999
382
+ - `adam_epsilon`: 1e-08
383
+ - `max_grad_norm`: 1
384
+ - `num_train_epochs`: 1
385
+ - `max_steps`: -1
386
+ - `lr_scheduler_type`: linear
387
+ - `lr_scheduler_kwargs`: {}
388
+ - `warmup_ratio`: 0.0
389
+ - `warmup_steps`: 0
390
+ - `log_level`: passive
391
+ - `log_level_replica`: warning
392
+ - `log_on_each_node`: True
393
+ - `logging_nan_inf_filter`: True
394
+ - `save_safetensors`: True
395
+ - `save_on_each_node`: False
396
+ - `save_only_model`: False
397
+ - `restore_callback_states_from_checkpoint`: False
398
+ - `no_cuda`: False
399
+ - `use_cpu`: False
400
+ - `use_mps_device`: False
401
+ - `seed`: 42
402
+ - `data_seed`: None
403
+ - `jit_mode_eval`: False
404
+ - `use_ipex`: False
405
+ - `bf16`: False
406
+ - `fp16`: False
407
+ - `fp16_opt_level`: O1
408
+ - `half_precision_backend`: auto
409
+ - `bf16_full_eval`: False
410
+ - `fp16_full_eval`: False
411
+ - `tf32`: None
412
+ - `local_rank`: 0
413
+ - `ddp_backend`: None
414
+ - `tpu_num_cores`: None
415
+ - `tpu_metrics_debug`: False
416
+ - `debug`: []
417
+ - `dataloader_drop_last`: False
418
+ - `dataloader_num_workers`: 0
419
+ - `dataloader_prefetch_factor`: None
420
+ - `past_index`: -1
421
+ - `disable_tqdm`: False
422
+ - `remove_unused_columns`: True
423
+ - `label_names`: None
424
+ - `load_best_model_at_end`: False
425
+ - `ignore_data_skip`: False
426
+ - `fsdp`: []
427
+ - `fsdp_min_num_params`: 0
428
+ - `fsdp_config`: {'min_num_params': 0, 'xla': False, 'xla_fsdp_v2': False, 'xla_fsdp_grad_ckpt': False}
429
+ - `fsdp_transformer_layer_cls_to_wrap`: None
430
+ - `accelerator_config`: {'split_batches': False, 'dispatch_batches': None, 'even_batches': True, 'use_seedable_sampler': True, 'non_blocking': False, 'gradient_accumulation_kwargs': None}
431
+ - `deepspeed`: None
432
+ - `label_smoothing_factor`: 0.0
433
+ - `optim`: adamw_torch
434
+ - `optim_args`: None
435
+ - `adafactor`: False
436
+ - `group_by_length`: False
437
+ - `length_column_name`: length
438
+ - `ddp_find_unused_parameters`: None
439
+ - `ddp_bucket_cap_mb`: None
440
+ - `ddp_broadcast_buffers`: False
441
+ - `dataloader_pin_memory`: True
442
+ - `dataloader_persistent_workers`: False
443
+ - `skip_memory_metrics`: True
444
+ - `use_legacy_prediction_loop`: False
445
+ - `push_to_hub`: False
446
+ - `resume_from_checkpoint`: None
447
+ - `hub_model_id`: None
448
+ - `hub_strategy`: every_save
449
+ - `hub_private_repo`: None
450
+ - `hub_always_push`: False
451
+ - `gradient_checkpointing`: False
452
+ - `gradient_checkpointing_kwargs`: None
453
+ - `include_inputs_for_metrics`: False
454
+ - `include_for_metrics`: []
455
+ - `eval_do_concat_batches`: True
456
+ - `fp16_backend`: auto
457
+ - `push_to_hub_model_id`: None
458
+ - `push_to_hub_organization`: None
459
+ - `mp_parameters`:
460
+ - `auto_find_batch_size`: False
461
+ - `full_determinism`: False
462
+ - `torchdynamo`: None
463
+ - `ray_scope`: last
464
+ - `ddp_timeout`: 1800
465
+ - `torch_compile`: False
466
+ - `torch_compile_backend`: None
467
+ - `torch_compile_mode`: None
468
+ - `dispatch_batches`: None
469
+ - `split_batches`: None
470
+ - `include_tokens_per_second`: False
471
+ - `include_num_input_tokens_seen`: False
472
+ - `neftune_noise_alpha`: None
473
+ - `optim_target_modules`: None
474
+ - `batch_eval_metrics`: False
475
+ - `eval_on_start`: False
476
+ - `use_liger_kernel`: False
477
+ - `eval_use_gather_object`: False
478
+ - `average_tokens_across_devices`: False
479
+ - `prompts`: None
480
+ - `batch_sampler`: batch_sampler
481
+ - `multi_dataset_batch_sampler`: round_robin
482
+
483
+ </details>
484
+
485
+ ### Training Logs
486
+ | Epoch | Step | spearman_cosine |
487
+ |:-----:|:----:|:---------------:|
488
+ | 1.0 | 6 | -0.0686 |
489
+
490
+
491
+ ### Framework Versions
492
+ - Python: 3.11.11
493
+ - Sentence Transformers: 3.4.1
494
+ - Transformers: 4.49.0
495
+ - PyTorch: 2.1.2
496
+ - Accelerate: 1.4.0
497
+ - Datasets: 3.3.2
498
+ - Tokenizers: 0.21.0
499
+
500
+ ## Citation
501
+
502
+ ### BibTeX
503
+
504
+ #### Sentence Transformers
505
+ ```bibtex
506
+ @inproceedings{reimers-2019-sentence-bert,
507
+ title = "Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks",
508
+ author = "Reimers, Nils and Gurevych, Iryna",
509
+ booktitle = "Proceedings of the 2019 Conference on Empirical Methods in Natural Language Processing",
510
+ month = "11",
511
+ year = "2019",
512
+ publisher = "Association for Computational Linguistics",
513
+ url = "https://arxiv.org/abs/1908.10084",
514
+ }
515
+ ```
516
+
517
+ <!--
518
+ ## Glossary
519
+
520
+ *Clearly define terms in order to be accessible across audiences.*
521
+ -->
522
+
523
+ <!--
524
+ ## Model Card Authors
525
+
526
+ *Lists the people who create the model card, providing recognition and accountability for the detailed work that goes into its construction.*
527
+ -->
528
+
529
+ <!--
530
+ ## Model Card Contact
531
+
532
+ *Provides a way for people who have updates to the Model Card, suggestions, or questions, to contact the Model Card authors.*
533
+ -->
src/fine_tuned_design_embeddings_20250225_161918/config.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_name_or_path": "sentence-transformers/distilbert-base-nli-stsb-mean-tokens",
3
+ "activation": "gelu",
4
+ "architectures": [
5
+ "DistilBertModel"
6
+ ],
7
+ "attention_dropout": 0.1,
8
+ "dim": 768,
9
+ "dropout": 0.1,
10
+ "hidden_dim": 3072,
11
+ "initializer_range": 0.02,
12
+ "max_position_embeddings": 512,
13
+ "model_type": "distilbert",
14
+ "n_heads": 12,
15
+ "n_layers": 6,
16
+ "pad_token_id": 0,
17
+ "qa_dropout": 0.1,
18
+ "seq_classif_dropout": 0.2,
19
+ "sinusoidal_pos_embds": false,
20
+ "tie_weights_": true,
21
+ "torch_dtype": "float32",
22
+ "transformers_version": "4.49.0",
23
+ "vocab_size": 30522
24
+ }
src/fine_tuned_design_embeddings_20250225_161918/config_sentence_transformers.json ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "__version__": {
3
+ "sentence_transformers": "3.4.1",
4
+ "transformers": "4.49.0",
5
+ "pytorch": "2.1.2"
6
+ },
7
+ "prompts": {},
8
+ "default_prompt_name": null,
9
+ "similarity_fn_name": "cosine"
10
+ }
src/fine_tuned_design_embeddings_20250225_161918/eval/similarity_evaluation_results.csv ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ epoch,steps,cosine_pearson,cosine_spearman
2
+ 1.0,6,-0.13960523700017818,-0.06863870136546027
src/fine_tuned_design_embeddings_20250225_161918/modules.json ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "idx": 0,
4
+ "name": "0",
5
+ "path": "",
6
+ "type": "sentence_transformers.models.Transformer"
7
+ },
8
+ {
9
+ "idx": 1,
10
+ "name": "1",
11
+ "path": "1_Pooling",
12
+ "type": "sentence_transformers.models.Pooling"
13
+ }
14
+ ]
src/fine_tuned_design_embeddings_20250225_161918/sentence_bert_config.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "max_seq_length": 128,
3
+ "do_lower_case": false
4
+ }
src/fine_tuned_design_embeddings_20250225_161918/special_tokens_map.json ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cls_token": {
3
+ "content": "[CLS]",
4
+ "lstrip": false,
5
+ "normalized": false,
6
+ "rstrip": false,
7
+ "single_word": false
8
+ },
9
+ "mask_token": {
10
+ "content": "[MASK]",
11
+ "lstrip": false,
12
+ "normalized": false,
13
+ "rstrip": false,
14
+ "single_word": false
15
+ },
16
+ "pad_token": {
17
+ "content": "[PAD]",
18
+ "lstrip": false,
19
+ "normalized": false,
20
+ "rstrip": false,
21
+ "single_word": false
22
+ },
23
+ "sep_token": {
24
+ "content": "[SEP]",
25
+ "lstrip": false,
26
+ "normalized": false,
27
+ "rstrip": false,
28
+ "single_word": false
29
+ },
30
+ "unk_token": {
31
+ "content": "[UNK]",
32
+ "lstrip": false,
33
+ "normalized": false,
34
+ "rstrip": false,
35
+ "single_word": false
36
+ }
37
+ }
src/fine_tuned_design_embeddings_20250225_161918/tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
src/fine_tuned_design_embeddings_20250225_161918/tokenizer_config.json ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "added_tokens_decoder": {
3
+ "0": {
4
+ "content": "[PAD]",
5
+ "lstrip": false,
6
+ "normalized": false,
7
+ "rstrip": false,
8
+ "single_word": false,
9
+ "special": true
10
+ },
11
+ "100": {
12
+ "content": "[UNK]",
13
+ "lstrip": false,
14
+ "normalized": false,
15
+ "rstrip": false,
16
+ "single_word": false,
17
+ "special": true
18
+ },
19
+ "101": {
20
+ "content": "[CLS]",
21
+ "lstrip": false,
22
+ "normalized": false,
23
+ "rstrip": false,
24
+ "single_word": false,
25
+ "special": true
26
+ },
27
+ "102": {
28
+ "content": "[SEP]",
29
+ "lstrip": false,
30
+ "normalized": false,
31
+ "rstrip": false,
32
+ "single_word": false,
33
+ "special": true
34
+ },
35
+ "103": {
36
+ "content": "[MASK]",
37
+ "lstrip": false,
38
+ "normalized": false,
39
+ "rstrip": false,
40
+ "single_word": false,
41
+ "special": true
42
+ }
43
+ },
44
+ "clean_up_tokenization_spaces": false,
45
+ "cls_token": "[CLS]",
46
+ "do_basic_tokenize": true,
47
+ "do_lower_case": true,
48
+ "extra_special_tokens": {},
49
+ "full_tokenizer_file": null,
50
+ "mask_token": "[MASK]",
51
+ "model_max_length": 128,
52
+ "never_split": null,
53
+ "pad_token": "[PAD]",
54
+ "sep_token": "[SEP]",
55
+ "strip_accents": null,
56
+ "tokenize_chinese_chars": true,
57
+ "tokenizer_class": "DistilBertTokenizer",
58
+ "unk_token": "[UNK]"
59
+ }
src/fine_tuned_design_embeddings_20250225_161918/vocab.txt ADDED
The diff for this file is too large to render. See raw diff
 
uv.lock CHANGED
@@ -1,6 +1,24 @@
1
  version = 1
2
  requires-python = "==3.11.*"
3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  [[package]]
5
  name = "aiofiles"
6
  version = "23.2.1"
@@ -834,6 +852,7 @@ name = "imagineui"
834
  version = "0.1.0"
835
  source = { editable = "." }
836
  dependencies = [
 
837
  { name = "beautifulsoup4" },
838
  { name = "chainlit" },
839
  { name = "datasets" },
@@ -847,6 +866,7 @@ dependencies = [
847
  { name = "langgraph" },
848
  { name = "langsmith" },
849
  { name = "matplotlib" },
 
850
  { name = "notebook" },
851
  { name = "numpy" },
852
  { name = "openai" },
@@ -865,6 +885,7 @@ dependencies = [
865
 
866
  [package.metadata]
867
  requires-dist = [
 
868
  { name = "beautifulsoup4", specifier = ">=4.12.0" },
869
  { name = "chainlit", specifier = ">=0.7.700" },
870
  { name = "datasets", specifier = ">=2.17.0" },
@@ -878,6 +899,7 @@ requires-dist = [
878
  { name = "langgraph", specifier = ">=0.0.19" },
879
  { name = "langsmith", specifier = ">=0.3.11" },
880
  { name = "matplotlib", specifier = ">=3.10.0" },
 
881
  { name = "notebook" },
882
  { name = "numpy", specifier = ">=1.26.0" },
883
  { name = "openai", specifier = ">=1.63.2,<2.0.0" },
 
1
  version = 1
2
  requires-python = "==3.11.*"
3
 
4
+ [[package]]
5
+ name = "accelerate"
6
+ version = "1.4.0"
7
+ source = { registry = "https://pypi.org/simple" }
8
+ dependencies = [
9
+ { name = "huggingface-hub" },
10
+ { name = "numpy" },
11
+ { name = "packaging" },
12
+ { name = "psutil" },
13
+ { name = "pyyaml" },
14
+ { name = "safetensors" },
15
+ { name = "torch" },
16
+ ]
17
+ sdist = { url = "https://files.pythonhosted.org/packages/8f/02/24a4c4edb9cf0f1e0bc32bb6829e2138f1cc201442e7a24f0daf93b8a15a/accelerate-1.4.0.tar.gz", hash = "sha256:37d413e1b64cb8681ccd2908ae211cf73e13e6e636a2f598a96eccaa538773a5", size = 348745 }
18
+ wheels = [
19
+ { url = "https://files.pythonhosted.org/packages/0a/f6/791b9d7eb371a2f385da3b7f1769ced72ead7bf09744637ea2985c83d7ee/accelerate-1.4.0-py3-none-any.whl", hash = "sha256:f6e1e7dfaf9d799a20a1dc45efbf4b1546163eac133faa5acd0d89177c896e55", size = 342129 },
20
+ ]
21
+
22
  [[package]]
23
  name = "aiofiles"
24
  version = "23.2.1"
 
852
  version = "0.1.0"
853
  source = { editable = "." }
854
  dependencies = [
855
+ { name = "accelerate" },
856
  { name = "beautifulsoup4" },
857
  { name = "chainlit" },
858
  { name = "datasets" },
 
866
  { name = "langgraph" },
867
  { name = "langsmith" },
868
  { name = "matplotlib" },
869
+ { name = "nest-asyncio" },
870
  { name = "notebook" },
871
  { name = "numpy" },
872
  { name = "openai" },
 
885
 
886
  [package.metadata]
887
  requires-dist = [
888
+ { name = "accelerate", specifier = ">=0.26.0" },
889
  { name = "beautifulsoup4", specifier = ">=4.12.0" },
890
  { name = "chainlit", specifier = ">=0.7.700" },
891
  { name = "datasets", specifier = ">=2.17.0" },
 
899
  { name = "langgraph", specifier = ">=0.0.19" },
900
  { name = "langsmith", specifier = ">=0.3.11" },
901
  { name = "matplotlib", specifier = ">=3.10.0" },
902
+ { name = "nest-asyncio", specifier = ">=1.6.0" },
903
  { name = "notebook" },
904
  { name = "numpy", specifier = ">=1.26.0" },
905
  { name = "openai", specifier = ">=1.63.2,<2.0.0" },