首页 > 教程 > DeepSeek Harness 教程 > DeepSeek Harness 实战:构建能力
DeepSeek Harness 教程

DeepSeek Harness 实战:构建能力

第 24 / 35 节 2026-11-07

目标:myCap 能力

上一章讲了三角色概念,本章落地为代码:实现一个 myCap 能力——输入一段文本,输出全部大写。它足够小,又完整覆盖 Definition、Provider、Consumer 三个包,最后在 cordis.yml 中组合加载。

第一步:Service Definition

Definition 只声明契约——抽象类继承 Service,用 super(ctx, 'myCap') 注册命名服务,并用声明合并补类型,不含任何实现:

import { Service, type Context } from '@deepseek-ai/cordis'

declare module '@deepseek-ai/cordis' {
  interface Context {
    myCap: MyCapService
  }
}

export abstract class MyCapService extends Service {
  constructor(ctx: Context) {
    super(ctx, 'myCap') // 注册为 ctx.myCap
  }

  abstract execute(request: MyCapRequest): Promise<MyCapResult>
}

export interface MyCapRequest {
  input: string
}

export interface MyCapResult {
  output: string
}

请求与结果类型由 Definition 包拥有,Provider 与 Consumer 都从它导入。

第二步:Service Provider

Provider 继承抽象类填上真实行为,只依赖 Definition 包:

import type { Context } from '@deepseek-ai/cordis'
import { MyCapService, type MyCapRequest, type MyCapResult } from '@deepseek-ai/dsh-my-cap'

class MyCapLocal extends MyCapService {
  async execute(request: MyCapRequest): Promise<MyCapResult> {
    return { output: request.input.toUpperCase() }
  }
}

export const name = 'my-cap-local'

export function apply(ctx: Context) {
  ctx.plugin(MyCapLocal) // 注册成 ctx.myCap 的实际服务
}

第三步:Consumer

Consumer 把能力包装成模型可调用的工具,inject 保证 tools 与 myCap 就绪:

import type { Context } from '@deepseek-ai/cordis'
import { defineTool } from '@deepseek-ai/dsh-tools'

export const name = 'tool-my-cap'
export const inject = ['tools', 'myCap']

export function apply(ctx: Context) {
  ctx.tools.register(defineTool({
    name: 'my_cap',
    description: 'Execute my capability.',
    parameters: {
      input: { type: 'string', required: true },
    },
    output: {
      schema: { type: 'string' },
      render: (_args, value) => [{ type: 'text', text: value }],
    },
    async execute(args) {
      const result = await ctx.myCap.execute({ input: args.input })
      return result.output
    },
  }))
}

模型不认识 ctx.myCap,只认识 my_cap 工具;Consumer 是两者之间的桥梁。数据流为:模型调用工具 → Consumer 包装成 MyCapRequest → Definition 委托给当前 Provider → 结果沿原路返回并渲染成文本。换掉 Provider 时,Consumer 与模型都无感知。

在 cordis.yml 中组合

# 文件:cordis.yml
# 先加载 Provider,让 ctx.myCap 有实现
- name: '@deepseek-ai/dsh-my-cap-local'

# 再加载 Consumer,让模型能用 my_cap 工具
- name: '@deepseek-ai/dsh-tool-my-cap'

Cordis 会按依赖自动排序,加载先后并不关键;换 Provider 只改第一行。

设计要点

  1. 不要预防性拆分:只有角色需要独立演进时才拆包,简单工具插件一个包承担多角色完全合法。
  2. Definition 拥有 Request/Result 类型:因为 Provider 与 Consumer 只依赖 Definition。
  3. 显式优于隐式:用显式的 resolve(request) 处理默认值,而不是在 run() 里隐藏 ?? default——Bash seam 的 ctx.shell.resolve(request) 就是范例。

小结自测

写一个可替换能力 = Definition 抽象类 + Provider 子类 + Consumer 工具,再加一份 cordis.yml。自测:MyCapRequest 应定义在哪个包?Provider 与 Consumer 之间有没有依赖?为什么不建议预防性拆分?

 

©️版权声明:
本网站(https://aigc.izzi.cn)刊载的所有内容,包括文字、图片、音频、视频等均在网上搜集。
访问者可将本网站提供的内容或服务用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯本网站及相关权利人的合法权利。除此以外,将本网站任何内容或服务用于其他用途时,须征得本网站及相关权利人的书面许可,并支付报酬。
本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站,予以删除。

继续学习其他教程