UNPKG

defect-inspection-tools-mcp-server

Version:

Defect inspection tools server handling defect detection, analysis, and reporting with AI/ML capabilities for quality control

353 lines (345 loc) 15.6 kB
import { logger } from './logger.js'; import { SanitizationMiddleware } from '../middleware/sanitization-middleware.js'; export class LLMService { constructor(openaiService, perplexityService, cohereService) { this.openaiService = openaiService; this.perplexityService = perplexityService || openaiService; this.cohereService = cohereService || openaiService; } // OpenAI ChatGPT completion async chatCompletion(messages, model = 'gpt-3.5-turbo', options = {}) { try { const opts = { ...LLMService.DEFAULT_OPTIONS, ...options }; logger.info('Starting OpenAI chat completion', { model, messageCount: messages.length, options: opts }); // Sanitize messages const sanitizedMessages = messages.map(msg => ({ role: msg.role, content: SanitizationMiddleware.sanitizeString(msg.content, 8000) })); const startTime = Date.now(); const response = await this.openaiService.post('/chat/completions', { model, messages: sanitizedMessages, temperature: opts.temperature, max_tokens: opts.maxTokens, top_p: opts.topP, frequency_penalty: opts.frequencyPenalty, presence_penalty: opts.presencePenalty, stop: opts.stop, stream: opts.stream }); if (!response.success) { throw new Error(`OpenAI API error: ${response.error}`); } const responseTime = Date.now() - startTime; const data = response.data?.data; const result = { content: data.choices[0].message.content, usage: { promptTokens: data.usage?.prompt_tokens || 0, completionTokens: data.usage?.completion_tokens || 0, totalTokens: data.usage?.total_tokens || 0 }, metadata: { model: data.model, finishReason: data.choices[0].finish_reason, responseTime } }; logger.info('OpenAI chat completion successful', { model, responseTime, totalTokens: result.usage?.totalTokens, contentLength: result.content.length }); return result; } catch (error) { logger.error('OpenAI chat completion failed', { model, error: error.message, messageCount: messages.length }); throw error; } } // Perplexity completion for search-augmented responses async perplexityCompletion(messages, model = 'llama-3.1-sonar-small-128k-online', options = {}) { try { const opts = { ...LLMService.DEFAULT_OPTIONS, ...options }; logger.info('Starting Perplexity completion', { model, messageCount: messages.length, options: opts }); // Sanitize messages const sanitizedMessages = messages.map(msg => ({ role: msg.role, content: SanitizationMiddleware.sanitizeString(msg.content, 8000) })); const startTime = Date.now(); const response = await this.perplexityService.post('/chat/completions', { model, messages: sanitizedMessages, temperature: opts.temperature, max_tokens: opts.maxTokens, top_p: opts.topP, frequency_penalty: opts.frequencyPenalty, presence_penalty: opts.presencePenalty, stop: opts.stop, stream: opts.stream }); if (!response.success) { throw new Error(`Perplexity API error: ${response.error}`); } const responseTime = Date.now() - startTime; const data = response.data?.data; const result = { content: data.choices[0].message.content, usage: { promptTokens: data.usage?.prompt_tokens || 0, completionTokens: data.usage?.completion_tokens || 0, totalTokens: data.usage?.total_tokens || 0 }, metadata: { model: data.model, finishReason: data.choices[0].finish_reason, responseTime } }; logger.info('Perplexity completion successful', { model, responseTime, totalTokens: result.usage?.totalTokens, contentLength: result.content.length }); return result; } catch (error) { logger.error('Perplexity completion failed', { model, error: error.message, messageCount: messages.length }); throw error; } } // Cohere completion async cohereCompletion(prompt, model = 'command-xlarge', options = {}) { try { const opts = { ...LLMService.DEFAULT_OPTIONS, ...options }; logger.info('Starting Cohere completion', { model, promptLength: prompt.length, options: opts }); // Sanitize prompt const sanitizedPrompt = SanitizationMiddleware.sanitizeString(prompt, 8000); const startTime = Date.now(); const response = await this.cohereService.post('/v1/generate', { model, prompt: sanitizedPrompt, temperature: opts.temperature, max_tokens: opts.maxTokens, top_p: opts.topP, frequency_penalty: opts.frequencyPenalty, presence_penalty: opts.presencePenalty, stop_sequences: opts.stop, stream: opts.stream }); if (!response.success) { throw new Error(`Cohere API error: ${response.error}`); } const responseTime = Date.now() - startTime; const data = response.data?.data; const result = { content: data.generations[0].text, usage: { promptTokens: data.meta?.tokens?.input_tokens || 0, completionTokens: data.meta?.tokens?.output_tokens || 0, totalTokens: (data.meta?.tokens?.input_tokens || 0) + (data.meta?.tokens?.output_tokens || 0) }, metadata: { model: data.model, finishReason: data.generations[0].finish_reason, responseTime } }; logger.info('Cohere completion successful', { model, responseTime, totalTokens: result.usage?.totalTokens, contentLength: result.content.length }); return result; } catch (error) { logger.error('Cohere completion failed', { model, error: error.message, promptLength: prompt.length }); throw error; } } // Maritime-specific analysis using LLM async analyzeMaritimeDefect(defectData, analysisType = 'severity') { try { const sanitizedData = SanitizationMiddleware.sanitizeToolArguments(defectData); const systemPrompt = this.getMaritimeSystemPrompt(analysisType); const userPrompt = this.formatDefectDataForAnalysis(sanitizedData, analysisType); const messages = [ { role: 'system', content: systemPrompt }, { role: 'user', content: userPrompt } ]; // Use OpenAI for structured analysis return await this.chatCompletion(messages, 'gpt-4', { temperature: 0.3, // Lower temperature for more consistent analysis maxTokens: 1024 }); } catch (error) { logger.error('Maritime defect analysis failed', { analysisType, error: error.message }); throw error; } } // Generate maritime compliance report async generateComplianceReport(vesselData, inspectionData, reportType = 'SIRE') { try { const sanitizedVesselData = SanitizationMiddleware.sanitizeToolArguments(vesselData); const sanitizedInspectionData = SanitizationMiddleware.sanitizeToolArguments(inspectionData); const systemPrompt = this.getComplianceSystemPrompt(reportType); const userPrompt = this.formatComplianceDataForReport(sanitizedVesselData, sanitizedInspectionData, reportType); const messages = [ { role: 'system', content: systemPrompt }, { role: 'user', content: userPrompt } ]; // Use OpenAI for comprehensive report generation return await this.chatCompletion(messages, 'gpt-4', { temperature: 0.2, // Very low temperature for formal reports maxTokens: 2048 }); } catch (error) { logger.error('Compliance report generation failed', { reportType, error: error.message }); throw error; } } // Search-augmented maritime query async searchAugmentedQuery(query, context = []) { try { const sanitizedQuery = SanitizationMiddleware.sanitizeSearchQuery(query); const sanitizedContext = context.map(c => SanitizationMiddleware.sanitizeString(c, 2000)); const messages = [ { role: 'system', content: `You are a maritime expert assistant. Use the provided context to answer questions about maritime defect inspection, compliance, and quality control. If the context doesn't contain enough information, clearly state that additional information is needed. Context: ${sanitizedContext.join('\n\n')} Guidelines: - Focus on maritime industry standards and regulations - Provide specific, actionable recommendations - Reference relevant maritime codes and standards - Consider safety implications in all responses` }, { role: 'user', content: sanitizedQuery } ]; // Use Perplexity for search-augmented responses return await this.perplexityCompletion(messages, 'llama-3.1-sonar-small-128k-online', { temperature: 0.7, maxTokens: 1024 }); } catch (error) { logger.error('Search-augmented query failed', { query: SanitizationMiddleware.sanitizeForLogging(query), error: error.message }); throw error; } } // Helper methods for maritime-specific prompts getMaritimeSystemPrompt(analysisType) { const basePrompt = `You are a maritime safety expert specializing in vessel defect inspection and compliance. You have extensive knowledge of international maritime regulations, industry standards, and best practices.`; switch (analysisType) { case 'severity': return `${basePrompt} Analyze the provided defect data and classify the severity level as Critical, High, Medium, or Low based on safety implications, regulatory requirements, and operational impact.`; case 'root_cause': return `${basePrompt} Analyze the provided defect data and identify the most likely root cause. Consider factors such as maintenance practices, operational procedures, equipment age, environmental conditions, and human factors.`; case 'recommendation': return `${basePrompt} Provide specific, actionable recommendations to address the defect. Include immediate actions, long-term solutions, preventive measures, and relevant regulatory compliance requirements.`; case 'compliance': return `${basePrompt} Assess the compliance implications of the defect against relevant maritime regulations such as SOLAS, MARPOL, ISM Code, and port state control requirements.`; default: return basePrompt; } } getComplianceSystemPrompt(reportType) { const basePrompt = `You are a maritime compliance expert specializing in vessel inspections and regulatory reporting.`; switch (reportType) { case 'SIRE': return `${basePrompt} Generate a comprehensive SIRE (Ship Inspection Report Programme) compliance report following OCIMF guidelines and standards.`; case 'CDI': return `${basePrompt} Generate a CDI (Chemical Distribution Institute) inspection report focusing on chemical tanker operations and safety standards.`; case 'PSC': return `${basePrompt} Generate a Port State Control inspection report highlighting deficiencies and compliance status with international maritime conventions.`; case 'TMSA': return `${basePrompt} Generate a TMSA (Tanker Management and Self Assessment) report focusing on management systems and operational excellence.`; default: return basePrompt; } } formatDefectDataForAnalysis(defectData, analysisType) { return `Please analyze the following maritime defect data: Defect Information: - Vessel: ${defectData.vessel_name || 'Unknown'} - IMO Number: ${defectData.imo_number || 'Unknown'} - Defect Type: ${defectData.defect_type || 'Unknown'} - Location: ${defectData.location || 'Unknown'} - Description: ${defectData.description || 'Not provided'} - Inspection Date: ${defectData.inspection_date || 'Unknown'} - Status: ${defectData.status || 'Unknown'} - Severity: ${defectData.severity || 'Unknown'} Analysis Type: ${analysisType} Please provide a detailed analysis based on the requested type.`; } formatComplianceDataForReport(vesselData, inspectionData, reportType) { return `Generate a ${reportType} compliance report for the following vessel: Vessel Information: - Name: ${vesselData.vessel_name || 'Unknown'} - IMO Number: ${vesselData.imo_number || 'Unknown'} - Type: ${vesselData.vessel_type || 'Unknown'} - Flag State: ${vesselData.flag_state || 'Unknown'} - Classification Society: ${vesselData.class_society || 'Unknown'} - Built: ${vesselData.built_year || 'Unknown'} Inspection Data: - Inspection Date: ${inspectionData.inspection_date || 'Unknown'} - Inspector: ${inspectionData.inspector || 'Unknown'} - Port: ${inspectionData.port || 'Unknown'} - Findings: ${JSON.stringify(inspectionData.findings || [])} - Deficiencies: ${JSON.stringify(inspectionData.deficiencies || [])} Please generate a comprehensive ${reportType} report with executive summary, detailed findings, recommendations, and compliance status.`; } } LLMService.DEFAULT_OPTIONS = { temperature: 0.7, maxTokens: 2048, topP: 1.0, frequencyPenalty: 0, presencePenalty: 0, stream: false }; //# sourceMappingURL=llm.js.map