ai-functions
Version:
A powerful TypeScript library for building AI-powered applications with template literals and structured outputs
86 lines • 3.27 kB
JavaScript
export class StreamProgressTracker {
constructor(options) {
this.tokensGenerated = 0;
this.startTime = Date.now();
this.lastUpdateTime = Date.now();
this.tokenRate = 0;
this.alpha = 0.3; // EMA smoothing factor
this.options = options;
this.callback = options.onProgress || (() => { });
}
updateTokenRate(newTokens) {
const now = Date.now();
const timeDiff = now - this.lastUpdateTime;
if (timeDiff > 0) {
// Calculate instantaneous rate
const instantRate = newTokens / timeDiff;
// Apply exponential moving average for smoother rate
if (this.tokenRate === 0) {
this.tokenRate = instantRate;
}
else {
this.tokenRate = (this.alpha * instantRate) + ((1 - this.alpha) * this.tokenRate);
}
this.lastUpdateTime = now;
}
}
estimateTimeRemaining() {
if (!this.options.estimateTimeRemaining || this.tokenRate === 0) {
return undefined;
}
// Use dynamic estimation based on current progress
const progressRatio = this.tokensGenerated / Math.max(100, this.tokensGenerated * 2);
const estimatedTotalTokens = Math.max(this.tokensGenerated * (1 + (1 - progressRatio)), this.tokensGenerated + 100);
const remainingTokens = estimatedTotalTokens - this.tokensGenerated;
const estimatedMs = remainingTokens / this.tokenRate;
// Return undefined if estimate is unreasonable
return estimatedMs > 0 && estimatedMs < 3600000 ? estimatedMs : undefined;
}
onChunk(chunk) {
// Rough token count estimation (can be replaced with more accurate counting)
const estimatedTokens = Math.ceil(chunk.length / 4);
this.tokensGenerated += estimatedTokens;
if (this.options.enableTokenCounting) {
this.updateTokenRate(estimatedTokens);
}
const progress = {
type: 'chunk',
chunk,
...(this.options.enableTokenCounting && {
tokensGenerated: this.tokensGenerated,
}),
...(this.options.estimateTimeRemaining && {
estimatedTimeRemaining: this.estimateTimeRemaining(),
}),
};
this.callback(progress);
}
onToken(token) {
this.tokensGenerated += 1;
if (this.options.enableTokenCounting) {
this.updateTokenRate(1);
}
const progress = {
type: 'token',
chunk: token,
...(this.options.enableTokenCounting && {
tokensGenerated: this.tokensGenerated,
}),
...(this.options.estimateTimeRemaining && {
estimatedTimeRemaining: this.estimateTimeRemaining(),
}),
};
this.callback(progress);
}
onComplete() {
const progress = {
type: 'complete',
...(this.options.enableTokenCounting && {
tokensGenerated: this.tokensGenerated,
totalTokens: this.tokensGenerated,
}),
};
this.callback(progress);
}
}
//# sourceMappingURL=stream-progress.js.map