Newer
Older
TelosDB / scripts / verify_dim.cjs
@楽曲作りまくりおじさん 楽曲作りまくりおじさん 12 hours ago 3 KB build: improve Windows resource compile logging and error messages
const { spawn } = require('child_process');
const http = require('http');
const path = require('path');

const projectRoot = path.resolve(__dirname, '..');
const llamaServerPath = path.join(projectRoot, 'bin', 'llama-server-x86_64-pc-windows-msvc.exe');
const modelPath = path.join(projectRoot, 'models', 'embeddinggemma-300m-q4_0.gguf');

console.log(`Starting llama-server with model: ${modelPath}`);

const server = spawn(llamaServerPath, [
    '-m', modelPath,
    '--embedding',
    '--port', '8081', // Use a different port to avoid conflicts
    '--host', '127.0.0.1'
], {
    cwd: path.join(projectRoot, 'bin'),
    env: { ...process.env, PATH: `${path.join(projectRoot, 'bin')};${process.env.PATH}` }
});

server.stdout.on('data', (data) => {
    // console.log(`stdout: ${data}`);
});

server.stderr.on('data', (data) => {
    // console.log(`stderr: ${data}`);
});

async function checkHealth() {
    return new Promise((resolve) => {
        const req = http.get('http://127.0.0.1:8081/health', (res) => {
            resolve(res.statusCode === 200);
        });
        req.on('error', () => resolve(false));
    });
}

async function getEmbedding() {
    return new Promise((resolve, reject) => {
        const data = JSON.stringify({
            content: "This is a test to verify embedding dimension."
        });

        const options = {
            hostname: '127.0.0.1',
            port: 8081,
            path: '/embeddings',
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Content-Length': data.length
            }
        };

        const req = http.request(options, (res) => {
            let body = '';
            res.on('data', (chunk) => body += chunk);
            res.on('end', () => {
                try {
                    const json = JSON.parse(body);
                    // llama-server can return either {results: [...]} or directly [...]
                    // And the embedding itself can be nested as [[...]]
                    let embedding = json.results ? json.results[0].embedding : (Array.isArray(json) ? json[0].embedding : json.embedding);
                    if (Array.isArray(embedding[0])) {
                        embedding = embedding[0];
                    }
                    resolve(embedding);
                } catch (e) {
                    reject(new Error(`Failed to parse response: ${body}`));
                }
            });
        });

        req.on('error', reject);
        req.write(data);
        req.end();
    });
}

(async () => {
    let attempts = 0;
    while (!(await checkHealth()) && attempts < 20) {
        attempts++;
        console.log(`Waiting for server to be ready... (${attempts}/20)`);
        await new Promise(r => setTimeout(r, 2000));
    }

    if (attempts === 20) {
        console.error("Server failed to start.");
        server.kill();
        process.exit(1);
    }

    console.log("Server is ready. Requesting embedding...");
    try {
        const embedding = await getEmbedding();
        console.log(`\n========================================`);
        console.log(`RESULT: Embedding Dimension is ${embedding.length}`);
        console.log(`========================================\n`);
    } catch (e) {
        console.error("Error getting embedding:", e.message);
    } finally {
        server.kill();
        process.exit(0);
    }
})();