OverviewFilesCommitsIssuesDocsReleasesPeers

P2P-Hiverelay / test / smoke / qvac-ai-service.test.js

74 lines · javascript ref:
import test from 'brittle'
import { AIService } from 'p2p-hiveservices/builtin/ai-service.js'
import { ServiceRegistry } from 'p2p-hiverelay/core/services/registry.js'

const smoke = process.env.HIVERELAY_QVAC_SMOKE === '1' ? test : test.skip

smoke('QVAC smoke - local qvac model is reachable through HiveRelay AIService', async (t) => {
  let sdk
  try {
    sdk = await import('@qvac/sdk')
  } catch (err) {
    t.fail(`@qvac/sdk is required for smoke test: ${err.message}`)
    return
  }

  const modelSrc = resolveModelSrc(sdk)
  if (!modelSrc) {
    t.fail('Set HIVERELAY_QVAC_MODEL_SRC or HIVERELAY_QVAC_MODEL_CONSTANT for the qvac smoke test')
    return
  }

  const registry = new ServiceRegistry({ metering: false })
  const ai = new AIService({ qvac: { sdk } })
  registry.register(ai)
  await registry.startAll({})
  t.teardown(() => registry.stopAll())

  const modelId = process.env.HIVERELAY_QVAC_MODEL_ID || 'qvac-smoke'
  const modelType = process.env.HIVERELAY_QVAC_MODEL_TYPE || 'llm'
  const modelConfig = parseJsonEnv('HIVERELAY_QVAC_MODEL_CONFIG') || {}
  const prompt = process.env.HIVERELAY_QVAC_PROMPT || 'Reply with the word HiveRelay.'

  await registry.handleRequest('ai', 'register-model', {
    modelId,
    type: 'llm',
    backend: 'qvac',
    modelSrc,
    modelType,
    modelConfig
  }, { role: 'local' })

  const list = await registry.handleRequest('ai', 'list-models', {}, { role: 'anonymous' })
  t.ok(list.find(m => m.modelId === modelId && m.backend === 'qvac'), 'qvac model is listed through ai.list-models')

  const result = await registry.handleRequest('ai', 'infer', {
    modelId,
    input: prompt,
    options: {
      qvac: parseJsonEnv('HIVERELAY_QVAC_COMPLETION_OPTIONS') || {}
    }
  }, { role: 'authenticated-user', remotePubkey: 'qvac-smoke' })

  t.is(result.state, 'complete', result.error || 'qvac inference completed')
  t.ok(result.result?.text && result.result.text.length > 0, 'qvac returned completion text through ai.infer')
  t.is(result.result.backend, 'qvac')
})

function resolveModelSrc (sdk) {
  if (process.env.HIVERELAY_QVAC_MODEL_SRC) return process.env.HIVERELAY_QVAC_MODEL_SRC
  const constant = process.env.HIVERELAY_QVAC_MODEL_CONSTANT
  if (!constant) return null
  return sdk[constant] || null
}

function parseJsonEnv (name) {
  const value = process.env[name]
  if (!value) return null
  try {
    return JSON.parse(value)
  } catch (err) {
    throw new Error(`${name} must be valid JSON: ${err.message}`)
  }
}