Upload serve_gemma.js with huggingface_hub
Browse files- serve_gemma.js +71 -0
serve_gemma.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const http = require('http'), fs = require('fs'), path = require('path');
|
| 2 |
+
const PORT = 8150;
|
| 3 |
+
const ROOT = __dirname;
|
| 4 |
+
const SPLITS = path.join(ROOT, 'model_splits');
|
| 5 |
+
|
| 6 |
+
const MIME = {
|
| 7 |
+
'.html': 'text/html', '.js': 'text/javascript', '.mjs': 'text/javascript',
|
| 8 |
+
'.json': 'application/json', '.gguf': 'application/octet-stream',
|
| 9 |
+
'.wasm': 'application/wasm', '.ts': 'text/javascript',
|
| 10 |
+
};
|
| 11 |
+
|
| 12 |
+
http.createServer((req, res) => {
|
| 13 |
+
if (req.method === 'OPTIONS') {
|
| 14 |
+
res.writeHead(200, {
|
| 15 |
+
'Access-Control-Allow-Origin': '*',
|
| 16 |
+
'Access-Control-Allow-Methods': 'GET,HEAD',
|
| 17 |
+
'Access-Control-Allow-Headers': 'Content-Type,Range',
|
| 18 |
+
'Cross-Origin-Embedder-Policy': 'require-corp',
|
| 19 |
+
'Cross-Origin-Opener-Policy': 'same-origin',
|
| 20 |
+
});
|
| 21 |
+
return res.end();
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
let p = decodeURIComponent(req.url.split('?')[0]);
|
| 25 |
+
if (p === '/') p = '/index.html';
|
| 26 |
+
|
| 27 |
+
let fp;
|
| 28 |
+
if (p.startsWith('/model/')) {
|
| 29 |
+
fp = path.join(SPLITS, p.slice('/model/'.length));
|
| 30 |
+
} else {
|
| 31 |
+
fp = path.join(ROOT, p);
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
fs.stat(fp, (e, st) => {
|
| 35 |
+
if (e) { res.writeHead(404); return res.end('not found: ' + fp); }
|
| 36 |
+
const total = st.size;
|
| 37 |
+
const range = req.headers.range;
|
| 38 |
+
const ct = MIME[path.extname(fp)] || 'application/octet-stream';
|
| 39 |
+
|
| 40 |
+
const headers = {
|
| 41 |
+
'Content-Type': ct,
|
| 42 |
+
'Accept-Ranges': 'bytes',
|
| 43 |
+
'Access-Control-Allow-Origin': '*',
|
| 44 |
+
'Cross-Origin-Embedder-Policy': 'require-corp',
|
| 45 |
+
'Cross-Origin-Opener-Policy': 'same-origin',
|
| 46 |
+
};
|
| 47 |
+
|
| 48 |
+
if (range) {
|
| 49 |
+
const m = range.match(/bytes=(\d+)-(\d*)/);
|
| 50 |
+
if (m) {
|
| 51 |
+
const start = parseInt(m[1]);
|
| 52 |
+
const end = m[2] ? parseInt(m[2]) : total - 1;
|
| 53 |
+
headers['Content-Range'] = 'bytes ' + start + '-' + end + '/' + total;
|
| 54 |
+
headers['Content-Length'] = end - start + 1;
|
| 55 |
+
res.writeHead(206, headers);
|
| 56 |
+
fs.createReadStream(fp, { start, end }).pipe(res);
|
| 57 |
+
return;
|
| 58 |
+
}
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
headers['Content-Length'] = total;
|
| 62 |
+
res.writeHead(200, headers);
|
| 63 |
+
fs.createReadStream(fp).pipe(res);
|
| 64 |
+
});
|
| 65 |
+
}).listen(PORT, () => {
|
| 66 |
+
console.log('Gemma WebGPU on :' + PORT);
|
| 67 |
+
console.log('Model splits: ' + SPLITS);
|
| 68 |
+
const files = fs.readdirSync(SPLITS).filter(f => f.endsWith('.gguf'));
|
| 69 |
+
console.log('Split files: ' + files.length);
|
| 70 |
+
console.log('CORS + COEP/COOP headers enabled for wllama multi-threading');
|
| 71 |
+
});
|