Files
cim_summary/backend/src/index.ts
Jon 57770fd99d feat: Implement hybrid LLM approach with enhanced prompts for CIM analysis
🎯 Major Features:
- Hybrid LLM configuration: Claude 3.7 Sonnet (primary) + GPT-4.5 (fallback)
- Task-specific model selection for optimal performance
- Enhanced prompts for all analysis types with proven results

🔧 Technical Improvements:
- Enhanced financial analysis with fiscal year mapping (100% success rate)
- Business model analysis with scalability assessment
- Market positioning analysis with TAM/SAM extraction
- Management team assessment with succession planning
- Creative content generation with GPT-4.5

📊 Performance & Cost Optimization:
- Claude 3.7 Sonnet: /5 per 1M tokens (82.2% MATH score)
- GPT-4.5: Premium creative content (5/50 per 1M tokens)
- ~80% cost savings using Claude for analytical tasks
- Automatic fallback system for reliability

 Proven Results:
- Successfully extracted 3-year financial data from STAX CIM
- Correctly mapped fiscal years (2023→FY-3, 2024→FY-2, 2025E→FY-1, LTM Mar-25→LTM)
- Identified revenue: 4M→1M→1M→6M (LTM)
- Identified EBITDA: 8.9M→3.9M→1M→7.2M (LTM)

🚀 Files Added/Modified:
- Enhanced LLM service with task-specific model selection
- Updated environment configuration for hybrid approach
- Enhanced prompt builders for all analysis types
- Comprehensive testing scripts and documentation
- Updated frontend components for improved UX

📚 References:
- Eden AI Model Comparison: Claude 3.7 Sonnet vs GPT-4.5
- Artificial Analysis Benchmarks for performance metrics
- Cost optimization based on model strengths and pricing
2025-07-28 16:46:06 -04:00

173 lines
5.0 KiB
TypeScript

import express from 'express';
import cors from 'cors';
import helmet from 'helmet';
import morgan from 'morgan';
import rateLimit from 'express-rate-limit';
import { config } from './config/env';
import { logger } from './utils/logger';
import authRoutes from './routes/auth';
import documentRoutes from './routes/documents';
import vectorRoutes from './routes/vector';
import { errorHandler } from './middleware/errorHandler';
import { notFoundHandler } from './middleware/notFoundHandler';
import { jobQueueService } from './services/jobQueueService';
const app = express();
const PORT = config.port || 5000;
// Security middleware
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
scriptSrc: ["'self'"],
imgSrc: ["'self'", "data:", "https:"],
},
},
}));
// CORS configuration
app.use(cors({
origin: config.frontendUrl || 'http://localhost:3000',
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization'],
}));
// Rate limiting
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 1000, // limit each IP to 1000 requests per windowMs (increased for testing)
message: {
error: 'Too many requests from this IP, please try again later.',
},
standardHeaders: true,
legacyHeaders: false,
});
app.use(limiter);
// Body parsing middleware
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true, limit: '10mb' }));
// Logging middleware
app.use(morgan('combined', {
stream: {
write: (message: string) => logger.info(message.trim()),
},
}));
// Health check endpoint
app.get('/health', (_req, res) => { // _req to fix TS6133
res.status(200).json({
status: 'ok',
timestamp: new Date().toISOString(),
uptime: process.uptime(),
environment: config.nodeEnv,
});
});
// Agentic RAG health check endpoints
app.get('/health/agentic-rag', async (_req, res) => {
try {
const { agenticRAGDatabaseService } = await import('./services/agenticRAGDatabaseService');
const healthStatus = await agenticRAGDatabaseService.getHealthStatus();
res.json(healthStatus);
} catch (error) {
logger.error('Agentic RAG health check failed', { error });
res.status(500).json({
error: 'Health check failed',
status: 'unhealthy',
timestamp: new Date().toISOString()
});
}
});
app.get('/health/agentic-rag/metrics', async (_req, res) => {
try {
const { agenticRAGDatabaseService } = await import('./services/agenticRAGDatabaseService');
const startDate = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000); // 30 days ago
const metrics = await agenticRAGDatabaseService.generatePerformanceReport(startDate, new Date());
res.json(metrics);
} catch (error) {
logger.error('Agentic RAG metrics retrieval failed', { error });
res.status(500).json({ error: 'Metrics retrieval failed' });
}
});
// API routes
app.use('/api/auth', authRoutes);
app.use('/api/documents', documentRoutes);
app.use('/api/vector', vectorRoutes);
// API root endpoint
app.get('/api', (_req, res) => { // _req to fix TS6133
res.json({
message: 'CIM Document Processor API',
version: '1.0.0',
endpoints: {
auth: '/api/auth',
documents: '/api/documents',
health: '/health',
agenticRagHealth: '/health/agentic-rag',
agenticRagMetrics: '/health/agentic-rag/metrics',
},
});
});
// 404 handler
app.use(notFoundHandler);
// Global error handler (must be last)
app.use(errorHandler);
// Start server
const server = app.listen(PORT, () => {
logger.info(`🚀 Server running on port ${PORT}`);
logger.info(`📊 Environment: ${config.nodeEnv}`);
logger.info(`🔗 API URL: http://localhost:${PORT}/api`);
logger.info(`🏥 Health check: http://localhost:${PORT}/health`);
});
// Start job queue service
jobQueueService.start();
logger.info('📋 Job queue service started');
// Graceful shutdown
const gracefulShutdown = (signal: string) => {
logger.info(`${signal} received, shutting down gracefully`);
// Stop accepting new connections
server.close(async () => {
logger.info('HTTP server closed');
// Stop job queue service
jobQueueService.stop();
logger.info('Job queue service stopped');
// Stop upload progress service
try {
const { uploadProgressService } = await import('./services/uploadProgressService');
uploadProgressService.stop();
logger.info('Upload progress service stopped');
} catch (error) {
logger.warn('Could not stop upload progress service', { error });
}
logger.info('Process terminated');
process.exit(0);
});
// Force close after 30 seconds
setTimeout(() => {
logger.error('Could not close connections in time, forcefully shutting down');
process.exit(1);
}, 30000);
};
process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
process.on('SIGINT', () => gracefulShutdown('SIGINT'));
export default app;