115 lines
3.5 KiB
JavaScript
115 lines
3.5 KiB
JavaScript
const { artifacts } = require('@talkingbooklet/core');
|
|
|
|
function chatConfig(overrides = {}) {
|
|
return {
|
|
ingestVersion: 'v1',
|
|
persona: 'companion',
|
|
cacheTtl: '5m',
|
|
cacheMinTokens: 4096,
|
|
cacheKeepalive: false,
|
|
cacheKeepaliveMax: 3,
|
|
modelFullContext: 'full-model',
|
|
modelHybrid: 'hybrid-model',
|
|
modelSummarizeHistory: 'summary-model',
|
|
modelJudge: 'judge-model',
|
|
modelEmbed: 'amazon.titan-embed-text-v2:0',
|
|
embedDimensions: 2,
|
|
indexAlias: 'books_current',
|
|
autoFullContextMaxTokens: 60000,
|
|
autoPremiumPlans: ['premium'],
|
|
agentMaxIterations: 4,
|
|
agentMaxToolCalls: 6,
|
|
agentTurnTimeoutMs: 120000,
|
|
maxAnswerTokensVoice: 220,
|
|
maxAnswerTokensChat: 900,
|
|
maxConcurrency: 4,
|
|
historyVerbatimTurns: 6,
|
|
historyTokenBudget: 3000,
|
|
toolResultMaxChars: 100,
|
|
chapterReturnTokenCap: 1500,
|
|
priceTable: {
|
|
'full-model': { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
|
|
'hybrid-model': { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
|
|
},
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
function sampleBook(marked = 'x'.repeat(20000)) {
|
|
return {
|
|
bookId: '3',
|
|
marked,
|
|
bookCard: {
|
|
title: 'Day 3',
|
|
author: null,
|
|
chapters: [
|
|
{ no: 2, title: 'Later', pageStart: 3, pageEnd: 4 },
|
|
{ no: 1, title: 'Opening', pageStart: 1, pageEnd: 2 },
|
|
],
|
|
},
|
|
summaries: [
|
|
{ chapterNo: 2, title: 'Later', pageStart: 3, pageEnd: 4, oneLine: 'later', summary: 'The later pages.' },
|
|
{ chapterNo: 1, title: 'Opening', pageStart: 1, pageEnd: 2, oneLine: 'open', summary: 'The opening.' },
|
|
],
|
|
chapters: [
|
|
{ chapterNo: 0, title: 'Introduction', startPage: 1, endPage: 1 },
|
|
{ chapterNo: 1, title: 'Opening', startPage: 2, endPage: 2 },
|
|
{ chapterNo: 3, title: 'Workshop', startPage: 3, endPage: 4 },
|
|
],
|
|
pages: [
|
|
{ page: 1, text: 'Welcome' },
|
|
{ page: 2, text: 'Opening body' },
|
|
{ page: 3, text: 'Workshop body' },
|
|
{ page: 4, text: 'Close' },
|
|
],
|
|
stats: { pageCount: 4, tokenCount: 100 },
|
|
};
|
|
}
|
|
|
|
function memoryStorage(bookId = '3') {
|
|
const files = {
|
|
[artifacts.marked(bookId)]: 'Hello from the booklet',
|
|
[artifacts.bookCard(bookId)]: JSON.stringify({ title: 'Day 3', chapters: [] }),
|
|
[artifacts.summaries(bookId)]: JSON.stringify([
|
|
{ chapterNo: 1, title: 'Opening', pageStart: 1, pageEnd: 1, oneLine: 'open', summary: 'Opening.' },
|
|
]),
|
|
[artifacts.stats(bookId)]: JSON.stringify({ pageCount: 1, tokenCount: 20 }),
|
|
[artifacts.chapters(bookId)]: JSON.stringify({
|
|
chapters: [{ chapterNo: 1, title: 'Opening', startPage: 1, endPage: 1 }],
|
|
}),
|
|
[artifacts.pages(bookId)]: `${JSON.stringify({ page: 1, text: 'Hello', removedLines: [] })}\n`,
|
|
};
|
|
let reads = 0;
|
|
return {
|
|
reads: () => reads,
|
|
async getText(key) {
|
|
reads += 1;
|
|
if (!(key in files)) throw new Error(`missing ${key}`);
|
|
return files[key];
|
|
},
|
|
async getJson(key) {
|
|
return JSON.parse(await this.getText(key));
|
|
},
|
|
};
|
|
}
|
|
|
|
function textStream(text, usage) {
|
|
return (async function* () {
|
|
yield { contentBlockDelta: { contentBlockIndex: 0, delta: { text } } };
|
|
yield { messageStop: { stopReason: 'end_turn' } };
|
|
yield { metadata: { usage } };
|
|
})();
|
|
}
|
|
|
|
function usage(partial) {
|
|
return {
|
|
inputTokens: 1000,
|
|
outputTokens: 0,
|
|
cacheReadInputTokens: 0,
|
|
cacheWriteInputTokens: 0,
|
|
...partial,
|
|
};
|
|
}
|
|
|
|
module.exports = { chatConfig, sampleBook, memoryStorage, textStream, usage };
|