Files
Luminary/README.md
T
renjue a831012c48
CI / docker (push) Failing after 1m35s
Add Gitea CI, align Docker for multi-arch, and drop legacy YAML config.
Introduce Gitea Actions workflow and CI-aligned Dockerfile; remove file-based
config in favor of SQLite settings; refresh branding and tighten gitignore.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-23 21:10:38 +08:00

236 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Luminary AI Gateway
Go + Vue 3 AI 网关,参考 [Bifrost](https://github.com/maximhq/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 范围)
## 快速开始
```bash
# 构建(含 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 兼容。
**鉴权**
```http
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 格式(含流式)。
**示例:对话补全**
```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"}'
```
**示例:RerankCohere 兼容)**
```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 限流与路由规则均在管理台「入口管理」配置;白名单为空表示不限制。
## 开发
```bash
# 终端 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 拉取代码。
```bash
# 本地构建镜像
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/workflows/ci.yml),详细配置见 [`.gitea/README.md`](.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-xxxxxxx`
- `push tag v*`:额外推送 `:v1.2.3`
示例镜像地址(仓库 `rose_cat707/luminary`Gitea 在 `git.rc707blog.top`):
```text
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 白名单或登录冷却导致无法进入管理台时,可在容器内执行恢复工具(已内置在镜像中):
```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` |
## 项目结构
```
cmd/luminary/ 主服务入口
cmd/luminary-recover/ 应急恢复 CLI(容器内 docker exec 使用)
scripts/ 运维脚本(含 luminary-recover.sh
internal/ Go 后端(gateway、store、handler...
web/ Vue 3 前端(构建产物嵌入二进制)
```
## License
MIT