助理调用说明
1.认证打通
1.1.快速接入
适用目标客户:私有化客户接入 信任三方传递的用户信息,保存并且组装上下文。
1.2.标准三方
适用目标客户:百度云、飞书、钉钉、企微等 使用第三方的登录页面,登录成功之后返回IDP登录校验并获取用户信息
流程说明
- 通过超级助理登录页面选择登录方式。
- 点击跳转到对应的登录页面地址并携带 超级助手登录地址作为跳转地址 eg:百度云登录地址 https://login.bce.baidu.com/?redirect=https://superhelper.bce.baidu.com/api/idp/v1/authentication/login?state=IAM&u=https://superhelper.bce.baidu.com/helper/web/dashboard
参数说明:
参数 | 说明 |
---|---|
api/idp/v1/authentication/login | IDP登录地址 |
state | 登录来源 |
u | 登录成功之后跳转地址(非必须) |
- IDP服务处理,根据state判断登录来源,获取对应认证code或token访问对应认证地址获取用户信息。 本地存储用户信息并生成验证cookie:login_auth_type,方便后续的每次请求拦截认证校验
2.「助理」使用方式
2.1 OpenApi 使用步骤
2.1.1 访问凭证获取
通过ak/sk获取超级助理颁发的访问凭证tenant_access_token
接口说明
GET https://{host}/api/idp/v1/accessToken/get
请求参数
字段 | 说明 |
---|---|
ak | 应用颁发KEY |
sk | 应用颁发Secret Key |
返回参数
{
"success": true,
"code": 200,
"msg": "ok",
"data": "ePMbrL87v8PNcB4UPixxx......xxxNpEGHqTk498QYS7qFiKVz1=="
}
2.2.2 API调用
接口说明:
GET https://{host}/open/api/aiChat/conversation
请求参数
RequestHeader
字段 | 必要 | 说明 |
---|---|---|
Authorization | Y | 'Bearer {tenant_access_token}' 请求头中添加应用凭证 |
Accept | N | text/event-stream |
RequestParam
字段 | 必要 | 说明 |
---|---|---|
content | Y | 用户输入的问题 |
userId | N | 当前使用者的用户ID |
userName | N | 当前使用者的用户名称 |
userId和userName有助于业务逻辑中对当前使用者提供更好的处理
响应结果
响应结果示例
event:ack
data:{"msgType":"","userInfo":{"userId":"0","avatar":""},"msgId":"1791352321427951616","questionId":"","conversationId":"","docKey":"","orderId":7013,"actionType":"","timestamp":0,"contents":null,"vertical":"","verticalGroup":"","debugInfo":"aichat-server_cp3fcue25l5mmnu34di0","reqDebug":null,"logId":""}
event:loading
data:{"msgType":"intent","userInfo":{"userId":"","avatar":""},"msgId":"","questionId":"","conversationId":"","docKey":"","orderId":0,"actionType":"","timestamp":0,"contents":"","vertical":"","verticalGroup":"","debugInfo":"aichat-server_cp3fcue25l5mmnu34di0","reqDebug":null,"logId":""}
event:loading
data:{"msgType":"identifying","userInfo":{"userId":"","avatar":""},"msgId":"","questionId":"","conversationId":"","docKey":"","orderId":0,"actionType":"","timestamp":0,"contents":"","vertical":"","verticalGroup":"","debugInfo":"aichat-server_cp3fcue25l5mmnu34di0","reqDebug":null,"logId":""}
event:loading
data:{"msgType":"generating","userInfo":{"userId":"","avatar":""},"msgId":"","questionId":"","conversationId":"","docKey":"","orderId":0,"actionType":"","timestamp":0,"contents":"正在生成回答","vertical":"verticalPublic","verticalGroup":"verticalPublic","debugInfo":"aichat-server_cp3fcue25l5mmnu34di0","reqDebug":null,"logId":""}
event:message
data:{"msgType":"aigc","userInfo":{"userId":"assistant","avatar":""},"msgId":"1791352321440534528","questionId":"1791352321427951616","conversationId":"","docKey":"","orderId":0,"actionType":"","timestamp":1715926650262,"contents":[{"type":"vertical-title","contents":{"text":"基于「千帆千亿问答」回答","pluginName":"千帆千亿问答","pluginVersion":""}}],"vertical":"verticalPublic","verticalGroup":"verticalPublic","debugInfo":"logId=aichat-server_cp3fcue25l5mmnu34di0","reqDebug":null,"logId":""}
data:{"msgType":"aigc","userInfo":{"userId":"assistant","avatar":""},"msgId":"1791352321440534528","questionId":"1791352321427951616","conversationId":"","docKey":"","orderId":0,"actionType":"","timestamp":1715926650263,"contents":[{"type":"ai-markdown","contents":{"text":"你好"}}],"vertical":"verticalPublic","verticalGroup":"verticalPublic","debugInfo":"logId=aichat-server_cp3fcue25l5mmnu34di0","reqDebug":null,"logId":""}
event:finish
data:end
响应结果说明
- event 消息类型:
event 类型 | 说明 |
---|---|
ack | 开始发送消息 |
loading | 消息加载中 |
message | 需要渲染的消息 |
finish | 发送消息完成 |
- data 消息体:
字段 | 说明 |
---|---|
contents | 消息内容 |
msgType | 消息类型 |
msgId | 消息ID |
conversationId | 会话ID |
timestamp | 时间 |
- contents 消息内容:
字段 | 说明 |
---|---|
type | 需要渲染的消息类型 |
contents | 需要渲染的消息内容 |
-
前端支持渲染的消息类型
- 通用类型
类型 | 说明 | 渲染效果样例 |
---|---|---|
vertical-title | 插件标题 | |
para | 纯文本,段落 | |
text | 纯文本,文字 | |
ai-text | 纯文本,仅支持链接识别 | |
ai-markdown | markdown 类型的内容,支持链接识别能力,支持表格 / 代码 / 列表 / 引用 等能力 | |
image-group | 图片组,端内支持点击放大效果 | |
link | 一段简单的文本链接,支持加一个 icon | |
reference | 参考资源,较为常用 | |
file | 文件解读场景,仅发送场景展现 | |
workflow-card | 工作卡,较为常用 | |
query-recommend | query 推荐 |
- 智能助理消息类型
类型 | 说明 | 渲染效果样例 |
---|---|---|
status_info | 消息标题 | |
answer_summary | 消息-总结 | |
answer_clarify | 消息-列表 | |
answer_finalAnswer | 消息-文本 | |
thinking | denbug 信息-思考 | |
action | denbug 信息 | |
action_input | denbug 信息 | |
observation | denbug 信息 |
2.2.3 获取AK、SK、OpenApiUrl
进入【管理后台】 ---> 点击【助理管理】---> 点击要使用的Agent(默认应用)查看详情 ---> 获取AK、SK、Agent访问地址
2.2.4 消息类型在前端的渲染
接口返回的消息格式遵循与前端约定的协议,不同的type对应不同的渲染方式,使用时可根据业务灵活实现 返回类型主要分两类
markdown类型
1.添加渲染引起依赖包 "@baidu/markdown-typed-render-engine": "1.0.6-assistant.1"
该包现只支持React,暂不支持Vue
注意:@baidu/markdown-typed-render-engine渲染包属于厂内包,如果需要可以咨询售前同学提供
如果只是需要渲染简单markdown数据也可使用markdown-it来渲染
2.使用markdown渲染引擎
import MarkdownRenderEngine from '@baidu/markdown-typed-render-engine';
import '@baidu/markdown-typed-render-engine/dist/index.css';
// 渲染markdown类型数据
<MarkdownRenderEngine
className={styles.markdown} // markdown渲染组件样式
value={text} // 待渲染的markdown类型数据
typed={
isLastMarkdownString: status === 'finish',
renderLength: 3, // 每次渲染的长度
autoInit: true,
full: true,
}
render={{
chartV1: true, // 开启 chartV1 图表自动渲染,默认关闭
}}
/>
工作卡(workflow)类型
工作卡渲染方式:
1.引入对应的flow.js脚本
<script src="https://{host}/super-help/api/v1/engine-pre/js-rcv/flow.js?sceneId=knowledge"></script>
2.拿到消息中的关键模版信息
const {cardInfo, teplateInfo} = message;
3.调用挂载在window上的渲染方法
const renderData = {
cardInfo,
templateInfo,
dom: document.getElementById('renderCardWrapper'), //作为容器的dom节点
uuid: uuid(), //唯一的uuid,用来标记区分不同的工作卡
type: 'inline',
callback:(success: boolean)=>{} //可选参数,渲染后执行的回调,成功执行callback(true),失败callback(false)
}
window.flow.linkRecognize.renderCardByData(renderData);
3.JSSDK接入
3.1 SDK安装
1.直接浏览器标签引入
<script src="https://superhelper-online.bj.bcebos.com/jssdk/js/SuperHelper.iife.js"></script>
3.2 SDK使用
3.2.1 登录
SDK使用之前需要先进行登录,登录采用AK/SK的校验方式,此方式会从后端获得临时token,用于用户后续对话的鉴权。
const {login, Renderer} = window.SuperHelper;
// other codes...
// 第三方逻辑,已获取到用于登录的token和tenantId
login({
ak: ak,
sk: sk,
// 指定登录域名,可选
host: 'https://superhelper.bce.baidu.com'
}).then(() => {
// 登录完成后可以进行后面超级助理的渲染
render()
})
3.2.2 渲染
登录之后便可以进行超级助理界面的渲染。使用Renderer类提供的render方法来渲染整个界面,包含悬浮窗和侧边栏。
function render() {
const renderer = new Renderer({
// 指定超级助理页面地址,可选
aiChatHost: 'https://superhelper.bce.baidu.com',
});
renderer.render();
// other...
}
此时会在右侧渲染出一个悬浮窗,Renderer同时提供了showFlowWindow()和hideFlowWindow()来控制悬浮窗的显隐。 点击悬浮窗会展示侧边栏,同样Renderer提供了showSideBar()和hideSidebar() 方法来控制侧边栏的显隐。
3.2.3 事件
超级助理的相关事件都是通过Renderer的实例来进行监听和触发的,SuperHelper提供了一个RENDERER_EVENT对象,方便获取相关事件的type名称,所有支持的事件名都会维护到这个对象上。
const {RENDERER_EVENT} = window.SuperHelper;
render.addEventListener(RENDERER_EVENT.sideBarDisplay, isShow => {
console.log('sideBarDisplay', isShow);
});
render.addEventListener(RENDERER_EVENT.chatReply, message => {
// message返回为格式详见下方聊天消息结果的获取
console.log('aichatMessage', message);
});
目前支持的事件:
const RENDERER_EVENT = {
// 界面渲染完成
mounted: 'mounted',
// 界面销毁完成
destroyed: 'destroyed',
// 聊天消息回复
chatReply: 'chatReply',
// 侧边栏显隐事件
sideBarDisplay: 'sideBarDisplay',
};
3.2.4 聊天消息的结果获取
通过监听聊天返回事件可以拿到超级助理的返回结果,包含所使用插件、消息内容等。 如提问“888”的返回结果:
{
'content': '888',
'result': [
{'text': '基于「文心一言插件」回答', 'pluginName': '文心一言插件', 'pluginVersion': ''},
{
'text': '“888”在网络用语中通常表示一种祝福或祈愿的用语,尤其在中国网络文化中,它被广泛使用。这个数字的发音与“发发发”非常相似,因此它被视为一种寓意吉祥、财运亨通的数字。\n\n在中国的传统文化中,数字8是一个非常吉祥的数字,代表着好运、成功和发财。因此,“888”在网络用语中也被视为一个幸运数字,可以带来好运和幸福。\n\n此外,“888”在某些情况下也可以表示一种告别或分手的意味,但这种用法相对较少。\n\n总之,“888”在中国网络用语中通常是一种祝福或祈愿的用语,代表着吉祥、好运和财富。',
},
],
};
4.H5接入
4.1 生成签名(Server端)
企业Server端根据签名算法生成sign,通过接口下发给前端的方式,供前端调用H5页面
4.1.1 企业自定义签名
通过使用SK对 AK + params进行hmac_sha256 运算签名
- 使用有序map整合 ak + params
- 对map按照key进行字典排序,并将map转为 key=value&xxx 格式的字符串
- 使用SK对需要加密的字符串进行加密
params参数
字段 | 说明 | 必填 |
---|---|---|
userId | 用户ID(客户系统) | Y |
userName | 用户名称 | Y |
tenantId | 租户ID(超级助理下发) | Y |
tenantName | 租户名称(超级助理下发) | N |
租户ID查看(tenantId)
JAVA代码示例
import org.apache.commons.codec.digest.HmacAlgorithms;
import org.apache.commons.codec.digest.HmacUtils;
Map<String, String> params = // 用户数据
String ak = "" // 真实的AK
String sk = "" // 真实的SK
LinkedHashMap<String, String> signParams = new LinkedHashMap<>();
params.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach((entry) -> {
signParams.put(entry.getKey(), entry.getValue());
});
signParams.put("ak", ak);
String data = signParams.entrySet().stream()
.map(entry -> entry.getKey() + "=" + entry.getValue())
.collect(Collectors.joining("&"));
String sign = hmacSha256(sk, data)
private static String hmacSha256(String key, String data){
HmacUtils hmacUtils = new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key);
return hmacUtils.hmacHex(data);
}
4.2 页面嵌入
4.2.1 获取参数
前端需要提前根据当前用户的登录态,向企业系统server端获取userInfo、ak、signature等信息
// 用户信息格式,有当前企业系统获取的当前用户信息
const userInfo = {
userId,
userName,
tenantId,
tenantName, // tenantName非必传,可为''
}
// 应用的ak
const ak = 'xxxxx';
// 从server获取当前用户的签名(根据4.1签名算法生成)
const signature: any = await getSignature();
4.2.2 创建iframe
location.origin 为当前环境的请求地址 eg:https://superhelper.bce.baidu.com
参考例子:
const host = location.origin + '/public/agents/web?isJiliFlag=1';
const iframe = document.createElement('iframe') as HTMLIFrameElement;
iframe.src = host;
if (iframe) {
iframe.style.width = "100vw";
iframe.style.height = window.innerHeight+'px';
iframe.style.border = 'none';
iframeContainerRef.current.appendChild(iframe); // iframeContainerRef.current属于React的ref语法,目的是为了将创建的iframe添加到所需的元素中
iframeRef.current = iframe; // iframeRef.current属于React的ref语法,目的是为了后续对iframe元素对象方便获取和赋值
}
4.2.3 监听 postmessage
window.addEventListener('message', func); // 建议在创建iframe之前执行,关注时机
const func = (event) => {
const data = event.data;
if (data?.type === 'GET_TOKEN') {
const time = new Date(new Date().getTime() + 60 * 60 * 1000).toISOString();
iframeRef.current?.contentWindow?.postMessage(
{
type: 'SET_TOKEN', // 固定填充
href: location.href, // 当前嵌入的主页面的地址,比如百度网站嵌入超级助理,则为 https://www.baidu.com/?query=test
requestId: data.requestId, // 固定填充
data: {
userInfo, // 用户信息,与签名传传入的userInfo一致
expireTime: time, // 超时时间
sign: signature, // 服务端下发的签名(4.1.1步骤)
ak: ak, // 应用ak
isJSSDK: true, // 固定填充
},
},
host // 超级助理的页面地址(企业嵌入地址)。固定填充:https://superhelper.bce.baidu.com/public/agents/web
);
}
}
例子:
// 响应函数参考:
window.addEventListener('message', func); // 建议在创建iframe之前执行,关注时机
const func = (event) => {
const data = event.data;
if (data?.type === 'GET_TOKEN') {
const time = new Date(new Date().getTime() + 60 * 60 * 1000).toISOString();
iframeRef.current?.contentWindow?.postMessage(
{
type: 'SET_TOKEN',
href: "https://superhelper.bce.baidu.com/openweb/cloudMeet",
requestId: 'xxxx',
data: {
userInfo: {
tenantId: "xxxxxx"
tenantName: "xxx"
userId: "xxx"
userName: "huicheng_mine"
},
expireTime: "2024-06-12T13:50:21.013Z",
sign: 'xxxxx',
ak: 'xxxxx',
isJSSDK: true,
},
},
location.origin + '/public/agents/web''
);
}
}
FAQ
1. H5页面签名校验失败 请检查签名信息里面必须包含正确的ak和params(params为前端传入的用户信息,签名和前端传入的参数必须一致)。
2. 访问超级助理页面出现跨域问题(CORS) 当前超级助理默认开启了跨域(Cross-origin resource sharin)控制,如需内嵌请联系管理员或者发送邮件信息(superhelper_rd@baidu.com)开启白名单。