feat: Add multi-LLM provider support with DeepSeek integration

Major Features:
-  Multi-LLM provider support (DeepSeek, Ollama, OpenAI, Custom)
- 🤖 Admin panel LLM configuration management UI
- 🔄 Dynamic provider switching without restart
- 🧪 Built-in API connection testing
- 🔒 Secure API key management

Backend Changes:
- Add routes/llmConfig.js: Complete LLM config CRUD API
- Update routes/analyze.js: Use database LLM configuration
- Update server.js: Add LLM config routes
- Add scripts/add-deepseek-config.js: DeepSeek setup script

Frontend Changes:
- Update src/pages/AdminPage.jsx: Add LLM Config tab + modal
- Update src/services/api.js: Add LLM config API methods
- Provider presets for DeepSeek, Ollama, OpenAI
- Test connection feature in config modal

Configuration:
- Update .env.example: Add DeepSeek API configuration
- Update package.json: Add llm:add-deepseek script

Documentation:
- Add docs/LLM_CONFIGURATION_GUIDE.md: Complete guide
- Add DEEPSEEK_INTEGRATION.md: Integration summary
- Quick setup instructions for DeepSeek

API Endpoints:
- GET /api/llm-config: List all configurations
- GET /api/llm-config/active: Get active configuration
- POST /api/llm-config: Create configuration
- PUT /api/llm-config/🆔 Update configuration
- PUT /api/llm-config/:id/activate: Activate configuration
- DELETE /api/llm-config/🆔 Delete configuration
- POST /api/llm-config/test: Test API connection

Database:
- Uses existing llm_configs table
- Only one config active at a time
- Fallback to Ollama if no database config

Security:
- Admin-only access to LLM configuration
- API keys never returned in GET requests
- Audit logging for all config changes
- Cannot delete active configuration

DeepSeek Model:
- Model: deepseek-chat
- High-quality 5 Why analysis
- Excellent Chinese language support
- Cost-effective pricing

🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
donald
2025-12-06 00:33:10 +08:00
parent 30e39b5c6f
commit 957003bc7c
10 changed files with 1564 additions and 16 deletions

View File

@@ -0,0 +1,88 @@
#!/usr/bin/env node
/**
* Add DeepSeek LLM Configuration
* This script adds a DeepSeek configuration to the llm_configs table
*/
import { pool, query } from '../config.js';
import dotenv from 'dotenv';
dotenv.config();
async function addDeepSeekConfig() {
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log(' Adding DeepSeek LLM Configuration');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
try {
// Check if DeepSeek config already exists
const existing = await query(
`SELECT id FROM llm_configs WHERE provider_name = 'DeepSeek' LIMIT 1`
);
if (existing.length > 0) {
console.log('✅ DeepSeek configuration already exists (ID:', existing[0].id, ')');
console.log(' Skipping...\n');
return;
}
// Get API key from environment or leave empty
const apiKey = process.env.DEEPSEEK_API_KEY || '';
if (!apiKey) {
console.log('⚠️ Warning: DEEPSEEK_API_KEY not found in .env');
console.log(' You will need to add the API key in the admin panel\n');
}
// First, deactivate all existing configs
await query('UPDATE llm_configs SET is_active = 0');
// Insert DeepSeek configuration
const result = await query(
`INSERT INTO llm_configs
(provider_name, api_endpoint, api_key, model_name, temperature, max_tokens, timeout_seconds, is_active)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
[
'DeepSeek',
process.env.DEEPSEEK_API_URL || 'https://api.deepseek.com',
apiKey || null,
process.env.DEEPSEEK_MODEL || 'deepseek-chat',
0.7,
6000,
120,
1 // Set as active
]
);
console.log('✅ DeepSeek configuration added successfully!');
console.log(' Config ID:', result.insertId);
console.log(' Provider: DeepSeek');
console.log(' Model: deepseek-chat');
console.log(' Status: Active\n');
console.log('📝 Next steps:');
console.log(' 1. Go to Admin Panel > LLM 配置');
console.log(' 2. Add your DeepSeek API key if not already set');
console.log(' 3. Test the connection');
console.log(' 4. Start using DeepSeek for 5 Why analysis!\n');
} catch (error) {
console.error('❌ Error adding DeepSeek configuration:', error.message);
process.exit(1);
} finally {
await pool.end();
}
}
// Run the script
addDeepSeekConfig()
.then(() => {
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log(' Configuration Complete');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
process.exit(0);
})
.catch((error) => {
console.error('Fatal error:', error);
process.exit(1);
});