ai-server(AI 服务)

内部 AI 能力服务

统一发布场景,稳定交付给业务应用调用

平台把供应商密钥、模型配置、场景实现版本、输出结构校验和调用日志留在后端, 业务应用只通过 App Token 调用已发布的场景接口。

ai-server(AI 服务)调用链路图
业务应用只调用内置 scenario,provider、model、Prompt 和 Schema 由平台管理。
管理后台 http://localhost:5200
业务调用路径 POST /api/v1/scenarios/{scenario_key}/invoke
认证方式 Authorization: Bearer App Token

工作流

从模型配置到业务调用

V1 聚焦内置 AI 场景。管理员配置供应商和模型,发布场景实现版本,再把 App Token 和动态接口文档交给一方业务应用。

1

配置供应商

在后台保存 provider base URL、类型和 API key。密钥只进入后端加密存储,不暴露给浏览器或业务应用。

2

注册模型

登记模型名称、展示名、temperature、top_p、max_tokens 和能力标记,包括文本、图片和 JSON 输出能力。模型测试请求由后端代理执行。

3

发布实现

为内置场景创建实现版本,选择模型并配置 Prompt 模板;请求体、输出 Schema 和 mock 输出由代码固定。

4

交付应用

创建 App Client,授权可调用场景,生成只展示一次的 App Token,并复制动态接口文档给业务应用。

接入方式

业务应用接入方式

业务应用只能调用授权场景,不能覆盖 provider、model、Prompt 模板、输出 Schema 或默认模型参数。

统一调用协议

  • 接口路径固定为 /api/v1/scenarios/{scenario_key}/invoke
  • 请求体由每个内置场景固定定义。
  • 场景 mock 开启时直接返回代码内置 mock 输出。
  • 响应中的 output 已按场景输出 JSON Schema 校验。
  • 失败时记录 request_id,用于后台调用日志排查。
curl "${AI_PLATFORM_BASE_URL}/api/v1/scenarios/clothing-attributes/invoke" \
  -H "Authorization: Bearer ${AI_PLATFORM_APP_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "image": {
      "url": "http://localhost:9000/closet-media/closet/users/user_1/clothing/item_001/front.jpg",
      "bucket": "closet-media",
      "object_key": "closet/users/user_1/clothing/item_001/front.jpg"
    },
    "item_name": "粉色连帽上衣"
  }'

动态接口文档

每个 App Client 的动态文档由后台按当前授权场景生成。进入管理后台的“应用令牌”页面,点击目标应用的“接口文档”,复制 Markdown 后交付给业务方。

材料 来源 交付边界
App Token 管理后台创建令牌时一次性展示 只交给业务服务端,不进入前端、小程序、移动端或公开仓库
场景接口文档 应用令牌列表的“接口文档”按钮 包含可调用场景、输入输出 Schema、示例请求和错误码
后台管理员账号 CloudBase Run 环境变量 只供平台管理员使用,不交给业务应用

接口契约

六个业务场景接口说明

六个能力都复用同一个调用通路。业务方只传场景专属结构化入参;模型、Prompt 模板、temperature、top_p、max_tokens、mock 开关和发布版本都由管理后台控制。

统一请求 POST /api/v1/scenarios/{scenario_key}/invoke
统一鉴权 Authorization: Bearer <App Token>
统一响应外壳 { request_id, status, schema_valid, output, provider, model, latency_ms }

1. 衣物识别 / 搭配特征提取

scenario_key: clothing-attributes

图片输入

识别衣物基础信息,并额外提取可用于后续智能搭配的结构化特征和文本摘要。后续搭配接口应传衣物特征值,不传衣物图片。

入参

{
  "image": {
    "url": "http://localhost:9000/closet-media/closet/users/user_1/clothing/item_001/front.jpg",
    "bucket": "closet-media",
    "object_key": "closet/users/user_1/clothing/item_001/front.jpg",
    "mime_type": "image/jpeg",
    "metadata": { "name": "front.jpg", "size": 238912 }
  },
  "item_name": "粉色上衣"
}

出参

{
  "name": "粉色短袖连帽针织上衣",
  "brand": null,
  "color": "粉色",
  "price": null,
  "style": "甜美",
  "season": "春夏",
  "material": null,
  "attributes": { "sleeve": "短袖", "hooded": true },
  "category_1": "上衣",
  "category_2": "卫衣",
  "confidence": 0.95,
  "match_features": {
    "wearing_slot": "upper",
    "color_family": "pink",
    "style_tags": ["甜美", "休闲"],
    "occasion_tags": ["日常", "约会"],
    "season_tags": ["春", "夏"],
    "versatility_score": 0.72,
    "matching_keywords": ["浅色", "甜美", "春夏"]
  },
  "matching_summary": "粉色短袖连帽针织上衣,适合春夏日常或约会,风格甜美休闲。"
}

2. 试穿

scenario_key: virtual-try-on

图片输入

根据人物图和一件或多件衣物图生成试穿结果。新接入建议使用 garments 数组;旧版单件 garment_image 仍兼容。

入参

{
  "person_image": {
    "url": "http://localhost:9000/closet-media/closet/users/user_1/try-on/person.jpg",
    "bucket": "closet-media",
    "object_key": "closet/users/user_1/try-on/person.jpg",
    "mime_type": "image/jpeg",
    "metadata": { "name": "person.jpg" }
  },
  "garments": [
    {
      "slot": "upper",
      "image": {
        "url": "http://localhost:9000/closet-media/closet/users/user_1/try-on/top.jpg",
        "bucket": "closet-media",
        "object_key": "closet/users/user_1/try-on/top.jpg",
        "mime_type": "image/jpeg",
        "metadata": { "name": "top.jpg" }
      }
    },
    {
      "slot": "lower",
      "image": {
        "url": "http://localhost:9000/closet-media/closet/users/user_1/try-on/bottom.jpg",
        "bucket": "closet-media",
        "object_key": "closet/users/user_1/try-on/bottom.jpg",
        "mime_type": "image/jpeg",
        "metadata": { "name": "bottom.jpg" }
      }
    }
  ]
}

出参

{
  "generated_image": {
    "object_key": "scenario-debug/virtual-try-on/mock-output.png",
    "url": null,
    "mime_type": "image/png",
    "metadata": { "source": "mock" }
  },
  "status": "succeeded",
  "description": "虚拟试穿 mock 结果",
  "metadata": { "mode": "mock" }
}

3. 文字找衣

scenario_key: text-to-clothing-filters

文本推理

把用户自由文本解析成前端搜索框可回填的筛选条件。返回值应尽量从 filter_options 中选择,不凭空创造前端不可用的筛选值。

入参

{
  "text": "我想找一件春天通勤穿的浅色上衣",
  "filter_options": {
    "wearing_slot": ["upper", "lower", "outerwear", "dress", "shoes", "accessory"],
    "colors": ["黑色", "白色", "粉色", "蓝色", "米色", "灰色"],
    "style_tags": ["通勤", "休闲", "甜美", "运动", "复古"],
    "season_tags": ["春", "夏", "秋", "冬"],
    "category_1": ["上衣", "下装", "外套", "连衣裙", "鞋子", "配饰"],
    "category_2": ["衬衫", "T恤", "卫衣", "牛仔裤", "半身裙"]
  }
}

出参

{
  "selected_filters": {
    "wearing_slot": ["upper"],
    "colors": ["白色", "米色"],
    "style_tags": ["通勤"],
    "season_tags": ["春"],
    "category_1": ["上衣"],
    "category_2": []
  },
  "query_summary": "春天通勤浅色上衣",
  "unmatched_terms": [],
  "confidence": 0.86
}

4. 语音转文字

scenario_key: speech-to-text

语音输入

把已上传的语音文件 URL / 对象存储引用转写成文字。上层语音找衣或语音搭配流程应先调用本场景,再把返回文字传给文字找衣或文本智能搭配场景。

入参

{
  "audio": {
    "url": "http://localhost:9000/closet-media/closet/users/user_1/voice/search-voice.m4a",
    "bucket": "closet-media",
    "object_key": "closet/users/user_1/voice/search-voice.m4a",
    "mime_type": "audio/mp4",
    "metadata": {
      "name": "search-voice.m4a",
      "duration_ms": 3200
    }
  },
  "language_hint": "zh-CN"
}

出参

{
  "text": "今晚朋友聚餐,想舒服一点但不要太随便",
  "language": "zh-CN",
  "duration_ms": 5200,
  "confidence": 0.92
}

5. 文本智能搭配

scenario_key: outfit-recommendation

文本推理

根据用户搭配需求、时间天气等上下文,以及用户衣柜中所有衣物的文本特征,挑选一套或多套合适穿搭。衣物只传 ID 和特征,不传图片。

入参

{
  "request_text": "今晚朋友聚餐,想舒服一点但不要太随便",
  "context": {
    "time": "2026-05-30 19:00",
    "location": "上海",
    "weather": { "condition": "多云", "temperature_c": 24 }
  },
  "wardrobe_items": [
    {
      "id": "item_001",
      "name": "白色短袖衬衫",
      "wearing_slot": "upper",
      "category_1": "上衣",
      "category_2": "衬衫",
      "color": "白色",
      "style": "通勤",
      "season": "春夏",
      "match_features": { "style_tags": ["通勤", "简约"] },
      "matching_summary": "白色短袖衬衫,春夏适合,风格简约清爽。"
    }
  ],
  "preferences": {
    "max_outfits": 3,
    "avoid_items": [],
    "must_include_items": []
  }
}

出参

{
  "outfits": [
    {
      "title": "清爽聚餐搭配",
      "items": [
        { "id": "item_001" }
      ],
      "recommendation_reason": "白色衬衫适合聚餐场景,清爽但不随便。",
      "style_summary": "整体舒适、清爽,适合朋友聚餐。",
      "match_reasoning": {
        "occasion_fit": "适合朋友聚餐。",
        "weather_fit": "适合当前天气。",
        "color_harmony": "颜色协调。",
        "style_consistency": "风格统一。"
      },
      "score": 0.91
    }
  ],
  "missing_roles": [],
  "overall_suggestion": "建议选择轻薄、清爽、偏休闲但整洁的单品。"
}

6. 一周穿搭推荐

scenario_key: weekly-outfit-recommendation

文本推理

根据未来一周每天的天气、可选备注、整体偏好和衣柜特征,生成每日穿搭推荐。每天备注可为空,例如周三聚餐、周五见客户。

入参

{
  "week_context": {
    "start_date": "2026-06-01",
    "days": [
      {
        "date": "2026-06-01",
        "weekday": "Monday",
        "weather": {
          "condition": "晴",
          "temperature_low_c": 20,
          "temperature_high_c": 28
        },
        "note": "正常上班"
      }
    ]
  },
  "request_text": "这周尽量穿得清爽一点,工作日不要太休闲",
  "wardrobe_items": [
    {
      "id": "item_001",
      "name": "白色短袖衬衫",
      "wearing_slot": "upper",
      "match_features": { "style_tags": ["通勤", "简约"] },
      "matching_summary": "白色短袖衬衫,春夏适合,风格简约清爽。"
    }
  ],
  "preferences": {
    "avoid_repeating_same_item": true,
    "max_repeat_count_per_item": 2
  }
}

出参

{
  "weekly_outfits": [
    {
      "date": "2026-06-01",
      "weekday": "Monday",
      "title": "清爽通勤搭配",
      "items": [
        {
          "id": "item_001",
          "wearing_slot": "upper",
          "reason": "白色衬衫适合工作日,清爽且正式感适中。"
        }
      ],
      "style_summary": "清爽、简约、适合上班。",
      "weather_fit": "适合 20-28 摄氏度晴天。",
      "occasion_fit": "适合正常上班。",
      "score": 0.9
    }
  ],
  "overall_suggestion": "本周天气偏暖,建议以轻薄上衣和清爽配色为主。",
  "missing_roles_by_day": []
}

运维管理

后台使用要点

供应商与密钥

API key 在响应、日志和测试快照中都不展示。更新供应商时如不填写新 key,则保留原密钥。

实现发布

实现草稿修改不会影响业务调用。mock 关闭后,业务调用使用当前发布的场景实现版本。

令牌轮换

App Token 只展示一次。重新创建或停用令牌会立即影响业务调用,发布前需和业务方确认切换窗口。

调用日志

日志保留 request_id、app_client_id、scenario_key、implementation_version_id 和状态等追踪字段,避免记录原始密钥。

发布

发布边界

当前开发测试以本机 Docker 后端和本机 Vite 管理后台为准。CloudBase 只保留为参考部署方案,明确要求时再执行。

后端服务

本地后端 API 使用 http://localhost:5210;Docker 容器内部服务端口为 8080。Go 服务启动时执行非破坏性 Schema 初始化。

cd backend
go test ./...

本地管理后台

管理后台运行在 http://localhost:5200,用于配置、调试和应用层契约测试。当前不默认部署到 CloudBase 静态托管。

cd site/admin
npm run build