JohnSupertramp2026 commited on
Commit
ef3d61f
·
verified ·
1 Parent(s): ff110e2

Upload 5 files

Browse files

Portada del proyecto

.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ matriz_confusion_convnext-tiny.png filter=lfs diff=lfs merge=lfs -text
37
+ matriz_confusion_vit-base.png filter=lfs diff=lfs merge=lfs -text
README.md CHANGED
@@ -1,11 +1,49 @@
1
  ---
2
- title: Fitoasistente
3
- emoji: 📉
4
  colorFrom: blue
5
- colorTo: red
6
  sdk: static
 
7
  pinned: false
8
  license: mit
 
9
  ---
10
 
11
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: FitoAsistente
3
+ emoji: 🌿
4
  colorFrom: blue
5
+ colorTo: green
6
  sdk: static
7
+ app_file: index.html
8
  pinned: false
9
  license: mit
10
+ short_description: Diagnostico fitosanitario con ViT, ConvNeXt y VLM
11
  ---
12
 
13
+ # FitoAsistente
14
+
15
+ Proyecto Final de Inteligencia Artificial · Magíster en Data Science, Universidad San Sebastián
16
+ Jonathan Núñez Moya · Francisco Rietta González
17
+
18
+ Asistente multimodal para el diagnóstico fitosanitario de cultivos. Combina dos capacidades
19
+ distintas de modelos fundacionales de Hugging Face:
20
+
21
+ | Tarea | Modelos | Entrenamiento |
22
+ |---|---|---|
23
+ | `image-classification` | ViT-Base/16, ConvNeXt-Tiny | Fine-tuning sobre PlantVillage, 38 clases |
24
+ | `image-text-to-text` | SmolVLM-256M-Instruct | Zero-shot |
25
+
26
+ ## Modelos publicados
27
+
28
+ - https://huggingface.co/JohnSupertramp2026/vit-base-plantvillage
29
+ - https://huggingface.co/JohnSupertramp2026/convnext-tiny-plantvillage
30
+
31
+ ## Sobre este despliegue
32
+
33
+ Desde julio de 2026 las cuentas gratuitas de Hugging Face solo pueden crear Spaces de tipo
34
+ Static; los de tipo Gradio requieren plan PRO
35
+ ([foro oficial](https://discuss.huggingface.co/t/gradio-sdk-now-marked-as-paid-when-creating-a-new-space/177619)).
36
+
37
+ Por eso este Space aloja la portada del proyecto y la aplicación Gradio se ejecuta desde un
38
+ cuaderno de Google Colab, que publica una dirección pública con `share=True`. El código de la
39
+ interfaz es el mismo en ambos casos.
40
+
41
+ ## Cómo actualizar la dirección de la aplicación
42
+
43
+ En `index.html`, al final del archivo, cambia la constante:
44
+
45
+ ```js
46
+ const URL_APP = "https://xxxxxxxx.gradio.live";
47
+ ```
48
+
49
+ Si queda vacía, el botón se muestra desactivado con una explicación.
curvas_entrenamiento.png ADDED
index.html CHANGED
@@ -1,19 +1,244 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </html>
 
1
+ <!DOCTYPE html>
2
+ <html lang="es">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>FitoAsistente · Universidad San Sebastián</title>
7
+ <style>
8
+ :root{
9
+ --navy:#052A4A; --navy2:#0C3A5E; --blue:#297FD5; --teal:#00949D;
10
+ --steel:#435D74; --gold:#C0A264; --gray:#606163; --bg:#F7F9FC;
11
+ --card:#FFFFFF; --line:#DCE7F3;
12
+ }
13
+ *{box-sizing:border-box}
14
+ body{
15
+ margin:0; background:var(--bg); color:var(--gray);
16
+ font-family:Calibri,"Segoe UI",system-ui,-apple-system,sans-serif;
17
+ line-height:1.6; font-size:16px;
18
+ }
19
+ a{color:var(--blue); text-decoration:none}
20
+ a:hover{text-decoration:underline}
21
+ .wrap{max-width:960px; margin:0 auto; padding:0 24px}
22
+
23
+ header{background:var(--navy); color:#fff; padding:48px 0 40px}
24
+ header .eyebrow{
25
+ font-size:12px; letter-spacing:.14em; text-transform:uppercase;
26
+ color:#8FB4CE; font-weight:700; margin-bottom:18px;
27
+ }
28
+ header h1{margin:0 0 6px; font-size:46px; font-weight:700; letter-spacing:-.5px}
29
+ header .sub{font-size:19px; color:#C9DCEA; margin:0 0 26px; max-width:620px}
30
+ header .rule{height:3px; width:88px; background:var(--gold); margin-bottom:24px}
31
+ header .meta{font-size:14px; color:#A9C4D6}
32
+
33
+ .cta{
34
+ display:inline-block; background:var(--gold); color:var(--navy);
35
+ font-weight:700; padding:13px 26px; border-radius:6px; margin:6px 10px 6px 0;
36
+ font-size:16px;
37
+ }
38
+ .cta:hover{background:#D0B478; text-decoration:none}
39
+ .cta.ghost{background:transparent; color:#C9DCEA; border:1px solid #3C6484}
40
+ .cta.ghost:hover{background:#0C3A5E}
41
+
42
+ section{padding:44px 0; border-bottom:1px solid var(--line)}
43
+ section:last-of-type{border-bottom:none}
44
+ h2{color:var(--navy); font-size:27px; margin:0 0 6px; font-weight:700}
45
+ h2 + .lead{color:var(--steel); font-style:italic; margin:0 0 22px}
46
+ h3{color:var(--teal); font-size:18px; margin:26px 0 8px; font-weight:700}
47
+
48
+ .aviso{
49
+ background:#FFF8E8; border:1px solid #E8D9AE; border-left:4px solid var(--gold);
50
+ border-radius:6px; padding:18px 22px; margin:26px 0;
51
+ }
52
+ .aviso strong{color:var(--navy)}
53
+
54
+ .cards{display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:16px; margin-top:20px}
55
+ .card{background:var(--card); border:1px solid var(--line); border-radius:8px; padding:20px 22px}
56
+ .card h4{margin:0 0 4px; color:var(--navy); font-size:17px}
57
+ .card .tag{
58
+ display:inline-block; font-size:11px; letter-spacing:.09em; text-transform:uppercase;
59
+ color:var(--teal); font-weight:700; margin-bottom:8px;
60
+ }
61
+ .card p{margin:0; font-size:14.5px}
62
+ .card .big{font-size:30px; font-weight:700; color:var(--teal); line-height:1.2}
63
+
64
+ table{width:100%; border-collapse:collapse; margin:18px 0 6px; background:var(--card); font-size:14.5px}
65
+ th{background:var(--navy); color:#fff; text-align:left; padding:11px 13px; font-weight:700}
66
+ th:not(:first-child), td:not(:first-child){text-align:center}
67
+ td{padding:10px 13px; border-bottom:1px solid var(--line)}
68
+ tr:nth-child(even) td{background:#F3F8FD}
69
+ .win{color:var(--gold); font-weight:700}
70
+ caption{caption-side:bottom; text-align:left; font-size:13px; font-style:italic; color:var(--steel); padding-top:8px}
71
+
72
+ figure{margin:22px 0}
73
+ figure img{width:100%; border:1px solid var(--line); border-radius:6px; background:#fff}
74
+ figcaption{font-size:13px; font-style:italic; color:var(--steel); margin-top:7px}
75
+ .figpair{display:grid; grid-template-columns:1fr 1fr; gap:16px}
76
+ @media(max-width:700px){.figpair{grid-template-columns:1fr} header h1{font-size:34px}}
77
+
78
+ ul{padding-left:20px} li{margin-bottom:7px}
79
+ code{background:#EDF3FA; padding:2px 6px; border-radius:4px; font-size:13.5px; color:var(--navy)}
80
+
81
+ footer{background:var(--navy); color:#A9C4D6; padding:32px 0; font-size:14px}
82
+ footer a{color:#C9DCEA}
83
+ .gold-bar{height:4px; background:var(--gold)}
84
+ </style>
85
+ </head>
86
+ <body>
87
+
88
+ <header>
89
+ <div class="wrap">
90
+ <div class="eyebrow">Universidad San Sebastián · Facultad de Ingeniería · Magíster en Data Science</div>
91
+ <h1>FitoAsistente</h1>
92
+ <p class="sub">Asistente multimodal para el diagnóstico fitosanitario de cultivos, con modelos fundacionales de Hugging Face.</p>
93
+ <div class="rule"></div>
94
+ <a class="cta" id="btn-app" href="#" target="_blank" rel="noopener">Abrir la aplicación</a>
95
+ <a class="cta ghost" href="https://huggingface.co/JohnSupertramp2026/vit-base-plantvillage" target="_blank" rel="noopener">Modelo ViT</a>
96
+ <a class="cta ghost" href="https://huggingface.co/JohnSupertramp2026/convnext-tiny-plantvillage" target="_blank" rel="noopener">Modelo ConvNeXt</a>
97
+ <p class="meta" style="margin-top:26px">
98
+ Jonathan Núñez Moya · Francisco Rietta González<br>
99
+ Inteligencia Artificial — Prof. Manuel Alejandro Goyo · Agosto de 2026
100
+ </p>
101
+ </div>
102
+ </header>
103
+ <div class="gold-bar"></div>
104
+
105
+ <div class="wrap">
106
+
107
+ <section>
108
+ <h2>Qué hace</h2>
109
+ <p class="lead">Dos capacidades distintas de modelos fundacionales, en una sola aplicación</p>
110
+ <p>Subes la foto de una hoja y el sistema hace dos cosas que no son la misma. La <strong>clasifica</strong> entre 38 categorías fitopatológicas, y por separado <strong>la describe</strong> en lenguaje natural, sin comprometerse con un nombre de enfermedad.</p>
111
+
112
+ <div class="cards">
113
+ <div class="card">
114
+ <span class="tag">Capacidad 1 · image-classification</span>
115
+ <h4>ViT-Base/16 y ConvNeXt-Tiny</h4>
116
+ <p>Ajustados sobre PlantVillage. Devuelven una etiqueta entre 38 clases con su probabilidad. Se pueden ejecutar por separado o comparar lado a lado.</p>
117
+ </div>
118
+ <div class="card">
119
+ <span class="tag">Capacidad 2 · image-text-to-text</span>
120
+ <h4>SmolVLM-256M-Instruct</h4>
121
+ <p>Sin ajustar. Genera texto libre describiendo los síntomas visibles y responde preguntas abiertas sobre la imagen.</p>
122
+ </div>
123
+ </div>
124
+
125
+ <h3>Por qué se necesitan las dos</h3>
126
+ <p>El clasificador es preciso pero cerrado: ante una especie que nunca vio devuelve igual una de sus 38 etiquetas, con alta confianza y sin manera de decir «no sé». El modelo de lenguaje es impreciso pero abierto, y puede describir cualquier hoja. Cuando la descripción no calza con la etiqueta, esa discrepancia es una señal para desconfiar del diagnóstico.</p>
127
+ </section>
128
+
129
+ <section>
130
+ <h2>Resultados</h2>
131
+ <p class="lead">Comparación controlada sobre el conjunto de prueba, usado una sola vez</p>
132
+
133
+ <table>
134
+ <caption>Todas las condiciones idénticas salvo la arquitectura: 20 % estratificado de PlantVillage, partición 80/10/10, semilla 42, 3 épocas, lote 32, learning rate 5e-5, GPU T4.</caption>
135
+ <thead>
136
+ <tr><th>Modelo</th><th>Preentr.</th><th>Parámetros</th><th>Exactitud</th><th>Macro F1</th><th>Weighted F1</th><th>Latencia CPU</th></tr>
137
+ </thead>
138
+ <tbody>
139
+ <tr><td>CNN desde cero <span style="color:#8A93A0">(referencia)</span></td><td>No</td><td>8,49 M</td><td>59,60 %</td><td>0,354</td><td>0,544</td><td>—</td></tr>
140
+ <tr><td><strong>ViT-Base/16</strong></td><td>IN-21k</td><td>85,83 M</td><td class="win">99,08 %</td><td class="win">0,988</td><td class="win">0,991</td><td>395,0 ms</td></tr>
141
+ <tr><td><strong>ConvNeXt-Tiny</strong></td><td>IN-1k</td><td>27,85 M</td><td>96,41 %</td><td>0,919</td><td>0,960</td><td class="win">119,6 ms</td></tr>
142
+ </tbody>
143
+ </table>
144
+
145
+ <div class="cards">
146
+ <div class="card"><div class="big">+63,4 pp</div><p>de macro F1 sobre la red entrenada desde cero, contra +39,5 pp de exactitud</p></div>
147
+ <div class="card"><div class="big">+6,9 pp</div><p>de macro F1 de ViT sobre ConvNeXt, con solo 2,7 pp de diferencia en exactitud</p></div>
148
+ <div class="card"><div class="big">3,3×</div><p>más rápido ConvNeXt en CPU, con un tercio de los parámetros</p></div>
149
+ </div>
150
+
151
+ <h3>Por qué la brecha es tan distinta según la métrica</h3>
152
+ <p>ConvNeXt obtuvo un F1 de <strong>0,000</strong> en <code>Potato___healthy</code>, una clase con solo tres ejemplos en prueba, y <strong>0,182</strong> en <code>Corn___Cercospora_leaf_spot</code>. ViT resolvió las dos por encima de 0,900. Abandonar las clases pequeñas es exactamente el mismo patrón que había mostrado la red entrenada desde cero, y por eso elegimos ViT como modelo por defecto aunque sea más lento.</p>
153
+ <p>Las dos arquitecturas coinciden en tres de sus cinco peores clases. Cuando los dos modelos fallan en lo mismo, la dificultad viene del problema y no del modelo.</p>
154
+
155
+ <div class="figpair">
156
+ <figure><img src="figuras/matriz_confusion_vit-base.png" alt="Matriz de confusión de ViT-Base"><figcaption>Matriz de confusión normalizada — ViT-Base/16</figcaption></figure>
157
+ <figure><img src="figuras/matriz_confusion_convnext-tiny.png" alt="Matriz de confusión de ConvNeXt-Tiny"><figcaption>Matriz de confusión normalizada — ConvNeXt-Tiny</figcaption></figure>
158
+ </div>
159
+ <figure><img src="figuras/curvas_entrenamiento.png" alt="Curvas de entrenamiento"><figcaption>Pérdida y macro F1 de validación. ViT llegó a 0,981 de macro F1 en la primera época; ConvNeXt partió en 0,646 y necesitó las tres para llegar a 0,936.</figcaption></figure>
160
+ </section>
161
+
162
+ <section>
163
+ <h2>Lo que aprendimos del modelo de lenguaje</h2>
164
+ <p class="lead">Un resultado que nos hizo cambiar el diseño de la aplicación</p>
165
+ <p>Probamos tres formas de pedirle lo mismo al modelo de visión y lenguaje, sobre una hoja de duraznero verde, con manchas pardo-rojizas y el borde superior desgarrado.</p>
166
+ <table>
167
+ <thead><tr><th>Formulación</th><th style="text-align:left">Respuesta</th><th style="text-align:left">Observación</th></tr></thead>
168
+ <tbody>
169
+ <tr><td>A · descripción libre</td><td style="text-align:left"><em>«dark green with reddish brown spots… damaged or torn in the middle»</em></td><td style="text-align:left">Correcta. Todo verificable en la imagen.</td></tr>
170
+ <tr><td>B · síntomas guiados</td><td style="text-align:left"><em>«The leaf is brown… dry and appears to be dead»</em></td><td style="text-align:left">Falso: la hoja está verde y turgente.</td></tr>
171
+ <tr><td>C · con contexto</td><td style="text-align:left"><em>«Bacterial spot.»</em></td><td style="text-align:left">Repitió la etiqueta que le entregamos y dejó de describir.</td></tr>
172
+ </tbody>
173
+ </table>
174
+ <p>Habíamos diseñado la aplicación para entregarle al modelo la clase predicha como contexto. Resultó contraproducente: un mecanismo de verificación que recibe la respuesta que debe verificar deja de verificar nada. La aplicación quedó con la instrucción más simple y con el contexto desactivado por defecto, disponible como casilla opcional.</p>
175
+ </section>
176
+
177
+ <section>
178
+ <h2>Limitaciones</h2>
179
+ <p class="lead">Lo que este trabajo no demuestra</p>
180
+ <ul>
181
+ <li><strong>El 99,08 % está inflado.</strong> PlantVillage contiene varias fotografías de la misma hoja física. La versión original trae particiones que preservan ese agrupamiento; nosotros repartimos al azar, así que es probable que fotos de una misma hoja hayan quedado en entrenamiento y en prueba. Infla las tres filas por igual, de modo que la comparación entre modelos sigue siendo válida, pero la cifra no estima el desempeño sobre hojas nuevas.</li>
182
+ <li><strong>Laboratorio, no campo.</strong> Mohanty et al. (2016) documentaron que la exactitud cae al 31 % en fotografías de terreno.</li>
183
+ <li><strong>Tres épocas es poco.</strong> ConvNeXt todavía venía subiendo en la tercera, así que su cifra final subestima su techo.</li>
184
+ <li><strong>Muestras pequeñas.</strong> Varias clases tienen menos de diez ejemplos en prueba y sus F1 individuales son inestables.</li>
185
+ <li><strong>Conjunto cerrado.</strong> El clasificador no tiene mecanismo de rechazo.</li>
186
+ <li>La aplicación prioriza la atención de un profesional. No lo reemplaza.</li>
187
+ </ul>
188
+ <p>En lo metodológico, los dos hallazgos que más cambiaron nuestra lectura de los resultados —el buffer de barajado del experimento de referencia y el agrupamiento por hoja de PlantVillage— no tienen nada que ver con la arquitectura de los modelos.</p>
189
+ </section>
190
+
191
+ <section>
192
+ <h2>Sobre este despliegue</h2>
193
+ <div class="aviso">
194
+ <p style="margin:0 0 10px"><strong>Por qué la aplicación no corre dentro de este Space.</strong></p>
195
+ <p style="margin:0 0 10px">En julio de 2026 Hugging Face modificó su política: las cuentas gratuitas creadas después de ese cambio solo pueden crear Spaces de tipo <strong>Static</strong>, y los de tipo <strong>Gradio</strong> pasaron a requerir plan PRO. Está documentado en el <a href="https://discuss.huggingface.co/t/gradio-sdk-now-marked-as-paid-when-creating-a-new-space/177619" target="_blank" rel="noopener">foro oficial de Hugging Face</a>.</p>
196
+ <p style="margin:0">La aplicación es exactamente la misma que habíamos preparado. Lo único que cambia es dónde se ejecuta el proceso: en vez del contenedor de Hugging Face, corre en un cuaderno de Google Colab y Gradio publica la dirección con <code>share=True</code>. Los dos modelos ajustados siguen publicados en el Hub, y esta portada está desplegada como Space Static.</p>
197
+ </div>
198
+
199
+ <h3>Componentes del proyecto</h3>
200
+ <ul>
201
+ <li><a href="https://huggingface.co/JohnSupertramp2026/vit-base-plantvillage" target="_blank" rel="noopener">ViT-Base/16 ajustado sobre PlantVillage</a> — 38 clases, publicado en el Hub</li>
202
+ <li><a href="https://huggingface.co/JohnSupertramp2026/convnext-tiny-plantvillage" target="_blank" rel="noopener">ConvNeXt-Tiny ajustado sobre PlantVillage</a> — 38 clases, publicado en el Hub</li>
203
+ <li><a href="https://huggingface.co/HuggingFaceTB/SmolVLM-256M-Instruct" target="_blank" rel="noopener">SmolVLM-256M-Instruct</a> — usado sin modificar</li>
204
+ <li><a href="https://huggingface.co/datasets/BrandonFors/Plant-Diseases-PlantVillage-Dataset" target="_blank" rel="noopener">Dataset PlantVillage</a> — 54.305 imágenes, 38 clases</li>
205
+ <li>Esta portada, desplegada como Space Static en Hugging Face</li>
206
+ </ul>
207
+ </section>
208
+
209
+ </div>
210
+
211
+ <div class="gold-bar"></div>
212
+ <footer>
213
+ <div class="wrap">
214
+ <strong style="color:#fff">Universidad San Sebastián</strong> · Facultad de Ingeniería · Magíster en Data Science<br>
215
+ Proyecto Final de Inteligencia Artificial · Prof. Manuel Alejandro Goyo · Agosto de 2026<br>
216
+ Jonathan Núñez Moya · Francisco Rietta González
217
+ </div>
218
+ </footer>
219
+
220
+ <script>
221
+ // Dirección pública de la aplicación (Gradio con share=True desde Colab).
222
+ // Cambiarla aquí cada vez que se levante el cuaderno.
223
+ const URL_APP = "";
224
+
225
+ const b = document.getElementById("btn-app");
226
+ if (URL_APP) {
227
+ b.href = URL_APP;
228
+ } else {
229
+ b.textContent = "Aplicación no disponible en este momento";
230
+ b.style.background = "#3C6484";
231
+ b.style.color = "#C9DCEA";
232
+ b.style.cursor = "default";
233
+ b.removeAttribute("target");
234
+ b.addEventListener("click", e => {
235
+ e.preventDefault();
236
+ alert("La aplicación se levanta desde un cuaderno de Colab durante la presentación.\n\n" +
237
+ "Si estás revisando esto fuera de ese horario, los modelos siguen disponibles " +
238
+ "en el Hub y se pueden probar directamente desde sus fichas.");
239
+ });
240
+ }
241
+ </script>
242
+
243
+ </body>
244
  </html>
matriz_confusion_convnext-tiny.png ADDED

Git LFS Details

  • SHA256: bb5edd7398539d38dde46fbdfdea8de2098385b519fc6ee860e17c19f5c201c0
  • Pointer size: 131 Bytes
  • Size of remote file: 118 kB
matriz_confusion_vit-base.png ADDED

Git LFS Details

  • SHA256: eb83476e1dbadafe75e71622af070cded2cf078b673d1f7c2d08ff6b2b41467e
  • Pointer size: 131 Bytes
  • Size of remote file: 117 kB