UNPKG

@lobehub/chat

Version:

Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.

183 lines (170 loc) • 6.43 kB
import { Pricing } from 'model-bank'; import { describe, expect, it } from 'vitest'; import { getAudioInputUnitRate, getAudioOutputUnitRate, getCachedAudioInputUnitRate, getCachedTextInputUnitRate, getTextInputUnitRate, getTextOutputUnitRate, getUnitRateByName, getWriteCacheInputUnitRate, } from './pricing'; describe('pricing utilities (new)', () => { describe('getUnitRateByName', () => { it('returns undefined when pricing or unitName is missing', () => { expect(getUnitRateByName()).toBeUndefined(); const p = { units: [] } as Pricing; expect(getUnitRateByName(p)).toBeUndefined(); }); it('returns undefined when unit not found', () => { const pricing: Pricing = { units: [{ name: 'textOutput', strategy: 'fixed', unit: 'millionTokens', rate: 0.002 }], }; expect(getUnitRateByName(pricing, 'textInput')).toBeUndefined(); }); it('handles fixed strategy', () => { const pricing: Pricing = { units: [{ name: 'textInput', strategy: 'fixed', unit: 'millionTokens', rate: 0.001 }], }; expect(getUnitRateByName(pricing, 'textInput')).toBe(0.001); }); it('handles tiered strategy (first tier)', () => { const pricing: Pricing = { units: [ { name: 'audioInput', strategy: 'tiered', unit: 'second', tiers: [ { rate: 0.01, upTo: 3600 }, { rate: 0.008, upTo: 'infinity' }, ], }, ], }; expect(getUnitRateByName(pricing, 'audioInput')).toBe(0.01); }); it('returns undefined when tiered.tiers is absent or empty', () => { const noTiers: Pricing = { units: [ { name: 'textInput', strategy: 'tiered', unit: 'millionTokens', tiers: undefined as any }, ], }; const emptyTiers: Pricing = { units: [{ name: 'textInput', strategy: 'tiered', unit: 'millionTokens', tiers: [] }], }; expect(getUnitRateByName(noTiers, 'textInput')).toBeUndefined(); expect(getUnitRateByName(emptyTiers, 'textInput')).toBeUndefined(); }); it('handles lookup strategy (first price value)', () => { const pricing: Pricing = { units: [ { name: 'textInput', strategy: 'lookup', unit: 'millionTokens', lookup: { pricingParams: ['model'], prices: { a: 0.001, b: 0.03 }, }, }, ], }; expect(getUnitRateByName(pricing, 'textInput')).toBe(0.001); }); it('returns undefined when lookup missing or has no prices', () => { const missingLookup: Pricing = { units: [ { name: 'textInput', strategy: 'lookup', unit: 'millionTokens', lookup: undefined as any, }, ], } as any; const emptyPrices: Pricing = { units: [ { name: 'textInput', strategy: 'lookup', unit: 'millionTokens', lookup: { pricingParams: ['model'], prices: {} }, }, ], }; expect(getUnitRateByName(missingLookup, 'textInput')).toBeUndefined(); expect(getUnitRateByName(emptyPrices, 'textInput')).toBeUndefined(); }); it('works with multiple units', () => { const pricing: Pricing = { units: [ { name: 'textInput', strategy: 'fixed', unit: 'millionTokens', rate: 0.001 }, { name: 'textOutput', strategy: 'fixed', unit: 'millionTokens', rate: 0.002 }, { name: 'audioInput', strategy: 'tiered', unit: 'second', tiers: [ { rate: 0.01, upTo: 3600 }, { rate: 0.008, upTo: 'infinity' }, ], }, ], }; expect(getUnitRateByName(pricing, 'textInput')).toBe(0.001); expect(getUnitRateByName(pricing, 'textOutput')).toBe(0.002); expect(getUnitRateByName(pricing, 'audioInput')).toBe(0.01); }); }); describe('wrapper helpers', () => { it('return the same values as getUnitRateByName for each unit', () => { const pricing: Pricing = { units: [ { name: 'textInput', strategy: 'fixed', unit: 'millionTokens', rate: 0.001 }, { name: 'textOutput', strategy: 'fixed', unit: 'millionTokens', rate: 0.002 }, { name: 'audioInput', strategy: 'tiered', unit: 'second', tiers: [ { rate: 0.01, upTo: 3600 }, { rate: 0.008, upTo: 'infinity' }, ], }, { name: 'audioOutput', strategy: 'fixed', unit: 'second', rate: 0.015 }, { name: 'textInput_cacheRead', strategy: 'fixed', unit: 'millionTokens', rate: 0.0005 }, { name: 'textInput_cacheWrite', strategy: 'lookup', unit: 'millionTokens', lookup: { pricingParams: ['ttl'], prices: { '5': 0.2, '60': 0.6 } }, }, { name: 'audioInput_cacheRead', strategy: 'fixed', unit: 'second', rate: 0.005 }, ], }; expect(getTextInputUnitRate(pricing)).toBe(getUnitRateByName(pricing, 'textInput')); expect(getTextOutputUnitRate(pricing)).toBe(getUnitRateByName(pricing, 'textOutput')); expect(getAudioInputUnitRate(pricing)).toBe(getUnitRateByName(pricing, 'audioInput')); expect(getAudioOutputUnitRate(pricing)).toBe(getUnitRateByName(pricing, 'audioOutput')); expect(getCachedTextInputUnitRate(pricing)).toBe( getUnitRateByName(pricing, 'textInput_cacheRead'), ); expect(getWriteCacheInputUnitRate(pricing)).toBe( getUnitRateByName(pricing, 'textInput_cacheWrite'), ); expect(getCachedAudioInputUnitRate(pricing)).toBe( getUnitRateByName(pricing, 'audioInput_cacheRead'), ); // also validate expected concrete values for clarity expect(getTextInputUnitRate(pricing)).toBe(0.001); expect(getTextOutputUnitRate(pricing)).toBe(0.002); expect(getAudioInputUnitRate(pricing)).toBe(0.01); expect(getAudioOutputUnitRate(pricing)).toBe(0.015); expect(getCachedTextInputUnitRate(pricing)).toBe(0.0005); expect(getWriteCacheInputUnitRate(pricing)).toBe(0.2); expect(getCachedAudioInputUnitRate(pricing)).toBe(0.005); }); }); });