联想智能体小程序开发攻略

智能体小程序介绍

1.智能体小程序

智能体小程序是基于联想智能体、联想浏览器、桌面助手等联想矩阵产品的应用程序形态。用户无需下载安装即可在联想矩阵产品(联想智能体、联想浏览器、桌面助手等)上使用。这些小程序涵盖了多种功能和服务,为用户提供了便捷的使用体验。

智能体小程序覆盖了多端设备,一次接入可以在多端进行适配。入口更丰富,通过联想矩阵产品均可调起服务。

1.1联想智能体入口    

可通过联想智能体的用户query和小程序商店调起/进入您的智能体小程序。

1.2联想浏览器入口

”联想浏览器“是联想原厂出品的一款高性能浏览器。用户可在联想浏览器新标签页、侧边栏等位置进入您的智能体小程序。

1.3桌面助手入口

 “桌面助手”是呈现在屏幕上的小组件组合,用户可根据自己的喜好摆放不同的组件,让功能使用更方便。用户可通过桌面组件进入您的智能体小程序。

智能体小程序开发指南

1.联想小程序介绍

智能体小程序是基于小天智能体、联想浏览器、桌面助手等联想矩阵产品的应用程序形态。用户无需下载安装即可在联想矩阵产品(小天智能体、联想浏览器、桌面助手)上使用。这些小程序涵盖了多种功能和服务,为用户提供了便捷的使用体验。

联想小程序覆盖了多端设备,一次接入可以在多端进行适配。入口更丰富,通过联想矩阵产品均可调起服务。

2.开发流程介绍

获取开发信息(appid、公私钥)

  • 开放平台注册联想账号,并申请开发者
  • 开放平台创建配置智能体小程序(保存-本地开发调试,提交审核-调试完成后)

小程序功能开发

1.基础功能开发(必须)

(1)说明:保证开发者小程序在联想Runtime中的适配,以确保从所有入口调起的小程序能够良好运行;

(2)接入启动接口、设备详情接口。

2.联运功能开发

(1)说明:“联运”即指开发者与联想侧联合运营小程序,此模式适用于有清晰付费模式的小程序;

(2)接入授权接口(必须)、登录相关接口(可选)、支付接口(必须)。

上架到各个入口,需要额外开发

1.联想浏览器

入口为H5的组件,需要参考4.组件开发文档,开发后浏览器、桌面助手通用

2.电脑管家--桌面助手

入口为H5的组件,需要参考4.组件开发文档,开发后浏览器、桌面助手通用

3.联想应用商店

仅提供素材即可

4.联想小天

小程序商店点击调起,仅提供图标、产品名称、产品互联网访问地址、产品简介等素材即可

自然语言对话调起,需要参考5.插件开发文档(暂时不用开发)

3.小程序开发文档

小程序开发文档包含基础功能开发联运功能开发,基础功能开发部分说明了开发者如何调用小程序的相关接口和调试,按此文档开发完成后可通过本地命令行调起小程序,效果等同于从各个入口调起小程序;联运功能开发部分说明了开发者如何接入联运的功能、调用联运的接口。

3.1.参数字段描述

小程序Runtime当前是cef内核,IFrame方式加载H5页面。

安装、使用小程序的runtime有两个途径:安装联想电脑管家或者联想智能体

在这两个环境下都可以运行、开发和调试小程序runtime。

3.1.1.标准字段

在开发启动小程序的时候,可以配置如下的标准字段来看具体的效果

此字段信息会和服务器小程序的信息保持一致

字段名称是否可选描述备注
appid必选此小程序的appid暂定和插件id保持一致
url可选小程序的H5页面如果没有定义url,并且此appid的小程序还没有打开,则点击没有效果
width可选小程序启动的宽度,默认为360
height可选小程序启动的高度,默认为680
minwidth可选最小宽度,默认为width-360
minheight可选最小高度,默认为height-690
maxwidth可选最大宽度,默认为窗口所在屏幕的宽度
maxheight可选最大高度,默认为窗口所在屏幕的高度
resizeable可选是否可以拉升,默认1
icon可选ICON的网络路径图片内容必须为icon格式
title可选标题

3.1.2.扩展字段

小程序启动的一些扩展字段,业务根据需要来添加使用

字段名称是否可选描述备注
sourcekey可选启动的来源,上报大数据使用小乐同学:xiaole
浏览器:slbbrowser
商店:appstore
助手:desktopassist
type可选默认为00 如果不存在此appid的小程序,则以url打开此小程序。如果已经存在则通知小程序小程序相关的信息,由小程序来做处理
1 如果不存在此appid的小程序,则以url打开此小程序。如果已经存在则刷新此小程序的url
shownavigator可选默认为1默认是否显示小程序的返回按钮
data可选上下文的数据此数据会通过jssdk透传通知到小程序的H5

3.2.jsbridge的接口定义

小程序runtime提供一系列的接口供开发者使用

接口文档参考:3.6.小程序API

3.3.联运功能说明

小程序联运包含应用小程序联运和游戏小程序联运,开发者可根据小程序的类型接入。联想小程序联运提供联想账号登录、支付的基础功能,若为游戏小程序联运,联想也提供实名认证、防沉迷的服务。

3.3.1.登录功能

(1) 提供给开发者联想账号登录的接口,具体详见章节3.7.4.1;

(2) 开发者的小程序接入登录功能后,用户在小程序的登录状态会同步给各个小程序;

(3) 需注意,登录功能为游戏小程序的必接功能,否则无法实现未成年人防沉迷服务。

3.3.2.支付功能

(1) 联想小程序联运服务提供普通支付的支付能力,在pc端表现为聚合码支付收银台(页面由联想开发,开发者调用支付接口即可调起),在移动端表现为微信、支付宝、聚合码支付三种方式组合的移动端收银台(固定为三种支付方式,开发者不可选择);

(2) 开发者的小程序若已实现多端适配,可通过接一次支付接口实现支付收银台的多端适配,支付接口具体详见章节3.7.5.2;

(3) 需注意,支付通知已服务端的通知结果为准,服务端接口详见章节3.8;

(4) 其他有关商户订单号、支付金额、时间的说明详见章节3.9;

  • 收银台样式

PC端

3.3.3.游戏实名认证、防沉迷说明

整体说明:若选择的应用类型为游戏,小程序联运服务有提供实名认证、未成年人防沉迷(时长、支付限额)的功能。此些功能不需要开发者单独的接入和测试,已封装在小程序的流程里。

1.作为游戏用户,登录Lenovo ID后,小程序联运服务会判断此用户是否已完成实名认证,若为已完成,则可以直接进入游戏内;若未完成,小程序会弹窗提示用户先完成实名认证再继续后面的流程。

2.在用户完成实名认证后,小程序联运服务会判断该用户的年龄是否符合国家对未成年人游戏防沉迷的限制,如果不符合国家规定,则会无法进入游戏并直接给出提示,需要用户退出小程序。若未成年用户在国家规定的时段外进入游戏,或者在玩游戏时到了规定不可继续玩的时间,小程序会直接给出页面提示,请用户退出游戏。

3.在用户每次充值时,小程序联运服务也会判断用户的充值金额、累计充值金额是否符合规定,并在不符合规定时,不予充值。

4.以下为小程序内的弹窗页面

3.4.开发注意事项

  • 小程序的H5是以IFrame的方式显示的,线上的H5不能禁用X-Frame-Options
  • 小程序禁用所有的的外链,打开新的页面和脚本的window.open 都会被自动禁止(允许页面跳转)
  • 在调用小程序的方法之前,需判断此方法是否存在,需注意历史版本接口兼容问题。

3.5.小程序API

3.5.1.概述

  • 默认都是异步接口
  • 除了事件监听(如以 jsbridge.on开头)和特殊说明的,都以 Promise 风格调用
  • 同步接口加标识 sync,如 jsbridge.getLaunchOptionsSync()
  • 以 jsbridge.on 开头的 API 是监听某个事件发生的 API 接口,接受一个 CALLBACK 函数作为参数。当该事件触发时,会调用 CALLBACK 函数。

3.5.2.基础

3.5.2.1启动

3.5.2.1.1.jsbridge.smallapp.asyncGetSmallAppData() 旧

功能描述

异步获取小程序启动信息

小程序启动后,获取启动小程序的参数和信息

由于历史原因,增加了命名空间、方法名称未统一、返回参数类型是 字符串。

推荐使用 jsbridge.getLaunchOptions()

参数

返回值

String res

启动参数

属性类型说明是否必须返回
appidstring此小程序的appid暂定和插件id保持一致
urlstirng如果没有定义url,并且此appid的小程序还没有打开,则点击没有效果
datastirng通过智能体传递的上下文的数据此数据会通过jssdk透传通知到小程序的H5

示例代码

jsbridge.smallapp.asyncGetSmallAppData().then(res => {
  res = JSON.parse(res)
  console.log(res.appid)
  console.log(res.url)
  console.log(res.data)
})

3.5.2.1.2.jsbridge.getLaunchOptions()

Windows:支持

Android:支持

功能描述

异步获取小程序启动信息

小程序启动后,获取启动小程序的参数和信息

参数

返回值

Object res

属性类型说明
queryObject启动小程序的 query 参数

query说明

Object

属性类型说明是否必须返回
appidstring此小程序的appid暂定和插件id保持一致
urlstirng如果没有定义url,并且此appid的小程序还没有打开,则点击没有效果
datastirng通过智能体传递的上下文的数据此数据会通过jssdk透传通知到小程序的H5

示例代码

jsbridge.getLaunchOptions().then(res => {
  const query = res.query
  console.log(query.appid)
  console.log(query.url)
  console.log(query.data)
})

3.5.2.1.3.jsbridge.smallapp.onNotify() 旧

Windows:支持

Android:支持

功能描述

小程序接收通知

小程序的框架会负责将jsbridge协议的数据解析为json格式的字符串,并通知到小程序页面

由于历史原因,增加了命名空间、方法名称未统一、返回参数类型是 字符串。

推荐使用新版 jsbridge.onSmallAppNotify()

参数

回调函数参数

String res

属性类型说明是否必须返回
appidstring此小程序的appid暂定和插件id保持一致
urlstirng如果没有定义url,并且此appid的小程序还没有打开,则点击没有效果
datastirng通过智能体传递的上下文的数据此数据会通过jssdk透传通知到小程序的H5

示例代码

jsbridge.smallapp.onNotify(res => {
  res = JSON.parse(res)
  console.log(res.appid)
  console.log(res.url)
  console.log(res.data)
})

3.5.2.1.4.jsbridge.onSmallAppNotify()

Windows:支持

Android:支持

功能描述

小程序接收通知

小程序的框架会负责将jsbridge协议的数据解析为json格式的字符串,并通知到小程序页面

参数

回调函数参数

Object res

属性类型说明
queryObject启动小程序的 query 参数

query说明

Object

属性类型说明是否必须返回
appidstring此小程序的appid暂定和插件id保持一致
urlstirng如果没有定义url,并且此appid的小程序还没有打开,则点击没有效果
datastirng通过智能体传递的上下文的数据此数据会通过jssdk透传通知到小程序的H5

示例代码

jsbridge.onSmallAppNotify(res => {
  const query = res.query
  console.log(query.appid)
  console.log(query.url)
  console.log(query.data)
  })

3.5.3.设备

3.5.3.1.系统

3.5.3.1.1.jsbridge.getSystemInfo()

Windows:支持

Android:支持

功能描述

异步获取系统信息

返回值参数

Object res

属性类型说明
SDKVersionstring客户端基础库版本(即JSSDK版本)
modelstring设备型号
brandstring设备品牌
systemstring操作系统及版本
platformstring客户端平台(windows、android)
pixelRationumber设备像素比
screenWidthnumber屏幕宽度,单位px
screenHeightnumber屏幕高度,单位px

示例代码

jsbridge.getSystemInfo().then(res => {
  console.log(res.platform)
  console.log(res.model)
  console.log(res.SDKVersion)
  console.log(res.brand)
  console.log(res.system)
  console.log(res.pixelRatio)
  console.log(res.screenWidth)
  console.log(res.screenHeight)
})

3.5.4.开放接口

3.5.4.1.登录

3.5.4.1.1.jsbridge.showLogin()

基础库 1.0.1 开始支持,低版本需做兼容处理。

Windows:支持

Android:支持

功能描述

打开登录弹出框。

即调起宿主APP Lenovo ID SDK的登录弹出框。当用户登录成功后,可通过接口  jsbridge.onLoginStatusChange() 监听到登录状态,并获取到用户信息

示例代码

jsbridge.showLogin().then(res => {
  console.log('打开登录弹出框成功')
}).catch(err => {
  console.log('打开登录弹出框失败')
})

3.5.4.1.2.jsbridge.onLoginStatusChange()

注意:获取用户 token后,需调用服务端接口 3.8.4.根据 token 获取 lenovoid

和用户账号的接口来获取用户的唯一ID。

基础库 1.0.1 开始支持,低版本需做兼容处理。

Windows:支持

Android:支持

功能描述

监听登录状态发生变化

返回值参数

Object res

属性类型说明
statusCodenumber登录状态码:1登录成功,0退出登录
tokenstring登录令牌
realmstring权限域
userInfoObject用户信息对象

userInfo说明

Object

属性类型说明
lenovoIDstring联想用户标识
userNamestring登录的用户名
nickNamestring用户昵称
avatarUrlstring用户头像图片的 URL

示例代码

jsbridge.onLoginStatusChange(res => {
        if (res.statusCode === 1) {
               // 登录成功
               console.log(res.token) 
               console.log(res.realm) 
               const userInfo = res.userInfo
               console.log(userInfo.lenovoID)
               console.log(userInfo.nickName)
               console.log(userInfo.avatarUrl)
        } else if (res.statusCode === 0) {
               // 退出登录
               console.log(res)
        }
}) 

3.5.4.2.用户信息

3.5.4.2.1.jsbridge.getUserInfo()

基础库 1.0.1 开始支持,低版本需做兼容处理。

Windows:支持

Android:支持

功能描述

获取用户信息

返回值参数

Object res

属性类型说明
statusCodenumber登录状态码:1已登录,0未登录
tokenstring登录令牌
realmstring权限域
userInfoObject用户信息对象

userInfo说明

Object

属性类型说明
lenovoIDstring联想用户标识
userNamestring登录的用户名
nickNamestring用户昵称
avatarUrlstring用户头像图片的 URL

示例代码

jsbridge.getUserInfo().then(res => {
        if (res.statusCode === 1) {
               console.log(res.token)
               console.log(res.realm)
               const userInfo = res.userInfo
               console.log(userInfo.lenovoID)
               console.log(userInfo.nickName)
               console.log(userInfo.avatarUrl)
        }
})

3.5.5.联运接口

3.5.5.1.授权

3.5.5.1.1.jsbridge.requestGrant(appid, privateKey)

基础库 1.0.2 开始支持,低版本需做兼容处理。

Windows:支持

Android:支持

功能描述

请求授权使用联运能力

注意:对于加入联运的小程序,小程序Runtime会一直Loading直到小程序请求授权成功。

入参

属性类型说明
appidstring智能体小程序ID
privateKeystring智能体小程序私钥

返回值: Promise

Promise.resolve: 授权成功,Promise.reject:授权失败

示例代码

jsbridge.requestGrant(appid, privateKey).then(() => {
  // 授权成功
}).catch(() => {
  // 授权失败
})

3.5.5.2.支付

3.5.5.2.1.jsbridge.requestPayment(object)

基础库 1.0.2 开始支持,低版本需做兼容处理。

Windows:支持

Android:支持

功能描述

调起联运支付

注意:只是调起支付弹窗(创单成功),后续的支付成功通过云端同步。

入参

Object object

属性类型说明
object.payNotifystring支付通知地址:支付结果通知URL
object.mchNostring商户订单号:开发者小程序H5页面内部订单号
object.goodsCodestring商品编码
object.goodsNamestring商品名称
object.goodsDescstring可选,商品描述
object.payAmountnumber支付金额(单位:分)
object.attachstring可选,开发者想要透传给payNotify的附加数据

返回值参数

Object res

属性类型说明
属性类型说明
codenumber10000:调起支付成功,10001:还没有实名认证,10003-10005:不符合防沉迷规定,其他:调起支付错误
messagestring返回码code的描述
dataObject调起支付成功时返回的数据
data.tradeNostring支付订单号

示例代码

jsbridge.requestPayment({
  payNotify: 'https://xxxx',
  mchNo: '123123123',
  goodsCode: '243234243',
  goodsName: '测试商品',
  goodsDesc: '这是商品描述',
  payAmount: 10000,
  attach: '这是透传的数据,一个字符串'
}).then(res => {
  // 调起支付成功
  console.log(res.data.tradeNo)
}).catch(() => {
  // 调起支付失败
  console.log(res.code) // 10001、10003、10004、10005、50000
})

3.6.联运-服务端接口说明

3.6.1.接口说明

API 采用REST风格设计。所有接口请求地址都是可预期的以及面向资源的。使用规范的HTTP响应代码来表示请求结果的正确或错误信息。所有的API请求都会以规范友好的JSON对象格式返回(包括错误信息)。

  • 请求参数格式说明:

请求参数分为2部分,Body和head。Head参数不参与签名,为鉴权所用。Body参数分为基础参数和业务参数。所有基础参数都为必填参数,业务参数根据不同的场景,有所不同。

  • http状态码说明:
HTTP状态码描述
200OK
401签名或者token无效
500错误信息
  • 接口统一响应数据格式说明
{
	"code": 10000,
	"data": "",
	"message": "success"
}
变量名必填类型描述
codeYString返回码,发生错误时code不等于10000
dataYObject返回数据,发生错误时返回null
messageYString返回码描述,发生错误时返回错误信息

3.6.2.支付通知

  • 当用户支付完成后,订阅服务端将数据post到支付通知地址。商户返回SUCCESS则表示该订单支付通知,商户成功接收。商户返回其它任何字符都代表接收失败。
  • 订阅服务端会再次发送通知。通知触达10次,到达通知次数后,不会触发通知。
Post数据
字段名变量名必填类型示例值描述
商户IDmchIdYLong78993434342
应用IDappIdYLong343453453445
签名signYString参考签名算法
签名方式signTypeYStringRSA2固定值RSA2
版本versionYString1.0固定值1.0
编码charSetYStringutf-8固定值utf-8
随机字符nonceYStringdsafsadfasdfasa随机字符串
商户订单号mchNoYString
交易订单号tradeNoYLong9860494571601920交易订单号
银行流水号serialsNoYString2019090239230923第三方支付渠道的交易流水号
支付金额payFeeYInt1支付金额单位(分)
支付状态payStatusYString支付状态 1 已支付支付状态 1 已支付
支付时间payTimeYString2022-03-23 19:17:56yyyy-MM-dd HH:mm:ss
附加数据attachNStringDfasas商户私有数据
  • 商户需返回参数

SUCCESS

通知示例代码:

{
    "mchNo": "*********1111", 
    "tradeNo": 969549918857856, 
    "serialsNo": "***********2222", 
    "payFee": 3000, 
    "payTime": "2022-10-19 17:23:12", 
    "payStatus": "1", 
    "appId": 12312312, 
    "mchId": 123123123, 
    "sign": "T2IuyxblOnKstHf7EuJZWGBroSUzwN4n6l6yZ1zahsvGfBDn2AxAhifpPUblbMuq2XHsh9Mvg==", 
    "signType": "RSA2", 
    "version": "1.0", 
    "charSet": "UTF-8", 
    "nonce": "m1wo53f6iy"
}

3.6.3.查询支付结果接口

  • 接口地址:

https://cloud-rest.lenovomm.com/cloud-intermodal-core/api/v1/pay/query/trade

  • 请求方式:POST
  • 请求头参数说明:Content-Type: application/json
  • 请求Body参数说明:

1.基础参数

基础参数
字段名变量名必填类型示例值描述
商户IDmchIdYLong96291345分配的商户号
应用IDappIdYLong11962913商户号下创建的APPID
随机字符串nonceYString5K8264ILTKCH16C随机字符串,不长于32位
时间戳timestampYString1648878162182时间戳(从1970-01-01T00:00:00Z开始的毫秒数)
版本versionYString1.0版本号 固定值1.0
签名signYString参考5.4签名算法
签名方式signTypeYStringRSA2签名方式RSA2

2. 业务参数说明

业务参数
字段名变量名必填类型示例值描述
交易订单号tradeNoYLong524498630711936
  • 返回参数说明:
字段名变量名必填类型示例值
返回码codeYString10000
返回消息msgYStringSUCCESS
返回数据体dataNString

示例:

  • 请求参数:

{
	"mchId": 233799539766016,
	"appId": 233799539766016,
	"sign": "ngAcXTBZnuuI944ae8pyMY60CpiRILjTm2uX***SEwHG19+aWotz",
	"signType": "RSA2",
	"timestamp": "1666593772589",
	"nonce": "w190bfrrog1666593772585",
	"version": "1.0",
	"tradeNo": 977319841453440,
}
  • 返回参数:

http状态200

{
	"code": 10000,
	"message": "Success",
	"data": {
		"tradeNo": 877319841453440,
		"serialsNo": "4200001493202206141879749159",
		"payStatus": 1,
		"payTime": "2022-06-14 11:17:48",
		"payAmount": 1
	}
}

data 数据说明:

变量名必填类型描述
tradeNoYlong交易订单号
serialsNoNString交易流水号
payStatusYByte支付状态:待支付:0,已支付:1
payTimeNString支付时间 yyyy-MM-dd HH:mm:ss
payAmountYBigDecimal支付金额单位分

错误返回数据:

http状态码:非200

{"code":401,"message":"unauthorizedException","data":null}

{"code":500,"message":"error","data":null}

3.6.4.根据token获取lenovo ID接口

  • 接口地址:

https://cloud-rest.lenovomm.com/cloud-intermodal-core/api/v1/oauth/token

  • 请求方式:POST
  • 请求头参数说明:
  • token: "ZAgAAAAAAAGE ",请求头里面必须添加token参数。从SDK提供方法获取tokenrealm:  com.lenovo.cis.runtime,固定值
  • 求Body参数说明:

请求参数

基础参数
字段名变量名必填类型示例值描述
商户IDmchIdYLong96291345分配的商户号
应用IDappIdYLong11962913分配的APPID
随机字符串nonceYString5K8264ILTKCH16C随机字符串,不长于32位
时间戳timestampYString1648878162182时间戳(从1970-01-01T00:00:00Z开始的毫秒数)
版本versionYString1.0版本号(1.0、2.0) 2.0 返回用户信息用户账号信息,具体看响应结果
签名signYString参考签名算法
签名方式signTypeYStringRSA2签名方式RSA2
  • 返回参数说明:
字段名变量名必填类型示例值
返回码codeYString10000
返回消息msgYStringSUCCESS
返回数据体dataNString

示例:

  • 请求参数:
 { "mchId":233799539766016,
    "appId":233799539766016,    "sign":"viHirVTUoz5M3FsnBNq4BtvHxam+GqkNyFrsbYbY4gXt/cy9oa5AmFrq21QXl2+05ao63zkuKyNE/0/UtSsKb0qeLV5rv8YZWi87EO98lbLAFz6h0R9HP01ZdOKCgUmbB1XxA3mdNBCi9/FSCsFpFQ5QxoFhiXPbXTUIEDqEajd92LaqHZZZdsaxCUQDvbRmik3RtG5jJWfMDaTGx3+NffKWyWFR+lMkI0ZcsbcAlS8zDet72fNJpiOZIN2Yh8+Rtn7rRJ2Ok0zu3349P3QvQ/GYxF8R8VhVJ08sBBSle7pa5e0UhRq9MdtO7vKWCmAiyy8KNHxswuj7NThOOPvT9Q==",
    "signType":"RSA2",
    "timestamp":"1649215075332",
    "nonce":"nonceStr82751c47-ab56-4f",
    "version":"1.0"
}
  • 返回参数:
http状态200 
version为1.0时返回结果:
{"code":10000,"message":"Success","data":"10086910024"}
version为2.0时返回结果:
{ "code": 10000, "message": "Success",
  "data": {
    "lenovoId": "10086910024",
    "account": "s*******@lenovo.com"
  }
}
错误返回数据:
http状态码:非200
{"code":401,"message":"unauthorizedException","data":null}
{"code":500,"message":"{ refundAmount.Null.message}","data":null}

3.7.联运-其他说明

3.7.1.商户订单号

商户支付的订单号由商户自定义生成,仅支持使用字母、数字、中划线-、下划线_、竖线|、星号*这些英文半角字符的组合,请勿使用汉字或全角等特殊字符。订阅服务平台要求商户订单号保持唯一性,同一个应用ID不可重复(建议根据当前系统时间加随机序列来生成订单号)。重新发起一笔支付要使用新订单号,避免重复支付。

3.7.2.交易金额

交易金额默认为人民币交易,接口中参数支付金额单位为【分】,支付金额必须大于 0,参数值不能带小数,暂不支持外币交易。

3.7.3.日期时间

标准北京时间,时区为东八区;如果商户的系统时间为非标准北京时间。按照各个接口需要日期时间格式的传入。

3.7.4.签名算法

开发者需要自行实现签名,签名过程如下:

1.筛选并排序

获取所有请求参数,不包括字节类型参数,如文件,字节流,剔除sign字段,剔除值为空的参数,并按照第一个字符的键值ASCII码递增排序(字母升序排序),如果遇到相同字符则按照第二个字符的键值ASCII码递增排序,以此类推。

2.拼接

将排序后的参数与其对应值,组合成“参数=参数值”的格式,并且把这些参数用&字符连接起来,此时生成的字符串为待签名字符串。

例如:appId=2018071360678029&sign_type=RSA2&version=1.0

3.签名

使用各自语言对应的SHA256WithRSA(对应signType为RSA2)签名函数利用开发者私钥对待签名字符串进行签名。

4.把生成的签名赋值给sign参数,拼接到请求参数中.

5.验签工具:联想验签工具

4.组件开发文档

4.1.客户端框架简介

加载流程

  • 桌面助手主程序(Browser进程)负责加载主框架H5
  • 主框架H5通过主框架的插件获取组件的H5列表,并加载所有的组件H5,
  • 主框架负责注入pcmjssdk
  • 主框架有自己的插件进程
  • 每个组件有自己的插件进程,不需要Native支持的组件没有插件进程(譬如天气组件)

相关技术

  • 使用CEF的框架,最新版本使用Chromium92内核(管家5.0.60之前的版本使用Chromium84内核)
  • 助手框架负责管理所有的显示模块,包括 模块加载、拖动、大小、右键、设置、管理等
  • 所有的C++插件都在独立的插件进程中里加载,和主框架进程隔离,使用IPC通讯

框架图

插件调用流程

  • 框架负责H5和插件的双向通信
  • 组件支持Native的能力,只能通过sdk的接口window.pcmjssdk.asyncSendIPCMessage 进行访问, 调用流程如下图
  • 支持组件的插件给H5发送通知, 通知的流程如下图(后半部分), C++的通知不支持返回值

4.2.桌面助手环境的安装

安装、使用桌面助手的环境,需要安装最新版本的联想电脑管家,安装地址:联想电脑_电脑管家_弹窗拦截_杀毒软件_垃圾清理__一键驱动管理__联想官方客服__联想电脑管家官网_-

组件设计接入文档:

联想开放平台

管家的默认安装路径:C:\Program Files (x86)\Lenovo\PCManager\管家版本号\

如果修改了管家的安装路径,可以通过注册表查看管家的安装路径:计算机\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{A9861883-31C5-4324-BD9A-DC9527EEB675}_is1\InstallLocation

打开联想电脑管家->工具箱→桌面助手, 可以启动联想桌面助手

4.3.桌面助手组件目录结构

桌面助手的组件和缓存目录为:C:\ProgramData\Lenovo\devicecenter\extends

此目录会存放桌面助手的runtime和所有组件、缓存等

4.3.1.extends

modules目录:为所有的组件目录

cefcache目录: 缓存目录

4.3.2.extends/modules

modules.json:  描述组件列表的文件

desktopmainframe目录: 桌面助手主框架,下面是以每个模块的appid命名的子目录。

4.3.3.extends/modules/ $appid$

config.ini文件: 里面目前只有version这个字段,表示当前模块已经安装并且正在使用的版本

$version$目录:和config.ini 里的version对应,包含此版本里所有的资源模块,桌面助手会加载此版本下的模块

4.3.4.extends/ $appid$/$version$

module.json: 此版本的信息,具体参考组件列表

h5目录: 可选。 本地的H5界面,此目录下必须有index.html作为入口, 桌面助手的框架会加载此h5页面

previewimg目录:可选。 此模块的预览图, 目前支持大中小三种图, 文件名固定为:small.svg, medium.svg,big.svg,要求必须是矢量图

4.4.组件列表

modules.json是缓存的组件列表,此文件包含了所有需要显示的组件列表

服务器请求成功后会更新此列表

4.4.1.根节点字段

字段名称类型描述
version字符串版本号的规则,譬如:1.0。 后续备用,
preview_img预览图的地址譬如:https://ldc-fast.lenovo.com.cn/desktopassist/modules/客户端根据此地址 按照规则拼出预览图的地址: $appid+$previeimgversion+previewimg+$图片名称 图片格式: SVG图片名称规则:小预览图:small.svg中预览图:medium.svg大预览图:big.svg

4.4.2.modules数组的字段:

字段名称类型描述
字段名称类型描述
app_id字符串模块的唯一标识
version字符串版本号
url字符串组件的H5地址,如果为空,则会尝试读取缓存目录下的h5/index.html
support_sizeint此模块支持的大小, 位操作 1:小 2:中 4:大. 譬如:如果大中小都支持,这位1+2+4=7
default_sizeint默认的大小 必须是 1,2或者4, 否则认为无效
title字符串模块的标题
sub_title字符串模块的子标题
default_showint此模块是否默认显示, 0表示默认不显示,1 表示默认显示
support_editint此模块是否支持编辑, 默认为0, 0表示不支持, 1表示支持
orderint模块排序

4.5.组件开发环境配置


•组件开发至少需要一个组件显示的H5页面, H5支持本地和云端页面,云端页面在无网情况下无法加载,会显示一个默认的加载失败页面。

4.5.1.开发环境搭建

4.5.1.1.基础环境(可使用开发工具进行开发环境搭建),此工具支持:

•允许开发者编辑组件目录下的文件

•使用本地组件列表,临时禁用服务器列表的请求

•包含示例H5组件的demo

4.5.1.2.运行开发者工具进行环境配置,配置完成后请重启桌面助手

组件目录为%ProgramData%\Lenovo\devicecenter\extends\modules, 以下用%DESKTOPASSISTMODULES%代替

4.5.2.H5组件配置

参考开发者工具中带的示例。

%DESKTOPASSISTMODULES%\modules.json 里添加组件(如下),具体的字段描述参考4.3.2

{
"app_id": "baidugushitong",
"default_show": 1,
"default_size": 2,
"sub_title": "股市信息",
"support_edit": 1,
"support_size": 7,
"title": "股市信息",
"url": "https://gushitong.baidu.com/",
"version": "1.0"
}

url填写H5页面的地址

4.6.组件开发接口能力说明

针对小组件H5开发,桌面助手框架提供了一些交互上的能力

页面目前支持三种大小,大小由框架来设置, 建议组件的H5实现自适应大小(譬如使用媒体查询)

H5的sample可以参考demomodule的H5代码

•组件大小、是否支持编辑由组件的配置来支持

•组件的拖动由框架来支持

•组件的编辑只支持大尺寸的显示,尺寸由框架来控制

4.6.1.框架接口

事件名称事件描述备注
window.onModuleEditFinish点击编辑完成需调用此事件编辑完成,子组件需要调用框架的onModuleEditFinish方法来通知框架

4.6.2.window.open

框架会拦截此方法,业务端可以调用此接口打开浏览器, 譬如:window.open('http:///www.baidu.com?s=1')

如果电脑安装了联想浏览器,则默认会使用联想浏览器打开,否则会使用默认浏览器打开

需要注意:使用浏览器打开指定的页面只能使用window.open。

4.6.3.页面接口

页面根据业务需要,实现相关的接口,来实现相关的业务功能

事件名称事件描述备注
window.onModuleEdit右键此组件,点击编辑,会触发此页面的函数举例:window.onModuleEdit = ()=>{ 组件内部逻辑处理 } 右键编辑,框架会调子组件的onModuleEdit方法来通知子组件 如果组件不支持编辑,可以不需要实现此接口
window.onModuleShow桌面助手显示会触发此事件
window.onModuleHide桌面助手隐藏会触发此事件
window.onModuleSetSize切换组件大小会触发此事件举例:window.onModuleSetSize = (evt) => { //size 1 小 2 中 4 大 console.log('onModuleSetSize:', evt, evt.size);}
window.onModuleActive桌面助手激活会触发此事件
window.onModuleDeactive桌面助手失去激活会触发此事件

4.6.4.扩展接口

根据业务的需要,框架会在升级的版本里提供一些扩展的接口

4.6.4.1.获取模块信息:

可以通过jssdk的方法获取当前模块的一些信息

调用方法:window.pcmjssdk.getModuleInfo()

返回:{version:'1.0', appid:''appid, extends:"extends"}

可以通过返回值获取当前模块的appid和version等信息

sample:window.pcmjssdk.getModuleInfo().version 获取当前模块的版本

框架支持的版本:所有

4.6.5.组件拖动

框架会hook鼠标的点击消息来完成页面的拖动,组件可以根据业务的需要来禁用此拖动。 譬如在编辑页面、文本框输入页面、button等

此功能只在桌面助手框架1.20及以上的版本支持

1)控件添加样式disablecomponentdrag, 譬如<div class="disablecomponentdrag"></div>

框架会递归查找父组件的样式,如果有此样式,则禁用拖动

2)页面实现window.allowDragComponet, 返回false表示禁用。 框架在点击时调用此方法来决定是否拖动, 参数为鼠标点击MouseEvent

示例:

window.allowDragComponet = (evt) = > 
{
     return (evt.pageY < 40); 
}

4.6.6.组件编辑

•组件如果支持编辑,则样式需要实现统一的反转动画,编辑态组件的大小和大组件的大小一致

•页面需要实现window.onModuleEdit, 在此方法里实现反转动画和页面的切换

•编辑完成后,需要调用框架接口:window.onModuleEditFinish,做页面的切换

具体可以下载 5.3章节的demomodule.zip

代码示例:

html 代码
<div id="content">展示页</div>
<div id="setting">编辑页</div>

css代码
#setting {
  transform: rotateY(0deg);
}
.rotate {
  transition: 0.3s;
  transform: rotateY(90deg);
}
.rotates {
  transform: rotateY(90deg)!important;
}

js代码
// 反转动画dom
  var settingDom = document.querySelector('#setting');
  var contentDom = document.querySelector('#content');
  settingDom.className = 'rotates';
  // TODO 用户点击了'编辑此小组件'
  window.onModuleEdit = (evt) => {
    settingDom.style.transition = '0.3s';
    contentDom.className = 'rotate';
    setTimeout(() => {
      // TODO 因为rotate存在过度动画0.3s 所以给setting的行为也延迟0.3s
      settingDom.className = '';
    }, 300);
  };
  //调用设置完成的接口
  function finishEdit() {
    settingDom.className = 'rotates';
    setTimeout(() => {
      contentDom.className = '';
      contentDom.style.transition = '0.3s';
      setTimeout(() => {
        window.onModuleEditFinish(); // 关闭大窗口
        contentDom.style.removeProperty('transition');
      }, 300);
    }, 300);
  }

4.6.7.小程序相关

助手1.80及以后的版本支持小程序相关的接口,jssdk增加了window.pcmjssdk.smallapp对象

在使用小程序相关的方法时,需要先判断此对象是否存在

譬如:

桌面助手1.80及以后的版本支持小程序相关的接口,jssdk增加了window.pcmjssdk.smallapp对象

在使用小程序相关的方法时,需要先判断此对象是否存在

譬如:

if (window.pcmjssdk.smallapp) { window.pcmjssdk.smallapp.asyncStart()}
接口名称接口描述备注
asyncStart启动组件的小程序组件的页面,可以在用户点击组件的时候调用 启动当前组件的小程序不需要传入参数,框架会负责加载组件对应的小程序页面 window.pcmjssdk.smallapp.asyncStart()
asyncStartWith带参数启动小程序助手1.130版本开始支持启动小程序的时候带上data参数

4.6.8.上线需要的材料

1.组件支持尺寸(大、中、小)和相关尺寸的图片,此图片必须是svg格式的矢量图,保证在各种DPI下显示的效果

2. 默认显示的尺寸,大中小选择一个

3.是否支持编辑

4.组件标题(在组件库里显示)

5.组件描述(在组件库里显示)

4.7.注意事项

4.7.1.线上的H5,不能禁用X-Frame-Options

4.7.2.H5的组件,图片建议使用svg矢量图,避免出现不同DPI下图片显示模糊的问题

4.7.3.组件H5页面禁止使用长期持续的动画(譬如CSS3、svga、svg等),避免较高的CPU功耗占用

4.7.4.线上的H5页面建议禁用cache, 否则需要处理断网情况下,页面缓存加载成功情况下的用户体验

4.7.5.为了减少电脑功耗,助手在托盘状态(托盘显示,页面隐藏)时,会将非Browser进程的子进程都suspend (所有JS的行为都会被禁用)

4.7.6.H5的组件禁止使用WebAssembly

4.7.7.用户没有使用组件的情况下,禁止高CPU的占用,避免较高的功耗使用。组件可以依赖5.3页面激活的通知来处理相关的业务,避免空闲状态的高功耗占用

4.7.8.桌面助手目前只支持win10及以后的系统

5.插件开发文档(内测中,可暂不开发提交)

5.1.智能体小程序概述

5.1.1.联想智能体产品概述

5.1.1.1产品简介

联想智能体是一款AI智能助手类产品,该产品预装联想AIPC发布,主要面向PC端用户。

该产品基于人工智能和大语言模型致力于为用户带来工作、生活、娱乐等全方面的服务,通过AI智能交互提升用户在使用电脑全流程的体验。

5.1.1.2 产品核心功能

1)联想智能体默认态:首屏露出,伴随态工作

2)联想智能体主页面,通过和联想智能体进行对话,生成智能回答

3)智能体小程序能力展示页面

通过智能体小程序,引入更多三方能力,为用户带来更丰富的产品体验

Eg. PPT助手

Step1 向联想智能体发起问题

Step2 调起PPT助手卡片

Step3 联想智能体生成PPT大纲

Step4 点击编辑大纲

Step5 拉起小程序窗口,体验更多功能

5.1.2.智能体小程序

联想智能体的智能体小程序,包含小程序和插件两部分。

插件作为联想智能体的扩展程序,通过用户指令调起并回复内容。插件通过提供更加专业的信息活第三方服务,丰富联想智能体的能力,与联想智能体配合更好地理解用户的意图,让用户可以获得更加便捷、高效、智能的服务和体验。

小程序Runtime可封装开发者应用的所有功能,为用户提供更深度的交互方式。当联想智能体的聊天对话框中不能满足插件全部功能时,开发者可以选择接入小程序,用小程序来提供给用户丰富的功能。同时小程序可以与联想浏览器、桌面助手的部分多个端进行集成,为开发者应用引流。

更多相关信息,请见接入指南。

5.2.接入指南

5.2.1.接入概述

实现面向用户的智能体小程序,需要完成两部分工作:

1)以云端插件方式,接入联想AI服务,实现对于用户意图的理解(必须),以便用户可以在联想智能体中使用该功能

2)如果有更多功能需要提供给用户,在联想智能体的对话页面中不足以支撑,可以接入小程序窗口,提供更多内容(非必须)

5.2.2.接入流程

接入流程图:

5.2.3设计规范

1)AI小程序的调用入口

通过点击「小程序」icon,即可勾选对应的小程序能力。

2)AI小程序的调用入口

联想智能体的AI小程序商店是一个专门展示和提供下载各种基于人工智能的小程序,为用户提供便捷的方式来探索和使用AI驱动的应用程序。

3)AI小程序的展示形式

AI小程序作为一种集成人工智能功能的应用程序,在联想智能体的产品端内通过生长屏的方式呈现,以提供用户友好的交互体验。

5.2.4.云端插件接入

5.2.4.1.插件工作原理简介

举个例子:用户在平台上选择天气插件,输入:“今天北京的天气怎么样?”, 模型首先会根据用户意图调用天气插件,并且解析query中时间(今天)和地点(北京)信息,然后以json结构输入开发者提供的天气API接口中,获得接口返回的天气信息,经过大模型进行语言润色后,生成面向用户的回答。

5.2.4.2.快速跑通云端插件开发全流程

1)构思插件 manifest 描述文件(ai-plugin.json,必选)

2)定义插件服务描述文件(openapi.yaml,必选)

3)编写示例描述文件(example.yaml,可选,强烈建议)

4)启动插件服务并且对齐描述文件(openapi服务,必选)

5)上传配置文件并调试(接入流程,必选)

6)发布到插件市场(分享发布,可选)

5.2.4.3.如何从0-1开发云端插件

创建一个插件必备的步骤:

1)构思插件 manifest 描述文件(ai-plugin.json,必选)

2)定义插件服务描述文件(openapi.yaml,必选)

3)编写示例描述文件(example.yaml,可选)

4)启动插件服务(openapi服务, 必选)

1、构思插件 manifest 描述文件(ai-plugin.json,必选)

一个插件需要一份ai-plugin.json命名的manifest文件,这个文件需要描述插件的基本信息。具体示例及要求见5.2.4.2

2、定义插件服务描述文件(openapi.yaml,必选)

您的APIs定义描述文件需要满足OpenAPI标准(详见https://swagger.io/specification )

我们只能获取到您在API描述中明确定义的内容。这意味着您只需要向模型暴露插件能力实现必要的API端点,无需暴露所有API端点。

基础的OpenAPI格式的API描述见5.2.4.2

3、编写示例描述文件(example.yaml,可选)

说明:example机制可帮助开发者提供示例,提升插件调用的正确率。

为了保障模型触发的效果,每个example.yaml 文件中最多提供 3 个示例。每个example.yaml 文件的长度建议不超过 300 个字符,具体描述见2.4.2

4、开发自己的plugin-server

注意:为了给用户提供更好的体验,插件服务有超时要求:0.5s连接超时,3s读超时,2s读响应头超时,如果插件服务内部处理流程较长,建议采用sse流式方式及时返回,为用户显示执行动作。

注意:将以上编写的插件文件直接选中,然后压缩上传,不要将插件文件所在的文件夹压缩后上传

5、其它进阶开发说明

(一)API接口开发注意事项:

1)接口支持8种http协议,支持restFul风格的http接口

2)入参支持body传参,path传参,header传参(同名参数将不做位置区分),当前不支持无参接口触发

3)当前api接口支持如下三种媒体类型:

a)application/json json类型

b)multipart/form-data 表单类型

c)application/x-www-form-urlencoded 媒体表单

4)api接口返回仅支持在body中返回json数据,支持sse流式返回内容,api流式返回时,模型只认为最后一条结果为最终结果前面返回的数据将被忽略,强烈建议将json格式化为一行返回,多行返回将会被解释为流式返回,导致内容不全

5)prompt、errCode、errMsg、actionName、actionContent为保留字段:

prompt:prompt字段将会作为模型的回复规范进入大模型

errCode:返回此字段不为0时,系统将认为api调用失败

errMsg:暂无

actionName:此字段将在前端界面显示前部分内容

actionContent:此字段将在前端界面显示后部分内容

(二)插件为用户显示执行动作

如果您希望将插件的执行动作,显示在用户前端,可在返回 json 内容中,包含如下几个字段:状态码(errCode)、状态名(actionName)、状态内容(actionContent)

规范要求:一组执行动作,包括 1 个动作名(actionName)和1 个动作内容(actionContent)。此执行动作将会显示给用户,并且将

每一组执行动作中,动作名可重复,动作内容不可重复, 例如:阅读文档|开始阅读文档;阅读文档 | 完成阅读文档

要求
状态码(errCode)平台约定字段,无需在 yaml 文件中定义仅支持数字和字母,不超过 10 个字符
状态名(actionName)仅支持中文汉字,不超过 8 个字符,建议使用 4 个字符,且各动作名称要简单概要
状态内容(actionContent)仅支持中文汉字,不超过 50 个字符,建议尽量简短可描述执行动作的内容、状态、错误信息等

5、其它进阶开发说明

(一)API接口开发注意事项:

1)接口支持8种http协议,支持restFul风格的http接口

2)入参支持body传参,path传参,header传参(同名参数将不做位置区分),当前不支持无参接口触发

3)当前api接口支持如下三种媒体类型:

a)application/json json类型

b)multipart/form-data 表单类型

c)application/x-www-form-urlencoded 媒体表单

4)api接口返回仅支持在body中返回json数据,支持sse流式返回内容,api流式返回时,模型只认为最后一条结果为最终结果前面返回的数据将被忽略,强烈建议将json格式化为一行返回,多行返回将会被解释为流式返回,导致内容不全

5)prompt、errCode、errMsg、actionName、actionContent为保留字段:

prompt:prompt字段将会作为模型的回复规范进入大模型

errCode:返回此字段不为0时,系统将认为api调用失败

errMsg:暂无

actionName:此字段将在前端界面显示前部分内容

actionContent:此字段将在前端界面显示后部分内容

(二)插件为用户显示执行动作

如果您希望将插件的执行动作,显示在用户前端,可在返回 json 内容中,包含如下几个字段:状态码(errCode)、状态名(actionName)、状态内容(actionContent)

规范要求:一组执行动作,包括 1 个动作名(actionName)和1 个动作内容(actionContent)。此执行动作将会显示给用户,并且将

每一组执行动作中,动作名可重复,动作内容不可重复, 例如:阅读文档|开始阅读文档;阅读文档 | 完成阅读文档

要求
状态码(errCode)平台约定字段,无需在 yaml 文件中定义仅支持数字和字母,不超过 10 个字符
状态名(actionName)仅支持中文汉字,不超过 8 个字符,建议使用 4 个字符,且各动作名称要简单概要
状态内容(actionContent)仅支持中文汉字,不超过 50 个字符,建议尽量简短可描述执行动作的内容、状态、错误信息等

插件返回的最后一个 json 是作为进入大模型的实际内容。前面的几个 json,都是为了显示调用动作。

5.2.4.4.云端插件关键注释文件详解

一、关键注册文档详解

1、ai-plugin.json(必选)

一个插件需要一份ai-plugin.json命名的manifest文件,这个文件需要描述插件的基本信息。以下是简单的示例,这个示例创建了一个名为“单词本”的插件。

ai-plugin.json(必填)

{
    "schema_version": "v1.0.0",
    "name_for_human": "应用商店助手",
    "name_for_model": "store_aigc_996",
    "description_for_human": "应用商店AI助手,可以推荐应用, 下载应用以及进行应用相关的对话",
    "description_for_model": "应用商店(包括软件和游戏)的管理员小天智能, 对任何软件和游戏了如指掌, 可以推荐应用、下载应用、进行应用相关的对话",
    "auth": {
        "type": "none"
    },
    "logo_url": "http://127.0.0.1:8081/logo.png",
    "contact_email": "gongjun3@lenovo.com",
    "legal_info_url": "http://www.example.com/legal"
    }

ai-plugin.json 文件总长度建议不超过 1500 字符,其中各字段的要求详见下方表格:

插件注册字段:

关键字类型描述/选项是否必填
schema_versionString插件的版本号,用于开发者标记和使用
name_for_modelString模型将用于定位插件的名称(不允许使用空格,只能使用字母和数字)此字段将作为插件的唯一标识。描述请带有一定的语义,不要超过20个字符。
name_for_humanString此字段将面向用户查看,是插件对外公开的名字。不超过20个字符。建议编写时按照如下要点顺序: “插件能力->适用场景->使用条件”
description_for_modelString面向模型的自然语言描述,请描述插件的核心能力、使用场景等,将用于模型参考解析是否触发插件,建议不超过200个字符。
description_for_humanString面向用户介绍插件,建议介绍插件的主要能力,相关限制等。不超过100个字符,前端可完整显示前40 个字符,超出的字符将在用户 hover 时展示。
authObject提供了noAuth,服务级鉴权方式;可支持对服务鉴权方式
logo_urlString用于获取插件标识的URL。建议大小:512 x 512。支持透明背景。必须是图像,不允许使用GIF。
contact_emailString安全/审核、支持和停用的电子邮件联系方式
legal_info_urlString用户查看插件信息的重定向URL
pluginTypeString插件类型,{SERVICE,TOOL,AIGC}
uploadObject定义插件服务是否支持上传附件,以及支持上传附件的类型

auth

关键字类型描述/选项
typeString支持两种:"none"、"service_http"
authorization_typeStringtype = "service_http" 有效,支持basic,bearer,apiKey
verification_tokensObject对应的tokens

verification_tokens

关键字类型描述/选项
tokensStringbearer 类型授权生效
user_nameStringbasic 类型授权生效
passwordStringbasic 类型授权生效
locationString参数位置:header、 query,apiKey 类型授权生效
param_nameString参数名称,apiKey 类型授权生效
api_keyString密钥key,apiKey 类型授权生效
api_key_prefixString前缀,apiKey 类型授权生效

upload

关键字类型描述/选项
support_uploadboolean插件是否支持上传附件
upload_typesString支持上传的附件类型 例如:png,txt
max_file_sizeint最大上传文件限制单位Mb

2、openapi.yaml(必选)

openapi.yaml是描述插件接口和参数的文件,描述写法直接影响效果,请务必认真阅读下方的内容,按照规范来开发该文件。

您的APIs定义描述文件需要满足OpenAPI标准(详见https://swagger.io/specification/)

联想插件平台只能获取到您在API描述中明确定义的内容。这意味着您只需要向模型暴露插件能力实现必要的API端点,无需暴露所有API端点。

一个基础的OpenAPI格式的API描述如下所示:(openapi的version必须是3.0.1)

openapi.yaml(必填)

openapi: 3.0.1
info:
    title: 软件商店AI助手
    description: 软件商店(包括软件和游戏)的管理员小天智能, 对任何软件和游戏了如指掌, 可以推荐软件、下载软件、进行软件相关的对话。
    version: "v1"
servers:
    - url: https://cloud-ai-core.mbgtest.lenovomm.com/api
paths:
    /app_talk:
        post:
            operationId: appTalk
            description: 回复软件和游戏相关性对话
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: "#/components/schemas/appTalk"
            responses:
                "200":
                    description: 回复生成成功
                    content:
                        application/json:
                            schema:
                                $ref: "#/components/schemas/appTalkResponse"
    /generate_app_recommend:
        post:      
            operationId: generateAppRecommend
            description: 推荐电脑软件和游戏
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: "#/components/schemas/generateAppRecommend"
            responses:
                "200":
                    description: 推荐信息生成成功
                    content:
                        application/json:
                            schema:
                                $ref: "#/components/schemas/appRecommendResponse"
    /generate_download_app:
        post:
            operationId: generateDownloadApp
            description: 为用户提供下载与安装软件的识别信息
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: "#/components/schemas/generateDownloadApp"
            responses:
                "200":
                    description: 识别下载应用生成成功
                    content:
                        application/json:
                            schema:
                                $ref: "#/components/schemas/downloadAppResponse"
  
components:
    schemas:
        appTalk:
            type: object
            required: [ appQuestion ]
            properties:
                appQuestion:
                    type: string
                    description: 软件和游戏的相关提问
        generateAppRecommend:
            type: object
            required: [appRequirements]
            properties:
                appRequirements:
                    type: array
                    items:
                        type: string
                    description: 推荐软件和游戏需求列表
        generateDownloadApp:
            type: object
            required: [ appName ]
            properties:
                appName:
                    type: string
                    description: 下载软件的名称或简称
        appTalkResponse:
            type: object
            required: [ answer,prompt]
            properties:
                answer:
                    type: string
                    description: 软件相关对话的回复
        appRecommendResponse:
            type: object
            required: [appList,prompt]
            properties:
                appList:
                    type: array
                    items:
                        type: object
                        required: [appName, introduction]
                        description: 软件信息
                        properties:
                            appName:
                                type: string
                                description: 软件名称
                            introduction:
                                type: string
                                description: 软件介绍
                    description: 软件推荐列表
  
        downloadAppResponse:
            type: object
            required: [ appName, introduction,prompt ]
            description: 软件信息
            properties:
                appName:
                    type: string
                    description: 软件名称
                introduction:
                    type: string
                    description: 软件介绍
事项规范说明
yaml 文件总长度YAML 文件总长度,不可超过 1000个字符 (不包含空格)
pathsrequest:数量:定义 1-2 个接口 (建议)api_id 不可超过 20 个字符 接口描述 summary 和 description在 description 字段中描述详细的接口介绍,长度不超过 150 个字符 (强制) summary 字段可抽象接口能力,长度不超过 50 个字符 (强制)存在 description,则优先使用 descriptionresponse:body中不要返回状态码、错误码 (建议)body仅给和插件结果相关的信息 (比如结果文本) (建议)错误码用http code表示 (建议)
components参数名称:最多 20 个字符,使用 string 类型 (强制)参数描述:最多 50 个字符,使用 string 类型 (强制)参数数量:参数不超过 5 个 (建议)参数类型:建议使用string, number,boolean;array和包含复杂嵌套的object不建议使用 (建议)

接口描述 description 需要清晰、全面地描述接口的功能,有助于插件平台正确地理解该接口的功能。以下通过一个具体例子来说明该字段对触发效果的影响。

3、example.yaml(可选但强烈建议)

说明:example机制可帮助开发者提供示例,提升插件调用的正确率。

为了保障模型触发的效果,可以提供一个example.yaml 文件,其中最多提供 3 个示例。

example.yaml 文件的长度建议不超过 300 个字符

example.yaml(可选但强烈建议)

version: 0.0.1
examples:
  - context: # 对话历史
      - role: user
        content: wps包含了哪些功能
      - role: bot
        # 触发插件
        plugin:
          # 应当触发的接口operationId
          operationId: appTalk
          # 思考过程,对触发有帮助
          thoughts: 这是询问软件功能的需求
          requestArguments:
            appQuestion: "wps包含了哪些功能"
            query: wps包含了哪些功能
      - role: user
        content: 推荐3个免费的pdf编辑软件
      - role: bot
        # 触发插件
        plugin:
          # 应当触发的接口operationId
          operationId: generateAppRecommend
          # 思考过程,对触发有帮助
          thoughts: 这是一个推荐软件的需求
          requestArguments:
            appRequirements: "[3个,免费,pdf编辑]"
            query: 推荐3个免费的pdf编辑软件
      - role: user
        content: 请帮我介绍下第一个推荐的软件
      - role: bot
        # 触发插件
        plugin:
          # 应当触发的接口operationId
          operationId: appTalk
          # 思考过程,对触发有帮助
          thoughts: 读取上下文理解用户软件介绍的需求
          requestArguments:
            appQuestion: "请帮我介绍下第一个推荐的软件"
            query: 请帮我介绍下第一个推荐的软件
      - role: user
        content: 我要下载安装爱奇艺
      - role: bot
        # 触发插件
        plugin:
          # 应当触发的接口operationId
          operationId: generateDownloadApp
          # 思考过程,对触发有帮助
          thoughts: 这是一个识别下载安装软件识别信息的需求
          requestArguments:
            appName: "爱奇艺"
            query: 我要下载安装爱奇艺
      - role: user
        content: 推荐几个最火的应用
      - role: bot
        # 触发插件
        plugin:
          # 应当触发的接口operationId
          operationId: generateAppRecommend
          # 思考过程,对触发有帮助
          thoughts: 这是一个需要理解语义推荐软件的需求
          requestArguments:
            appRequirements: "[热门应用]"
            query: 推荐几个最火的应用

4、 msg_content.yaml(可选)

说明:插件动作消息注册文件,为yaml格式,用于描述和定义了插件动作,该动作可以显示在插件信息栏中。

# yaml文件中定义的operationId
queryweatherInfo:
  # 标识插件调用失败的错误码和文案
  error:
    - errCode: "500"
      actionName: 查询失败
      actionContent: 天气查询失败,建议您换一个话题,更新描述后可再次尝试
  success: 
    - errCode: "10000"
      actionName: 执行成功
      actionContent: 插件执行成功
  # 有时使用sse返回,执行过程中有很多过程,都应该定义为成功
    - errCode: doing
      actionName: 开始执行
      actionContent: 开始查询天气信息
    - errCode: complete
      actionName: 执行完成
      actionContent: 查询完成,已返回天气信息
      
  # 此错误码用于帮助用户自查,显示提示用户错误信息
  # user_error中定义的错误码,在插件返回此类错误码时,会将错误显示提示给用户,同时针对此类错误码,我们将不会认为是插件无法正常提供服务
  user_error: 
    - errCode: "1"
      actionName: 执行错误
      actionContent: 无法查询近15天以外的天气信息
      
# 可定义通用的错误码和文案,将为每一个api追加common中的内容
# common为保留字,如果将一个api的operationId定义为了common,此处定义的错误码仍会生效到每一个api上
common:
  # 同上
  error:
    # 如果错误码与其他operationId中定义的相同,以其他operationId为准
    - errCode: "401"
      actionName: 鉴权失败
      actionContent: 鉴权信息已过期,请重新登录

二、如何设置大模型直接输出插件返回结果

本章节针对openapi.yaml升级相关扩展规范而制定。 依据该规范,开发者可以更灵活的设置模型对于插件api的json输出结果的润色逻辑,以满足不同场景下对于json转自然语言的差异性需求,可以支持模型返回json结果中指定字符串直接输出。

规范使用说明:

扩展规范写法:在Operation对象级增加扩展字段。

x-return-raw:
    - description: 标记当前API请求的结果是否经过大模型,当name的值不空时,从插件结果中获取具体字段,类型必须string,直接返回,而不经过大模型。
    - mediaType: application/json
    - name: this_is_a_field_name
    - type: string

具体规范字段位置: 整体放置于接口定义下的post节点下,与operationId、requestBody等字段并列。

规范字段含义说明:

  • x-return-raw 为配置当前API不经过大模型的配置根节点,名字固定。下面包括4个成员。分别如下:
  • description: 非空的字符串 - 不可缺少,内容不空,填写本规范的相关描述信息。其中“标记当前API请求的结果是否经过大模型,当name的值不空时,从插件结果中获取具体字段,类型必须string,直接返回,而不经过大模型。” 为示范。
  • mediaType: application/json - 固定写法,其含义是目前的规范仅仅在metaType所设定的api接口上生效,不支持其他值。
  • type: string - 固定写法,其含义是 return-raw所获取的字段的类型必须是string,不支持多级嵌套的json 字段结构。
  • name: 非空的字符串 - 其含义是 从api接口所返回responses字段中,根据此字段获取接口的原始信息,最终返回给用户。

x-return-raw代码示例

paths:
    /this/is/a/post/api
        post:
            operationId: xxxx
            summary: this is operation xxxx
            requestBody:
              content:
                'application/json':
                  schema:
                    properties:
                      field_str1:
                        description: this is field_str1
                        type: string
                      field_int1:
                        description: this is field_int1
                        type: int
            responses:
                "200":
                    description: 接口执行成功
                    content:
                        application/json:
                            schema:
                                $ref: "#/components/schemas/xxxxResponseOK"
             
            x-return-raw:
                description: 标记当前API请求的结果是否经过大模型,当name的值不空时,从插件结果中获取具体字段,类型必须string,直接返回,而不经过大模型。
                mediaType: application/json
                name: this_is_a_field_name
                type: string

三、如何改善最终润色输出结果

什么是润色功能?

当通过x-return-raw参数控制,不直接返回插件的最终结果后,插件平台会默认会对插件的响应结果进行润色,得到最终返回给用户的结果,插件平台的润色功能可以让结果更自然语言化,更贴近人类的阅读习惯;但默认的润色效果却很难保证,为改善最终润色输出的结果,插件平台提供了prompt优化最终结果的能力;

以单词本插件为例,当需要背单词时,该插件接口的返回结果为:“words: hello,love,like”,而最终插件平台会输出:”为您提供以下单词:hello,love,like;祝你***”,即插件平台对插件返回结果润色后的输出。如果希望输出结果符合某种规范,可以使用润色 prompt 对结果进行控制。**

润色 prompt 怎么写?

在开发插件的过程中,可以通过编写润色 prompt 使插件平台对插件返回结果按照指定的要求进行润色。该功能需要在插件返回的结果中添加 prompt 字段,插件平台会按照 prompt 字段的内容,对插件结果进行润色

注意:这里一定保"prompt":prompt在返回json的第一层级,不要调整层级结构

Case 1: 如不需要插件平台对插件结果进行润色,使最终输出结果更加稳定,可以**在插件服务代码中**通过如下 prompt 进行控制:

Case 2:如果希望插件平台对插件返回结果按照某种规范进行输出,则可以编写相应的 prompt 指令进行控制:

四、如何指定客户端调用

规范使用说明:

扩展规范写法:在Operation对象级增加扩展字段。

x-operation

x-operation:
    - description: 标记当前函数为客户端命令,直接把函数名返回客户端。
    - type: command

具体规范字段位置: 整体放置于接口定义下的post节点下,与operationId、requestBody等字段并列。

规范字段含义规范说明:

· type:  函数操作的类型,command - 本地执行指令,call- 客户端执行函数调用请求。

· description: 非空的字符串 - 不可缺少,内容不空,填写本规范的相关描述信息。

· baseUrl: call类型下可选回调地址

x-operation代码示例

paths:
    /this/is/a/post/api
        post:
            operationId: xxxx
            summary: this is operation xxxx
            requestBody:
              content:
                'application/json':
                  schema:
                    properties:
                      field_str1:
                        description: this is field_str1
                        type: string
                      field_int1:
                        description: this is field_int1
                        type: int
            responses:
                "200":
                    description: 接口执行成功
                    content:
                        application/json:
                            schema:
                                $ref: "#/components/schemas/xxxxResponseOK"
             
            x-operation:
                description: 非空的字符串 - 不可缺少,内容不空,填写本规范的相关描述信息。
                type: command

五、如何提升插件触发应用效果

模型触发效果与插件描述文件、API描述文件都有很大关联,可以通过以下方式尝试优化。

#### 提升接口触发准确率:

Q:服务有多个接口,调错接口,怎么优化?

A:请检查openapi.yaml(必选)文件中的接口描述,重点关注description字段,检查该字段是否清楚地描述了接口功能,与用户的query是否在语义上是否具备一定的相关性;

不同的接口,description字段必须有所区别,体现出每个接口自己的功能特点,否则容易调错;

具体请参考openapi.yaml(必选)中的样例;

Q:不该触发的query,误触发插件,怎么优化?

A:建议在example.yaml(可选但强烈建议有)中增加不希望触发的负样例,需要有代表性,通常是有一定区分难度的负样例;

#### 提升接口填参准确率:

Q接口可以正确触发,但填参结果不准确,或者不稳定,怎么优化?

A:

· 如果还没有添加example.yaml,强烈建议增加example,每个接口覆盖最典型的case,具体参考example.yaml(可选但强烈建议);

· 请检查参数的description字段描述,是否清晰、准确、简洁地描述了参数值的内容应该是什么,尽量避免使用语义不明确的行业黑话;

#### 提升触发召回率:

Q:预期触发的query,无法触发,怎么优化?

A:请检查openapi.yaml(必选)文件是否清晰描述了插件功能,检查openapi.yaml(必选)文件是否清晰描述了接口功能,应严格根据以上两个文档下方的字段要求进行字段内容的填写,否则会直接影响触发的效果;

#### 提升润色准确率:

Q:我想指定插件返回结果的输出规范,不想让插件平台自己发挥,怎么改?

A:具体请参考如何进行结果润色中插件返回结果润色prompt的写法建议;

#### 提升多轮效果:

Q:我希望构造多轮对话的example,以此来提升多轮的效果,怎么构造?

A:请参考example.yaml(可选但强烈建议有),第一个example即多轮对话,user、bot的内容交替出现;

#### 其他问题:

Q:对于参数的格式有特殊要求,比如希望某个参数的值限定在一个封闭集合里,怎么写?

A:参考openapi的规范 https://github.com/OAI/OpenAPI-Specification/blob/3.0.1/versions/3.0.1.md#responseObject

5.2.5.客户端小程序接入

5.2.5.1.背景

目前文心一言闲聊的数据格式是MarkDown格式的,为了保证更好的兼容性和后续扩展性,端上的小程序聊天聊天的显示数据也使用MarkDown格式

5.2.5.2.注意项

小程序的H5是以IFrame的方式显示的,线上的H5不能禁用X-Frame-Options

5.2.5.3.MarkDown格式

联想智能体的聊天显示支持标准的MarkDown格式,具体参考:Markdown Guide

为了支持聊天数据可以打开小程序,支持了自定义协议

5.2.5.4.MarkDown 打开&更新小程序(非必须)

如果需要打开小程序,MarkDown需要使用自定义协议格式的链接,格式如下:

jsbridge://laa.smallapp?appid=122&type=1&url=https%3A%2F%2Fwww.baidu.com&data=

  • jsbridge: 必选项,自定义协议 固定为jsbridge
  • laa.smallapp:  LAA小程序的协议,固定为laa.smallapp

此链接是一个自定义协议,框架根据此协议来打开或者更新小程序

针对laa.smallapp 小程序协议的字段描述(每个字段的数据都需要urlencode,如&abc=xxx中字段abc的值xxx需要encode)

字段名称是否可选描述备注
appid必选此小程序的appid暂定和插件id保持一致
type可选默认为00 如果不存在此appid的小程序,则以url打开此小程序。如果已经存在则通知小程序小程序相关的信息,由小程序来做处理1 如果不存在此appid的小程序,则以url打开此小程序。如果已经存在则刷新此小程序的url
url可选如果没有定义url,并且此appid的小程序还没有打开,则点击没有效果
data可选上下文的数据此数据会通过jssdk透传通知到小程序的H5

5.2.5.5.示例(MarkDown) (非必须)

## 背景介绍

* AIPC定义

* AIPC的重要性

[编辑大纲](jsbridge://laa.smallapp?appid=122&url=https%3A%2F%2Fwww.baidu.com)

根据MarkDown的规则,编辑大纲在界面上显示为一个链接

点击链接后,框架会负责将jsbridge的协议的参数处理为json格式的数据,并以此参数打开小程序

5.2.5.6.API接入

概述

  • 默认都是异步接口
  • 除了事件监听(如以 jsbridge.on开头)和特殊说明的,都以 Promise 风格调用
  • 同步接口加标识 sync,如 jsbridge.getLaunchOptionsSync()
  • 以 jsbridge.on 开头的 API 是监听某个事件发生的 API 接口,接受一个 CALLBACK 函数作为参数。当该事件触发时,会调用 CALLBACK 函数。

基础

启动

jsbridge.getLaunchOptions()

功能描述

异步获取小程序启动信息

小程序启动后,获取启动小程序的参数和信息

参数

返回值

Object res

启动参数

属性类型说明
queryObject启动小程序的 query 参数

query说明

Object

属性类型说明是否必须返回
appidstring此小程序的appid暂定和插件id保持一致
urlstirng如果没有定义url,并且此appid的小程序还没有打开,则点击没有效果
datastirng通过智能体传递的上下文的数据此数据会通过jssdk透传通知到小程序的H5

示例代码

jsbridge.getLaunchOptions().then(res => {
  const query = res.query
  console.log(query.appid)
  console.log(query.url)
  console.log(query.data
})
jsbridge.onSmallAppNotify()

功能描述

小程序接收通知

小程序的框架会负责将jsbridge协议的数据解析为json格式的字符串,并通知到小程序页面

参数

回调函数参数

Object res

属性类型说明
queryObject启动小程序的 query 参数

query说明

Object

属性类型说明是否必须返回
appidstring此小程序的appid暂定和插件id保持一致
urlstirng如果没有定义url,并且此appid的小程序还没有打开,则点击没有效果
datastirng通过智能体传递的上下文的数据此数据会通过jssdk透传通知到小程序的H5

示例代码

jsbridge.onSmallAppNotify(res => {
  const query = res.query
  console.log(query.appid)
  console.log(query.url)
  console.log(query.data)
})

设备

系统

jsbridge.getSystemInfo()

功能描述

异步获取系统信息

返回值参数

Object res

属性类型说明
SDKVersionstring客户端基础库版本(即JSSDK版本)
modelstring设备型号
brandstring设备品牌
systemstring操作系统及版本
platformstring客户端平台(windows、android)
pixelRationumber设备像素比
screenWidthnumber屏幕宽度,单位px
screenHeightnumber屏幕高度,单位px

示例代码

jsbridge.getSystemInfo().then(res => {
  console.log(res.platform)
  console.log(res.model)
  console.log(res.SDKVersion)
  console.log(res.brand)
  console.log(res.system)
  console.log(res.pixelRatio)
  console.log(res.screenWidth)
  console.log(res.screenHeight)
})

5.2.6.客户端小程序调试开发

小程序框架主程序为联想智能体安装目录的根目录下的XLSmartApp.exe,可使用5.2.5.4 中 MarkDown格式对应的参数调起XLSmartApp.exe来运行小程序框架,小程序运行后会加载url参数表示的页面,加载完成后可打开控制台进行调试开发。

5.2.6.1.小程序运行启动

启动步骤如下:

1)安装联想智能体开发包

2)使用命令行 --message=xxx 调起联想智能体安装根目录(默认: C:\Program Files\Lenovo\AIAgent)下的XLSmartApp.exe,其中xxx为Json格式参数,参数的key参考5.2.5.4 中的表格。

示例(调试阶段appid可以是任意非空字符串):

命令行参数对应的 MarkDown格式链接
XLSmartApp.exe --message={"appid":"123","url":"https://miniprogram.lenovomm.com/api/index.html","data":"123"}jsbridge://laa.smallapp?appid=123&url=https%3A%2F%2Fminiprogram.lenovomm.com%2Fapi%2Findex.html&data=123

5.2.6.2.H5页面调试

为方便调试开发,在小程序运行后,使用Shift + F11 快捷键可打开控制台进行调试开发。(若开启了FnLock,则快捷键为Shift + Fn + F11)

示例:

小程序运行后打开控制台,使用jsbridge.getLaunchOptions() 获取启动参数

联想智能体小程序发布指南

1. 进入“联想开放平台”,并登录您的账号。

2. 从首页进入“管理中心”,选择“智能体小程序“,点击“创建”。

3. 创建类型选择“智能体小程序”,点击“下一步”。

4. 在此“基本信息”界面,您需要依次填写名称、icon、一句话描述、适用平台、选择类型、选择分类(标注*为必填项),完成后点击“提交审核”,详情见下文。

注:

1)”类型”提交后不可修改。

2)“选择分类”在“类型”选定后才可选

3)icon命名格式

5. 在”插件包体管理”界面上传插件包

6. 在“小程序管理”界面填写小程序网址,点击确定后,出现下拉界面,依次填写“是否联运”、“窗口启动尺寸”、“是否可以拉伸”、“窗口最小尺寸和最大尺寸”。

注:

1)联运为与联想联合运营,支付接入联想支付,详见联运文档。

7. 在组件信息界面填写”是否支持组件”、选择”是“则需依次填写“组件链接、是否具有右键编辑能力、上传组件缩略图、组件默认尺寸”,选择“否”则无需下拉相关信息。

注:

1)组件链接详见开发指引。

2)右键编辑能力则为支持用户右键自定义编辑。

3)组件缩略图用于库内组件展示,格式为SVG,尺寸分为大(150px*150px)、

     中(256px*120px)、小(150px*150px)三种,命名需以big/medium/small命名。

8. 在补充材料界面填写备注和上传相关资质证明及补充材料,然后点击提交审核即可。

注:小程序页面中,如涉及新闻信息、即时通信、网络直播、系统工具、网络社交、网络支付、加密代理、网络金融类应用需提交ICP证或ICP备案截图等资质或代理授权书,请上传JPG/PNG/JPEG格式的软件著作权证书,不大于15M。

9. 提交审核后,我们将在3个工作日内完成审核。若审核通过,将按照您的要求即时或定时发布应用;若审核未通过,我们会将详情反馈至开放平台的消息中心与您的邮箱。

想开放平台地址:联想开放平台

联想开发者专属QQ客服(工作日9:30-18:00):联想开发平台首页右侧悬浮的在线客服聊天入口可直接会话。也可搜索官方客服QQ号2881414004。

联想应用商店微信公众号:

  • 18
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值