- 人工智能
- 大模型
- AI Agent
- 提示工程
- AI 评测
- 可观测性
- 后端
- 前端
【免费下载链接】coze-loop
Next-generation AI Agent Optimization Platform: Cozeloop addresses challenges in AI agent development by providing full-lifecycle management capabilities from development, debugging, and evaluation to monitoring.
本文以 ARCHITECTURE.md 为骨架,深入解析 coze-loop 这一开源 LLM 评测与可观测性平台的整体架构:多语言单体仓库布局、Go 后端的 DDD 分层与依赖不变量、前端 Rush 单体仓库的分层与 Adapter 模式、Thrift IDL 共享契约,以及代码生成、CI/CD 与 Git Hooks 等横切关注点。读完本文,你将掌握该仓库从目录结构、模块边界到构建、测试、部署的全链路技术组织方式,并能在实际开发中遵循其架构约束。
全景视图:一个仓库,三层核心
coze-loop 采用Go 后端 + TypeScript/React 前端的多语言单体仓库(Monorepo)架构。仓库顶层按职责划分为若干一级目录,其中三个目录构成了平台的核心:
frontend/:Rush.js 管理的 SPA 单体仓库,约 59 个包,负责全部前端界面;backend/:Go DDD 服务,包含 6 个业务模块,提供 HTTP 与消息消费两类进程入口;release/:Docker / Helm 部署配置,覆盖镜像构建、Docker Compose 本地部署与 Kubernetes 部署。
三者通过idl/thrift/中的 Thrift IDL 形成共享契约:IDL 既是后端 Kitex 生成 Go 代码的输入,也是前端infra/idl/工具链转换为 TypeScript 类型的来源,前后端围绕同一份契约演进。
仓库还包含若干支撑设施:common/存放由 Rush 管理的 Git Hooks(pre-commit、commit-msg、pre-push 等);.github/workflows/承载 CI/CD 工作流;根目录Makefile提供镜像、Compose、Helm 的快捷操作目标。整体布局如下(摘自 ARCHITECTURE.md 的全景视图):
┌─────────────────────────────────────────────────────────────────┐ │ coze-loop 仓库 │ │ │ │ ┌──────────────┐ ┌───────────────┐ ┌────────────────────┐ │ │ │ frontend/ │ │ backend/ │ │ release/ │ │ │ │ Rush.js SPA │──▶│ Go DDD 服务 │ │ Docker / Helm │ │ │ │ 59 packages │ │ 6 业务模块 │ │ 部署配置 │ │ │ └──────┬───────┘ └───────┬───────┘ └────────────────────┘ │ │ │ │ │ │ └───────┬───────────┘ │ │ ▼ │ │ ┌────────────┐ │ │ │ idl/thrift/ │ Thrift IDL(前后端共享契约) │ │ └────────────┘ │ │ │ │ ┌──────────────┐ ┌───────────────┐ ┌────────────────────┐ │ │ │ common/ │ │ .github/ │ │ Makefile │ │ │ │ git-hooks │ │ workflows/ │ │ image / deploy │ │ │ └──────────────┘ └───────────────┘ └────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘代码地图:Backend(backend/)
后端是一个 Go 服务,模块路径为github.com/coze-dev/coze-loop/backend。整个后端由 8 类目录组成,每一类都有明确的职责边界与架构约束:
| 目录 | 职责 | 架构不变量 |
|---|---|---|
cmd/ | 服务入口(main.go HTTP, consumer.go MQ) | 只做启动编排,不含业务逻辑 |
api/ | HTTP 路由 + handler(Hertz 框架) | handler 只做参数校验和转发,业务逻辑在 application 层 |
modules/ | 6 个 DDD 业务模块 | 模块间不直接互调 |
infra/ | 共享基础设施(DB, Redis, ClickHouse, MQ, HTTP, middleware) | 被 modules 引用,不引用 modules |
pkg/ | 共享工具库(errors, JSON, logging, context cache) | 纯工具,无业务依赖 |
kitex_gen/ | Kitex/Thrift 生成代码 | 自动生成,禁止手动修改 |
loop_gen/ | 其他生成代码 | 自动生成,禁止手动修改 |
script/ | 代码生成脚本(cloudwego, gorm_gen, errorx) | 生成结果提交到仓库 |
服务入口:两个进程,一个编排层
cmd/目录下有两个入口文件,分别对应 HTTP 服务与消息队列消费:
- backend/cmd/main.go:构建全部组件(Redis、MySQL、ClickHouse、S3 对象存储、ID 生成器、MQ 工厂、限流器等),随后调用
api.Init组装 HTTP handler,再通过registry.NewConsumerRegistryWithShutdown注册并启动 MQ 消费者,最后以go api.Start(handler)启动 Hertz HTTP 服务,并通过signal.NotifyContext监听 SIGTERM/SIGINT 实现优雅退出。 - backend/cmd/consumer.go:
MustInitConsumerWorkers一次性注册 evaluation、data、observability 三个模块的 MQ 消费者,分别由各模块的infra/mq/consumer目录提供 Worker 构造逻辑。
值得关注的是,main.go中的基础设施配置全部通过COZE_LOOP_*环境变量注入(如COZE_LOOP_REDIS_DOMAIN、COZE_LOOP_MYSQL_DOMAIN、COZE_LOOP_CLICKHOUSE_DOMAIN、COZE_LOOP_OSS_*等),而log_level、ClickHouse 超时、ID 生成器server_ids等则来自 backend/conf/infrastructure.yaml 中infra配置段,由 viper 配置工厂加载。这形成了"敏感连接信息走环境变量、常规参数走配置文件"的运维约定。
Backend DDD 分层:依赖单向,领域干净
每个modules/<domain>/内部遵循严格的 DDD 分层,目录结构如下(摘自 ARCHITECTURE.md):
modules/<domain>/ ├── application/ # 应用服务(用例编排、Wire DI) │ ├── wire.go # DI 定义 │ └── wire_gen.go # DI 生成代码 ├── domain/ # 领域模型(entity, repo 接口, service) │ ├── entity/ │ ├── repo/ # 仓储接口定义 │ └── service/ ├── infra/ # 基础设施实现(repo 实现, RPC, MQ, storage) │ ├── repo/ # 仓储接口实现 │ ├── mq/ rpc/ storage/ │ └── ... ├── pkg/ # 模块内工具(errno, utils) └── consts/ # 模块常量依赖方向:api/ → application/ → domain/ ← infra/。即 domain 层只定义接口与领域模型,infra 层负责实现(如 MySQL/ClickHouse 的 DAO、RocketMQ 生产者、外部 RPC 客户端),domain 层绝不引用 infra 层。这一约束保证了领域核心可独立测试、不被技术细节污染。
以 backend/modules/prompt/application/wire.go 为例,可以看到 Google Wire 如何将这套分层组织为依赖图:promptDomainSet中既有领域服务(service.NewPromptService、service.NewPromptFormatter),也有仓储接口与 MySQL/Redis 实现(repo.NewManageRepo、mysql.NewPromptBasicDAO、rediscache.NewPromptBasicDAO),还有跨模块 RPC 客户端(rpc.NewLLMRPCProvider、rpc.NewAuthRPCProvider、rpc.NewFileRPCProvider等)。manageSet、executeSet、openAPISet等则分别组合出不同的应用服务入口,最终由wire命令生成wire_gen.go。
模块隔离:不直接互调,在 API 层装配
架构文档强调"模块间不直接互调",而 backend/api/api.go 展示了这一约束的实际落地方式:6 个模块的 handler 在 API 组装层通过loop_gen生成的 Local Service 适配器互相连接。例如:
loauth.NewLocalAuthService(foundationHandler.AuthService)把 foundation 模块的鉴权能力暴露给 prompt / llm / evaluation 等模块;lodataset.NewLocalDatasetService(dataHandler.IDatasetApplication)让 evaluation 模块复用 data 模块的数据集应用服务;lotrace.NewLocalTraceService(observabilityHandler.ITraceApplication)与lotask.NewLocalTaskService(...)以"本地 RPC 客户端"的形式,让 evaluation 模块触发可观测性模块的 trace 查询与任务执行。
模块之间通过接口契约解耦,真正实现"同进程、模块边界仍清晰"的架构效果。api.go的Start函数还展示了 Hertz 服务的关键配置:使用第三方 JSON 序列化器(js_conv)、绑定第三方 JSON Unmarshaler,并将请求体上限设为 20MB。
Backend 技术栈
| 领域 | 选型 |
|---|---|
| HTTP | Hertz(CloudWeGo) |
| RPC | Kitex(CloudWeGo)+ Thrift |
| ORM | GORM(MySQL, ClickHouse) |
| DI | Wire(Google) |
| LLM | Eino |
| 存储 | MySQL(主存储)、ClickHouse(分析查询)、Redis(缓存/锁)、RocketMQ(异步消息) |
其中可观测性模块对 ClickHouse 的依赖尤为突出:在 backend/modules/observability/application/wire.go 中,trace 数据通过ckdao.NewSpansCkDaoImpl/ckdao.NewAnnotationCkDaoImpl落盘 ClickHouse,span 采集链路则由rmqreceiver(RocketMQ 接收)→queueprocessor(队列处理)→clickhouseexporter(ClickHouse 导出)三段式 Collector 构成;任务侧则注册了TaskTypeAutoEval自动评测处理器与StatusCheckTask、LocalCacheRefreshTask两类定时任务,并通过lock.NewRedisLockerWithHolder保证调度互斥。
代码地图:Frontend(frontend/)
前端是由Rush.js 5.172.1管理、pnpm 10.27.0安装依赖的 TypeScript/React 单体仓库,共 59 个包。包被组织为 6 个依赖层级:
| 层级 | 目录 | 包数 | 职责 |
|---|---|---|---|
| Level-6 | apps/cozeloop/ | 1 | 主 SPA(React 18, Rsbuild, react-router, zustand) |
| Level-5 | packages/loop-pages/ | 5 | 页面模块(auth, evaluate, observation, prompt, tag) |
| Level-4 | packages/loop-modules/ | 1 | 高阶业务模块(evaluate) |
| Level-3 | packages/loop-components/ | 13 | UI 组件包 + adapter 模式 |
| Level-2 | packages/loop-base/ | 20 | 基础库(account, api-schema, hooks, components, env, i18n, stores, route...) |
| Level-1 | config/+infra/ | 10+ | 工具链配置 + ESLint 插件 + IDL 转换 |
依赖不变量:高层级只能依赖低层级,禁止反向依赖。这与后端api → application → domain ← infra的单向依赖哲学一脉相承,保证了包图无环、可独立升级。
主 SPA 的组装
frontend/apps/cozeloop/package.json 显示主应用@cozeloop/community-base基于 React 18.2 + react-router 6.22 + zustand 4.4,构建工具为 Rsbuild 2.x,测试框架为 Vitest 3.x,并提供了dev、build、build:prod、lint、test等脚本(开发模式通过REGION=cn CUSTOM_VERSION=inhouse BUILD_TYPE=offline等环境变量区分部署环境)。frontend/apps/cozeloop/src/app.tsx 展示了 SPA 的根组件:CozeLoopProvider统一注入 i18n 与事件上报适配器,Suspense + PageLoading处理路由懒加载,LocaleProvider负责多语言上下文,最后由RouterProvider消费createBrowserRouter(routeConfig)渲染整个应用。
Adapter 模式:解耦商业版与开源版差异
在 Level-3 的loop-components中,平台采用 Adapter 模式隔离商业版与开源版的差异:
adapter-interfaces/ # 接口定义(Level-3) ↑ *-adapter/ # 接口实现(Level-3,按 evaluate/observation 等分) ↑ components-with-adapter/ # 消费者(Level-3)架构不变量:新增商业版/开源版差异必须走 adapter 接口,不可在组件中硬编码条件分支。这使开源版可以替换为 noop 或社区实现,商业版则注入完整实现,组件消费方无需感知差异。
代码地图:IDL(idl/thrift/)
idl/thrift/coze/loop/按模块组织 Thrift 定义:apis/、data/、evaluation/、foundation/、llm/、observability/、prompt/,另有extra.thrift与trajectory.thrift。以 idl/thrift/coze/loop/foundation/coze.loop.foundation.auth.thrift 为例,可以看到 IDL 同时承载接口契约与序列化/校验细节:api.body、api.js_conv、go.tag等注解被分别用于前端路由参数、JavaScript 类型转换和后端 Go 标签生成,255: base.Base/base.BaseResp则统一了公共请求/响应结构。
修改 IDL 后需分别运行两套生成:
- 后端:执行 backend/script/cloudwego/ 下的脚本重新生成 Go 代码(Kitex + Hertz);
- 前端:使用 frontend/infra/idl/ 工具链将 Thrift 转换为 TypeScript 类型。
IDL 是名副其实的"前后端共享契约":一次修改、双端同步,任何一方私自改接口都会在 CI 中被检出。
代码地图:Release(release/)与 Makefile
| 目录 | 内容 |
|---|---|
release/image/ | Dockerfile(主服务, debug, python-faas) |
release/deployment/docker-compose/ | Docker Compose 本地部署 |
release/deployment/helm-chart/ | Helm Chart (Kubernetes 部署) |
根目录 Makefile 将三类部署方式封装为快捷目标,支持从开发到发布的全流程:
- 镜像:
make image--login登录镜像仓库(docker.io/cozedev);make image-<version>用docker buildx build构建并推送 amd64/arm64 双平台镜像;make image-python-faas-bpush-<version>构建 python-faas 镜像。 - Compose:提供
make compose-up(基础服务)、make compose-up-dev(基础 + 开发服务,构建)、make compose-up-debug(调试模式)以及对应的restart-*、down、down-v(含删除卷)系列命令;up时使用--profile "*"拉起全部 profile。 - Helm:
make helm-chart-deps构建 Chart 依赖、make helm-chart-bpush-<version>打包并以 OCI 推送;make helm-up以--install --force方式部署到coze-loop命名空间;另有helm-ctx、helm-ns、helm-pod、helm-svc、helm-ingress、helm-logf-<app>、helm-tpl-<app>等集群巡检与日志/模板调试目标;make minikube-start/make minikube-tunnel则用于本地 minikube(含 ingress addon)验证。
横切关注点:代码生成
仓库把"生成代码提交入库"作为统一策略——生成结果直接写入kitex_gen/、loop_gen/与各模块wire_gen.go,任何人在 CI 中均可复现校验。四类生成物如下:
| 生成物 | 触发方式 | 输入 |
|---|---|---|
kitex_gen/ | backend/script/cloudwego/ | idl/thrift/ |
loop_gen/ | 相关脚本 | IDL / schema |
wire_gen.go | 各 moduleapplication/目录下执行wire | wire.go |
router_gen.go | Hertz 代码生成 | 路由定义 |
以 backend/script/cloudwego/kitex_tool.sh 为例,生成流水线分为三步:先遍历idl/thrift/下所有.thrift,对含service的文件执行cloudwego_kitex -streamx -thrift ignore_initialisms=false -thrift-plugin validator -deep-copy-api=true生成 Kitex 代码,再执行cloudwego_hz model生成 Hertz 模型,随后运行loopgen生成以lo为前缀的本地服务适配层(输出到loop_gen/),最后将产物整体移动到backend/kitex_gen与backend/loop_gen并自动提交(NO_PUSH_REMOTE=true可跳过推送)。backend/script/cloudwego/code_gen.sh 则是入口脚本:先执行install.sh安装工具链,再依次运行kitex_tool.sh与hertz_tool.sh。此外,backend/script/gorm_gen/generate.go 负责 GORM DAO 生成,backend/script/errorx/ 则基于各模块 YAML 定义(如evaluation.yaml、observability.yaml)生成错误码体系。
横切关注点:CI/CD
.github/workflows/下共有 10 个工作流,覆盖后端、前端、IDL、Schema、PR 规范与 License 等多个维度:
| 工作流 | 触发 | 作用 |
|---|---|---|
backend-ci.yaml | PR (backend/**) | Go test + lint + Codecov |
frontend-ci.yaml | PR (frontend/**) | Rush build + Vitest + lint |
frontend-tsc-ci.yaml | PR (frontend/**) | TypeScript 类型检查 |
idl.yaml | PR (idl/**) | IDL 变更检查 |
mysql-schema-check.yaml | PR | 数据库 schema 变更检查 |
semantic-pull-request.yaml | PR | PR 标题规范检查 |
license-check.yaml | PR | License 合规检查 |
ai-cr-required.yaml | PR | AI 代码评审 |
issue-sync.yaml/pr-sync.yaml | issue/PR | 仓库协作自动化 |
以 .github/workflows/backend-ci.yaml 为例,后端 CI 在ubuntu-latest上安装Go 1.24.0,先运行 golangci-lint(v2.2.1,配置为../.github/.golangci.yaml),再执行go build -v ./...与带-race的单元测试,并将覆盖率上传 Codecov。.github/workflows/frontend-ci.yaml 使用 Node 24,通过install-run-rush.js install安装依赖、rush rebuild全量构建,再以rush increment --action lint/style对变更文件做增量 lint 与样式检查(并缓存 pnpm store 加速)。.github/workflows/idl.yaml 则对所有 Thrift 文件逐一执行kitex -streamx语法校验,确保任何 IDL 变更在合入前都是可生成的。此外,semantic-pull-request.yaml强制 PR 标题符合 Conventional Commits 规范,mysql-schema-check.yaml关注数据库 schema 变更的合规性。
横切关注点:Git Hooks(common/git-hooks/)
Git Hooks 由 Rush 统一管理,包含pre-commit、commit-msg、pre-push、post-checkout、post-commit、post-merge六个钩子,配合common/autoinstallers/下的rush-commitlint、rush-lint-staged等插件,在本地提交阶段就完成提交信息规范检查与暂存区 lint-staged 校验,与远端 CI 形成"本地先拦截、远端再兜底"的双重防线。具体接入与使用方式详见 CONTRIBUTING.md。
小结:架构约束即协作契约
coze-loop 的架构价值不在于某一项技术选型,而在于它把"约束"写进了目录结构与 CI:后端domain ← infra的单向依赖、前端 Level 层级禁止反向引用、商业版/开源版差异只走 Adapter、生成代码禁止手改且必须入库、IDL 变更必须双端重新生成——每一条都能在源码与工作流中找到对应落地。理解了这套架构地图,无论是新增一个业务模块、修改一个 Thrift 接口,还是本地起一套 Docker Compose 环境,都能沿着明确的边界行事,而不至于破坏整体一致性。
- 人工智能
- 大模型
- AI Agent
- 提示工程
- AI 评测
- 可观测性
- 后端
- 前端
【免费下载链接】coze-loop
Next-generation AI Agent Optimization Platform: Cozeloop addresses challenges in AI agent development by providing full-lifecycle management capabilities from development, debugging, and evaluation to monitoring.
相关推荐
Yokai框架完整指南:构建简单、模块化且可观测的Go后端应用
Yokai框架完整指南:构建简单、模块化且可观测的Go后端应用 Yokai是一个简单、模块化且可观测的Go框架,专门用于构建生产级的后端应用程序。它让开发者能够
OpenObserve架构演进:从单体到分布式可观测性平台的完整指南
OpenObserve架构演进:从单体到分布式可观测性平台的完整指南 OpenObserve是一款高性能、低成本的可观测性平台,作为Elasticsearch/
可观测性日志分析指标监控链路追踪后端云原生终极指南:如何用OpenObserve构建统一可观测性数据平台
终极指南:如何用OpenObserve构建统一可观测性数据平台 OpenObserve是一个高性能、低成本的可观测性平台,作为Elasticsearch/Spl
可观测性日志分析指标监控链路追踪后端云原生
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考