diff --git a/.env.example b/.env.example index 401785d..57b8648 100644 --- a/.env.example +++ b/.env.example @@ -1,8 +1,13 @@ # DS2API 环境变量配置模板 # 复制此文件为 .env 并根据需要修改 +# 最后更新:2026-02 -# ===== 服务配置 ===== -# 服务端口 +# =============================================================== +# 核心配置 +# =============================================================== + +# ----- 服务配置 ----- +# 服务端口(默认 5001) PORT=5001 # 服务监听地址 @@ -11,38 +16,59 @@ HOST=0.0.0.0 # 日志级别 (DEBUG, INFO, WARNING, ERROR) LOG_LEVEL=INFO -# ===== 配置来源(以下三种方式选一种)===== -# 方式1: JSON 字符串 +# =============================================================== +# 数据配置(三选一) +# =============================================================== + +# 方式1: JSON 字符串(适合简单配置) # DS2API_CONFIG_JSON={"keys":["your-api-key"],"accounts":[{"email":"user@example.com","password":"xxx","token":""}]} -# 方式2: Base64 编码的 JSON(推荐用于 Vercel,避免特殊字符问题) +# 方式2: Base64 编码的 JSON(推荐用于 Vercel,避免特殊字符转义问题) +# 生成方式: echo '{"keys":["your-api-key"],"accounts":[...]}' | base64 # DS2API_CONFIG_JSON=eyJrZXlzIjpbInlvdXItYXBpLWtleSJdLCJhY2NvdW50cyI6W3siZW1haWwiOiJ1c2VyQGV4YW1wbGUuY29tIiwicGFzc3dvcmQiOiJ4eHgiLCJ0b2tlbiI6IiJ9XX0= -# 方式3: 配置文件路径(默认为 config.json) +# 方式3: 配置文件路径(本地开发推荐) # DS2API_CONFIG_PATH=config.json -# ===== 可选:自定义路径 ===== + +# =============================================================== +# 管理界面配置 +# =============================================================== + +# Admin API 密钥(Vercel 部署必填!) +# 用于保护 WebUI 管理界面,首次访问 /admin 时需要输入此密钥登录 +DS2API_ADMIN_KEY=your-admin-secret-key + +# JWT Token 过期时间(秒,默认 86400 = 24小时) +# DS2API_SESSION_EXPIRE=86400 + + +# =============================================================== +# Vercel 集成(可选) +# =============================================================== + +# Vercel API Token +# 获取方式: https://vercel.com/account/tokens +# VERCEL_TOKEN=your-vercel-token + +# Vercel Project ID +# 获取方式: Vercel 控制台 -> 项目设置 -> General -> Project ID +# VERCEL_PROJECT_ID=prj_xxxxxxxxxxxx + +# Vercel Team ID(个人项目无需填写,团队项目才需要) +# VERCEL_TEAM_ID= + + +# =============================================================== +# 高级配置(可选) +# =============================================================== + # Tokenizer 目录(留空使用项目根目录) # DS2API_TOKENIZER_DIR= # 模板目录 # DS2API_TEMPLATES_DIR=templates -# WASM 文件路径 +# WASM 文件路径(PoW 计算用) # DS2API_WASM_PATH=sha3_wasm_bg.7b9ca65ddd.wasm - -# ===== Admin 管理界面 ===== -# Admin API 密钥(Vercel 部署必填!保护 WebUI 管理界面) -# 首次同步时会自动保存到 Vercel 环境变量 -DS2API_ADMIN_KEY=your-admin-secret-key - -# ===== Vercel 集成(可选,用于一键同步部署)===== -# Vercel API Token(从 https://vercel.com/account/tokens 获取) -# VERCEL_TOKEN=your-vercel-token - -# Vercel Project ID(在项目设置中找) -# VERCEL_PROJECT_ID=prj_xxxxxxxxxxxx - -# Vercel Team ID(个人项目无需填写) -# VERCEL_TEAM_ID= diff --git a/API.md b/API.md index f3fed0a..a5e73db 100644 --- a/API.md +++ b/API.md @@ -1,12 +1,39 @@ -# API 文档 +# DS2API 接口文档 本文档详细介绍 DS2API 提供的所有 API 端点。 +--- + +## 目录 + +- [基础信息](#基础信息) +- [OpenAI 兼容接口](#openai-兼容接口) + - [获取模型列表](#获取模型列表) + - [对话补全](#对话补全) +- [Claude 兼容接口](#claude-兼容接口) + - [Claude 模型列表](#claude-模型列表) + - [Claude 消息接口](#claude-消息接口) + - [Token 计数](#token-计数) +- [管理接口](#管理接口) + - [登录认证](#登录认证) + - [配置管理](#配置管理) + - [账号管理](#账号管理) + - [Vercel 同步](#vercel-同步) +- [错误处理](#错误处理) +- [使用示例](#使用示例) + +--- + ## 基础信息 -- **Base URL**: `https://your-domain.com` 或 `http://localhost:5001` -- **认证方式**: Bearer Token -- **响应格式**: JSON +| 项目 | 说明 | +|-----|------| +| **Base URL** | `https://your-domain.com` 或 `http://localhost:5001` | +| **OpenAI 认证** | `Authorization: Bearer ` | +| **Claude 认证** | `x-api-key: ` | +| **响应格式** | JSON | + +--- ## OpenAI 兼容接口 @@ -16,7 +43,7 @@ GET /v1/models ``` -**响应示例**: +**响应示例**: ```json { @@ -40,41 +67,52 @@ Authorization: Bearer your-api-key Content-Type: application/json ``` -**请求参数**: +**请求参数**: | 参数 | 类型 | 必填 | 说明 | -|-----|------|------|------| -| `model` | string | ✅ | 模型名称 | +|-----|------|:----:|------| +| `model` | string | ✅ | 模型名称(见下表) | | `messages` | array | ✅ | 对话消息列表 | | `stream` | boolean | ❌ | 是否流式输出,默认 `false` | -| `temperature` | number | ❌ | 温度参数,0-2 | +| `temperature` | number | ❌ | 温度参数,范围 0-2 | | `max_tokens` | number | ❌ | 最大输出 token 数 | -| `tools` | array | ❌ | 工具定义列表(OpenAI 格式) | +| `tools` | array | ❌ | 工具定义列表(Function Calling) | | `tool_choice` | string | ❌ | 工具选择策略 | -**支持的模型**: +**支持的模型**: -| 模型 | thinking_enabled | search_enabled | 说明 | -|-----|-----------------|----------------|------| +| 模型 | 深度思考 | 联网搜索 | 说明 | +|-----|:--------:|:--------:|------| | `deepseek-chat` | ❌ | ❌ | 标准对话 | -| `deepseek-reasoner` | ✅ | ❌ | 深度思考(R1 推理) | -| `deepseek-chat-search` | ❌ | ✅ | 联网搜索 | -| `deepseek-reasoner-search` | ✅ | ✅ | 深度思考 + 联网搜索 | +| `deepseek-reasoner` | ✅ | ❌ | 推理模式,输出思考过程 | +| `deepseek-chat-search` | ❌ | ✅ | 联网搜索增强 | +| `deepseek-reasoner-search` | ✅ | ✅ | 推理 + 联网搜索 | -**请求示例**: +**基础请求示例**: + +```json +{ + "model": "deepseek-chat", + "messages": [ + {"role": "system", "content": "你是一个有帮助的助手。"}, + {"role": "user", "content": "你好"} + ] +} +``` + +**流式请求示例**: ```json { "model": "deepseek-reasoner-search", "messages": [ - {"role": "system", "content": "你是一个有帮助的助手。"}, {"role": "user", "content": "今天有什么重要新闻?"} ], "stream": true } ``` -**流式响应格式** (`stream: true`): +**流式响应格式** (`stream: true`): ``` data: {"id":"...","object":"chat.completion.chunk","choices":[{"delta":{"role":"assistant"},"index":0}]} @@ -88,13 +126,15 @@ data: {"id":"...","object":"chat.completion.chunk","choices":[{"index":0,"finish data: [DONE] ``` -**非流式响应格式** (`stream: false`): +> **注意**:推理模式会输出 `reasoning_content` 字段,包含模型的思考过程。 + +**非流式响应格式** (`stream: false`): ```json { "id": "chatcmpl-xxx", "object": "chat.completion", - "created": 1699000000, + "created": 1738400000, "model": "deepseek-reasoner", "choices": [{ "index": 0, @@ -108,12 +148,17 @@ data: [DONE] "usage": { "prompt_tokens": 10, "completion_tokens": 50, - "total_tokens": 60 + "total_tokens": 60, + "completion_tokens_details": { + "reasoning_tokens": 20 + } } } ``` -**工具调用请求示例**: +#### 工具调用 (Function Calling) + +**请求示例**: ```json { @@ -136,7 +181,7 @@ data: [DONE] } ``` -**工具调用响应格式**: +**响应示例**: ```json { @@ -163,18 +208,154 @@ data: [DONE] --- +## Claude 兼容接口 + +### Claude 模型列表 + +```http +GET /anthropic/v1/models +``` + +**响应示例**: + +```json +{ + "object": "list", + "data": [ + {"id": "claude-sonnet-4-20250514", "object": "model", "owned_by": "anthropic"}, + {"id": "claude-sonnet-4-20250514-fast", "object": "model", "owned_by": "anthropic"}, + {"id": "claude-sonnet-4-20250514-slow", "object": "model", "owned_by": "anthropic"} + ] +} +``` + +**模型映射说明**: + +| Claude 模型 | 实际调用 | 说明 | +|------------|---------|------| +| `claude-sonnet-4-20250514` | deepseek-chat | 标准模式 | +| `claude-sonnet-4-20250514-fast` | deepseek-chat | 快速模式 | +| `claude-sonnet-4-20250514-slow` | deepseek-reasoner | 推理模式(深度思考) | + +--- + +### Claude 消息接口 + +```http +POST /anthropic/v1/messages +x-api-key: your-api-key +Content-Type: application/json +anthropic-version: 2023-06-01 +``` + +**请求参数**: + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|:----:|------| +| `model` | string | ✅ | 模型名称 | +| `max_tokens` | integer | ✅ | 最大输出 token | +| `messages` | array | ✅ | 对话消息 | +| `stream` | boolean | ❌ | 是否流式,默认 `false` | +| `system` | string | ❌ | 系统提示词 | +| `temperature` | number | ❌ | 温度参数 | + +**请求示例**: + +```json +{ + "model": "claude-sonnet-4-20250514", + "max_tokens": 1024, + "messages": [ + {"role": "user", "content": "你好,请介绍一下你自己"} + ] +} +``` + +**非流式响应**: + +```json +{ + "id": "msg_xxx", + "type": "message", + "role": "assistant", + "content": [{ + "type": "text", + "text": "你好!我是一个 AI 助手..." + }], + "model": "claude-sonnet-4-20250514", + "stop_reason": "end_turn", + "usage": { + "input_tokens": 10, + "output_tokens": 50 + } +} +``` + +**流式响应** (SSE): + +``` +event: message_start +data: {"type":"message_start","message":{"id":"msg_xxx","type":"message","role":"assistant","model":"claude-sonnet-4-20250514"}} + +event: content_block_start +data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}} + +event: content_block_delta +data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"你好"}} + +event: content_block_stop +data: {"type":"content_block_stop","index":0} + +event: message_delta +data: {"type":"message_delta","delta":{"stop_reason":"end_turn"},"usage":{"output_tokens":50}} + +event: message_stop +data: {"type":"message_stop"} +``` + +--- + +### Token 计数 + +```http +POST /anthropic/v1/messages/count_tokens +x-api-key: your-api-key +Content-Type: application/json +``` + +**请求示例**: + +```json +{ + "model": "claude-sonnet-4-20250514", + "messages": [ + {"role": "user", "content": "你好"} + ] +} +``` + +**响应示例**: + +```json +{ + "input_tokens": 5 +} +``` + +--- + ## 管理接口 -所有管理接口需要在请求头中携带 `Authorization: Bearer `。 +所有管理接口(除登录外)需要在请求头携带 JWT Token:`Authorization: Bearer ` -### 登录 +### 登录认证 ```http POST /admin/login Content-Type: application/json ``` -**请求体**: +**请求体**: ```json { @@ -182,26 +363,30 @@ Content-Type: application/json } ``` -**响应**: +**响应**: ```json { "success": true, - "token": "jwt-token", + "token": "jwt-token-string", "expires_in": 86400 } ``` +> Token 有效期默认 24 小时。 + --- -### 获取配置 +### 配置管理 + +#### 获取配置 ```http GET /admin/config Authorization: Bearer ``` -**响应**: +**响应**: ```json { @@ -216,9 +401,28 @@ Authorization: Bearer } ``` +#### 更新配置 + +```http +POST /admin/config +Authorization: Bearer +Content-Type: application/json +``` + +**请求体**: + +```json +{ + "keys": ["new-api-key"], + "accounts": [...] +} +``` + --- -### 添加账号 +### 账号管理 + +#### 添加账号 ```http POST /admin/accounts @@ -226,7 +430,7 @@ Authorization: Bearer Content-Type: application/json ``` -**请求体**: +**请求体**: ```json { @@ -235,9 +439,7 @@ Content-Type: application/json } ``` ---- - -### 批量导入账号 +#### 批量导入账号 ```http POST /admin/accounts/batch @@ -245,7 +447,7 @@ Authorization: Bearer Content-Type: application/json ``` -**请求体**: +**请求体**: ```json { @@ -256,9 +458,7 @@ Content-Type: application/json } ``` ---- - -### 测试账号 +#### 测试单个账号 ```http POST /admin/accounts/test @@ -266,7 +466,7 @@ Authorization: Bearer Content-Type: application/json ``` -**请求体**: +**请求体**: ```json { @@ -274,25 +474,21 @@ Content-Type: application/json } ``` ---- - -### 批量测试所有账号 +#### 测试所有账号 ```http POST /admin/accounts/test-all Authorization: Bearer ``` ---- - -### 获取队列状态 +#### 获取队列状态 ```http GET /admin/queue/status Authorization: Bearer ``` -**响应**: +**响应**: ```json { @@ -303,7 +499,7 @@ Authorization: Bearer { "email": "user@example.com", "status": "healthy", - "last_used": "2026-02-01T06:00:00Z" + "last_used": "2026-02-01T12:00:00Z" } ] } @@ -311,7 +507,7 @@ Authorization: Bearer --- -### 同步到 Vercel +### Vercel 同步 ```http POST /admin/vercel/sync @@ -319,7 +515,7 @@ Authorization: Bearer Content-Type: application/json ``` -**请求体**: +**请求体**(首次同步需要): ```json { @@ -328,6 +524,17 @@ Content-Type: application/json } ``` +> 首次同步成功后,凭证会被保存,后续同步可不传。 + +**响应**: + +```json +{ + "success": true, + "message": "配置已同步到 Vercel" +} +``` + --- ## 错误处理 @@ -344,10 +551,10 @@ Content-Type: application/json } ``` -**常见错误码**: +**常见错误码**: | HTTP 状态码 | 错误类型 | 说明 | -|------------|---------|------| +|:----------:|---------|------| | 400 | `invalid_request_error` | 请求参数错误 | | 401 | `authentication_error` | API Key 无效或未提供 | | 403 | `permission_denied` | 权限不足 | @@ -359,30 +566,58 @@ Content-Type: application/json ## 使用示例 -### Python +### Python (OpenAI SDK) ```python -import openai +from openai import OpenAI -client = openai.OpenAI( +client = OpenAI( api_key="your-api-key", base_url="https://your-domain.com/v1" ) +# 普通对话 response = client.chat.completions.create( + model="deepseek-chat", + messages=[{"role": "user", "content": "你好"}] +) +print(response.choices[0].message.content) + +# 流式 + 推理模式 +for chunk in client.chat.completions.create( model="deepseek-reasoner", - messages=[{"role": "user", "content": "你好"}], + messages=[{"role": "user", "content": "解释相对论"}], stream=True +): + delta = chunk.choices[0].delta + if hasattr(delta, 'reasoning_content') and delta.reasoning_content: + print(f"[思考] {delta.reasoning_content}", end="") + if delta.content: + print(delta.content, end="") +``` + +### Python (Anthropic SDK) + +```python +import anthropic + +client = anthropic.Anthropic( + api_key="your-api-key", + base_url="https://your-domain.com/anthropic" ) -for chunk in response: - if chunk.choices[0].delta.content: - print(chunk.choices[0].delta.content, end="") +response = client.messages.create( + model="claude-sonnet-4-20250514", + max_tokens=1024, + messages=[{"role": "user", "content": "你好"}] +) +print(response.content[0].text) ``` ### cURL ```bash +# OpenAI 格式 curl https://your-domain.com/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-api-key" \ @@ -390,11 +625,23 @@ curl https://your-domain.com/v1/chat/completions \ "model": "deepseek-chat", "messages": [{"role": "user", "content": "你好"}] }' + +# Claude 格式 +curl https://your-domain.com/anthropic/v1/messages \ + -H "Content-Type: application/json" \ + -H "x-api-key: your-api-key" \ + -H "anthropic-version: 2023-06-01" \ + -d '{ + "model": "claude-sonnet-4-20250514", + "max_tokens": 1024, + "messages": [{"role": "user", "content": "你好"}] + }' ``` -### JavaScript +### JavaScript / TypeScript ```javascript +// OpenAI 格式 - 流式请求 const response = await fetch('https://your-domain.com/v1/chat/completions', { method: 'POST', headers: { @@ -414,6 +661,39 @@ const decoder = new TextDecoder(); while (true) { const { done, value } = await reader.read(); if (done) break; - console.log(decoder.decode(value)); + + const chunk = decoder.decode(value); + const lines = chunk.split('\n').filter(line => line.startsWith('data: ')); + + for (const line of lines) { + const data = line.slice(6); + if (data === '[DONE]') continue; + + const json = JSON.parse(data); + const content = json.choices?.[0]?.delta?.content; + if (content) process.stdout.write(content); + } +} +``` + +### Node.js (OpenAI SDK) + +```javascript +import OpenAI from 'openai'; + +const client = new OpenAI({ + apiKey: 'your-api-key', + baseURL: 'https://your-domain.com/v1' +}); + +const stream = await client.chat.completions.create({ + model: 'deepseek-reasoner', + messages: [{ role: 'user', content: '解释黑洞' }], + stream: true +}); + +for await (const chunk of stream) { + const content = chunk.choices[0]?.delta?.content; + if (content) process.stdout.write(content); } ``` diff --git a/DEPLOY.md b/DEPLOY.md new file mode 100644 index 0000000..386752e --- /dev/null +++ b/DEPLOY.md @@ -0,0 +1,319 @@ +# DS2API 部署指南 + +本文档详细介绍 DS2API 的各种部署方式。 + +--- + +## 目录 + +- [Vercel 部署(推荐)](#vercel-部署推荐) +- [本地开发](#本地开发) +- [生产环境部署](#生产环境部署) +- [常见问题](#常见问题) + +--- + +## Vercel 部署(推荐) + +### 一键部署 + +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FCJackHwang%2Fds2api&env=DS2API_ADMIN_KEY&envDescription=管理面板访问密码(必填)&envLink=https%3A%2F%2Fgithub.com%2FCJackHwang%2Fds2api%23环境变量&project-name=ds2api&repository-name=ds2api) + +### 部署步骤 + +1. **点击部署按钮** + - 登录你的 GitHub 账号 + - 授权 Vercel 访问 + +2. **设置环境变量** + - `DS2API_ADMIN_KEY`: 管理面板密码(**必填**) + +3. **等待部署完成** + - Vercel 会自动构建并部署项目 + - 部署完成后获得访问 URL + +4. **配置账号** + - 访问 `https://your-project.vercel.app/admin` + - 输入管理密码登录 + - 添加 DeepSeek 账号 + - 设置自定义 API Key + +5. **同步配置** + - 点击「同步到 Vercel」按钮 + - 首次需要输入 Vercel Token 和 Project ID + - 同步成功后配置会持久化 + +### 获取 Vercel 凭证 + +**Vercel Token**: +1. 访问 https://vercel.com/account/tokens +2. 点击 "Create Token" +3. 设置名称和有效期 +4. 复制生成的 Token + +**Project ID**: +1. 进入 Vercel 项目页面 +2. 点击 Settings -> General +3. 复制 "Project ID" + +--- + +## 本地开发 + +### 环境要求 + +- Python 3.9+ +- Node.js 18+ (WebUI 开发) +- pip + +### 快速开始 + +```bash +# 1. 克隆项目 +git clone https://github.com/CJackHwang/ds2api.git +cd ds2api + +# 2. 安装 Python 依赖 +pip install -r requirements.txt + +# 3. 配置账号 +cp config.example.json config.json +# 编辑 config.json,填入 DeepSeek 账号信息 + +# 4. 启动服务 +python dev.py +``` + +### 配置文件示例 + +```json +{ + "keys": ["my-api-key-1", "my-api-key-2"], + "accounts": [ + { + "email": "your-email@example.com", + "password": "your-password", + "token": "" + }, + { + "mobile": "12345678901", + "password": "your-password", + "token": "" + } + ] +} +``` + +**说明**: +- `keys`: 自定义 API Key,用于调用本服务的接口 +- `accounts`: DeepSeek 网页版账号 + - 支持 `email` 或 `mobile` 登录 + - `token` 留空,系统会自动获取 + +### WebUI 开发 + +```bash +# 进入 WebUI 目录 +cd webui + +# 安装依赖 +npm install + +# 启动开发服务器 +npm run dev +``` + +WebUI 开发服务器会启动在 `http://localhost:5173`,并自动代理 API 请求到后端 `http://localhost:5001`。 + +--- + +## 生产环境部署 + +### 使用 systemd (Linux) + +1. **创建服务文件** + +```bash +sudo nano /etc/systemd/system/ds2api.service +``` + +```ini +[Unit] +Description=DS2API Service +After=network.target + +[Service] +Type=simple +User=www-data +WorkingDirectory=/opt/ds2api +ExecStart=/usr/bin/python3 app.py +Restart=always +RestartSec=10 +Environment=PORT=5001 +Environment=DS2API_ADMIN_KEY=your-admin-key + +[Install] +WantedBy=multi-user.target +``` + +2. **启动服务** + +```bash +sudo systemctl daemon-reload +sudo systemctl enable ds2api +sudo systemctl start ds2api +``` + +3. **查看状态** + +```bash +sudo systemctl status ds2api +sudo journalctl -u ds2api -f +``` + +### Nginx 反向代理 + +```nginx +server { + listen 80; + server_name api.yourdomain.com; + + # SSL 配置(推荐) + # listen 443 ssl http2; + # ssl_certificate /path/to/cert.pem; + # ssl_certificate_key /path/to/key.pem; + + location / { + proxy_pass http://127.0.0.1:5001; + proxy_http_version 1.1; + + # 关闭缓冲,支持 SSE + proxy_buffering off; + proxy_cache off; + + # 连接设置 + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # SSE 超时设置 + proxy_read_timeout 300s; + proxy_send_timeout 300s; + + # 分块传输 + chunked_transfer_encoding on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 120; + } +} +``` + +### Docker 部署(可选) + +```dockerfile +# Dockerfile +FROM python:3.11-slim + +WORKDIR /app +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + +EXPOSE 5001 +CMD ["python", "app.py"] +``` + +```bash +# 构建镜像 +docker build -t ds2api . + +# 运行容器 +docker run -d \ + --name ds2api \ + -p 5001:5001 \ + -e DS2API_ADMIN_KEY=your-admin-key \ + -e DS2API_CONFIG_JSON='{"keys":["api-key"],"accounts":[...]}' \ + ds2api +``` + +### Docker Compose + +```yaml +# docker-compose.yml +version: '3.8' + +services: + ds2api: + build: . + ports: + - "5001:5001" + environment: + - DS2API_ADMIN_KEY=${DS2API_ADMIN_KEY} + - DS2API_CONFIG_JSON=${DS2API_CONFIG_JSON} + restart: unless-stopped +``` + +--- + +## 常见问题 + +### Q: 账号验证失败怎么办? + +**A**: 检查以下几点: +1. 确认 DeepSeek 账号密码正确 +2. 检查账号是否被封禁或需要验证 +3. 尝试在浏览器中手动登录一次 +4. 查看日志获取详细错误信息 + +### Q: 流式响应断开怎么办? + +**A**: +1. 检查 Nginx/反向代理配置,确保关闭了 `proxy_buffering` +2. 增加 `proxy_read_timeout` 超时时间 +3. 检查网络连接稳定性 + +### Q: Vercel 部署后配置丢失? + +**A**: +1. 确保点击了「同步到 Vercel」按钮 +2. 检查 Vercel Token 是否正确且未过期 +3. 确认 Project ID 正确 + +### Q: 如何更新到新版本? + +**本地部署**: +```bash +git pull origin main +pip install -r requirements.txt +# 重启服务 +``` + +**Vercel 部署**: +- 项目会自动从 GitHub 同步更新 +- 或在 Vercel 控制台手动触发重新部署 + +### Q: 如何查看日志? + +**本地开发**: +```bash +# 设置日志级别 +export LOG_LEVEL=DEBUG +python dev.py +``` + +**Vercel**: +- 访问 Vercel 控制台 -> 项目 -> Deployments -> Logs + +### Q: Token 计数不准确? + +**A**: DS2API 使用估算方式计算 token 数量(字符数 / 4),与 OpenAI 官方的 tokenizer 可能有差异,仅供参考。 + +--- + +## 获取帮助 + +- **GitHub Issues**: https://github.com/CJackHwang/ds2api/issues +- **文档**: https://github.com/CJackHwang/ds2api diff --git a/README.MD b/README.MD index ea35082..300d956 100644 --- a/README.MD +++ b/README.MD @@ -3,78 +3,100 @@ [![License](https://img.shields.io/github/license/CJackHwang/ds2api.svg)](LICENSE) ![Stars](https://img.shields.io/github/stars/CJackHwang/ds2api.svg) ![Forks](https://img.shields.io/github/forks/CJackHwang/ds2api.svg) +[![Version](https://img.shields.io/badge/version-1.6.11-blue.svg)](version.txt) -将 DeepSeek 网页版转换为 OpenAI 兼容 API,支持多账号轮询、自动 Token 刷新、可视化管理界面。 +将 DeepSeek 免费对话版转换为 **OpenAI & Claude 兼容 API**,支持多账号轮询、自动 Token 刷新、可视化管理界面。 ## ✨ 特性 -- 🚀 **OpenAI 兼容** - 完全兼容 OpenAI API 格式,无缝接入现有应用 -- 🔄 **多账号轮询** - Round-Robin 负载均衡,支持高并发 +- 🔄 **双协议兼容** - 同时支持 OpenAI 和 Claude (Anthropic) API 格式 +- 🚀 **多账号轮询** - Round-Robin 负载均衡,支持高并发场景 - 🔐 **Token 自动刷新** - 过期自动重新登录,无需手动维护 -- 🌐 **WebUI 管理** - 可视化添加账号、测试 API、同步 Vercel -- 🔍 **联网搜索** - 支持 DeepSeek 搜索增强模式 -- 🧠 **深度思考** - 支持 R1 推理模式 -- ☁️ **Vercel 部署** - 一键部署,无需服务器 +- 🌐 **WebUI 管理** - 可视化添加账号、测试 API、同步 Vercel 配置 +- 🔍 **联网搜索** - 支持 DeepSeek 原生搜索增强模式 +- 🧠 **深度思考** - 支持推理模式,输出思考过程 +- 🛠️ **工具调用** - 兼容 OpenAI Function Calling 格式 +- ☁️ **Vercel 一键部署** - 无需服务器,快速上线 ## 📋 模型支持 +### OpenAI 兼容接口 (`/v1/chat/completions`) + +| 模型 | 深度思考 | 联网搜索 | 说明 | +|-----|:--------:|:--------:|------| +| `deepseek-chat` | ❌ | ❌ | 标准对话模式 | +| `deepseek-reasoner` | ✅ | ❌ | 推理模式(输出思考过程) | +| `deepseek-chat-search` | ❌ | ✅ | 联网搜索模式 | +| `deepseek-reasoner-search` | ✅ | ✅ | 推理 + 联网搜索 | + +### Claude 兼容接口 (`/anthropic/v1/messages`) + | 模型 | 说明 | |-----|------| -| `deepseek-chat` | DeepSeek V3.2 非推理模式 | -| `deepseek-reasoner` | DeepSeek V3.2 推理模式(深度思考) | -| `deepseek-chat-search` | 非推理 + 联网搜索 | -| `deepseek-reasoner-search` | 推理 + 联网搜索 | +| `claude-sonnet-4-20250514` | 映射到 deepseek-chat(标准模式) | +| `claude-sonnet-4-20250514-fast` | 映射到 deepseek-chat(快速模式) | +| `claude-sonnet-4-20250514-slow` | 映射到 deepseek-reasoner(推理模式) | + +> **提示**:Claude 接口实际调用的是 DeepSeek,响应格式会自动转换为 Anthropic 标准格式。 ## 🚀 快速开始 -### Vercel 部署(推荐) +### 方式一:Vercel 部署(推荐) [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FCJackHwang%2Fds2api&env=DS2API_ADMIN_KEY&envDescription=管理面板访问密码(必填)&envLink=https%3A%2F%2Fgithub.com%2FCJackHwang%2Fds2api%23环境变量&project-name=ds2api&repository-name=ds2api) -1. 点击上方按钮,填写管理密码 `DS2API_ADMIN_KEY` +1. 点击上方按钮,设置管理密码 `DS2API_ADMIN_KEY` 2. 部署完成后访问 `/admin` 管理界面 -3. 添加 DeepSeek 账号和 API Key +3. 添加 DeepSeek 账号和自定义 API Key 4. 点击「同步到 Vercel」保存配置 -> **首次同步会自动验证账号、保存 Token 和 Vercel 凭证,后续操作无需再输入。** +> **首次同步会自动验证账号并保存 Token,后续操作无需重复输入凭证。** -### 本地运行 +### 方式二:本地开发 ```bash -# 克隆仓库 +# 1. 克隆仓库 git clone https://github.com/CJackHwang/ds2api.git cd ds2api -# 安装依赖 +# 2. 安装依赖 pip install -r requirements.txt -# 配置 +# 3. 配置账号 cp config.example.json config.json -# 编辑 config.json 添加账号 +# 编辑 config.json,添加 DeepSeek 账号信息 -# 运行 +# 4. 启动服务 python dev.py ``` +服务启动后访问 `http://localhost:5001` + ## ⚙️ 配置说明 ### 环境变量 -| 变量 | 说明 | 是否必填 | -|-----|------|---------| -| `DS2API_ADMIN_KEY` | WebUI 管理密码 | Vercel 必填 | -| `DS2API_CONFIG_JSON` | 配置 JSON(支持 Base64) | 可选 | -| `VERCEL_TOKEN` | Vercel API Token(用于快捷同步) | 可选 | +| 变量 | 说明 | 必填 | +|-----|------|:----:| +| `DS2API_ADMIN_KEY` | 管理面板密码 | Vercel 必填 | +| `DS2API_CONFIG_JSON` | 配置 JSON 或 Base64 编码 | 可选 | +| `VERCEL_TOKEN` | Vercel API Token(用于同步) | 可选 | | `VERCEL_PROJECT_ID` | Vercel 项目 ID | 可选 | +| `PORT` | 服务端口(默认 5001) | 可选 | -### 配置文件格式 +### 配置文件格式 (`config.json`) ```json { - "keys": ["your-api-key"], + "keys": ["your-api-key-1", "your-api-key-2"], "accounts": [ { - "email": "your@email.com", + "email": "user@example.com", + "password": "your-password", + "token": "" + }, + { + "mobile": "12345678901", "password": "your-password", "token": "" } @@ -82,41 +104,79 @@ python dev.py } ``` -## 📡 API 接口 +> **说明**: +> - `keys`: 自定义的 API 密钥,用于调用本服务 +> - `accounts`: DeepSeek 网页版账号,支持邮箱或手机号登录 +> - `token`: 留空即可,系统会自动获取并刷新 -完整的 API 文档请参阅 **[API.md](API.md)**。 +## 📡 API 使用 + +完整 API 文档请参阅 **[API.md](API.md)** ### 快速示例 -**模型列表**: -``` -GET /v1/models +**获取模型列表**: +```bash +curl http://localhost:5001/v1/models ``` -**对话补全**: +**OpenAI 格式调用**: ```bash -curl https://your-domain.com/v1/chat/completions \ +curl http://localhost:5001/v1/chat/completions \ -H "Authorization: Bearer your-api-key" \ -H "Content-Type: application/json" \ - -d '{"model":"deepseek-chat","messages":[{"role":"user","content":"你好"}]}' + -d '{ + "model": "deepseek-chat", + "messages": [{"role": "user", "content": "你好"}], + "stream": true + }' ``` -### 管理接口 +**Claude 格式调用**: +```bash +curl http://localhost:5001/anthropic/v1/messages \ + -H "x-api-key: your-api-key" \ + -H "Content-Type: application/json" \ + -H "anthropic-version: 2023-06-01" \ + -d '{ + "model": "claude-sonnet-4-20250514", + "max_tokens": 1024, + "messages": [{"role": "user", "content": "你好"}] + }' +``` -| 接口 | 说明 | -|-----|------| -| `GET /admin` | 管理界面 | -| `GET /admin/config` | 获取配置 | -| `POST /admin/accounts/test` | 测试单个账号 | -| `POST /admin/accounts/test-all` | 批量测试账号 | -| `POST /admin/vercel/sync` | 同步到 Vercel | +### Python SDK 使用 -## 🔧 Nginx 反代配置 +```python +from openai import OpenAI + +client = OpenAI( + api_key="your-api-key", + base_url="http://localhost:5001/v1" +) + +response = client.chat.completions.create( + model="deepseek-reasoner", + messages=[{"role": "user", "content": "请解释量子纠缠"}], + stream=True +) + +for chunk in response: + if chunk.choices[0].delta.content: + print(chunk.choices[0].delta.content, end="") +``` + +## 🔧 部署配置 + +### Nginx 反向代理 ```nginx location / { proxy_pass http://localhost:5001; + proxy_http_version 1.1; + proxy_set_header Connection ""; proxy_buffering off; + proxy_cache off; chunked_transfer_encoding on; tcp_nopush on; tcp_nodelay on; @@ -124,18 +184,31 @@ location / { } ``` +### Docker 部署(可选) + +```bash +# 使用环境变量配置 +docker run -d \ + -p 5001:5001 \ + -e DS2API_ADMIN_KEY=your-admin-key \ + -e DS2API_CONFIG_JSON='{"keys":["api-key"],"accounts":[...]}' \ + ds2api +``` + ## ⚠️ 免责声明 -**逆向 API 不稳定,建议前往 [DeepSeek 官方](https://platform.deepseek.com/) 付费使用 API。** +**本项目基于逆向工程实现,服务稳定性无法保证。** -**本项目仅供学习交流,禁止商用或对外提供服务,风险自担!** +- 仅供学习研究使用,**禁止商业用途或对外提供服务** +- 建议正式项目使用 [DeepSeek 官方 API](https://platform.deepseek.com/) +- 使用本项目产生的任何风险由用户自行承担 ## 📜 鸣谢 -本项目基于以下开源项目并进行了大量修改: +本项目基于以下开源项目: -- [iidamie/deepseek2api](https://github.com/iidamie/deepseek2api) - 二开版本 -- [LLM-Red-Team/deepseek-free-api](https://github.com/LLM-Red-Team/deepseek-free-api) - 早期原始项目 +- [iidamie/deepseek2api](https://github.com/iidamie/deepseek2api) +- [LLM-Red-Team/deepseek-free-api](https://github.com/LLM-Red-Team/deepseek-free-api) ## 📊 Star History diff --git a/config.example.json b/config.example.json index 6af6454..7614e77 100644 --- a/config.example.json +++ b/config.example.json @@ -1,23 +1,28 @@ { + "_comment": "DS2API 配置文件示例 - 复制为 config.json 使用", + "_doc": "详细文档: https://github.com/CJackHwang/ds2api", "keys": [ "your-api-key-1", "your-api-key-2" ], "accounts": [ { + "_comment": "邮箱登录方式", "email": "example1@example.com", "password": "your-password-1", "token": "" }, { + "_comment": "邮箱登录方式 - 账号2", "email": "example2@example.com", "password": "your-password-2", "token": "" }, { + "_comment": "手机号登录方式(中国大陆)", "mobile": "12345678901", "password": "your-password-3", "token": "" } ] -} +} \ No newline at end of file