Compare commits
1 commit
wiki-share
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5d3855c2c |
58 changed files with 2514 additions and 0 deletions
11
HANDOFF-status-2026-10-21.md
Normal file
11
HANDOFF-status-2026-10-21.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Состояние 21 октября 2026
|
||||
|
||||
После перезагрузки user@10.9.8.230 по запросу пользователя восстановлены все готовые демо: http://10.9.8.230:8080/altai_viz.html, /aug_viz.html, /fast_viz.html; http://10.9.8.230:8081/native_viz.html; http://10.9.8.230:8082/. Проверены внешние HTTP200 и настоящие API-инференсы CPU/GoldenModel MNIST и CUDA Pet lab. PID в штатных runtime/server.pid и runtime/web-server.pid. Запуск nohup, автозапуска после reboot нет. Подробности reports/2026-10-21/журнал.md.
|
||||
|
||||
Все ограничения/цифры 15 октября сохраняются. Коллекций нет, транспорт completed, модель и данные неизменны. Муха отложена. viz/app.html является незаполненным шаблоном, не отдельным демо. Готового транспортного web-демо нет. Никаких commit/push.
|
||||
|
||||
Добавлена точная самостоятельная копия Claude Artifact «Цифры на Алтае»: http://knp-digits.t.snw.su/ и http://10.9.8.230:8080/digits-compare/. Источник mnist-artifact/, README и SOURCE.json; экспорт Chrome в reports/2026-10-21/artifact. Браузерный симулятор STDP vs SNN8, не новый KNP/GM результат. При развёртывании сохранены веса и исходный код расчёта, локализованы шрифты, убрана оболочка Claude. Browser smoke48 примеров/mouse/touch/темы/инспектор прошёл. Сайт на станции viz/digits-compare; публичная копия /opt/knp-digits через Caddy. Ничего не коммитили/пушили.
|
||||
|
||||
Исходники вики сохранены по просьбе пользователя без запуска: /root/knp_docs, origin ssh://git@git.snw.su:30301/pgups/knp_docs.git, main540cdb9fed49a1c910437e0944454e8a56f88ffd. Полный verified Git bundle reports/2026-10-21/knp_docs.bundle. Пользователь сказал «сохрани пока», продолжение/развёртывание репозитория не запрошено.
|
||||
|
||||
Все шесть KNPдемо теперь через Caddy reverse_proxy на рабочую станцию: http://knp-columns.t.snw.su/, http://knp-shifts.t.snw.su/, http://knp-fast.t.snw.su/, http://knp-native.t.snw.su/, http://knp-pets.t.snw.su/, http://knp-digits.t.snw.su/. Последний больше не file_server /opt/knp-digits, а proxy8080/digits-compare. Старый статический backup /opt/knp-digits сохранён. Caddy validate/reload и HTTP/API проверки успешны; wiki не проксировалась. Актуальная вики только knp.snw.su, fs.snw.su устарел.
|
||||
7
deployment/README.md
Normal file
7
deployment/README.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# KNP demo hosting
|
||||
|
||||
`knp-demos.Caddyfile` contains the six HTTP reverse proxy hosts deployed on 2026-10-21. Import these blocks into the hosting server's Caddy configuration, preserving its other sites. Run `caddy validate --config /etc/caddy/Caddyfile` before reloading Caddy.
|
||||
|
||||
Upstream is `10.9.8.230`: browser demos and `digits-compare` on port8080, native CPU/GoldenModel API on8081, Pet lab CUDA API on8082. Start commands and limitations are in the experiment READMEs and reports/2026-10-21/журнал.md. The upstream Python servers currently require manual restart after a machine reboot.
|
||||
|
||||
The wiki is maintained separately at https://knp.snw.su/ and is not included in these proxy hosts. Its Git source is ssh://git@git.snw.su:30301/pgups/knp_docs.git.
|
||||
30
deployment/knp-demos.Caddyfile
Normal file
30
deployment/knp-demos.Caddyfile
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# KNP demo reverse proxies. Import into the main Caddyfile.
|
||||
|
||||
http://knp-digits.t.snw.su {
|
||||
rewrite * /digits-compare{uri}
|
||||
reverse_proxy 10.9.8.230:8080
|
||||
}
|
||||
|
||||
http://knp-columns.t.snw.su {
|
||||
rewrite / /altai_viz.html
|
||||
reverse_proxy 10.9.8.230:8080
|
||||
}
|
||||
|
||||
http://knp-shifts.t.snw.su {
|
||||
rewrite / /aug_viz.html
|
||||
reverse_proxy 10.9.8.230:8080
|
||||
}
|
||||
|
||||
http://knp-fast.t.snw.su {
|
||||
rewrite / /fast_viz.html
|
||||
reverse_proxy 10.9.8.230:8080
|
||||
}
|
||||
|
||||
http://knp-native.t.snw.su {
|
||||
rewrite / /native_viz.html
|
||||
reverse_proxy 10.9.8.230:8081
|
||||
}
|
||||
|
||||
http://knp-pets.t.snw.su {
|
||||
reverse_proxy 10.9.8.230:8082
|
||||
}
|
||||
16
mnist-artifact/README.md
Normal file
16
mnist-artifact/README.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# Цифры на «Алтае»: копия Claude Artifact
|
||||
|
||||
Публичная копия: http://knp-digits.t.snw.su/
|
||||
На рабочей машине: http://10.9.8.230:8080/digits-compare/
|
||||
|
||||
Источник пользователя: Chrome Ctrl+S экспорт https://claude.ai/artifact/Vc1q1WCZuPY2QAHBSGtrKF, архив получен с http://drop.t.snw.su/mearl. Оригинал сохранён в reports/2026-10-21/artifact/chrome-export.zip, SHA256 в SOURCE.json.
|
||||
|
||||
`python3 mnist-artifact/prepare.py` извлекает внутренний saved_resource.html, удаляет только служебный runtime Claude, локализует шрифты и очищает сохранённые Chrome кнопки перед их повторным созданием приложением. Исходный JS приложения, веса, тексты и расчёт сохраняются; перед исходным JS добавлено очищение двух контейнеров. Добавлены lang=ru и viewport для самостоятельного открытия страницы.
|
||||
|
||||
Это браузерный целочисленный симулятор двух моделей: STDP-колонки и temporal SNN8. Подписанные в артефакте test accuracy 92,2%/97,4% взяты из источника, при переносе заново не измерялись. Этот перенос не является KNP/CUDA/GoldenModel проверкой новых весов и не связан с подтверждённым native MNIST 97,76%.
|
||||
|
||||
В исходнике Clear очищает поле рисования, сохраняя предыдущий результат до нового ввода. Это поведение артефакта сохранено.
|
||||
|
||||
Проверки: 24 галерейных изображения в каждой из двух сетей, переключение моделей, инспектор нейрона, ползунок тактов, mouse/touch рисование, desktop/mobile 390px без горизонтального переполнения, светлая/тёмная темы, отсутствие JS errors и внешних запросов. Артефакты проверки в reports/2026-10-21/artifact/browser-checks.json и PNG.
|
||||
|
||||
Хостинг: Caddy /etc/caddy/Caddyfile, отдельный HTTP block knp-digits.t.snw.su, файлы /opt/knp-digits. Caddy validate и reload успешны. На станции статические файлы размещены в /home/user/KNP/viz/digits-compare, все 21 SHA256 сверены. Существующие серверы, модели, библиотеки и данные не менялись. Git commit/push не выполнялись.
|
||||
37
mnist-artifact/SOURCE.json
Normal file
37
mnist-artifact/SOURCE.json
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"source": "https://claude.ai/artifact/Vc1q1WCZuPY2QAHBSGtrKF",
|
||||
"export_url": "http://drop.t.snw.su/mearl",
|
||||
"archive_sha256": "94bf2e99581aec06cbec3078c50c93dcffd1907e40b954006d1fa444aae4eaf7",
|
||||
"inner_html_sha256": "4807bae6973ccc560b51aaf7c60f4b2b8be8d529aeb6848db86036522df2249d",
|
||||
"original_app_sha256": "61ea4ea4db5926c7c8a17f7ce057707fab9b01c6a121fd2e619c42d91b92846c",
|
||||
"changes": [
|
||||
"remove Claude iframe runtime",
|
||||
"clear saved controls before original startup",
|
||||
"local font files",
|
||||
"viewport and Russian document language"
|
||||
],
|
||||
"inference_code_and_weights": "preserved verbatim after the control-reset prelude",
|
||||
"files": {
|
||||
"app.js": "4ef53f5ebcac9b3b489daaf2dfb409a9d520fcc80e5e9502c4e789dce86e9744",
|
||||
"fonts/04b5819e5fda60389774.woff2": "197b6dbe5c6bec7276c59b02d70a16ee6acd44322fc2f8d0226c07f8d57976c2",
|
||||
"fonts/0c46fc34202128a8b356.woff2": "bdb2b33ab916e9e7b42edb61f8aea5f5dd83ad773d6ee4e9b55665daf8954ce8",
|
||||
"fonts/13ff14c8cbbde52dd267.woff2": "7d0037a170882a49e65a45c38ef195237bb07b1cc791d078379f0ac0d7ae1935",
|
||||
"fonts/23f931dc9e4c044ca281.woff2": "35e30483bb79be6fd8de0fec4e038fda9e637fc7337f6ff61418c7d08077878b",
|
||||
"fonts/547062430ce141b89109.woff2": "691cd1d9b4c0cdf31a1dcf04259c86f92c85e69f6622abab7964d81e36890691",
|
||||
"fonts/560980fcddc4e6f493d8.woff2": "f598dd0700f155e2facfaa8ecfacace397d4c2c153e9ce37ab7ad310e8505bc2",
|
||||
"fonts/6b5e37b52d26eeac6a19.woff2": "62213be8a78b42f1e29d1452d91e2f8b3e745572a9dd98d3941e39fa00b37d76",
|
||||
"fonts/6d5e7fb80500edbb2ccc.woff2": "e2291e842cf5af167122a22881a740c7f2dda7716f1e8cd76680264f4a859470",
|
||||
"fonts/90a469f8becd8517007a.woff2": "f5052e4870bf211fc22df5b85e791a292a77b9baef8cef1dc5a8e62a783ea1e0",
|
||||
"fonts/99228c3b93e78c59da72.woff2": "73e7f7b1c980416ae0c2461268b14c7cfcce0668e683dc43fbb11a82a227b9f2",
|
||||
"fonts/99e400330f36ae77c882.woff2": "0a557721b1f8b36d3f3f84442689a71ca4a744300abcb46a1953f51bfc663b66",
|
||||
"fonts/b19c2080652a3c2b1288.woff2": "db5ff4db83e580426280e9337a58dc57d3a83784a1b03ad80914651594441d52",
|
||||
"fonts/c062627ec16ce1b40510.woff2": "09472f217ad1ebb61a7669cf532f9f2f80685e07652ee862fde9a79665aef479",
|
||||
"fonts/c4064400db3750ce826c.woff2": "c89b9cc0bc6262bd4f8d8494b6961601f3aefa829d08c2e3635f4d501d3a47c2",
|
||||
"fonts/cc27b30471250057c5e6.woff2": "83c005d49d8a6a50474c73a5a36ac0468076e9c4a29da7bdb14995d80560a5be",
|
||||
"fonts/eb83d8d40af4411f395f.woff2": "e17cfd15fb96909d64095015f958207063a0c07191da3512df7d560a781aebdf",
|
||||
"fonts/f582230492bfd11eff7b.woff2": "d160e20920ae4d6556518d352d3af27a74e9b0de3d8fe17b1c1044fc75aa2f81",
|
||||
"fonts/fd8b74284fe6ff9705c0.woff2": "9409ee21811f0f5272b7e1d828fe8838005b0573481ef906e7e55b63f6610ab0",
|
||||
"fonts.css": "564d3c95a3b80d7c5ae21347ab77028cb10125812c24520a12f584fa880a6f61",
|
||||
"index.html": "cfb514c642469601364b4482d3ce7cde715ef8fbbf0b0f099fb5dd43466b6eb3"
|
||||
}
|
||||
}
|
||||
63
mnist-artifact/prepare.py
Normal file
63
mnist-artifact/prepare.py
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Extract the saved inner artifact, preserving its UI and inference code."""
|
||||
from pathlib import Path
|
||||
import concurrent.futures
|
||||
import hashlib
|
||||
import json
|
||||
import re
|
||||
import urllib.request
|
||||
import zipfile
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
ARCHIVE = ROOT.parent / 'reports/2026-10-21/artifact/chrome-export.zip'
|
||||
OUT = ROOT / 'site'
|
||||
OUT.mkdir(exist_ok=True)
|
||||
with zipfile.ZipFile(ARCHIVE) as z:
|
||||
names = z.namelist()
|
||||
inner = next(n for n in names if n.endswith('/saved_resource.html'))
|
||||
original = z.read(inner).decode('utf-8')
|
||||
css = z.read(next(n for n in names if n.endswith('/css2'))).decode('utf-8')
|
||||
scripts = re.findall(r'<script\b[^>]*>(.*?)</script>', original, re.S)
|
||||
assert len(scripts) == 3 and scripts[2].lstrip().startswith('const D = ')
|
||||
app = scripts[2]
|
||||
# Chrome saves the already populated DOM. The original code appends these controls.
|
||||
reset = '// Remove Chrome-saved controls before the original application recreates them.\n' \
|
||||
'document.getElementById("switch").replaceChildren();\n' \
|
||||
'document.getElementById("gal").replaceChildren();\n'
|
||||
(OUT / 'app.js').write_text(reset + app)
|
||||
html = re.sub(r'<script\b[^>]*>.*?</script>', '', original, flags=re.S)
|
||||
html = re.sub(r'<!-- saved from url=.*?-->', '', html)
|
||||
html = html.replace('<html>', '<html lang="ru">', 1)
|
||||
html = html.replace('<head>', '<head><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">', 1)
|
||||
html = html.replace('href="./css2"', 'href="./fonts.css"')
|
||||
html = re.sub(r'<link rel="preconnect"[^>]*>', '', html)
|
||||
html = html.replace('</body>', '<script src="./app.js"></script>\n</body>')
|
||||
(OUT / 'index.html').write_text(html)
|
||||
fonts = OUT / 'fonts'
|
||||
fonts.mkdir(exist_ok=True)
|
||||
urls = sorted(set(re.findall(r'url\((https://[^)]+)\)', css)))
|
||||
def fetch(url):
|
||||
name = hashlib.sha256(url.encode()).hexdigest()[:20] + '.woff2'
|
||||
target = fonts / name
|
||||
if not target.exists():
|
||||
with urllib.request.urlopen(url, timeout=30) as r:
|
||||
target.write_bytes(r.read())
|
||||
return url, './fonts/' + name
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=6) as pool:
|
||||
for url, local in pool.map(fetch, urls):
|
||||
css = css.replace(url, local)
|
||||
(OUT / 'fonts.css').write_text(css)
|
||||
manifest = {
|
||||
'source': 'https://claude.ai/artifact/Vc1q1WCZuPY2QAHBSGtrKF',
|
||||
'export_url': 'http://drop.t.snw.su/mearl',
|
||||
'archive_sha256': hashlib.sha256(ARCHIVE.read_bytes()).hexdigest(),
|
||||
'inner_html_sha256': hashlib.sha256(original.encode()).hexdigest(),
|
||||
'original_app_sha256': hashlib.sha256(app.encode()).hexdigest(),
|
||||
'changes': ['remove Claude iframe runtime', 'clear saved controls before original startup',
|
||||
'local font files', 'viewport and Russian document language'],
|
||||
'inference_code_and_weights': 'preserved verbatim after the control-reset prelude',
|
||||
'files': {str(p.relative_to(OUT)): hashlib.sha256(p.read_bytes()).hexdigest()
|
||||
for p in sorted(OUT.rglob('*')) if p.is_file()},
|
||||
}
|
||||
(ROOT / 'SOURCE.json').write_text(json.dumps(manifest, ensure_ascii=False, indent=2) + '\n')
|
||||
print(json.dumps({'fonts': len(urls), 'files': len(manifest['files']), 'archive_sha256': manifest['archive_sha256']}))
|
||||
329
mnist-artifact/site/app.js
Normal file
329
mnist-artifact/site/app.js
Normal file
File diff suppressed because one or more lines are too long
396
mnist-artifact/site/fonts.css
Normal file
396
mnist-artifact/site/fonts.css
Normal file
|
|
@ -0,0 +1,396 @@
|
|||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/13ff14c8cbbde52dd267.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/fd8b74284fe6ff9705c0.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/560980fcddc4e6f493d8.woff2) format('woff2');
|
||||
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/99228c3b93e78c59da72.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/f582230492bfd11eff7b.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/6d5e7fb80500edbb2ccc.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/13ff14c8cbbde52dd267.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/fd8b74284fe6ff9705c0.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/560980fcddc4e6f493d8.woff2) format('woff2');
|
||||
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/99228c3b93e78c59da72.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/f582230492bfd11eff7b.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/6d5e7fb80500edbb2ccc.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/13ff14c8cbbde52dd267.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/fd8b74284fe6ff9705c0.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/560980fcddc4e6f493d8.woff2) format('woff2');
|
||||
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/99228c3b93e78c59da72.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/f582230492bfd11eff7b.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/6d5e7fb80500edbb2ccc.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(./fonts/6b5e37b52d26eeac6a19.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(./fonts/eb83d8d40af4411f395f.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(./fonts/99e400330f36ae77c882.woff2) format('woff2');
|
||||
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(./fonts/c4064400db3750ce826c.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(./fonts/b19c2080652a3c2b1288.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(./fonts/cc27b30471250057c5e6.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(./fonts/6b5e37b52d26eeac6a19.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(./fonts/eb83d8d40af4411f395f.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(./fonts/99e400330f36ae77c882.woff2) format('woff2');
|
||||
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(./fonts/c4064400db3750ce826c.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(./fonts/b19c2080652a3c2b1288.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(./fonts/cc27b30471250057c5e6.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* arabic */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(./fonts/90a469f8becd8517007a.woff2) format('woff2');
|
||||
unicode-range: U+0600-06FF, U+0750-077F, U+0870-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC, U+102E0-102FB, U+10E60-10E7E, U+10EC2-10EC7, U+10EC9-10EEE, U+10EF0-10EFF, U+1EE00-1EE03, U+1EE05-1EE1F, U+1EE21-1EE22, U+1EE24, U+1EE27, U+1EE29-1EE32, U+1EE34-1EE37, U+1EE39, U+1EE3B, U+1EE42, U+1EE47, U+1EE49, U+1EE4B, U+1EE4D-1EE4F, U+1EE51-1EE52, U+1EE54, U+1EE57, U+1EE59, U+1EE5B, U+1EE5D, U+1EE5F, U+1EE61-1EE62, U+1EE64, U+1EE67-1EE6A, U+1EE6C-1EE72, U+1EE74-1EE77, U+1EE79-1EE7C, U+1EE7E, U+1EE80-1EE89, U+1EE8B-1EE9B, U+1EEA1-1EEA3, U+1EEA5-1EEA9, U+1EEAB-1EEBB, U+1EEF0-1EEF1;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(./fonts/23f931dc9e4c044ca281.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(./fonts/0c46fc34202128a8b356.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* hebrew */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(./fonts/04b5819e5fda60389774.woff2) format('woff2');
|
||||
unicode-range: U+0307-0308, U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(./fonts/c062627ec16ce1b40510.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(./fonts/547062430ce141b89109.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* arabic */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(./fonts/90a469f8becd8517007a.woff2) format('woff2');
|
||||
unicode-range: U+0600-06FF, U+0750-077F, U+0870-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC, U+102E0-102FB, U+10E60-10E7E, U+10EC2-10EC7, U+10EC9-10EEE, U+10EF0-10EFF, U+1EE00-1EE03, U+1EE05-1EE1F, U+1EE21-1EE22, U+1EE24, U+1EE27, U+1EE29-1EE32, U+1EE34-1EE37, U+1EE39, U+1EE3B, U+1EE42, U+1EE47, U+1EE49, U+1EE4B, U+1EE4D-1EE4F, U+1EE51-1EE52, U+1EE54, U+1EE57, U+1EE59, U+1EE5B, U+1EE5D, U+1EE5F, U+1EE61-1EE62, U+1EE64, U+1EE67-1EE6A, U+1EE6C-1EE72, U+1EE74-1EE77, U+1EE79-1EE7C, U+1EE7E, U+1EE80-1EE89, U+1EE8B-1EE9B, U+1EEA1-1EEA3, U+1EEA5-1EEA9, U+1EEAB-1EEBB, U+1EEF0-1EEF1;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(./fonts/23f931dc9e4c044ca281.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(./fonts/0c46fc34202128a8b356.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* hebrew */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(./fonts/04b5819e5fda60389774.woff2) format('woff2');
|
||||
unicode-range: U+0307-0308, U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(./fonts/c062627ec16ce1b40510.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(./fonts/547062430ce141b89109.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
BIN
mnist-artifact/site/fonts/04b5819e5fda60389774.woff2
Normal file
BIN
mnist-artifact/site/fonts/04b5819e5fda60389774.woff2
Normal file
Binary file not shown.
BIN
mnist-artifact/site/fonts/0c46fc34202128a8b356.woff2
Normal file
BIN
mnist-artifact/site/fonts/0c46fc34202128a8b356.woff2
Normal file
Binary file not shown.
BIN
mnist-artifact/site/fonts/13ff14c8cbbde52dd267.woff2
Normal file
BIN
mnist-artifact/site/fonts/13ff14c8cbbde52dd267.woff2
Normal file
Binary file not shown.
BIN
mnist-artifact/site/fonts/23f931dc9e4c044ca281.woff2
Normal file
BIN
mnist-artifact/site/fonts/23f931dc9e4c044ca281.woff2
Normal file
Binary file not shown.
BIN
mnist-artifact/site/fonts/547062430ce141b89109.woff2
Normal file
BIN
mnist-artifact/site/fonts/547062430ce141b89109.woff2
Normal file
Binary file not shown.
BIN
mnist-artifact/site/fonts/560980fcddc4e6f493d8.woff2
Normal file
BIN
mnist-artifact/site/fonts/560980fcddc4e6f493d8.woff2
Normal file
Binary file not shown.
BIN
mnist-artifact/site/fonts/6b5e37b52d26eeac6a19.woff2
Normal file
BIN
mnist-artifact/site/fonts/6b5e37b52d26eeac6a19.woff2
Normal file
Binary file not shown.
BIN
mnist-artifact/site/fonts/6d5e7fb80500edbb2ccc.woff2
Normal file
BIN
mnist-artifact/site/fonts/6d5e7fb80500edbb2ccc.woff2
Normal file
Binary file not shown.
BIN
mnist-artifact/site/fonts/90a469f8becd8517007a.woff2
Normal file
BIN
mnist-artifact/site/fonts/90a469f8becd8517007a.woff2
Normal file
Binary file not shown.
BIN
mnist-artifact/site/fonts/99228c3b93e78c59da72.woff2
Normal file
BIN
mnist-artifact/site/fonts/99228c3b93e78c59da72.woff2
Normal file
Binary file not shown.
BIN
mnist-artifact/site/fonts/99e400330f36ae77c882.woff2
Normal file
BIN
mnist-artifact/site/fonts/99e400330f36ae77c882.woff2
Normal file
Binary file not shown.
BIN
mnist-artifact/site/fonts/b19c2080652a3c2b1288.woff2
Normal file
BIN
mnist-artifact/site/fonts/b19c2080652a3c2b1288.woff2
Normal file
Binary file not shown.
BIN
mnist-artifact/site/fonts/c062627ec16ce1b40510.woff2
Normal file
BIN
mnist-artifact/site/fonts/c062627ec16ce1b40510.woff2
Normal file
Binary file not shown.
BIN
mnist-artifact/site/fonts/c4064400db3750ce826c.woff2
Normal file
BIN
mnist-artifact/site/fonts/c4064400db3750ce826c.woff2
Normal file
Binary file not shown.
BIN
mnist-artifact/site/fonts/cc27b30471250057c5e6.woff2
Normal file
BIN
mnist-artifact/site/fonts/cc27b30471250057c5e6.woff2
Normal file
Binary file not shown.
BIN
mnist-artifact/site/fonts/eb83d8d40af4411f395f.woff2
Normal file
BIN
mnist-artifact/site/fonts/eb83d8d40af4411f395f.woff2
Normal file
Binary file not shown.
BIN
mnist-artifact/site/fonts/f582230492bfd11eff7b.woff2
Normal file
BIN
mnist-artifact/site/fonts/f582230492bfd11eff7b.woff2
Normal file
Binary file not shown.
BIN
mnist-artifact/site/fonts/fd8b74284fe6ff9705c0.woff2
Normal file
BIN
mnist-artifact/site/fonts/fd8b74284fe6ff9705c0.woff2
Normal file
Binary file not shown.
180
mnist-artifact/site/index.html
Normal file
180
mnist-artifact/site/index.html
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html lang="ru"><head><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><!-- frame-runtime --><!-- /frame-runtime --><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><style>:root{color-scheme:light;box-sizing:border-box;padding-top:env(safe-area-inset-top,0px);padding-bottom:env(safe-area-inset-bottom,0px)}html{scroll-padding-top:env(safe-area-inset-top,0px)}body{margin:0;padding:0;font:14px -apple-system,BlinkMacSystemFont,sans-serif;background:#fff;color:#000}img{max-width:100%}[hidden]:not([hidden=until-found i]){display:none!important}</style></head><body>
|
||||
<title>Цифры на «Алтае»</title>
|
||||
<meta name="claude:viewport-fit-sides" content="cover">
|
||||
|
||||
<link rel="stylesheet" href="./fonts.css">
|
||||
<style>
|
||||
/* Layout: one column of three numbered stages (до / внутри / после) under a sticky network switch; pixel views are always on a dark "scope" ground */
|
||||
:root {
|
||||
--bg: #F2F4F6; --panel: #FFFFFF; --ink: #16202A; --muted: #586674; --line: #D8DEE4;
|
||||
--scope: #0D1318; --scope-dim: #27323C; --spike: #CF5A16; --charge: #137F89; --neg: #B0435A; --good: #2E7D4B; --bad: #B23B3B;
|
||||
--spike-on-scope: #F2903F; --charge-on-scope: #38BAC3; --neg-on-scope: #E06A80;
|
||||
--f-display: "Rubik", "Trebuchet MS", sans-serif; --f-body: "IBM Plex Sans", "Segoe UI", Arial, sans-serif; --f-mono: "JetBrains Mono", "Courier New", monospace;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) {
|
||||
--bg: #0E1318; --panel: #161D24; --ink: #E6EBEF; --muted: #95A3AF; --line: #27323C;
|
||||
--scope: #080C10; --scope-dim: #222C35; --spike: #F08A3E; --charge: #3DBDC6; --neg: #E07085; --good: #5DBE7C; --bad: #EE6B6B; color-scheme: dark } }
|
||||
:root[data-theme="dark"] {
|
||||
--bg: #0E1318; --panel: #161D24; --ink: #E6EBEF; --muted: #95A3AF; --line: #27323C;
|
||||
--scope: #080C10; --scope-dim: #222C35; --spike: #F08A3E; --charge: #3DBDC6; --neg: #E07085; --good: #5DBE7C; --bad: #EE6B6B; color-scheme: dark }
|
||||
* { box-sizing: border-box }
|
||||
body { background: var(--bg); color: var(--ink); font: 16px/1.5 var(--f-body); }
|
||||
body::before { content: ""; position: fixed; inset: 0 0 auto; height: env(safe-area-inset-top, 0px); z-index: 10; background: var(--bg) }
|
||||
.wrap { max-width: 1120px; margin: 0 auto; padding-left: max(16px, env(safe-area-inset-left, 0px)); padding-right: max(16px, env(safe-area-inset-right, 0px)); padding-block: 28px 64px; display: flex; flex-direction: column; gap: 28px }
|
||||
h1, h2, h3 { font-family: var(--f-display); font-weight: 600; margin: 0; text-wrap: balance; line-height: 1.15 }
|
||||
h1 { font-size: clamp(28px, 4.2vw, 42px) }
|
||||
h2 { font-size: 24px }
|
||||
h3 { font-size: 17px }
|
||||
p { margin: 0 }
|
||||
.lead { color: var(--muted); max-width: 68ch; font-size: 17px }
|
||||
.mono { font-family: var(--f-mono); font-variant-numeric: tabular-nums }
|
||||
.muted { color: var(--muted) }
|
||||
.small { font-size: 14px }
|
||||
.eyebrow { font-family: var(--f-mono); font-size: 13px; letter-spacing: .08em; text-transform: uppercase; color: var(--spike) }
|
||||
.head { display: flex; flex-direction: column; gap: 10px }
|
||||
|
||||
.switch { position: sticky; top: env(safe-area-inset-top, 0px); z-index: 5; background: var(--bg); padding-block: 8px; display: flex; flex-wrap: wrap; gap: 8px }
|
||||
.switch button { flex: 1 1 240px; text-align: left; font: inherit; color: var(--ink); background: var(--panel); border: 1.5px solid var(--line); border-radius: 12px; padding: 10px 14px; cursor: pointer; display: flex; flex-direction: column; gap: 2px }
|
||||
.switch button b { font-family: var(--f-display); font-weight: 600; font-size: 16px }
|
||||
.switch button span { color: var(--muted); font-size: 14px }
|
||||
.switch button[aria-pressed="true"] { border-color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink) }
|
||||
button:focus-visible, canvas:focus-visible, input:focus-visible { outline: 2px solid var(--charge); outline-offset: 2px }
|
||||
|
||||
.panel { background: var(--panel); border: 1px solid var(--line); border-radius: 16px; padding: 20px; display: flex; flex-direction: column; gap: 16px; min-width: 0 }
|
||||
.row { display: flex; flex-wrap: wrap; gap: 16px; align-items: flex-start }
|
||||
.row > * { min-width: 0 }
|
||||
.grow { flex: 1 1 280px }
|
||||
.btn { font: inherit; font-size: 15px; color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 10px; padding: 7px 14px; cursor: pointer }
|
||||
.btn:hover { border-color: var(--muted) }
|
||||
.btn.primary { background: var(--ink); color: var(--panel); border-color: var(--ink) }
|
||||
|
||||
.pad { width: 280px; max-width: 100%; aspect-ratio: 1; display: block; border-radius: 14px; background: #000; touch-action: none; cursor: crosshair }
|
||||
.px { image-rendering: pixelated; background: var(--scope); border-radius: 10px; display: block }
|
||||
.fig { display: flex; flex-direction: column; gap: 6px; align-items: flex-start }
|
||||
.cap { font-size: 13px; color: var(--muted); max-width: 22ch; line-height: 1.35 }
|
||||
.gal { display: flex; flex-wrap: wrap; gap: 5px }
|
||||
.gal button { padding: 2px; border: 2px solid var(--line); border-radius: 9px; background: var(--scope); cursor: pointer; line-height: 0 }
|
||||
.gal button[aria-pressed="true"] { border-color: var(--spike) }
|
||||
.gal canvas { width: 34px; height: 34px; image-rendering: pixelated; border-radius: 5px }
|
||||
|
||||
.answer { display: grid; grid-template-columns: auto 1fr; gap: 4px 18px; align-items: center }
|
||||
.answer .digit { grid-row: span 3; font-family: var(--f-mono); font-size: 84px; font-weight: 600; line-height: 1 }
|
||||
.verdict { font-weight: 600 }
|
||||
.verdict.ok { color: var(--good) } .verdict.no { color: var(--bad) }
|
||||
.facts { display: flex; flex-wrap: wrap; gap: 6px 18px; font-size: 14px; color: var(--muted) }
|
||||
.facts b { color: var(--ink); font-family: var(--f-mono); font-weight: 600 }
|
||||
|
||||
.stage-title { display: flex; align-items: baseline; gap: 12px }
|
||||
.stage-title .n { font-family: var(--f-mono); font-size: 14px; color: var(--muted); border: 1px solid var(--line); border-radius: 99px; padding: 1px 9px }
|
||||
.flow { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 10px }
|
||||
.flow .arrow { align-self: center; color: var(--muted); font-size: 22px; padding-top: 0 }
|
||||
|
||||
.transport { display: flex; flex-wrap: wrap; align-items: center; gap: 12px }
|
||||
.transport input[type=range] { flex: 1 1 200px; accent-color: var(--spike) }
|
||||
.story { background: var(--bg); border-radius: 12px; padding: 12px 16px; max-width: 80ch }
|
||||
.views { display: grid; grid-template-columns: auto auto minmax(0, 1fr); gap: 20px; align-items: start }
|
||||
@media (max-width: 760px) { .views { grid-template-columns: 1fr 1fr } .views > .outs { grid-column: 1 / -1 } }
|
||||
.lanes { display: flex; flex-direction: column; gap: 3px; width: 100% }
|
||||
.lane { display: grid; grid-template-columns: 18px minmax(60px, 1fr) 64px; gap: 10px; align-items: center; padding: 3px 8px; border-radius: 8px; font-family: var(--f-mono); font-size: 14px }
|
||||
.lane.fire { background: color-mix(in srgb, var(--spike) 16%, transparent) }
|
||||
.lane.lead { box-shadow: inset 0 0 0 1.5px var(--good) }
|
||||
.lane .bar { height: 12px; border-radius: 4px; background: var(--line); position: relative; overflow: hidden }
|
||||
.lane .bar i { position: absolute; inset: 0 auto 0 0; background: var(--charge) }
|
||||
.lane .bar i.votes { background: var(--spike) }
|
||||
.lane .dots { display: flex; gap: 3px; flex-wrap: wrap }
|
||||
.lane .dots i { width: 8px; height: 8px; border-radius: 50%; background: var(--spike) }
|
||||
.lane b { font-weight: 400; color: var(--muted); text-align: right }
|
||||
.colgrid { display: grid; grid-template-columns: 16px auto; gap: 0 6px; align-items: stretch }
|
||||
.colgrid .labels { display: grid; grid-template-rows: repeat(10, 1fr); font-family: var(--f-mono); font-size: 12px; color: var(--muted); text-align: right }
|
||||
.colgrid .labels span { display: flex; align-items: center; justify-content: flex-end }
|
||||
.legend { display: flex; flex-wrap: wrap; gap: 6px 16px; font-size: 13px; color: var(--muted) }
|
||||
.legend span::before { content: ""; display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 6px; vertical-align: -1px; background: var(--c) }
|
||||
.ramp { display: inline-block; width: 120px; height: 10px; border-radius: 3px; vertical-align: -1px; margin: 0 6px }
|
||||
|
||||
.inspect { display: grid; grid-template-columns: auto auto minmax(0, 1fr); gap: 18px; align-items: start; border-top: 1px solid var(--line); padding-top: 16px }
|
||||
@media (max-width: 760px) { .inspect { grid-template-columns: 1fr 1fr } .inspect > .txt { grid-column: 1 / -1 } }
|
||||
.voters { display: flex; flex-wrap: wrap; gap: 8px }
|
||||
.voters button { display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 4px; border: 1.5px solid var(--line); border-radius: 10px; background: var(--panel); color: var(--ink); cursor: pointer; font: 12px var(--f-mono) }
|
||||
.voters button[aria-pressed="true"] { border-color: var(--spike) }
|
||||
.voters canvas { width: 56px; height: 56px; image-rendering: pixelated; border-radius: 6px; background: var(--scope) }
|
||||
.spark { width: 100%; max-width: 360px; height: 90px; display: block }
|
||||
.after { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 20px }
|
||||
@media (max-width: 760px) { .after { grid-template-columns: 1fr } }
|
||||
.cost { display: flex; flex-direction: column; gap: 10px }
|
||||
.cost .line { display: grid; grid-template-columns: 1fr auto; gap: 12px; border-bottom: 1px solid var(--line); padding-bottom: 6px; font-size: 15px }
|
||||
.cost .line b { font-family: var(--f-mono); font-weight: 600 }
|
||||
.train p + p { margin-top: 8px }
|
||||
.train ol { margin: 8px 0 0; padding-left: 22px; display: flex; flex-direction: column; gap: 6px; max-width: 80ch }
|
||||
@media (prefers-reduced-motion: reduce) { * { transition: none !important } }
|
||||
</style>
|
||||
|
||||
<div class="wrap">
|
||||
<header class="head">
|
||||
<p class="eyebrow">KNP · AltAI · импульсные сети</p>
|
||||
<h1>Как сеть на «Алтае» узнаёт цифру</h1>
|
||||
<p class="lead">Нарисуйте цифру или выберите тестовую. Ниже видно всё, что с ней происходит: как обычный процессор готовит картинку, как спайки идут через сеть такт за тактом и как из них получается ответ. Расчёт точный и целочисленный, по тем же правилам, что на чипе.</p>
|
||||
</header>
|
||||
|
||||
<nav class="switch" id="switch" aria-label="Сеть"><button type="button" data-net="snn" aria-pressed="true"><b>Последняя версия: Сеть по тактам</b><span>97,4% на тесте · 8 тактов · обучена на компьютере</span></button><button type="button" data-net="cols" aria-pressed="false"><b>Первая версия: Колонки STDP</b><span>92,2% на тесте · 15 тактов · обучена в KNP</span></button></nav>
|
||||
|
||||
<section class="panel">
|
||||
<div class="row">
|
||||
<div class="fig">
|
||||
<canvas id="pad" class="pad" width="280" height="280" aria-label="Поле для рисования цифры"></canvas>
|
||||
<div class="row" style="gap:10px;align-items:center"><button class="btn" id="clear">Очистить</button><span class="small muted" id="src">Тестовая цифра «3», №381</span></div>
|
||||
</div>
|
||||
<div class="grow" style="display:flex;flex-direction:column;gap:16px">
|
||||
<div class="answer" aria-live="polite">
|
||||
<span class="digit" id="ans">3</span>
|
||||
<span class="small muted" id="ansNet">Последняя версия: Сеть по тактам</span>
|
||||
<span class="verdict ok" id="verdict">верно</span>
|
||||
<span class="small muted" id="ansNote">ответ ясен с такта 4 из 8</span>
|
||||
</div>
|
||||
<div class="facts" id="netFacts"><span>тактов <b>9</b></span><span>входных спайков <b>142</b></span><span>спайков нейронов <b>42</b></span><span>сложений на чипе <b>19 604</b></span></div>
|
||||
<div style="display:flex;flex-direction:column;gap:6px">
|
||||
<span class="small muted">Тестовые цифры MNIST — сеть их не видела при обучении</span>
|
||||
<div class="gal" id="gal" role="group" aria-label="Тестовые цифры"><button type="button" aria-label="Цифра 4, тест №447" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 7, тест №124" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 3, тест №381" aria-pressed="true"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 9, тест №92" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 3, тест №158" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 2, тест №222" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 8, тест №290" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 7, тест №0" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 0, тест №3" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 4, тест №4" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 4, тест №115" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 2, тест №321" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 2, тест №1" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 1, тест №2" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 1, тест №5" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 4, тест №6" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 9, тест №7" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 5, тест №8" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 9, тест №9" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 0, тест №10" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 6, тест №11" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 9, тест №12" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 0, тест №13" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 1, тест №14" aria-pressed="false"><canvas width="28" height="28"></canvas></button></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="panel" aria-labelledby="t1">
|
||||
<div class="stage-title"><span class="n">1</span><h2 id="t1">До сети: обычный процессор готовит вход</h2></div>
|
||||
<p class="muted" id="beforeText">Сеть училась на цифрах определённого вида, поэтому процессор сначала приводит рисунок к нему: вписывает в квадрат 20×20, ставит центр масс в центр поля 28×28, выпрямляет наклон и уменьшает с усреднением, чтобы края стали серыми. Потом каждый пиксель ярче 32 получает момент своего единственного спайка: чем ярче, тем раньше.</p>
|
||||
<div class="flow" id="flow"><div class="fig"><canvas width="28" height="28" class="px" aria-label="1. исходная цифра MNIST" style="width: 140px; height: 140px; max-width: 100%;"></canvas><span class="cap">1. исходная цифра MNIST</span></div><span class="arrow" aria-hidden="true">→</span><div class="fig"><canvas width="28" height="28" class="px" aria-label="2. в квадрат 20×20, центр масс в центр" style="width: 140px; height: 140px; max-width: 100%;"></canvas><span class="cap">2. в квадрат 20×20, центр масс в центр</span></div><span class="arrow" aria-hidden="true">→</span><div class="fig"><canvas width="28" height="28" class="px" aria-label="3. наклон выпрямлен" style="width: 140px; height: 140px; max-width: 100%;"></canvas><span class="cap">3. наклон выпрямлен</span></div><span class="arrow" aria-hidden="true">→</span><div class="fig"><canvas width="28" height="28" class="px" aria-label="4. уменьшение с усреднением: вход сети" style="width: 140px; height: 140px; max-width: 100%;"></canvas><span class="cap">4. уменьшение с усреднением: вход сети</span></div><span class="arrow" aria-hidden="true">→</span><div class="fig"><canvas width="28" height="28" class="px" aria-label="Моменты спайков" style="width: 140px; height: 140px; max-width: 100%;"></canvas><span class="cap">5. моменты спайков: яркое стреляет на такте 0, тусклое — на 7-м. Всего 142 спайков</span></div></div>
|
||||
</section>
|
||||
|
||||
<section class="panel" aria-labelledby="t2">
|
||||
<div class="stage-title"><span class="n">2</span><h2 id="t2">Внутри сети: такт за тактом</h2></div>
|
||||
<div class="transport">
|
||||
<button class="btn primary" id="play">▶ Пуск</button>
|
||||
<input type="range" id="tick" min="0" max="8" value="0" aria-label="Такт">
|
||||
<span class="mono" id="tickLab">такт 8 из 8</span>
|
||||
</div>
|
||||
<p class="story" id="story">Такт 8, последний. Новых пикселей нет: выходы получают последние спайки скрытого слоя. Выходы получили 1 спайков скрытого слоя с прошлого такта, выстрелили «3». Лидер «3» больше не сменится — ответ ясен уже сейчас.</p>
|
||||
<div class="views" id="views"><div class="fig"><span class="cap">784 входа: пиксели, стреляющие сейчас</span><canvas width="28" height="28" class="px" aria-label="Входные спайки на этом такте" style="width: 168px; height: 168px; max-width: 100%;"></canvas></div><div class="fig"><span class="cap">256 скрытых нейронов (нажмите на любой)</span><canvas width="16" height="16" class="px" aria-label="256 скрытых нейронов" tabindex="0" style="width: 168px; height: 168px; max-width: 100%; cursor: pointer;"></canvas></div><div class="fig outs"><span class="cap">10 выходов: заряд до порога 8 и спайки</span><div class="lanes"><div class="lane"><span>0</span><div class="bar" title="заряд 0 из 8"><i style="width:0%"></i></div><div class="dots"><b>0</b></div></div><div class="lane"><span>1</span><div class="bar" title="заряд 1 из 8"><i style="width:12.5%"></i></div><div class="dots"><b>0</b></div></div><div class="lane"><span>2</span><div class="bar" title="заряд 3 из 8"><i style="width:37.5%"></i></div><div class="dots"><i></i><b></b></div></div><div class="lane fire lead"><span>3</span><div class="bar" title="заряд 0 из 8"><i style="width:0%"></i></div><div class="dots"><i></i><i></i><i></i><i></i><i></i><b></b></div></div><div class="lane"><span>4</span><div class="bar" title="заряд 2 из 8"><i style="width:25%"></i></div><div class="dots"><b>0</b></div></div><div class="lane"><span>5</span><div class="bar" title="заряд 3 из 8"><i style="width:37.5%"></i></div><div class="dots"><b>0</b></div></div><div class="lane"><span>6</span><div class="bar" title="заряд 0 из 8"><i style="width:0%"></i></div><div class="dots"><b>0</b></div></div><div class="lane"><span>7</span><div class="bar" title="заряд 4 из 8"><i style="width:50%"></i></div><div class="dots"><i></i><i></i><i></i><b></b></div></div><div class="lane"><span>8</span><div class="bar" title="заряд 3 из 8"><i style="width:37.5%"></i></div><div class="dots"><b>0</b></div></div><div class="lane"><span>9</span><div class="bar" title="заряд 2 из 8"><i style="width:25%"></i></div><div class="dots"><i></i><b></b></div></div></div></div></div>
|
||||
<div class="legend" id="legend"><span style="--c: var(--spike-on-scope)">спайк на этом такте</span><span style="--c: var(--charge-on-scope)">заряд нейрона</span><span style="--c: var(--scope-dim)">пиксель уже выстрелил</span></div>
|
||||
<div class="inspect" id="inspect"><div class="fig"><span class="cap">Нейрон №112: что он ищет</span><canvas width="28" height="28" class="px" aria-label="Веса нейрона 112" style="width: 168px; height: 168px; max-width: 100%;"></canvas><span class="cap">бирюзовый — вес «+», красный — вес «−»</span></div><div class="fig"><span class="cap">что дала ему эта картинка</span><canvas width="28" height="28" class="px" aria-label="Что этот нейрон получил от картинки" style="width: 168px; height: 168px; max-width: 100%;"></canvas><span class="cap">сумма весов по закрашенным пикселям: +31</span></div><div class="txt" style="display:flex;flex-direction:column;gap:10px"><h3>Нейрон №112: 3 спайков за картинку</h3><p class="small muted">Скрытый нейрон — это детектор кусочка формы. Бирюзовые пиксели заряжают его, красные — разряжают. Набрал 8 — выстрелил и отправил спайк выходам.</p><p class="small"><b>Связи к выходам: </b>0: −2 · 1: +2 · 3: +4 · 4: −1 · 5: −1 · 6: +2 · 7: +2 · 8: −2 · 9: −2</p><div><span class="cap" style="max-width:none">заряд по тактам: растёт, когда приходят веса; дошёл до порога — спайк (оранжевая точка), и порог вычитается. Красный пунктир — сумма за такт оказалась ниже нуля, и заряд обрезан до 0: хранить минус нейрону не разрешено настройкой</span><svg viewBox="0 0 360 110" class="spark" role="img" aria-label="Заряд нейрона по тактам"><line x1="16" x2="344" y1="42.42857142857143" y2="42.42857142857143" stroke="#95A3AF" stroke-dasharray="4 4" stroke-width="1"></line><text x="344" y="38.42857142857143" text-anchor="end" font-size="11" fill="#95A3AF" font-family="JetBrains Mono, monospace">порог 8</text><line x1="16" x2="344" y1="84.71428571428571" y2="84.71428571428571" stroke="#95A3AF" stroke-width="1" opacity="0.5"></line><text x="344" y="96.71428571428571" text-anchor="end" font-size="11" fill="#95A3AF" font-family="JetBrains Mono, monospace">0</text><line x1="303" x2="303" y1="84.71428571428571" y2="90" stroke="#E07085" stroke-width="2" stroke-dasharray="3 3"></line><circle cx="303" cy="90" r="2.5" fill="#E07085"></circle><path d="M8,84.71428571428571 L16,53 L16,53 L57,16 L57,58.285714285714285 L98,53 L98,53 L139,42.42857142857143 L139,84.71428571428571 L180,63.57142857142857 L180,63.57142857142857 L221,58.285714285714285 L221,58.285714285714285 L262,37.142857142857146 L262,79.42857142857143 L303,84.71428571428571 L303,84.71428571428571 L344,84.71428571428571 L344,84.71428571428571" fill="none" stroke="#3DBDC6" stroke-width="2" stroke-linejoin="round"></path><circle cx="57" cy="16" r="4" fill="#F08A3E"></circle><rect x="55" y="2" width="4" height="10" rx="1" fill="#F08A3E"></rect><circle cx="139" cy="42.42857142857143" r="4" fill="#F08A3E"></circle><rect x="137" y="2" width="4" height="10" rx="1" fill="#F08A3E"></rect><circle cx="262" cy="37.142857142857146" r="4" fill="#F08A3E"></circle><rect x="260" y="2" width="4" height="10" rx="1" fill="#F08A3E"></rect><line x1="344" x2="344" y1="0" y2="94" stroke="#E6EBEF" stroke-width="1" opacity="0.35"></line><text x="16" y="107" text-anchor="start" font-size="11" fill="#95A3AF" font-family="JetBrains Mono, monospace">такт 0</text><text x="344" y="107" text-anchor="end" font-size="11" fill="#95A3AF" font-family="JetBrains Mono, monospace">такт 8</text></svg></div><h3>Больше всего за «3» проголосовали</h3><div class="voters"><button type="button" aria-pressed="true" aria-label="Нейрон 112"><canvas width="28" height="28"></canvas><span>№112 +12</span></button><button type="button" aria-pressed="false" aria-label="Нейрон 150"><canvas width="28" height="28"></canvas><span>№150 +8</span></button><button type="button" aria-pressed="false" aria-label="Нейрон 109"><canvas width="28" height="28"></canvas><span>№109 +4</span></button><button type="button" aria-pressed="false" aria-label="Нейрон 168"><canvas width="28" height="28"></canvas><span>№168 +4</span></button><button type="button" aria-pressed="false" aria-label="Нейрон 120"><canvas width="28" height="28"></canvas><span>№120 +2</span></button><button type="button" aria-pressed="false" aria-label="Нейрон 165"><canvas width="28" height="28"></canvas><span>№165 +2</span></button></div></div></div>
|
||||
</section>
|
||||
|
||||
<section class="panel" aria-labelledby="t3">
|
||||
<div class="stage-title"><span class="n">3</span><h2 id="t3">После сети: ответ и цена</h2></div>
|
||||
<div class="after">
|
||||
<div style="display:flex;flex-direction:column;gap:10px"><p id="ruleText">Процессор считает спайки десяти выходных нейронов. Ответ — цифра, чей нейрон выстрелил больше всех; при равенстве — тот, кто выстрелил раньше.</p><div class="lanes" id="final"><div class="lane"><span>0</span><div class="bar"><i class="votes" style="width:0%"></i></div><b>0 сп.</b></div><div class="lane"><span>1</span><div class="bar"><i class="votes" style="width:0%"></i></div><b>0 сп.</b></div><div class="lane"><span>2</span><div class="bar"><i class="votes" style="width:20%"></i></div><b>1 сп.</b></div><div class="lane lead"><span>3</span><div class="bar"><i class="votes" style="width:100%"></i></div><b>5 сп.</b></div><div class="lane"><span>4</span><div class="bar"><i class="votes" style="width:0%"></i></div><b>0 сп.</b></div><div class="lane"><span>5</span><div class="bar"><i class="votes" style="width:0%"></i></div><b>0 сп.</b></div><div class="lane"><span>6</span><div class="bar"><i class="votes" style="width:0%"></i></div><b>0 сп.</b></div><div class="lane"><span>7</span><div class="bar"><i class="votes" style="width:60%"></i></div><b>3 сп.</b></div><div class="lane"><span>8</span><div class="bar"><i class="votes" style="width:0%"></i></div><b>0 сп.</b></div><div class="lane"><span>9</span><div class="bar"><i class="votes" style="width:20%"></i></div><b>1 сп.</b></div></div></div>
|
||||
<div class="cost" id="cost"><h3>Сколько работы у чипа</h3><div class="line"><span>входных спайков</span><b>142</b></div><div class="line"><span>спайков нейронов</span><b>42</b></div><div class="line"><span>сложений «спайк → вес»</span><b>19 604</b></div><div class="line"><span>обычная сеть 784→256→10, умножений</span><b>203 264</b></div><p class="small muted">Каждый входной спайк задевает в среднем ≈139 из 256 скрытых нейронов: у остальных вес 0, и такая связь на чипе не создаётся. Поэтому работы примерно 143 × 139 ≈ 20 тыс. сложений.</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="panel train" aria-labelledby="t4">
|
||||
<h2 id="t4">Как эта сеть обучена</h2>
|
||||
<div id="train"><p>Обучена на обычном компьютере (PyTorch), а не в KNP: на чип загружаются готовые целые веса. 55 000 цифр MNIST, 30 эпох (проходов по всем цифрам), около 17 минут на процессоре без видеокарты.</p><ol><li>При обучении сеть считает ровно как чип: 8 тактов, целые веса, порог 8, вычитание порога после спайка, задержка в такт между слоями.</li><li>Спайк — это ступенька, у неё нет производной. При расчёте ошибки ступенька подменяется плавной «горкой» (суррогатный градиент), и сеть понимает, куда сдвигать веса.</li><li>С 9-й эпохи веса округляются до допустимых на чипе 0, ±1, ±2, ±4, и сеть доучивается уже с ними. Плюс небольшой штраф за лишние спайки.</li><li>Половина обучающих цифр перерисована пером постоянной толщины, как мышью, плюс сдвиги и повороты. Поэтому сеть хорошо узнаёт рисунки: 95,9% на перерисованном тесте.</li><li>Лучшая эпоха выбрана на 5000 отложенных цифрах отдельным целочисленным симулятором; тест открыт один раз.</li></ol></div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<script src="./app.js"></script>
|
||||
</body></html>
|
||||
396
reports/2026-10-21/artifact/browser-checks.json
Normal file
396
reports/2026-10-21/artifact/browser-checks.json
Normal file
|
|
@ -0,0 +1,396 @@
|
|||
{
|
||||
"url": "http://knp-digits.t.snw.su/",
|
||||
"page_errors": [],
|
||||
"failed_requests": [],
|
||||
"switch_buttons": 2,
|
||||
"gallery_buttons": 24,
|
||||
"gallery_inferences": [
|
||||
{
|
||||
"net": "snn",
|
||||
"label": 4,
|
||||
"answer": 4,
|
||||
"ticks": 9,
|
||||
"synaptic": 23597,
|
||||
"input": 166
|
||||
},
|
||||
{
|
||||
"net": "snn",
|
||||
"label": 7,
|
||||
"answer": 4,
|
||||
"ticks": 9,
|
||||
"synaptic": 19654,
|
||||
"input": 139
|
||||
},
|
||||
{
|
||||
"net": "snn",
|
||||
"label": 3,
|
||||
"answer": 3,
|
||||
"ticks": 9,
|
||||
"synaptic": 19604,
|
||||
"input": 142
|
||||
},
|
||||
{
|
||||
"net": "snn",
|
||||
"label": 9,
|
||||
"answer": 9,
|
||||
"ticks": 9,
|
||||
"synaptic": 13563,
|
||||
"input": 97
|
||||
},
|
||||
{
|
||||
"net": "snn",
|
||||
"label": 3,
|
||||
"answer": 3,
|
||||
"ticks": 9,
|
||||
"synaptic": 17912,
|
||||
"input": 129
|
||||
},
|
||||
{
|
||||
"net": "snn",
|
||||
"label": 2,
|
||||
"answer": 2,
|
||||
"ticks": 9,
|
||||
"synaptic": 34053,
|
||||
"input": 244
|
||||
},
|
||||
{
|
||||
"net": "snn",
|
||||
"label": 8,
|
||||
"answer": 4,
|
||||
"ticks": 9,
|
||||
"synaptic": 23105,
|
||||
"input": 166
|
||||
},
|
||||
{
|
||||
"net": "snn",
|
||||
"label": 7,
|
||||
"answer": 7,
|
||||
"ticks": 9,
|
||||
"synaptic": 15195,
|
||||
"input": 109
|
||||
},
|
||||
{
|
||||
"net": "snn",
|
||||
"label": 0,
|
||||
"answer": 0,
|
||||
"ticks": 9,
|
||||
"synaptic": 26241,
|
||||
"input": 189
|
||||
},
|
||||
{
|
||||
"net": "snn",
|
||||
"label": 4,
|
||||
"answer": 4,
|
||||
"ticks": 9,
|
||||
"synaptic": 16383,
|
||||
"input": 117
|
||||
},
|
||||
{
|
||||
"net": "snn",
|
||||
"label": 4,
|
||||
"answer": 4,
|
||||
"ticks": 9,
|
||||
"synaptic": 14714,
|
||||
"input": 105
|
||||
},
|
||||
{
|
||||
"net": "snn",
|
||||
"label": 2,
|
||||
"answer": 7,
|
||||
"ticks": 9,
|
||||
"synaptic": 15480,
|
||||
"input": 110
|
||||
},
|
||||
{
|
||||
"net": "snn",
|
||||
"label": 2,
|
||||
"answer": 2,
|
||||
"ticks": 9,
|
||||
"synaptic": 22048,
|
||||
"input": 154
|
||||
},
|
||||
{
|
||||
"net": "snn",
|
||||
"label": 1,
|
||||
"answer": 1,
|
||||
"ticks": 9,
|
||||
"synaptic": 10150,
|
||||
"input": 69
|
||||
},
|
||||
{
|
||||
"net": "snn",
|
||||
"label": 1,
|
||||
"answer": 1,
|
||||
"ticks": 9,
|
||||
"synaptic": 11161,
|
||||
"input": 77
|
||||
},
|
||||
{
|
||||
"net": "snn",
|
||||
"label": 4,
|
||||
"answer": 4,
|
||||
"ticks": 9,
|
||||
"synaptic": 18462,
|
||||
"input": 131
|
||||
},
|
||||
{
|
||||
"net": "snn",
|
||||
"label": 9,
|
||||
"answer": 9,
|
||||
"ticks": 9,
|
||||
"synaptic": 17206,
|
||||
"input": 120
|
||||
},
|
||||
{
|
||||
"net": "snn",
|
||||
"label": 5,
|
||||
"answer": 5,
|
||||
"ticks": 9,
|
||||
"synaptic": 22631,
|
||||
"input": 161
|
||||
},
|
||||
{
|
||||
"net": "snn",
|
||||
"label": 9,
|
||||
"answer": 9,
|
||||
"ticks": 9,
|
||||
"synaptic": 22909,
|
||||
"input": 164
|
||||
},
|
||||
{
|
||||
"net": "snn",
|
||||
"label": 0,
|
||||
"answer": 0,
|
||||
"ticks": 9,
|
||||
"synaptic": 24243,
|
||||
"input": 172
|
||||
},
|
||||
{
|
||||
"net": "snn",
|
||||
"label": 6,
|
||||
"answer": 6,
|
||||
"ticks": 9,
|
||||
"synaptic": 23217,
|
||||
"input": 163
|
||||
},
|
||||
{
|
||||
"net": "snn",
|
||||
"label": 9,
|
||||
"answer": 9,
|
||||
"ticks": 9,
|
||||
"synaptic": 18540,
|
||||
"input": 132
|
||||
},
|
||||
{
|
||||
"net": "snn",
|
||||
"label": 0,
|
||||
"answer": 0,
|
||||
"ticks": 9,
|
||||
"synaptic": 22741,
|
||||
"input": 162
|
||||
},
|
||||
{
|
||||
"net": "snn",
|
||||
"label": 1,
|
||||
"answer": 1,
|
||||
"ticks": 9,
|
||||
"synaptic": 12139,
|
||||
"input": 84
|
||||
},
|
||||
{
|
||||
"net": "cols",
|
||||
"label": 4,
|
||||
"answer": 9,
|
||||
"ticks": 15,
|
||||
"synaptic": 237200,
|
||||
"input": 1186
|
||||
},
|
||||
{
|
||||
"net": "cols",
|
||||
"label": 7,
|
||||
"answer": 9,
|
||||
"ticks": 15,
|
||||
"synaptic": 180000,
|
||||
"input": 900
|
||||
},
|
||||
{
|
||||
"net": "cols",
|
||||
"label": 3,
|
||||
"answer": 7,
|
||||
"ticks": 15,
|
||||
"synaptic": 132800,
|
||||
"input": 664
|
||||
},
|
||||
{
|
||||
"net": "cols",
|
||||
"label": 9,
|
||||
"answer": 4,
|
||||
"ticks": 15,
|
||||
"synaptic": 101800,
|
||||
"input": 509
|
||||
},
|
||||
{
|
||||
"net": "cols",
|
||||
"label": 3,
|
||||
"answer": 2,
|
||||
"ticks": 15,
|
||||
"synaptic": 165400,
|
||||
"input": 827
|
||||
},
|
||||
{
|
||||
"net": "cols",
|
||||
"label": 2,
|
||||
"answer": -1,
|
||||
"ticks": 15,
|
||||
"synaptic": 377000,
|
||||
"input": 1885
|
||||
},
|
||||
{
|
||||
"net": "cols",
|
||||
"label": 8,
|
||||
"answer": 9,
|
||||
"ticks": 15,
|
||||
"synaptic": 215400,
|
||||
"input": 1077
|
||||
},
|
||||
{
|
||||
"net": "cols",
|
||||
"label": 7,
|
||||
"answer": 7,
|
||||
"ticks": 15,
|
||||
"synaptic": 130600,
|
||||
"input": 653
|
||||
},
|
||||
{
|
||||
"net": "cols",
|
||||
"label": 0,
|
||||
"answer": 0,
|
||||
"ticks": 15,
|
||||
"synaptic": 264800,
|
||||
"input": 1324
|
||||
},
|
||||
{
|
||||
"net": "cols",
|
||||
"label": 4,
|
||||
"answer": 4,
|
||||
"ticks": 15,
|
||||
"synaptic": 137200,
|
||||
"input": 686
|
||||
},
|
||||
{
|
||||
"net": "cols",
|
||||
"label": 4,
|
||||
"answer": 4,
|
||||
"ticks": 15,
|
||||
"synaptic": 121600,
|
||||
"input": 608
|
||||
},
|
||||
{
|
||||
"net": "cols",
|
||||
"label": 2,
|
||||
"answer": 7,
|
||||
"ticks": 15,
|
||||
"synaptic": 136400,
|
||||
"input": 682
|
||||
},
|
||||
{
|
||||
"net": "cols",
|
||||
"label": 2,
|
||||
"answer": 2,
|
||||
"ticks": 15,
|
||||
"synaptic": 203200,
|
||||
"input": 1016
|
||||
},
|
||||
{
|
||||
"net": "cols",
|
||||
"label": 1,
|
||||
"answer": 1,
|
||||
"ticks": 15,
|
||||
"synaptic": 70000,
|
||||
"input": 350
|
||||
},
|
||||
{
|
||||
"net": "cols",
|
||||
"label": 1,
|
||||
"answer": 1,
|
||||
"ticks": 15,
|
||||
"synaptic": 99400,
|
||||
"input": 497
|
||||
},
|
||||
{
|
||||
"net": "cols",
|
||||
"label": 4,
|
||||
"answer": 4,
|
||||
"ticks": 15,
|
||||
"synaptic": 150600,
|
||||
"input": 753
|
||||
},
|
||||
{
|
||||
"net": "cols",
|
||||
"label": 9,
|
||||
"answer": 9,
|
||||
"ticks": 15,
|
||||
"synaptic": 149400,
|
||||
"input": 747
|
||||
},
|
||||
{
|
||||
"net": "cols",
|
||||
"label": 5,
|
||||
"answer": 5,
|
||||
"ticks": 15,
|
||||
"synaptic": 216800,
|
||||
"input": 1084
|
||||
},
|
||||
{
|
||||
"net": "cols",
|
||||
"label": 9,
|
||||
"answer": 9,
|
||||
"ticks": 15,
|
||||
"synaptic": 223200,
|
||||
"input": 1116
|
||||
},
|
||||
{
|
||||
"net": "cols",
|
||||
"label": 0,
|
||||
"answer": 0,
|
||||
"ticks": 15,
|
||||
"synaptic": 213600,
|
||||
"input": 1068
|
||||
},
|
||||
{
|
||||
"net": "cols",
|
||||
"label": 6,
|
||||
"answer": 6,
|
||||
"ticks": 15,
|
||||
"synaptic": 197000,
|
||||
"input": 985
|
||||
},
|
||||
{
|
||||
"net": "cols",
|
||||
"label": 9,
|
||||
"answer": 9,
|
||||
"ticks": 15,
|
||||
"synaptic": 162800,
|
||||
"input": 814
|
||||
},
|
||||
{
|
||||
"net": "cols",
|
||||
"label": 0,
|
||||
"answer": 0,
|
||||
"ticks": 15,
|
||||
"synaptic": 210600,
|
||||
"input": 1053
|
||||
},
|
||||
{
|
||||
"net": "cols",
|
||||
"label": 1,
|
||||
"answer": 1,
|
||||
"ticks": 15,
|
||||
"synaptic": 126000,
|
||||
"input": 630
|
||||
}
|
||||
],
|
||||
"desktop_and_mobile_drawing": "passed",
|
||||
"tick_scrubbing_and_neuron_selection": "passed",
|
||||
"mobile_no_horizontal_overflow": true
|
||||
}
|
||||
BIN
reports/2026-10-21/artifact/chrome-export.zip
Normal file
BIN
reports/2026-10-21/artifact/chrome-export.zip
Normal file
Binary file not shown.
BIN
reports/2026-10-21/artifact/dark.png
Normal file
BIN
reports/2026-10-21/artifact/dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 419 KiB |
BIN
reports/2026-10-21/artifact/desktop.png
Normal file
BIN
reports/2026-10-21/artifact/desktop.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 415 KiB |
BIN
reports/2026-10-21/artifact/mobile-debug.png
Normal file
BIN
reports/2026-10-21/artifact/mobile-debug.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 402 KiB |
BIN
reports/2026-10-21/artifact/mobile.png
Normal file
BIN
reports/2026-10-21/artifact/mobile.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 397 KiB |
BIN
reports/2026-10-21/knp_docs.bundle
Normal file
BIN
reports/2026-10-21/knp_docs.bundle
Normal file
Binary file not shown.
74
reports/2026-10-21/proxy-checks.json
Normal file
74
reports/2026-10-21/proxy-checks.json
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
[
|
||||
{
|
||||
"host": "knp-columns",
|
||||
"path": "/",
|
||||
"status": 200,
|
||||
"bytes": 556820
|
||||
},
|
||||
{
|
||||
"host": "knp-shifts",
|
||||
"path": "/",
|
||||
"status": 200,
|
||||
"bytes": 601167
|
||||
},
|
||||
{
|
||||
"host": "knp-fast",
|
||||
"path": "/",
|
||||
"status": 200,
|
||||
"bytes": 7164
|
||||
},
|
||||
{
|
||||
"host": "knp-fast",
|
||||
"path": "/fast-model.js",
|
||||
"status": 200,
|
||||
"bytes": 8641
|
||||
},
|
||||
{
|
||||
"host": "knp-fast",
|
||||
"path": "/fast-gallery.json",
|
||||
"status": 200,
|
||||
"bytes": 32550
|
||||
},
|
||||
{
|
||||
"host": "knp-native",
|
||||
"path": "/",
|
||||
"status": 200,
|
||||
"bytes": 7693
|
||||
},
|
||||
{
|
||||
"host": "knp-native",
|
||||
"path": "/native-model.js",
|
||||
"status": 200,
|
||||
"bytes": 9101
|
||||
},
|
||||
{
|
||||
"host": "knp-pets",
|
||||
"path": "/",
|
||||
"status": 200,
|
||||
"bytes": 14798
|
||||
},
|
||||
{
|
||||
"host": "knp-pets",
|
||||
"path": "/api/info",
|
||||
"status": 200,
|
||||
"bytes": 287
|
||||
},
|
||||
{
|
||||
"host": "knp-digits",
|
||||
"path": "/",
|
||||
"status": 200,
|
||||
"bytes": 30683
|
||||
},
|
||||
{
|
||||
"host": "knp-digits",
|
||||
"path": "/app.js",
|
||||
"status": 200,
|
||||
"bytes": 549257
|
||||
},
|
||||
{
|
||||
"host": "knp-digits",
|
||||
"path": "/fonts.css",
|
||||
"status": 200,
|
||||
"bytes": 15020
|
||||
}
|
||||
]
|
||||
33
reports/2026-10-21/журнал.md
Normal file
33
reports/2026-10-21/журнал.md
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# Проверка состояния перед продолжением
|
||||
|
||||
По просьбе пользователя прочитаны передачи и отчёты 15 октября, выполнена read-only SSH-проверка user@10.9.8.230. Машина knp доступна, uptime около 15 минут. Порты 8080/8081/8082 не слушают; прежние демо после перезапуска не работают. Транспортный pipeline.json: completed, done=true, failed=false; runner.pid содержит исторический PID49452. Ничего не запускали, не пересобирали, модели и данные не меняли. Пароли в файлы не сохранялись.
|
||||
|
||||
Последняя остановка по передаче: муха отложена пользователем; Pet lab не совместим с Алтаем-2 как есть; native MNIST имеет отдельное подтверждение GoldenModel только в режиме replicas<=2. Возможное продолжение: восстановление демо, аппаратная адаптация отдельной новой модели либо улучшение транспорта по validation с сохранением test.
|
||||
|
||||
## Восстановлены все готовые демо
|
||||
|
||||
По запросу пользователя запущены прежние серверы через nohup: 8080 PID8214 (mnist-viz/start.sh), 8081 PID8225 (mnist-altai-native/server.py), 8082 PID8236 (pets-knp/server.py). PID сохранены в штатные runtime-файлы. С внешней машины HTTP200 у altai_viz.html, aug_viz.html, fast_viz.html, native_viz.html, fast-model.js, native-model.js, Pet lab и /api/info. Реальные запросы: MNIST первый сохранённый пример ->5 в CPU (~115ms) и GM (~5680ms); Pet lab первый gallery sample ->cat, outputs[1,0], ~445ms. Это smoke, новая accuracy не измерялась. viz/app.html содержит DATA=null и является шаблоном экспорта, самостоятельным демо не считается. Транспортного web-сервера нет, муха остаётся остановлена. Модели/библиотеки не менялись, системный автозапуск не добавлен.
|
||||
|
||||
## Запрошен перенос Claude Artifact
|
||||
|
||||
Пользователь просит целиком скопировать и захостить https://claude.ai/artifact/Vc1q1WCZuPY2QAHBSGtrKF; вики https://fs.snw.su/knp/ дана только как дополнительный источник, не как замена артефакта. Встроенный docslib-manifest вики прочитан: revision 3a6bbbb01711ce1e14f5, updated_at 2026-10-19T08:25:20.902+00:00, 23 страницы; client.js.custom содержит веса и виджеты трёх моделей, включая temporal SNN8. Эти новые данные пока не подтверждены нашими KNP-прогонами, переносить доказательства старой модели на них нельзя.
|
||||
|
||||
Ссылка Claude отдаёт оболочку с frame UUID e7a36cae-a7f7-4c83-b0f2-ff0fa979600e. В Chromium фактический API /api/frame/<uuid>?via=user_open&bk=initial&actor=id&vt=1 отвечает HTTP403 Cloudflare Just a moment; оболочка показывает Page not found. Исходный код и визуальное содержимое артефакта не получены. Аналогичный результат у обычного HTTP-запроса API. Нельзя считать Page not found доказательством удаления артефакта, поскольку причина наблюдаемого отказа — Cloudflare. Подменять артефакт отдельной страницей по вики пользователь не просил. Новая страница не создана, прежние демо не менялись. Для точного переноса требуется экспорт HTML/React исходника артефакта либо доступный источник.
|
||||
|
||||
## Артефакт из Chrome Ctrl+S перенесён и опубликован
|
||||
|
||||
Пользователь предоставил ZIP http://drop.t.snw.su/mearl, SHA256 94bf2e99581aec06cbec3078c50c93dcffd1907e40b954006d1fa444aae4eaf7. ZIP содержит полный inner saved_resource.html с данными COLS/SNN/gallery и кодом. Источник архивирован в reports/2026-10-21/artifact/chrome-export.zip. Создан mnist-artifact/prepare.py и site, SOURCE.json фиксирует SHA256 оригинального приложения и результата. Удалён Claude runtime/оболочка, встроенный код расчёта сохранён дословно после двух строк очистки DOM: Chrome сохранил уже сгенерированные кнопки, без очистки они дублируются. Шрифты (18 файлов) локализованы, добавлены viewport/lang. Веса, обучение и UI исходника не переписывались. Исходная кнопка Clear очищает только рисунок, сохраняет прежний результат до нового ввода; это поведение сохранено.
|
||||
|
||||
Публичный URL http://knp-digits.t.snw.su/ через отдельный Caddy block, /opt/knp-digits. Конфигурация проверена caddy validate перед reload; прежние block не менялись, HTTPS не включался. На станции /home/user/KNP/viz/digits-compare, URL http://10.9.8.230:8080/digits-compare/; все 21 SHA256 совпали. Оба URL HTTP200, JS200. Перед записью на станции подтверждены completed pipeline и отсутствие collection. Исходные модели/библиотеки/данные и прежние демо не менялись.
|
||||
|
||||
Chromium: 24 примера ×2 сети=48 реальных браузерных распознаваний, 2 кнопки переключателя, 24 gallerybuttons, стартовая3->3; slider0/8, выбор нейрона, mouse/touch strokes, мобильный390 без horizontaloverflow, light/dark; JS errors0 и failedrequests0. Сохранены browser-checks.json и desktop/dark/mobile PNG. При первой touch-проверке начало жеста попало под sticky navigation; тест исправлен, прикладной код не менялся, реальное touch распознавание прошло. Перенос не является повторной оценкой accuracy или проверкой KNP/GoldenModel новой SNN. Указанные92,2%/97,4% — сведения источника.
|
||||
|
||||
## Сохранён исходный Git-репозиторий вики
|
||||
По просьбе пользователя только сохранён ssh://git@git.snw.su:30301/pgups/knp_docs.git. Полный clone /root/knp_docs, main HEAD540cdb9fed49a1c910437e0944454e8a56f88ffd («Добавить run.sh для сервера, домен knp.snw.su»), рабочее дерево чистое. Резервная копия полной истории и refs: reports/2026-10-21/knp_docs.bundle, git bundle verify успешен, SHA256 5a5c9bfb8f0f65d9fad3ef3073143f4dc1d13c141879f3163f890a715a1bc7db. Код не запускался, сайты/модели/станция не менялись, commit/push нет.
|
||||
|
||||
## Все готовые локальные демо доступны через Caddy reverse proxy
|
||||
По запросу пользователя добавлены отдельные HTTPдомены: knp-columns.t.snw.su ->10.9.8.230:8080/altai_viz.html; knp-shifts ->8080/aug_viz.html; knp-fast ->8080/fast_viz.html; knp-native ->8081/native_viz.html; knp-pets ->8082/. knp-digits.t.snw.su переведён с локального file_server на reverse_proxy 10.9.8.230:8080 с префиксом /digits-compare. Корневые URL первых четырёх переписываются на соответствующую страницу, относительные assets/API продолжают работать. Wiki исключена, никаких новых транспортных/flyсайтов не создавалось. Прочие Caddyhosts сохранены, validate перед reload успешен, HTTPS не включали.
|
||||
Проверены12 HTML/JS/JSON/CSS/API URL — HTTP200, результаты proxy-checks.json. Реальное PetAPI через новый домен:cat,outputs[1,0],402ms. NativePOST через домен: blank200. Сервисы/модели/библиотеки на станции не менялись, commit/push нет. Актуальная вики по уточнению пользователя только https://knp.snw.su/; fs.snw.su устарел и больше не используется.
|
||||
|
||||
## Подготовка push по явному запросу пользователя
|
||||
Пользователь явно разрешил «отпушь все». Основной checkout /root/our_knp, origin ssh://git@git.snw.su:30301/int/our_knp.git, main. Сохранены только относящиеся к KNP шесть Caddyblocks в deployment/knp-demos.Caddyfile, без чужой серверной конфигурации. Исходники артефакта, локальные шрифты, browserproofs, исходный Chromeexport, bundle вики и передачи включаются в commit. Проверка экспорта не обнаружила непустых строковых значений assetToken/access_token/refresh_token/share_key/consentToken/token. Репозиторий самой вики /root/knp_docs чистый, изменений для push там нет.
|
||||
329
viz/digits-compare/app.js
Normal file
329
viz/digits-compare/app.js
Normal file
File diff suppressed because one or more lines are too long
396
viz/digits-compare/fonts.css
Normal file
396
viz/digits-compare/fonts.css
Normal file
|
|
@ -0,0 +1,396 @@
|
|||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/13ff14c8cbbde52dd267.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/fd8b74284fe6ff9705c0.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/560980fcddc4e6f493d8.woff2) format('woff2');
|
||||
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/99228c3b93e78c59da72.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/f582230492bfd11eff7b.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/6d5e7fb80500edbb2ccc.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/13ff14c8cbbde52dd267.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/fd8b74284fe6ff9705c0.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/560980fcddc4e6f493d8.woff2) format('woff2');
|
||||
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/99228c3b93e78c59da72.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/f582230492bfd11eff7b.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/6d5e7fb80500edbb2ccc.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/13ff14c8cbbde52dd267.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/fd8b74284fe6ff9705c0.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/560980fcddc4e6f493d8.woff2) format('woff2');
|
||||
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/99228c3b93e78c59da72.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/f582230492bfd11eff7b.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-stretch: 100%;
|
||||
font-display: swap;
|
||||
src: url(./fonts/6d5e7fb80500edbb2ccc.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(./fonts/6b5e37b52d26eeac6a19.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(./fonts/eb83d8d40af4411f395f.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(./fonts/99e400330f36ae77c882.woff2) format('woff2');
|
||||
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(./fonts/c4064400db3750ce826c.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(./fonts/b19c2080652a3c2b1288.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(./fonts/cc27b30471250057c5e6.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(./fonts/6b5e37b52d26eeac6a19.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(./fonts/eb83d8d40af4411f395f.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(./fonts/99e400330f36ae77c882.woff2) format('woff2');
|
||||
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(./fonts/c4064400db3750ce826c.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(./fonts/b19c2080652a3c2b1288.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(./fonts/cc27b30471250057c5e6.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* arabic */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(./fonts/90a469f8becd8517007a.woff2) format('woff2');
|
||||
unicode-range: U+0600-06FF, U+0750-077F, U+0870-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC, U+102E0-102FB, U+10E60-10E7E, U+10EC2-10EC7, U+10EC9-10EEE, U+10EF0-10EFF, U+1EE00-1EE03, U+1EE05-1EE1F, U+1EE21-1EE22, U+1EE24, U+1EE27, U+1EE29-1EE32, U+1EE34-1EE37, U+1EE39, U+1EE3B, U+1EE42, U+1EE47, U+1EE49, U+1EE4B, U+1EE4D-1EE4F, U+1EE51-1EE52, U+1EE54, U+1EE57, U+1EE59, U+1EE5B, U+1EE5D, U+1EE5F, U+1EE61-1EE62, U+1EE64, U+1EE67-1EE6A, U+1EE6C-1EE72, U+1EE74-1EE77, U+1EE79-1EE7C, U+1EE7E, U+1EE80-1EE89, U+1EE8B-1EE9B, U+1EEA1-1EEA3, U+1EEA5-1EEA9, U+1EEAB-1EEBB, U+1EEF0-1EEF1;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(./fonts/23f931dc9e4c044ca281.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(./fonts/0c46fc34202128a8b356.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* hebrew */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(./fonts/04b5819e5fda60389774.woff2) format('woff2');
|
||||
unicode-range: U+0307-0308, U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(./fonts/c062627ec16ce1b40510.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(./fonts/547062430ce141b89109.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* arabic */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(./fonts/90a469f8becd8517007a.woff2) format('woff2');
|
||||
unicode-range: U+0600-06FF, U+0750-077F, U+0870-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC, U+102E0-102FB, U+10E60-10E7E, U+10EC2-10EC7, U+10EC9-10EEE, U+10EF0-10EFF, U+1EE00-1EE03, U+1EE05-1EE1F, U+1EE21-1EE22, U+1EE24, U+1EE27, U+1EE29-1EE32, U+1EE34-1EE37, U+1EE39, U+1EE3B, U+1EE42, U+1EE47, U+1EE49, U+1EE4B, U+1EE4D-1EE4F, U+1EE51-1EE52, U+1EE54, U+1EE57, U+1EE59, U+1EE5B, U+1EE5D, U+1EE5F, U+1EE61-1EE62, U+1EE64, U+1EE67-1EE6A, U+1EE6C-1EE72, U+1EE74-1EE77, U+1EE79-1EE7C, U+1EE7E, U+1EE80-1EE89, U+1EE8B-1EE9B, U+1EEA1-1EEA3, U+1EEA5-1EEA9, U+1EEAB-1EEBB, U+1EEF0-1EEF1;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(./fonts/23f931dc9e4c044ca281.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(./fonts/0c46fc34202128a8b356.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* hebrew */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(./fonts/04b5819e5fda60389774.woff2) format('woff2');
|
||||
unicode-range: U+0307-0308, U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(./fonts/c062627ec16ce1b40510.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(./fonts/547062430ce141b89109.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
BIN
viz/digits-compare/fonts/04b5819e5fda60389774.woff2
Normal file
BIN
viz/digits-compare/fonts/04b5819e5fda60389774.woff2
Normal file
Binary file not shown.
BIN
viz/digits-compare/fonts/0c46fc34202128a8b356.woff2
Normal file
BIN
viz/digits-compare/fonts/0c46fc34202128a8b356.woff2
Normal file
Binary file not shown.
BIN
viz/digits-compare/fonts/13ff14c8cbbde52dd267.woff2
Normal file
BIN
viz/digits-compare/fonts/13ff14c8cbbde52dd267.woff2
Normal file
Binary file not shown.
BIN
viz/digits-compare/fonts/23f931dc9e4c044ca281.woff2
Normal file
BIN
viz/digits-compare/fonts/23f931dc9e4c044ca281.woff2
Normal file
Binary file not shown.
BIN
viz/digits-compare/fonts/547062430ce141b89109.woff2
Normal file
BIN
viz/digits-compare/fonts/547062430ce141b89109.woff2
Normal file
Binary file not shown.
BIN
viz/digits-compare/fonts/560980fcddc4e6f493d8.woff2
Normal file
BIN
viz/digits-compare/fonts/560980fcddc4e6f493d8.woff2
Normal file
Binary file not shown.
BIN
viz/digits-compare/fonts/6b5e37b52d26eeac6a19.woff2
Normal file
BIN
viz/digits-compare/fonts/6b5e37b52d26eeac6a19.woff2
Normal file
Binary file not shown.
BIN
viz/digits-compare/fonts/6d5e7fb80500edbb2ccc.woff2
Normal file
BIN
viz/digits-compare/fonts/6d5e7fb80500edbb2ccc.woff2
Normal file
Binary file not shown.
BIN
viz/digits-compare/fonts/90a469f8becd8517007a.woff2
Normal file
BIN
viz/digits-compare/fonts/90a469f8becd8517007a.woff2
Normal file
Binary file not shown.
BIN
viz/digits-compare/fonts/99228c3b93e78c59da72.woff2
Normal file
BIN
viz/digits-compare/fonts/99228c3b93e78c59da72.woff2
Normal file
Binary file not shown.
BIN
viz/digits-compare/fonts/99e400330f36ae77c882.woff2
Normal file
BIN
viz/digits-compare/fonts/99e400330f36ae77c882.woff2
Normal file
Binary file not shown.
BIN
viz/digits-compare/fonts/b19c2080652a3c2b1288.woff2
Normal file
BIN
viz/digits-compare/fonts/b19c2080652a3c2b1288.woff2
Normal file
Binary file not shown.
BIN
viz/digits-compare/fonts/c062627ec16ce1b40510.woff2
Normal file
BIN
viz/digits-compare/fonts/c062627ec16ce1b40510.woff2
Normal file
Binary file not shown.
BIN
viz/digits-compare/fonts/c4064400db3750ce826c.woff2
Normal file
BIN
viz/digits-compare/fonts/c4064400db3750ce826c.woff2
Normal file
Binary file not shown.
BIN
viz/digits-compare/fonts/cc27b30471250057c5e6.woff2
Normal file
BIN
viz/digits-compare/fonts/cc27b30471250057c5e6.woff2
Normal file
Binary file not shown.
BIN
viz/digits-compare/fonts/eb83d8d40af4411f395f.woff2
Normal file
BIN
viz/digits-compare/fonts/eb83d8d40af4411f395f.woff2
Normal file
Binary file not shown.
BIN
viz/digits-compare/fonts/f582230492bfd11eff7b.woff2
Normal file
BIN
viz/digits-compare/fonts/f582230492bfd11eff7b.woff2
Normal file
Binary file not shown.
BIN
viz/digits-compare/fonts/fd8b74284fe6ff9705c0.woff2
Normal file
BIN
viz/digits-compare/fonts/fd8b74284fe6ff9705c0.woff2
Normal file
Binary file not shown.
180
viz/digits-compare/index.html
Normal file
180
viz/digits-compare/index.html
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html lang="ru"><head><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><!-- frame-runtime --><!-- /frame-runtime --><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><style>:root{color-scheme:light;box-sizing:border-box;padding-top:env(safe-area-inset-top,0px);padding-bottom:env(safe-area-inset-bottom,0px)}html{scroll-padding-top:env(safe-area-inset-top,0px)}body{margin:0;padding:0;font:14px -apple-system,BlinkMacSystemFont,sans-serif;background:#fff;color:#000}img{max-width:100%}[hidden]:not([hidden=until-found i]){display:none!important}</style></head><body>
|
||||
<title>Цифры на «Алтае»</title>
|
||||
<meta name="claude:viewport-fit-sides" content="cover">
|
||||
|
||||
<link rel="stylesheet" href="./fonts.css">
|
||||
<style>
|
||||
/* Layout: one column of three numbered stages (до / внутри / после) under a sticky network switch; pixel views are always on a dark "scope" ground */
|
||||
:root {
|
||||
--bg: #F2F4F6; --panel: #FFFFFF; --ink: #16202A; --muted: #586674; --line: #D8DEE4;
|
||||
--scope: #0D1318; --scope-dim: #27323C; --spike: #CF5A16; --charge: #137F89; --neg: #B0435A; --good: #2E7D4B; --bad: #B23B3B;
|
||||
--spike-on-scope: #F2903F; --charge-on-scope: #38BAC3; --neg-on-scope: #E06A80;
|
||||
--f-display: "Rubik", "Trebuchet MS", sans-serif; --f-body: "IBM Plex Sans", "Segoe UI", Arial, sans-serif; --f-mono: "JetBrains Mono", "Courier New", monospace;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) {
|
||||
--bg: #0E1318; --panel: #161D24; --ink: #E6EBEF; --muted: #95A3AF; --line: #27323C;
|
||||
--scope: #080C10; --scope-dim: #222C35; --spike: #F08A3E; --charge: #3DBDC6; --neg: #E07085; --good: #5DBE7C; --bad: #EE6B6B; color-scheme: dark } }
|
||||
:root[data-theme="dark"] {
|
||||
--bg: #0E1318; --panel: #161D24; --ink: #E6EBEF; --muted: #95A3AF; --line: #27323C;
|
||||
--scope: #080C10; --scope-dim: #222C35; --spike: #F08A3E; --charge: #3DBDC6; --neg: #E07085; --good: #5DBE7C; --bad: #EE6B6B; color-scheme: dark }
|
||||
* { box-sizing: border-box }
|
||||
body { background: var(--bg); color: var(--ink); font: 16px/1.5 var(--f-body); }
|
||||
body::before { content: ""; position: fixed; inset: 0 0 auto; height: env(safe-area-inset-top, 0px); z-index: 10; background: var(--bg) }
|
||||
.wrap { max-width: 1120px; margin: 0 auto; padding-left: max(16px, env(safe-area-inset-left, 0px)); padding-right: max(16px, env(safe-area-inset-right, 0px)); padding-block: 28px 64px; display: flex; flex-direction: column; gap: 28px }
|
||||
h1, h2, h3 { font-family: var(--f-display); font-weight: 600; margin: 0; text-wrap: balance; line-height: 1.15 }
|
||||
h1 { font-size: clamp(28px, 4.2vw, 42px) }
|
||||
h2 { font-size: 24px }
|
||||
h3 { font-size: 17px }
|
||||
p { margin: 0 }
|
||||
.lead { color: var(--muted); max-width: 68ch; font-size: 17px }
|
||||
.mono { font-family: var(--f-mono); font-variant-numeric: tabular-nums }
|
||||
.muted { color: var(--muted) }
|
||||
.small { font-size: 14px }
|
||||
.eyebrow { font-family: var(--f-mono); font-size: 13px; letter-spacing: .08em; text-transform: uppercase; color: var(--spike) }
|
||||
.head { display: flex; flex-direction: column; gap: 10px }
|
||||
|
||||
.switch { position: sticky; top: env(safe-area-inset-top, 0px); z-index: 5; background: var(--bg); padding-block: 8px; display: flex; flex-wrap: wrap; gap: 8px }
|
||||
.switch button { flex: 1 1 240px; text-align: left; font: inherit; color: var(--ink); background: var(--panel); border: 1.5px solid var(--line); border-radius: 12px; padding: 10px 14px; cursor: pointer; display: flex; flex-direction: column; gap: 2px }
|
||||
.switch button b { font-family: var(--f-display); font-weight: 600; font-size: 16px }
|
||||
.switch button span { color: var(--muted); font-size: 14px }
|
||||
.switch button[aria-pressed="true"] { border-color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink) }
|
||||
button:focus-visible, canvas:focus-visible, input:focus-visible { outline: 2px solid var(--charge); outline-offset: 2px }
|
||||
|
||||
.panel { background: var(--panel); border: 1px solid var(--line); border-radius: 16px; padding: 20px; display: flex; flex-direction: column; gap: 16px; min-width: 0 }
|
||||
.row { display: flex; flex-wrap: wrap; gap: 16px; align-items: flex-start }
|
||||
.row > * { min-width: 0 }
|
||||
.grow { flex: 1 1 280px }
|
||||
.btn { font: inherit; font-size: 15px; color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 10px; padding: 7px 14px; cursor: pointer }
|
||||
.btn:hover { border-color: var(--muted) }
|
||||
.btn.primary { background: var(--ink); color: var(--panel); border-color: var(--ink) }
|
||||
|
||||
.pad { width: 280px; max-width: 100%; aspect-ratio: 1; display: block; border-radius: 14px; background: #000; touch-action: none; cursor: crosshair }
|
||||
.px { image-rendering: pixelated; background: var(--scope); border-radius: 10px; display: block }
|
||||
.fig { display: flex; flex-direction: column; gap: 6px; align-items: flex-start }
|
||||
.cap { font-size: 13px; color: var(--muted); max-width: 22ch; line-height: 1.35 }
|
||||
.gal { display: flex; flex-wrap: wrap; gap: 5px }
|
||||
.gal button { padding: 2px; border: 2px solid var(--line); border-radius: 9px; background: var(--scope); cursor: pointer; line-height: 0 }
|
||||
.gal button[aria-pressed="true"] { border-color: var(--spike) }
|
||||
.gal canvas { width: 34px; height: 34px; image-rendering: pixelated; border-radius: 5px }
|
||||
|
||||
.answer { display: grid; grid-template-columns: auto 1fr; gap: 4px 18px; align-items: center }
|
||||
.answer .digit { grid-row: span 3; font-family: var(--f-mono); font-size: 84px; font-weight: 600; line-height: 1 }
|
||||
.verdict { font-weight: 600 }
|
||||
.verdict.ok { color: var(--good) } .verdict.no { color: var(--bad) }
|
||||
.facts { display: flex; flex-wrap: wrap; gap: 6px 18px; font-size: 14px; color: var(--muted) }
|
||||
.facts b { color: var(--ink); font-family: var(--f-mono); font-weight: 600 }
|
||||
|
||||
.stage-title { display: flex; align-items: baseline; gap: 12px }
|
||||
.stage-title .n { font-family: var(--f-mono); font-size: 14px; color: var(--muted); border: 1px solid var(--line); border-radius: 99px; padding: 1px 9px }
|
||||
.flow { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 10px }
|
||||
.flow .arrow { align-self: center; color: var(--muted); font-size: 22px; padding-top: 0 }
|
||||
|
||||
.transport { display: flex; flex-wrap: wrap; align-items: center; gap: 12px }
|
||||
.transport input[type=range] { flex: 1 1 200px; accent-color: var(--spike) }
|
||||
.story { background: var(--bg); border-radius: 12px; padding: 12px 16px; max-width: 80ch }
|
||||
.views { display: grid; grid-template-columns: auto auto minmax(0, 1fr); gap: 20px; align-items: start }
|
||||
@media (max-width: 760px) { .views { grid-template-columns: 1fr 1fr } .views > .outs { grid-column: 1 / -1 } }
|
||||
.lanes { display: flex; flex-direction: column; gap: 3px; width: 100% }
|
||||
.lane { display: grid; grid-template-columns: 18px minmax(60px, 1fr) 64px; gap: 10px; align-items: center; padding: 3px 8px; border-radius: 8px; font-family: var(--f-mono); font-size: 14px }
|
||||
.lane.fire { background: color-mix(in srgb, var(--spike) 16%, transparent) }
|
||||
.lane.lead { box-shadow: inset 0 0 0 1.5px var(--good) }
|
||||
.lane .bar { height: 12px; border-radius: 4px; background: var(--line); position: relative; overflow: hidden }
|
||||
.lane .bar i { position: absolute; inset: 0 auto 0 0; background: var(--charge) }
|
||||
.lane .bar i.votes { background: var(--spike) }
|
||||
.lane .dots { display: flex; gap: 3px; flex-wrap: wrap }
|
||||
.lane .dots i { width: 8px; height: 8px; border-radius: 50%; background: var(--spike) }
|
||||
.lane b { font-weight: 400; color: var(--muted); text-align: right }
|
||||
.colgrid { display: grid; grid-template-columns: 16px auto; gap: 0 6px; align-items: stretch }
|
||||
.colgrid .labels { display: grid; grid-template-rows: repeat(10, 1fr); font-family: var(--f-mono); font-size: 12px; color: var(--muted); text-align: right }
|
||||
.colgrid .labels span { display: flex; align-items: center; justify-content: flex-end }
|
||||
.legend { display: flex; flex-wrap: wrap; gap: 6px 16px; font-size: 13px; color: var(--muted) }
|
||||
.legend span::before { content: ""; display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 6px; vertical-align: -1px; background: var(--c) }
|
||||
.ramp { display: inline-block; width: 120px; height: 10px; border-radius: 3px; vertical-align: -1px; margin: 0 6px }
|
||||
|
||||
.inspect { display: grid; grid-template-columns: auto auto minmax(0, 1fr); gap: 18px; align-items: start; border-top: 1px solid var(--line); padding-top: 16px }
|
||||
@media (max-width: 760px) { .inspect { grid-template-columns: 1fr 1fr } .inspect > .txt { grid-column: 1 / -1 } }
|
||||
.voters { display: flex; flex-wrap: wrap; gap: 8px }
|
||||
.voters button { display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 4px; border: 1.5px solid var(--line); border-radius: 10px; background: var(--panel); color: var(--ink); cursor: pointer; font: 12px var(--f-mono) }
|
||||
.voters button[aria-pressed="true"] { border-color: var(--spike) }
|
||||
.voters canvas { width: 56px; height: 56px; image-rendering: pixelated; border-radius: 6px; background: var(--scope) }
|
||||
.spark { width: 100%; max-width: 360px; height: 90px; display: block }
|
||||
.after { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 20px }
|
||||
@media (max-width: 760px) { .after { grid-template-columns: 1fr } }
|
||||
.cost { display: flex; flex-direction: column; gap: 10px }
|
||||
.cost .line { display: grid; grid-template-columns: 1fr auto; gap: 12px; border-bottom: 1px solid var(--line); padding-bottom: 6px; font-size: 15px }
|
||||
.cost .line b { font-family: var(--f-mono); font-weight: 600 }
|
||||
.train p + p { margin-top: 8px }
|
||||
.train ol { margin: 8px 0 0; padding-left: 22px; display: flex; flex-direction: column; gap: 6px; max-width: 80ch }
|
||||
@media (prefers-reduced-motion: reduce) { * { transition: none !important } }
|
||||
</style>
|
||||
|
||||
<div class="wrap">
|
||||
<header class="head">
|
||||
<p class="eyebrow">KNP · AltAI · импульсные сети</p>
|
||||
<h1>Как сеть на «Алтае» узнаёт цифру</h1>
|
||||
<p class="lead">Нарисуйте цифру или выберите тестовую. Ниже видно всё, что с ней происходит: как обычный процессор готовит картинку, как спайки идут через сеть такт за тактом и как из них получается ответ. Расчёт точный и целочисленный, по тем же правилам, что на чипе.</p>
|
||||
</header>
|
||||
|
||||
<nav class="switch" id="switch" aria-label="Сеть"><button type="button" data-net="snn" aria-pressed="true"><b>Последняя версия: Сеть по тактам</b><span>97,4% на тесте · 8 тактов · обучена на компьютере</span></button><button type="button" data-net="cols" aria-pressed="false"><b>Первая версия: Колонки STDP</b><span>92,2% на тесте · 15 тактов · обучена в KNP</span></button></nav>
|
||||
|
||||
<section class="panel">
|
||||
<div class="row">
|
||||
<div class="fig">
|
||||
<canvas id="pad" class="pad" width="280" height="280" aria-label="Поле для рисования цифры"></canvas>
|
||||
<div class="row" style="gap:10px;align-items:center"><button class="btn" id="clear">Очистить</button><span class="small muted" id="src">Тестовая цифра «3», №381</span></div>
|
||||
</div>
|
||||
<div class="grow" style="display:flex;flex-direction:column;gap:16px">
|
||||
<div class="answer" aria-live="polite">
|
||||
<span class="digit" id="ans">3</span>
|
||||
<span class="small muted" id="ansNet">Последняя версия: Сеть по тактам</span>
|
||||
<span class="verdict ok" id="verdict">верно</span>
|
||||
<span class="small muted" id="ansNote">ответ ясен с такта 4 из 8</span>
|
||||
</div>
|
||||
<div class="facts" id="netFacts"><span>тактов <b>9</b></span><span>входных спайков <b>142</b></span><span>спайков нейронов <b>42</b></span><span>сложений на чипе <b>19 604</b></span></div>
|
||||
<div style="display:flex;flex-direction:column;gap:6px">
|
||||
<span class="small muted">Тестовые цифры MNIST — сеть их не видела при обучении</span>
|
||||
<div class="gal" id="gal" role="group" aria-label="Тестовые цифры"><button type="button" aria-label="Цифра 4, тест №447" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 7, тест №124" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 3, тест №381" aria-pressed="true"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 9, тест №92" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 3, тест №158" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 2, тест №222" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 8, тест №290" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 7, тест №0" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 0, тест №3" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 4, тест №4" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 4, тест №115" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 2, тест №321" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 2, тест №1" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 1, тест №2" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 1, тест №5" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 4, тест №6" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 9, тест №7" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 5, тест №8" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 9, тест №9" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 0, тест №10" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 6, тест №11" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 9, тест №12" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 0, тест №13" aria-pressed="false"><canvas width="28" height="28"></canvas></button><button type="button" aria-label="Цифра 1, тест №14" aria-pressed="false"><canvas width="28" height="28"></canvas></button></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="panel" aria-labelledby="t1">
|
||||
<div class="stage-title"><span class="n">1</span><h2 id="t1">До сети: обычный процессор готовит вход</h2></div>
|
||||
<p class="muted" id="beforeText">Сеть училась на цифрах определённого вида, поэтому процессор сначала приводит рисунок к нему: вписывает в квадрат 20×20, ставит центр масс в центр поля 28×28, выпрямляет наклон и уменьшает с усреднением, чтобы края стали серыми. Потом каждый пиксель ярче 32 получает момент своего единственного спайка: чем ярче, тем раньше.</p>
|
||||
<div class="flow" id="flow"><div class="fig"><canvas width="28" height="28" class="px" aria-label="1. исходная цифра MNIST" style="width: 140px; height: 140px; max-width: 100%;"></canvas><span class="cap">1. исходная цифра MNIST</span></div><span class="arrow" aria-hidden="true">→</span><div class="fig"><canvas width="28" height="28" class="px" aria-label="2. в квадрат 20×20, центр масс в центр" style="width: 140px; height: 140px; max-width: 100%;"></canvas><span class="cap">2. в квадрат 20×20, центр масс в центр</span></div><span class="arrow" aria-hidden="true">→</span><div class="fig"><canvas width="28" height="28" class="px" aria-label="3. наклон выпрямлен" style="width: 140px; height: 140px; max-width: 100%;"></canvas><span class="cap">3. наклон выпрямлен</span></div><span class="arrow" aria-hidden="true">→</span><div class="fig"><canvas width="28" height="28" class="px" aria-label="4. уменьшение с усреднением: вход сети" style="width: 140px; height: 140px; max-width: 100%;"></canvas><span class="cap">4. уменьшение с усреднением: вход сети</span></div><span class="arrow" aria-hidden="true">→</span><div class="fig"><canvas width="28" height="28" class="px" aria-label="Моменты спайков" style="width: 140px; height: 140px; max-width: 100%;"></canvas><span class="cap">5. моменты спайков: яркое стреляет на такте 0, тусклое — на 7-м. Всего 142 спайков</span></div></div>
|
||||
</section>
|
||||
|
||||
<section class="panel" aria-labelledby="t2">
|
||||
<div class="stage-title"><span class="n">2</span><h2 id="t2">Внутри сети: такт за тактом</h2></div>
|
||||
<div class="transport">
|
||||
<button class="btn primary" id="play">▶ Пуск</button>
|
||||
<input type="range" id="tick" min="0" max="8" value="0" aria-label="Такт">
|
||||
<span class="mono" id="tickLab">такт 8 из 8</span>
|
||||
</div>
|
||||
<p class="story" id="story">Такт 8, последний. Новых пикселей нет: выходы получают последние спайки скрытого слоя. Выходы получили 1 спайков скрытого слоя с прошлого такта, выстрелили «3». Лидер «3» больше не сменится — ответ ясен уже сейчас.</p>
|
||||
<div class="views" id="views"><div class="fig"><span class="cap">784 входа: пиксели, стреляющие сейчас</span><canvas width="28" height="28" class="px" aria-label="Входные спайки на этом такте" style="width: 168px; height: 168px; max-width: 100%;"></canvas></div><div class="fig"><span class="cap">256 скрытых нейронов (нажмите на любой)</span><canvas width="16" height="16" class="px" aria-label="256 скрытых нейронов" tabindex="0" style="width: 168px; height: 168px; max-width: 100%; cursor: pointer;"></canvas></div><div class="fig outs"><span class="cap">10 выходов: заряд до порога 8 и спайки</span><div class="lanes"><div class="lane"><span>0</span><div class="bar" title="заряд 0 из 8"><i style="width:0%"></i></div><div class="dots"><b>0</b></div></div><div class="lane"><span>1</span><div class="bar" title="заряд 1 из 8"><i style="width:12.5%"></i></div><div class="dots"><b>0</b></div></div><div class="lane"><span>2</span><div class="bar" title="заряд 3 из 8"><i style="width:37.5%"></i></div><div class="dots"><i></i><b></b></div></div><div class="lane fire lead"><span>3</span><div class="bar" title="заряд 0 из 8"><i style="width:0%"></i></div><div class="dots"><i></i><i></i><i></i><i></i><i></i><b></b></div></div><div class="lane"><span>4</span><div class="bar" title="заряд 2 из 8"><i style="width:25%"></i></div><div class="dots"><b>0</b></div></div><div class="lane"><span>5</span><div class="bar" title="заряд 3 из 8"><i style="width:37.5%"></i></div><div class="dots"><b>0</b></div></div><div class="lane"><span>6</span><div class="bar" title="заряд 0 из 8"><i style="width:0%"></i></div><div class="dots"><b>0</b></div></div><div class="lane"><span>7</span><div class="bar" title="заряд 4 из 8"><i style="width:50%"></i></div><div class="dots"><i></i><i></i><i></i><b></b></div></div><div class="lane"><span>8</span><div class="bar" title="заряд 3 из 8"><i style="width:37.5%"></i></div><div class="dots"><b>0</b></div></div><div class="lane"><span>9</span><div class="bar" title="заряд 2 из 8"><i style="width:25%"></i></div><div class="dots"><i></i><b></b></div></div></div></div></div>
|
||||
<div class="legend" id="legend"><span style="--c: var(--spike-on-scope)">спайк на этом такте</span><span style="--c: var(--charge-on-scope)">заряд нейрона</span><span style="--c: var(--scope-dim)">пиксель уже выстрелил</span></div>
|
||||
<div class="inspect" id="inspect"><div class="fig"><span class="cap">Нейрон №112: что он ищет</span><canvas width="28" height="28" class="px" aria-label="Веса нейрона 112" style="width: 168px; height: 168px; max-width: 100%;"></canvas><span class="cap">бирюзовый — вес «+», красный — вес «−»</span></div><div class="fig"><span class="cap">что дала ему эта картинка</span><canvas width="28" height="28" class="px" aria-label="Что этот нейрон получил от картинки" style="width: 168px; height: 168px; max-width: 100%;"></canvas><span class="cap">сумма весов по закрашенным пикселям: +31</span></div><div class="txt" style="display:flex;flex-direction:column;gap:10px"><h3>Нейрон №112: 3 спайков за картинку</h3><p class="small muted">Скрытый нейрон — это детектор кусочка формы. Бирюзовые пиксели заряжают его, красные — разряжают. Набрал 8 — выстрелил и отправил спайк выходам.</p><p class="small"><b>Связи к выходам: </b>0: −2 · 1: +2 · 3: +4 · 4: −1 · 5: −1 · 6: +2 · 7: +2 · 8: −2 · 9: −2</p><div><span class="cap" style="max-width:none">заряд по тактам: растёт, когда приходят веса; дошёл до порога — спайк (оранжевая точка), и порог вычитается. Красный пунктир — сумма за такт оказалась ниже нуля, и заряд обрезан до 0: хранить минус нейрону не разрешено настройкой</span><svg viewBox="0 0 360 110" class="spark" role="img" aria-label="Заряд нейрона по тактам"><line x1="16" x2="344" y1="42.42857142857143" y2="42.42857142857143" stroke="#95A3AF" stroke-dasharray="4 4" stroke-width="1"></line><text x="344" y="38.42857142857143" text-anchor="end" font-size="11" fill="#95A3AF" font-family="JetBrains Mono, monospace">порог 8</text><line x1="16" x2="344" y1="84.71428571428571" y2="84.71428571428571" stroke="#95A3AF" stroke-width="1" opacity="0.5"></line><text x="344" y="96.71428571428571" text-anchor="end" font-size="11" fill="#95A3AF" font-family="JetBrains Mono, monospace">0</text><line x1="303" x2="303" y1="84.71428571428571" y2="90" stroke="#E07085" stroke-width="2" stroke-dasharray="3 3"></line><circle cx="303" cy="90" r="2.5" fill="#E07085"></circle><path d="M8,84.71428571428571 L16,53 L16,53 L57,16 L57,58.285714285714285 L98,53 L98,53 L139,42.42857142857143 L139,84.71428571428571 L180,63.57142857142857 L180,63.57142857142857 L221,58.285714285714285 L221,58.285714285714285 L262,37.142857142857146 L262,79.42857142857143 L303,84.71428571428571 L303,84.71428571428571 L344,84.71428571428571 L344,84.71428571428571" fill="none" stroke="#3DBDC6" stroke-width="2" stroke-linejoin="round"></path><circle cx="57" cy="16" r="4" fill="#F08A3E"></circle><rect x="55" y="2" width="4" height="10" rx="1" fill="#F08A3E"></rect><circle cx="139" cy="42.42857142857143" r="4" fill="#F08A3E"></circle><rect x="137" y="2" width="4" height="10" rx="1" fill="#F08A3E"></rect><circle cx="262" cy="37.142857142857146" r="4" fill="#F08A3E"></circle><rect x="260" y="2" width="4" height="10" rx="1" fill="#F08A3E"></rect><line x1="344" x2="344" y1="0" y2="94" stroke="#E6EBEF" stroke-width="1" opacity="0.35"></line><text x="16" y="107" text-anchor="start" font-size="11" fill="#95A3AF" font-family="JetBrains Mono, monospace">такт 0</text><text x="344" y="107" text-anchor="end" font-size="11" fill="#95A3AF" font-family="JetBrains Mono, monospace">такт 8</text></svg></div><h3>Больше всего за «3» проголосовали</h3><div class="voters"><button type="button" aria-pressed="true" aria-label="Нейрон 112"><canvas width="28" height="28"></canvas><span>№112 +12</span></button><button type="button" aria-pressed="false" aria-label="Нейрон 150"><canvas width="28" height="28"></canvas><span>№150 +8</span></button><button type="button" aria-pressed="false" aria-label="Нейрон 109"><canvas width="28" height="28"></canvas><span>№109 +4</span></button><button type="button" aria-pressed="false" aria-label="Нейрон 168"><canvas width="28" height="28"></canvas><span>№168 +4</span></button><button type="button" aria-pressed="false" aria-label="Нейрон 120"><canvas width="28" height="28"></canvas><span>№120 +2</span></button><button type="button" aria-pressed="false" aria-label="Нейрон 165"><canvas width="28" height="28"></canvas><span>№165 +2</span></button></div></div></div>
|
||||
</section>
|
||||
|
||||
<section class="panel" aria-labelledby="t3">
|
||||
<div class="stage-title"><span class="n">3</span><h2 id="t3">После сети: ответ и цена</h2></div>
|
||||
<div class="after">
|
||||
<div style="display:flex;flex-direction:column;gap:10px"><p id="ruleText">Процессор считает спайки десяти выходных нейронов. Ответ — цифра, чей нейрон выстрелил больше всех; при равенстве — тот, кто выстрелил раньше.</p><div class="lanes" id="final"><div class="lane"><span>0</span><div class="bar"><i class="votes" style="width:0%"></i></div><b>0 сп.</b></div><div class="lane"><span>1</span><div class="bar"><i class="votes" style="width:0%"></i></div><b>0 сп.</b></div><div class="lane"><span>2</span><div class="bar"><i class="votes" style="width:20%"></i></div><b>1 сп.</b></div><div class="lane lead"><span>3</span><div class="bar"><i class="votes" style="width:100%"></i></div><b>5 сп.</b></div><div class="lane"><span>4</span><div class="bar"><i class="votes" style="width:0%"></i></div><b>0 сп.</b></div><div class="lane"><span>5</span><div class="bar"><i class="votes" style="width:0%"></i></div><b>0 сп.</b></div><div class="lane"><span>6</span><div class="bar"><i class="votes" style="width:0%"></i></div><b>0 сп.</b></div><div class="lane"><span>7</span><div class="bar"><i class="votes" style="width:60%"></i></div><b>3 сп.</b></div><div class="lane"><span>8</span><div class="bar"><i class="votes" style="width:0%"></i></div><b>0 сп.</b></div><div class="lane"><span>9</span><div class="bar"><i class="votes" style="width:20%"></i></div><b>1 сп.</b></div></div></div>
|
||||
<div class="cost" id="cost"><h3>Сколько работы у чипа</h3><div class="line"><span>входных спайков</span><b>142</b></div><div class="line"><span>спайков нейронов</span><b>42</b></div><div class="line"><span>сложений «спайк → вес»</span><b>19 604</b></div><div class="line"><span>обычная сеть 784→256→10, умножений</span><b>203 264</b></div><p class="small muted">Каждый входной спайк задевает в среднем ≈139 из 256 скрытых нейронов: у остальных вес 0, и такая связь на чипе не создаётся. Поэтому работы примерно 143 × 139 ≈ 20 тыс. сложений.</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="panel train" aria-labelledby="t4">
|
||||
<h2 id="t4">Как эта сеть обучена</h2>
|
||||
<div id="train"><p>Обучена на обычном компьютере (PyTorch), а не в KNP: на чип загружаются готовые целые веса. 55 000 цифр MNIST, 30 эпох (проходов по всем цифрам), около 17 минут на процессоре без видеокарты.</p><ol><li>При обучении сеть считает ровно как чип: 8 тактов, целые веса, порог 8, вычитание порога после спайка, задержка в такт между слоями.</li><li>Спайк — это ступенька, у неё нет производной. При расчёте ошибки ступенька подменяется плавной «горкой» (суррогатный градиент), и сеть понимает, куда сдвигать веса.</li><li>С 9-й эпохи веса округляются до допустимых на чипе 0, ±1, ±2, ±4, и сеть доучивается уже с ними. Плюс небольшой штраф за лишние спайки.</li><li>Половина обучающих цифр перерисована пером постоянной толщины, как мышью, плюс сдвиги и повороты. Поэтому сеть хорошо узнаёт рисунки: 95,9% на перерисованном тесте.</li><li>Лучшая эпоха выбрана на 5000 отложенных цифрах отдельным целочисленным симулятором; тест открыт один раз.</li></ol></div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<script src="./app.js"></script>
|
||||
</body></html>
|
||||
37
viz/digits-compare/source.json
Normal file
37
viz/digits-compare/source.json
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"source": "https://claude.ai/artifact/Vc1q1WCZuPY2QAHBSGtrKF",
|
||||
"export_url": "http://drop.t.snw.su/mearl",
|
||||
"archive_sha256": "94bf2e99581aec06cbec3078c50c93dcffd1907e40b954006d1fa444aae4eaf7",
|
||||
"inner_html_sha256": "4807bae6973ccc560b51aaf7c60f4b2b8be8d529aeb6848db86036522df2249d",
|
||||
"original_app_sha256": "61ea4ea4db5926c7c8a17f7ce057707fab9b01c6a121fd2e619c42d91b92846c",
|
||||
"changes": [
|
||||
"remove Claude iframe runtime",
|
||||
"clear saved controls before original startup",
|
||||
"local font files",
|
||||
"viewport and Russian document language"
|
||||
],
|
||||
"inference_code_and_weights": "preserved verbatim after the control-reset prelude",
|
||||
"files": {
|
||||
"app.js": "4ef53f5ebcac9b3b489daaf2dfb409a9d520fcc80e5e9502c4e789dce86e9744",
|
||||
"fonts/04b5819e5fda60389774.woff2": "197b6dbe5c6bec7276c59b02d70a16ee6acd44322fc2f8d0226c07f8d57976c2",
|
||||
"fonts/0c46fc34202128a8b356.woff2": "bdb2b33ab916e9e7b42edb61f8aea5f5dd83ad773d6ee4e9b55665daf8954ce8",
|
||||
"fonts/13ff14c8cbbde52dd267.woff2": "7d0037a170882a49e65a45c38ef195237bb07b1cc791d078379f0ac0d7ae1935",
|
||||
"fonts/23f931dc9e4c044ca281.woff2": "35e30483bb79be6fd8de0fec4e038fda9e637fc7337f6ff61418c7d08077878b",
|
||||
"fonts/547062430ce141b89109.woff2": "691cd1d9b4c0cdf31a1dcf04259c86f92c85e69f6622abab7964d81e36890691",
|
||||
"fonts/560980fcddc4e6f493d8.woff2": "f598dd0700f155e2facfaa8ecfacace397d4c2c153e9ce37ab7ad310e8505bc2",
|
||||
"fonts/6b5e37b52d26eeac6a19.woff2": "62213be8a78b42f1e29d1452d91e2f8b3e745572a9dd98d3941e39fa00b37d76",
|
||||
"fonts/6d5e7fb80500edbb2ccc.woff2": "e2291e842cf5af167122a22881a740c7f2dda7716f1e8cd76680264f4a859470",
|
||||
"fonts/90a469f8becd8517007a.woff2": "f5052e4870bf211fc22df5b85e791a292a77b9baef8cef1dc5a8e62a783ea1e0",
|
||||
"fonts/99228c3b93e78c59da72.woff2": "73e7f7b1c980416ae0c2461268b14c7cfcce0668e683dc43fbb11a82a227b9f2",
|
||||
"fonts/99e400330f36ae77c882.woff2": "0a557721b1f8b36d3f3f84442689a71ca4a744300abcb46a1953f51bfc663b66",
|
||||
"fonts/b19c2080652a3c2b1288.woff2": "db5ff4db83e580426280e9337a58dc57d3a83784a1b03ad80914651594441d52",
|
||||
"fonts/c062627ec16ce1b40510.woff2": "09472f217ad1ebb61a7669cf532f9f2f80685e07652ee862fde9a79665aef479",
|
||||
"fonts/c4064400db3750ce826c.woff2": "c89b9cc0bc6262bd4f8d8494b6961601f3aefa829d08c2e3635f4d501d3a47c2",
|
||||
"fonts/cc27b30471250057c5e6.woff2": "83c005d49d8a6a50474c73a5a36ac0468076e9c4a29da7bdb14995d80560a5be",
|
||||
"fonts/eb83d8d40af4411f395f.woff2": "e17cfd15fb96909d64095015f958207063a0c07191da3512df7d560a781aebdf",
|
||||
"fonts/f582230492bfd11eff7b.woff2": "d160e20920ae4d6556518d352d3af27a74e9b0de3d8fe17b1c1044fc75aa2f81",
|
||||
"fonts/fd8b74284fe6ff9705c0.woff2": "9409ee21811f0f5272b7e1d828fe8838005b0573481ef906e7e55b63f6610ab0",
|
||||
"fonts.css": "564d3c95a3b80d7c5ae21347ab77028cb10125812c24520a12f584fa880a6f61",
|
||||
"index.html": "cfb514c642469601364b4482d3ce7cde715ef8fbbf0b0f099fb5dd43466b6eb3"
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue