Add Groq as AI provider + new inline AI tasks, extend database to support more prompt types
This commit is contained in:
@@ -36,7 +36,9 @@ async function ensureInitialized() {
|
||||
|
||||
const result = await aiService.initialize({
|
||||
openaiApiKey: process.env.OPENAI_API_KEY,
|
||||
groqApiKey: process.env.GROQ_API_KEY,
|
||||
mysqlConnection: connection,
|
||||
pool: null, // Will be set by setPool()
|
||||
logger: console
|
||||
});
|
||||
|
||||
@@ -45,7 +47,10 @@ async function ensureInitialized() {
|
||||
return false;
|
||||
}
|
||||
|
||||
console.log('[AI Routes] AI service initialized:', result.stats);
|
||||
console.log('[AI Routes] AI service initialized:', {
|
||||
...result.stats,
|
||||
groqEnabled: result.groqEnabled
|
||||
});
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('[AI Routes] Failed to initialize AI service:', error);
|
||||
@@ -278,4 +283,148 @@ router.post('/similar', async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// INLINE AI VALIDATION ENDPOINTS (Groq-powered)
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* POST /api/ai/validate/inline/name
|
||||
* Validate a single product name for spelling, grammar, and naming conventions
|
||||
*
|
||||
* Body: { product: { name, company_name, company_id, line_name, description } }
|
||||
* Returns: { isValid, suggestion?, issues[], latencyMs }
|
||||
*/
|
||||
router.post('/validate/inline/name', async (req, res) => {
|
||||
try {
|
||||
const ready = await ensureInitialized();
|
||||
if (!ready) {
|
||||
return res.status(503).json({ error: 'AI service not available' });
|
||||
}
|
||||
|
||||
if (!aiService.hasChatCompletion()) {
|
||||
return res.status(503).json({
|
||||
error: 'Chat completion not available - GROQ_API_KEY not configured'
|
||||
});
|
||||
}
|
||||
|
||||
const { product } = req.body;
|
||||
|
||||
if (!product) {
|
||||
return res.status(400).json({ error: 'Product is required' });
|
||||
}
|
||||
|
||||
// Get pool from app.locals (set by server.js)
|
||||
const pool = req.app.locals.pool;
|
||||
|
||||
const result = await aiService.runTask(aiService.TASK_IDS.VALIDATE_NAME, {
|
||||
product,
|
||||
pool
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
return res.status(500).json({
|
||||
error: result.error || 'Validation failed',
|
||||
code: result.code
|
||||
});
|
||||
}
|
||||
|
||||
res.json(result);
|
||||
} catch (error) {
|
||||
console.error('[AI Routes] Name validation error:', error);
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* POST /api/ai/validate/inline/description
|
||||
* Validate a single product description for quality and guideline compliance
|
||||
*
|
||||
* Body: { product: { name, description, company_name, company_id, categories } }
|
||||
* Returns: { isValid, suggestion?, issues[], latencyMs }
|
||||
*/
|
||||
router.post('/validate/inline/description', async (req, res) => {
|
||||
try {
|
||||
const ready = await ensureInitialized();
|
||||
if (!ready) {
|
||||
return res.status(503).json({ error: 'AI service not available' });
|
||||
}
|
||||
|
||||
if (!aiService.hasChatCompletion()) {
|
||||
return res.status(503).json({
|
||||
error: 'Chat completion not available - GROQ_API_KEY not configured'
|
||||
});
|
||||
}
|
||||
|
||||
const { product } = req.body;
|
||||
|
||||
if (!product) {
|
||||
return res.status(400).json({ error: 'Product is required' });
|
||||
}
|
||||
|
||||
// Get pool from app.locals (set by server.js)
|
||||
const pool = req.app.locals.pool;
|
||||
|
||||
const result = await aiService.runTask(aiService.TASK_IDS.VALIDATE_DESCRIPTION, {
|
||||
product,
|
||||
pool
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
return res.status(500).json({
|
||||
error: result.error || 'Validation failed',
|
||||
code: result.code
|
||||
});
|
||||
}
|
||||
|
||||
res.json(result);
|
||||
} catch (error) {
|
||||
console.error('[AI Routes] Description validation error:', error);
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* POST /api/ai/validate/sanity-check
|
||||
* Run consistency/sanity check on a batch of products
|
||||
*
|
||||
* Body: { products: Array<product data> }
|
||||
* Returns: { issues: Array<{ productIndex, field, issue, suggestion? }>, summary, latencyMs }
|
||||
*/
|
||||
router.post('/validate/sanity-check', async (req, res) => {
|
||||
try {
|
||||
const ready = await ensureInitialized();
|
||||
if (!ready) {
|
||||
return res.status(503).json({ error: 'AI service not available' });
|
||||
}
|
||||
|
||||
if (!aiService.hasChatCompletion()) {
|
||||
return res.status(503).json({
|
||||
error: 'Chat completion not available - GROQ_API_KEY not configured'
|
||||
});
|
||||
}
|
||||
|
||||
const { products } = req.body;
|
||||
|
||||
if (!Array.isArray(products) || products.length === 0) {
|
||||
return res.status(400).json({ error: 'Products array is required' });
|
||||
}
|
||||
|
||||
const result = await aiService.runTask(aiService.TASK_IDS.SANITY_CHECK, {
|
||||
products
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
return res.status(500).json({
|
||||
error: result.error || 'Sanity check failed',
|
||||
code: result.code
|
||||
});
|
||||
}
|
||||
|
||||
res.json(result);
|
||||
} catch (error) {
|
||||
console.error('[AI Routes] Sanity check error:', error);
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
||||
Reference in New Issue
Block a user