321683f863
CI / docker (push) Successful in 3m38s
Add model input defaults (including prompt), workflow model editing, ingress API docs, and fix img2img image upload filenames for signed URLs. Co-authored-by: Cursor <cursoragent@cursor.com>
421 lines
15 KiB
Markdown
421 lines
15 KiB
Markdown
# Luminary
|
||
|
||
OpenAI 兼容 AI 网关,带 Web 管理台。支持多 Provider 出口、入口密钥治理、看板监控与安全管控。控制面自研(Go + SQLite),数据面统一通过入口密钥对外提供 **OpenAI 兼容推理 API** 与 **Replicate 兼容 Predictions API** 两套协议。
|
||
|
||
所有运行参数在 Web 管理台完成配置,**无需手写配置文件**。管理台支持**简体中文、英文**两种界面语言,可在顶栏随时切换。
|
||
|
||
## 界面预览
|
||
|
||
以下为 Web 管理台主要页面(点击可查看原图)。
|
||
|
||
| 登录 | 看板监控 |
|
||
|:---:|:---:|
|
||
|  |  |
|
||
| 默认密码 `admin123`,首次登录后请修改 | Provider 健康、24h 请求/Token 与入口用量排行 |
|
||
|
||
| 出口管理 | 入口管理 |
|
||
|:---:|:---:|
|
||
|  |  |
|
||
| 多 Provider、多 Key 负载均衡与故障转移 | 入口密钥(`sk-lum-*`)、路由规则与预算限流 |
|
||
|
||
| 请求日志 | IP 规则 |
|
||
|:---:|:---:|
|
||
|  |  |
|
||
| 全量请求记录与成本估算 | 精确 / CIDR 白黑名单(admin / proxy 范围) |
|
||
|
||
| 系统设置 | |
|
||
|:---:|:---:|
|
||
|  | |
|
||
| 加密密钥、会话、登录限流、健康检查与重试策略 | |
|
||
|
||
## 功能概览
|
||
|
||
| 模块 | 说明 |
|
||
|------|------|
|
||
| 出口管理 | OpenAI / Anthropic / Azure OpenAI / OpenRouter / Ollama / Custom / ComfyUI,多 Key 加权负载均衡与故障转移 |
|
||
| 入口管理 | OpenAI 兼容 API,入口密钥(`sk-lum-*`),Virtual Key 路由、预算与 RPM/TPM 限流 |
|
||
| 看板监控 | Provider 健康检查、24h 请求/Token 统计、入口用量排行 |
|
||
| 请求日志 | 全量请求记录、按模型定价的成本估算 |
|
||
| IP 安全 | 管理员与推理入口分范围的白名单 / 黑名单(精确、CIDR) |
|
||
| 系统设置 | 加密密钥、信任代理、会话、登录限流、用量刷盘、网关重试 |
|
||
|
||
## 架构
|
||
|
||
```
|
||
客户端 SDK / curl
|
||
→ /v1/*(入口密钥 sk-lum-*)
|
||
├─ OpenAI 兼容推理(chat / embeddings / rerank …)
|
||
└─ Replicate 兼容 Predictions(ComfyUI 工作流)
|
||
→ Luminary Gateway(路由、限流、故障转移)
|
||
→ Provider 出口(多 Key 加权负载均衡)
|
||
↑
|
||
管理台 REST API + Vue UI (:8293)
|
||
↓
|
||
SQLite + 内存缓存
|
||
```
|
||
|
||
## 入口协议
|
||
|
||
Luminary 的核心是 **AI 网关**:客户端用入口密钥(`sk-lum-*`)调用,网关负责鉴权、路由、限流与上游故障转移。对外提供两套兼容协议,Base URL 均为 `http://<host>:8293/v1`:
|
||
|
||
| 协议 | 兼容标准 | 典型场景 |
|
||
|------|----------|----------|
|
||
| **OpenAI 兼容推理 API** | [OpenAI `/v1/*`](https://platform.openai.com/docs/api-reference) | 语言模型对话、向量嵌入、重排序等同步推理 |
|
||
| **Replicate Predictions API** | [Replicate `/v1/predictions`](https://replicate.com/docs/reference/http) | ComfyUI 工作流异步图像生成 |
|
||
|
||
两套协议共用同一入口密钥;具体可调用的 endpoint 取决于「出口管理」中为 Provider 启用的能力分类。
|
||
|
||
## 快速开始(开发)
|
||
|
||
### 依赖
|
||
|
||
- Go 1.25+(见 `go.mod`)
|
||
- Node.js 20+(仅开发/构建前端)
|
||
|
||
依赖镜像(已写入 `Makefile`、`web/.npmrc`,国内网络友好):
|
||
|
||
- Go:`GOPROXY=https://goproxy.cn,direct`
|
||
- npm:`registry=https://registry.npmmirror.com`
|
||
|
||
海外用户可将 `GOPROXY` 改为 `https://proxy.golang.org,direct`,npm 使用默认 registry 即可。
|
||
|
||
### 启动
|
||
|
||
```bash
|
||
cd web && npm install # 安装前端依赖
|
||
|
||
# 终端 1:后端
|
||
go run ./cmd/luminary
|
||
|
||
# 终端 2:前端(Vite 代理 /api、/v1 → :8293)
|
||
cd web && npm run dev
|
||
```
|
||
|
||
访问 http://localhost:5173 ,默认账号 `admin` / `admin123`(**首次登录后请立即修改**)。
|
||
|
||
```bash
|
||
go test ./... # 运行单元测试
|
||
make build # 构建 luminary 二进制(含嵌入前端)
|
||
```
|
||
|
||
## 部署
|
||
|
||
镜像由 Gitea Actions 自动构建并发布到 Container Registry,**无需自行编译**。直接拉取运行即可。
|
||
|
||
```bash
|
||
docker pull git.rc707blog.top/rose_cat707/luminary:latest
|
||
```
|
||
|
||
| Tag | 说明 |
|
||
|-----|------|
|
||
| `latest` | `main` / `master` 分支最新构建 |
|
||
| `sha-xxxxxxx` | 对应 commit 短 SHA |
|
||
| `v1.2.3` | 推送 Git tag `v1.2.3` 时发布 |
|
||
|
||
### docker run
|
||
|
||
```bash
|
||
docker pull git.rc707blog.top/rose_cat707/luminary:latest
|
||
|
||
docker run -d --name luminary \
|
||
--restart unless-stopped \
|
||
-p 8293:8293 \
|
||
-v luminary-data:/data \
|
||
git.rc707blog.top/rose_cat707/luminary:latest
|
||
```
|
||
|
||
或使用项目内 `docker compose up -d`(通过环境变量 `LUMINARY_IMAGE` 指定镜像)。
|
||
|
||
### 本地自行构建
|
||
|
||
```bash
|
||
make docker-build
|
||
# 或
|
||
docker build \
|
||
--build-arg IMAGE_PREFIX=docker.1panel.live/library/ \
|
||
--build-arg GOPROXY=https://goproxy.cn,direct \
|
||
-t luminary:local .
|
||
```
|
||
|
||
**端口(默认)**
|
||
|
||
| 服务 | 端口 | 说明 |
|
||
|------|------|------|
|
||
| 管理 API / Web UI / 推理入口 | 8293 | 管理台与 `/v1/*` 共用同一监听地址 |
|
||
|
||
监听地址可通过启动参数 `-addr` 或环境变量 `LUMINARY_ADDR` 修改。
|
||
|
||
## 数据目录
|
||
|
||
数据默认存储在 `./data/luminary.db`(SQLite),Docker 部署时挂载为 `/data`:
|
||
|
||
```
|
||
data/
|
||
└── luminary.db # Provider、入口密钥、规则、日志、系统设置
|
||
```
|
||
|
||
首次启动自动创建数据库与默认系统设置(含随机加密密钥)。默认管理账号 `admin` / `admin123`(仅当数据库中尚无管理员时创建)。
|
||
|
||
## 入口密钥与协议
|
||
|
||
管理台「入口管理」中的每个密钥属于以下两类之一:
|
||
|
||
| 协议 | 用途 | 可调用的 API |
|
||
|------|------|----------------|
|
||
| **文本(OpenAI)** | LLM / Embedding / Rerank | `/v1/chat/completions`、`/v1/embeddings` 等 |
|
||
| **图片(Replicate)** | ComfyUI 文生图 / 图生图 | `/v1/predictions`、`GET /v1/models`(Replicate 格式) |
|
||
|
||
已有密钥默认归类为**文本**,可在管理台编辑修改为**图片**。
|
||
|
||
同一密钥不能混用两套协议:用文本密钥访问 `/v1/predictions` 或用图片密钥访问 `/v1/chat/completions` 将返回 `403`。
|
||
|
||
## 入口 API(OpenAI 兼容)
|
||
|
||
客户端使用协议为**文本**的入口密钥(`sk-lum-*`)调用,与 OpenAI SDK 兼容。
|
||
|
||
**鉴权**(二选一)
|
||
|
||
```http
|
||
Authorization: Bearer sk-lum-<your-key>
|
||
```
|
||
|
||
```http
|
||
X-Api-Key: sk-lum-<your-key>
|
||
```
|
||
|
||
**Base URL**:`http://<host>:8293/v1`
|
||
|
||
| 方法 | 路径 | 说明 | 状态 |
|
||
|------|------|------|------|
|
||
| `GET` | `/v1/models` | 列出当前文本密钥可用的模型(OpenAI 格式) | 已支持 |
|
||
| `POST` | `/v1/chat/completions` | 对话补全;`stream: true` 时返回 SSE 流式 | 已支持 |
|
||
| `POST` | `/v1/responses` | OpenAI Responses API;`stream: true` 时返回 SSE 流式 | 已支持 |
|
||
| `POST` | `/v1/completions` | 文本补全(Legacy) | 已支持 |
|
||
| `POST` | `/v1/embeddings` | 向量嵌入 | 已支持 |
|
||
| `POST` | `/v1/rerank` | Cohere 兼容重排序 | 已支持 |
|
||
| `POST` | `/v1/audio/speech` | 语音合成 | 预留 |
|
||
| `POST` | `/v1/audio/transcriptions` | 语音转写 | 预留 |
|
||
| `POST` | `/v1/images/generations` | 图像生成 | 预留 |
|
||
|
||
> 实际可访问的接口取决于上游 Provider 在「出口管理」中启用的 endpoint;未启用的接口网关不会转发。
|
||
>
|
||
> **Responses 适配**:若出口仅启用 `chat_completion` 而未启用 `responses`,网关会将 `/v1/responses` 自动转换为 `/v1/chat/completions` 请求,并将响应转回 Responses API 格式(含流式)。
|
||
|
||
**示例:对话补全**
|
||
|
||
```bash
|
||
curl http://localhost:8293/v1/chat/completions \
|
||
-H "Authorization: Bearer sk-lum-..." \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"Hello"}]}'
|
||
```
|
||
|
||
**示例:流式对话**
|
||
|
||
```bash
|
||
curl http://localhost:8293/v1/chat/completions \
|
||
-H "Authorization: Bearer sk-lum-..." \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"model":"gpt-4o-mini","stream":true,"messages":[{"role":"user","content":"Hello"}]}'
|
||
```
|
||
|
||
**示例:Embeddings**
|
||
|
||
```bash
|
||
curl http://localhost:8293/v1/embeddings \
|
||
-H "Authorization: Bearer sk-lum-..." \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"model":"text-embedding-3-small","input":"hello"}'
|
||
```
|
||
|
||
**示例:Rerank(Cohere 兼容)**
|
||
|
||
```bash
|
||
curl http://localhost:8293/v1/rerank \
|
||
-H "Authorization: Bearer sk-lum-..." \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"model":"bge-reranker-v2-m3","query":"What is the capital of France?","documents":["Paris is the capital of France.","Berlin is in Germany."],"top_n":2}'
|
||
```
|
||
|
||
**示例:列出模型**
|
||
|
||
```bash
|
||
curl http://localhost:8293/v1/models \
|
||
-H "Authorization: Bearer sk-lum-..."
|
||
```
|
||
|
||
入口密钥的 Provider / Model 白名单、预算、RPM/TPM 限流与路由规则均在管理台「入口管理」配置;白名单为空表示不限制。
|
||
|
||
## Predictions API(Replicate 兼容)
|
||
|
||
ComfyUI 出口的异步任务接口,需使用协议为**图片**的入口密钥。
|
||
|
||
| 方法 | 路径 | 说明 | 状态 |
|
||
|------|------|------|------|
|
||
| `GET` | `/v1/models` | 列出当前图片密钥可用的工作流模型(Replicate 格式) | 已支持 |
|
||
| `POST` | `/v1/predictions` | 创建异步任务;请求头 `Prefer: wait` 时同步等待完成 | 已支持 |
|
||
| `GET` | `/v1/predictions` | 列出任务(`cursor` 分页) | 已支持 |
|
||
| `GET` | `/v1/predictions/:id` | 查询任务状态与输出 | 已支持 |
|
||
| `POST` | `/v1/predictions/:id/cancel` | 取消进行中的任务 | 已支持 |
|
||
| `GET` | `/v1/predictions/:id/stream` | SSE 流式推送任务进度 | 已支持 |
|
||
|
||
请求体中 `version` 为入口 Model ID,支持 `owner/name` 或短 `name`(与 `GET /v1/models` 返回的 `latest_version.id` / `owner`+`name` 一致);`input` 字段见模型 `openapi_schema.components.schemas.Input`。
|
||
|
||
**示例:列出工作流模型**
|
||
|
||
```bash
|
||
curl http://localhost:8293/v1/models \
|
||
-H "Authorization: Bearer sk-lum-..." # 图片协议密钥
|
||
```
|
||
|
||
**示例:创建 Predictions 任务**
|
||
|
||
```bash
|
||
curl -X POST http://localhost:8293/v1/predictions \
|
||
-H "Authorization: Bearer sk-lum-..." \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"version":"luminary/flux-txt2img","input":{"prompt":"a cat"}}'
|
||
```
|
||
|
||
任务完成后,输出图像通过网关签名的 URL 返回(`/files/:id?exp=&sig=`)。
|
||
|
||
## 使用攻略(简要)
|
||
|
||
### 1. 首次登录
|
||
|
||
1. 打开 `http://<主机>:8293`
|
||
2. 默认账号 `admin` / `admin123`,登录后进入「系统设置」修改密码
|
||
3. 顶栏切换界面语言(中文 / English)
|
||
|
||
### 2. 配置出口
|
||
|
||
1. 「出口管理」→ 新建 Provider,选择类型并填写 Base URL
|
||
2. 添加 API Key,配置加权与故障转移
|
||
3. 启用所需 endpoint 分类(语言模型 / 向量嵌入 / 重排序 / 图像等)
|
||
|
||
### 3. 配置入口
|
||
|
||
1. 「入口管理」→ 新建入口密钥(`sk-lum-*`)
|
||
2. 配置 Provider / Model 白名单、预算与 RPM/TPM 限流
|
||
3. 按需设置 Virtual Key 路由规则
|
||
|
||
### 4. IP 安全
|
||
|
||
1. 「IP 规则」添加白名单 / 黑名单(支持 CIDR)
|
||
2. 规则可按 `admin`(管理台)或 `proxy`(推理入口)范围生效
|
||
|
||
### 5. 日常运维
|
||
|
||
| 操作 | 位置 |
|
||
|------|------|
|
||
| 查看流量与健康 | 看板监控 |
|
||
| 管理 Provider 与 Key | 出口管理 |
|
||
| 管理入口密钥 | 入口管理 |
|
||
| 查看请求与成本 | 请求日志 |
|
||
| 修改运行参数 | 系统设置 |
|
||
|
||
## 系统设置
|
||
|
||
所有运行参数在管理台 **系统设置** 页面维护,存入 SQLite。
|
||
|
||
| 设置项 | 说明 |
|
||
|------|------|
|
||
| 加密密钥 | Provider API Key 加密密钥(首次启动自动生成) |
|
||
| 信任代理 | 信任的反向代理 IP/CIDR;仅此时才读取 `X-Forwarded-For` |
|
||
| 会话 / 登录限制 | 管理员 Session 有效期、登录尝试次数与锁定时长 |
|
||
| 用量刷盘 / 健康检查 | 后台任务间隔 |
|
||
| 网关重试 | 上游故障时的重试次数与退避 |
|
||
|
||
启动参数(非阻塞,仅决定进程如何监听与数据存放位置):
|
||
|
||
| 参数 / 环境变量 | 说明 | 默认 |
|
||
|------|------|------|
|
||
| `-data-dir` / `LUMINARY_DATA` | SQLite 数据目录 | `./data` |
|
||
| `-addr` / `LUMINARY_ADDR` | HTTP 监听地址 | `:8293` |
|
||
|
||
可选环境变量 `LUMINARY_ENCRYPTION_KEY`:仅在首次初始化系统设置时写入加密密钥(一般无需设置,管理台可改)。
|
||
|
||
## 应急恢复(容器内)
|
||
|
||
当 IP 白名单或登录冷却导致无法进入管理台时,可在容器内执行恢复工具(已内置在镜像中):
|
||
|
||
```bash
|
||
# 一键:重置密码为 admin123、清空 IP 规则与会话,并重启进程(清除内存中的登录冷却)
|
||
docker exec luminary luminary-recover.sh --all
|
||
|
||
# 指定新密码
|
||
docker exec luminary luminary-recover.sh --all --password 'your-new-password'
|
||
|
||
# 分项执行(不重启)
|
||
docker exec luminary luminary-recover.sh \
|
||
--reset-password --clear-ip --clear-sessions --password 'your-new-password'
|
||
|
||
# 仅清除登录冷却(需重启进程;登录冷却存在内存中)
|
||
docker exec luminary luminary-recover.sh --restart
|
||
```
|
||
|
||
本地非容器环境:
|
||
|
||
```bash
|
||
chmod +x scripts/luminary-recover.sh
|
||
./scripts/luminary-recover.sh --all
|
||
# 或
|
||
go run ./cmd/luminary-recover --all
|
||
```
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `--all` | 重置密码 + 清空 IP 规则 + 清空会话 + 重启进程 |
|
||
| `--reset-password` | 重置管理员密码 |
|
||
| `--clear-ip` | 删除全部 IP 规则 |
|
||
| `--clear-sessions` | 删除全部管理员 Session |
|
||
| `--restart` | 向 PID 1 发送 SIGTERM,由容器重启策略拉起新进程 |
|
||
| `--password` | 新密码(默认 `admin123`) |
|
||
| `--username` | 管理员用户名(默认 `admin`) |
|
||
| `-data-dir` / `LUMINARY_DATA` | 数据目录(默认 `./data`,容器内为 `/data`) |
|
||
|
||
## 命令行
|
||
|
||
| 命令 | 说明 |
|
||
|------|------|
|
||
| `luminary` | 启动网关(默认 `-data-dir ./data`、`-addr :8293`) |
|
||
| `luminary-recover` | 应急恢复 CLI(容器内 `luminary-recover.sh` 封装) |
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
cmd/luminary/ # 主服务入口
|
||
cmd/luminary-recover/ # 应急恢复 CLI
|
||
internal/
|
||
gateway/ # 路由、故障转移、健康检查
|
||
handler/ # 管理 API、推理代理、静态资源
|
||
provider/ # 各 Provider 客户端与适配
|
||
store/ # SQLite 与内存缓存
|
||
auth/ # 密码、登录限流
|
||
middleware/ # IP 过滤、客户端 IP
|
||
monitor/ # 监控统计
|
||
pricing/ # 成本估算
|
||
web/ # Vue 3 管理台
|
||
src/i18n/ # 多语言资源
|
||
src/views/ # 页面
|
||
docs/
|
||
image/ # README 界面截图
|
||
UI-DESIGN-SYSTEM.md
|
||
.gitea/workflows/ # Gitea Actions CI
|
||
```
|
||
|
||
## CI / 镜像发布
|
||
|
||
推送 `main` / `master` 或 tag `v*` 时,Gitea Actions 构建多架构镜像并推送到 Registry。工作流与 Dockerfile 约定见 [.gitea/README.md](.gitea/README.md);act_runner 部署参考见 [.gitea/act-runner/](.gitea/act-runner/)。
|
||
|
||
**一次性配置**(仓库 Settings → Actions):
|
||
|
||
| 类型 | 名称 | 说明 |
|
||
|------|------|------|
|
||
| Secret | `REGISTRY_TOKEN` | Gitea PAT,需 `write:package` 权限 |
|
||
| Variable | `REGISTRY` | 公网 Gitea 域名,如 `git.rc707blog.top` |
|
||
|
||
## 许可
|
||
|
||
[Luminary 采用 MIT License](LICENSE).
|