koach 开发者文档

示例 Demo

五个可以直接复制运行的完整场景。都用沙箱密钥就能跑, 按顺序做下来大约两小时,足够判断这套能力值不值得进入正式 POC。

开始之前

先按快速开始配好 KOACH_API_KEYKOACH_BASE_URL, 并安装 SDK:pip install koach openai

一 · 会看训练数据的问答机器人

最小可用的形态:用户上传一次跑步数据,机器人给出解读并回答追问。 用 metrics.interpret 拿结构化分析,再交给模型讲成人话。

import os
    from koach import Koach

    kc = Koach(api_key=os.environ["KOACH_API_KEY"],
               base_url=os.environ["KOACH_BASE_URL"])

    activity = {
        "type": "running",
        "started_at": "2026-08-16T06:12:00+08:00",
        "distance_km": 12.4,
        "duration_s": 3720,
    }
    series = {
        "heart_rate":    [132, 141, 148, 155, 161, 166, 171, 168],
        "pace_s_per_km": [340, 322, 310, 305, 301, 298, 296, 305],
        "cadence_spm":   [172, 174, 176, 178, 178, 179, 180, 176],
        "sample_interval_s": 465,
    }

    # 第一步:Skill 出结构化分析
    analysis = kc.skills.invoke(
        "metrics.interpret",
        input={"activity": activity, "series": series,
               "context": {"temperature_c": 31, "humidity": 0.74}},
    ).output

    # 第二步:把分析结果交给模型组织成对话
    messages = [
        {"role": "system", "content":
            "你是跑步教练。基于给定的分析结果回答用户,语气平实,不要罗列指标名。"},
        {"role": "system", "content": f"分析结果:{analysis}"},
        {"role": "user",   "content": "我这次跑得怎么样?"},
    ]

    reply = kc.chat.completions.create(
        model="keepace-lite", messages=messages, temperature=0.4,
    )
    print(reply.choices[0].message.content)

    # 追问时把上一轮回答带上即可
    messages.append({"role": "assistant", "content": reply.choices[0].message.content})
    messages.append({"role": "user", "content": "那我明天还能跑吗?"})
    print(kc.chat.completions.create(
        model="keepace-lite", messages=messages).choices[0].message.content)
为什么不直接把原始数据丢给模型

试过就知道,模型能算出平均心率,但算不准心率漂移,也不会主动把它和当天的 温湿度关联起来。这类领域计算交给 Skill 更可靠也更便宜 —— 用 lite 加 Skill 的成本,比用 pro 硬算低一个量级,准确度还更高。

二 · 让模型查你自己的数据

模型不知道你的会员体系、课程库存和线下排期。用 tool calling 把这些接进来, 下面是完整的两轮流程。

import json

    def get_member_status(user_id: str) -> dict:
        """你自己的业务查询,这里用假数据代替"""
        return {"level": "gold", "remaining_pt_sessions": 3,
                "expires_at": "2026-12-31"}

    tools = [{
        "type": "function",
        "function": {
            "name": "get_member_status",
            "description": "查询用户的会员等级与剩余私教课时",
            "parameters": {
                "type": "object",
                "properties": {"user_id": {"type": "string"}},
                "required": ["user_id"],
            },
        },
    }]

    messages = [{"role": "user", "content": "我还剩几节私教课?想约下周三。"}]

    # 第一轮:模型决定要调用哪个函数
    first = kc.chat.completions.create(
        model="keepace-pro", messages=messages, tools=tools,
    )
    msg = first.choices[0].message
    messages.append(msg)

    # 执行函数,把结果回填
    for call in msg.tool_calls or []:
        args = json.loads(call.function.arguments)
        result = get_member_status(**args)
        messages.append({
            "role": "tool",
            "tool_call_id": call.id,
            "content": json.dumps(result, ensure_ascii=False),
        })

    # 第二轮:模型基于真实数据作答
    second = kc.chat.completions.create(
        model="keepace-pro", messages=messages, tools=tools,
    )
    print(second.choices[0].message.content)
    # → 你还有 3 节私教课,12 月 31 日到期。下周三想约几点?

三 · 让 Agent 记住用户

前两个例子里,机器人每次都是从零开始。接上记忆大脑之后, 它会知道这个用户是谁、练了多久、伤过哪里。

# 1) 建档案(通常在用户注册或授权时做一次)
    kc.memory.profile.update("usr_demo01", data={
        "demographics": {"age_band": "30-34", "sex": "male"},
        "body": {"weight_kg": 71.5, "resting_hr": 52},
        "history": {"training_years": 4,
                    "injuries": [{"site": "achilles_right", "year": 2024,
                                  "status": "recovered"}]},
        "goals": [{"type": "race", "event": "marathon",
                   "date": "2026-10-18", "target_time_min": 230}],
    })

    # 2) 把已有的训练数据同步进来(通常做一次全量 + 之后增量)
    kc.memory.events.append("usr_demo01", events=[
        {"type": "workout", "at": "2026-07-27T06:10:00+08:00",
         "data": {"sport": "running", "distance_km": 28, "rpe": 6}},
        {"type": "workout", "at": "2026-08-03T06:08:00+08:00",
         "data": {"sport": "running", "distance_km": 31, "rpe": 7}},
        {"type": "workout", "at": "2026-08-10T06:15:00+08:00",
         "data": {"sport": "running", "distance_km": 34, "rpe": 8}},
    ])

    # 3) 建 Agent
    agent = kc.agents.create(
        name="马拉松备赛教练",
        model="keepace-pro",
        instructions="你是马拉松备赛教练,说话简短。回答训练问题前先看用户的负荷趋势。",
        skills=["training.plan.generate", "metrics.interpret", "injury.risk.screen"],
        memory={"mode": "auto", "retention_days": 365},
    )

    # 4) 提一个没有任何上下文的问题
    run = kc.agents.runs.create(
        agent_id=agent.id, profile="usr_demo01",
        input="这周该怎么练?",
    )

    print(run.output_text)
    for s in run.steps:
        print(f"  [{s.type}] {s.name}  {s.duration_ms}ms")

「这周该怎么练?」这句话里没有任何信息,但 Agent 能答出具体方案:

连续三周加量 28 → 31 → 34 公里,本周该减了。
    跑量压到 24 公里,速度课留一次,周日长距离 8 公里。
    你右跟腱有旧伤,减量周正好把跟腱离心训练补上,每天三组。

      [memory.read] profile              31ms
      [skill] metrics.interpret         798ms
      [skill] injury.risk.screen        612ms
      [model] final                    1355ms
把这一段和第一个例子对比着看

同样是回答训练问题,区别不在模型多强,而在于它知不知道这个人是谁。 这也是我们建议在 POC 里一定要接上记忆大脑的原因 —— 不接的话,测出来的效果会明显低估。

四 · 把品牌内容变成课程

L3 场景合作里最常见的一条链路:品牌方有素材,需要变成用户愿意反复练的结构化课程。

course = kc.skills.invoke(
        "course.aigc.compose",
        idempotency_key="course-fall2026-core20",   # 按次计费,加幂等键
        input={
            "source": {
                "type": "brand_assets",
                "video_urls": ["https://cdn.example.com/campaign_fall.mp4"],
                "brand_kit": {
                    "tone": "专业克制",
                    "forbidden_words": ["瘦身", "速成", "月瘦十斤"],
                },
            },
            "target": {
                "duration_min": 20,
                "level": "beginner",
                "equipment": ["yoga_mat"],
                "focus": ["core", "mobility"],
            },
            "output_format": ["structure", "script", "shot_list"],
        },
    )

    for block in course.output["structure"]:
        print(f"{block['phase']:6s} {block['duration_s']:>4}s  "
              f"{'、'.join(m['name'] for m in block['movements'])}")
warmup   180s  猫牛式、世界最伟大拉伸、髋部环绕
    main     900s  死虫式、鸟狗式、侧平板、臀桥、卷腹
    cooldown 240s  婴儿式、仰卧脊柱扭转、股四头肌拉伸

五 · 用评测集证明效果

前面四个例子是「看起来不错」,这一个是「能进评审会」。 同一套题跑三个模型:你现在在用的、keepace 原版、以及微调后的版本。

run = kc.evaluations.create(
        suite="sport.safety.v3",
        models=[
            # 对照组:你现在在用的通用模型
            {"id": "gpt-4o-mini", "endpoint": "https://api.openai.com/v1",
             "api_key": os.environ["OPENAI_API_KEY"]},
            # 实验组
            "keepace-lite",
            "ft:keepace-lite:acme:morning-run-v2:9dK2",
        ],
        judge="hybrid",
        human_sample_rate=0.1,
        report_format="pdf",
    )

    result = kc.evaluations.wait(run.id)          # 阻塞直到完成,通常 20 到 40 分钟

    for r in result.results:
        print(f"{r['model']:<44s} {r['overall']:.3f}")

    print("\n报告:", result.report_url)
    print("失败样本:", result.failures_url)
gpt-4o-mini                                  0.716
    keepace-lite                                 0.842
    ft:keepace-lite:acme:morning-run-v2:9dK2     0.913

    报告: https://api.koach.ai/v1/evaluations/evalrun_01JQ9F1X3B/report.pdf
    失败样本: https://api.koach.ai/v1/evaluations/evalrun_01JQ9F1X3B/failures.jsonl
这三个数字是示例

实际差距取决于你的评测集构成和业务口径。 我们不承诺任何具体分数 —— 承诺具体分数的供应商, 多半是在自己出的题上跑的。你应该用自己的题来测。

从 Demo 到 POC

跑完这五个例子,你已经覆盖了 L1 和 L2 的主要能力。 接下来通常是:

换成你自己的数据重跑一遍

示例里的档案、训练记录和评测集都是我们的。 换成你真实业务里的样本,结论才有意义。

把成本账算清楚

统计每个场景的 token 与 Skill 调用量,换算成单用户月成本, 和你现在的方案做对比。

约一次技术对齐

带着你跑出来的数字和遇到的问题来。 FDE 会一起看哪些该微调、哪些该改提示词、哪些其实不需要 AI。

预约一次 POC 沟通, 或直接把你的 request_id 和问题发到工单,我们一个工作日内回。

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

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