Orginize
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
/**
|
||||
* Diagnose a GGUF on disk after load failure (magic / size / sha256).
|
||||
*/
|
||||
|
||||
/** @type {Record<string, { size: number, sha256: string }>} */
|
||||
export const BARE_OS_QVAC_KNOWN_GGUF = {
|
||||
'Qwen3-0.6B-Q4_0.gguf': {
|
||||
size: 382156480,
|
||||
sha256: '33bcc57074ec7b6eada5a90651ee546ec0c2b271002c22baf9f1b2dd1e8f75cb'
|
||||
},
|
||||
'Qwen3-1.7B-Q4_0.gguf': {
|
||||
size: 1056782912,
|
||||
sha256: 'c876f159707a4e4f70e045106c69db15bfc935a4981706fd4f65c6e7ea1e81c5'
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} filePath
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
export async function bareOsQvacDiagnoseGguf(filePath) {
|
||||
const p = String(filePath || '').trim()
|
||||
if (!p) return 'gguf: (no path)'
|
||||
/** @type {string[]} */
|
||||
const lines = ['gguf path: ' + p]
|
||||
try {
|
||||
let fs
|
||||
try {
|
||||
fs = await import('bare-fs')
|
||||
} catch {
|
||||
fs = await import('fs')
|
||||
}
|
||||
const fsp = fs.promises || fs
|
||||
const st = await fsp.stat(p)
|
||||
lines.push('size: ' + st.size + ' bytes')
|
||||
|
||||
const base =
|
||||
p.split(/[/\\]/).pop() ||
|
||||
''
|
||||
const known = BARE_OS_QVAC_KNOWN_GGUF[base.replace(/^[0-9a-f]+_/i, '')] ||
|
||||
Object.entries(BARE_OS_QVAC_KNOWN_GGUF).find(([name]) =>
|
||||
base.endsWith(name)
|
||||
)?.[1]
|
||||
if (known) {
|
||||
lines.push(
|
||||
'expectedSize: ' +
|
||||
known.size +
|
||||
(st.size === known.size ? ' (ok)' : ' (MISMATCH)')
|
||||
)
|
||||
}
|
||||
|
||||
const buf = Buffer.alloc(4)
|
||||
let fh
|
||||
try {
|
||||
if (typeof fsp.open === 'function') {
|
||||
fh = await fsp.open(p, 'r')
|
||||
if (typeof fh.read === 'function') {
|
||||
await fh.read(buf, 0, 4, 0)
|
||||
} else if (typeof fs.read === 'function' && fh.fd != null) {
|
||||
await new Promise((resolve, reject) => {
|
||||
fs.read(fh.fd, buf, 0, 4, 0, (err) => (err ? reject(err) : resolve()))
|
||||
})
|
||||
}
|
||||
} else {
|
||||
const fd = fs.openSync(p, 'r')
|
||||
fs.readSync(fd, buf, 0, 4, 0)
|
||||
fs.closeSync(fd)
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
if (fh && typeof fh.close === 'function') await fh.close()
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
const magic = buf.toString('utf8')
|
||||
lines.push('magic: ' + JSON.stringify(magic) + (magic === 'GGUF' ? ' (ok)' : ' (BAD)'))
|
||||
|
||||
if (known && st.size === known.size && st.size <= 2 * 1024 * 1024 * 1024) {
|
||||
try {
|
||||
let crypto
|
||||
try {
|
||||
crypto = await import('bare-crypto')
|
||||
} catch {
|
||||
crypto = await import('crypto')
|
||||
}
|
||||
const createHash = crypto.createHash || crypto.default?.createHash
|
||||
if (typeof createHash === 'function') {
|
||||
const hash = createHash('sha256')
|
||||
const stream = fs.createReadStream
|
||||
? fs.createReadStream(p)
|
||||
: null
|
||||
if (stream) {
|
||||
await new Promise((resolve, reject) => {
|
||||
stream.on('data', (c) => hash.update(c))
|
||||
stream.on('error', reject)
|
||||
stream.on('end', resolve)
|
||||
})
|
||||
const dig = hash.digest('hex')
|
||||
lines.push(
|
||||
'sha256: ' +
|
||||
dig +
|
||||
(dig === known.sha256 ? ' (ok)' : ' (MISMATCH want ' + known.sha256 + ')')
|
||||
)
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
lines.push('sha256: (skip ' + String(e && e.message ? e.message : e) + ')')
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
lines.push('diagnose error: ' + String(e && e.message ? e.message : e))
|
||||
}
|
||||
return lines.join('; ')
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a GGUF path from a QVAC / llama error string.
|
||||
* @param {string} msg
|
||||
* @returns {string}
|
||||
*/
|
||||
export function bareOsQvacExtractGgufPath(msg) {
|
||||
const m = /failed to load model '([^']+\.gguf)'/i.exec(String(msg || ''))
|
||||
if (m) return m[1]
|
||||
const m2 = /(\/[^\s']+\.gguf)/i.exec(String(msg || ''))
|
||||
return m2 ? m2[1] : ''
|
||||
}
|
||||
Reference in New Issue
Block a user