vangogh
by guowei-xie
README.md
# vangogh(梵高)
> 一个面向数据分析团队的 **AI 分析助手内容中台**:MCP 网关 + 运营后台 + 多客户端插件。
分析师在 Claude Code、Codex、openclaw 等 AI 客户端里用自然语言提问、取数、做归因。要让 AI 答得准,它需要知道的东西有:指标口径、分析方法、SQL 模板、系统提示词、分析工作流,以及能查哪些表、哪些列。vangogh 把这些沉淀成**可运营的内容资产**:
- 资产按岗位打包成**角色包**,发放到客户端;
- 所有取数经 **MCP 网关**执行,网关负责鉴权、表/列 ACL、SQL AST 校验、脱敏和审计;
- 使用中发现的口径缺口、好用的 SQL 等,由客户端的 data-collector 整理成**结构化候选变更**回流到后台,形成**反馈飞轮**。
运营在后台的每一次改动,最终决定 AI 回答问题时用哪个指标口径、哪套方法、能查哪些表。
仓库自带一套**虚构电商示范数据**和一键启动脚本,克隆后几分钟就能在本机跑通完整链路。
---
## 两端如何衔接
```mermaid
flowchart LR
subgraph 运营后台 [运营后台 · 管理端]
A[内容资产<br/>指标 / 方法 / SQL / 提示词 / 工作流 / 表元数据]
B[反馈飞轮<br/>反馈池 → 素材池 → 提案池]
C[角色包编排与发布]
end
subgraph 网关 [MCP 网关]
G[鉴权 · 表/列 ACL · SQL AST 校验<br/>脱敏 · 限流 · 审计]
end
subgraph 客户端 [分析师客户端 · 使用端]
D[Claude Code / Codex / openclaw]
end
DB[(业务库<br/>DuckDB 只读)]
R[(远程数据源<br/>SQL-over-HTTP,可选)]
B -->|提案合入| A
A --> C
C -->|发布角色包版本| G
G -->|会话启动拉取角色包| D
D -->|MCP 工具调用| G
G --> DB
G --> R
D -->|data-collector 上报反馈| B
```
- **运营后台**(管理端):维护内容资产,处理分析师反馈,编排并发布角色包,签发访问凭证。
- **MCP 网关**:业务数据的唯一出口。客户端不持有任何数据库凭证,所有 SQL 都由网关校验后代为执行。
- **客户端插件**(使用端):会话启动时按 token 拉取已授权的角色包,注入口径、模板和方法;分析过程中通过 MCP 工具取数。
- 两端靠**角色包版本**衔接:后台发布新版本后,分析师下次开会话时自动拉取。
## 功能概览
> 截图均基于仓库自带的虚构电商示范数据。
### 登录
后台默认使用**本地账号**登录。首个超管用命令行创建,其余账号由超管在后台新建。飞书 OAuth 扫码登录是**可选通道**,配置后可以和本地账号并存。

### 内容资产维护
后台有五类内容资产:指标、SQL 模板、方法论、系统提示词、工作流,操作方式完全一致。
- 资产只有「启用 / 停用」一个开关,**编辑保存即刻生效**,并自动重算内容指纹 `content_hash`。
- 保存不会自动改动已发布的角色包版本;引用了旧内容的版本会被标为「过时引用」。


### 反馈飞轮:反馈池 → 素材池 → 提案池
分析师端的反馈要经过三级流转才写回内容资产。原则是:**采纳反馈不等于改资产**,所有写入都要在**提案池**复核后合入,全程留痕。


### 角色包编排与发布
角色包把一套内容资产打包成一个版本,内容包括系统提示词、指标、方法、SQL 模板、工作流和表访问 ACL。
- 资产被改过之后,引用它的发布版本会标出「待重 compose」。
- 运营重组出新版本并「设为发布中」后,分析师才会用到新内容。
- 版本可以指派(pin)给个别 token 做灰度,也可以一键回退。

### 客户端插件包发放
这一页按渠道(claude-code / codex / openclaw / 运营 skill)列出各插件包的构建产物、sha256、下载链接和安装说明。配合 Token 管理签发凭证,就能把客户端发给分析师安装。

### 其他能力
- **运营分析**:按分析对象分三页,分别看分析师使用(调用量、活跃/授权分析师、成功率、留存、闲置 Token)、对外数据应用的用量、以及反馈 → 提案 → 合入的漏斗。
- **审计中心**:逐条记录每次工具调用。SQL 原文不落库,只存 sha256 摘要。
- **资产全景图**:把用户、角色包、内容资产、数据表、数据源连成一张关系图,用来评估改动的影响面。
- **数据应用**:面向 BI / ETL 等非 AI 系统的只读 REST 取数通道,见下文「对外只读查数服务」。
- **远程数据源**:可以接入任意实现了 [远程数据源协议](docs/remote-source-protocol.md) 的 SQL-over-HTTP 服务。远程表和本地表共用同一套 ACL、模板与脱敏体系。
- **运营 Skill**(`skills/vangogh-operate`):在 Claude Code 里用对话方式盘点资产、把 SOP/SQL 萃取成提案、消费素材池。它只产出提案,不直接改库。
---
## Quick Start(本地一键 demo)
依赖:[uv](https://docs.astral.sh/uv/)、Node.js 18+、Docker。
```bash
git clone <repo-url> vangogh && cd vangogh
# 一键准备:构建前端 → 安装依赖 → 生成示范业务库 → 起 MySQL → 迁移
# → 写入全局资产与示范角色包 → 创建本地超管(交互输入密码)
make demo
# 非交互场景:VANGOGH_ADMIN_PASSWORD='<至少 8 位>' make demo
# 另开两个终端
make run-gateway # MCP 网关 http://127.0.0.1:8089
make run-admin # 运营后台 http://127.0.0.1:8090/vangogh/admin/
```
打开 <http://127.0.0.1:8090/vangogh/admin/>,用 `admin` 和刚设置的密码登录。可以看到示范角色包「电商经营分析师」(`ecom_ops_analyst`)。
`make help` 列出全部目标。常用的几个:
| 目标 | 作用 |
|---|---|
| `make demo-data` | 重新生成虚构电商业务库 `data/demo.duckdb` |
| `make db-up` / `make db-down` | 启动 / 停止并清空 demo MySQL(默认宿主端口 13306,可用 `VANGOGH_MYSQL_PORT` 改) |
| `make migrate` | 平台库迁移到最新 |
| `make seed` | 写入平台全局资产(`scripts/seed_globals.py`)与示范角色包(`scripts/example_full_compose.py`),可重复执行 |
| `make create-superuser` | 创建本地超管(`ADMIN_USER=admin`) |
| `make test` | 运行测试 |
demo 使用 `deploy/config/config.demo.ini`(Makefile 已通过 `VANGOGH_CONFIG` 指定)。
### 接一个客户端试试
1. 在后台「Token 管理」新建 Token,绑定 `ecom_ops_analyst`。明文只显示一次,请立即复制。
2. 构建插件包:`VANGOGH_RELEASE_GATEWAY_URL=http://127.0.0.1:8089 ./scripts/build_plugin_release.sh all 0.1.0`。产物写入 `static/download/`,由网关的 `/download/*` 对外提供。
3. 按对应客户端的安装说明安装,并写入 token:
- Claude Code:[plugins/claude-code/vangogh/INSTALL.md](plugins/claude-code/vangogh/INSTALL.md),一键安装脚本是 `<gateway_url>/download/claude-plugin/install-desktop.sh`
- Codex:[plugins/codex/vangogh/CODEX_INSTALL.md](plugins/codex/vangogh/CODEX_INSTALL.md)
- openclaw:[plugins/openclaw/vangogh/OPENCLAW_INSTALL.md](plugins/openclaw/vangogh/OPENCLAW_INSTALL.md)
4. 完全重启客户端,运行 `/vangogh doctor` 自检,然后直接提问,例如:
- 「2026 年 9 月各渠道大类 GMV 达成怎么样?缺口在哪?」
- 「8 月达人种草渠道的退款率为什么这么高?」
## 示范数据集
`scripts/build_demo_duckdb.py` 会生成一家**虚构**综合电商「拾野优选」近 12 个月的经营数据。品牌、城市、商品、渠道全部是虚构的;随机种子固定,重复运行结果逐字节一致。
| 表 | 内容 |
|---|---|
| `dwd_order_detail` | 订单明细(一行一单,约 5.7 万单) |
| `dim_user` | 用户维表(性别、年龄段、城市等级、会员等级、首单渠道) |
| `dim_channel` | 渠道维表:自有 APP、小程序(自营);搜索广告、信息流广告(付费投放);直播带货、达人种草(内容电商) |
| `dim_product` | 商品维表(品类、品牌、标价) |
| `ads_sales_target` | 月度 × 渠道大类的 GMV / 订单目标 |
| `ads_traffic_daily` | 日 × 渠道的流量漏斗(UV / PV / 加购 / 下单人数) |
所有表都带 `dt` 快照分区。`dt` 表示「数据截至日」,**取 `MAX(dt)` 就是最新全量**,不同 `dt` 之间不能相加。
数据里预埋了几条可供分析和归因的「故事」:
1. **2026-09 内容电商 GMV 未达标**:达成率约 77%,其余月份和大类都在 97%~104%。原因是直播带货当月 UV 下滑约 35%,转化率基本持平,**缺口来自流量而不是转化**。
2. **2026-08 达人种草退款异常**:该渠道当月退款率约 20%(上月约 8%)。问题集中在「美妆个护」品类的虚构品牌「露汐」,退款率约 36%,同品类其他品牌正常。
3. **大促峰值**:2025-11 和 2026-06 是 GMV 峰值月,折扣加深,客单价被拉低;2026-02 是低谷。
4. **小程序转化提升**:支付转化率从约 3.0% 稳步提升到约 3.9%。
5. **会员复购差异**:复购率按普通 → 银卡 → 金卡 → 黑卡依次升高。
6. **口径陷阱**:`gmv` 列是原价,指标「GMV」的口径是实付 `pay_amount`。这一条正好用来演示指标口径资产的价值。
示范角色包 `ecom_ops_analyst`(电商经营分析师)包含:
- 7 个指标:GMV、订单数、客单价、支付转化率、复购率、退款率、GMV 目标达成率;
- 1 个方法:目标缺口归因(流量 × 转化 × 客单价);
- 3 个 SQL 模板:GMV 目标达成追踪、渠道流量转化漏斗、退款率多维下钻;
- 1 个工作流:GMV 体检;
- 6 张表的访问 ACL,其中 `dim_user.gender` 被设为禁查列,用来演示列级权限。
## 配置说明
配置统一用 INI 格式。模板见 `deploy/config/config.ini.example`(生产)、`config.dev.ini`(本地开发)、`config.demo.ini`(一键 demo)。进程按以下顺序找配置文件:
1. 环境变量 `VANGOGH_CONFIG` 指定的文件;
2. 当前目录下自动发现的 `deploy/config/config.ini`。
`*.secret.ini` 已被 `.gitignore` 排除。主要配置段如下:
| 段 | 说明 |
|---|---|
| `[server]` | 网关监听地址;`gateway_url` 是对外网关基址,打插件包时会写进安装说明 |
| `[admin]` | 后台端口;`public_prefix` 是对外子路径前缀,默认 `/vangogh`,后台地址为 `<host>/vangogh/admin/` |
| `[auth]` | `providers`:后台登录通道,逗号分隔,`local`(本地账号,默认)和 / 或 `lark`;`session_ttl_days` 是本地登录会话的有效期 |
| `[lark]` | **可选**飞书应用。要作为登录通道,需要 `enabled = true` 且 `[auth] providers` 里包含 `lark`;`host` 可切换国内版或国际版(larksuite) |
| `[lark_notify]` | **可选**:新反馈到来时给运营推送飞书审批卡片,复用 `[lark]` 凭据,默认关闭 |
| `[business_duckdb]` | 业务库 DuckDB 文件路径(网关以 `read_only` 方式打开)、允许的 schema、超时与行数上限 |
| `[platform_mysql]` | 平台库(MySQL 8.0+),存放 token、角色包、内容资产、反馈、审计等元数据 |
| `[rate_limit]` | 每个 token 的限流,默认 5 次/秒、50 次/分钟 |
| `[external_api]` | 对外只读查数服务 `/api/v1` 的总开关,默认关闭 |
| `[audit]` | 是否对全部 MCP 工具调用写审计(运营分析依赖它) |
| `[template_render]` | SQL 模板渲染层的安全参数和应急降级开关 |
| `[data_source.<code>]` | **可选**远程 SQL 数据源,一段对应一个源,协议见 [docs/remote-source-protocol.md](docs/remote-source-protocol.md) |
### 后台账号
```bash
# 创建(或用 --update-existing 重置)本地超管
VANGOGH_CONFIG=<配置文件> uv run vangogh-admin create-superuser --username admin
# 密码依次取自 --password、环境变量 VANGOGH_ADMIN_PASSWORD,都没有时交互输入(至少 8 位)
```
其余账号由超管在后台「系统 → 后台用户」点「新建本地账号」创建,再在「后台角色」里按权限码组装角色并绑定给账号。
`vangogh-admin` 不带参数(或带 `serve`)时启动后台服务。
## 本地开发
```bash
uv sync --extra dev # 按 uv.lock 安装依赖
cd src/vangogh/admin/web && npm ci && npm run build && cd - # 首次构建前端(Python 包会打包其产物)
cp deploy/config/config.dev.ini deploy/config/config.dev.secret.ini # 填平台库口令等
export VANGOGH_CONFIG=deploy/config/config.dev.secret.ini
uv run alembic -c src/migrations/alembic.ini upgrade head
uv run python -m uvicorn vangogh.gateway.server:app --reload --port 8089
uv run python -m uvicorn vangogh.admin.server:app --reload --port 8090
uv run python -m pytest -q
```
> 前端热更新:`cd src/vangogh/admin/web && npm run dev`。vite dev 跑在 `:5173`,已配置把 `/vangogh/admin/api` 反代到 `:8090`。前端的资源前缀默认是 `/vangogh/admin/`,换前缀时在构建前设置 `VANGOGH_WEB_BASE`,并同步修改 `[admin] public_prefix`。
## 生产部署要点
仓库不附带 systemd 或 nginx 文件,按自己的基础设施部署即可。要点如下:
- **进程**:网关(`vangogh-gateway`,默认 `:8089`)和后台(`vangogh-admin`,默认 `:8090`,API 与 SPA 同端口)是两个独立进程。可以用 systemd、supervisor 或容器托管,以低权限用户运行。
- **准备**:执行 `./scripts/server_bootstrap.sh [--with-migrate] [--with-plugins]`,它会幂等地完成构建前端、建 `.venv`、执行迁移、打插件包这几步。
- **配置**:`cp deploy/config/config.ini.example deploy/config/config.ini && chmod 600`,按注释填写。口令可以放进 `password_file` / `api_key_file` 外置文件。
- **数据**:业务 DuckDB 以只读方式挂载到部署机;平台库用 MySQL 8.0+。
- **反向代理**:前置层终结 TLS,把 `<prefix>/` 转发到网关、`<prefix>/admin/` 转发到后台。`<prefix>` 与 `public_prefix` 保持一致。
- **健康检查**:`GET /healthz`(网关)、`GET /admin/healthz`(后台)。
- **升级**:拉取新代码后重跑 bootstrap(加 `--with-migrate --with-plugins`),再重启两个进程。
## 对外只读查数服务(非 AI 接入)
BI、ETL 等业务系统可以通过网关的 `/api/v1/*` REST 通道对业务库做**只读**查数。
- 调用方需要在后台注册为「**数据应用**」,凭 API key 调用。数据应用与 AI 角色包完全解耦。
- 安全链路和 MCP 通道同等强度:只读连接、应用级表/列 ACL、SQL guard、敏感列脱敏、全量审计。
这条通道默认关闭,在配置里打开 `[external_api] enabled = true` 后重启网关。
- Base URL:`<gateway_url>/api/v1`
- 鉴权:`Authorization: Bearer dak_...` 或 `X-API-Key: dak_...`
| 方法 | 路径 | 用途 |
|---|---|---|
| GET | `/me` | 应用自检:授权的表、模板和限流配置 |
| GET | `/tables` · `/tables/{name}` | 授权范围内的表元数据(禁查列已剔除) |
| GET | `/templates` | 白名单内的 SQL 模板(含参数 schema) |
| POST | `/templates/{code}/run` | **模板取数(推荐)**,body 为 `{"params": {...}}` |
| POST | `/query` | 自由 SQL(仅 SELECT),需要应用开启 `allow_free_sql` |
```bash
curl -X POST <gateway_url>/api/v1/templates/sql_ecom_channel_funnel/run \
-H "Authorization: Bearer dak_xxx" -H "Content-Type: application/json" \
-d '{"params": {"start_date": "2026-09-01", "end_date": "2026-09-30"}}'
```
返回结构包含 `columns`、`rows`、`row_count`、`elapsed_ms`、`effective_limit` 等字段。错误统一为 `{"error": {"code","message","details"}}`,其中带 `details.trace_id`;429 响应附 `Retry-After`。Python 示例和后台配置步骤见 [docs/admin-guide.md](docs/admin-guide.md) 的「数据应用」一章。
## 目录结构
```
src/vangogh/common/ 配置 / 鉴权 / 模型 / SQL guard / 模板渲染 / 脱敏 / 权限码
src/vangogh/gateway/ MCP 网关(JSON-RPC + REST)、查询路由、远程数据源、对外 /api/v1
src/vangogh/admin/ 运营后台 FastAPI(routes / services / schemas)
src/vangogh/admin/web/ Vite + Vue 3 + Element Plus 前端
src/migrations/ alembic(单一初始迁移 0001_initial)
plugins/ Claude Code / Codex / openclaw 客户端插件(_shared 为共享模块)
skills/vangogh-operate/ 运营 Skill(基于后台 API 的对话式运营)
scripts/ 示范数据 / 示范角色包 / 全局资产 / 部署 bootstrap / 插件打包
deploy/config/ 配置模板
docs/ 架构、运营手册、用户手册、远程数据源协议
tests/ 单元与集成测试
```
## 文档
- [docs/architecture.md](docs/architecture.md):架构、数据模型、接口契约、SQL 安全、反馈飞轮设计
- [docs/admin-guide.md](docs/admin-guide.md):运营后台使用手册(界面操作与底层口径)
- [docs/user-manual.md](docs/user-manual.md):分析师端使用手册
- [docs/remote-source-protocol.md](docs/remote-source-protocol.md):远程数据源 HTTP 协议
## License
[MIT](LICENSE)
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo recent community issues