koach 开发者文档

快速开始

这一页的目标很窄:让你在五分钟内拿到一个真实的模型响应,排除掉环境问题。 效果评估和成本测算留到后面几页。

1 · 获取 API Key

koach 控制台 的「API Keys」页面创建密钥。 密钥分两种,前缀不同:

前缀环境额度说明
sk-test-沙箱500 万 token / 账号 不计费。请求与响应 30 天后清理,不用于任何模型训练
sk-live-生产按合同 计费。需要完成企业实名与合同签署后开通
密钥只在创建时显示一次

它等同于你账户的支付凭证,任何拿到密钥的人都可以消耗你的额度。 不要写进前端代码、不要提交进 Git 仓库、不要放进移动端安装包 —— 移动端应当由你自己的服务端代理转发,密钥留在服务端。

怀疑泄露时在控制台直接吊销,吊销即时生效。

把密钥放进环境变量,后面所有示例都从这里读:

export KOACH_API_KEY="sk-test-••••••••••••••••"
    export KOACH_BASE_URL="https://api-sandbox.koach.ai/v1"

2 · 第一次调用

先用一个最小请求确认链路通畅。这个问题故意选了一个通用模型容易答错的方向 —— 跑量增长的安全上限。

curl "$KOACH_BASE_URL/chat/completions" \
      -H "Authorization: Bearer $KOACH_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "model": "keepace-pro",
        "messages": [
          {"role": "user", "content": "我现在周跑量 30 公里,想两个月后跑半马,怎么加量比较安全?"}
        ]
      }'
import os
    from openai import OpenAI

    client = OpenAI(
        api_key=os.environ["KOACH_API_KEY"],
        base_url=os.environ["KOACH_BASE_URL"],
    )

    resp = client.chat.completions.create(
        model="keepace-pro",
        messages=[{
            "role": "user",
            "content": "我现在周跑量 30 公里,想两个月后跑半马,怎么加量比较安全?",
        }],
    )

    print(resp.choices[0].message.content)
    print("消耗 token:", resp.usage.total_tokens)
import OpenAI from "openai";

    const client = new OpenAI({
      apiKey: process.env.KOACH_API_KEY,
      baseURL: process.env.KOACH_BASE_URL,
    });

    const resp = await client.chat.completions.create({
      model: "keepace-pro",
      messages: [{
        role: "user",
        content: "我现在周跑量 30 公里,想两个月后跑半马,怎么加量比较安全?",
      }],
    });

    console.log(resp.choices[0].message.content);
    console.log("消耗 token:", resp.usage.total_tokens);

响应结构

与 OpenAI 一致,多了一个 koach 字段用于回传领域相关的元信息。

{
      "id": "chatcmpl-8Kq2nR4vXpL",
      "object": "chat.completion",
      "created": 1771305600,
      "model": "keepace-pro-20260601",
      "choices": [
        {
          "index": 0,
          "message": {
            "role": "assistant",
            "content": "两个月从周跑量 30 公里备战半马是可行的,关键是加量节奏……"
          },
          "finish_reason": "stop"
        }
      ],
      "usage": {
        "prompt_tokens": 38,
        "completion_tokens": 512,
        "total_tokens": 550
      },
      "koach": {
        "domain": "training.endurance",
        "safety_level": "general",
        "knowledge_refs": ["acsm.progression.10pct", "keep.kb.halfmarathon.plan"]
      }
    }
koach.domain
模型判定的领域分类,可用于你自己的路由或埋点统计
koach.safety_level
general 表示常规建议;caution 表示已触发损伤或疾病相关的谨慎策略; referral 表示模型判断应当建议用户就医,此时回答里会包含转诊提示
koach.knowledge_refs
本次回答引用的知识条目标识。需要在产品里展示依据来源时用得上, 默认返回,可用 koach_cite: false 关闭

3 · 开启流式输出

运动健康的回答通常偏长(一份训练计划几百字很常见),非流式的等待感很明显。 加上 stream: true 走 SSE:

stream = client.chat.completions.create(
        model="keepace-pro",
        messages=[{"role": "user", "content": "给我一份四周的半马进阶计划"}],
        stream=True,
    )

    for chunk in stream:
        delta = chunk.choices[0].delta.content
        if delta:
            print(delta, end="", flush=True)
const stream = await client.chat.completions.create({
      model: "keepace-pro",
      messages: [{ role: "user", content: "给我一份四周的半马进阶计划" }],
      stream: true,
    });

    for await (const chunk of stream) {
      const delta = chunk.choices[0]?.delta?.content;
      if (delta) process.stdout.write(delta);
    }
curl -N "$KOACH_BASE_URL/chat/completions" \
      -H "Authorization: Bearer $KOACH_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "model": "keepace-pro",
        "messages": [{"role": "user", "content": "给我一份四周的半马进阶计划"}],
        "stream": true
      }'

SSE 每一帧是一个 data: 行,最后以 data: [DONE] 结束:

data: {"id":"chatcmpl-8Kq2nR4vXpL","choices":[{"delta":{"role":"assistant"},"index":0}]}

    data: {"id":"chatcmpl-8Kq2nR4vXpL","choices":[{"delta":{"content":"第一周"},"index":0}]}

    data: {"id":"chatcmpl-8Kq2nR4vXpL","choices":[{"delta":{"content":"以适应为主"},"index":0}]}

    data: {"id":"chatcmpl-8Kq2nR4vXpL","choices":[{"delta":{},"index":0,"finish_reason":"stop"}],
           "usage":{"prompt_tokens":21,"completion_tokens":486,"total_tokens":507}}

    data: [DONE]
usage 只在最后一帧返回

如果你要统计成本,别在中间帧里找 usage,它只出现在带 finish_reason 的那一帧上。

4 · 带上用户档案

上面的回答是通用的,因为模型对这个用户一无所知。传入 koach_profile 之后, 模型会结合该用户的训练历史、身体状况与目标来回答 —— 这是 koach 与通用模型最主要的差别。 档案的写入方式见记忆大脑

resp = client.chat.completions.create(
        model="keepace-pro",
        messages=[{"role": "user", "content": "这周该怎么练?"}],
        extra_body={
            "koach_profile": "usr_8f2a41",   # 你的用户在记忆大脑里的 ID
            "koach_safety": "strict",         # 触及医疗边界时更保守
        },
    )

同一个问题「这周该怎么练?」,不带档案时模型只能反问;带上档案后它知道这个用户 上周跑了 42 公里、有过跟腱不适、目标是十月的全马,于是会直接给出减量周的建议。

5 · 处理错误

非 2xx 响应统一返回下面这个结构。生产接入前请至少处理 429(限流)和 5xx(服务端),这两类是可重试的。

{
      "error": {
        "type": "rate_limit_error",
        "code": "rate_limit_exceeded",
        "message": "每分钟请求数超出上限,请在 1.4 秒后重试。",
        "param": null,
        "request_id": "req_01JQ7X2M9K"
      }
    }
报障时请带上 request_id

每个响应的 header 和错误体里都有 request_id。 有它我们能直接定位到那一次调用的完整链路,没有的话排查会慢很多。

完整的状态码、错误类型与建议的退避策略见 错误码与重试

下一步

本页内容属于 koach 商业化合作方案的一部分。接口定义可能在正式签约前调整, 以合同附件中的版本为准。

koach · AI by Keep 隐私政策 用户协议 联系我们