piclets / src /lib /services /textGenerationClient.ts
Fraser's picture
switch to qwen3
24561f7
raw
history blame
4.14 kB
/**
* Text Generation Client Manager
* Provides unified interface for text generation with automatic fallback
* Primary: Qwen3 (Qwen/Qwen3-Demo), Fallback: Zephyr-7B (Fraser/zephyr-7b)
*/
import { qwen3Client } from './qwen3Client';
interface TextGenerationClient {
predict(endpoint: string, params: any[]): Promise<{data: any[]}>;
testConnection?(): Promise<boolean>;
}
class TextGenerationManager {
private primaryClient: TextGenerationClient;
private fallbackClient: TextGenerationClient | null = null;
private useQwen3: boolean = true;
private connectionTested: boolean = false;
constructor() {
this.primaryClient = qwen3Client;
}
/**
* Set the fallback client (Zephyr-7B)
*/
setFallbackClient(client: TextGenerationClient) {
this.fallbackClient = client;
}
/**
* Test connection and determine which client to use
*/
async initialize(): Promise<void> {
if (this.connectionTested) return;
console.log('Testing Qwen3 connection...');
try {
if (this.primaryClient.testConnection) {
const qwen3Available = await this.primaryClient.testConnection();
if (qwen3Available) {
console.log('βœ… Qwen3 client is available and will be used for text generation');
this.useQwen3 = true;
} else {
console.log('⚠️ Qwen3 client is not available, falling back to Zephyr-7B');
this.useQwen3 = false;
}
}
} catch (error) {
console.error('Failed to test Qwen3 connection:', error);
console.log('⚠️ Falling back to Zephyr-7B due to connection error');
this.useQwen3 = false;
}
this.connectionTested = true;
}
/**
* Get the active client for text generation
*/
private getActiveClient(): TextGenerationClient {
if (this.useQwen3) {
return this.primaryClient;
} else if (this.fallbackClient) {
return this.fallbackClient;
} else {
console.warn('No fallback client available, using Qwen3 client');
return this.primaryClient;
}
}
/**
* Predict method with automatic fallback
*/
async predict(endpoint: string, params: any[]): Promise<{data: any[]}> {
// Ensure initialization has been attempted
if (!this.connectionTested) {
await this.initialize();
}
const activeClient = this.getActiveClient();
const clientName = this.useQwen3 ? 'Qwen3' : 'Zephyr-7B';
console.log(`πŸ€– Using ${clientName} for text generation`);
try {
const result = await activeClient.predict(endpoint, params);
return result;
} catch (error) {
console.error(`${clientName} prediction failed:`, error);
// If primary client fails and we have a fallback, try it
if (this.useQwen3 && this.fallbackClient) {
console.log('πŸ”„ Qwen3 failed, trying fallback to Zephyr-7B...');
try {
const fallbackResult = await this.fallbackClient.predict(endpoint, params);
// Mark for future calls to use fallback
this.useQwen3 = false;
return fallbackResult;
} catch (fallbackError) {
console.error('Fallback client also failed:', fallbackError);
throw new Error(`Both primary (${clientName}) and fallback clients failed`);
}
}
throw error;
}
}
/**
* Force switch to Qwen3
*/
useQwen3Client() {
this.useQwen3 = true;
console.log('πŸ”„ Switched to Qwen3 client');
}
/**
* Force switch to fallback (Zephyr-7B)
*/
useFallbackClient() {
if (this.fallbackClient) {
this.useQwen3 = false;
console.log('πŸ”„ Switched to fallback (Zephyr-7B) client');
} else {
console.warn('No fallback client available');
}
}
/**
* Get current client status
*/
getStatus() {
return {
usingQwen3: this.useQwen3,
hasFallback: this.fallbackClient !== null,
connectionTested: this.connectionTested,
activeClient: this.useQwen3 ? 'Qwen3' : 'Zephyr-7B'
};
}
}
// Export singleton instance
export const textGenerationManager = new TextGenerationManager();