@flowlab/all
Version:
A cool library focusing on handling various flows
81 lines (76 loc) • 3.55 kB
text/typescript
// src/aiConditionHelper.ts
import { IWorkflowContext } from '@flowlab/core';
import { AIProviderRegistry, AIModelOptions } from './types';
import { aiProviderRegistry } from './providerRegistry'; // Use singleton
export class AIConditionHelper {
// Use the shared registry
private registry: AIProviderRegistry = aiProviderRegistry;
// TODO: Integrate prompt rendering logic similar to BaseAINode
/**
* Evaluates a condition using an AI model, expecting a 'true' or 'false' response.
* @param context Workflow context for variable access.
* @param providerName Name of the AI provider.
* @param promptTemplate Prompt guiding the AI to answer true/false.
* @param options Model options.
* @returns Promise<boolean>
*/
async evaluateBoolean(
context: IWorkflowContext,
providerName: string,
promptTemplate: string,
options?: AIModelOptions
): Promise<boolean> {
try {
const provider = this.registry.getProvider(providerName);
// Simplified rendering for example - use BaseAINode's logic ideally
const renderedPrompt = this.renderPrompt(promptTemplate, context.variables);
const { text } = await provider.generateText(renderedPrompt, { ...options, maxTokens: 10 }); // Limit tokens for boolean
return text.trim().toLowerCase() === 'true';
} catch (error) {
console.error(`AI Boolean condition evaluation failed: ${error}`);
return false; // Default to false on error? Or throw? Needs decision.
}
}
/**
* Asks AI to choose one option from a list based on the prompt.
* @param context Workflow context.
* @param providerName AI provider name.
* @param promptTemplate Prompt guiding the AI to select a choice.
* @param choices Array of possible string choices.
* @param options Model options.
* @returns Promise<string> The chosen string, or the first choice as fallback on error/mismatch.
*/
async evaluateChoice(
context: IWorkflowContext,
providerName: string,
promptTemplate: string,
choices: string[],
options?: AIModelOptions
): Promise<string> {
if (!choices || choices.length === 0) return ''; // Return empty if no choices
try {
const provider = this.registry.getProvider(providerName);
const renderedPrompt = this.renderPrompt(promptTemplate, context.variables); // Use shared render logic
const promptWithChoices = `${renderedPrompt}\n\nChoose one of the following options exactly: ${choices.join(', ')}`;
const { text } = await provider.generateText(promptWithChoices, options);
const chosen = text.trim();
// Find the choice that matches the AI output (case-insensitive, trim)
const matchedChoice = choices.find(c => c.trim().toLowerCase() === chosen.toLowerCase());
return matchedChoice || choices[0]; // Return matched or fallback to first choice
} catch (error) {
console.error(`AI Choice condition evaluation failed: ${error}`);
return choices[0]; // Fallback to first choice on error
}
}
// Placeholder for shared rendering logic (ideally import from utils)
private renderPrompt(template: string, variables: Record<string, any>): string {
let rendered = template;
// Matches ${varName}
rendered = rendered.replace(/\$\{(\w+)\}/g, (match, varName) => {
return String(variables[varName] ?? '');
});
return rendered;
}
}
// Default export for easy access
export const aiConditionHelper = new AIConditionHelper();