Adrian Gabriel commited on
Commit
689b46a
·
1 Parent(s): 0629791

latest changs

Browse files
Files changed (4) hide show
  1. Dockerfile +8 -10
  2. instrumentation.py +14 -2
  3. requirements.txt +4 -0
  4. static/index.html +54 -5
Dockerfile CHANGED
@@ -1,25 +1,23 @@
1
- # Use the official lightweight Python image
2
  FROM python:3.9-slim
3
 
4
- # Set the working directory inside the container
5
  WORKDIR /code
6
 
7
- # 1. Copy requirements first (for better caching)
 
8
  COPY ./requirements.txt /code/requirements.txt
9
-
10
- # 2. Install dependencies
11
- # We use --no-cache-dir to keep the image small
12
  RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
13
 
14
- # 3. Copy the rest of the application code
15
  COPY . /code
16
 
17
- # 4. Create a non-root user (Security Best Practice for HF Spaces)
18
  RUN useradd -m -u 1000 user
19
  USER user
20
  ENV HOME=/home/user \
21
  PATH=/home/user/.local/bin:$PATH
22
 
23
- # 5. Define the command to run the app
24
- # IMPORTANT: Hugging Face expects port 7860, not 8000!
25
  CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
 
1
+ # Use Python 3.9
2
  FROM python:3.9-slim
3
 
4
+ # Set working directory
5
  WORKDIR /code
6
 
7
+ # 1. Install dependencies
8
+ # We copy requirements first to cache them effectively
9
  COPY ./requirements.txt /code/requirements.txt
 
 
 
10
  RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
11
 
12
+ # 2. Copy the rest of the application
13
  COPY . /code
14
 
15
+ # 3. Security: Create a non-root user (Required for HF Spaces)
16
  RUN useradd -m -u 1000 user
17
  USER user
18
  ENV HOME=/home/user \
19
  PATH=/home/user/.local/bin:$PATH
20
 
21
+ # 4. Run the application
22
+ # IMPORTANT: Hugging Face listens on port 7860 by default!
23
  CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
instrumentation.py CHANGED
@@ -123,9 +123,21 @@ class Instrumentor:
123
  # Get the layer name
124
  layer_name = instance.__class__.__name__
125
 
126
- # Emit op event for the layer
 
127
  meta = {'layer_type': layer_name}
128
- instrumentor.tracer.op(layer_name.lower(), [x], result, meta)
 
 
 
 
 
 
 
 
 
 
 
129
 
130
  return result
131
 
 
123
  # Get the layer name
124
  layer_name = instance.__class__.__name__
125
 
126
+ # Build inputs list - for Linear, include weight and bias
127
+ inputs = [x]
128
  meta = {'layer_type': layer_name}
129
+
130
+ # For Linear layers, include weight and bias for visualization
131
+ if layer_name == 'Linear':
132
+ if hasattr(instance, 'weight'):
133
+ inputs.append(instance.weight)
134
+ meta['has_weight'] = True
135
+ if hasattr(instance, 'bias') and instance.bias is not None:
136
+ inputs.append(instance.bias)
137
+ meta['has_bias'] = True
138
+
139
+ # Emit op event for the layer
140
+ instrumentor.tracer.op(layer_name.lower(), inputs, result, meta)
141
 
142
  return result
143
 
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ numpy
4
+ # Add any other libraries you import in your python code
static/index.html CHANGED
@@ -204,16 +204,17 @@
204
  min-width: 50px;
205
  }
206
 
207
- .layout-grid { gap: 10px; } /* display: inline-grid set above */
208
  .layout-binary {
209
  grid-template-columns: auto auto;
210
  grid-template-rows: auto auto;
211
- gap: 12px;
212
  }
213
  .layout-unary { grid-template-columns: auto; }
214
- .pos-left { grid-row: 1 / 3; grid-column: 1; align-self: center; }
215
- .pos-top { grid-row: 1; grid-column: 2; }
216
- .pos-result { grid-row: 2; grid-column: 2; }
 
217
 
218
  /* Element-wise operation layout: inputs side by side, result below left */
219
  .layout-elementwise {
@@ -234,6 +235,18 @@
234
  padding: 0 8px;
235
  user-select: none;
236
  }
 
 
 
 
 
 
 
 
 
 
 
 
237
 
238
  /* TOOLBAR */
239
  #toolbar {
@@ -1352,6 +1365,7 @@ box("Loss Computation", [y_pred, target_probs, loss], "6")
1352
  const isElementwise = ['add', 'sub', 'mul', 'div'].includes(type) && inputs.length >= 2;
1353
  const isMatmul = type === 'matmul' && inputs.length >= 2;
1354
  const isLoss = ['mseloss', 'crossentropyloss', 'bceloss'].includes(type) && inputs.length >= 2;
 
1355
 
1356
  // Determine output orientation for reduction operations
1357
  let outputOrientation = 'auto';
@@ -1434,6 +1448,41 @@ box("Loss Computation", [y_pred, target_probs, loss], "6")
1434
  return;
1435
  }
1436
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1437
  if (isMatmul) {
1438
  // Matrix multiplication: keep grid layout for proper alignment
1439
  const grid = document.createElement('div');
 
204
  min-width: 50px;
205
  }
206
 
207
+ .layout-grid { gap: 8px; } /* display: inline-grid set above */
208
  .layout-binary {
209
  grid-template-columns: auto auto;
210
  grid-template-rows: auto auto;
211
+ gap: 8px;
212
  }
213
  .layout-unary { grid-template-columns: auto; }
214
+ /* Matmul layout: a on left, b on top-right, result on bottom-right */
215
+ .pos-left { grid-row: 2; grid-column: 1; align-self: start; }
216
+ .pos-top { grid-row: 1; grid-column: 2; align-self: end; }
217
+ .pos-result { grid-row: 2; grid-column: 2; align-self: start; }
218
 
219
  /* Element-wise operation layout: inputs side by side, result below left */
220
  .layout-elementwise {
 
235
  padding: 0 8px;
236
  user-select: none;
237
  }
238
+
239
+ /* Linear layer layout: matmul-style with X on top, W on left, result at intersection */
240
+ .layout-linear {
241
+ display: inline-grid;
242
+ grid-template-columns: auto auto;
243
+ grid-template-rows: auto auto;
244
+ gap: 8px;
245
+ }
246
+ .linear-empty { grid-row: 1; grid-column: 1; } /* Empty top-left cell */
247
+ .linear-input { grid-row: 1; grid-column: 2; align-self: end; } /* X on top, aligned to bottom */
248
+ .linear-weight { grid-row: 2; grid-column: 1; align-self: start; } /* W on left, aligned to top */
249
+ .linear-output { grid-row: 2; grid-column: 2; align-self: start; } /* Result aligned to top with W */
250
 
251
  /* TOOLBAR */
252
  #toolbar {
 
1365
  const isElementwise = ['add', 'sub', 'mul', 'div'].includes(type) && inputs.length >= 2;
1366
  const isMatmul = type === 'matmul' && inputs.length >= 2;
1367
  const isLoss = ['mseloss', 'crossentropyloss', 'bceloss'].includes(type) && inputs.length >= 2;
1368
+ const isLinear = type === 'linear' && inputs.length >= 2 && meta?.has_weight;
1369
 
1370
  // Determine output orientation for reduction operations
1371
  let outputOrientation = 'auto';
 
1448
  return;
1449
  }
1450
 
1451
+ if (isLinear) {
1452
+ // Linear layer: show as matmul with bias trick
1453
+ // inputs[0] = x, inputs[1] = weight, inputs[2] = bias (optional)
1454
+ const x = inputs[0];
1455
+ const weight = inputs[1];
1456
+ const bias = inputs.length > 2 ? inputs[2] : null;
1457
+
1458
+ const wrapper = document.createElement('div');
1459
+ wrapper.className = 'layout-linear';
1460
+
1461
+ // Empty cell for top-left (matmul alignment)
1462
+ const emptyCell = document.createElement('div');
1463
+ emptyCell.className = 'linear-empty';
1464
+ wrapper.appendChild(emptyCell);
1465
+
1466
+ // Input X (top-right position, like matmul)
1467
+ const inputCard = createMatrixCard(x.name || 'x', x);
1468
+ inputCard.classList.add('linear-input');
1469
+ wrapper.appendChild(inputCard);
1470
+
1471
+ // Weight matrix (left position)
1472
+ let weightLabel = weight.name || 'W';
1473
+ const weightCard = createMatrixCard(weightLabel, weight);
1474
+ weightCard.classList.add('linear-weight');
1475
+ wrapper.appendChild(weightCard);
1476
+
1477
+ // Output (bottom-right, result of x @ W + b)
1478
+ const outputCard = createMatrixCard(output.name || 'y', output);
1479
+ outputCard.classList.add('linear-output');
1480
+ wrapper.appendChild(outputCard);
1481
+
1482
+ container.appendChild(wrapper);
1483
+ return;
1484
+ }
1485
+
1486
  if (isMatmul) {
1487
  // Matrix multiplication: keep grid layout for proper alignment
1488
  const grid = document.createElement('div');