Skip to main content
MN 内置了 AI 服务。插件无须自行接入模型,也无须自行保管密钥;发送的内容范围、消耗的额度以及用户是否知情,均由 MN 处理。

声明 AI 任务

任务声明在模板中,增加一条任务只需改动模板,MN 本身无须改动。mnaddon.json 不必为此增加字段。
template.json
任务可用的字段如下:
  • id:任务的标识,依据该字段指定要调用的任务。
  • title:显示给用户的任务名称。
  • trigger:说明该任务的发起方式。默认值 "user"。
    • "user" 表示仅在用户触发之后发出
    • "auto" 表示允许插件自行发起。需要先取得一次同意。
  • scope:发送出去的材料的范围。
    • word_sentence 允许插件提供一个词语和该词语所在的句子。词语不超过 80 个字符,句子不超过 600 个字符。
    • card_text MN 从卡片中取出标题与正文,插件传入的内容不予采用。
    • attempt_ink 用于读取卡上书写内容的场合:手写、文本框与公式框合并为一张图片发送,交由识别手写的模型处理,卡上没有书写内容时该次调用会被拒绝。
  • prompt:提示词。
  • output:返回值的 JSON Schema,取值只能是 "string"、"number" 与 "bool"。
  • required:output 中必须有值的字段。
  • tier:所用的模型级别,0 最快,2 最强,默认值 0。

调用 AI

页面以 mn.ai(卡片id, 任务id, 参数) 调用一条已经声明过的任务。 参数随 scope 而定:
  • word_sentence 的材料由插件放进参数,需提供 word 与 sentence。
  • card_text 的材料由 MN 从卡片上取出,参数不会发送出去,参数 中填写的内容不予采用。
  • attempt_ink 的图片由 MN 从卡上合成,图片之外的材料由插件放进参数,例如题干与参考答案。
下面是一个对上文定义的 AI 任务的调用例子:
index.html
返回结果的形式如下:
  • 成功时返回 { ok: true, text, json }。
    • json:按任务的 output 解析出来的对象
    • text:模型返回的原文。
  • 失败时返回 { ok: false, error },error 包括:
    • bad_args 表示材料不符合要求,或该任务的声明不合格。
    • bad_output 表示模型返回的字段结构不对,卡片上没有写入任何内容。
    • task_used 表示同一张卡上的该任务 MN 只发送一次,重复请求会被拒绝。
    • declined 表示用户在弹出的提示中选择了拒绝。
    • consent_required 表示自动发起的任务尚未取得同意。
    • max_required 表示该任务需要 MAX 订阅。
    • no_service 表示 App 中尚未配置 AI 服务。
    • rate_limited 表示请求过于频繁。
    • no_ticket 表示该卡没有交给本插件的 AI。
    • not_owner 表示该卡上的 AI 交给了别的插件。
    • network 表示请求没有送达。
    • no_ink 表示作答区域中没有可以取用的内容。
AI 的处理需要数秒。等待期间用户可能已经切换到别的卡片,返回的结果应当写入发起时记录的卡片,不要用当前聚焦的卡片进行处理。
MN 在扣除额度之前会弹出提示征求用户同意。提示尚未关闭时再次发送请求,会被视为拒绝。因此发起期间应当禁用按钮,避免重复点击。

指定 AI 交给的插件

模板的摘录工具与划线快捷项各自带有 ai_addon 字段,取值为插件的 id,指明用该工具摘下来的卡片交由该插件处理。划线快捷项指在文档中选中一段文字时,菜单条上出现的一排快捷按钮。 在 编辑场景模板→ 卡片与摘录菜单 中,添加划线快捷项时可配置AI 交给:……。
template.json
用该摘录工具摘录出的卡片,只有 ai_addon 字段指向的插件能对其调用 AI。卡片已经交给别的插件之后,本插件在该卡上调用任务会被拒绝,收到 not_owner;该工具没有启用 AI 时收到 no_ticket。

从模板读取任务列表

页面可以读取当前模板声明的任务,并依据声明生成按钮,这样再往模板中增加任务时不必改动插件:
index.html