resig.js
Version:
Universal reactive signal library with complete platform features: signals, animations, CRDTs, scheduling, DOM integration. Works identically across React, SolidJS, Svelte, Vue, and Qwik.
277 lines • 21.5 kB
JavaScript
/**
* AI Transformer Interface
* Streaming AI integration with confidence tracking and token management
*/
import { signal } from '../core/signal';
import { createStreamingSignal } from './coalgebra';
// Base AI transformer implementation
export class BaseAITransformer {
constructor(config) {
this.confidenceSignal = signal(0);
this.tokensSignal = signal({
input: 0,
output: 0,
total: 0,
});
this.processingSignal = signal(false);
this.config = { ...config };
this.rateLimitState = {
requestCount: 0,
windowStart: Date.now(),
maxRequests: 60, // Default: 60 requests per minute
windowSize: 60000,
};
}
transform(input) {
const output = createStreamingSignal(null);
input.subscribe(async (inputValue) => {
if (inputValue === null || inputValue === undefined)
return;
try {
this.processingSignal._set(true);
// Check rate limiting
await this.checkRateLimit();
// Process the request
const response = await this.processRequest(inputValue);
// Update signals
this.confidenceSignal._set(response.confidence);
this.tokensSignal._set(response.tokens);
output._set(response.data);
}
catch (error) {
console.error('AI transformer error:', error);
this.confidenceSignal._set(0);
}
finally {
this.processingSignal._set(false);
}
});
return output;
}
async checkRateLimit() {
const now = Date.now();
// Reset window if needed
if (now - this.rateLimitState.windowStart >=
this.rateLimitState.windowSize) {
this.rateLimitState.requestCount = 0;
this.rateLimitState.windowStart = now;
}
// Check if we've exceeded the limit
if (this.rateLimitState.requestCount >= this.rateLimitState.maxRequests) {
const waitTime = this.rateLimitState.windowSize -
(now - this.rateLimitState.windowStart);
await new Promise((resolve) => setTimeout(resolve, waitTime));
return this.checkRateLimit();
}
this.rateLimitState.requestCount++;
}
confidence() {
return this.confidenceSignal;
}
tokens() {
return this.tokensSignal;
}
isProcessing() {
return this.processingSignal;
}
getModel() {
return this.config.model;
}
setConfig(config) {
this.config = { ...this.config, ...config };
}
}
// OpenAI GPT transformer
export class OpenAITransformer extends BaseAITransformer {
async processRequest(input) {
const startTime = Date.now();
try {
const response = await fetch(`${this.config.baseURL || 'https://api.openai.com/v1'}/chat/completions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${this.config.apiKey}`,
},
body: JSON.stringify({
model: this.config.model === 'gpt-4' ? 'gpt-4' : 'gpt-3.5-turbo',
messages: [{ role: 'user', content: input }],
max_tokens: this.config.maxTokens,
temperature: this.config.temperature,
stream: this.config.streaming,
}),
});
if (!response.ok) {
throw new Error(`OpenAI API error: ${response.status}`);
}
const data = await response.json();
const choice = data.choices[0];
const usage = data.usage;
return {
data: choice.message.content,
confidence: this.calculateConfidence(choice),
tokens: {
input: usage.prompt_tokens,
output: usage.completion_tokens,
total: usage.total_tokens,
},
processingTime: Date.now() - startTime,
model: data.model,
timestamp: Date.now(),
};
}
catch (error) {
throw new Error(`OpenAI processing failed: ${error}`);
}
}
calculateConfidence(choice) {
// Simple confidence calculation based on finish_reason and logprobs
if (choice.finish_reason === 'stop')
return 0.9;
if (choice.finish_reason === 'length')
return 0.7;
return 0.5;
}
}
// Mock AI transformer for testing
export class MockAITransformer extends BaseAITransformer {
async processRequest(input) {
const startTime = Date.now();
// Simulate processing delay
await new Promise((resolve) => setTimeout(resolve, 100 + Math.random() * 500));
const output = `AI response to: "${input}"`;
const inputTokens = Math.ceil(input.length / 4); // Rough token estimation
const outputTokens = Math.ceil(output.length / 4);
return {
data: output,
confidence: 0.8 + Math.random() * 0.2,
tokens: {
input: inputTokens,
output: outputTokens,
total: inputTokens + outputTokens,
},
processingTime: Date.now() - startTime,
model: 'mock-ai',
timestamp: Date.now(),
};
}
}
// Multi-modal AI transformer for vision + language
export class MultiModalTransformer extends BaseAITransformer {
async processRequest(input) {
const startTime = Date.now();
// Simulate multi-modal processing
await new Promise((resolve) => setTimeout(resolve, 200 + Math.random() * 800));
let response = '';
if (input.text)
response += `Text analysis: ${input.text}. `;
if (input.image)
response += `Image analysis: [Image content description]. `;
const inputTokens = (input.text?.length || 0) / 4 + (input.image ? 100 : 0); // Images cost more tokens
const outputTokens = response.length / 4;
return {
data: response.trim(),
confidence: 0.75 + Math.random() * 0.25,
tokens: {
input: Math.ceil(inputTokens),
output: Math.ceil(outputTokens),
total: Math.ceil(inputTokens + outputTokens),
},
processingTime: Date.now() - startTime,
model: 'multimodal-ai',
timestamp: Date.now(),
};
}
}
// Factory functions for creating AI transformers
export const createLLMTransformer = (model, config = {}) => {
const fullConfig = {
model,
maxTokens: 4000,
temperature: 0.7,
streaming: false,
timeout: 30000,
retryAttempts: 3,
rateLimitDelay: 1000,
...config,
};
switch (model) {
case 'gpt-4':
return new OpenAITransformer(fullConfig);
case 'custom':
return new MockAITransformer(fullConfig);
default:
return new MockAITransformer(fullConfig);
}
};
export const createVisionModel = (_model, config = {}) => {
const fullConfig = {
model: 'custom',
maxTokens: 2000,
temperature: 0.5,
streaming: false,
timeout: 45000,
retryAttempts: 2,
rateLimitDelay: 2000,
...config,
};
return new MultiModalTransformer(fullConfig);
};
// AI agent composition utilities
export const composeAITransformers = (first, second) => {
return {
transform: (input) => {
const intermediate = first.transform(input);
return second.transform(intermediate);
},
confidence: () => {
// Combined confidence is the minimum of both
const conf1 = first.confidence().value();
const conf2 = second.confidence().value();
return signal(Math.min(conf1, conf2));
},
tokens: () => {
// Combined token usage
const tokens1 = first.tokens().value();
const tokens2 = second.tokens().value();
return signal({
input: tokens1.input,
output: tokens2.output,
total: tokens1.total + tokens2.total,
});
},
isProcessing: () => {
// Either transformer is processing
const proc1 = first.isProcessing().value();
const proc2 = second.isProcessing().value();
return signal(proc1 || proc2);
},
getModel: () => 'composed',
setConfig: (config) => {
first.setConfig(config);
second.setConfig(config);
},
};
};
// Batch processing for multiple inputs
export const createBatchAITransformer = (baseTransformer, batchSize = 10) => {
return {
transform: (input) => {
const batched = input.buffer(batchSize);
const batchOutput = baseTransformer.transform(batched);
// Flatten batch output back to individual items
const output = createStreamingSignal(null);
batchOutput.subscribe((batch) => {
if (batch && Array.isArray(batch)) {
batch.forEach((item) => output._set(item));
}
});
return output;
},
confidence: baseTransformer.confidence,
tokens: baseTransformer.tokens,
isProcessing: baseTransformer.isProcessing,
getModel: baseTransformer.getModel,
setConfig: baseTransformer.setConfig,
};
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWktdHJhbnNmb3JtZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc3RyZWFtaW5nL2FpLXRyYW5zZm9ybWVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUVILE9BQU8sRUFBVSxNQUFNLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUVoRCxPQUFPLEVBQUUscUJBQXFCLEVBQW1CLE1BQU0sYUFBYSxDQUFDO0FBMkRyRSxxQ0FBcUM7QUFDckMsTUFBTSxPQUFnQixpQkFBaUI7SUFXckMsWUFBWSxNQUFnQjtRQVRsQixxQkFBZ0IsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDN0IsaUJBQVksR0FBRyxNQUFNLENBQWE7WUFDMUMsS0FBSyxFQUFFLENBQUM7WUFDUixNQUFNLEVBQUUsQ0FBQztZQUNULEtBQUssRUFBRSxDQUFDO1NBQ1QsQ0FBQyxDQUFDO1FBQ08scUJBQWdCLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBSXpDLElBQUksQ0FBQyxNQUFNLEdBQUcsRUFBRSxHQUFHLE1BQU0sRUFBRSxDQUFDO1FBQzVCLElBQUksQ0FBQyxjQUFjLEdBQUc7WUFDcEIsWUFBWSxFQUFFLENBQUM7WUFDZixXQUFXLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRTtZQUN2QixXQUFXLEVBQUUsRUFBRSxFQUFFLGtDQUFrQztZQUNuRCxVQUFVLEVBQUUsS0FBSztTQUNsQixDQUFDO0lBQ0osQ0FBQztJQUlELFNBQVMsQ0FBQyxLQUF5QjtRQUNqQyxNQUFNLE1BQU0sR0FBRyxxQkFBcUIsQ0FBSSxJQUFXLENBQUMsQ0FBQztRQUVyRCxLQUFLLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxVQUFVLEVBQUUsRUFBRTtZQUNuQyxJQUFJLFVBQVUsS0FBSyxJQUFJLElBQUksVUFBVSxLQUFLLFNBQVM7Z0JBQUUsT0FBTztZQUU1RCxJQUFJLENBQUM7Z0JBQ0YsSUFBSSxDQUFDLGdCQUF3QixD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