| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- """
- DeepSeek API helpers (OpenAI-compatible SDK).
- """
- from __future__ import annotations
- import os
- from typing import Any
- from flask import current_app, has_app_context
- from openai import OpenAI
- DEEPSEEK_DEFAULT_BASE_URL = "https://api.deepseek.com"
- def _clean_secret(value: str | None) -> str:
- if not value:
- return ""
- return str(value).strip().strip("\r\n\t")
- def get_llm_api_key() -> str:
- """Resolve API key: DEEPSEEK_API_KEY first, then LLM_API_KEY / app config."""
- candidates = []
- if has_app_context():
- candidates.extend(
- [
- current_app.config.get("DEEPSEEK_API_KEY"),
- current_app.config.get("LLM_API_KEY"),
- ]
- )
- candidates.extend([os.environ.get("DEEPSEEK_API_KEY"), os.environ.get("LLM_API_KEY")])
- for candidate in candidates:
- cleaned = _clean_secret(candidate)
- if cleaned and cleaned not in {
- "replace-with-your-deepseek-api-key",
- "your-api-key",
- }:
- return cleaned
- return ""
- def normalize_llm_base_url(raw: str | None = None) -> str:
- """Normalize DeepSeek OpenAI-compatible base URL for SDK usage."""
- if raw is None:
- if has_app_context():
- raw = str(current_app.config.get("LLM_BASE_URL") or "")
- if not raw:
- raw = os.environ.get("LLM_BASE_URL", DEEPSEEK_DEFAULT_BASE_URL)
- url = _clean_secret(raw) or DEEPSEEK_DEFAULT_BASE_URL
- url = url.rstrip("/")
- # OpenAI SDK 会自动追加 /v1;若 env 已带 /v1,去掉以避免重复
- if url.endswith("/v1"):
- url = url[:-3]
- return url or DEEPSEEK_DEFAULT_BASE_URL
- def get_llm_base_url() -> str:
- return normalize_llm_base_url()
- def get_llm_chat_completions_url() -> str:
- """Return the HTTP endpoint for raw requests.post() callers."""
- return f"{get_llm_base_url()}/v1/chat/completions"
- def get_llm_model() -> str:
- raw = ""
- if has_app_context():
- raw = str(current_app.config.get("LLM_MODEL_NAME") or "")
- if not raw:
- raw = os.environ.get("LLM_MODEL_NAME", "deepseek-chat")
- return _clean_secret(raw) or "deepseek-chat"
- def create_llm_client() -> OpenAI:
- api_key = get_llm_api_key()
- if not api_key:
- raise ValueError(
- "DeepSeek API Key 未配置,请在 /etc/dataops-platform/dataops.env 中设置 DEEPSEEK_API_KEY"
- )
- return OpenAI(api_key=api_key, base_url=get_llm_base_url())
- def chat_completions_create(
- client: OpenAI,
- *,
- messages: list[dict[str, str]],
- temperature: float = 0.7,
- max_tokens: int = 1024,
- use_thinking: bool = False,
- **kwargs: Any,
- ):
- """Create a chat completion; optional DeepSeek thinking mode for complex tasks."""
- create_kwargs: dict[str, Any] = {
- "model": get_llm_model(),
- "messages": messages,
- "stream": False,
- "temperature": temperature,
- "max_tokens": max_tokens,
- **kwargs,
- }
- if use_thinking:
- create_kwargs["reasoning_effort"] = current_app.config.get(
- "LLM_REASONING_EFFORT", "high"
- )
- create_kwargs["extra_body"] = {"thinking": {"type": "enabled"}}
- return client.chat.completions.create(**create_kwargs)
|