UNPKG

vtseditor

Version:
138 lines (116 loc) 3.7 kB
import {ConfigProvider} from '../Config/Config.js'; import {ASchemaProvider} from './ASchemaProvider.js'; import {ProviderConversationJson, SchemaProviderConversationJson} from './SchemaProviderConversationJson.js'; import {ConversationPartRole, ProviderConversationPart} from './SchemaProviderConversationPart.js'; import {SchemaProviderConversationPrompt} from './SchemaProviderConversationPrompt.js'; /** * Schema provider ai base */ export abstract class SchemaProviderAIBase extends ASchemaProvider { /** * Conversation * @protected */ protected _conversation: ProviderConversationPart[] = []; /** * Max tokens * @protected */ protected _maxTokens: number = 100_000; /** * constructor * @param {ConfigProvider} config * @param {ProviderConversationPart[]} conversation */ public constructor(config: ConfigProvider, conversation: ProviderConversationPart[] = []) { super(config); this._conversation = conversation; } /** * Generate Schema * Template Method Pattern: * - preps conversation * - calls provider-specific request * - parses response * * @param {string} description */ public async generateSchema(description: string): Promise<void> { let msg = description; // initial system prompt (once) if (this._conversation.length === 0) { this._conversation.push({ role: ConversationPartRole.user, text: SchemaProviderConversationPrompt.join(" "), json: null }); } this._conversation.push({ role: ConversationPartRole.user, text: msg, json: null }); // Provider-specific request const text = await this._sendRequest(this._conversation); if (!text) { throw new Error("No answer from model"); } const returnJsonText = this._extractJson(text); const returnJsonData = JSON.parse(returnJsonText) || {}; let returnJson: ProviderConversationJson | null = null; if (SchemaProviderConversationJson.validate(returnJsonData, [])) { returnJson = returnJsonData; } else { console.log('⛔ KI Schema not validate!'); } this._conversation.push({ role: ConversationPartRole.model, text: text, json: returnJson }); if (this._getTotalTokens() > this._maxTokens) { this._trimHistory(); } } /** * Each provider implements its own request/response handling */ protected abstract _sendRequest( conversation: ProviderConversationPart[] ): Promise<string | null>; /** * Extract total tokens from provider response * (default 0, override if needed) */ protected _getTotalTokens(): number { return 0; } /** * Trim history if too long */ protected _trimHistory() { this._conversation = this._conversation.slice(-10); } /** * Return conversation * @return {ProviderConversationPart[]} */ public getConversation(): ProviderConversationPart[] { return this._conversation; } /** * Extract JSON from text */ protected _extractJson(text: string): string { let cleaned = text .replace(/^```json\s*/i, "") .replace(/^```\s*/i, "") .replace(/\s*```$/i, "") .trim(); const match = cleaned.match(/\{[\s\S]*}/); if (match) { cleaned = match[0].trim(); } return cleaned; } }