Keep a minimal dist/index.html in version control so go:embed succeeds when CI checks out without a frontend build; ignore other dist artifacts. Co-authored-by: Cursor <cursoragent@cursor.com>
Luminary AI Gateway
Go + Vue 3 AI 网关,参考 Bifrost 设计,支持多 Provider 出口、入口密钥治理、看板监控与安全管控。SQLite 持久化 + 内存缓存,单二进制部署。
功能
- 出口管理:OpenAI / Anthropic / Azure OpenAI / OpenRouter / Ollama / Custom,多 Key 加权负载均衡与故障转移,接口 Path 覆盖,分类(语言模型 / 向量嵌入 / 重排序 / 图像)
- 入口管理:OpenAI 兼容 API(含流式 SSE、
/v1/embeddings、/v1/rerank),入口密钥(sk-lum-*),Virtual Key 路由规则,预算与 RPM/TPM 限流 - 看板监控:Provider 健康检查、24h 请求/Token 统计、入口用量排行
- 请求日志:全量请求记录、按模型定价的成本估算
- 安全:管理员登录、Session、IP 白名单/黑名单(分 admin/proxy 范围)
快速开始
# 构建(含 Vue 前端嵌入)
make build
# 运行(数据目录默认 ./data,监听 :8293)
./luminary
# 或指定参数 / 环境变量
./luminary -data-dir ./data -addr :8293
# LUMINARY_DATA=./data LUMINARY_ADDR=:8293 ./luminary
首次启动自动创建 SQLite 数据库与默认系统设置(含随机加密密钥)。默认管理账号:admin / admin123(仅当数据库中尚无管理员时创建)
默认监听端口:8293(可通过 -addr 或 LUMINARY_ADDR 修改)
- 管理台:http://localhost:8293
- 管理 API:
/api/admin/*(Session 登录) - 推理入口 API:
/v1/*(入口密钥鉴权,OpenAI 兼容)
入口 API(推理)
客户端使用在管理台创建的入口密钥(sk-lum-*)调用,与 OpenAI SDK 兼容。
鉴权
Authorization: Bearer sk-lum-<your-key>
Base URL:http://<host>:8293/v1(端口以启动参数 -addr 为准)
| 方法 | 路径 | 说明 | 状态 |
|---|---|---|---|
GET |
/v1/models |
列出当前入口密钥可用的模型 | 已支持 |
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 格式(含流式)。
示例:对话补全
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"}]}'
示例:流式对话
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
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 兼容)
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}'
示例:列出模型
curl http://localhost:8293/v1/models \
-H "Authorization: Bearer sk-lum-..."
入口密钥的 Provider / Model 白名单、预算、RPM/TPM 限流与路由规则均在管理台「入口管理」配置;白名单为空表示不限制。
开发
# 终端 1:后端
go run ./cmd/luminary
# 终端 2:前端(代理到后端,默认 8293)
cd web && npm install && npm run dev
系统设置
所有运行参数在管理台 系统设置 页面维护,存入 SQLite,无需配置文件即可启动。
| 设置项 | 说明 |
|---|---|
| 加密密钥 | Provider API Key 加密密钥(首次启动自动生成) |
| 信任代理 | 信任的反向代理 IP/CIDR;仅此时才读取 X-Forwarded-For |
| 会话 / 登录限制 | 管理员 Session 有效期、登录尝试次数与锁定时长 |
| 用量刷盘 / 健康检查 | 后台任务间隔 |
| 网关重试 | 上游故障时的重试次数与退避 |
启动参数(非阻塞,仅决定进程如何监听与数据存放位置):
| 参数 / 环境变量 | 说明 | 默认 |
|---|---|---|
-data-dir / LUMINARY_DATA |
SQLite 数据目录 | ./data |
-addr / LUMINARY_ADDR |
HTTP 监听地址 | :8293 |
可选环境变量 LUMINARY_ENCRYPTION_KEY:仅在首次初始化系统设置时写入加密密钥(一般无需设置,管理台可改)。
Docker 部署
镜像在构建阶段完成前端与 Go 二进制编译,容器启动时直接运行,不再从 Git 拉取代码。
# 本地构建镜像
make docker-build
# 或指定标签
LUMINARY_IMAGE=registry.example.com/luminary:v1.0.0 make docker-build
# 推送到仓库
LUMINARY_IMAGE=registry.example.com/luminary:v1.0.0 make docker-push
# 启动(仅持久化 /data)
docker compose up -d
docker-compose.yml 通过环境变量 LUMINARY_IMAGE 指定镜像名(默认 registry.rc707blog.top/rose_cat707/luminary:latest)。更新版本需重新 docker build / docker push 后重启容器。
Gitea Actions CI
生产镜像由 Gitea Actions 自动构建并推送到 Container Registry,工作流见 .gitea/workflows/ci.yml,详细配置见 .gitea/README.md。
一次性配置(仓库 Settings → Actions):
| 类型 | 名称 | 说明 |
|---|---|---|
| Secret | REGISTRY_TOKEN |
Gitea PAT,需 write:package 权限 |
| Variable | REGISTRY |
公网 Gitea 域名,如 git.rc707blog.top(勿用内网 IP) |
触发与镜像 tag:
pull_request:go test + 单架构 Docker 构建验证(不推送)push main/master:多架构构建并推送:latest、:sha-xxxxxxxpush tag v*:额外推送:v1.2.3
示例镜像地址(仓库 rose_cat707/luminary,Gitea 在 git.rc707blog.top):
git.rc707blog.top/rose_cat707/luminary:latest
git.rc707blog.top/rose_cat707/luminary:sha-35b3b48
git.rc707blog.top/rose_cat707/luminary:v1.0.0
部署时设置 LUMINARY_IMAGE 指向 CI 推送的镜像即可。
应急恢复(容器内)
当 IP 白名单或登录冷却导致无法进入管理台时,可在容器内执行恢复工具(已内置在镜像中):
# 一键:重置密码为 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
本地非容器环境:
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) |
项目结构
cmd/luminary/ 主服务入口
cmd/luminary-recover/ 应急恢复 CLI(容器内 docker exec 使用)
scripts/ 运维脚本(含 luminary-recover.sh)
internal/ Go 后端(gateway、store、handler...)
web/ Vue 3 前端(构建产物嵌入二进制)
License
MIT