CodeReview/backend/app/services/llm/factory.py

219 lines
6.7 KiB
Python
Raw Permalink Normal View History

"""
LLM工厂类 - 统一创建和管理LLM适配器
使用 LiteLLM 作为主要适配器支持大多数 LLM 提供商
对于 API 格式特殊的提供商百度MiniMax豆包使用原生适配器
"""
from typing import Dict, List
from .types import LLMConfig, LLMProvider, DEFAULT_MODELS
from .base_adapter import BaseLLMAdapter
from .adapters import (
LiteLLMAdapter,
BaiduAdapter,
MinimaxAdapter,
DoubaoAdapter,
)
# 必须使用原生适配器的提供商API 格式特殊)
NATIVE_ONLY_PROVIDERS = {
LLMProvider.BAIDU,
LLMProvider.MINIMAX,
LLMProvider.DOUBAO,
}
class LLMFactory:
"""LLM工厂类"""
_adapters: Dict[str, BaseLLMAdapter] = {}
@classmethod
def create_adapter(cls, config: LLMConfig) -> BaseLLMAdapter:
"""创建LLM适配器实例"""
cache_key = cls._get_cache_key(config)
# 从缓存中获取
if cache_key in cls._adapters:
return cls._adapters[cache_key]
# 创建新的适配器实例
adapter = cls._instantiate_adapter(config)
# 缓存实例
cls._adapters[cache_key] = adapter
return adapter
@classmethod
def _instantiate_adapter(cls, config: LLMConfig) -> BaseLLMAdapter:
"""根据提供商类型实例化适配器"""
# 如果未指定模型,使用默认模型
if not config.model:
config.model = DEFAULT_MODELS.get(config.provider, "gpt-4o-mini")
# 对于必须使用原生适配器的提供商
if config.provider in NATIVE_ONLY_PROVIDERS:
return cls._create_native_adapter(config)
# 其他提供商使用 LiteLLM
if LiteLLMAdapter.supports_provider(config.provider):
return LiteLLMAdapter(config)
# 不支持的提供商
raise ValueError(f"不支持的LLM提供商: {config.provider}")
@classmethod
def _create_native_adapter(cls, config: LLMConfig) -> BaseLLMAdapter:
"""创建原生适配器(仅用于 API 格式特殊的提供商)"""
native_adapter_map = {
LLMProvider.BAIDU: BaiduAdapter,
LLMProvider.MINIMAX: MinimaxAdapter,
LLMProvider.DOUBAO: DoubaoAdapter,
}
adapter_class = native_adapter_map.get(config.provider)
if not adapter_class:
raise ValueError(f"不支持的原生适配器提供商: {config.provider}")
return adapter_class(config)
@classmethod
def _get_cache_key(cls, config: LLMConfig) -> str:
"""生成缓存键"""
api_key_prefix = config.api_key[:8] if config.api_key else "no-key"
return f"{config.provider.value}:{config.model}:{api_key_prefix}"
@classmethod
def clear_cache(cls) -> None:
"""清除缓存"""
cls._adapters.clear()
@classmethod
def get_supported_providers(cls) -> List[LLMProvider]:
"""获取支持的提供商列表"""
return list(LLMProvider)
@classmethod
def get_default_model(cls, provider: LLMProvider) -> str:
"""获取提供商的默认模型"""
return DEFAULT_MODELS.get(provider, "gpt-4o-mini")
@classmethod
def get_available_models(cls, provider: LLMProvider) -> List[str]:
"""获取提供商的可用模型列表 (2025年最新)"""
models = {
LLMProvider.GEMINI: [
"gemini-3-pro",
"gemini-3.0-deep-think",
"gemini-2.5-flash",
"gemini-2.5-pro",
"gemini-2.5-flash-lite",
"gemini-2.5-flash-live-api",
"veo-3.1",
"veo-3.1-fast",
],
LLMProvider.OPENAI: [
"gpt-5",
"gpt-5.1",
"gpt-5.1-instant",
"gpt-5.1-codex-max",
"gpt-4o",
"gpt-4o-mini",
"gpt-4.5",
"o4-mini",
"o3",
"o3-mini",
"gpt-oss-120b",
"gpt-oss-20b",
],
LLMProvider.CLAUDE: [
"claude-opus-4.5",
"claude-sonnet-4.5",
"claude-haiku-4.5",
"claude-sonnet-4",
"claude-opus-4",
"claude-3.7-sonnet",
"claude-3.5-sonnet",
"claude-3.5-haiku",
"claude-3-opus",
],
LLMProvider.QWEN: [
"qwen3-max-instruct",
"qwen3-235b-a22b",
"qwen3-turbo",
"qwen3-32b",
"qwen3-4b",
"qwen3-embedding-8b",
"qwen-image",
"qwen-vl",
"qwen-audio",
],
LLMProvider.DEEPSEEK: [
"deepseek-v3.1-terminus",
"deepseek-r1-70b",
"deepseek-r1-zero",
"deepseek-v3.2-exp",
"deepseek-chat",
"deepseek-reasoner",
"deepseek-ocr",
],
LLMProvider.ZHIPU: [
"glm-4.6",
"glm-4.6-reap-218b",
"glm-4.5",
"glm-4.5v",
"glm-4.5-air-106b",
"glm-4-flash",
"glm-4v-flash",
"glm-4.1v-thinking",
],
LLMProvider.MOONSHOT: [
"kimi-k2",
"kimi-k2-thinking",
"kimi-k2-instruct-0905",
"kimi-k1.5",
"kimi-vl",
"kimi-dev-72b",
"kimi-researcher",
"kimi-linear",
],
LLMProvider.BAIDU: [
"ernie-4.5",
"ernie-4.5-21b-a3b-thinking",
"ernie-4.0-8k",
"ernie-3.5-8k",
"ernie-vl",
],
LLMProvider.MINIMAX: [
"minimax-m2",
"minimax-01-text",
"minimax-01-vl",
"minimax-m1",
"speech-2.6",
"hailuo-02",
"music-1.5",
],
LLMProvider.DOUBAO: [
"doubao-1.6-pro",
"doubao-1.5-pro",
"doubao-seed-code",
"doubao-seed-1.6",
"doubao-vision-language",
],
LLMProvider.OLLAMA: [
"llama3.3-70b",
"qwen3-8b",
"gemma3-27b",
"dolphin-3.0-llama3.1-8b",
"cogito-v1",
"deepseek-r1",
"gpt-oss-120b",
"llama3.1-405b",
"mistral-nemo",
"phi-3",
],
}
return models.get(provider, [])