BISHENG 多租户管理视图切换(Admin Scope)机制详解:Redis 滑动 TTL、管理类 API 过滤与 Celery 巡检的完整实现
2026/9/15 11:11:18 网站建设 项目流程

BISHENG 多租户管理视图切换(Admin Scope)机制详解:Redis 滑动 TTL、管理类 API 过滤与 Celery 巡检的完整实现

【免费下载链接】bishengBISHENG is an open LLM devops platform for next generation Enterprise AI applications. Powerful and comprehensive features include: GenAI workflow, RAG, Agent, Unified model management, Evaluation, SFT, Dataset Management, Enterprise-level System Management, Observability and more.项目地址: https://gitcode.com/GitHub_Trending/bi/bisheng

导读

本文围绕 BISHENG v2.5.1 的 F019-admin-tenant-scope(管理视图切换 / Admin Scope)功能,完整讲解"全局超管临时切换到某个 Child Tenant 管理视角"的机制设计、API 契约、Service 实现、中间件注入、Celery 巡检与全量验收(AC)映射。读完本文,你将掌握该机制为何选 Redis 而非 JWT、4 小时滑动 TTL 如何在每次管理类 API 命中时刷新、scope 为何只作用于管理类 API 白名单、以及登出/主部门变更/角色撤销/租户禁用四类生命周期事件如何清理 scope。所有结论均可在当前仓库源码中逐一验证。


1. 功能背景:为什么需要"管理视图切换"

1.1 问题:跨 Child 管理缺少上下文

在 v2.5.1 的 Tenant 树形架构下,集团 IT 的全局超管需要跨 Child Tenant 管理资源,尤其是各 Child 专属的 LLM 模型、角色、配额和审计日志。原方案POST /api/v1/user/switch-tenant在 2026-04-20 收窄中已废弃(返回 410 Gone),理由是:用户归属由主部门派生,不应由 JWT 随意切换(见 spec.md §1 与 §3)。

F019 提供的是一套语义完全不同的机制——管理视图切换(Admin Scope)

  • Redis 驻留,非 JWT;
  • 仅限全局超管使用;
  • 仅对管理类 API 生效;
  • 与用户归属完全解耦。

1.2 核心用户故事

作为集团 IT 的全局超管,我希望临时切换到某个 Child Tenant 的管理视角(查看/配置该 Child 专属的 LLM 模型、角色、配额、审计日志),以便跨 Child 管理时有明确的上下文,而不需要登出/重登或改动自己的用户归属。

1.3 仓库落地位置

  • 需求与验收标准:features/v2.5.1/019-admin-tenant-scope/spec.md
  • AC 对照与回归验证:features/v2.5.1/019-admin-tenant-scope/ac-verification.md
  • 角色撤销钩子调研:features/v2.5.1/019-admin-tenant-scope/role-revoke-hook.md

2. 架构决策:7 项 AD 及其理由

spec §4 给出了 7 项关键架构决策,ac-verification.md 的"架构决策(§4 AD-01~07)落地证据"表逐一核对了它们在当前仓库中的实现:

ID决策结论落地证据(仓库路径)
AD-01存储介质Redis(非 JWT、非 MySQL)tenant_scope.py 只读写admin_scope:{user_id}key,JWT 签名逻辑未改动
AD-02TTL 策略滑动刷新(非固定)admin_scope.py 每次管理类 API 命中调aexpire_key
AD-03TTL 长度4h(对比 1h/8h 折衷)multi_tenant.pyadmin_scope_ttl_seconds=14400
AD-04scope 作用域仅管理类 API 白名单admin_scope.pyMANAGEMENT_API_PREFIXES
AD-05适用角色仅全局超管Endpoint 层_check_is_global_super守卫 + Middleware 层 fail-closed 再校验
AD-06非超管调用处理403 拒绝(非静默忽略)AdminScopeForbiddenError(Code=19701)→ HTTP 403
AD-07Child 禁用后清理Celery 巡检(非实时钩子)tasks.py + beat*/10 * * * *

其中 AD-07 的权衡值得注意:若在 Tenant 禁用/归档的热路径上同步扫描 Redis 清理 scope,会拖慢禁用操作本身;选择 Celery 每 10 分钟巡检,换来的是"最大不一致窗口 ≤ 10 分钟"的折衷(spec §3 边界情况、AC-13)。


3. 16 条验收标准(AC)全景

spec §2 定义了 16 条验收标准,ac-verification.md 将全部 16 条映射到了自动化测试与手工 QA 清单:

AC描述要点预期结果
AC-01超管 POST{tenant_id: 5}200 +scope_tenant_id=5+ Redis TTL≈14400
AC-02超管 GET200 +{scope_tenant_id, expires_at}(ISO 格式 + 剩余 TTL)
AC-03POST{tenant_id: null}200 + Redis DEL + 后续 GET 返 null
AC-04 / AC-05Child Admin / 普通用户 POSTHTTP 403 + 错误码 19701
AC-06已设 scope=5 调管理类 API(如/llm结果按tenant_id IN (5, 1)过滤
AC-07已设 scope=5 调业务 API(如/chat不受影响,按 JWT leaf 执行
AC-084h 内持续调用管理类 APIRedis TTL 滑动刷新,scope 不过期
AC-09超过 TTL 未调用Redis 自然过期,回退"看全树"
AC-10logoutRedis DELadmin_scope:{user_id}
AC-11user.token_version +1(主部门变更)钩子 DEL Redis key
AC-12超管角色被撤销钩子 DEL(当前无公开撤销 API,由中间件 fail-closed 兜底)
AC-13Child 被禁用/归档/删除Celery 每 10 分钟清理指向非 active Tenant 的 key
AC-14每次 POSTaudit_log,action=admin.scope_switch,含 from/to_scope、ip、user_agent、operator_id
AC-15tenant_id 指向不存在 TenantHTTP 400 + 错误码 19702
AC-16tenant_id=1(Root)允许,等价"锁定看 Root 视图"(IN 列表 ={1}

3.1 AC-16 的一个易混淆点

AC-16 与"不设 scope"有行为差异,spec §2 特别说明:

  • 显式设 scope=1:管理类 API 的可见集合 IN 列表 ={1}只看到 Root 自身
  • 不设 scope:可见集合 = None,看到全树(全部 Child)

4. API 契约与错误码

4.1 端点定义

模块编码197admin_scope),共两个端点,定义在 tenant_scope.py:

POST /api/v1/admin/tenant-scope 设置或清除当前调用者的 scope GET /api/v1/admin/tenant-scope 读取当前 scope 与剩余 TTL

请求体为{tenant_id: int | null}(pydantic 模型SetScopeRequesttenant_id可空)。

4.2 错误码(spec §5)

错误码定义在 admin_scope.py:

错误码错误类HTTP 状态触发位置
19701AdminScopeForbiddenError403Endpoint_check_is_global_super失败
19702AdminScopeTenantNotFoundError400Serviceset_scope校验 tenant_id 不存在时抛出

Endpoint 层维护_ERRCODE_HTTP_STATUS映射,通过_errcode_to_response将结构化错误码翻译为真实 HTTP 403/400 响应体,遵循 F018 的先例。

4.3 超管识别细节

spec 声明依赖 F013 的LoginUser.is_global_super(),但该公开方法在落地时未随 F013 交付。F019 的 Endpoint 与中间件统一复用bisheng.utils.http_middleware._check_is_global_super(user_id)——同一套 FGA 查询 + Redis 缓存逻辑,保证全栈判定一致(见 tenant_scope.py 模块 docstring 与 ac-verification.md"开发实际偏差")。这是 F013 合约缺口的临时补丁,F020 落地时可一并抽公共 helper。


5. Service 层:Redis 读写与审计日志

核心实现位于 tenant_scope.py,Redis key 模板为admin_scope:{user_id}

5.1 set_scope:设置 / 覆盖 / 清除

key = _redis_key(user_id) # admin_scope:{user_id} old_raw = await redis.aget(key) # 读旧值(用于 audit from_scope) old_scope = int(old_raw) if old_raw else None if tenant_id is None: await redis.adelete(key) # AC-03:清除 expires_at = None else: if not await TenantDao.aexists(tenant_id): # AC-15:先校验存在 raise AdminScopeTenantNotFoundError() # 19702 ttl = settings.multi_tenant.admin_scope_ttl_seconds await redis.aset(key, str(tenant_id), expiration=ttl) # 值存字符串 expires_at = _iso_expiry(ttl)

要点:

  • 校验顺序:先查TenantDao.aexists(tenant_id)再写 Redis,不存在直接抛 19702(AC-15);
  • 值类型:Redis 里存的是str(tenant_id),读取时再int()还原;
  • 过期时间expires_at_iso_expiry生成 ISO-8601 UTC 时间戳返回给前端展示。

5.2 audit_log:每次切换留痕(AC-14)

每次 POST 都会写一条audit_log,action 使用TenantAuditAction.ADMIN_SCOPE_SWITCH(定义于bisheng/tenant/domain/constants.py),metadata 含:

{ "from_scope": 3, // 旧 scope(首次为 null) "to_scope": 5, // 新 scope "ip": "192.168.x.x", "user_agent": "curl/8.x" }

operator_tenant_id硬编码为ROOT_TENANT_ID(1):因为调用者必然是全局超管(Endpoint 层已强制),且 INV-T11 保证 Root 是唯一恒存在的 Tenant(spec §5.2 注释说明"硬编码 1 避免查库")。

5.3 get_scope:精确剩余 TTL

raw = await redis.aget(key) if raw is None: return {'scope_tenant_id': None, 'expires_at': None} ttl = await redis.attl(key) # 新增基础设施方法 if ttl is None or ttl < 0: expires_at = None # key 无 TTL(-1) 或不存在(-2) else: expires_at = _iso_expiry(ttl) return {'scope_tenant_id': int(raw), 'expires_at': expires_at}

注意:RedisClient.attl是 F019 为精确读取剩余 TTL 而新增的一行封装(async_connection.ttl(key)),属于通用基础设施扩展,非 F019 专有(见 ac-verification.md"开发实际偏差")。

5.4 生命周期清理钩子

Service 暴露三个幂等 DEL 钩子:

钩子调用方对应 AC
clear_on_logoutAuthService.logout(bisheng/user/api/user.pyAC-10
clear_on_token_version_bumpUserTenantSyncService.sync_user 主部门变更成功后AC-11
clear_on_role_revoke未来 RoleService 撤销超管角色时AC-12(当前未挂接,见 §8)

三个钩子统一委托_clear(user_id)执行redis.adelete(key),天然幂等。


6. 中间件:ContextVar 注入与滑动 TTL

中间件 admin_scope.py 是 scope 生效的核心消费点。

6.1 白名单(AD-04)

MANAGEMENT_API_PREFIXES: tuple[str, ...] = ( '/api/v1/llm', '/api/v1/workstation', '/api/v1/linsight', '/api/v1/tool', '/api/v1/knowledge', '/api/v1/chat/online', '/api/v1/admin', )

与 spec 初稿相比有一处值得注意的收窄:v2.5.1 原计划包含/api/v1/roles/api/v1/audit_log,但产品评审结论是——角色使用"全局视图 + 字段过滤"模式,审计日志对超管天然全局、对 Child Admin 天然按visible_tenant_ids子树收敛,均无需 scope 切换;且/api/v1/audit_log字面量本就是死代码(真实路由前缀是/api/v1/audit)。最终 scope 只影响 LLM 管理面及设置它的 admin 端点本身(中间件注释明确记载了这一决策过程)。代码注释强调:白名单"刻意保守",给整个 API 面套上 scope 会改变 chat、workflow 执行、知识库摄取等业务流。

6.2 注入与滑动刷新逻辑

dispatch流程(对应 AC-06/07/08/09):

  1. 判断is_mgmt并写入_is_management_apiContextVar;
  2. 非管理类 API 直接放行——不解 JWT、不读 Redis、不做 FGA 检查,热路径零额外开销(AC-07,spec §3 边界情况);
  3. 管理类 API:解 JWT 取user_id_check_is_global_super校验;
  4. 非超管 fail-closed:即使 Redis 里残留 scope key 也不读取,防止"非超管被代理进 scope 视图"(spec §3 边界情况:非超管误设 scope,Redis key 虽写入但中间件仅为超管读取);
  5. admin_scope:{user_id},非空则set_admin_scope_tenant_id(int(raw))注入 ContextVar(由 F012 §5.4 在core/context/tenant.py定义,本 Feature 消费而非定义);
  6. 滑动刷新:调redis.aexpire_key(key, settings.multi_tenant.admin_scope_ttl_seconds)刷新 TTL(AC-08);TTL 更新失败不阻塞请求(fail-open + 仅记 debug 日志)。

6.3 注册顺序(关键细节)

中间件在 main.py 中于CustomMiddleware之前添加,使其入站顺序在 Custom 之后成为运行时内层中间件——即 CustomMiddleware 先解码 JWT 并填充visible_tenant_idsContextVar,AdminScopeMiddleware 的dispatch在其后执行。这一顺序是 6.2 中"解 JWT → 校验超管 → 注入 scope"能工作的前提。

6.4 Redis 竞态与失败语义

spec §3 明示了两类边界行为:

  • TTL 临界点竞态:两个并发请求可能一个读到 scope、一个读到 None;不做跨请求事务,UI 下次刷新即恢复;
  • Redis 故障 fail-open:中间件对 Redis 读失败、超管校验异常均放行并记 debug 日志,避免中间件故障拖垮整条请求链。

7. Celery 巡检任务:清理失效 scope(AC-13)

任务定义在 tasks.py,beat schedule 在 settings.py 注册为*/10 * * * *(每 10 分钟)。

7.1 执行流程

@bisheng_celery.task(acks_late=True, time_limit=600, soft_time_limit=540, name='bisheng.worker.admin_scope.tasks.admin_scope_cleanup') def admin_scope_cleanup(): run_async_task(_cleanup_async) async def _cleanup_async(): redis = await get_redis_client() keys = await redis.akeys('admin_scope:*') if not keys: return # 快速路径:无 key 直接跳过 DB 查询 with bypass_tenant_filter(): # 关键:跨 Tenant 查询必须 bypass non_active = set(await TenantDao.aget_non_active_ids()) if not non_active: return for key in keys: # 读取值 → int() 解析(解析失败视为损坏值直接 DEL) # scope_id in non_active → DEL

7.2 两个必须知道的实现细节

  1. bypass_tenant_filter()包裹:Celery worker 进程没有 HTTP 请求上下文,current_tenant_idContextVar 为 None。若不做 bypass,SQLAlchemy 自动注入的 tenant_filter 事件在current_tenant_id=None时行为未定义(可能过滤为空结果或抛TenantContextMissing)。任务 docstring 与 spec §5.4 均特别强调了这一点。
  2. 快速路径优化admin_scope:*无 key 时连 DB 查询都跳过;non_active为空时也提前返回,避免空转。

7.3 与 AC-12 的配合

AC-13 覆盖的是"租户状态变化"(禁用/归档/孤儿/删除,status IN (disabled, archived, orphaned));AC-12 覆盖的是"角色撤销"。二者共同保证 stale key 的最终收敛,中间件 fail-closed 则在两个事件窗口内兜底。


8. 角色撤销钩子:AC-12 的现实处理

ac-verification.md"开发实际偏差"与 tenant_scope.py docstring 都记载了同一结论:

  • TenantScopeService.clear_on_role_revoke方法已就位但未挂接
  • 原因:调研发现system:global#super_admin当前无公开撤销 APIuser_addrole/user_delete都显式拒绝操作超管);
  • AC-12 的可观察行为由中间件_check_is_global_super每请求再校验兜底——即使 Redis 残留了 scope key,已撤销超管角色的用户也无法获得 scope 注入;
  • 未来 RoleService 落地撤销 API 时,只需 3 行接入(详见 role-revoke-hook.md)。

这是"方法就位 + 中间件兜底 + 文档化 TODO"的典型渐进落地模式,代码中以TODO(#F019-role-revoke)标注。


9. 配置项

# config.yaml → multi_tenant 段 multi_tenant: admin_scope_ttl_seconds: 14400 # 默认 4h 滑动 TTL

配置模型定义在 multi_tenant.py,pydanticField(default=14400),注释明确"Sliding refresh on each management API hit. Default 4h."。该值同时被 Service(set_scope写 key 时设置过期)与中间件(滑动刷新)消费。


10. 手工 QA:16 个场景的完整 curl 演练

ac-verification.md 提供了基于 114 环境的完整手工验证清单,以下为可直接执行的验证脚本(前置要求:全局超管账号 + ≥1 个 Child Tenant)。

10.1 登录与设置(AC-01)

# 以 admin 登录取 Cookie curl -b jar -c jar -X POST http://<host>:7860/api/v1/user/login \ -H 'Content-Type: application/json' \ -d '{"user_name": "admin", "password": "Bisheng@top1"}' # POST scope=5 curl -b jar -X POST http://<host>:7860/api/v1/admin/tenant-scope \ -H 'Content-Type: application/json' -d '{"tenant_id": 5}' # 期望:200,body.data.scope_tenant_id=5,body.data.expires_at≠null

10.2 读取(AC-02)与清除(AC-03)

curl -b jar http://<host>:7860/api/v1/admin/tenant-scope # 期望:200,body.data.scope_tenant_id=5 # 清除 curl -b jar -X POST http://<host>:7860/api/v1/admin/tenant-scope \ -H 'Content-Type: application/json' -d '{"tenant_id": null}' curl -b jar http://<host>:7860/api/v1/admin/tenant-scope # 期望:后续 GET 返 {scope_tenant_id: null, expires_at: null}

10.3 权限拒绝(AC-04/AC-05)

# 以 Child Admin 登录 → POST /admin/tenant-scope → HTTP 403 + status_code=19701 # 以普通用户登录 → POST /admin/tenant-scope → HTTP 403 + status_code=19701

10.4 滑动 TTL(AC-08)与自然过期(AC-09)

# scope=5 → 等 3 分钟 → GET /api/v1/llm(命中中间件) # redis-cli TTL admin_scope:1 → 预期刷新回 > 14000 # 快速模拟过期(等价语义): redis-cli DEL admin_scope:1 # 再 GET → 回退(ContextVar=None)

10.5 登出清理(AC-10)

curl -b jar -X POST http://<host>:7860/api/v1/admin/tenant-scope \ -H 'Content-Type: application/json' -d '{"tenant_id": 5}' curl -b jar -X POST http://<host>:7860/api/v1/user/logout # redis-cli EXISTS admin_scope:1 → 期望 0

10.6 主部门变更清理(AC-11)

# 手工调 POST /api/v1/departments/... 变更超管主部门(跨 Tenant) # → UserTenantSyncService.sync_user 执行 → redis-cli EXISTS admin_scope:1 → 0

10.7 中间件兜底(AC-12 可观察行为)

# 模拟非超管的 stale key: redis-cli SET admin_scope:999 5 # 以 user_id=999 普通用户登录,调 GET /api/v1/llm # 中间件 _check_is_global_super 返 False → 不注入 scope

10.8 Celery 巡检(AC-13)

# 1. scope=5 后禁用 Child 5:PUT /api/v1/tenants/5/status {status: 'disabled'} # 2. 等 10 分钟(或手动触发 celery beat admin_scope_cleanup) # 3. redis-cli EXISTS admin_scope:1 → 期望 0

10.9 审计日志(AC-14)

SELECT id, tenant_id, operator_id, operator_tenant_id, action, audit_metadata FROM audit_log WHERE action='admin.scope_switch' ORDER BY id DESC LIMIT 5; -- 最新一行 metadata 含 from_scope / to_scope / ip / user_agent

10.10 不存在的 Tenant(AC-15)与 Root(AC-16)

curl -b jar -X POST http://<host>:7860/api/v1/admin/tenant-scope \ -H 'Content-Type: application/json' -d '{"tenant_id": 99999}' # 期望:HTTP 400 + body.status_code=19702 curl -b jar -X POST http://<host>:7860/api/v1/admin/tenant-scope \ -H 'Content-Type: application/json' -d '{"tenant_id": 1}' # 期望:200 + scope_tenant_id=1(ContextVar 注入后,管理类 API 见集合 = {1})

11. 自动化测试:37/37 全通过

ac-verification.md 记录了 F019 新增的 6 个测试文件、37 个用例全部通过,与 16 条 AC 一一对应:

测试文件用例数覆盖 AC
test_admin_tenant_scope_service.py10Service 单测(含 AC-01/02/03/14/15 等)
test_admin_tenant_scope_api.py9HTTP 集成(403/400 映射)
test_admin_scope_middleware.py8中间件注入与滑动刷新
test_logout_scope_clear.py3AC-10(AST 源码检查 + Service 行为)
test_sync_user_scope_clear.py3AC-11 钩子
test_admin_scope_cleanup_task.py4AC-13 Celery 巡检

回归结果:F012 71/71、F011/F013 53/53 全部通过;其余失败均为预存 flakiness(permission_enrichment / role_service / f017_chat_message_service 在 2.5.0-PM baseline 相同失败,minimax_provider 1 条预存内容 mismatch),非 F019 引入。

11.1 回归命令

# 单独 F019 专项 cd src/backend && uv run pytest \ test/test_admin_tenant_scope_service.py \ test/test_admin_tenant_scope_api.py \ test/test_admin_scope_middleware.py \ test/test_logout_scope_clear.py \ test/test_sync_user_scope_clear.py \ test/test_admin_scope_cleanup_task.py -v # 全量回归 cd src/backend && uv run pytest -q

11.2 开发过程中的三个测试偏差(值得借鉴)

ac-verification.md"开发实际偏差"记录了三个务实的测试工程决策:

  1. _FakeRedis替代真实 pickle 往返:Service 层与真实实现的契约是"存str(tenant_id),读出来同值",测试以 mock 的 aget/aset 为准,pickle 行为由 F012 的 Redis 同异步测试矩阵覆盖;
  2. logout 测试改 AST 源码检查 + Service 行为测试:原计划 importlib 动态导入bisheng.user.api.user,但该模块在测试环境下有 import chain 脆性(conftest pre-mock 后子模块 import 失败 + FastAPI response-model validation error),改为 AST 读源码断言钩子存在 + 重新验证 Service DEL 行为,语义等价且更抗未来 import chain 变化;
  3. Celery 测试 importlib 路径派生:从__file__.resolve().parent.parent派生而非 hard-code 路径,支持任意 checkout root。

12. 遗留事项与后续依赖

ac-verification.md 与 spec §9/§10 共同交代了本功能的边界与后续:

  • AC-12 挂接点clear_on_role_revoke方法已就位,等未来 RoleService 落地撤销 API 时 3 行接入;
  • F019 → F020 依赖:前端useAdminScopehook +AdminScopeSelector组件归 F020 拥有(本 Feature 仅提供src/frontend/platform/src/controllers/API/admin.ts中的setTenantScope/getTenantScopeaxios 封装);AC-06 真正的"GET /api/v1/llm 结果按 IN(5,1) 过滤"需 F020 的LLMDaotenant 感知改造到位后联调;
  • Out of Scope:Redis key 可观测性仪表盘、scope 历史查询 API(audit_log 已含,MVP 不单独建表)、跨实例 scope 同步(bisheng 私有化部署单实例即可)、自动按"上次操作的 Child"预置 scope(避免魔法行为)。

13. 关键文件速查

类别文件说明
API 端点tenant_scope.pyPOST/GET 两个端点 + errcode→HTTP 映射
Servicetenant_scope.pyset_scope/get_scope/clear_on_logout/clear_on_token_version_bump/clear_on_role_revoke
中间件admin_scope.py白名单 + 超管 fail-closed + 滑动刷新
Celery 任务tasks.pybypass_tenant_filter包裹 + 快速路径
错误码admin_scope.py19701 / 19702
配置multi_tenant.pyadmin_scope_ttl_seconds=14400
beat 注册settings.py*/10 * * * *巡检调度
Redis 基础设施redis_conn.pyattl/aexpire_keyhelper
前端 API 封装admin.tssetTenantScope/getTenantScope
设计文档spec.md需求、AC、架构决策、实现骨架
AC 对照ac-verification.md16 条 AC 映射、手工 QA、回归结果
调研笔记role-revoke-hook.mdT10 方案 2 调研

总结

F019 Admin Scope 以"Redis 驻留、非 JWT、仅超管、仅管理类 API"四个约束,在不动用户归属的前提下为全局超管提供了跨 Child 的管理视图切换能力。其设计精髓在于:Redis 滑动 TTL 平衡安全与体验(4h)白名单限定作用域避免污染业务热路径三层清理(登出/主部门变更/角色撤销钩子 + Celery 巡检 + 中间件 fail-closed 兜底)保证 stale key 最终收敛。从 spec 到 AC 对照表再到源码,16 条验收标准、37 个自动化用例与 7 项架构决策在仓库中全部有据可查,是一套可直接复用的多租户管理上下文设计范本。

【免费下载链接】bishengBISHENG is an open LLM devops platform for next generation Enterprise AI applications. Powerful and comprehensive features include: GenAI workflow, RAG, Agent, Unified model management, Evaluation, SFT, Dataset Management, Enterprise-level System Management, Observability and more.项目地址: https://gitcode.com/GitHub_Trending/bi/bisheng

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询