Skip to content

Commit b38305b

Browse files
authored
feat(model): Support DeepSeek proxy LLM (#1491)
1 parent 863b540 commit b38305b

File tree

7 files changed

+152
-1
lines changed

7 files changed

+152
-1
lines changed

.env.template

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,11 @@ TONGYI_PROXY_API_KEY={your-tongyi-sk}
219219
# MOONSHOT_API_BASE=https://api.moonshot.cn/v1
220220
# MOONSHOT_API_KEY={your-moonshot-api-key}
221221

222+
## Deepseek Proxyllm, https://platform.deepseek.com/api-docs/
223+
# DEEPSEEK_MODEL_VERSION=deepseek-chat
224+
# DEEPSEEK_API_BASE=https://api.deepseek.com/v1
225+
# DEEPSEEK_API_KEY={your-deepseek-api-key}
226+
222227

223228
#*******************************************************************#
224229
#** SUMMARY_CONFIG **#

README.zh.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,9 @@
167167
- 🔥🔥🔥 [Yi-34B-Chat](https://huggingface.co/01-ai/Yi-34B-Chat)
168168
- [更多开源模型](https://www.yuque.com/eosphoros/dbgpt-docs/iqaaqwriwhp6zslc#qQktR)
169169

170-
- 支持在线代理模型
170+
- 支持在线代理模型
171+
- [x] [DeepSeek.deepseek-chat](https://platform.deepseek.com/api-docs/)
172+
- [x] [Ollama.API](https://github.com/ollama/ollama/blob/main/docs/api.md)
171173
- [x] [月之暗面.Moonshot](https://platform.moonshot.cn/docs/)
172174
- [x] [零一万物.Yi](https://platform.lingyiwanwu.com/docs)
173175
- [x] [OpenAI·ChatGPT](https://api.openai.com/)

dbgpt/_private/config.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,16 @@ def __init__(self) -> None:
128128
os.environ["moonshot_proxyllm_api_base"] = os.getenv(
129129
"MOONSHOT_API_BASE", "https://api.moonshot.cn/v1"
130130
)
131+
# Deepseek proxy
132+
self.deepseek_proxy_api_key = os.getenv("DEEPSEEK_API_KEY")
133+
if self.deepseek_proxy_api_key:
134+
os.environ["deepseek_proxyllm_proxy_api_key"] = self.deepseek_proxy_api_key
135+
os.environ["deepseek_proxyllm_proxyllm_backend"] = os.getenv(
136+
"DEEPSEEK_MODEL_VERSION", "deepseek-chat"
137+
)
138+
os.environ["deepseek_proxyllm_api_base"] = os.getenv(
139+
"DEEPSEEK_API_BASE", "https://api.deepseek.com/v1"
140+
)
131141

132142
self.proxy_server_url = os.getenv("PROXY_SERVER_URL")
133143

dbgpt/configs/model_config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ def get_device() -> str:
7070
# https://platform.moonshot.cn/docs/
7171
"moonshot_proxyllm": "moonshot_proxyllm",
7272
"ollama_proxyllm": "ollama_proxyllm",
73+
# https://platform.deepseek.com/api-docs/
74+
"deepseek_proxyllm": "deepseek_proxyllm",
7375
"llama-2-7b": os.path.join(MODEL_PATH, "Llama-2-7b-chat-hf"),
7476
"llama-2-13b": os.path.join(MODEL_PATH, "Llama-2-13b-chat-hf"),
7577
"llama-2-70b": os.path.join(MODEL_PATH, "Llama-2-70b-chat-hf"),

dbgpt/model/adapter/proxy_adapter.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,31 @@ def get_async_generate_stream_function(self, model, model_path: str):
294294
return moonshot_generate_stream
295295

296296

297+
class DeepseekProxyLLMModelAdapter(ProxyLLMModelAdapter):
298+
"""Deepseek proxy LLM model adapter.
299+
300+
See Also: `Deepseek Documentation <https://platform.deepseek.com/api-docs/>`_
301+
"""
302+
303+
def support_async(self) -> bool:
304+
return True
305+
306+
def do_match(self, lower_model_name_or_path: Optional[str] = None):
307+
return lower_model_name_or_path == "deepseek_proxyllm"
308+
309+
def get_llm_client_class(
310+
self, params: ProxyModelParameters
311+
) -> Type[ProxyLLMClient]:
312+
from dbgpt.model.proxy.llms.deepseek import DeepseekLLMClient
313+
314+
return DeepseekLLMClient
315+
316+
def get_async_generate_stream_function(self, model, model_path: str):
317+
from dbgpt.model.proxy.llms.deepseek import deepseek_generate_stream
318+
319+
return deepseek_generate_stream
320+
321+
297322
register_model_adapter(OpenAIProxyLLMModelAdapter)
298323
register_model_adapter(TongyiProxyLLMModelAdapter)
299324
register_model_adapter(OllamaLLMModelAdapter)
@@ -305,3 +330,4 @@ def get_async_generate_stream_function(self, model, model_path: str):
305330
register_model_adapter(BaichuanProxyLLMModelAdapter)
306331
register_model_adapter(YiProxyLLMModelAdapter)
307332
register_model_adapter(MoonshotProxyLLMModelAdapter)
333+
register_model_adapter(DeepseekProxyLLMModelAdapter)

dbgpt/model/proxy/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ def __lazy_import(name):
1212
"YiLLMClient": "dbgpt.model.proxy.llms.yi",
1313
"MoonshotLLMClient": "dbgpt.model.proxy.llms.moonshot",
1414
"OllamaLLMClient": "dbgpt.model.proxy.llms.ollama",
15+
"DeepseekLLMClient": "dbgpt.model.proxy.llms.deepseek",
1516
}
1617

1718
if name in module_path:
@@ -35,4 +36,5 @@ def __getattr__(name):
3536
"YiLLMClient",
3637
"MoonshotLLMClient",
3738
"OllamaLLMClient",
39+
"DeepseekLLMClient",
3840
]

dbgpt/model/proxy/llms/deepseek.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import os
2+
from typing import TYPE_CHECKING, Any, Dict, Optional, Union, cast
3+
4+
from dbgpt.core import ModelRequest, ModelRequestContext
5+
from dbgpt.model.proxy.llms.proxy_model import ProxyModel
6+
7+
from .chatgpt import OpenAILLMClient
8+
9+
if TYPE_CHECKING:
10+
from httpx._types import ProxiesTypes
11+
from openai import AsyncAzureOpenAI, AsyncOpenAI
12+
13+
ClientType = Union[AsyncAzureOpenAI, AsyncOpenAI]
14+
15+
# 32K model
16+
_DEFAULT_MODEL = "deepseek-chat"
17+
18+
19+
async def deepseek_generate_stream(
20+
model: ProxyModel, tokenizer, params, device, context_len=2048
21+
):
22+
client: DeepseekLLMClient = cast(DeepseekLLMClient, model.proxy_llm_client)
23+
context = ModelRequestContext(stream=True, user_name=params.get("user_name"))
24+
request = ModelRequest.build_request(
25+
client.default_model,
26+
messages=params["messages"],
27+
temperature=params.get("temperature"),
28+
context=context,
29+
max_new_tokens=params.get("max_new_tokens"),
30+
)
31+
async for r in client.generate_stream(request):
32+
yield r
33+
34+
35+
class DeepseekLLMClient(OpenAILLMClient):
36+
"""Deepseek LLM Client.
37+
38+
Deepseek's API is compatible with OpenAI's API, so we inherit from OpenAILLMClient.
39+
40+
API Reference: https://platform.deepseek.com/api-docs/
41+
"""
42+
43+
def __init__(
44+
self,
45+
api_key: Optional[str] = None,
46+
api_base: Optional[str] = None,
47+
api_type: Optional[str] = None,
48+
api_version: Optional[str] = None,
49+
model: Optional[str] = _DEFAULT_MODEL,
50+
proxies: Optional["ProxiesTypes"] = None,
51+
timeout: Optional[int] = 240,
52+
model_alias: Optional[str] = "deepseek_proxyllm",
53+
context_length: Optional[int] = None,
54+
openai_client: Optional["ClientType"] = None,
55+
openai_kwargs: Optional[Dict[str, Any]] = None,
56+
**kwargs,
57+
):
58+
api_base = (
59+
api_base or os.getenv("DEEPSEEK_API_BASE") or "https://api.deepseek.com/v1"
60+
)
61+
api_key = api_key or os.getenv("DEEPSEEK_API_KEY")
62+
model = model or _DEFAULT_MODEL
63+
if not context_length:
64+
if "deepseek-chat" in model:
65+
context_length = 1024 * 32
66+
elif "deepseek-coder" in model:
67+
context_length = 1024 * 16
68+
else:
69+
# 8k
70+
context_length = 1024 * 8
71+
72+
if not api_key:
73+
raise ValueError(
74+
"Deepseek API key is required, please set 'DEEPSEEK_API_KEY' in "
75+
"environment variable or pass it to the client."
76+
)
77+
super().__init__(
78+
api_key=api_key,
79+
api_base=api_base,
80+
api_type=api_type,
81+
api_version=api_version,
82+
model=model,
83+
proxies=proxies,
84+
timeout=timeout,
85+
model_alias=model_alias,
86+
context_length=context_length,
87+
openai_client=openai_client,
88+
openai_kwargs=openai_kwargs,
89+
**kwargs,
90+
)
91+
92+
def check_sdk_version(self, version: str) -> None:
93+
if not version >= "1.0":
94+
raise ValueError(
95+
"Deepseek API requires openai>=1.0, please upgrade it by "
96+
"`pip install --upgrade 'openai>=1.0'`"
97+
)
98+
99+
@property
100+
def default_model(self) -> str:
101+
model = self._model
102+
if not model:
103+
model = _DEFAULT_MODEL
104+
return model

0 commit comments

Comments
 (0)