openvibers/openvibe.exchange Commits
The refusal rate of an offer, with the day it was measured (#102)
Changes
@@@ -16,6 +16,17 @@ const money = (n, free = false) => (free ? 'free' : n == null ? '–' : n === 0const inOut = (price) => (price ? `${money(price.in)} in · ${money(price.out)} out` : 'no per-token price');const ms = (n) => (n == null ? '–' : n < 1000 ? `${Math.round(n)} ms` : `${(n / 1000).toFixed(1)} s`);const pct = (n) => (n == null ? '–' : `${(n * 100).toFixed(1)}%`);++++/**++ * The refusal rate of an offer, with the day it was measured. The rate is a share of the published probe set++ * (OpenVibe.AI measures it), and a number without its date would look current when it may be weeks old, so++ * the day is part of the number. An offer nobody measured shows nothing at all: no rate, no dash.++ */++const refusalText = (o) => {++ if (!o || o.refusal_rate == null) return null;++ const date = o.refusal_measured_on ? ` (measured ${o.refusal_measured_on})` : '';++ return `refuses ${pct(o.refusal_rate)}${date}`;++};const count = (n) => (n == null ? '–' : Number(n).toLocaleString('en-US'));const blended = (price) => (price ? (Number(price.in) + Number(price.out)) / 2 : Number.POSITIVE_INFINITY);const cheapest = (m) => (m.offers || []).filter((o) => o.price).sort((a, b) => blended(a.price) - blended(b.price))[0] || null;@@@ -134,7 +145,8 @@ function modelRow(m, { withTry = true } = {}) {// A stat not measured yet is left out, never printed as a dash ("– · –" read as noise in a row).if (best) bits.push(providerLabel(best), inOut(best.price), ...(best.speed && best.speed.p50_ms != null ? [ms(best.speed.p50_ms)] : []), ...(best.uptime != null ? [`${pct(best.uptime)} up`] : []));else if (m.offers[0]) bits.push(providerLabel(m.offers[0]), 'free capacity');-- if (best && best.refusal_rate != null) bits.push(`refuses ${pct(best.refusal_rate)}`);++ const refuses = refusalText(best);++ if (refuses) bits.push(refuses);const pv = privacyOf(best || m.offers[0]);if (pv) bits.push(pv.short);return `<li class="ex-mrow">@@@ -305,12 +317,13 @@ function modelPage({ model, viewer, result = null, problem = null, text = '', ad];const rows = offers.map((o) => {const p = privacyOf(o);++ const refuses = refusalText(o);return {provider: `<a class="ex-offer-name" href="#try">${esc(providerLabel(o))}</a>${o.trust === 'community' ? ` ${kit.badge('Community', 'accent')}` : ''}${freeTier(o) ? ` ${kit.badge('Free to try')}` : (freePaused(o) ? ` ${kit.badge('Free paused')}` : '')}`,price: o.price ? `<b>${money(o.price.in)}</b> / ${money(o.price.out)}` : '<span class="ex-muted">free capacity</span>',speed: `${ms(o.speed.p50_ms)} <small>p50</small> · ${ms(o.speed.p95_ms)} <small>p95</small>`,uptime: o.uptime == null ? '–' : pct(o.uptime),-- privacy: p ? `${kit.badge(p.label, p.kind)}${o.refusal_rate != null ? `<br><small>refuses ${pct(o.refusal_rate)}</small>` : ''}` : '–',++ privacy: `${p ? kit.badge(p.label, p.kind) : ''}${refuses ? `<br><small>${esc(refuses)}</small>` : ''}` || '–',policy: policyText(o.data_policy),try: '<a class="ex-mini" href="#try">Try it</a>',};@@@ -448,6 +461,7 @@ ${keyPrivacy && keyPrivacy.note ? kit.notice({ kind: 'info', text: keyPrivacy.no</form>`);return `<div class="ex-wrap ex-page">${kit.head({ title: 'The API', sub: 'One endpoint. OpenAI and Anthropic compatible.', actions: [kit.button({ href: '/chat', label: 'Chat', icon: 'chat', kind: 'quiet' })] })}++${panel({ title: 'Batches, at half price', body: `<p class="ex-prose">Half price. Answered within your deadline when spare low-cost capacity is free; if none comes free in time, the prompt expires and you pay nothing.</p>` })}${panel({ title: 'One endpoint', body: `<p class="ex-prose"><code>${ENDPOINT}</code> speaks OpenAI's Chat Completions; <code>https://api.openvibe.exchange/v1/messages</code> speaks Anthropic's Messages API, so Claude Code works by pointing <code>ANTHROPIC_BASE_URL</code> at it.</p>${kit.snippet({ code: `curl ${ENDPOINT} \\\n -H "Authorization: Bearer $OPENVIBE_KEY" \\\n -H "Content-Type: application/json" \\\n -d '{"model":"openvibe/auto","messages":[{"role":"user","content":"Hello"}]}'`, id: 'api-curl' })}nnew file mode 100644@@@ -0,0 +1,45 @@++'use strict';++/**++ * The measured refusal rate on an offer, and the day it was measured.++ *++ * The rate is measured by OpenVibe.AI on a published probe set and travels on the catalog's offer. The page++ * shows it with the day it was measured: a share without its date would look current when it may be weeks++ * old. An offer nobody measured shows no rate at all.++ */++const assert = require('assert');++const { boot, check, done } = require('./helpers/boot');++const { createFakeAi } = require('./helpers/ai');++++const offer = {++ provider: 'shared', provider_name: 'Shared provider', model: 'deepseek-chat', id: 'deepseek/deepseek-chat@v1',++ trust: 'first-party', free: false, price: { in: 0.2, out: 0.3 }, speed: { p50_ms: 400, p95_ms: 800 },++ uptime: 0.99, requests_7d: 5, data_policy: { trains: false, retention_days: 0 },++};++const model = {++ slug: 'deepseek/deepseek-chat', canonical: 'deepseek/deepseek-chat', name: 'DeepSeek Chat', family: 'DeepSeek',++ kind: 'chat', capabilities: {}, requests_7d: 5, offers: [offer],++};++const catalogWith = (o) => async () => ({ generated_at: '', models: [{ ...model, offers: [o] }], families: [], count: 1 });++++(async () => {++ const c = await boot({ ai: { ...createFakeAi(), catalog: catalogWith({ ...offer, refusal_rate: 0.25, refusal_measured_on: '2026-11-07' }) } });++ try {++ await check('an offer shows its refusal rate with the day it was measured', async () => {++ const r = await c.get('/m/deepseek/deepseek-chat');++ assert.strictEqual(r.status, 200, r.text);++ assert.ok(r.text.includes('refuses 25.0%'), 'the rate is shown as a percentage');++ assert.ok(r.text.includes('measured 2026-11-07'), 'and with the day it was measured');++ });++ } finally { await c.close(); }++++ const u = await boot({ ai: { ...createFakeAi(), catalog: catalogWith({ ...offer, refusal_rate: null, refusal_measured_on: null }) } });++ try {++ await check('an offer nobody measured shows no rate at all', async () => {++ const r = await u.get('/m/deepseek/deepseek-chat');++ assert.strictEqual(r.status, 200, r.text);++ assert.ok(!/refuses \d/.test(r.text), 'no rate is shown for an offer nobody measured');++ });++ } finally { await u.close(); }++++ done();++})();
@@ -16,6 +16,17 @@ const money = (n, free = false) => (free ? 'free' : n == null ? '–' : n === 0
@@ -16,6 +16,17 @@ const money = (n, free = false) => (free ? 'free' : n == null ? '–' : n === 0
const inOut = (price) => (price ? `${money(price.in)} in · ${money(price.out)} out` : 'no per-token price');
const inOut = (price) => (price ? `${money(price.in)} in · ${money(price.out)} out` : 'no per-token price');
const ms = (n) => (n == null ? '–' : n < 1000 ? `${Math.round(n)} ms` : `${(n / 1000).toFixed(1)} s`);
const ms = (n) => (n == null ? '–' : n < 1000 ? `${Math.round(n)} ms` : `${(n / 1000).toFixed(1)} s`);
const pct = (n) => (n == null ? '–' : `${(n * 100).toFixed(1)}%`);
const pct = (n) => (n == null ? '–' : `${(n * 100).toFixed(1)}%`);
+
+/**
+ * The refusal rate of an offer, with the day it was measured. The rate is a share of the published probe set
+ * (OpenVibe.AI measures it), and a number without its date would look current when it may be weeks old, so
+ * the day is part of the number. An offer nobody measured shows nothing at all: no rate, no dash.
+ */
+const refusalText = (o) => {
+ if (!o || o.refusal_rate == null) return null;
+ const date = o.refusal_measured_on ? ` (measured ${o.refusal_measured_on})` : '';
+ return `refuses ${pct(o.refusal_rate)}${date}`;
+};
const count = (n) => (n == null ? '–' : Number(n).toLocaleString('en-US'));
const count = (n) => (n == null ? '–' : Number(n).toLocaleString('en-US'));
const blended = (price) => (price ? (Number(price.in) + Number(price.out)) / 2 : Number.POSITIVE_INFINITY);
const blended = (price) => (price ? (Number(price.in) + Number(price.out)) / 2 : Number.POSITIVE_INFINITY);
const cheapest = (m) => (m.offers || []).filter((o) => o.price).sort((a, b) => blended(a.price) - blended(b.price))[0] || null;
const cheapest = (m) => (m.offers || []).filter((o) => o.price).sort((a, b) => blended(a.price) - blended(b.price))[0] || null;
@@ -134,7 +145,8 @@ function modelRow(m, { withTry = true } = {}) {
@@ -134,7 +145,8 @@ function modelRow(m, { withTry = true } = {}) {
// A stat not measured yet is left out, never printed as a dash ("– · –" read as noise in a row).
// A stat not measured yet is left out, never printed as a dash ("– · –" read as noise in a row).
if (best) bits.push(providerLabel(best), inOut(best.price), ...(best.speed && best.speed.p50_ms != null ? [ms(best.speed.p50_ms)] : []), ...(best.uptime != null ? [`${pct(best.uptime)} up`] : []));
if (best) bits.push(providerLabel(best), inOut(best.price), ...(best.speed && best.speed.p50_ms != null ? [ms(best.speed.p50_ms)] : []), ...(best.uptime != null ? [`${pct(best.uptime)} up`] : []));
else if (m.offers[0]) bits.push(providerLabel(m.offers[0]), 'free capacity');
else if (m.offers[0]) bits.push(providerLabel(m.offers[0]), 'free capacity');
- if (best && best.refusal_rate != null) bits.push(`refuses ${pct(best.refusal_rate)}`);
+ const refuses = refusalText(best);
+ if (refuses) bits.push(refuses);
const pv = privacyOf(best || m.offers[0]);
const pv = privacyOf(best || m.offers[0]);
if (pv) bits.push(pv.short);
if (pv) bits.push(pv.short);
return `<li class="ex-mrow">
return `<li class="ex-mrow">
@@ -305,12 +317,13 @@ function modelPage({ model, viewer, result = null, problem = null, text = '', ad
@@ -305,12 +317,13 @@ function modelPage({ model, viewer, result = null, problem = null, text = '', ad
];
];
const rows = offers.map((o) => {
const rows = offers.map((o) => {
const p = privacyOf(o);
const p = privacyOf(o);
+ const refuses = refusalText(o);
return {
return {
provider: `<a class="ex-offer-name" href="#try">${esc(providerLabel(o))}</a>${o.trust === 'community' ? ` ${kit.badge('Community', 'accent')}` : ''}${freeTier(o) ? ` ${kit.badge('Free to try')}` : (freePaused(o) ? ` ${kit.badge('Free paused')}` : '')}`,
provider: `<a class="ex-offer-name" href="#try">${esc(providerLabel(o))}</a>${o.trust === 'community' ? ` ${kit.badge('Community', 'accent')}` : ''}${freeTier(o) ? ` ${kit.badge('Free to try')}` : (freePaused(o) ? ` ${kit.badge('Free paused')}` : '')}`,
price: o.price ? `<b>${money(o.price.in)}</b> / ${money(o.price.out)}` : '<span class="ex-muted">free capacity</span>',
price: o.price ? `<b>${money(o.price.in)}</b> / ${money(o.price.out)}` : '<span class="ex-muted">free capacity</span>',
speed: `${ms(o.speed.p50_ms)} <small>p50</small> · ${ms(o.speed.p95_ms)} <small>p95</small>`,
speed: `${ms(o.speed.p50_ms)} <small>p50</small> · ${ms(o.speed.p95_ms)} <small>p95</small>`,
uptime: o.uptime == null ? '–' : pct(o.uptime),
uptime: o.uptime == null ? '–' : pct(o.uptime),
- privacy: p ? `${kit.badge(p.label, p.kind)}${o.refusal_rate != null ? `<br><small>refuses ${pct(o.refusal_rate)}</small>` : ''}` : '–',
+ privacy: `${p ? kit.badge(p.label, p.kind) : ''}${refuses ? `<br><small>${esc(refuses)}</small>` : ''}` || '–',
policy: policyText(o.data_policy),
policy: policyText(o.data_policy),
try: '<a class="ex-mini" href="#try">Try it</a>',
try: '<a class="ex-mini" href="#try">Try it</a>',
};
};
@@ -448,6 +461,7 @@ ${keyPrivacy && keyPrivacy.note ? kit.notice({ kind: 'info', text: keyPrivacy.no
@@ -448,6 +461,7 @@ ${keyPrivacy && keyPrivacy.note ? kit.notice({ kind: 'info', text: keyPrivacy.no
</form>`);
</form>`);
return `<div class="ex-wrap ex-page">
return `<div class="ex-wrap ex-page">
${kit.head({ title: 'The API', sub: 'One endpoint. OpenAI and Anthropic compatible.', actions: [kit.button({ href: '/chat', label: 'Chat', icon: 'chat', kind: 'quiet' })] })}
${kit.head({ title: 'The API', sub: 'One endpoint. OpenAI and Anthropic compatible.', actions: [kit.button({ href: '/chat', label: 'Chat', icon: 'chat', kind: 'quiet' })] })}
+${panel({ title: 'Batches, at half price', body: `<p class="ex-prose">Half price. Answered within your deadline when spare low-cost capacity is free; if none comes free in time, the prompt expires and you pay nothing.</p>` })}
${panel({ title: 'One endpoint', body: `
${panel({ title: 'One endpoint', body: `
<p class="ex-prose"><code>${ENDPOINT}</code> speaks OpenAI's Chat Completions; <code>https://api.openvibe.exchange/v1/messages</code> speaks Anthropic's Messages API, so Claude Code works by pointing <code>ANTHROPIC_BASE_URL</code> at it.</p>
<p class="ex-prose"><code>${ENDPOINT}</code> speaks OpenAI's Chat Completions; <code>https://api.openvibe.exchange/v1/messages</code> speaks Anthropic's Messages API, so Claude Code works by pointing <code>ANTHROPIC_BASE_URL</code> at it.</p>
${kit.snippet({ code: `curl ${ENDPOINT} \\\n -H "Authorization: Bearer $OPENVIBE_KEY" \\\n -H "Content-Type: application/json" \\\n -d '{"model":"openvibe/auto","messages":[{"role":"user","content":"Hello"}]}'`, id: 'api-curl' })}
${kit.snippet({ code: `curl ${ENDPOINT} \\\n -H "Authorization: Bearer $OPENVIBE_KEY" \\\n -H "Content-Type: application/json" \\\n -d '{"model":"openvibe/auto","messages":[{"role":"user","content":"Hello"}]}'`, id: 'api-curl' })}
new file mode 100644
new file mode 100644
@@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
+'use strict';
+/**
+ * The measured refusal rate on an offer, and the day it was measured.
+ *
+ * The rate is measured by OpenVibe.AI on a published probe set and travels on the catalog's offer. The page
+ * shows it with the day it was measured: a share without its date would look current when it may be weeks
+ * old. An offer nobody measured shows no rate at all.
+ */
+const assert = require('assert');
+const { boot, check, done } = require('./helpers/boot');
+const { createFakeAi } = require('./helpers/ai');
+
+const offer = {
+ provider: 'shared', provider_name: 'Shared provider', model: 'deepseek-chat', id: 'deepseek/deepseek-chat@v1',
+ trust: 'first-party', free: false, price: { in: 0.2, out: 0.3 }, speed: { p50_ms: 400, p95_ms: 800 },
+ uptime: 0.99, requests_7d: 5, data_policy: { trains: false, retention_days: 0 },
+};
+const model = {
+ slug: 'deepseek/deepseek-chat', canonical: 'deepseek/deepseek-chat', name: 'DeepSeek Chat', family: 'DeepSeek',
+ kind: 'chat', capabilities: {}, requests_7d: 5, offers: [offer],
+};
+const catalogWith = (o) => async () => ({ generated_at: '', models: [{ ...model, offers: [o] }], families: [], count: 1 });
+
+(async () => {
+ const c = await boot({ ai: { ...createFakeAi(), catalog: catalogWith({ ...offer, refusal_rate: 0.25, refusal_measured_on: '2026-11-07' }) } });
+ try {
+ await check('an offer shows its refusal rate with the day it was measured', async () => {
+ const r = await c.get('/m/deepseek/deepseek-chat');
+ assert.strictEqual(r.status, 200, r.text);
+ assert.ok(r.text.includes('refuses 25.0%'), 'the rate is shown as a percentage');
+ assert.ok(r.text.includes('measured 2026-11-07'), 'and with the day it was measured');
+ });
+ } finally { await c.close(); }
+
+ const u = await boot({ ai: { ...createFakeAi(), catalog: catalogWith({ ...offer, refusal_rate: null, refusal_measured_on: null }) } });
+ try {
+ await check('an offer nobody measured shows no rate at all', async () => {
+ const r = await u.get('/m/deepseek/deepseek-chat');
+ assert.strictEqual(r.status, 200, r.text);
+ assert.ok(!/refuses \d/.test(r.text), 'no rate is shown for an offer nobody measured');
+ });
+ } finally { await u.close(); }
+
+ done();
+})();