Files
renjue c4b01ebe2b
CI / docker (push) Successful in 2m52s
实现 Atlas AI 平台一期能力并完成品牌化改造。
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 23:54:49 +08:00

310 lines
12 KiB
Markdown
Raw Permalink 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.
# Atlas
Atlas 是面向 AI 能力的统一接入与使用平台。Go + Vue 单体部署:用户端提供对话、文生图、图生图与历史记录;管理端配置上游 Provider 与模型、查看请求日志;内部 Gateway 兼容 OpenAI / Replicate 协议,统一编排、日志与路由。
## 特性
- **单体部署**:API 与 SPA 同进程、同端口,生产环境无需 Node.js
- **多协议 Gateway**`/v1/*` 透传 OpenAIChat、Embeddings 等)与 ReplicatePredictions
- **统一 invoke 编排**:同步/异步调用、任务队列、上游轮询 + 前端 SSE 进度推送
- **Provider 管理**:管理端配置上游地址与密钥;模型优先从上游 `/v1/models` 同步,也可手动维护
- **请求日志**Gateway 与用户 invoke 全链路记录,管理端可检索
- **用户会话隔离**:Cookie 会话区分用户数据;管理端独立 Bearer 鉴权
- **纯 Go 编译**SQLite 使用 `glebarez/go-sqlite``CGO_ENABLED=0`);Docker 构建对齐 LuminaryBuildKit 缓存、`npm ci`、阿里云 apk 源)
## 快速开始
```bash
# 开发模式(两个终端)
make run # 后端 :8080
make dev-web # 前端 :5173/api 代理到 8080
# 生产构建
make build
./dist/app
# Docker
docker compose up -d
```
启动后访问:
| 入口 | 地址 | 说明 |
|------|------|------|
| 用户端 | `http://localhost:8080/chat` | 对话、生图、历史(无需登录) |
| 管理端 | `http://localhost:8080/admin` | Provider、日志、设置(需登录) |
| Gateway | `http://localhost:8080/v1/*` | OpenAI / Replicate 兼容 API |
| 健康检查 | `GET /health` | `{ "status": "ok" }` |
默认管理员密码:`admin`(可在管理端设置页修改)。
---
## 架构
```
┌─────────────────────────────────────────────────────────────────────┐
│ 单一 Go 进程 │
│ ┌─────────────┐ ┌─────────────┐ ┌──────────────┐ ┌──────────┐ │
│ │ /api/v1/* │ │ /v1/* │ │ /health │ │ /* SPA │ │
│ │ 用户 + 管理 │ │ Gateway │ │ │ │ embed │ │
│ └──────┬──────┘ └──────┬──────┘ └──────────────┘ └──────────┘ │
│ │ │ │
│ ┌──────▼────────────────▼──────────────────────────────────────┐ │
│ │ api → service (invoke / chat / reqlog / taskevents) → store │ │
│ └──────────────────────────┬───────────────────────────────────┘ │
│ │ │
│ ┌──────────────────────────▼───────────────────────────────────┐ │
│ │ provider (Router / ModelsService / ProxyStream) → 上游 API │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌──────────────────────────▼───────────────────────────────────┐ │
│ │ SQLite WAL {data}/app.db │ │
│ └────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
```
### 调用链路
**对话(Chat**
```
浏览器 → POST /api/v1/user/conversations/:id/messages
→ chat.Service → provider.ProxyStream → 上游 SSE 真流式回传
```
**生图(异步任务)**
```
浏览器 → POST /api/v1/user/generate
→ invoke.Service 创建 task → async_worker 轮询上游
→ GET /api/v1/user/tasks/:id/events (SSE) 推送进度
```
**Gateway 直连**
```
客户端 → /v1/chat/completions | /v1/predictions ...
→ provider.Router 按模型路由 → 上游 + request_logs
```
### 分层约定
| 层 | 路径 | 职责 |
|----|------|------|
| 入口 | `cmd/app/` | 参数解析、依赖初始化、HTTP 服务、优雅关闭 |
| HTTP | `internal/api/` | 路由、中间件、用户/管理/Gateway Handler、SPA |
| 编排 | `internal/service/` | invoke、chat、reqlog、taskevents、asset |
| 上游 | `internal/provider/` | HTTP 代理、模型列表、流式转发、Provider 路由 |
| 领域 | `internal/domain/` | 服务类型、invoke 请求/响应模型 |
| 持久化 | `internal/store/` | SQLite、goose 迁移、仓储与 HotCache |
| 配置 | `internal/settings/` | KV 配置键、默认值、脱敏 |
| 前端 | `web/` | Vue SPA,构建产物嵌入 `internal/api/static/` |
---
## 目录结构
```
.
├── cmd/app/ # 进程入口
├── internal/
│ ├── api/
│ │ ├── handlers.go # 基础路由、鉴权、设置
│ │ ├── user_handlers.go # 用户端 API
│ │ ├── admin_handlers.go # 管理端 API
│ │ ├── gateway*.go # /v1 Gateway
│ │ ├── task_sse.go # 任务 SSE
│ │ └── static/ # 前端 embed 产物
│ ├── service/
│ │ ├── invoke/ # 同步/异步 invoke + worker
│ │ ├── chat/ # 对话编排
│ │ ├── reqlog/ # 请求日志
│ │ └── taskevents/ # 任务事件广播
│ ├── provider/ # 上游 HTTP 代理与路由
│ ├── domain/
│ ├── store/migrations/ # goose SQL002_atlas, 003_provider_models
│ └── settings/
├── web/src/
│ ├── views/ # Chat、生图、History、Admin 页面
│ ├── layouts/ # UserLayout / AdminLayout
│ ├── composables/ # useInvoke (SSE)、useUserMeta 等
│ └── styles/global.css # 设计规范落地样式
├── docs/UI-DESIGN-SYSTEM.md # UI 设计规范
├── Makefile
├── Dockerfile
└── docker-compose.yml
```
---
## 技术栈
| 层级 | 选型 |
|------|------|
| 后端 | Go 1.25 + Gin |
| 数据库 | SQLite (glebarez/go-sqlite) |
| 迁移 | goose v3 (embed SQL) |
| 前端 | Vue 3 + Vite + TypeScript |
| UI | Element Plus |
| 状态 | Pinia |
| HTTP | axios(管理端)/ fetch + EventSource(用户端 SSE |
---
## 功能模块
### 用户端(`/chat`、`/image/*`、`/history`
- 多轮对话,SSE 流式输出
- 文生图、图生图(异步任务 + SSE 进度)
- 生成历史、参数预设
- 基于 `Atlas-Session` Cookie 的会话隔离
### 管理端(`/admin/*`
- Provider CRUDOpenAI / Replicate 协议、base_url、api_key
- 模型列表:上游 sync 或手动添加
- 请求日志检索、仪表盘统计
- 系统设置(应用名、鉴权、语言等)
### Gateway`/v1/*`
| 协议 | 路由示例 |
|------|----------|
| OpenAI | `GET /v1/models``POST /v1/chat/completions``POST /v1/embeddings` … |
| Replicate | `POST /v1/predictions``GET /v1/predictions/:id``GET /v1/predictions/:id/stream` … |
Gateway 使用与用户端相同的 Cookie 会话,按模型名路由到已配置的 Provider。
---
## API 概览
**前缀:** `/api/v1`
### 鉴权(管理端)
| 接口 | 说明 |
|------|------|
| `POST /api/v1/auth/login` | 登录,返回 `{ "token": "..." }` |
| `GET /api/v1/auth/status` | `{ "enabled": true \| false }` |
| 受保护路由 | Header: `Authorization: Bearer <token>` |
`auth_enabled` 不为 `"true"` 时,管理端路由跳过鉴权(便于本地调试)。用户端路由始终公开,通过 Cookie 区分会话。
### 用户端(节选)
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/user/session` | 初始化会话 |
| GET | `/user/meta` | 可用模型与服务元信息 |
| * | `/user/conversations/*` | 对话 CRUD 与消息 |
| POST | `/user/generate` | 文生图 / 图生图 |
| POST | `/user/upload` | 上传参考图 |
| GET | `/user/tasks/:id/events` | 任务进度 SSE |
| * | `/user/generations/*`、`/user/presets/*` | 历史与预设 |
### 管理端(节选)
| 方法 | 路径 | 说明 |
|------|------|------|
| * | `/admin/providers/*` | Provider 与模型管理 |
| POST | `/admin/providers/:id/models/sync` | 从上游同步模型 |
| GET | `/admin/logs` | 请求日志 |
| GET | `/admin/dashboard/stats` | 统计 |
### 响应格式
```json
{ "ok": true }
{ "items": [...], "total": 42 }
{ "error": "human readable message" }
```
列表接口支持 `?limit=`(默认 50,最大 500)与 `?offset=`。
---
## 配置
### 启动参数与环境变量
| 来源 | 名称 | 默认 | 说明 |
|------|------|------|------|
| CLI | `-data` | `./data` | 数据目录(SQLite、上传文件等) |
| CLI | `-addr` | `:8080` | HTTP 监听地址 |
| Env | `APP_DATA` | — | 覆盖 `-data` |
| Env | `APP_ADDR` | — | 覆盖 `-addr` |
### 运行时配置(SQLite KV
| 键 | 说明 |
|----|------|
| `app_name` | 应用名称(默认 `Atlas` |
| `admin_password` | 管理员密码 |
| `auth_enabled` | 是否启用管理端认证 |
| `ui_locale` | 界面语言(`zh-CN` / `en` |
| `file_sign_secret` | 文件访问签名密钥 |
可通过管理端设置页修改,无需重启。
---
## 开发工作流
```bash
# 终端 1 — 后端
make run
# 终端 2 — 前端热更新
make dev-web
# 浏览器 http://localhost:5173
```
| 命令 | 作用 |
|------|------|
| `make run` | 运行后端 |
| `make dev-web` | Vite 开发服务器 |
| `make build` | 构建含 embed 前端的完整二进制 |
| `make build-go` | 仅编译后端(跳过前端) |
| `make test` | Go 测试 |
| `make tidy` | `go mod tidy` |
| `make clean` | 清理构建产物 |
---
## Docker 部署
```bash
make docker-build # Docker 内完整构建(含 BuildKit 缓存)
make docker-push-prebuilt # 本地编译 Go + 轻量 runtime 镜像(最快,推荐)
docker run -d -p 8080:8080 -v atlas-data:/data atlas:latest
```
或:
```bash
docker compose up -d
```
镜像多阶段构建(Node 编译前端 → Go 编译 → Alpine 运行),非 root 用户,数据持久化至 `/data`。
---
## CI
仓库包含 `.gitea/workflows/ci.yml`push 到 `main` 或打 `v*` tag 时运行测试并构建 Docker 镜像。详见 [.gitea/README.md](.gitea/README.md)。
---
## UI 设计
前端样式与布局规范见 [docs/UI-DESIGN-SYSTEM.md](docs/UI-DESIGN-SYSTEM.md)。页面统一使用 `PageHeader`、`AppCard`、`StatCard` 等壳层组件,品牌色与间距 Token 定义在 `web/src/styles/global.css`。
---
## License
MIT — 见 [LICENSE](./LICENSE)