Spaces:
Sleeping
Sleeping
Upload deepseek.py
Browse files
llm_services/providers/deepseek.py
CHANGED
|
@@ -1,14 +1,20 @@
|
|
| 1 |
-
"""DeepSeek
|
| 2 |
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
|
|
|
|
|
|
|
|
|
| 6 |
"""
|
| 7 |
from __future__ import annotations
|
|
|
|
| 8 |
import os
|
| 9 |
from openai import OpenAI
|
| 10 |
|
| 11 |
_ALLOWED_THINKING = {"enabled", "disabled"}
|
|
|
|
|
|
|
| 12 |
|
| 13 |
|
| 14 |
def _config():
|
|
@@ -18,6 +24,21 @@ def _config():
|
|
| 18 |
return mode
|
| 19 |
|
| 20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
def create_client():
|
| 22 |
key = os.environ["DEEPSEEK_API_KEY"]
|
| 23 |
return OpenAI(
|
|
@@ -31,23 +52,43 @@ def create_client():
|
|
| 31 |
def complete(messages, *, model=None, max_completion_tokens=1200):
|
| 32 |
requested = model or os.getenv("DEEPSEEK_MODEL", "deepseek-flash")
|
| 33 |
mode = _config()
|
| 34 |
-
|
| 35 |
-
#
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
if not resp.choices:
|
| 44 |
raise RuntimeError("DeepSeek returned no choices")
|
|
|
|
| 45 |
choice = resp.choices[0]
|
| 46 |
usage = resp.usage
|
| 47 |
prompt_details = getattr(usage, "prompt_tokens_details", None) if usage else None
|
| 48 |
-
|
|
|
|
| 49 |
if cached is None and prompt_details is not None:
|
| 50 |
cached = getattr(prompt_details, "cached_tokens", None)
|
|
|
|
| 51 |
return {
|
| 52 |
"answer": choice.message.content or "",
|
| 53 |
"provider": "deepseek",
|
|
@@ -55,10 +96,18 @@ def complete(messages, *, model=None, max_completion_tokens=1200):
|
|
| 55 |
"model_returned": resp.model,
|
| 56 |
"finish_reason": choice.finish_reason,
|
| 57 |
"thinking_mode": mode,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
"usage": {
|
| 59 |
"input_tokens": usage.prompt_tokens if usage else None,
|
| 60 |
"output_tokens": usage.completion_tokens if usage else None,
|
| 61 |
"total_tokens": usage.total_tokens if usage else None,
|
| 62 |
"cached_input_tokens": cached,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
},
|
| 64 |
}
|
|
|
|
| 1 |
+
"""DeepSeek research-only adapter for WaterScope-AI.
|
| 2 |
|
| 3 |
+
Preserves the previous DeepSeek integration, HF/Azure routing, user prompts,
|
| 4 |
+
full paper evidence, and scientific answer word ceiling. In thinking mode,
|
| 5 |
+
DeepSeek `max_tokens` counts *both* reasoning and final answer tokens; the
|
| 6 |
+
research endpoint's 2-tokens-per-word allowance is only for final text.
|
| 7 |
+
This adapter adds an independent reasoning headroom so thinking responses
|
| 8 |
+
are not prematurely cut off. The setting is a ceiling, not a token target.
|
| 9 |
"""
|
| 10 |
from __future__ import annotations
|
| 11 |
+
|
| 12 |
import os
|
| 13 |
from openai import OpenAI
|
| 14 |
|
| 15 |
_ALLOWED_THINKING = {"enabled", "disabled"}
|
| 16 |
+
_ALLOWED_EFFORT = {"low", "high", "max"}
|
| 17 |
+
_DEFAULT_REASONING_RESERVE = 32768
|
| 18 |
|
| 19 |
|
| 20 |
def _config():
|
|
|
|
| 24 |
return mode
|
| 25 |
|
| 26 |
|
| 27 |
+
def _reasoning_config():
|
| 28 |
+
effort = os.getenv("DEEPSEEK_REASONING_EFFORT", "high").strip().lower()
|
| 29 |
+
if effort not in _ALLOWED_EFFORT:
|
| 30 |
+
raise ValueError("DEEPSEEK_REASONING_EFFORT must be low, high or max")
|
| 31 |
+
|
| 32 |
+
raw = os.getenv("DEEPSEEK_REASONING_RESERVE_TOKENS", str(_DEFAULT_REASONING_RESERVE))
|
| 33 |
+
try:
|
| 34 |
+
reserve = int(raw)
|
| 35 |
+
except (ValueError, TypeError) as exc:
|
| 36 |
+
raise ValueError("DEEPSEEK_REASONING_RESERVE_TOKENS must be an integer") from exc
|
| 37 |
+
if not 0 <= reserve <= 100000:
|
| 38 |
+
raise ValueError("DEEPSEEK_REASONING_RESERVE_TOKENS must be 0-100000")
|
| 39 |
+
return effort, reserve
|
| 40 |
+
|
| 41 |
+
|
| 42 |
def create_client():
|
| 43 |
key = os.environ["DEEPSEEK_API_KEY"]
|
| 44 |
return OpenAI(
|
|
|
|
| 52 |
def complete(messages, *, model=None, max_completion_tokens=1200):
|
| 53 |
requested = model or os.getenv("DEEPSEEK_MODEL", "deepseek-flash")
|
| 54 |
mode = _config()
|
| 55 |
+
|
| 56 |
+
# This budget is passed in from the research endpoint, where it is sized
|
| 57 |
+
# for the final visible answer (300 words per selected paper).
|
| 58 |
+
final_text_budget = int(max_completion_tokens)
|
| 59 |
+
if final_text_budget < 1:
|
| 60 |
+
raise ValueError("max_completion_tokens must be >= 1")
|
| 61 |
+
|
| 62 |
+
effort = None
|
| 63 |
+
reserve = 0
|
| 64 |
+
if mode == "enabled":
|
| 65 |
+
effort, reserve = _reasoning_config()
|
| 66 |
+
|
| 67 |
+
# DeepSeek Chat Completions `max_tokens` includes reasoning and final text.
|
| 68 |
+
# Do not impose the original final-text-only budget on thinking mode.
|
| 69 |
+
api_max_tokens = final_text_budget + reserve
|
| 70 |
+
params = {
|
| 71 |
+
"model": requested,
|
| 72 |
+
"messages": messages,
|
| 73 |
+
"stream": False,
|
| 74 |
+
"max_tokens": api_max_tokens,
|
| 75 |
+
"extra_body": {"thinking": {"type": mode}},
|
| 76 |
+
}
|
| 77 |
+
if effort is not None:
|
| 78 |
+
params["reasoning_effort"] = effort
|
| 79 |
+
|
| 80 |
+
resp = create_client().chat.completions.create(**params)
|
| 81 |
if not resp.choices:
|
| 82 |
raise RuntimeError("DeepSeek returned no choices")
|
| 83 |
+
|
| 84 |
choice = resp.choices[0]
|
| 85 |
usage = resp.usage
|
| 86 |
prompt_details = getattr(usage, "prompt_tokens_details", None) if usage else None
|
| 87 |
+
completion_details = getattr(usage, "completion_tokens_details", None) if usage else None
|
| 88 |
+
cached = getattr(usage, "prompt_cache_hit_tokens", None) if usage else None
|
| 89 |
if cached is None and prompt_details is not None:
|
| 90 |
cached = getattr(prompt_details, "cached_tokens", None)
|
| 91 |
+
|
| 92 |
return {
|
| 93 |
"answer": choice.message.content or "",
|
| 94 |
"provider": "deepseek",
|
|
|
|
| 96 |
"model_returned": resp.model,
|
| 97 |
"finish_reason": choice.finish_reason,
|
| 98 |
"thinking_mode": mode,
|
| 99 |
+
"thinking_effort": effort,
|
| 100 |
+
"final_text_token_allowance": final_text_budget,
|
| 101 |
+
"reasoning_token_reserve": reserve,
|
| 102 |
+
"max_tokens_sent": api_max_tokens,
|
| 103 |
"usage": {
|
| 104 |
"input_tokens": usage.prompt_tokens if usage else None,
|
| 105 |
"output_tokens": usage.completion_tokens if usage else None,
|
| 106 |
"total_tokens": usage.total_tokens if usage else None,
|
| 107 |
"cached_input_tokens": cached,
|
| 108 |
+
"reasoning_tokens": (
|
| 109 |
+
getattr(completion_details, "reasoning_tokens", None)
|
| 110 |
+
if completion_details is not None else None
|
| 111 |
+
),
|
| 112 |
},
|
| 113 |
}
|