Skip to content

Commit c0cff4f

Browse files
zxjwznpre-commit-ci[bot]KomoriDev
authored
✨ 自定义模型 API Key 和 prompt (#18)
Co-authored-by: Zaxpris <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: KomoriDev <[email protected]>
1 parent a5f0d29 commit c0cff4f

File tree

5 files changed

+36
-13
lines changed

5 files changed

+36
-13
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ plugins = ["nonebot_plugin_deepseek"]
112112
113113
- `name`: 模型名称(必填)
114114
- `base_url`: 接口地址(默认为:<https://api.deepseek.com>)(自建模型必填)
115+
- `api_key`: API Key(默认使用 `deepseek__api_key`
116+
- `prompt`: 模型预设(默认使用 `deepseek__prompt`
115117
- `max_tokens`: 模型生成补全的最大 token 数
116118
- `deepseek-chat`: 介于 1 到 8192 间的整数,默认使用 4096
117119
- `deepseek-reasoner`: 默认为 4K,最大为 8K

nonebot_plugin_deepseek/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
from .apis import API
3636
from . import hook as hook
3737
from .utils import DeepSeekHandler
38+
from .exception import RequestException
3839
from .extension import CleanDocExtension
3940
from .config import Config, config, model_config
4041

@@ -114,7 +115,7 @@ async def _(is_superuser: bool = Depends(SuperUser())):
114115
if not is_superuser:
115116
return
116117
try:
117-
balances = await API.query_balance()
118+
balances = await API.query_balance(model_config.default_model)
118119

119120
await deepseek.finish(
120121
"".join(
@@ -129,6 +130,8 @@ async def _(is_superuser: bool = Depends(SuperUser())):
129130
)
130131
except ValueError as e:
131132
await deepseek.finish(str(e))
133+
except RequestException as e:
134+
await deepseek.finish(str(e))
132135

133136

134137
@deepseek.assign("model.list")

nonebot_plugin_deepseek/apis/request.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from nonebot.log import logger
33

44
from ..config import config
5+
from ..compat import model_dump
56

67
# from ..function_call import registry
78
from ..exception import RequestException
@@ -11,17 +12,18 @@
1112
class API:
1213
_headers = {
1314
"Accept": "application/json",
14-
"Authorization": f"Bearer {config.api_key}",
1515
}
1616

1717
@classmethod
1818
async def chat(cls, message: list[dict[str, str]], model: str = "deepseek-chat") -> ChatCompletions:
1919
"""普通对话"""
2020
model_config = config.get_model_config(model)
21+
22+
api_key = model_config.api_key or config.api_key
23+
prompt = model_dump(model_config, exclude_none=True).get("prompt", config.prompt)
24+
2125
json = {
22-
"messages": [{"content": config.prompt, "role": "system"}] + message
23-
if config.prompt and model == "deepseek-chat"
24-
else message,
26+
"messages": [{"content": prompt, "role": "system"}] + message if prompt else message,
2527
"model": model,
2628
**model_config.to_dict(),
2729
}
@@ -31,7 +33,7 @@ async def chat(cls, message: list[dict[str, str]], model: str = "deepseek-chat")
3133
async with httpx.AsyncClient() as client:
3234
response = await client.post(
3335
f"{model_config.base_url}/chat/completions",
34-
headers={**cls._headers, "Content-Type": "application/json"},
36+
headers={**cls._headers, "Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
3537
json=json,
3638
timeout=50,
3739
)
@@ -40,12 +42,15 @@ async def chat(cls, message: list[dict[str, str]], model: str = "deepseek-chat")
4042
return ChatCompletions(**response.json())
4143

4244
@classmethod
43-
async def query_balance(cls) -> Balance:
44-
"""查询账号余额"""
45+
async def query_balance(cls, model_name: str) -> Balance:
46+
model_config = config.get_model_config(model_name)
47+
api_key = model_config.api_key or config.api_key
48+
4549
async with httpx.AsyncClient() as client:
4650
response = await client.get(
47-
f"{config.get_model_url('deepseek-chat')}/user/balance",
48-
headers=cls._headers,
51+
f"{model_config.base_url}/user/balance",
52+
headers={**cls._headers, "Authorization": f"Bearer {api_key}"},
4953
)
50-
54+
if response.status_code == 404:
55+
raise RequestException("本地模型不支持查询余额,请更换默认模型")
5156
return Balance(**response.json())

nonebot_plugin_deepseek/config.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ class CustomModel(BaseModel):
4444
"""Model Name"""
4545
base_url: str = "https://api.deepseek.com"
4646
"""Custom base URL for this model (optional)"""
47+
api_key: Optional[str] = None
48+
"""Custom API Key for the model (optional)"""
49+
prompt: Optional[str] = None
50+
"""Custom character preset for the model (optional)"""
4751
max_tokens: int = Field(default=4090, gt=1, lt=8192)
4852
"""
4953
限制一次请求中模型生成 completion 的最大 token 数
@@ -123,7 +127,9 @@ def check_max_token(cls, data: Any) -> Any:
123127
return data
124128

125129
def to_dict(self):
126-
return model_dump(self, exclude_unset=True, exclude_none=True, exclude={"name", "base_url"})
130+
return model_dump(
131+
self, exclude_unset=True, exclude_none=True, exclude={"name", "base_url", "api_key", "prompt"}
132+
)
127133

128134

129135
class ScopedConfig(BaseModel):

tutorial.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,21 @@ ollama run deepseek-r1:7b
3131
配置示例
3232

3333
```bash
34+
deepseek__prompt = "You are a helpful assistant."
3435
deepseek__api_key = "sk-xxx"
3536
deepseek__enable_models='
3637
[
3738
{ "name": "deepseek-chat" },
3839
{ "name": "deepseek-reasoner" },
3940
{
4041
"name": "deepseek-r1:7b",
41-
"base_url": "http://localhost:11434/v1"
42+
"base_url": "http://localhost:11434/v1",
43+
"prompt": None
44+
},
45+
{
46+
"name": "deepseek-r1:free",
47+
"base_url": "https://openrouter.ai/api/v1",
48+
"api_key": "sk-openrouter-xxx"
4249
}
4350
]
4451
'

0 commit comments

Comments
 (0)