first commit
This commit is contained in:
@@ -0,0 +1,290 @@
|
||||
const groqService = require('./groqService');
|
||||
const { Plan, Message, Conversation } = require('../models');
|
||||
const logger = require('../utils/logger');
|
||||
|
||||
class Model1Service {
|
||||
constructor() {
|
||||
this.modelType = 'MODEL1';
|
||||
this.systemPrompt = `You are MODEL1, an expert engineering reasoning system. Your primary function is to analyze complex engineering problems and create detailed, step-by-step plans to solve them.
|
||||
|
||||
Your capabilities include:
|
||||
- Structural engineering analysis
|
||||
- Mechanical engineering design
|
||||
- Electrical engineering systems
|
||||
- Civil engineering projects
|
||||
- Computer Enginnering
|
||||
- Safety and compliance considerations
|
||||
- Cost estimation and feasibility analysis
|
||||
- Risk assessment and mitigation
|
||||
- All other engineering related courses
|
||||
|
||||
When creating plans, always:
|
||||
1. Break down complex problems into clear, actionable steps
|
||||
2. Consider safety, feasibility, and best practices
|
||||
3. Include relevant calculations, standards, and regulations
|
||||
4. Suggest appropriate tools and resources
|
||||
5. Provide time estimates for each step
|
||||
6. Consider potential challenges and mitigation strategies
|
||||
7. DO NOT give the answer, your job is to plan
|
||||
8. Only give plan when the user ask about actionable questions
|
||||
|
||||
Format your response as a structured plan with:
|
||||
- Title: Clear, descriptive title
|
||||
- Description: Brief overview of the problem and approach
|
||||
- Steps: Numbered list of detailed steps
|
||||
- Tools Required: List of tools needed
|
||||
- Estimated Duration: Total time estimate
|
||||
- Complexity Score: 1-10 scale
|
||||
- Safety Considerations: Key safety points
|
||||
- Quality Checks: Verification steps`;
|
||||
}
|
||||
|
||||
async generatePlan(query, context = {}) {
|
||||
try {
|
||||
const startTime = Date.now();
|
||||
|
||||
// Prepare context for the model
|
||||
const enhancedContext = {
|
||||
...context,
|
||||
timestamp: new Date().toISOString(),
|
||||
modelType: this.modelType
|
||||
};
|
||||
|
||||
// Generate the plan using Groq
|
||||
const response = await groqService.generateEngineeringPlan(query, enhancedContext);
|
||||
|
||||
const endTime = Date.now();
|
||||
const processingTime = (endTime - startTime) / 1000;
|
||||
|
||||
// Parse the response to extract structured plan data
|
||||
const planData = this.parsePlanResponse(response.content);
|
||||
|
||||
logger.info(`MODEL1 plan generated in ${processingTime}s for query: ${query.substring(0, 100)}...`);
|
||||
|
||||
return {
|
||||
...planData,
|
||||
processingTime,
|
||||
tokensUsed: response.usage.total_tokens,
|
||||
model: response.model,
|
||||
finishReason: response.finishReason
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error('MODEL1 plan generation error:', error);
|
||||
throw new Error(`MODEL1 plan generation failed: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
parsePlanResponse(content) {
|
||||
try {
|
||||
// Extract structured data from the response
|
||||
const lines = content.split('\n');
|
||||
let title = '';
|
||||
let description = '';
|
||||
let steps = [];
|
||||
let toolsRequired = [];
|
||||
let estimatedDuration = 0;
|
||||
let complexityScore = 5;
|
||||
let safetyConsiderations = [];
|
||||
let qualityChecks = [];
|
||||
|
||||
let currentSection = '';
|
||||
|
||||
for (const line of lines) {
|
||||
const trimmedLine = line.trim();
|
||||
|
||||
if (trimmedLine.toLowerCase().includes('title:')) {
|
||||
title = trimmedLine.split(':')[1]?.trim() || 'Engineering Plan';
|
||||
} else if (trimmedLine.toLowerCase().includes('description:')) {
|
||||
description = trimmedLine.split(':')[1]?.trim() || '';
|
||||
} else if (trimmedLine.toLowerCase().includes('steps:')) {
|
||||
currentSection = 'steps';
|
||||
} else if (trimmedLine.toLowerCase().includes('tools required:')) {
|
||||
currentSection = 'tools';
|
||||
} else if (trimmedLine.toLowerCase().includes('estimated duration:')) {
|
||||
const duration = trimmedLine.split(':')[1]?.trim();
|
||||
estimatedDuration = this.parseDuration(duration);
|
||||
} else if (trimmedLine.toLowerCase().includes('complexity score:')) {
|
||||
const score = trimmedLine.split(':')[1]?.trim();
|
||||
complexityScore = parseInt(score) || 5;
|
||||
} else if (trimmedLine.toLowerCase().includes('safety considerations:')) {
|
||||
currentSection = 'safety';
|
||||
} else if (trimmedLine.toLowerCase().includes('quality checks:')) {
|
||||
currentSection = 'quality';
|
||||
} else if (trimmedLine.match(/^\d+\./)) {
|
||||
if (currentSection === 'steps') {
|
||||
steps.push(trimmedLine);
|
||||
}
|
||||
} else if (trimmedLine.startsWith('-')) {
|
||||
if (currentSection === 'tools') {
|
||||
toolsRequired.push(trimmedLine.substring(1).trim());
|
||||
} else if (currentSection === 'safety') {
|
||||
safetyConsiderations.push(trimmedLine.substring(1).trim());
|
||||
} else if (currentSection === 'quality') {
|
||||
qualityChecks.push(trimmedLine.substring(1).trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If no structured data found, create a basic plan
|
||||
if (!title) {
|
||||
title = 'Engineering Plan';
|
||||
description = content.substring(0, 200) + '...';
|
||||
steps = [content];
|
||||
}
|
||||
|
||||
return {
|
||||
title,
|
||||
description,
|
||||
steps,
|
||||
toolsRequired,
|
||||
estimatedDuration,
|
||||
complexityScore,
|
||||
safetyConsiderations,
|
||||
qualityChecks,
|
||||
rawContent: content
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error('Error parsing plan response:', error);
|
||||
return {
|
||||
title: 'Engineering Plan',
|
||||
description: content,
|
||||
steps: [content],
|
||||
toolsRequired: [],
|
||||
estimatedDuration: 60,
|
||||
complexityScore: 5,
|
||||
safetyConsiderations: [],
|
||||
qualityChecks: [],
|
||||
rawContent: content
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
parseDuration(duration) {
|
||||
if (!duration) return 60;
|
||||
|
||||
const match = duration.match(/(\d+)\s*(hour|hr|minute|min|day|d)/i);
|
||||
if (match) {
|
||||
const value = parseInt(match[1]);
|
||||
const unit = match[2].toLowerCase();
|
||||
|
||||
switch (unit) {
|
||||
case 'hour':
|
||||
case 'hr':
|
||||
return value * 60;
|
||||
case 'minute':
|
||||
case 'min':
|
||||
return value;
|
||||
case 'day':
|
||||
case 'd':
|
||||
return value * 24 * 60;
|
||||
default:
|
||||
return 60;
|
||||
}
|
||||
}
|
||||
|
||||
return 60; // Default to 60 minutes
|
||||
}
|
||||
|
||||
async savePlan(planData, conversationId, userId) {
|
||||
try {
|
||||
const plan = await Plan.create({
|
||||
conversation_id: conversationId,
|
||||
title: planData.title,
|
||||
description: planData.description,
|
||||
steps: planData.steps,
|
||||
status: 'draft',
|
||||
tools_required: planData.toolsRequired,
|
||||
estimated_duration: planData.estimatedDuration,
|
||||
complexity_score: planData.complexityScore,
|
||||
metadata: {
|
||||
safetyConsiderations: planData.safetyConsiderations,
|
||||
qualityChecks: planData.qualityChecks,
|
||||
processingTime: planData.processingTime,
|
||||
tokensUsed: planData.tokensUsed,
|
||||
model: planData.model
|
||||
}
|
||||
});
|
||||
|
||||
// Create a message record for the plan
|
||||
await Message.create({
|
||||
conversation_id: conversationId,
|
||||
plan_id: plan.id,
|
||||
role: 'assistant',
|
||||
content: planData.rawContent,
|
||||
message_type: 'plan',
|
||||
metadata: {
|
||||
modelType: this.modelType,
|
||||
processingTime: planData.processingTime,
|
||||
tokensUsed: planData.tokensUsed
|
||||
}
|
||||
});
|
||||
|
||||
logger.info(`Plan saved: ${plan.id} for conversation: ${conversationId}`);
|
||||
|
||||
return plan;
|
||||
} catch (error) {
|
||||
logger.error('Error saving plan:', error);
|
||||
throw new Error(`Failed to save plan: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async validatePlan(planId, feedback = []) {
|
||||
try {
|
||||
const plan = await Plan.findByPk(planId);
|
||||
if (!plan) {
|
||||
throw new Error('Plan not found');
|
||||
}
|
||||
|
||||
const validationResponse = await groqService.validatePlan(plan.description, feedback);
|
||||
|
||||
// Update plan with validation results
|
||||
await plan.update({
|
||||
status: validationResponse.content.includes('valid') ? 'approved' : 'rejected',
|
||||
approval_feedback: validationResponse.content,
|
||||
metadata: {
|
||||
...plan.metadata,
|
||||
validation: {
|
||||
response: validationResponse.content,
|
||||
tokensUsed: validationResponse.usage.total_tokens,
|
||||
processingTime: validationResponse.processingTime
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
logger.info(`Plan validated: ${planId}, status: ${plan.status}`);
|
||||
|
||||
return {
|
||||
plan,
|
||||
validation: validationResponse
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error('Plan validation error:', error);
|
||||
throw new Error(`Plan validation failed: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async getModelStatus() {
|
||||
try {
|
||||
const groqInfo = await groqService.getModelInfo();
|
||||
const connectionTest = await groqService.testConnection();
|
||||
|
||||
return {
|
||||
modelType: this.modelType,
|
||||
status: connectionTest.success ? 'active' : 'error',
|
||||
groqInfo,
|
||||
connectionTest,
|
||||
lastChecked: new Date().toISOString()
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error('MODEL1 status check error:', error);
|
||||
return {
|
||||
modelType: this.modelType,
|
||||
status: 'error',
|
||||
error: error.message,
|
||||
lastChecked: new Date().toISOString()
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new Model1Service();
|
||||
Reference in New Issue
Block a user