mirror of
https://github.com/Nikhil-Doye/workflow-builder.git
synced 2026-07-22 02:01:56 +02:00
Implement prompt optimization features across workflow components
- Integrated a new prompt optimization service to enhance AI task node prompts, improving context-awareness and domain specificity. - Updated NodeConfiguration component to include a button for optimizing prompts, displaying results for user review and application. - Enhanced workflow generation logic to utilize optimized prompts, ensuring better performance in AI analysis tasks. - Refactored existing prompt generation methods to leverage the new prompt optimizer, streamlining the process for various data types and tasks. - Added detailed context and instructions for AI tasks, improving the overall user experience and output quality.
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import React from "react";
|
||||
import React, { useState } from "react";
|
||||
import { NodeData } from "../types";
|
||||
import { useWorkflowStore } from "../store/workflowStore";
|
||||
import { X, Settings } from "lucide-react";
|
||||
import { X, Settings, Sparkles } from "lucide-react";
|
||||
import { promptOptimizer } from "../services/promptOptimizer";
|
||||
import { callOpenAI } from "../services/openaiService";
|
||||
|
||||
interface NodeConfigurationProps {
|
||||
nodeId: string;
|
||||
@@ -192,6 +194,8 @@ export const NodeConfiguration: React.FC<NodeConfigurationProps> = ({
|
||||
}) => {
|
||||
const { updateNode, currentWorkflow } = useWorkflowStore();
|
||||
const config = nodeTypeConfigs[data.type];
|
||||
const [isOptimizing, setIsOptimizing] = useState(false);
|
||||
const [optimizationResult, setOptimizationResult] = useState<string>("");
|
||||
|
||||
// Get the latest node data from the store to ensure we have the most up-to-date config
|
||||
const currentNode = currentWorkflow?.nodes.find((node) => node.id === nodeId);
|
||||
@@ -210,19 +214,163 @@ export const NodeConfiguration: React.FC<NodeConfigurationProps> = ({
|
||||
updateNode(nodeId, { label });
|
||||
};
|
||||
|
||||
const handleOptimizePrompt = async () => {
|
||||
if (!currentData.config.prompt) {
|
||||
alert("Please enter a prompt first");
|
||||
return;
|
||||
}
|
||||
|
||||
setIsOptimizing(true);
|
||||
setOptimizationResult("");
|
||||
|
||||
try {
|
||||
// Extract intent from the prompt itself
|
||||
const prompt = currentData.config.prompt;
|
||||
const entities = {
|
||||
aiTasks: prompt.toLowerCase().includes("analyze")
|
||||
? ["analyze"]
|
||||
: prompt.toLowerCase().includes("summarize")
|
||||
? ["summarize"]
|
||||
: prompt.toLowerCase().includes("extract")
|
||||
? ["extract"]
|
||||
: prompt.toLowerCase().includes("classify")
|
||||
? ["classify"]
|
||||
: prompt.toLowerCase().includes("generate")
|
||||
? ["generate"]
|
||||
: ["process"],
|
||||
dataTypes: prompt.toLowerCase().includes("resume")
|
||||
? ["resume"]
|
||||
: prompt.toLowerCase().includes("document")
|
||||
? ["document"]
|
||||
: prompt.toLowerCase().includes("text")
|
||||
? ["text"]
|
||||
: ["text"],
|
||||
urls: [],
|
||||
complexity: "medium",
|
||||
};
|
||||
|
||||
// Create mock node context
|
||||
const nodeContext = {
|
||||
dataType: "text",
|
||||
previousNodes: [],
|
||||
intent: "AI_ANALYSIS",
|
||||
domain: prompt.toLowerCase().includes("resume")
|
||||
? "jobApplication"
|
||||
: prompt.toLowerCase().includes("financial")
|
||||
? "financial"
|
||||
: prompt.toLowerCase().includes("legal")
|
||||
? "legal"
|
||||
: "general",
|
||||
workflowType: "ai_analysis",
|
||||
availableData: new Map(),
|
||||
};
|
||||
|
||||
// Generate optimized prompt using the prompt optimizer
|
||||
const optimizedPrompt = promptOptimizer.generateOptimizedPrompt(
|
||||
prompt,
|
||||
entities,
|
||||
nodeContext,
|
||||
new Map()
|
||||
);
|
||||
|
||||
// Make DeepSeek API call to further optimize the prompt
|
||||
const apiResponse = await callOpenAI(
|
||||
`You are a prompt optimization expert. Your task is to optimize the given prompt for better AI performance.
|
||||
|
||||
IMPORTANT: Return ONLY the optimized prompt. Do not include any explanations, comments, or additional text. Just the optimized prompt itself.
|
||||
|
||||
Original Prompt: ${prompt}
|
||||
|
||||
Optimized Template: ${optimizedPrompt}
|
||||
|
||||
Return only the optimized prompt:`,
|
||||
{
|
||||
model: "deepseek-chat",
|
||||
temperature: 0.7,
|
||||
maxTokens: 1000,
|
||||
}
|
||||
);
|
||||
|
||||
// Clean up the response to ensure we only get the optimized prompt
|
||||
let cleanedResult = apiResponse.content.trim();
|
||||
|
||||
// Remove common prefixes that might be added by the AI
|
||||
const prefixesToRemove = [
|
||||
"Optimized Prompt:",
|
||||
"Here's the optimized prompt:",
|
||||
"The optimized prompt is:",
|
||||
"Optimized version:",
|
||||
"Here is the optimized prompt:",
|
||||
"Optimized prompt:",
|
||||
"Here's the improved prompt:",
|
||||
"Improved prompt:",
|
||||
"Here is the improved prompt:",
|
||||
"The improved prompt is:",
|
||||
"Here's the enhanced prompt:",
|
||||
"Enhanced prompt:",
|
||||
"Here is the enhanced prompt:",
|
||||
"The enhanced prompt is:",
|
||||
];
|
||||
|
||||
for (const prefix of prefixesToRemove) {
|
||||
if (cleanedResult.toLowerCase().startsWith(prefix.toLowerCase())) {
|
||||
cleanedResult = cleanedResult.substring(prefix.length).trim();
|
||||
}
|
||||
}
|
||||
|
||||
// Remove any quotes that might wrap the prompt
|
||||
if (
|
||||
(cleanedResult.startsWith('"') && cleanedResult.endsWith('"')) ||
|
||||
(cleanedResult.startsWith("'") && cleanedResult.endsWith("'"))
|
||||
) {
|
||||
cleanedResult = cleanedResult.slice(1, -1).trim();
|
||||
}
|
||||
|
||||
setOptimizationResult(cleanedResult);
|
||||
} catch (error) {
|
||||
console.error("Error optimizing prompt:", error);
|
||||
setOptimizationResult("Error optimizing prompt. Please try again.");
|
||||
} finally {
|
||||
setIsOptimizing(false);
|
||||
}
|
||||
};
|
||||
|
||||
const applyOptimizedPrompt = () => {
|
||||
if (optimizationResult) {
|
||||
handleConfigChange("prompt", optimizationResult);
|
||||
setOptimizationResult("");
|
||||
}
|
||||
};
|
||||
|
||||
const renderField = (field: any) => {
|
||||
const value = currentData.config[field.key] || field.defaultValue || "";
|
||||
|
||||
switch (field.type) {
|
||||
case "textarea":
|
||||
return (
|
||||
<textarea
|
||||
value={value}
|
||||
onChange={(e) => handleConfigChange(field.key, e.target.value)}
|
||||
placeholder={field.placeholder}
|
||||
className="w-full p-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-primary-500 focus:border-transparent"
|
||||
rows={3}
|
||||
/>
|
||||
<div className="space-y-2">
|
||||
<textarea
|
||||
value={value}
|
||||
onChange={(e) => handleConfigChange(field.key, e.target.value)}
|
||||
placeholder={field.placeholder}
|
||||
className="w-full p-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-primary-500 focus:border-transparent"
|
||||
rows={3}
|
||||
/>
|
||||
{data.type === "llmTask" && field.key === "prompt" && (
|
||||
<div className="flex items-center space-x-2">
|
||||
<button
|
||||
onClick={handleOptimizePrompt}
|
||||
disabled={isOptimizing || !currentData.config.prompt}
|
||||
className="flex items-center space-x-2 px-3 py-1.5 bg-gradient-to-r from-purple-500 to-pink-500 text-white text-sm font-medium rounded-md hover:from-purple-600 hover:to-pink-600 disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-200 shadow-sm"
|
||||
>
|
||||
<Sparkles className="w-4 h-4" />
|
||||
<span>
|
||||
{isOptimizing ? "Optimizing..." : "Optimize Prompt"}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
case "select":
|
||||
if (field.multiple) {
|
||||
@@ -350,6 +498,49 @@ export const NodeConfiguration: React.FC<NodeConfigurationProps> = ({
|
||||
{renderField(field)}
|
||||
</div>
|
||||
))}
|
||||
|
||||
{/* Optimization Result Display */}
|
||||
{data.type === "llmTask" && optimizationResult && (
|
||||
<div className="mt-4 p-4 bg-gradient-to-r from-purple-50 to-pink-50 border border-purple-200 rounded-lg">
|
||||
<div className="flex items-center space-x-2 mb-3">
|
||||
<Sparkles className="w-4 h-4 text-purple-600" />
|
||||
<h4 className="text-sm font-semibold text-purple-800">
|
||||
Optimized Prompt Preview
|
||||
</h4>
|
||||
<span className="px-2 py-1 bg-purple-100 text-purple-700 text-xs rounded-full">
|
||||
Preview
|
||||
</span>
|
||||
</div>
|
||||
<div className="bg-white p-4 rounded-md border border-purple-100 shadow-sm">
|
||||
<div className="mb-2 text-xs text-gray-500 font-medium">
|
||||
Optimized Prompt:
|
||||
</div>
|
||||
<pre className="text-sm text-gray-800 whitespace-pre-wrap font-mono leading-relaxed bg-gray-50 p-3 rounded border">
|
||||
{optimizationResult}
|
||||
</pre>
|
||||
</div>
|
||||
<div className="mt-3 flex items-center justify-between">
|
||||
<div className="text-xs text-purple-600">
|
||||
Review the optimized prompt above and click "Apply" to replace
|
||||
your current prompt.
|
||||
</div>
|
||||
<div className="flex space-x-2">
|
||||
<button
|
||||
onClick={() => setOptimizationResult("")}
|
||||
className="px-3 py-1 text-xs text-gray-600 hover:text-gray-800 hover:bg-gray-100 rounded transition-colors"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
onClick={applyOptimizedPrompt}
|
||||
className="px-3 py-1 bg-green-500 text-white text-xs font-medium rounded hover:bg-green-600 transition-colors"
|
||||
>
|
||||
Apply Optimized Prompt
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end space-x-2 p-4 border-t border-gray-200">
|
||||
|
||||
@@ -275,14 +275,36 @@ Respond with JSON:
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate workflow structure using LLM
|
||||
* Generate workflow structure using LLM with optimized prompts
|
||||
*/
|
||||
private async generateWorkflowStructureWithLLM(
|
||||
userInput: string,
|
||||
intent: IntentClassification,
|
||||
entities: EntityExtraction
|
||||
): Promise<WorkflowStructure> {
|
||||
const prompt = `
|
||||
// Import the prompt optimizer
|
||||
const { promptOptimizer } = require("./promptOptimizer");
|
||||
|
||||
// Create context for workflow generation
|
||||
const workflowContext = {
|
||||
dataType: this.determineWorkflowDataType(entities),
|
||||
previousNodes: [],
|
||||
intent: intent.intent,
|
||||
domain: this.determineWorkflowDomain(userInput, entities),
|
||||
workflowType: this.determineWorkflowType(intent, entities),
|
||||
availableData: new Map(),
|
||||
};
|
||||
|
||||
// Generate optimized prompt for workflow generation
|
||||
const optimizedPrompt = promptOptimizer.generateOptimizedPrompt(
|
||||
userInput,
|
||||
entities,
|
||||
workflowContext,
|
||||
workflowContext.availableData
|
||||
);
|
||||
|
||||
const prompt = `${optimizedPrompt}
|
||||
|
||||
You are an AI workflow designer. Analyze the user's request and create a comprehensive workflow structure.
|
||||
|
||||
User Request: "${userInput}"
|
||||
@@ -300,10 +322,11 @@ Instructions:
|
||||
1. Understand the user's goal and break it down into logical steps
|
||||
2. Create a workflow that accomplishes their request
|
||||
3. Use appropriate node types for each step
|
||||
4. Configure nodes with realistic settings
|
||||
4. Configure nodes with realistic settings and optimized prompts
|
||||
5. Connect nodes logically with proper data flow
|
||||
6. Use variable substitution ({{nodeId.output}}) to pass data between nodes
|
||||
7. Make the workflow practical and executable
|
||||
8. For LLM nodes, use context-aware, domain-specific prompts
|
||||
|
||||
For job application workflows, consider:
|
||||
- Resume analysis and skill extraction
|
||||
@@ -628,6 +651,107 @@ Respond with valid JSON only:
|
||||
hitRate: 0.8, // Placeholder - would track actual hit rate
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine workflow data type from entities
|
||||
*/
|
||||
private determineWorkflowDataType(entities: EntityExtraction): string {
|
||||
if (entities.urls?.length > 0) return "url";
|
||||
if (entities.dataTypes?.includes("json")) return "json";
|
||||
if (entities.dataTypes?.includes("csv")) return "csv";
|
||||
if (entities.dataTypes?.includes("pdf")) return "pdf";
|
||||
if (
|
||||
entities.dataTypes?.includes("resume") ||
|
||||
entities.dataTypes?.includes("cv")
|
||||
)
|
||||
return "text";
|
||||
return "text";
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine workflow domain from user input and entities
|
||||
*/
|
||||
private determineWorkflowDomain(
|
||||
userInput: string,
|
||||
entities: EntityExtraction
|
||||
): string {
|
||||
const input = userInput.toLowerCase();
|
||||
|
||||
if (
|
||||
entities.dataTypes?.includes("resume") ||
|
||||
entities.dataTypes?.includes("cv") ||
|
||||
input.includes("resume") ||
|
||||
input.includes("job") ||
|
||||
input.includes("career")
|
||||
) {
|
||||
return "jobApplication";
|
||||
}
|
||||
|
||||
if (
|
||||
entities.dataTypes?.includes("financial") ||
|
||||
input.includes("financial") ||
|
||||
input.includes("revenue") ||
|
||||
input.includes("profit")
|
||||
) {
|
||||
return "financial";
|
||||
}
|
||||
|
||||
if (
|
||||
entities.dataTypes?.includes("legal") ||
|
||||
input.includes("legal") ||
|
||||
input.includes("contract") ||
|
||||
input.includes("agreement")
|
||||
) {
|
||||
return "legal";
|
||||
}
|
||||
|
||||
if (
|
||||
entities.dataTypes?.includes("medical") ||
|
||||
input.includes("medical") ||
|
||||
input.includes("health") ||
|
||||
input.includes("patient")
|
||||
) {
|
||||
return "medical";
|
||||
}
|
||||
|
||||
if (
|
||||
entities.dataTypes?.includes("technical") ||
|
||||
input.includes("technical") ||
|
||||
input.includes("code") ||
|
||||
input.includes("software")
|
||||
) {
|
||||
return "technical";
|
||||
}
|
||||
|
||||
if (
|
||||
input.includes("content") ||
|
||||
input.includes("marketing") ||
|
||||
input.includes("seo")
|
||||
) {
|
||||
return "contentAnalysis";
|
||||
}
|
||||
|
||||
return "general";
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine workflow type from intent and entities
|
||||
*/
|
||||
private determineWorkflowType(
|
||||
intent: IntentClassification,
|
||||
entities: EntityExtraction
|
||||
): string {
|
||||
if (intent.intent === "WEB_SCRAPING") return "web_scraping";
|
||||
if (intent.intent === "AI_ANALYSIS") return "ai_analysis";
|
||||
if (intent.intent === "DATA_PROCESSING") return "data_processing";
|
||||
if (intent.intent === "SEARCH_AND_RETRIEVAL") return "search_retrieval";
|
||||
if (
|
||||
entities.dataTypes?.includes("resume") ||
|
||||
entities.dataTypes?.includes("cv")
|
||||
)
|
||||
return "job_application";
|
||||
return "general";
|
||||
}
|
||||
}
|
||||
|
||||
// Export singleton instance
|
||||
|
||||
@@ -0,0 +1,593 @@
|
||||
/**
|
||||
* Advanced Prompt Optimization Service
|
||||
* Generates context-aware, domain-specific prompts for AI Task Nodes
|
||||
*/
|
||||
|
||||
export interface NodeContext {
|
||||
dataType: string;
|
||||
previousNodes: string[];
|
||||
intent: string;
|
||||
domain?: string;
|
||||
workflowType?: string;
|
||||
availableData: Map<string, any>;
|
||||
}
|
||||
|
||||
export interface PromptPerformance {
|
||||
quality: number; // 1-10 scale
|
||||
relevance: number; // 1-10 scale
|
||||
completeness: number; // 1-10 scale
|
||||
userSatisfaction?: number; // 1-10 scale
|
||||
executionTime?: number; // milliseconds
|
||||
}
|
||||
|
||||
export interface PromptRefinement {
|
||||
type:
|
||||
| "add_context"
|
||||
| "add_examples"
|
||||
| "improve_instructions"
|
||||
| "adjust_format";
|
||||
description: string;
|
||||
implementation: string;
|
||||
}
|
||||
|
||||
export interface DomainPromptTemplate {
|
||||
role: string;
|
||||
context: string;
|
||||
instructions: string;
|
||||
examples?: string[];
|
||||
outputFormat: string;
|
||||
chainOfThought?: boolean;
|
||||
}
|
||||
|
||||
export class PromptOptimizer {
|
||||
private promptHistory = new Map<string, PromptPerformance>();
|
||||
private domainTemplates = new Map<string, DomainPromptTemplate>();
|
||||
private fewShotExamples = new Map<string, any[]>();
|
||||
|
||||
constructor() {
|
||||
this.initializeDomainTemplates();
|
||||
this.initializeFewShotExamples();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an optimized prompt for an AI Task Node
|
||||
*/
|
||||
generateOptimizedPrompt(
|
||||
userIntent: string,
|
||||
entities: any,
|
||||
nodeContext: NodeContext,
|
||||
availableData: Map<string, any>
|
||||
): string {
|
||||
const promptBuilder = new PromptBuilder();
|
||||
|
||||
// Determine the appropriate domain and task type
|
||||
const domain = this.determineDomain(userIntent, entities, nodeContext);
|
||||
const taskType = this.determineTaskType(userIntent, entities);
|
||||
|
||||
// Add role and context
|
||||
const role = this.determineRole(userIntent, entities, domain);
|
||||
promptBuilder.addRole(role);
|
||||
|
||||
// Add domain-specific context
|
||||
const context = this.buildContext(
|
||||
userIntent,
|
||||
entities,
|
||||
nodeContext,
|
||||
domain
|
||||
);
|
||||
promptBuilder.addContext(context);
|
||||
|
||||
// Add specific instructions
|
||||
const instructions = this.generateInstructions(
|
||||
userIntent,
|
||||
entities,
|
||||
taskType,
|
||||
domain
|
||||
);
|
||||
promptBuilder.addInstructions(instructions);
|
||||
|
||||
// Add few-shot examples if available
|
||||
const examples = this.getRelevantExamples(taskType, domain);
|
||||
if (examples.length > 0) {
|
||||
promptBuilder.addExamples(examples);
|
||||
}
|
||||
|
||||
// Add chain-of-thought if needed
|
||||
if (this.shouldUseChainOfThought(taskType, entities)) {
|
||||
promptBuilder.addChainOfThought();
|
||||
}
|
||||
|
||||
// Add output format requirements
|
||||
const outputFormat = this.determineOutputFormat(
|
||||
userIntent,
|
||||
entities,
|
||||
taskType
|
||||
);
|
||||
promptBuilder.addOutputFormat(outputFormat);
|
||||
|
||||
// Add available data context
|
||||
const dataContext = this.buildDataContext(availableData, nodeContext);
|
||||
promptBuilder.addDataContext(dataContext);
|
||||
|
||||
return promptBuilder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the appropriate domain for the prompt
|
||||
*/
|
||||
private determineDomain(
|
||||
userIntent: string,
|
||||
entities: any,
|
||||
nodeContext: NodeContext
|
||||
): string {
|
||||
// Check for specific domain indicators
|
||||
if (
|
||||
entities.dataTypes?.includes("resume") ||
|
||||
entities.dataTypes?.includes("cv")
|
||||
) {
|
||||
return "jobApplication";
|
||||
}
|
||||
|
||||
if (
|
||||
entities.dataTypes?.includes("financial") ||
|
||||
userIntent.toLowerCase().includes("financial")
|
||||
) {
|
||||
return "financial";
|
||||
}
|
||||
|
||||
if (
|
||||
entities.dataTypes?.includes("legal") ||
|
||||
userIntent.toLowerCase().includes("legal")
|
||||
) {
|
||||
return "legal";
|
||||
}
|
||||
|
||||
if (
|
||||
entities.dataTypes?.includes("medical") ||
|
||||
userIntent.toLowerCase().includes("medical")
|
||||
) {
|
||||
return "medical";
|
||||
}
|
||||
|
||||
if (
|
||||
entities.dataTypes?.includes("technical") ||
|
||||
userIntent.toLowerCase().includes("technical")
|
||||
) {
|
||||
return "technical";
|
||||
}
|
||||
|
||||
if (nodeContext.workflowType === "content_analysis") {
|
||||
return "contentAnalysis";
|
||||
}
|
||||
|
||||
return "general";
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the specific task type
|
||||
*/
|
||||
private determineTaskType(userIntent: string, entities: any): string {
|
||||
const tasks = entities.aiTasks || [];
|
||||
|
||||
if (tasks.includes("summarize")) return "summarize";
|
||||
if (tasks.includes("analyze")) return "analyze";
|
||||
if (tasks.includes("extract")) return "extract";
|
||||
if (tasks.includes("classify")) return "classify";
|
||||
if (tasks.includes("generate")) return "generate";
|
||||
if (tasks.includes("translate")) return "translate";
|
||||
if (tasks.includes("sentiment")) return "sentiment";
|
||||
if (tasks.includes("compare")) return "compare";
|
||||
|
||||
// Fallback based on intent
|
||||
if (userIntent.toLowerCase().includes("summarize")) return "summarize";
|
||||
if (userIntent.toLowerCase().includes("analyze")) return "analyze";
|
||||
if (userIntent.toLowerCase().includes("extract")) return "extract";
|
||||
|
||||
return "process";
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the appropriate role for the AI
|
||||
*/
|
||||
private determineRole(
|
||||
userIntent: string,
|
||||
entities: any,
|
||||
domain: string
|
||||
): string {
|
||||
const domainRoles: Record<string, string> = {
|
||||
jobApplication: "expert career counselor and resume analyst",
|
||||
financial: "senior financial analyst and investment advisor",
|
||||
legal: "experienced legal counsel and document analyst",
|
||||
medical: "medical professional and clinical analyst",
|
||||
technical: "senior software engineer and technical architect",
|
||||
contentAnalysis: "content strategist and digital marketing expert",
|
||||
general: "expert data analyst and business consultant",
|
||||
};
|
||||
|
||||
return domainRoles[domain] || domainRoles.general;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build context-aware information
|
||||
*/
|
||||
private buildContext(
|
||||
userIntent: string,
|
||||
entities: any,
|
||||
nodeContext: NodeContext,
|
||||
domain: string
|
||||
): string {
|
||||
const contextParts = [];
|
||||
|
||||
// Add data type context
|
||||
if (nodeContext.dataType) {
|
||||
contextParts.push(`Data Type: ${nodeContext.dataType}`);
|
||||
}
|
||||
|
||||
// Add domain-specific context
|
||||
if (domain !== "general") {
|
||||
contextParts.push(`Domain: ${domain}`);
|
||||
}
|
||||
|
||||
// Add workflow context
|
||||
if (nodeContext.previousNodes.length > 0) {
|
||||
contextParts.push(
|
||||
`Previous Processing: ${nodeContext.previousNodes.join(" → ")}`
|
||||
);
|
||||
}
|
||||
|
||||
// Add entity context
|
||||
if (entities.urls?.length > 0) {
|
||||
contextParts.push(`Source URLs: ${entities.urls.join(", ")}`);
|
||||
}
|
||||
|
||||
if (entities.dataTypes?.length > 0) {
|
||||
contextParts.push(`Data Types: ${entities.dataTypes.join(", ")}`);
|
||||
}
|
||||
|
||||
return contextParts.join("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate specific instructions based on task type and domain
|
||||
*/
|
||||
private generateInstructions(
|
||||
userIntent: string,
|
||||
entities: any,
|
||||
taskType: string,
|
||||
domain: string
|
||||
): string {
|
||||
const template = this.domainTemplates.get(domain);
|
||||
if (template) {
|
||||
return template.instructions;
|
||||
}
|
||||
|
||||
// Fallback to task-specific instructions
|
||||
const taskInstructions: Record<string, string> = {
|
||||
summarize:
|
||||
"Provide a clear, concise summary that captures the key points and main insights.",
|
||||
analyze:
|
||||
"Conduct a thorough analysis, identifying patterns, trends, and actionable insights.",
|
||||
extract:
|
||||
"Extract specific information systematically, organizing it in a structured format.",
|
||||
classify:
|
||||
"Categorize the content accurately, providing clear reasoning for each classification.",
|
||||
generate:
|
||||
"Create high-quality content that meets the specified requirements and objectives.",
|
||||
translate:
|
||||
"Provide accurate, contextually appropriate translations while preserving meaning.",
|
||||
sentiment:
|
||||
"Analyze emotional tone and sentiment with specific evidence and confidence levels.",
|
||||
compare:
|
||||
"Perform detailed comparisons highlighting similarities, differences, and implications.",
|
||||
process:
|
||||
"Process the data systematically to extract maximum value and insights.",
|
||||
};
|
||||
|
||||
return taskInstructions[taskType] || taskInstructions.process;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get relevant few-shot examples
|
||||
*/
|
||||
private getRelevantExamples(taskType: string, domain: string): any[] {
|
||||
const key = `${domain}_${taskType}`;
|
||||
return (
|
||||
this.fewShotExamples.get(key) || this.fewShotExamples.get(taskType) || []
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if chain-of-thought prompting should be used
|
||||
*/
|
||||
private shouldUseChainOfThought(taskType: string, entities: any): boolean {
|
||||
const complexTasks = ["analyze", "compare", "classify", "sentiment"];
|
||||
return complexTasks.includes(taskType) || entities.complexity === "high";
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine output format requirements
|
||||
*/
|
||||
private determineOutputFormat(
|
||||
userIntent: string,
|
||||
entities: any,
|
||||
taskType: string
|
||||
): string {
|
||||
if (entities.outputFormat) {
|
||||
return entities.outputFormat;
|
||||
}
|
||||
|
||||
const formatPreferences: Record<string, string> = {
|
||||
summarize:
|
||||
"Provide a clear, structured summary with key points highlighted.",
|
||||
analyze:
|
||||
"Present findings in a structured format with clear sections and actionable insights.",
|
||||
extract:
|
||||
"Organize extracted information in a logical, easy-to-read format.",
|
||||
classify:
|
||||
"Provide classifications with clear categories and supporting evidence.",
|
||||
generate:
|
||||
"Format content appropriately for the intended audience and purpose.",
|
||||
sentiment:
|
||||
"Include sentiment scores, confidence levels, and supporting evidence.",
|
||||
compare:
|
||||
"Present comparisons in a clear, side-by-side format with conclusions.",
|
||||
process: "Structure the output for maximum clarity and usability.",
|
||||
};
|
||||
|
||||
return formatPreferences[taskType] || formatPreferences.process;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build data context from available node outputs
|
||||
*/
|
||||
private buildDataContext(
|
||||
availableData: Map<string, any>,
|
||||
nodeContext: NodeContext
|
||||
): string {
|
||||
if (availableData.size === 0) {
|
||||
return "Input data: {{input.output}}";
|
||||
}
|
||||
|
||||
const dataDescriptions = [];
|
||||
for (const [nodeId, data] of availableData) {
|
||||
if (data.output) {
|
||||
dataDescriptions.push(
|
||||
`${nodeId}: ${
|
||||
typeof data.output === "string"
|
||||
? data.output.substring(0, 100) + "..."
|
||||
: "Complex data object"
|
||||
}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return `Available data:\n${dataDescriptions.join(
|
||||
"\n"
|
||||
)}\n\nPrimary input: {{input.output}}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize domain-specific templates
|
||||
*/
|
||||
private initializeDomainTemplates(): void {
|
||||
// Job Application Domain
|
||||
this.domainTemplates.set("jobApplication", {
|
||||
role: "expert career counselor and resume analyst",
|
||||
context:
|
||||
"You are analyzing job application materials to provide career guidance and optimization recommendations.",
|
||||
instructions: `When analyzing resumes and job applications:
|
||||
1. Identify key skills, experience, and achievements
|
||||
2. Assess alignment with job requirements
|
||||
3. Highlight strengths and areas for improvement
|
||||
4. Provide specific, actionable recommendations
|
||||
5. Consider industry best practices and trends`,
|
||||
examples: [
|
||||
"Resume Analysis: \"This resume shows strong technical skills but could benefit from quantifiable achievements. Consider adding metrics like 'increased efficiency by 25%' or 'managed team of 8 developers'.\"",
|
||||
'Cover Letter Review: "The cover letter effectively addresses the job requirements but could be more specific about how your experience directly relates to their needs."',
|
||||
],
|
||||
outputFormat:
|
||||
"Provide structured analysis with clear sections: Summary, Strengths, Areas for Improvement, and Recommendations.",
|
||||
chainOfThought: true,
|
||||
});
|
||||
|
||||
// Financial Domain
|
||||
this.domainTemplates.set("financial", {
|
||||
role: "senior financial analyst and investment advisor",
|
||||
context:
|
||||
"You are analyzing financial data and providing investment insights and recommendations.",
|
||||
instructions: `When analyzing financial information:
|
||||
1. Examine key financial metrics and ratios
|
||||
2. Identify trends and patterns in the data
|
||||
3. Assess risk factors and opportunities
|
||||
4. Provide data-driven insights and recommendations
|
||||
5. Consider market conditions and economic factors`,
|
||||
examples: [
|
||||
'Financial Analysis: "The company shows strong revenue growth of 15% YoY, but operating margins have declined from 12% to 9%, indicating potential cost management issues."',
|
||||
'Investment Review: "Based on the P/E ratio of 18 and strong cash flow, this appears to be a solid investment opportunity, though market volatility should be considered."',
|
||||
],
|
||||
outputFormat:
|
||||
"Present analysis with clear financial metrics, trends, and actionable recommendations.",
|
||||
chainOfThought: true,
|
||||
});
|
||||
|
||||
// Content Analysis Domain
|
||||
this.domainTemplates.set("contentAnalysis", {
|
||||
role: "content strategist and digital marketing expert",
|
||||
context:
|
||||
"You are analyzing content for marketing effectiveness, SEO optimization, and audience engagement.",
|
||||
instructions: `When analyzing content:
|
||||
1. Assess readability and engagement potential
|
||||
2. Identify SEO opportunities and issues
|
||||
3. Evaluate brand voice and messaging consistency
|
||||
4. Suggest improvements for audience targeting
|
||||
5. Consider content performance metrics`,
|
||||
examples: [
|
||||
"Content Review: \"The article has good structure but could benefit from more specific keywords. Consider adding 'digital transformation' and 'cloud migration' to improve SEO.\"",
|
||||
'Engagement Analysis: "The content is informative but lacks emotional hooks. Adding personal stories or case studies could increase engagement."',
|
||||
],
|
||||
outputFormat:
|
||||
"Provide analysis with specific recommendations for content improvement and optimization.",
|
||||
chainOfThought: false,
|
||||
});
|
||||
|
||||
// Technical Domain
|
||||
this.domainTemplates.set("technical", {
|
||||
role: "senior software engineer and technical architect",
|
||||
context:
|
||||
"You are analyzing technical documentation and code to provide development insights and recommendations.",
|
||||
instructions: `When analyzing technical content:
|
||||
1. Evaluate code quality and best practices
|
||||
2. Identify potential security vulnerabilities
|
||||
3. Assess scalability and performance implications
|
||||
4. Suggest architectural improvements
|
||||
5. Consider maintainability and documentation`,
|
||||
examples: [
|
||||
'Code Review: "The function is well-structured but could benefit from error handling. Consider adding try-catch blocks for database operations."',
|
||||
'Architecture Analysis: "The microservices approach is good, but consider implementing a service mesh for better communication management."',
|
||||
],
|
||||
outputFormat:
|
||||
"Provide technical analysis with specific recommendations for improvement and optimization.",
|
||||
chainOfThought: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize few-shot learning examples
|
||||
*/
|
||||
private initializeFewShotExamples(): void {
|
||||
// General examples
|
||||
this.fewShotExamples.set("summarize", [
|
||||
{
|
||||
input:
|
||||
"Long technical document about machine learning algorithms, neural networks, deep learning applications, and practical implementation strategies...",
|
||||
output:
|
||||
"This document explains machine learning fundamentals, covering supervised learning algorithms, neural networks, and practical applications in data science. Key topics include algorithm selection, model training, and performance optimization techniques.",
|
||||
},
|
||||
]);
|
||||
|
||||
this.fewShotExamples.set("analyze", [
|
||||
{
|
||||
input:
|
||||
"Financial report showing Q3 revenue of $2.5M, 15% growth, new product launches, customer acquisition data...",
|
||||
output:
|
||||
"Analysis shows 15% revenue growth driven by new product launches. Key insights: Q3 performance exceeded expectations, customer acquisition increased 25%, operational efficiency improved 8%. Recommendations: Continue product innovation, optimize customer onboarding process.",
|
||||
},
|
||||
]);
|
||||
|
||||
// Job application examples
|
||||
this.fewShotExamples.set("jobApplication_summarize", [
|
||||
{
|
||||
input:
|
||||
"Resume with 5 years software engineering experience, Python/JavaScript skills, team lead experience...",
|
||||
output:
|
||||
"Experienced software engineer with 5 years in full-stack development. Strong technical skills in Python and JavaScript, proven leadership experience managing development teams. Key strengths: problem-solving, team collaboration, and technical innovation.",
|
||||
},
|
||||
]);
|
||||
|
||||
// Financial examples
|
||||
this.fewShotExamples.set("financial_analyze", [
|
||||
{
|
||||
input:
|
||||
"Company financials: Revenue $10M, Expenses $7M, Net Income $3M, Debt $2M, Cash $5M...",
|
||||
output:
|
||||
"Strong financial position with 30% net margin and healthy cash reserves. Revenue growth of 20% YoY indicates good market traction. Debt-to-equity ratio of 0.2 shows conservative leverage. Recommendation: Consider strategic investments for continued growth.",
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Track prompt performance for future optimization
|
||||
*/
|
||||
trackPerformance(promptId: string, performance: PromptPerformance): void {
|
||||
this.promptHistory.set(promptId, performance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get performance insights for prompt optimization
|
||||
*/
|
||||
getPerformanceInsights(): Map<string, PromptPerformance> {
|
||||
return new Map(this.promptHistory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompt Builder class for constructing optimized prompts
|
||||
*/
|
||||
class PromptBuilder {
|
||||
private role: string = "";
|
||||
private context: string = "";
|
||||
private instructions: string = "";
|
||||
private examples: any[] = [];
|
||||
private chainOfThought: boolean = false;
|
||||
private outputFormat: string = "";
|
||||
private dataContext: string = "";
|
||||
|
||||
addRole(role: string): PromptBuilder {
|
||||
this.role = `You are an ${role}.`;
|
||||
return this;
|
||||
}
|
||||
|
||||
addContext(context: string): PromptBuilder {
|
||||
this.context = `Context:\n${context}`;
|
||||
return this;
|
||||
}
|
||||
|
||||
addInstructions(instructions: string): PromptBuilder {
|
||||
this.instructions = `Instructions:\n${instructions}`;
|
||||
return this;
|
||||
}
|
||||
|
||||
addExamples(examples: any[]): PromptBuilder {
|
||||
if (examples.length > 0) {
|
||||
this.examples = examples;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
addChainOfThought(): PromptBuilder {
|
||||
this.chainOfThought = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
addOutputFormat(outputFormat: string): PromptBuilder {
|
||||
this.outputFormat = `Output Format:\n${outputFormat}`;
|
||||
return this;
|
||||
}
|
||||
|
||||
addDataContext(dataContext: string): PromptBuilder {
|
||||
this.dataContext = dataContext;
|
||||
return this;
|
||||
}
|
||||
|
||||
build(): string {
|
||||
const parts = [this.role];
|
||||
|
||||
if (this.context) parts.push(this.context);
|
||||
if (this.instructions) parts.push(this.instructions);
|
||||
|
||||
if (this.chainOfThought) {
|
||||
parts.push(`Please think through this step by step:
|
||||
1. First, analyze the input data and identify key elements
|
||||
2. Apply your expertise to process the information
|
||||
3. Generate insights and conclusions
|
||||
4. Format the output according to the requirements`);
|
||||
}
|
||||
|
||||
if (this.examples.length > 0) {
|
||||
parts.push("Examples:");
|
||||
this.examples.forEach((example, index) => {
|
||||
parts.push(`Example ${index + 1}:`);
|
||||
parts.push(`Input: ${example.input}`);
|
||||
parts.push(`Output: ${example.output}`);
|
||||
});
|
||||
}
|
||||
|
||||
if (this.outputFormat) parts.push(this.outputFormat);
|
||||
if (this.dataContext) parts.push(this.dataContext);
|
||||
|
||||
return parts.join("\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Export singleton instance
|
||||
export const promptOptimizer = new PromptOptimizer();
|
||||
+164
-1
@@ -667,11 +667,45 @@ const processLLMNode = async (
|
||||
nodeLabelToId?: Map<string, string>
|
||||
) => {
|
||||
const config = node.data.config;
|
||||
const prompt = config.prompt || "Process the following input: {{input}}";
|
||||
let prompt = config.prompt || "Process the following input: {{input}}";
|
||||
const model = config.model || "gpt-3.5-turbo";
|
||||
const temperature = config.temperature || 0.7;
|
||||
const maxTokens = config.maxTokens || 1000;
|
||||
|
||||
// Check if we should optimize the prompt
|
||||
if (config.optimizePrompt !== false) {
|
||||
try {
|
||||
// Import the prompt optimizer
|
||||
const { promptOptimizer } = require("../services/promptOptimizer");
|
||||
|
||||
// Create node context for optimization
|
||||
const nodeContext = {
|
||||
dataType: determineNodeDataType(node, nodeOutputs),
|
||||
previousNodes: getPreviousNodeIds(node, nodeOutputs),
|
||||
intent: "AI_ANALYSIS",
|
||||
domain: determineNodeDomain(node, nodeOutputs),
|
||||
workflowType: "ai_analysis",
|
||||
availableData: nodeOutputs,
|
||||
};
|
||||
|
||||
// Generate optimized prompt
|
||||
const optimizedPrompt = promptOptimizer.generateOptimizedPrompt(
|
||||
prompt,
|
||||
extractEntitiesFromPrompt(prompt),
|
||||
nodeContext,
|
||||
nodeOutputs
|
||||
);
|
||||
|
||||
// Use optimized prompt if it's different and better
|
||||
if (optimizedPrompt && optimizedPrompt !== prompt) {
|
||||
console.log("Using optimized prompt for LLM node:", node.id);
|
||||
prompt = optimizedPrompt;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("Failed to optimize prompt, using original:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply variable substitution to the prompt
|
||||
const processedPrompt = substituteVariables(
|
||||
prompt,
|
||||
@@ -990,3 +1024,132 @@ const processStructuredOutputNode = async (
|
||||
|
||||
return { output: mockStructuredOutput, model, schema };
|
||||
};
|
||||
|
||||
// Helper functions for prompt optimization
|
||||
function determineNodeDataType(
|
||||
node: WorkflowNode,
|
||||
nodeOutputs: Map<string, NodeOutput>
|
||||
): string {
|
||||
// Check if this is a data input node
|
||||
if (node.data.type === "dataInput") {
|
||||
return node.data.config?.dataType || "text";
|
||||
}
|
||||
|
||||
// Check previous nodes for data type
|
||||
const previousOutput = Array.from(nodeOutputs.values()).pop();
|
||||
if (previousOutput?.data?.type) {
|
||||
return previousOutput.data.type;
|
||||
}
|
||||
|
||||
// Check if previous output looks like specific data types
|
||||
if (previousOutput?.output) {
|
||||
const output = previousOutput.output;
|
||||
if (typeof output === "string") {
|
||||
if (output.startsWith("http")) return "url";
|
||||
if (output.includes("{") && output.includes("}")) return "json";
|
||||
if (output.includes(",") && output.includes("\n")) return "csv";
|
||||
}
|
||||
}
|
||||
|
||||
return "text";
|
||||
}
|
||||
|
||||
function getPreviousNodeIds(
|
||||
node: WorkflowNode,
|
||||
nodeOutputs: Map<string, NodeOutput>
|
||||
): string[] {
|
||||
return Array.from(nodeOutputs.keys());
|
||||
}
|
||||
|
||||
function determineNodeDomain(
|
||||
node: WorkflowNode,
|
||||
nodeOutputs: Map<string, NodeOutput>
|
||||
): string {
|
||||
// Check node label for domain indicators
|
||||
const label = node.data.label?.toLowerCase() || "";
|
||||
|
||||
if (
|
||||
label.includes("resume") ||
|
||||
label.includes("cv") ||
|
||||
label.includes("job")
|
||||
) {
|
||||
return "jobApplication";
|
||||
}
|
||||
|
||||
if (
|
||||
label.includes("financial") ||
|
||||
label.includes("revenue") ||
|
||||
label.includes("profit")
|
||||
) {
|
||||
return "financial";
|
||||
}
|
||||
|
||||
if (label.includes("legal") || label.includes("contract")) {
|
||||
return "legal";
|
||||
}
|
||||
|
||||
if (label.includes("medical") || label.includes("health")) {
|
||||
return "medical";
|
||||
}
|
||||
|
||||
if (label.includes("technical") || label.includes("code")) {
|
||||
return "technical";
|
||||
}
|
||||
|
||||
if (label.includes("content") || label.includes("marketing")) {
|
||||
return "contentAnalysis";
|
||||
}
|
||||
|
||||
// Check previous outputs for domain indicators
|
||||
for (const output of nodeOutputs.values()) {
|
||||
if (output.output && typeof output.output === "string") {
|
||||
const text = output.output.toLowerCase();
|
||||
if (text.includes("resume") || text.includes("cv"))
|
||||
return "jobApplication";
|
||||
if (text.includes("financial") || text.includes("revenue"))
|
||||
return "financial";
|
||||
if (text.includes("legal") || text.includes("contract")) return "legal";
|
||||
if (text.includes("medical") || text.includes("health")) return "medical";
|
||||
if (text.includes("technical") || text.includes("code"))
|
||||
return "technical";
|
||||
if (text.includes("content") || text.includes("marketing"))
|
||||
return "contentAnalysis";
|
||||
}
|
||||
}
|
||||
|
||||
return "general";
|
||||
}
|
||||
|
||||
function extractEntitiesFromPrompt(prompt: string): any {
|
||||
// Simple entity extraction from prompt text
|
||||
const entities: any = {
|
||||
aiTasks: [],
|
||||
dataTypes: [],
|
||||
};
|
||||
|
||||
const lowerPrompt = prompt.toLowerCase();
|
||||
|
||||
// Extract AI tasks
|
||||
if (lowerPrompt.includes("summarize")) entities.aiTasks.push("summarize");
|
||||
if (lowerPrompt.includes("analyze")) entities.aiTasks.push("analyze");
|
||||
if (lowerPrompt.includes("extract")) entities.aiTasks.push("extract");
|
||||
if (lowerPrompt.includes("classify")) entities.aiTasks.push("classify");
|
||||
if (lowerPrompt.includes("generate")) entities.aiTasks.push("generate");
|
||||
if (lowerPrompt.includes("translate")) entities.aiTasks.push("translate");
|
||||
if (lowerPrompt.includes("sentiment")) entities.aiTasks.push("sentiment");
|
||||
if (lowerPrompt.includes("compare")) entities.aiTasks.push("compare");
|
||||
|
||||
// Extract data types
|
||||
if (lowerPrompt.includes("resume") || lowerPrompt.includes("cv"))
|
||||
entities.dataTypes.push("resume");
|
||||
if (lowerPrompt.includes("pdf")) entities.dataTypes.push("pdf");
|
||||
if (lowerPrompt.includes("json")) entities.dataTypes.push("json");
|
||||
if (lowerPrompt.includes("csv")) entities.dataTypes.push("csv");
|
||||
if (lowerPrompt.includes("url")) entities.dataTypes.push("url");
|
||||
if (lowerPrompt.includes("financial")) entities.dataTypes.push("financial");
|
||||
if (lowerPrompt.includes("legal")) entities.dataTypes.push("legal");
|
||||
if (lowerPrompt.includes("medical")) entities.dataTypes.push("medical");
|
||||
if (lowerPrompt.includes("technical")) entities.dataTypes.push("technical");
|
||||
|
||||
return entities;
|
||||
}
|
||||
|
||||
@@ -539,39 +539,31 @@ function generateDefaultValue(entities: any): string {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate AI prompt based on entities
|
||||
* Generate AI prompt based on entities using the new prompt optimizer
|
||||
*/
|
||||
function generateAIPrompt(entities: any): string {
|
||||
const tasks = entities.aiTasks || [];
|
||||
const dataTypes = entities.dataTypes || [];
|
||||
function generateAIPrompt(
|
||||
entities: any,
|
||||
userInput?: string,
|
||||
nodeContext?: any
|
||||
): string {
|
||||
// Import the prompt optimizer
|
||||
const { promptOptimizer } = require("../services/promptOptimizer");
|
||||
|
||||
// Special handling for PDF files
|
||||
if (dataTypes.includes("pdf")) {
|
||||
if (tasks.includes("summarize")) {
|
||||
return "Summarize the PDF document in 2-3 sentences: {{input.output}}";
|
||||
}
|
||||
if (tasks.includes("analyze")) {
|
||||
return "Analyze the PDF content and provide insights: {{input.output}}";
|
||||
}
|
||||
if (tasks.includes("extract")) {
|
||||
return "Extract key information from the PDF: {{input.output}}";
|
||||
}
|
||||
return "Process the PDF content: {{input.output}}";
|
||||
}
|
||||
// Create node context if not provided
|
||||
const context = nodeContext || {
|
||||
dataType: determineInputDataType(entities),
|
||||
previousNodes: [],
|
||||
intent: "AI_ANALYSIS",
|
||||
availableData: new Map(),
|
||||
};
|
||||
|
||||
if (tasks.includes("summarize")) {
|
||||
return "Summarize the following content in 2-3 sentences: {{input.output}}";
|
||||
}
|
||||
|
||||
if (tasks.includes("analyze")) {
|
||||
return "Analyze the following content and provide insights: {{input.output}}";
|
||||
}
|
||||
|
||||
if (tasks.includes("classify")) {
|
||||
return "Classify the following content into categories: {{input.output}}";
|
||||
}
|
||||
|
||||
return "Process the following content: {{input.output}}";
|
||||
// Generate optimized prompt
|
||||
return promptOptimizer.generateOptimizedPrompt(
|
||||
userInput || "Process the input data",
|
||||
entities,
|
||||
context,
|
||||
context.availableData
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user