DeepSeeLite (DSL)
August 29, 2026 · View on GitHub
DeepSeeLite (DSL) 是面向轻量部署的视觉编排库和本地网关,为 DeepSeek API 增加图片 理解能力。它可以独立用于 Python/API 集成,也可以作为 DSH 的 DSV 网关;不需要安装 完整 DeepSee 才能使用 DSL。
DSL 通过独立的 PyPI 包名 deepseelite 发布,共享 deepsee import 包、
deepsee-server 命令和 ~/.config/deepsee 配置。完整 DeepSee 则通过 seedeep
发布;两个发行版不能安装在同一个 Python 环境中。
为 DeepSeek 官方 API 提供可插拔的视觉处理层,让 DeepSeek 获得多模态能力:
一次 ask_with_image() 调用,完成"视觉模型看图 → DeepSeek 推理回答"。
安装 DSL
pip install "deepseelite[server]"
deepsee-server
首次启动会显示 public key 和 admin key。普通 API/DSV 请求使用 public key;admin key 只用于管理端点,请勿交给客户端。
安装后可以直接调用 Python API:
from deepsee import ask_with_image
answer = ask_with_image("photo.jpg", "这张图里有什么?")
print(answer)
配置和启动
网关运行时的主事实来源是 ~/.config/deepsee/upstream.json 管理配置;也可以使用
deepsee.toml 或环境变量。最小的环境变量配置如下:
export DEEPSEEK_API_KEY='<DeepSeek API key>'
export VISION_API_KEY='<vision provider API key>'
export VISION_BASE_URL='https://dashscope.aliyuncs.com/compatible-mode/v1'
export VISION_MODEL='qwen-vl-max'
deepsee-server
完整配置格式、后端选择、鉴权和多协议端点见下方章节。
可选:接入 DSH
已经安装 DSH Web 的用户,可以按下面流程让 DSH 使用 DSL 的 DSV 网关;DSH 只保存 网关 public key,不接触 DeepSeek 或视觉 provider 的密钥。
1. 安装 DSH 适配层
在另一个终端运行:
curl -fsSL https://raw.githubusercontent.com/windyslime/DeepSeeLite/main/scripts/install-dsh-dsv.sh | bash
看到 Configure DeepSee connection automatically? [Y/n/c] 时:
- 直接按回车或输入
Y:选择自动配置;需要时粘贴刚才复制的 public key。 - 输入
n:只安装,暂时不配置连接。 - 输入
c:取消,不改动 DSH。
2. 重启 DSH 并发一张图片
在运行 DSH Web 的终端按 Ctrl+C 停止它,再用原来的启动命令重新启动并刷新浏览器。
然后在聊天中上传一张图片并提问。看到可折叠的“识图”行即表示连接生效。
3. 检查连接
curl -fsSL https://raw.githubusercontent.com/windyslime/DeepSeeLite/main/scripts/install-dsh-dsv.sh \
| bash -s -- --verify
看到 DeepSee gateway reachable 即表示 DSH 能找到 DSL 网关。若提示网关不可达,确认
安装 DSL 时启动的 deepsee-server 仍在运行后重试。
没有交互终端时,先设置 public key,再使用自动配置;只想安装时使用仅安装模式:
export DEEPSEE_DSV_API_KEY='<DSV public key>'
curl -fsSL https://raw.githubusercontent.com/windyslime/DeepSeeLite/main/scripts/install-dsh-dsv.sh \
| bash -s -- --configure
curl -fsSL https://raw.githubusercontent.com/windyslime/DeepSeeLite/main/scripts/install-dsh-dsv.sh \
| bash -s -- --no-configure
完整排错见 docs/DSH-DSV-INSTALL.zh.md。安装器的技术约束、
凭证处理和发布检查见 CONTRIBUTING.md。
与完整 DeepSee 的关系
以下命令安装的是功能更完整的 DeepSee 正式发布包,不是 DSL:
pip install seedeep
PyPI 上的
deepsee已被 2014 年的无关项目占用,本包发布名为seedeep; import 包名仍是deepsee。启动本地服务时用pip install "seedeep[server]"。
seedeep 与 deepseelite 提供相同的 deepsee import 包和 deepsee-server 命令,
不能安装在同一个 Python 环境中;切换版本时先卸载另一个。
配置
网关运行时的主事实来源是 ~/.config/deepsee/upstream.json 管理配置;浏览器管理端点
只写入这个文件,并且只返回脱敏状态。DSH 仅保存网关地址和 DSV public key,不接触
DeepSeek 或视觉 provider 的密钥。TOML 和环境变量仍然支持库调用、容器部署和启动时
覆盖,其中环境变量优先级最高,适合运维注入秘密。
配置文件 deepsee.toml(放在当前目录或 ~/.config/deepsee/),也可以只用环境变量
(DeepSee_DEEPSEEK_API_KEY 等)。${ENV} 可引用环境变量:
[deepseek]
api_key = "${DEEPSEEK_API_KEY}"
[vision]
backend = "openai_compatible" # openai_compatible | anthropic | gemini
api_key = "${VISION_API_KEY}"
base_url = "https://dashscope.aliyuncs.com/compatible-mode/v1"
model = "qwen-vl-max"
# Optional per-mode models. Omitted modes fall back to vision.model.
[vision.models]
auto = "qwen-vl-max"
ui = "qwen-vl-ui"
general = "qwen-vl-general"
vision.model 是旧配置格式保留的默认模型;vision.models.auto、
vision.models.ui 和 vision.models.general 可以分别覆盖 auto、ui、
general 三种视觉模式。只配置其中一部分时,未配置的模式继续回落到
vision.model,因此旧配置无需迁移。auto 会判断图片是界面截图还是普通图片,
ui 强制输出结构化界面分析,general 强制输出通用图片描述。
除 TOML 外,也可以使用环境变量覆盖每个模式。标准名称是
VISION_MODEL_AUTO、VISION_MODEL_UI 和 VISION_MODEL_GENERAL;带有
DeepSee_ 前缀的形式以及更短的 VISION_AUTO_MODEL、VISION_UI_MODEL、
VISION_GENERAL_MODEL 别名也受支持。环境变量优先于 TOML,旧的
VISION_MODEL 仍然作为三个模式的共同回退。切换视觉后端时,必须显式提供新后端的
VISION_API_KEY 和 VISION_MODEL,或同时提供三个模式变量。
用环境变量覆盖 VISION_BACKEND 切换后端时,TOML 中的 base_url / api_key
/ model 不会沿用(它们属于旧后端:base_url 指向旧主机,key 属于旧供应商,
会被发给错误的主机/供应商)。base_url 回落到新后端的官方默认主机 ——
Anthropic 和 Gemini 有默认主机;OpenAI-compatible 没有默认值,必须显式设置
VISION_BASE_URL。api_key 与 model 必须由环境变量显式提供,否则报错。
环境变量与 TOML 中字面量 backend 相同的 VISION_BACKEND 不算切换,
TOML 配置原样保留(自定义代理 / 审计 / 数据驻留场景)。但 TOML backend
若写成 ${ENV} 插值(如 backend = "${VISION_BACKEND}"),一律视为切换:
base_url 回落默认,且 api_key / model 必须使用标准环境变量
VISION_API_KEY / VISION_MODEL 显式提供 —— TOML 中的自定义 ${ENV}
占位符不会生效,旧变量可安全删除。
支持的后端
- openai_compatible: Qwen-VL、GPT-4o、GLM-4V、Moonshot 等任意 OpenAI 兼容服务
- anthropic: Claude 系列(原生 API)
- gemini: Google Gemini(原生 API)
流式输出
for chunk in ask_with_image("photo.jpg", "讲个故事", stream=True):
print(chunk, end="", flush=True)
异步 API
所有同步接口都有对应的 async 版本,签名一致:
import asyncio
from deepsee import ask_with_image_async
async def main():
# 非流式
answer = await ask_with_image_async("photo.jpg", "这张图里有什么?")
print(answer)
# 流式(async 迭代器)
async for chunk in ask_with_image_async("photo.jpg", "讲个故事", stream=True):
print(chunk, end="", flush=True)
asyncio.run(main())
另有 ask_async(纯文本)与 describe_image_async(仅视觉分析)。
错误语义与同步接口一致;图片处理(含 SSRF 防护)复用同一套同步管线。
本地网关
安装 server 依赖后启动网关:
pip install "deepseelite[server]"
deepsee-server
网关默认启用入站鉴权。首次启动会创建一组 public/admin key,明文只在该次
启动输出,磁盘中的 ~/.config/deepsee/api-keys.json 只保存 SHA-256 摘要。
普通推理和模型列表使用 public key:
curl http://127.0.0.1:8712/v1/models \
-H "Authorization: Bearer <public-key>"
/admin/* 管理端点使用独立的 admin key,通过
X-DeepSee-Admin-Key: <admin-key> 传递。需要补发密钥时运行
deepsee-server --create-recovery-keys;旧 key 保持有效,可通过管理 API 撤销。
临时本机开发可以显式关闭鉴权,但仅允许 loopback 地址:
deepsee-server --no-auth --host 127.0.0.1
默认每个身份每 60 秒最多 60 个推理请求,全局最多 8 个并发推理请求,并发队列
最多等待 2 秒。可用 DeepSee_RATE_LIMIT_REQUESTS、
DeepSee_RATE_LIMIT_WINDOW、DeepSee_MAX_CONCURRENT_REQUESTS 和
DeepSee_REQUEST_QUEUE_TIMEOUT 覆盖。计数只在当前进程内共享;多 worker 或多
实例部署还需要在反向代理层配置共享限速。
多协议端点
DSV 公开编排端点
POST /v1/dsv 是 DeepSee 对外提供的视觉编排/输出协议。客户端只提交图片、消息、
DeepSeek 模型和工具 schema;DeepSee 在内部调用配置的 OpenAI-compatible 视觉 API,
再编排 DeepSeek 推理。视觉 provider 的 api_key 不属于 DSV 请求体,也不会返回给
客户端。DSV v1 当前要求 [vision].backend = "openai_compatible"。
请求中的图片可以使用 DSV 原生 base64 形状,工具结果继续使用 OpenAI-compatible 的
role: "tool" 消息回传:
{
"model": "deepseek-chat",
"stream": true,
"messages": [{
"role": "user",
"content": [
{"type": "text", "text": "这张图里有什么?"},
{"type": "image", "source": {
"type": "base64",
"media_type": "image/png",
"data": "<BASE64>"
}}
]
}],
"tools": [],
"vision": {"mode": "auto", "include_analysis": true}
}
vision.mode 可选 auto、ui 或 general,省略时使用 auto。网关会按所选模式
调用对应的 vision.models.<mode>;DSV 响应的 `vision.model$ 元数据会报告实际使用的
模型,便于 \text{DSH} 展开“识图”结果时显示来源。
视觉模式可以与手动切分独立组合。示例使用 \text{UI} 识别、4 \times 4 网格、120% 区域尺寸和允许重叠:
$``json "vision": { "mode": "ui", "include_analysis": true, "split": {"mode": "manual", "rows": 4, "columns": 4, "scale": 120, "overlap": true} }
DSV 的 `vision.tiles` 按行优先排列;失败项包含 `row`、`column` 和 `status: "error"`,
客户端可在对应网格中央显示红色“识别失败”。OpenAI 兼容接口使用
`X-DeepSee-Vision-Split-Mode`、`X-DeepSee-Vision-Split-Grid`、
`X-DeepSee-Vision-Split-Scale` 和 `X-DeepSee-Vision-Split-Overlap` 请求头,
并从 `X-DeepSee-Vision-Tiles` 响应头读取状态。
SSE 流首先发送 `response.created`、`vision.started` 和完整的
`vision.completed`,随后发送 `reasoning.delta`、`answer.delta` 或
`tool_call.delta`。工具调用结束时发送 `response.requires_action`;调用方执行自己
的工具后,把结果作为下一次 DSV 请求的 `role: "tool"` 消息提交。DeepSee 不执行
调用方的工具。非流式响应将 `vision`、`answer`、`reasoning`、`tool_calls` 和
`usage` 保持为独立字段。
服务同时暴露三种协议形状的聊天端点。视觉分析可以作为响应元数据返回,
供 GUI 像展开思考过程一样点击查看(字段语义 = "模型看到了什么"):
- `POST /v1/chat/completions` — OpenAI 兼容;仅当请求包含
`X-DeepSee-Include-Vision: 1` 时,有图的非流式响应带
`choices[0].message.vision_analysis`,流式响应以独立前置 chunk 发出
`choices[0].delta.vision_analysis`(不含 `content`),随后是上游响应 chunk;
- `POST /v1/messages` — Anthropic messages 形状;非流式响应顶层
`vision_analysis`;流式响应在 `message_start` 后发
`{"type": "vision_analysis", "vision": ...}` 事件;
- `POST /v1beta/models/{model}:generateContent` — Gemini 形状;非流式
响应 `parts` 首位是 `{"text": ..., "vision": true}`;流式响应以独立前置
chunk 发出该 part。
三种端点都支持 `stream` 参数(流式/非流式),图片输入按各自协议形状
(data URL / base64 source / inline_data / http URL),统一受 SSRF 防护与
字节上限约束;`file://` 与本地路径一律拒绝。
OpenAI、Anthropic 和 Gemini 三种聊天协议都读取同一个
`X-DeepSee-Vision-Mode: auto|ui|general` 请求头;未提供时默认 `auto`。只想调用视觉
后端而不经过 DeepSeek 推理时,可使用 `POST /analyze`,请求体为
`{"image": "<data-url-or-http-url>", "question": "...", "mode": "general"}`;
该端点的 `mode` 默认是 `general`,响应返回 `{"kind": "description", "text": "..."}`。
**示例**(以 base64 图片 + 流式为例):
```bash
# OpenAI 兼容
curl -N http://127.0.0.1:8712/v1/chat/completions \
-H "Authorization: Bearer <public-key>" \
-H "X-DeepSee-Include-Vision: 1" \
-H "Content-Type: application/json" -d '{
"stream": true,
"messages": [{"role": "user", "content": [
{"type": "text", "text": "这张图里有什么?"},
{"type": "image_url", "image_url": {"url": "data:image/png;base64,<BASE64>"}}
]}]
}'
# 响应:首个 chunk 为 {"choices":[{"delta":{"vision_analysis":"..."}}]},
# 之后 chunk 为 {"choices":[{"delta":{"content":"..."}}]},最后 data: [DONE]
# Anthropic messages
curl -N http://127.0.0.1:8712/v1/messages \
-H "Authorization: Bearer <public-key>" \
-H "Content-Type: application/json" -d '{
"model": "claude-3-5-sonnet",
"max_tokens": 1024,
"stream": true,
"messages": [{"role": "user", "content": [
{"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": "<BASE64>"}},
{"type": "text", "text": "这张图里有什么?"}
]}]
}'
# 响应:message_start → {"type":"vision_analysis","vision":"..."} → content_block_delta(text) → message_stop
# Gemini generateContent
curl -N http://127.0.0.1:8712/v1beta/models/gemini-2.0-flash:generateContent \
-H "Authorization: Bearer <public-key>" \
-H "Content-Type: application/json" -d '{
"stream": true,
"contents": [{"parts": [
{"inline_data": {"mime_type": "image/png", "data": "<BASE64>"}},
{"text": "这张图里有什么?"}
]}]
}'
# 响应:首个 chunk 的 parts 为 [{"text":"...","vision":true}],后续 chunk 只带回答文本 part
安全限制
网关对模型、推理和分析端点强制 public key,对 /admin/* 强制 admin key;
直接导入 ASGI app 但未配置鉴权时 fail closed,只有 /health 保持公开。速率和
并发保护覆盖完整流式响应生命周期,客户端取消或上游异常后会释放并发名额。
图片加载对所有服务化图片入口统一生效(/v1/dsv 的 image.source/image_url、
/v1/chat/completions 的 image_url、/v1/messages 的 source.url/base64、
/v1beta/models/{model}:generateContent 的 file_data.file_uri/inline_data、
/analyze):
- SSRF 防护:http(s) URL 的主机(含每一跳重定向目标)解析到私网、loopback、
link-local、保留或特殊用途地址(如
127.0.0.1、169.254.169.254)时拒绝下载。 校验通过后,TCP 连接固定到已校验的 IP(域名只解析一次),消除 DNS rebinding TOCTOU;TLS 仍按原始域名校验证书。下载不读环境代理(trust_env=False), 防止代理绕过本地校验。RFC 6052 NAT64 前缀(64:ff9b::/96、64:ff9b:1::/48) 显式拒绝;部署网络若使用其他自定义 NAT64 前缀,需自行扩展deepsee/pipeline/image.py的_NAT64_NETWORKS; - 本地路径:服务端只接受
data:与 http(s) URL,file://与本地路径一律拒绝 (CLI 本地调用不受影响); - 资源上限:原始图片字节上限 20 MiB、解码像素上限约 1670 万(4096x4096),
超限在下载/解码前拒绝;下载请求
Accept-Encoding: identity并拒绝压缩响应, 字节上限按原始字节流式累计(扩容前检查),防止大响应与解压炸弹耗尽内存; - 请求体上限:服务端请求体超过 32 MiB 返回 413,请求体流式读取,
无
Content-Length的 chunked 请求同样受限; - 推理成本上限:默认最多 100 条消息/内容、4 张图片、20 万文本字符;
未指定输出长度时使用 4096 tokens,单次最多 8192 tokens。可通过
DeepSee_MAX_MESSAGES、DeepSee_MAX_IMAGES、DeepSee_MAX_TEXT_CHARS、DeepSee_DEFAULT_MAX_OUTPUT_TOKENS和DeepSee_MAX_OUTPUT_TOKENS覆盖; - 流式超时:DeepSeek 流式响应的 HTTP 帧间超时 120 秒(完全静默的上游
120 秒后报错),另有总时长上限 300 秒(
deepsee/composer/deepseek.py的_STREAM_TOTAL_TIMEOUT)—— 持续发送 SSE keepalive 却永不[DONE]的上游会触发总时长上限,超时抛ComposeError(服务端以 error chunk 通知)。 注意同步接口是检查点软上限(每次读到数据后检查截止时间,完全静默时 可能再等待一次 120 秒帧间超时);异步接口是响应体迭代阶段的硬上限 (响应头返回后每帧等待剩余时间;连接、响应头等待与重试不计入 300 秒); - 流式资源释放:库的流式接口(
stream=True)返回的迭代器需完整消费或 调用close()/aclose()(建议contextlib.closing/aclosing)以释放 底层连接;服务端流式端点已用aclosing保证取消/断开时释放; - 环境代理:库发起的上游请求不读环境代理(
trust_env=False)。SOCKS 代理 (如ALL_PROXY=socks5://)在未安装socksio时会直接 ImportError,且代理 会把含 API key 的请求转发到第三方。依赖代理访问公网 API 的环境需直连或 自行配置传输层。
已知限制与后续工作
以下问题已确认但不在当前版本修复,列为后续工作:
- CI: 仓库尚无 CI(GitHub Actions)。建议配置 pytest 在 Python 3.10-3.12 矩阵上运行,并开启依赖安全扫描;
- 分支保护: 主分支保护属 GitHub 仓库设置,需人工开启(建议要求 PR 评审 与 CI 通过后才能合并)。
许可证
MIT