TensorZero UI 前端开发与贡献指南:技术栈、编码规范与 Autopilot 本地联调
【免费下载链接】tensorzeroTensorZero is an open-source LLMOps platform that unifies an LLM gateway, observability, evaluation, optimization, and experimentation.项目地址: https://gitcode.com/GitHub_Trending/te/tensorzero
TensorZero 的 Web 控制台(ui/目录)为部署提供可观测性(Observability)、优化(Optimization)、数据集管理、评估等可视化能力。本文以 ui/CLAUDE.md 引用的 ui/AGENTS.md 为核心,结合仓库源码,系统讲解 TensorZero UI 的技术栈、路由组织、编码规范、质量门禁,以及 Autopilot 这一内部功能的本地开发与端到端测试流程。读完后,你将掌握在ui/目录下进行日常开发、自检与提交的全套实操方法,并理解 UI 如何与 TensorZero Gateway 通信。
技术栈与项目结构:React Router 7 + Tailwind + Node + pnpm
ui/CLAUDE.md的全部内容即一行@AGENTS.md,指向同目录下的 ui/AGENTS.md,其中明确规定了 UI 的技术栈:
- React Router 7:页面与 API 路由的框架,包管理统一使用pnpm;
- Tailwind:样式方案,配合
tailwindcssv4 与@tailwindcss/vite插件使用; - Node:运行时与构建工具链基础。
在 ui/package.json 中可以验证这套栈的具体版本与脚本:react-router/@react-router/dev为^7.12.0,tailwindcss为^4.1.11,react为^19.2.1,并依赖@tensorzero/tensorzero-node(file:../crates/tensorzero-node)作为本地 Rust 扩展绑定。
路由全部集中在 routes.ts
UI 路由(页面与 API)统一定义在 ui/app/routes.ts,采用 React Router 7 的index/route/prefixAPI 声明式组织,主要包括:
- API 路由(
/api前缀):网关密钥设置、inference/episode 预览、数据集计数、评估运行搜索与取消、反馈提交,以及 Autopilot 的 session 事件流、中断、配置应用等接口; - 数据集(Datasets):列表、Builder、按名称查看数据集与 datapoint;
- 评估(Evaluations)与Workflow Evaluations:运行列表与结果页;
- Autopilot:session 列表与会话详情页;
- Playground:
/playground; - 可观测性(Observability):functions、inferences、episodes、models 四个子模块;
- 其他:监督微调(Supervised Fine-Tuning)、API Keys、配置编辑器(Config)、健康检查(Health)。
新增页面或 API 时,应当同步修改该文件并在app/routes/下按约定路径(如$param动态段)添加对应模块。
编码规范:logger、useFetcher 与类型约定
统一使用logger而非 console
规范要求优先使用~/utils/logger导出的logger,而不是直接调用console.error、console.warn、console.log、console.debug。从 ui/app/utils/logger.ts 的实现可以看到原因:logger 封装了日志级别控制(debug/info/warn/error),服务端通过环境变量TENSORZERO_UI_LOG_LEVEL调整级别(默认info),浏览器端默认debug,并在消息前自动附加[TensorZero UI <版本>]前缀,便于在分布式日志中定位来源。
优先useFetcher而非直接fetch
规范要求优先使用 React Router 的useFetcher发起数据变更请求,而不是直接调用fetch。useFetcher与 React Router 的 action/loader 体系集成,能够自动处理加载状态、错误与并发,避免在组件内手写请求生命周期管理。
undefined优先于null
ui/README.md 补充了一条贯穿全项目的类型约定:新代码一律优先使用undefined而非null,唯一的例外是napi-rs兼容场景(napi-rs 用null表示Option<T>),并且永远不要写出T | undefined | null这种联合类型。
质量门禁:改完代码必须通过的三条命令
修改 UI 代码后,必须从ui/目录运行以下三条命令且全部通过(对应 ui/package.json 中的 scripts):
pnpm run format pnpm run lint pnpm run typecheckformat:使用oxfmt对**/*.{js,jsx,ts,tsx,css,scss,html,json,yaml,md}进行格式化;lint:先跑oxlint . --fix --deny-warnings,再跑eslint . --fix --max-warnings=0,即警告也会导致失败,保证零告警提交;typecheck:react-router typegen && tsc,先生成路由类型再执行 TypeScript 全量类型检查。
这套门禁同时提供了只检查不改动的format:check与lint:check变体,适合 CI 环境使用(参见 ui/package.json)。
Autopilot 功能:仅限内部贡献者的本地开发与 E2E 测试
Autopilot 是 TensorZero 的一项实验性功能,其 E2E 测试位于 ui/e2e_tests/autopilot/。ui/AGENTS.md特别声明:该功能依赖闭源的内部 API,外部贡献者无法运行这些测试;CI 中通过仓库 dispatch(repository dispatch)从 autopilot 私有仓库触发执行。从 ui/app/routes.ts 可看到其路由入口(/autopilot下的 sessions 列表与详情页),相关的 API 路由覆盖事件流、中断、批量批准与配置应用等能力。
设置 AUTOPILOT_REPO 环境变量
内部贡献者需要先将本地 autopilot 仓库检出路径导出为环境变量:
export AUTOPILOT_REPO=/path/to/autopilot后续的配置、测试命令都会引用$AUTOPILOT_REPO。
启动 Autopilot 依赖服务
使用 docker compose 启动带e2eprofile 的依赖服务,命令可在$AUTOPILOT_REPO目录下直接运行,或通过-f显式指定 compose 文件:
docker compose --profile e2e up -d或:
docker compose -f "$AUTOPILOT_REPO/docker-compose.yml" --profile e2e up -d以 Autopilot 配置启动 UI 开发服务器
从ui/目录启动开发服务器时,需要同时注入两个关键环境变量:
TENSORZERO_UI_CONFIG_FILE="$AUTOPILOT_REPO/e2e_tests/fixtures/config/tensorzero.toml" \ TENSORZERO_GATEWAY_URL=http://localhost:3040 \ pnpm devTENSORZERO_UI_CONFIG_FILE:指向 TensorZero 配置文件。从源码看,它不只是供 UI 读取,还决定配置写入(config apply)能力是否开启——apply.route.ts 与 apply-all.route.ts 中,未设置该变量时接口会直接返回 "Config writing is not enabled",session 详情页 也据此控制 UI 开关;TENSORZERO_GATEWAY_URL:指向本地 Gateway(此处为http://localhost:3040)。UI 的所有推理、事件流请求都经由此地址代理到 Gateway,例如 Autopilot 的 SSE 事件流就是由 stream.route.ts 将/internal/autopilot/v1/sessions/:id/events/stream转发给 Gateway,并透传Authorization: Bearer <key>头。
运行 Autopilot E2E 测试
在ui/目录下,额外设置TENSORZERO_PLAYWRIGHT_INCLUDE_AUTOPILOT=1即可让 Playwright 包含 autopilot 测试目录:
TENSORZERO_UI_CONFIG_FILE="$AUTOPILOT_REPO/e2e_tests/fixtures/config/tensorzero.toml" \ TENSORZERO_GATEWAY_URL=http://localhost:3040 \ TENSORZERO_PLAYWRIGHT_INCLUDE_AUTOPILOT=1 \ pnpm exec playwright test e2e_tests/autopilot/该开关的作用可从 ui/playwright.config.ts 得到印证:testIgnore默认排除autopilot/**,只有在设置了TENSORZERO_PLAYWRIGHT_INCLUDE_AUTOPILOT时才取消排除——这也解释了为什么外部贡献者运行时这些测试不会干扰普通 E2E 套件。仓库还提供了便捷脚本pnpm run test-e2e-autopilot(见 ui/package.json)。
运行单个测试文件同样简单:
TENSORZERO_UI_CONFIG_FILE="$AUTOPILOT_REPO/e2e_tests/fixtures/config/tensorzero.toml" \ TENSORZERO_GATEWAY_URL=http://localhost:3040 \ TENSORZERO_PLAYWRIGHT_INCLUDE_AUTOPILOT=1 \ pnpm exec playwright test e2e_tests/autopilot/autopilot.spec.ts其他 Playwright 环境变量
从 ui/playwright.config.ts 可以看到配套的环境变量约定,便于在 CI 或容器中运行:
TENSORZERO_PLAYWRIGHT_NO_WEBSERVER/TENSORZERO_CI:跳过内置 webServer 启动(CI 中使用 docker-compose 自行拉起 UI),并将 baseURL 切换为http://0.0.0.0:4000;TENSORZERO_PLAYWRIGHT_BASE_URL:显式覆盖 baseURL(如 CI 中的http://ui:4000);TENSORZERO_PLAYWRIGHT_RETRIES:自定义失败重试次数,CI 下默认重试 2 次;- CI 下
forbidOnly: true会阻止带有test.only的代码合入。
开发中的实用注意事项
- 离线测试优化工作流:当没有真实 Provider API 时,可启动仓库的
mock-provider-api并在运行 Gateway 时设置TENSORZERO_INTERNAL_MOCK_PROVIDER_API=http://localhost:3030(见 ui/README.md); - 优化与可观测性依赖:UI 的部分页面(如推理历史、评估运行)依赖 ClickHouse 等存储,完整的本地体验可参考 ui/fixtures/docker-compose.yml 与 ui/README.md 的部署说明;
- 通用测试脚本:
pnpm run test运行 vitest 单元测试,pnpm run test-e2e运行全部 Playwright 测试(默认排除 autopilot),pnpm run test-e2e-fast跳过带@slow标记的用例以加速迭代(见 ui/package.json)。
小结
TensorZero UI 的开发约定高度工程化:技术栈统一为 React Router 7 + Tailwind + Node + pnpm,路由集中管理于 ui/app/routes.ts,编码上要求使用logger与useFetcher,并坚持undefined优先;任何改动都必须通过format/lint/typecheck三重门禁。对于内部贡献者,Autopilot 的本地联调链路(AUTOPILOT_REPO+ docker compose e2e profile +TENSORZERO_UI_CONFIG_FILE/TENSORZERO_GATEWAY_URL/TENSORZERO_PLAYWRIGHT_INCLUDE_AUTOPILOT)既完整又可控,相关环境变量在 ui/playwright.config.ts 与各 API route 源码中均有明确实现依据,可直接照此搭建开发环境。
【免费下载链接】tensorzeroTensorZero is an open-source LLMOps platform that unifies an LLM gateway, observability, evaluation, optimization, and experimentation.项目地址: https://gitcode.com/GitHub_Trending/te/tensorzero
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考