from typing import Optional from sqlalchemy.orm import Session from openai import AsyncOpenAI from providers.base_provider import LLMProvider from services.api_key_service import ApiKeyService class DeepSeekProvider(LLMProvider): """ DeepSeek API provider implementation using OpenAI-compatible API """ def __init__(self, db: Session, api_key: Optional[str] = None): if not api_key: api_key = ApiKeyService.get_api_key(db, "deepseek") if not api_key: raise ValueError("DeepSeek API key not found in database or provided") self.client = AsyncOpenAI( api_key=api_key, base_url="https://api.deepseek.com" ) def supports_tools(self) -> bool: return False async def generate_response(self, model: str, prompt: str, max_tokens: Optional[int] = None) -> str: try: is_reasoner = "reasoner" in model or "r1" in model.lower() messages = [{"role": "user", "content": prompt}] # deepseek-reasoner 不支持 system message,把指令放进 user message if not is_reasoner: messages.insert(0, { "role": "system", "content": "你正在参与一场结构化辩论。请按照用户消息中的规则进行辩论,直接给出你的论点,不要重复提示词或历史记录。" }) kwargs = { "model": model, "messages": messages, } # reasoner 模型不支持 max_tokens,使用 max_completion_tokens if is_reasoner: kwargs["max_completion_tokens"] = max_tokens or 4096 else: kwargs["max_tokens"] = max_tokens or 500 response = await self.client.chat.completions.create(**kwargs) message = response.choices[0].message content = message.content or "" # deepseek-reasoner 的主要内容可能在 reasoning_content 中 if not content.strip() and is_reasoner: reasoning = getattr(message, "reasoning_content", None) if reasoning: content = reasoning return content.strip() except Exception as e: raise Exception(f"Error calling DeepSeek API: {str(e)}")