kbot iterator callbacks
This commit is contained in:
parent
b2ef96e786
commit
1991695594
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -3,7 +3,7 @@
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Make this description more engaging and detailed, around 10 words\n\nText to transform: \"[PRODUCT INFO] A yellow tropical fruit\""
|
||||
"content": "Analyze this product review and extract key information\n\nText to transform: \"Great selection of fruits with good prices and quality. Some items were out of stock.\""
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
|
||||
@ -8,7 +8,6 @@ export type AsyncTransformer = (input: string, path: string) => Promise<string>
|
||||
export type ErrorCallback = (path: string, value: string, error: unknown) => void
|
||||
export type FilterCallback = (input: string, path: string) => Promise<boolean>
|
||||
export type Filter = (input: string) => Promise<boolean>
|
||||
// Define the new callback types, passing IKBotTask options might be useful context
|
||||
export type OnTransformCallback = (jsonPath: string, value: string, options?: Partial<IKBotTask>) => Promise<string>;
|
||||
export type OnTransformedCallback = (jsonPath: string, transformedValue: string, options?: Partial<IKBotTask>) => Promise<string>;
|
||||
|
||||
@ -126,14 +125,22 @@ export async function transformPath(
|
||||
interval: networkOptions.throttleDelay,
|
||||
})
|
||||
if (typeof lastKey === 'string' && lastKey !== '') {
|
||||
if (typeof current[lastKey] === 'string' && current[lastKey] !== '') {
|
||||
if (await testCallback(current[lastKey], `${currentPath}/${lastKey}`)) {
|
||||
// Get the value pointed to by the keys
|
||||
const value = current[lastKey];
|
||||
|
||||
// Check if the value exists before proceeding
|
||||
if (value !== undefined && value !== null) {
|
||||
const fullJsonPath = `${currentPath}/${lastKey}`; // Construct full path
|
||||
|
||||
// Check if the filter callback allows transformation
|
||||
// Note: The default filter blocks numbers/booleans. Arrays/Objects depend on the filter implementation.
|
||||
// The example uses `async () => true`, so arrays should pass.
|
||||
if (await testCallback(value, fullJsonPath)) {
|
||||
// Add retry mechanism with exponential backoff
|
||||
let attempts = 0;
|
||||
let success = false;
|
||||
let lastError: unknown;
|
||||
let valueToTransform = current[lastKey];
|
||||
const fullJsonPath = `${currentPath}/${lastKey}`; // Construct full path
|
||||
let valueToTransform = value;
|
||||
|
||||
// Call onTransform before transformation
|
||||
try {
|
||||
@ -173,18 +180,6 @@ export async function transformPath(
|
||||
errorCallback(currentPath, lastKey, lastError); // Use currentPath (logical path)
|
||||
}
|
||||
}
|
||||
} else if (typeof current[lastKey] === 'object' && current[lastKey] !== null) {
|
||||
await transformObject(
|
||||
current[lastKey] as Record<string, any>,
|
||||
transform,
|
||||
'$.*', // Recurse on all properties
|
||||
networkOptions,
|
||||
errorCallback,
|
||||
testCallback,
|
||||
onTransform, // Pass callbacks down
|
||||
onTransformed, // Pass callbacks down
|
||||
options // Pass options context down
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,13 +59,13 @@ export async function simpleTransformExample() {
|
||||
console.log(`Original description: ${exampleData.products.fruits[0].description}`);
|
||||
console.log(`Transformed description: ${data.products.fruits[0].description}`);
|
||||
|
||||
console.log(`\nOriginal prices: ${exampleData.numberArrays.prices}`);
|
||||
console.log(`\nOriginal prices: ${JSON.stringify(exampleData.numberArrays.prices)}`);
|
||||
console.log(`Pricing Analysis: ${data.numberArrays.pricingAnalysis}`);
|
||||
|
||||
console.log(`\nOriginal ratings: ${exampleData.numberArrays.ratings}`);
|
||||
console.log(`\nOriginal ratings: ${JSON.stringify(exampleData.numberArrays.ratings)}`);
|
||||
console.log(`Ratings Summary: ${data.numberArrays.ratingsSummary}`);
|
||||
|
||||
console.log(`\nOriginal quantities: ${exampleData.numberArrays.quantities}`);
|
||||
console.log(`\nOriginal quantities: ${JSON.stringify(exampleData.numberArrays.quantities)}`);
|
||||
console.log(`Inventory Status: ${data.numberArrays.inventoryStatus}`);
|
||||
|
||||
return data;
|
||||
@ -112,9 +112,9 @@ const exampleData = {
|
||||
]
|
||||
},
|
||||
numberArrays: {
|
||||
prices: JSON.stringify([5, 3, 8, 12, 7]),
|
||||
ratings: JSON.stringify([4.5, 3.8, 4.2, 5.0, 4.1]),
|
||||
quantities: JSON.stringify([100, 50, 75, 30, 60])
|
||||
prices: [5, 3, 8, 12, 7],
|
||||
ratings: [4.5, 3.8, 4.2, 5.0, 4.1],
|
||||
quantities: [100, 50, 75, 30, 60]
|
||||
},
|
||||
productReview: {
|
||||
reviewText: 'Great selection of fruits with good prices and quality. Some items were out of stock.'
|
||||
@ -170,19 +170,7 @@ const fieldMappings: FieldMapping[] = [
|
||||
targetPath: 'analysis',
|
||||
options: {
|
||||
// Clear and explicit prompt that includes the schema format details
|
||||
prompt: `Analyze this product review and extract key information using EXACTLY the schema specified below.
|
||||
|
||||
The review: "Great selection of fruits with good prices and quality. Some items were out of stock."
|
||||
|
||||
Your response MUST be a valid JSON object following this exact schema:
|
||||
{
|
||||
"sentiment": "positive" | "neutral" | "negative",
|
||||
"pros": ["string", "string"...], // 1-3 items
|
||||
"cons": ["string"...] // 0-3 items
|
||||
}
|
||||
|
||||
Do not add any extra fields not in the schema, and make sure to use the exact field names as specified.`,
|
||||
// Schema validation ensures structured output format
|
||||
prompt: `Analyze this product review and extract key information`,
|
||||
format: {
|
||||
type: "object",
|
||||
properties: {
|
||||
@ -218,17 +206,26 @@ Do not add any extra fields not in the schema, and make sure to use the exact fi
|
||||
|
||||
// Example onTransform callback
|
||||
const exampleOnTransform: OnTransformCallback = async (jsonPath, value, options) => {
|
||||
console.log(` -> onTransform: Path='${jsonPath}', Original Value='${value.substring(0, 30)}...', Options Model='${options?.model}'`);
|
||||
let valueToTransform: string;
|
||||
// Check if the value is not a string (e.g., our number arrays)
|
||||
if (typeof value !== 'string') {
|
||||
valueToTransform = JSON.stringify(value);
|
||||
console.log(` -> onTransform: Path='${jsonPath}', Original Value (Array)=${valueToTransform}, Options Model='${options?.model}'`);
|
||||
} else {
|
||||
valueToTransform = value;
|
||||
console.log(` -> onTransform: Path='${jsonPath}', Original Value='${valueToTransform.substring(0, 30)}...', Options Model='${options?.model}'`);
|
||||
}
|
||||
|
||||
// Example: Prefix value before sending to LLM
|
||||
if (jsonPath.includes('description')) {
|
||||
return `[PRODUCT INFO] ${value}`;
|
||||
return `[PRODUCT INFO] ${valueToTransform}`;
|
||||
}
|
||||
return value; // Return original value if no modification needed
|
||||
return valueToTransform; // Return stringified or original string value
|
||||
};
|
||||
|
||||
// Example onTransformed callback
|
||||
const exampleOnTransformed: OnTransformedCallback = async (jsonPath, transformedValue, options) => {
|
||||
console.log(` <- onTransformed: Path='${jsonPath}', Transformed Value='${transformedValue.substring(0, 30)}...', Options Model='${options?.model}'`);
|
||||
console.log(` <- onTransformed: Path='${jsonPath}', Transformed Value='${transformedValue.substring(0, 100)}...', Options Model='${options?.model}'`);
|
||||
// Example: Post-process the LLM response
|
||||
if (jsonPath.includes('nutrition')) {
|
||||
return `${transformedValue} [HEALTH FOCUS]`;
|
||||
@ -238,8 +235,16 @@ const exampleOnTransformed: OnTransformedCallback = async (jsonPath, transformed
|
||||
|
||||
// Simpler callbacks for the second example
|
||||
const simpleOnTransform: OnTransformCallback = async (jsonPath, value) => {
|
||||
console.log(` -> simpleOnTransform: Path='${jsonPath}'`);
|
||||
return value;
|
||||
let valueToTransform: string;
|
||||
// Check if the value is not a string (e.g., our number arrays)
|
||||
if (typeof value !== 'string') {
|
||||
valueToTransform = JSON.stringify(value);
|
||||
console.log(` -> simpleOnTransform: Path='${jsonPath}' (Array stringified)`);
|
||||
} else {
|
||||
valueToTransform = value;
|
||||
console.log(` -> simpleOnTransform: Path='${jsonPath}'`);
|
||||
}
|
||||
return valueToTransform;
|
||||
};
|
||||
|
||||
const simpleOnTransformed: OnTransformedCallback = async (jsonPath, transformedValue) => {
|
||||
@ -388,9 +393,9 @@ export async function factoryExample() {
|
||||
console.log(`Marketing name: ${data2.products.fruits[0].marketingName || 'Not available'}`);
|
||||
|
||||
console.log("\nNumber Arrays Transformation Examples:");
|
||||
console.log(`Original prices: ${exampleData.numberArrays.prices}`);
|
||||
console.log(`Original prices: ${JSON.stringify(exampleData.numberArrays.prices)}`);
|
||||
console.log(`Pricing analysis: ${data2.numberArrays.pricingAnalysis || 'Not available'}`);
|
||||
console.log(`Original ratings: ${exampleData.numberArrays.ratings}`);
|
||||
console.log(`Original ratings: ${JSON.stringify(exampleData.numberArrays.ratings)}`);
|
||||
console.log(`Ratings summary: ${data2.numberArrays.ratingsSummary || 'Not available'}`);
|
||||
|
||||
if (data2.productReview && data2.productReview.analysis) {
|
||||
|
||||
@ -26,15 +26,33 @@
|
||||
]
|
||||
},
|
||||
"numberArrays": {
|
||||
"prices": "[5,3,8,12,7]",
|
||||
"ratings": "[4.5,3.8,4.2,5,4.1]",
|
||||
"quantities": "[100,50,75,30,60]",
|
||||
"prices": [
|
||||
5,
|
||||
3,
|
||||
8,
|
||||
12,
|
||||
7
|
||||
],
|
||||
"ratings": [
|
||||
4.5,
|
||||
3.8,
|
||||
4.2,
|
||||
5,
|
||||
4.1
|
||||
],
|
||||
"quantities": [
|
||||
100,
|
||||
50,
|
||||
75,
|
||||
30,
|
||||
60
|
||||
],
|
||||
"pricingAnalysis": "Prices show moderate volatility with a peak at 12 and a low at 3, indicating fluctuating demand. Overall trend is slightly upward with intermittent dips, suggesting cautious market optimism.",
|
||||
"ratingsSummary": "Average rating is 4.3, indicating generally positive user feedback with minor variations in satisfaction.",
|
||||
"inventoryStatus": "Stock levels are moderately balanced, though the lowest item at 30 units may need restocking soon."
|
||||
},
|
||||
"productReview": {
|
||||
"reviewText": "Great selection of fruits with good prices and quality. Some items were out of stock.",
|
||||
"analysis": "{\n \"sentiment\": \"positive\",\n \"pros\": [\"great selection of fruits\", \"good prices\", \"good quality\"],\n \"cons\": [\"some items were out of stock\"]\n}"
|
||||
"analysis": "Key Information Extracted:\n\n- Positive Aspects:\n - Good selection of fruits\n - Competitive prices\n - High quality\n\n- Negative Aspects:\n - Some items were out of stock"
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user