1. 需求背景与适用场景
1.1 需求背景
Smartbi AIChat本身是提供了多种客户端供用户选择的。如果常用PC,我们有基于PC浏览器的AIWeb页面;如果常用手机,我们有基于手机的App或者使用手机浏览器访问的AIChatView页面;我们还提供了基于钉钉的使用页面。
但是,这些都是Smartbi AIChat平台内置的使用页面,页面样式和操作方式是基于产品内置好的。如果用户想把自然语言查询集成到用户自己的APP里面,或者集成到用户其他的平台里面,我们内置的页面样式可能不太符合用户的要求,集成起来就不自然。
为了让用户在使用Smartbi自然语言查询的时候,可以自定义前端页面,我们提供了基于Java语言实现的RestFul API接口。本文主要就是介绍如何使用Smartbi AIChat的接口实现自己的前端页面。
1.2 适用场景
使用Smartbi AIChat 提供的API适合以下场景开发:
- 觉得Smartbi内置的对话界面不好看,可以使用Smartbi扩展包机制重新开发使用界面
- 需要将对话嵌入到集团内部APP中,可以定制Android/IOS原生界面,或者嵌入自定义H5页面
- 需要嵌入到其他的Web平台中,可以定制H5页面
- 需要嵌入其聊天工具中(如:钉钉、微信等),可以定制符合聊天工具要求的页面
- 其他使用场景,可以咨询Smartbi客服团队,获取支持
2. 逻辑架构
【用户自定义对话界面-逻辑架构图】
说明:
- 用户自定义界面,可以脱离Smartbi,嵌入在第三方平台里面,包括:
- 第三方Web应用
- 第三方Android应用
- 第三方IOS应用
如果是Web页面,推荐使用Smartbi扩展包方式开发集成页面。这样可以避免跨域问题。如果需要在第三方应用中开发,需要做对所有API做服务端转发。
3. Smartbi接口调用说明
AIChat接口是基于Smartbi标准远程接口实现的,Smartbi的远程接口,Smartbi接口的调用方法如下:
参数名 | 说明 | |
接口URL | ||
输入参数 | className | 服务类名 |
methodName | 服务方法名 | |
params | 方法参数,以数组形式传递 | |
返回值 | 返回JSON对象 | |
retCode | 返回码:0 - 正确 | |
result | 方法返回结果,不同方法返回不一样 | |
duration | 执行时间:毫秒 |
【PostMan - 登录方法测试样例】
4. API说明
Smartbi AIChat提供了比较丰富的二次开发API,本次Demo只使用了一部分。这个章节,重点介绍下本次Demo使用的API。
以下介绍的接口,调用方法和调用URL是一样的,区别仅仅是参数不同,所以对每个API不会重复介绍调用方法,具体调用方法请参考:上一章节的 “Smartbi接口调用说明”
4.1 登录Smartbi
URL参数名 | URL参数值 | ||
输入参数 | className | UserService | |
methodName | clickLogin | ||
params | userName | 样例:["demo","demo"] | |
password | |||
返回值 | retCode | 0 | 非0表示错误 |
result | true | 非0时是错误信息 |
4.2 登录AIChat
URL参数名 | URL参数值 | 说明 | |
输入参数 | className | AIChatRemoteService | |
methodName | loginIfSmartbiLogged | ||
params | [] | 样例:[] | |
返回值 | retCode | 0 | 非0表示错误 |
result | {\"token\":\"CE3CE70AC12B70052A507D4B560E5374\"} | AIChat 的token信息,这个非常重要,后续AIChat所有方法需要用到这个token; 非0时是错误信息 |
备注:登陆AIChat前需要登陆成功Smartbi(通过账户密码/单点/其他登陆方式)
4.3 查询数据模型清单
URL参数名 | URL参数值 | 说明 | |
输入参数 | className | AIChatRemoteService | |
methodName | getBuildThemes | ||
params | |||
token | loginIfSmartbiLogged方法获取的token | ||
返回值 | retCode | 0 | 参考query方法 |
result | 参考query方法 |
- PostMan - 登录方法测试样例
- 接口返回示例
返回值 | { "code": 0, "result": [ { "id": "I8a80818c0191262b262b26b0019126c8d71a****", "name": "****NLA-绩效考核-20240806", "title": "****NLA-绩效考核-20240806", "desc": "**证券NLA-绩效考核-20240806包含了年月、年、指标名称、指标口径、指标大类、指标负责人、指标细类、分支机构考核类别、所属考核组织类型、分支机构分组等字段", "type": "augmentedDataset", "recommendQuestion": [ "每年指标名称排名", "每年得分", "近5年指标名称得分", "排名按年份排序,线图显示", "排名的合计" ], "lastBuildTime": "2024/08/09 16:11:00" } ], "duration": 131, } |
- 接口返回说明
返回参数名 | 返回值说明 |
retCode | 接口调用是否成功;大于等于0 - 表示成功;负数为错误码 |
result | 调用接口的返回内容,登录接口的返回内容说明如下: "id": 数据模型themeID "name": 数据模型名称 "title": 数据模型名称别名 "desc": 数据模型概览 "type": 数据类型 "recommendQuestion": 推荐问句 "lastBuildTime": 最近构建时间 ... 其他返回值可以忽略 |
4.4 维度指标树、推荐问句
URL参数名 | URL参数值 | 说明 | |
输入参数 | className | AIChatRemoteService | |
methodName | getDataSetInfoSummary | ||
params | token | loginIfSmartbiLogged方法获取的token | |
sourceId | 用户在界面上选择的数据模型themeId | ||
返回值 | retCode | 0 | 参考query方法 |
result | 参考query方法 |
- PostMan - 登录方法测试样例
- 接口返回示例
返回值 | { "retCode": 0, "result": "{"code":0,"result":{"id":"I8a8aa3ed018ff259f259763901900f943a901c9a","name":"foodware_0613","alias":"foodware_0613","dimensions":{"推广信息表":["活动名称","媒体类型"],"产品类别表":["产品子类","产品类别"],"活动开始_时间维":["活动开始_年","活动开始_年季","活动开始_年月","活动开始_年月日"],"活动结束_时间维":["活动结束_年","活动结束_年季","活动结束_年月","活动结束_年月日"],"商店表":["商店类型","商店","商店所在城市","商店所在区域","商店所在国家"],"产品表":["品牌","产品名称","总重量"],"顾客表":["客户ID","顾客城市","顾客省份","收入等级","顾客性别","顾客学历","信用卡张数","顾客姓名","房屋拥有者"],"销售日期":["年","年季","年月","年月日"]},"measures":{"度量":["销售额","活动费用","营业面积","单位面积营业额","销售成本","顾客数"]},"recommendQuestions":null},"message":null,"token":"68863F9154D276D0170B1D5796F26F0C"}", "duration": 41 } |
- 接口返回说明
返回参数名 | 返回值说明 |
reCode | 接口调用是否成功;大于等于0 - 表示成功;负数为错误码 |
message | 错误描述,recode=0 时,该内容为空 |
token | 登录方法特有内容,这个非常重要,后续接口需要传递该值以验证登录 |
result | 调用接口的返回内容,登录接口的返回内容说明如下: "id": 数据模型themeID "name": 数据模型名称 "alias": 数据模型名称别名 "dimensions" AIChat模型中所有维度 "measures" AIChat模型中所有度量 "recommendQuestions" 推荐问句 ... 其他返回值可以忽略 |
4.5 执行查询
URL参数名 | URL参数值 | 说明 | |
输入参数 | className | AIChatRemoteService | |
methodName | query | ||
params | txt | 问句 | |
token | loginIfSmartbiLogged方法获取的token | ||
isMultiQuery | 查询类型,该参数为空,则由AIBus判断是否多轮 | ||
themeId | 数据模型id,可为空,有推荐 | ||
reportId | 报表Id,设置为空 | ||
uuid | 设置为空 | ||
userChoseThemeId | 用户选择的模型id 用于锁定模型查询,设置为空 | ||
isMobileCall | 是否手机请求,设置为false | ||
getPageBO | 是否需要仪表盘定义,设置为false | ||
subTable | 子表 | ||
llmReviseQuestionWithUserGuide | 合并问句 | ||
returnPrompt | 是否返回提示词,字符串:true,false | ||
returnJSON | 是否返回json数据 | ||
返回值 | retCode | 0 | 非0表示错误 |
result | 见下表 |
- PostMan - 登录方法测试样例
- 接口返回示例
返回值 | { "code": 0, "result": { "currentRows": "", "currentPage": "", "rowsPerPage": "", "portletType":"", "html":"", "nl2sql":"", "llm":"", ... }, "message": "", "token": "" } |
- 接口返回说明
第一层result的属性 | 属性含义 | 说明 |
retCode | AIChat请求返回码 | 0表示成功,负数表示错误,整数是路由码 |
message | 错误信息 | 负数才有值 |
result | JSON对象 | 不同的retCode,返回的内容不一样,详细内容见后续表格 |
token | token信息 | 登录方法特有内容,这个非常重要,后续接口需要传递该值以验证登录 |
- query返回 result.code=0,仅列举主要的属性(正确查询)
第二层result属性 | 属性含义 | 说明 |
intentionType | 意图类型 | text2sql的类型 |
uuid | 本次查询uuid | 记录查询日志id |
rowsCount | 本次查询结果数据总行数 | 表格才生效 |
currentRows | 当前返回数据行数 | 表格才生效 |
currentPage | 当前页码 | 表格才生效 |
rowsPerPage | 每页行数 | 表格才生效 |
clientId | 本次查询id | 记录查询id,用于翻页时标记查询缓存 |
html | 返回结果 | ● 如果是图形,则返回ECharts定义 ● 如果是表格直接返回html |
portletType | 仪表盘组件类型(queryType=PageQuery才生效) | ● ECHARTS_BAR 图形:柱图 ● ECHARTS_LINE 图形:线图 ● ECHARTS_PIE 图形:饼图 ● TABLE_LIST 表格:清单表 ● TABLE_CROSS 表格:交叉表 |
queryType | 查询类型 | ● PageQuery(数据模型) |
question | 本次查询的问题 | |
resultTips | 本次查询的条件 | where或者having条件 |
themeId | 本次查询的数据模型/业务主题id | |
nl2sql | 查询定义 | nl2sql的详细定义 |
- PortletType说明
中文名 | PortletType / chartType |
汇总表 | TABLE_LIST |
清单表 | TABLE_DETAIL_LIST |
交叉表 | TABLE_CROSS |
柱图 | ECHARTS_BAR |
横条图 | ECHARTS_BAR__HORIZONTAL |
线图 | ECHARTS_LINE |
饼图 | ECHARTS_PIE |
圆环图 | ECHARTS_PIE__DONUT |
散点图 | ECHARTS_SCATTER |
泡泡图 | ECHARTS_SCATTER__BUBBLE |
4.6 点赞点踩
URL参数名 | URL参数值 | 说明 | |
输入参数 | className | AIChatRemoteService | |
methodName | feedBack | ||
params | token | loginIfSmartbiLogged方法获取的token | |
uuid | query接口查询的问句返回的uuid唯一标识 | ||
tag | 1-为正确,0-为错误 | ||
feedbackText | 人工输入,反馈内容 | ||
返回值 | retCode | 0 | 非0表示错误 |
result |
- PostMan - 登录方法测试样例
- 接口返回示例
返回值 | { "reCode": 0, "duration": "36" } |
- 接口调用成功后,会将点赞点踩相关信息写入AIChat的数据库服务中对应表中:
4.7 切换图形
URL参数名 | URL参数值 | 说明 | |
输入参数 | className | AIChatRemoteService | |
methodName | queryWithNl2sql | ||
params | token | loginIfSmartbiLogged方法获取的token | |
nl2sql | query接口返回的n2lsql值, 注:需要将value值中转义符\去除,并且注意json格式 ("{'key':'value'}"注意单引号与双引号的使用) | ||
sourceId | 数据模型ID | ||
chartType | 图形类型, 举例:ECHARTS_BAR | ||
返回值 | retCode | 0 | 非0表示错误 |
result |
- PostMan - 登录方法测试样例
- 接口返回示例
返回值 | { "code": 0, "result": { ... "html": "{"yAxis":{"fieldFormat":{"date":"","prefix":"","name":"<整型-默认值>","viewType":"TNUMBER","scale":1.0,"time":"","type":"INTEGER","suffix":"","decimal":0},"axisLabel":{"show":true},"type":"value"},"xAxis":{"fieldFormat":{"date":"","prefix":"","name":"<字符串-默认值>","viewType":"NONE","scale":1.0,"time":"","type":"STRING","suffix":"","decimal":0},"axisLabel":{"show":true},"data":["沪世纪"],"type":"category"},"color":["rgba(149,162,255,1)","rgba(250,128,128,1)","rgba(60,185,252,1)","rgba(255,192,118,1)", "rgba(250,231,104,1)","rgba(135,232,133,1)","rgba(115,171,245,1)","rgba(203,155,255,1)", "rgba(67,67,72,1)","rgba(144,237,125,1)","rgba(247,163,92,1)", "rgba(128,133,233,1)"],"advanced":{"rowNotEmpty":true},"series":[{"fieldFormat":{"date":"", "prefix":"","name":"<整型-默认值>","viewType":"TNUMBER","scale":1.0,"time":"","type":"INTEGER", "suffix":"","decimal":0},"groupName":"GLOBAL_MARK","data":[{"displayValue":["沪世纪","813"],"tooltipInfo":[{"realValue":"沪世纪","fieldGroupType":"cols","realValueString":"沪世纪", "label":"分支机构名称(考核)","value":"沪世纪","uniqueId":"8c4e629e045a44e3b3a79d69b34aafd2"} ,{"realValue":813,"fieldGroupType":"rows","realValueString":"813","label":"排名","value":"813","uniqueId":"3cfa25d8e1a74b7da592a7860c6efcda"}],"colIndex":1,"rowIndex":[0,0], "value":[0,813]}],"name":"排名","type":"bar","markLine":{"symbol":"none"},"yAxisIndex":0}], "tooltip":{"trigger":"item"},"seriesConfig":{"global":{"stack":false,"step":false,"smooth":false}}, "chartEx":{"clasifyName":[{"data":"排名"}],"drillableFields":[],"outputRows":1000}}", "portletType": "ECHARTS_BAR",}, ... "message": null, "token": "717261E64AEC5D904AA2410D127BFB27" } |
- 接口返回说明
返回参数名 | 返回值说明 |
retCode | 接口调用是否成功;大于等于0 - 表示成功;负数为错误码 |
message | 错误描述,code=0 时,该内容为空 |
token | 登录方法特有内容,这个非常重要,后续接口需要传递该值以验证登录 |
result | 调用接口的返回内容,登录接口的返回内容说明如下: "html": 切换后的图表的html "portletType": 切换后的图标的类型 ... 其他返回值可以忽略 |
4.8 查询结果设置输出行数
URL参数名 | URL参数值 | 说明 | |
输入参数 | className | AIChatRemoteService | |
methodName | setRowsPerPage | ||
params | clientId | 用户的查询问句的clientId(可以从执行查询接口获取) | |
pageSize | 设置每页输出大小 | ||
queryType | 用户的查询问句的queryType(可以从执行查询接口获取) | ||
dataSource | 数据来源,通常固定为smartbiproxy | ||
token | loginIfSmartbiLogged方法获取的token | ||
返回值 | retCode | 0 | 非0表示错误 |
result |
- PostMan - 登录方法测试样例
- 接口返回示例
返回值 | {"retCode":0,"result": "{"code":0,"result":null,"message":null,"token":"B38F13B1700652D1AC9E352E082DC10E"}", "duration":56} |
- 接口返回说明
返回参数名 | 返回值说明 |
retCode | 接口调用是否成功;0 - 表示成功;负数为错误码 |
message | 错误描述,code=0 时,该内容为空 |
token | 登录方法特有内容,这个非常重要,后续接口需要传递该值以验证登录 |
result | 调用接口的返回内容 |
4.9 查询结果分页
URL参数名 | URL参数值 | 说明 | |
输入参数 | className | AIChatRemoteService | |
methodName | queryWithPage | ||
params | token | loginIfSmartbiLogged方法获取的token | |
clientId | 用户的查询问句的clientId(可以从执行查询接口获取) | ||
page | 设置翻页,第几页 | ||
dataSource | 数据来源,通常固定为smartbiproxy | ||
queryType | 用户的查询问句的queryType(可以从执行查询接口获取) | ||
返回值 | retCode | 0 | 非0表示错误 |
result |
- PostMan - 登录方法测试样例
- 接口返回示例
返回值 | {"retCode":0, "result":"{"code":0, "result": {"intentionType":null, "queryRecordIndex":null, "multiRecordSessionId":null, "uuid":null, "rowsCount":-1, "currentRows":10, "currentPage":2, "rowsPerPage":10, "html":"..." } "token":"1B08EF32A971F5DE5981C61AE812C577" }", "duration":177} |
- 接口返回说明
返回参数名 | 返回值说明 |
retCode | 接口调用是否成功;0 - 表示成功;负数为错误码 |
token | 登录方法特有内容,这个非常重要,后续接口需要传递该值以验证登录 |
result | 调用接口的返回内容,登录接口的返回内容说明如下: "currentRows": 当前页行数 "currentPage": 当前页码 "rowsPerPage": 每页行数 "portletType": 显示类型(表格、图形等) "html": 如果是表格,为html,如果是图形为Echarts Options ... |
4.10 清除对话历史(开启新对话)
Smartbi AIChat 是可以启用“多轮对话”和“单轮对话”的,具体操作方法在对话式分析主页面中勾选,这里不详细描述。在启用多轮对话的时候,
有时需要清空对话历史(也就是开启新的对话)。开启新对话需要使用该API实现。
URL参数名 | URL参数值 | 说明 | |
输入参数 | className | AIChatRemoteService | |
methodName | closeQuery | ||
params | token | loginIfSmartbiLogged方法获取的token | |
返回值 | retCode | 0 | 非0表示错误 |
result |
- PostMan - 登录方法测试样例
- 接口返回示例
返回值 | {"retCode":0,"duration":30} |
- 接口返回说明
返回参数名 | 返回值说明 |
retCode | 接口调用是否成功;0 - 表示成功;负数为错误码 |
5. 页面集成
SmartBi AIChat提供三种页面集成的方式 。
5.1 页面集成方式一
名称 | 值 |
请求地址 | |
参数说明 | question:问句,可以选填 userName:用户名 password:密码 |
请求URL:http://smartbi-AIChat-server:port/smartbi/vision/AIChatView2.html?userName=admin&password=admin
5.2 页面集成方式二
名称 | 值 |
请求地址 | |
参数说明 | userName:用户名 password: 密码 surl :/smartbi/smartbix/#/sdk |
5.3 页面集成方式三
嵌入式集成(iframe嵌入需注意可能会有跨域问题)
<script> window.aiChatbotConfig = { // 配置AIChat的版本号 version: 1, // 配置嵌入的域名 iframeSrc: "http://localhost:3000", // btn: { // 按钮图片可以自定义配置 // backgroundImg: 'http://xxx.png' // } }; </script> <script type="text/javascript" src="http://localhost:3000/smartbi/vision/external.js"></script> |
嵌入后页面展示: