Fix line/subline regressions, add in AI validation tracking and improve AI results dialog
This commit is contained in:
@@ -98,7 +98,51 @@ router.post("/debug", async (req, res) => {
|
||||
});
|
||||
|
||||
try {
|
||||
return await generateDebugResponse(cleanedProducts, res);
|
||||
const debugResponse = await generateDebugResponse(cleanedProducts, res);
|
||||
|
||||
// Get estimated processing time based on prompt length
|
||||
if (debugResponse && debugResponse.promptLength) {
|
||||
try {
|
||||
// Use the pool from the app
|
||||
const pool = req.app.locals.pool;
|
||||
if (!pool) {
|
||||
console.warn("⚠️ Local database pool not available for time estimates");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const avgTimeResults = await pool.query(
|
||||
`SELECT AVG(duration_seconds) as avg_duration,
|
||||
COUNT(*) as sample_count
|
||||
FROM ai_validation_performance
|
||||
WHERE prompt_length BETWEEN $1 * 0.8 AND $1 * 1.2`,
|
||||
[debugResponse.promptLength]
|
||||
);
|
||||
|
||||
// Add estimated time to the response
|
||||
if (avgTimeResults.rows && avgTimeResults.rows[0]) {
|
||||
debugResponse.estimatedProcessingTime = {
|
||||
seconds: avgTimeResults.rows[0].avg_duration || null,
|
||||
sampleCount: avgTimeResults.rows[0].sample_count || 0
|
||||
};
|
||||
console.log("📊 Retrieved processing time estimate:", debugResponse.estimatedProcessingTime);
|
||||
} else {
|
||||
console.log("📊 No processing time estimates available for prompt length:", debugResponse.promptLength);
|
||||
}
|
||||
} catch (queryError) {
|
||||
console.error("⚠️ Failed to query performance metrics:", queryError);
|
||||
// Check if table doesn't exist and log a more helpful message
|
||||
if (queryError.code === '42P01') {
|
||||
console.error("Table 'ai_validation_performance' does not exist. Make sure to run the setup-schema.sql script.");
|
||||
}
|
||||
}
|
||||
} catch (timeEstimateError) {
|
||||
console.error("Error getting time estimate:", timeEstimateError);
|
||||
// Don't fail the request if time estimate fails
|
||||
}
|
||||
}
|
||||
|
||||
return res.json(debugResponse);
|
||||
} catch (generateError) {
|
||||
console.error("Error generating debug response:", generateError);
|
||||
return res.status(500).json({
|
||||
@@ -271,7 +315,7 @@ async function generateDebugResponse(productsToUse, res) {
|
||||
};
|
||||
|
||||
console.log("Sending response with taxonomy stats:", response.taxonomyStats);
|
||||
return res.json(response);
|
||||
return response;
|
||||
} finally {
|
||||
if (promptConnection) await promptConnection.end();
|
||||
if (promptTunnel.ssh) promptTunnel.ssh.end();
|
||||
@@ -463,9 +507,7 @@ async function loadPrompt(connection, productsToValidate = null) {
|
||||
const taxonomy = await getTaxonomyData(connection);
|
||||
|
||||
// Add system instructions to the prompt
|
||||
const systemInstructions = `You are a specialized e-commerce product data processor for a crafting supplies website tasked with providing complete, correct, appealing, and SEO-friendly product listings. You should write professionally, but in a friendly and engaging tone.
|
||||
|
||||
`;
|
||||
const systemInstructions = `You are a specialized e-commerce product data processor for a crafting supplies website tasked with providing complete, correct, appealing, and SEO-friendly product listings. You should write professionally, but in a friendly and engaging tone. You have meticulous attention to detail and are a master at your craft.`;
|
||||
|
||||
// If we have products to validate, create a filtered prompt
|
||||
if (productsToValidate) {
|
||||
@@ -634,6 +676,7 @@ Here is the product data to validate:`;
|
||||
router.post("/validate", async (req, res) => {
|
||||
try {
|
||||
const { products } = req.body;
|
||||
const startTime = new Date(); // Track start time for performance metrics
|
||||
|
||||
console.log("🔍 Received products for validation:", {
|
||||
isArray: Array.isArray(products),
|
||||
@@ -654,6 +697,7 @@ router.post("/validate", async (req, res) => {
|
||||
|
||||
let ssh = null;
|
||||
let connection = null;
|
||||
let promptLength = 0; // Track prompt length for performance metrics
|
||||
|
||||
try {
|
||||
// Setup MySQL connection via SSH tunnel
|
||||
@@ -672,7 +716,8 @@ router.post("/validate", async (req, res) => {
|
||||
console.log("🔄 Loading prompt with filtered taxonomy...");
|
||||
const prompt = await loadPrompt(connection, products);
|
||||
const fullPrompt = prompt + "\n" + JSON.stringify(products);
|
||||
console.log("📝 Generated prompt length:", fullPrompt.length);
|
||||
promptLength = fullPrompt.length; // Store prompt length for performance metrics
|
||||
console.log("📝 Generated prompt length:", promptLength);
|
||||
|
||||
console.log("🤖 Sending request to OpenAI...");
|
||||
const completion = await openai.chat.completions.create({
|
||||
@@ -698,17 +743,27 @@ router.post("/validate", async (req, res) => {
|
||||
Object.keys(aiResponse)
|
||||
);
|
||||
|
||||
// Create a detailed comparison between original and corrected data
|
||||
const changeDetails = [];
|
||||
|
||||
// Compare original and corrected data
|
||||
if (aiResponse.correctedData) {
|
||||
console.log("📊 Changes summary:");
|
||||
products.forEach((original, index) => {
|
||||
const corrected = aiResponse.correctedData[index];
|
||||
if (corrected) {
|
||||
const productChanges = {
|
||||
productIndex: index,
|
||||
title: original.title || `Product ${index + 1}`,
|
||||
changes: []
|
||||
};
|
||||
|
||||
const changes = Object.keys(corrected).filter(
|
||||
(key) =>
|
||||
JSON.stringify(original[key]) !==
|
||||
JSON.stringify(corrected[key])
|
||||
);
|
||||
|
||||
if (changes.length > 0) {
|
||||
console.log(`\nProduct ${index + 1} changes:`);
|
||||
changes.forEach((key) => {
|
||||
@@ -719,14 +774,87 @@ router.post("/validate", async (req, res) => {
|
||||
console.log(
|
||||
` - Corrected: ${JSON.stringify(corrected[key])}`
|
||||
);
|
||||
|
||||
// Add to our detailed changes array
|
||||
productChanges.changes.push({
|
||||
field: key,
|
||||
original: original[key],
|
||||
corrected: corrected[key]
|
||||
});
|
||||
});
|
||||
|
||||
// Only add products that have changes
|
||||
if (productChanges.changes.length > 0) {
|
||||
changeDetails.push(productChanges);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Record performance metrics after successful validation
|
||||
const endTime = new Date();
|
||||
let performanceMetrics = {
|
||||
promptLength,
|
||||
productCount: products.length,
|
||||
processingTimeSeconds: (endTime - startTime) / 1000
|
||||
};
|
||||
|
||||
try {
|
||||
// Use the local PostgreSQL pool from the app instead of the MySQL connection
|
||||
const pool = req.app.locals.pool;
|
||||
if (!pool) {
|
||||
console.warn("⚠️ Local database pool not available for recording metrics");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Insert performance data into the local PostgreSQL database
|
||||
await pool.query(
|
||||
`INSERT INTO ai_validation_performance
|
||||
(prompt_length, product_count, start_time, end_time)
|
||||
VALUES ($1, $2, $3, $4)`,
|
||||
[promptLength, products.length, startTime, endTime]
|
||||
);
|
||||
|
||||
console.log("📊 Performance metrics inserted into database");
|
||||
|
||||
// Query for average processing time based on similar prompt lengths
|
||||
try {
|
||||
const avgTimeResults = await pool.query(
|
||||
`SELECT AVG(duration_seconds) as avg_duration,
|
||||
COUNT(*) as sample_count
|
||||
FROM ai_validation_performance
|
||||
WHERE prompt_length BETWEEN $1 * 0.8 AND $1 * 1.2`,
|
||||
[promptLength]
|
||||
);
|
||||
|
||||
if (avgTimeResults.rows && avgTimeResults.rows[0]) {
|
||||
performanceMetrics.avgDuration = avgTimeResults.rows[0].avg_duration;
|
||||
performanceMetrics.sampleCount = avgTimeResults.rows[0].sample_count;
|
||||
}
|
||||
|
||||
console.log("📊 Performance metrics retrieved:", performanceMetrics);
|
||||
} catch (queryError) {
|
||||
console.error("⚠️ Failed to query performance metrics:", queryError);
|
||||
}
|
||||
} catch (insertError) {
|
||||
console.error("⚠️ Failed to insert performance metrics:", insertError);
|
||||
// Check if table doesn't exist and log a more helpful message
|
||||
if (insertError.code === '42P01') {
|
||||
console.error("Table 'ai_validation_performance' does not exist. Make sure to run the setup-schema.sql script.");
|
||||
}
|
||||
}
|
||||
} catch (metricError) {
|
||||
// Don't fail the request if metrics recording fails
|
||||
console.error("⚠️ Failed to record performance metrics:", metricError);
|
||||
}
|
||||
|
||||
// Include performance metrics in the response
|
||||
res.json({
|
||||
success: true,
|
||||
changeDetails: changeDetails,
|
||||
performanceMetrics,
|
||||
...aiResponse,
|
||||
});
|
||||
} catch (parseError) {
|
||||
|
||||
Reference in New Issue
Block a user