Layout/style tweaks, remove text file prompts, integrate system prompt into database/settings

This commit is contained in:
2025-03-24 12:26:21 -04:00
parent dd4b3f7145
commit 228ae8b2a9
7 changed files with 232 additions and 315 deletions

View File

@@ -106,6 +106,33 @@ router.get('/type/general', async (req, res) => {
}
});
// Get system prompt
router.get('/type/system', async (req, res) => {
try {
const pool = req.app.locals.pool;
if (!pool) {
throw new Error('Database pool not initialized');
}
const result = await pool.query(`
SELECT * FROM ai_prompts
WHERE prompt_type = 'system'
`);
if (result.rows.length === 0) {
return res.status(404).json({ error: 'System AI prompt not found' });
}
res.json(result.rows[0]);
} catch (error) {
console.error('Error fetching system AI prompt:', error);
res.status(500).json({
error: 'Failed to fetch system AI prompt',
details: error instanceof Error ? error.message : 'Unknown error'
});
}
});
// Create new AI prompt
router.post('/', async (req, res) => {
try {
@@ -121,8 +148,8 @@ router.post('/', async (req, res) => {
}
// Validate prompt type
if (!['general', 'company_specific'].includes(prompt_type)) {
return res.status(400).json({ error: 'Prompt type must be either "general" or "company_specific"' });
if (!['general', 'company_specific', 'system'].includes(prompt_type)) {
return res.status(400).json({ error: 'Prompt type must be either "general", "company_specific", or "system"' });
}
// Validate company is provided for company-specific prompts
@@ -130,6 +157,11 @@ router.post('/', async (req, res) => {
return res.status(400).json({ error: 'Company is required for company-specific prompts' });
}
// Validate company is not provided for general or system prompts
if ((prompt_type === 'general' || prompt_type === 'system') && company) {
return res.status(400).json({ error: 'Company should not be provided for general or system prompts' });
}
const pool = req.app.locals.pool;
if (!pool) {
throw new Error('Database pool not initialized');
@@ -164,6 +196,11 @@ router.post('/', async (req, res) => {
error: 'A general prompt already exists',
details: error.message
});
} else if (error.message.includes('idx_unique_system_prompt')) {
return res.status(409).json({
error: 'A system prompt already exists',
details: error.message
});
}
}
@@ -190,14 +227,19 @@ router.put('/:id', async (req, res) => {
}
// Validate prompt type
if (!['general', 'company_specific'].includes(prompt_type)) {
return res.status(400).json({ error: 'Prompt type must be either "general" or "company_specific"' });
if (!['general', 'company_specific', 'system'].includes(prompt_type)) {
return res.status(400).json({ error: 'Prompt type must be either "general", "company_specific", or "system"' });
}
// Validate company is provided for company-specific prompts
if (prompt_type === 'company_specific' && !company) {
return res.status(400).json({ error: 'Company is required for company-specific prompts' });
}
// Validate company is not provided for general or system prompts
if ((prompt_type === 'general' || prompt_type === 'system') && company) {
return res.status(400).json({ error: 'Company should not be provided for general or system prompts' });
}
const pool = req.app.locals.pool;
if (!pool) {
@@ -241,6 +283,11 @@ router.put('/:id', async (req, res) => {
error: 'A general prompt already exists',
details: error.message
});
} else if (error.message.includes('idx_unique_system_prompt')) {
return res.status(409).json({
error: 'A system prompt already exists',
details: error.message
});
}
}

View File

@@ -296,7 +296,22 @@ async function generateDebugResponse(productsToUse, res) {
throw new Error("Database connection not available");
}
// First, fetch the general prompt
// First, fetch the system prompt
const systemPromptResult = await pool.query(`
SELECT * FROM ai_prompts
WHERE prompt_type = 'system'
`);
// Get system prompt or use default
let systemPrompt = null;
if (systemPromptResult.rows.length > 0) {
systemPrompt = systemPromptResult.rows[0];
console.log("📝 Loaded system prompt from database, ID:", systemPrompt.id);
} else {
console.warn("⚠️ No system prompt found in database, will use default");
}
// Then, fetch the general prompt
const generalPromptResult = await pool.query(`
SELECT * FROM ai_prompts
WHERE prompt_type = 'general'
@@ -337,7 +352,7 @@ async function generateDebugResponse(productsToUse, res) {
}
}
// Find company names from taxonomy
// Find company names from taxonomy for the validation endpoint
const companyPromptsWithNames = companyPrompts.map(prompt => {
let companyName = "Unknown Company";
if (taxonomy.companies && Array.isArray(taxonomy.companies)) {
@@ -399,10 +414,21 @@ async function generateDebugResponse(productsToUse, res) {
: null,
}
: null,
basePrompt: generalPrompt.prompt_text,
basePrompt: systemPrompt ? systemPrompt.prompt_text + "\n\n" + generalPrompt.prompt_text : generalPrompt.prompt_text,
sampleFullPrompt: fullPrompt,
promptLength: fullPrompt.length,
promptSources: {
...(systemPrompt ? {
systemPrompt: {
id: systemPrompt.id,
prompt_text: systemPrompt.prompt_text
}
} : {
systemPrompt: {
id: 0,
prompt_text: `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.`
}
}),
generalPrompt: {
id: generalPrompt.id,
prompt_text: generalPrompt.prompt_text
@@ -595,9 +621,6 @@ async function loadPrompt(connection, productsToValidate = null, appPool = null)
// Get taxonomy data using the provided MySQL connection
const taxonomy = await getTaxonomyData(connection);
// Initialize default system instructions
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.`;
// Use the provided pool parameter instead of global.app
const pool = appPool;
if (!pool) {
@@ -605,6 +628,23 @@ async function loadPrompt(connection, productsToValidate = null, appPool = null)
throw new Error("Database connection not available");
}
// Fetch the system prompt
const systemPromptResult = await pool.query(`
SELECT * FROM ai_prompts
WHERE prompt_type = 'system'
`);
// Default system instructions in case the system prompt is not found
let 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 system prompt exists in the database, use it
if (systemPromptResult.rows.length > 0) {
systemInstructions = systemPromptResult.rows[0].prompt_text;
console.log("📝 Loaded system prompt from database");
} else {
console.warn("⚠️ No system prompt found in database, using default");
}
// Fetch the general prompt
const generalPromptResult = await pool.query(`
SELECT * FROM ai_prompts
@@ -646,26 +686,6 @@ async function loadPrompt(connection, productsToValidate = null, appPool = null)
}
}
// Find company names from taxonomy for the validation endpoint
const companyPromptsWithNames = companyPrompts.map(prompt => {
let companyName = "Unknown Company";
if (taxonomy.companies && Array.isArray(taxonomy.companies)) {
const companyData = taxonomy.companies.find(company =>
String(company[0]) === String(prompt.company)
);
if (companyData && companyData[1]) {
companyName = companyData[1];
}
}
return {
id: prompt.id,
company: prompt.company,
companyName: companyName,
prompt_text: prompt.prompt_text
};
});
// Combine prompts - start with the general prompt
let combinedPrompt = basePrompt;
@@ -816,8 +836,8 @@ ${JSON.stringify(mixedTaxonomy.sizeCategories)}${
----------Here is the product data to validate----------`;
// Return the filtered prompt
return systemInstructions + combinedPrompt + "\n" + taxonomySection;
// Return the filtered prompt with system instructions first
return systemInstructions + "\n\n" + combinedPrompt + "\n" + taxonomySection;
}
// Generate the full unfiltered prompt
@@ -848,7 +868,8 @@ ${JSON.stringify(taxonomy.artists)}
Here is the product data to validate:`;
return systemInstructions + combinedPrompt + "\n" + taxonomySection;
// Return the full prompt with system instructions first
return systemInstructions + "\n\n" + combinedPrompt + "\n" + taxonomySection;
} catch (error) {
console.error("Error loading prompt:", error);
throw error; // Re-throw to be handled by the calling function
@@ -1049,6 +1070,11 @@ router.post("/validate", async (req, res) => {
let promptSources = null;
try {
// Get system prompt
const systemPromptResult = await pool.query(`
SELECT * FROM ai_prompts WHERE prompt_type = 'system'
`);
// Get general prompt
const generalPromptResult = await pool.query(`
SELECT * FROM ai_prompts WHERE prompt_type = 'general'
@@ -1074,7 +1100,7 @@ router.post("/validate", async (req, res) => {
companyPrompts = companyPromptsResult.rows;
}
// Find company names from taxonomy
// Find company names from taxonomy for the validation endpoint
const companyPromptsWithNames = companyPrompts.map(prompt => {
let companyName = "Unknown Company";
if (taxonomy.companies && Array.isArray(taxonomy.companies)) {
@@ -1097,7 +1123,24 @@ router.post("/validate", async (req, res) => {
// Set prompt sources
if (generalPromptResult.rows.length > 0) {
const generalPrompt = generalPromptResult.rows[0];
let systemPrompt = null;
if (systemPromptResult.rows.length > 0) {
systemPrompt = systemPromptResult.rows[0];
}
promptSources = {
...(systemPrompt ? {
systemPrompt: {
id: systemPrompt.id,
prompt_text: systemPrompt.prompt_text
}
} : {
systemPrompt: {
id: 0,
prompt_text: `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.`
}
}),
generalPrompt: {
id: generalPrompt.id,
prompt_text: generalPrompt.prompt_text