mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-22 16:43:35 +00:00
refactor: 重构gemini转部分
This commit is contained in:
2241
src/handlers/geminiHandlers.js
Normal file
2241
src/handlers/geminiHandlers.js
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -2,10 +2,11 @@ const express = require('express')
|
||||
const { authenticateApiKey } = require('../middleware/auth')
|
||||
const logger = require('../utils/logger')
|
||||
const { handleChatCompletion } = require('./openaiClaudeRoutes')
|
||||
// 从 handlers/geminiHandlers.js 导入处理函数
|
||||
const {
|
||||
handleGenerateContent: geminiHandleGenerateContent,
|
||||
handleStreamGenerateContent: geminiHandleStreamGenerateContent
|
||||
} = require('./geminiRoutes')
|
||||
} = require('../handlers/geminiHandlers')
|
||||
const openaiRoutes = require('./openaiRoutes')
|
||||
|
||||
const router = express.Router()
|
||||
@@ -16,25 +17,6 @@ function detectBackendFromModel(modelName) {
|
||||
return 'claude' // 默认 Claude
|
||||
}
|
||||
|
||||
// 首先尝试使用 modelService 查找模型的 provider
|
||||
try {
|
||||
const modelService = require('../services/modelService')
|
||||
const provider = modelService.getModelProvider(modelName)
|
||||
|
||||
if (provider === 'anthropic') {
|
||||
return 'claude'
|
||||
}
|
||||
if (provider === 'openai') {
|
||||
return 'openai'
|
||||
}
|
||||
if (provider === 'google') {
|
||||
return 'gemini'
|
||||
}
|
||||
} catch (error) {
|
||||
logger.warn(`⚠️ Failed to detect backend from modelService: ${error.message}`)
|
||||
}
|
||||
|
||||
// 降级到前缀匹配作为后备方案
|
||||
const model = modelName.toLowerCase()
|
||||
|
||||
// Claude 模型
|
||||
@@ -42,21 +24,16 @@ function detectBackendFromModel(modelName) {
|
||||
return 'claude'
|
||||
}
|
||||
|
||||
// OpenAI 模型
|
||||
if (
|
||||
model.startsWith('gpt-') ||
|
||||
model.startsWith('o1-') ||
|
||||
model.startsWith('o3-') ||
|
||||
model === 'chatgpt-4o-latest'
|
||||
) {
|
||||
return 'openai'
|
||||
}
|
||||
|
||||
// Gemini 模型
|
||||
if (model.startsWith('gemini-')) {
|
||||
return 'gemini'
|
||||
}
|
||||
|
||||
// OpenAI 模型
|
||||
if (model.startsWith('gpt-')) {
|
||||
return 'openai'
|
||||
}
|
||||
|
||||
// 默认使用 Claude
|
||||
return 'claude'
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const logger = require('../utils/logger')
|
||||
|
||||
/**
|
||||
@@ -9,54 +7,22 @@ const logger = require('../utils/logger')
|
||||
*/
|
||||
class ModelService {
|
||||
constructor() {
|
||||
this.modelsFile = path.join(process.cwd(), 'data', 'supported_models.json')
|
||||
this.supportedModels = null
|
||||
this.fileWatcher = null
|
||||
this.supportedModels = this.getDefaultModels()
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化模型服务
|
||||
*/
|
||||
async initialize() {
|
||||
try {
|
||||
this.loadModels()
|
||||
this.setupFileWatcher()
|
||||
logger.success('✅ Model service initialized successfully')
|
||||
} catch (error) {
|
||||
logger.error('❌ Failed to initialize model service:', error)
|
||||
}
|
||||
const totalModels = Object.values(this.supportedModels).reduce(
|
||||
(sum, config) => sum + config.models.length,
|
||||
0
|
||||
)
|
||||
logger.success(`✅ Model service initialized with ${totalModels} models`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载支持的模型配置
|
||||
*/
|
||||
loadModels() {
|
||||
try {
|
||||
if (fs.existsSync(this.modelsFile)) {
|
||||
const data = fs.readFileSync(this.modelsFile, 'utf8')
|
||||
this.supportedModels = JSON.parse(data)
|
||||
|
||||
const totalModels = Object.values(this.supportedModels).reduce(
|
||||
(sum, config) => sum + config.models.length,
|
||||
0
|
||||
)
|
||||
|
||||
logger.info(`📋 Loaded ${totalModels} supported models from configuration`)
|
||||
} else {
|
||||
logger.warn('⚠️ Supported models file not found, using defaults')
|
||||
this.supportedModels = this.getDefaultModels()
|
||||
|
||||
// 创建默认配置文件
|
||||
this.saveDefaultConfig()
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('❌ Failed to load supported models:', error)
|
||||
this.supportedModels = this.getDefaultModels()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取默认模型配置(后备方案)
|
||||
* 获取支持的模型配置
|
||||
*/
|
||||
getDefaultModels() {
|
||||
return {
|
||||
@@ -64,6 +30,8 @@ class ModelService {
|
||||
provider: 'anthropic',
|
||||
description: 'Claude models from Anthropic',
|
||||
models: [
|
||||
'claude-opus-4-5-20251101',
|
||||
'claude-haiku-4-5-20251001',
|
||||
'claude-sonnet-4-5-20250929',
|
||||
'claude-opus-4-1-20250805',
|
||||
'claude-sonnet-4-20250514',
|
||||
@@ -79,55 +47,22 @@ class ModelService {
|
||||
provider: 'openai',
|
||||
description: 'OpenAI GPT models',
|
||||
models: [
|
||||
'gpt-4o',
|
||||
'gpt-4o-mini',
|
||||
'gpt-4.1',
|
||||
'gpt-4.1-mini',
|
||||
'gpt-4.1-nano',
|
||||
'gpt-4-turbo',
|
||||
'gpt-4',
|
||||
'gpt-3.5-turbo',
|
||||
'o3',
|
||||
'o4-mini',
|
||||
'chatgpt-4o-latest'
|
||||
'gpt-5.1-2025-11-13',
|
||||
'gpt-5.1-codex-mini',
|
||||
'gpt-5.1-codex',
|
||||
'gpt-5.1-codex-max',
|
||||
'gpt-5-2025-08-07',
|
||||
'gpt-5-codex'
|
||||
]
|
||||
},
|
||||
gemini: {
|
||||
provider: 'google',
|
||||
description: 'Google Gemini models',
|
||||
models: [
|
||||
'gemini-1.5-pro',
|
||||
'gemini-1.5-flash',
|
||||
'gemini-2.0-flash',
|
||||
'gemini-2.0-flash-exp',
|
||||
'gemini-2.0-flash-thinking',
|
||||
'gemini-2.0-flash-thinking-exp',
|
||||
'gemini-2.0-pro',
|
||||
'gemini-2.5-flash',
|
||||
'gemini-2.5-flash-lite',
|
||||
'gemini-2.5-pro'
|
||||
]
|
||||
models: ['gemini-2.5-pro', 'gemini-3-pro-preview', 'gemini-2.5-flash']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存默认配置到文件
|
||||
*/
|
||||
saveDefaultConfig() {
|
||||
try {
|
||||
const dataDir = path.dirname(this.modelsFile)
|
||||
if (!fs.existsSync(dataDir)) {
|
||||
fs.mkdirSync(dataDir, { recursive: true })
|
||||
}
|
||||
|
||||
fs.writeFileSync(this.modelsFile, JSON.stringify(this.supportedModels, null, 2))
|
||||
logger.info('💾 Created default supported_models.json configuration')
|
||||
} catch (error) {
|
||||
logger.error('❌ Failed to save default config:', error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有支持的模型(OpenAI API 格式)
|
||||
*/
|
||||
@@ -183,83 +118,27 @@ class ModelService {
|
||||
return model ? model.owned_by : null
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新加载模型配置
|
||||
*/
|
||||
reloadModels() {
|
||||
logger.info('🔄 Reloading supported models configuration...')
|
||||
this.loadModels()
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置文件监听器(监听配置文件变化)
|
||||
*/
|
||||
setupFileWatcher() {
|
||||
try {
|
||||
// 如果已有监听器,先关闭
|
||||
if (this.fileWatcher) {
|
||||
this.fileWatcher.close()
|
||||
this.fileWatcher = null
|
||||
}
|
||||
|
||||
// 只有文件存在时才设置监听器
|
||||
if (!fs.existsSync(this.modelsFile)) {
|
||||
logger.debug('📋 Models file does not exist yet, skipping file watcher setup')
|
||||
return
|
||||
}
|
||||
|
||||
// 使用 fs.watchFile 监听文件变化
|
||||
const watchOptions = {
|
||||
persistent: true,
|
||||
interval: 60000 // 每60秒检查一次
|
||||
}
|
||||
|
||||
let lastMtime = fs.statSync(this.modelsFile).mtimeMs
|
||||
|
||||
fs.watchFile(this.modelsFile, watchOptions, (curr, _prev) => {
|
||||
if (curr.mtimeMs !== lastMtime) {
|
||||
lastMtime = curr.mtimeMs
|
||||
logger.info('📋 Detected change in supported_models.json, reloading...')
|
||||
this.reloadModels()
|
||||
}
|
||||
})
|
||||
|
||||
// 保存引用以便清理
|
||||
this.fileWatcher = {
|
||||
close: () => fs.unwatchFile(this.modelsFile)
|
||||
}
|
||||
|
||||
logger.info('👁️ File watcher set up for supported_models.json')
|
||||
} catch (error) {
|
||||
logger.error('❌ Failed to setup file watcher:', error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取服务状态
|
||||
*/
|
||||
getStatus() {
|
||||
const totalModels = this.supportedModels
|
||||
? Object.values(this.supportedModels).reduce((sum, config) => sum + config.models.length, 0)
|
||||
: 0
|
||||
const totalModels = Object.values(this.supportedModels).reduce(
|
||||
(sum, config) => sum + config.models.length,
|
||||
0
|
||||
)
|
||||
|
||||
return {
|
||||
initialized: this.supportedModels !== null,
|
||||
initialized: true,
|
||||
totalModels,
|
||||
providers: this.supportedModels ? Object.keys(this.supportedModels) : [],
|
||||
fileExists: fs.existsSync(this.modelsFile)
|
||||
providers: Object.keys(this.supportedModels)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理资源
|
||||
* 清理资源(保留接口兼容性)
|
||||
*/
|
||||
cleanup() {
|
||||
if (this.fileWatcher) {
|
||||
this.fileWatcher.close()
|
||||
this.fileWatcher = null
|
||||
logger.debug('📋 Model service file watcher closed')
|
||||
}
|
||||
logger.debug('📋 Model service cleanup (no-op)')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user