├── .gitignore ├── README.md ├── chat_rest ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── am │ │ └── chat │ │ └── bi │ │ ├── ChatBIApplication.java │ │ ├── comm │ │ ├── AppCode.java │ │ ├── ErrorCode.java │ │ ├── Result.java │ │ ├── ResultMeta.java │ │ ├── StateCode.java │ │ └── Utils.java │ │ ├── config │ │ └── SwaggerConfiguration.java │ │ ├── controller │ │ └── LLMsController.java │ │ ├── domain │ │ ├── dao │ │ │ └── SchemaMetaInfo.java │ │ └── vo │ │ │ └── ResponseVo.java │ │ └── service │ │ ├── LLMsService.java │ │ └── impl │ │ └── LLMsServiceImpl.java │ ├── resources │ ├── application-dev.yml │ ├── application.yml │ ├── assembly.xml │ ├── dev │ │ └── setenv.sh │ ├── logback-dev.xml │ ├── logback.xml │ ├── press │ │ └── setenv.sh │ ├── prod │ │ └── setenv.sh │ ├── sql │ │ └── mysql.sql │ └── test │ │ └── setenv.sh │ └── shell │ ├── comm.sh │ ├── start.sh │ └── stop.sh ├── chat_ui └── pom.xml ├── doc └── photo │ ├── 模块架构.jpeg │ └── 自动生成图表.png ├── plugins ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── am │ └── chat │ └── bi │ └── utils │ ├── AliLLMsUtil.java │ ├── LLMsResultUtil.java │ └── PromptUtil.java └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | target 3 | *.iml 4 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 自定义BI改变了传统IT主导开发固定报表的时代,让数据能够即席分析达到所见即所得,随着大模型的兴起与火热,LLMs 结合数据可视化技术,通过问答的方式能够让系统智能与数据交互与生成图表,无论是BI copilot还是ChatBI, 除了替代之前小助手功能只能查询已有报表数据外,更多的是省略创建dashboard的时候图表的拖拉拽操作,让系统自动生成的图表能够在dashboard中布局应用。 3 | ![自动图表生成](./doc/photo/自动生成图表.png) 4 | 5 | #### 一、实现思路主要考虑 6 | 7 | 1、如果没有大模型或者大模型服务宕机,自动化生成可视化工程化就不能实现? 8 | 9 | —— 直接解耦,大模型不能影响主体工程,图表这块不能大模型生成。 10 | 11 | 2、如果大模型正常服务能够推理,是否所有的问答都要经过推理服务? 12 | 13 | —— 大模型的推理是否那么靠谱稳定、对应响应的耗时以及对应采用商业大模型服务的费用成本因素。 14 | 15 | 3、以SQL交互为核心的配套组件,通过系统化的工程来达到生产可用要求。 16 | 17 | 借鉴[SQLChat](https://github.com/sqlchat/sqlchat), [DB-GPT](https://github.com/csunny/DB-GPT), 的开源项目思路,确定以SQL生成为核心,和数据库交互获取数据,通过data + 可视化图表组件方式实现。不考虑大模型自动生成图表的方式,主要考虑一是美观,二是灵活性,三最主要的是性能是否可控,尤其是大量查询的data很大时,是否分页等可以手动人为干预控制;而靠大模型自动生成图表类似markdown/html估计不会很理想。 18 | 19 | 20 | #### 二、主要思路框架 21 | ![框架图](./doc/photo/模块架构.jpeg) 22 | 23 | #### 三、说明 24 | 1、是否有表,指标字段,维度字段列级的查询权限,以及行级 ${input_dim_conditions} <= ${user_has_permission},否直接报权限不足。 25 | 26 | 2、如果维度、度量,都来自于一张表,解析查询条件,然后sql模版组装: 27 | ```sql 28 | select ${input_dim_names} , ${input_metric_names} from ${get_meta_table_name} where ${input_dim_conditions} [group by $s] [order by $s]; 29 | ``` 30 | 这种sql组装拼接成熟度很高,不一定直接依赖大模型服务,唯一有难点的就是文本中对应条件的解析。 31 | 32 | 3、 如果维度、度量都来自于多张表,则查找相似匹配的问题对应的答案Sql: 33 | 34 | ①、如果有对应sql, 则直接应用,可能只组装的就是sql的where条件。 35 | 36 | ②、如果有相似sql, 例如2张表的join找2张表join的sql模版则对应需要增加子查询方式与拼接where, 即 37 | ```sql 38 | select ${input_dim_names} , ${input_metric_names} from ( ${get_query_sql} ) TT where ${input_dim_conditions} [group by $s] [order by $s]; 39 | ``` 40 | 41 | **属于可选步骤(也可以直接调用大模型能力)**,这里where一般可以,sql引擎都支持谓词下推,但是子查询多列可能带来性能影响,不是所有的sql引擎都支持列剪裁。 同时注意相似如果是2张表join,则不能找3张表join的sql语句去拼接。 42 | 43 | ③、如果sql为null或者校验error的sql, 则通过提示词(问题、schema)交给大模型推理返回推理生成查询sql。 44 | 45 | 整体框架可能存在不足,但是相信随着时间的进步,大模型会越来越稳定可靠,响应快 以及细分领域SQL LLMs的诞生;也相信利他主义的开源者,会诞生更优秀的ChatBI项目。 46 | #### 四、模块结构 47 | 48 | |--rest api层 49 | 50 |     |-- server 服务层,调用解析,执行sql,和数据库交互 51 | 52 |     |-- mapper 元数据匹配 53 | 54 |     |--validate sql校验 55 | 56 | |--common 57 | 58 | |--parse 文本解析 59 | 60 | |--plugins 大模型插件,和大模型交互,智能生成 61 | -------------------------------------------------------------------------------- /chat_rest/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | chatBI 7 | com.am 8 | 1.0-SNAPSHOT 9 | 10 | 11 | 4.0.0 12 | 13 | chat_rest 14 | 15 | 16 | 17 | org.springframework.boot 18 | spring-boot-starter 19 | 20 | 21 | logback-classic 22 | ch.qos.logback 23 | 24 | 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter-web 29 | 30 | 31 | 32 | org.springframework 33 | spring-context-support 34 | 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-websocket 39 | 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-configuration-processor 44 | true 45 | 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-starter-test 50 | test 51 | 52 | 53 | 54 | io.springfox 55 | springfox-swagger2 56 | 57 | 58 | 59 | io.springfox 60 | springfox-swagger-ui 61 | 62 | 63 | 64 | com.github.pagehelper 65 | pagehelper-spring-boot-starter 66 | 67 | 68 | mybatis-spring-boot-starter 69 | org.mybatis.spring.boot 70 | 71 | 72 | 73 | 74 | 75 | org.mybatis.spring.boot 76 | mybatis-spring-boot-starter 77 | 78 | 79 | org.springframework.boot 80 | spring-boot-starter 81 | 82 | 83 | 84 | 85 | 86 | com.alibaba 87 | druid-spring-boot-starter 88 | 89 | 90 | 91 | mysql 92 | mysql-connector-java 93 | runtime 94 | 95 | 96 | 97 | org.mybatis.spring.boot 98 | mybatis-spring-boot-starter-test 99 | 100 | 101 | 102 | 103 | org.projectlombok 104 | lombok 105 | 106 | 107 | 108 | org.apache.commons 109 | commons-lang3 110 | 111 | 112 | 113 | ch.qos.logback 114 | logback-classic 115 | 116 | 117 | logback-core 118 | ch.qos.logback 119 | 120 | 121 | 122 | 123 | ch.qos.logback 124 | logback-core 125 | 126 | 127 | 128 | redis.clients 129 | jedis 130 | 131 | 132 | 133 | com.google.code.gson 134 | gson 135 | 136 | 137 | 138 | com.am 139 | plugins 140 | compile 141 | 1.0-SNAPSHOT 142 | 143 | 144 | 145 | 146 | 147 | dev 148 | 149 | dev 150 | 151 | 152 | true 153 | 154 | 155 | 156 | test 157 | 158 | test 159 | 160 | 161 | 162 | prod 163 | 164 | prod 165 | 166 | 167 | 168 | press 169 | 170 | press 171 | 172 | 173 | 174 | 175 | 176 | ${project.artifactId} 177 | src/main/java 178 | src/main/shell 179 | 180 | 181 | src/main/resources 182 | 183 | *.xml 184 | **/*.xml 185 | *.yml 186 | static/ 187 | templates/ 188 | mapper/ 189 | 190 | 191 | 192 | 193 | 194 | 195 | org.mybatis.generator 196 | mybatis-generator-maven-plugin 197 | 1.3.2 198 | 199 | 200 | mysql 201 | mysql-connector-java 202 | 5.1.38 203 | 204 | 205 | 206 | 207 | Generate MyBatis Artifacts 208 | none 209 | 210 | generate 211 | 212 | 213 | 214 | 215 | 216 | src/main/resources/generatorConfig.xml 217 | true 218 | 219 | 220 | 221 | 222 | org.apache.maven.plugins 223 | maven-jar-plugin 224 | 3.0.2 225 | 226 | 227 | 228 | false 229 | 230 | 231 | true 232 | lib/ 233 | ${start-class} 234 | 235 | 236 | 237 | config/ 238 | 239 | 240 | 241 | *.xml 242 | *.conf 243 | *.yml 244 | *.properties 245 | 246 | 247 | 248 | 249 | org.apache.maven.plugins 250 | maven-assembly-plugin 251 | 252 | 253 | src/main/resources/assembly.xml 254 | 255 | false 256 | 257 | 258 | 259 | make-assembly 260 | package 261 | 262 | single 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | -------------------------------------------------------------------------------- /chat_rest/src/main/java/com/am/chat/bi/ChatBIApplication.java: -------------------------------------------------------------------------------- 1 | package com.am.chat.bi; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.boot.web.servlet.ServletComponentScan; 9 | 10 | @SpringBootApplication 11 | @ServletComponentScan 12 | @MapperScan(basePackages = { "com.am.chat.bi.dao" }) 13 | public class ChatBIApplication { 14 | private static final Logger LOG = LoggerFactory.getLogger(ChatBIApplication.class); 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(ChatBIApplication.class, args); 18 | LOG.info("ChatBIApplication start run!"); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /chat_rest/src/main/java/com/am/chat/bi/comm/AppCode.java: -------------------------------------------------------------------------------- 1 | package com.am.chat.bi.comm; 2 | 3 | /** 4 | * @author wpl 5 | * 后期数据库配置 6 | */ 7 | public enum AppCode { 8 | VSKIT(1, "vskit") 9 | ; 10 | private int code; 11 | private String appName; 12 | 13 | AppCode(int code, String appName) { 14 | this.code = code; 15 | this.appName = appName; 16 | } 17 | 18 | public int getCode() { 19 | return code; 20 | } 21 | 22 | public String getAppName() { 23 | return appName; 24 | } 25 | 26 | public static String getAppName(int code) { 27 | switch (code){ 28 | case 1: 29 | case 2: 30 | default: 31 | return VSKIT.getAppName(); 32 | } 33 | } 34 | 35 | } 36 | 37 | -------------------------------------------------------------------------------- /chat_rest/src/main/java/com/am/chat/bi/comm/ErrorCode.java: -------------------------------------------------------------------------------- 1 | package com.am.chat.bi.comm; 2 | 3 | /** 4 | * @author wpl 5 | */ 6 | public enum ErrorCode { 7 | SUCCESS(1000, "success"), 8 | FAIL(1010, "fail"), 9 | FAIL_LLMs(1020, "fail LLMs"), 10 | FAIL_INSERT(1001, "fail insert"), 11 | FAIL_UPDATE(1002, "fail update"), 12 | FAIL_SELECT(1003, "fail select"), 13 | FAIL_UPLOAD(1004, "fail upload"), 14 | FAIL_EXPORT(1005, "fail export"), 15 | FAIL_DEL(1006, "fail delete"), 16 | FAIL_RUN_TASK(1007, "fail run task"), 17 | ; 18 | 19 | private int code; 20 | private String msg; 21 | 22 | ErrorCode(int code, String msg) { 23 | this.code = code; 24 | this.msg = msg; 25 | } 26 | 27 | public int getCode() { 28 | return code; 29 | } 30 | 31 | public String getMsg() { 32 | return msg; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /chat_rest/src/main/java/com/am/chat/bi/comm/Result.java: -------------------------------------------------------------------------------- 1 | package com.am.chat.bi.comm; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | import org.apache.commons.lang3.builder.ToStringBuilder; 7 | import org.apache.commons.lang3.builder.ToStringStyle; 8 | 9 | /** 10 | * @author wpl 11 | */ 12 | @Data 13 | @ApiModel 14 | public class Result { 15 | 16 | @ApiModelProperty(value = "元数据", required = true) 17 | private ResultMeta meta; 18 | 19 | @ApiModelProperty(value = "返回结果") 20 | private T response; 21 | 22 | public Result() {} 23 | 24 | private Result(ErrorCode errorCode) { 25 | this.meta = new ResultMeta(errorCode); 26 | } 27 | 28 | public static Result success() { 29 | return new Result<>(ErrorCode.SUCCESS); 30 | } 31 | 32 | public static Result fail(ErrorCode errorCode) { 33 | return new Result<>(errorCode); 34 | } 35 | 36 | public static boolean isSuccess(Result result) { 37 | return result != null && result.meta != null && result.meta.getCode() == 0; 38 | } 39 | 40 | public Result withErrorMsg(String msg) { 41 | this.meta.setMsg(msg); 42 | return this; 43 | } 44 | 45 | public Result withResponse(T response) { 46 | this.response = response; 47 | return this; 48 | } 49 | 50 | @Override 51 | public String toString() { 52 | return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /chat_rest/src/main/java/com/am/chat/bi/comm/ResultMeta.java: -------------------------------------------------------------------------------- 1 | package com.am.chat.bi.comm; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | /** 8 | * @Author: wpl 9 | */ 10 | @Data 11 | @ApiModel 12 | public class ResultMeta { 13 | 14 | @ApiModelProperty(value = "错误码", required = true) 15 | private int code; 16 | @ApiModelProperty(value = "描述", required = true) 17 | private String msg; 18 | 19 | public ResultMeta() {} 20 | 21 | public ResultMeta(ErrorCode errorCode) { 22 | this.code = errorCode.getCode(); 23 | this.msg = errorCode.getMsg(); 24 | } 25 | 26 | void setMsg(String msg) { 27 | this.msg = this.msg + " : " + msg; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /chat_rest/src/main/java/com/am/chat/bi/comm/StateCode.java: -------------------------------------------------------------------------------- 1 | package com.am.chat.bi.comm; 2 | 3 | /** 4 | * @author wpl 5 | */ 6 | public enum StateCode { 7 | IS_ADD(0), 8 | IS_UPDATE(1), 9 | IS_DEL(2) 10 | ; 11 | 12 | private Integer code; 13 | StateCode(Integer code) { 14 | this.code = code; 15 | } 16 | 17 | public static StateCode getStateCode(Integer code) { 18 | switch (code){ 19 | case 1: 20 | return IS_UPDATE; 21 | case 2: 22 | return IS_DEL; 23 | default: 24 | return IS_ADD; 25 | } 26 | } 27 | 28 | public Integer getCode() { 29 | return code; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /chat_rest/src/main/java/com/am/chat/bi/comm/Utils.java: -------------------------------------------------------------------------------- 1 | package com.am.chat.bi.comm; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import java.text.ParseException; 8 | import java.text.SimpleDateFormat; 9 | import java.util.Date; 10 | import java.util.concurrent.atomic.AtomicLong; 11 | 12 | public class Utils { 13 | private static final Logger LOG = LoggerFactory.getLogger(Utils.class); 14 | public static String getStringDate(Date date) { 15 | SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 16 | String dateString = formatter.format(date); 17 | return dateString; 18 | } 19 | 20 | public static Date getStringToDate(String date) { 21 | SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 22 | try { 23 | Date result = formatter.parse(date); 24 | return result; 25 | } catch (ParseException e) { 26 | e.printStackTrace(); 27 | LOG.error("string date 解析出错", e); 28 | } 29 | return null; 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /chat_rest/src/main/java/com/am/chat/bi/config/SwaggerConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.am.chat.bi.config; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import springfox.documentation.builders.ApiInfoBuilder; 7 | import springfox.documentation.builders.PathSelectors; 8 | import springfox.documentation.builders.RequestHandlerSelectors; 9 | import springfox.documentation.service.ApiInfo; 10 | import springfox.documentation.spi.DocumentationType; 11 | import springfox.documentation.spring.web.plugins.Docket; 12 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 13 | 14 | 15 | /** 16 | * @author wpl 17 | */ 18 | @EnableSwagger2 19 | @Configuration 20 | public class SwaggerConfiguration { 21 | @Value("${com.am.chat.bi.api.doc.path:com.am.chat.bi}") 22 | private String path; 23 | 24 | @Value("${com.am.chat.bi.api.doc.title:Chat BI Platform API doc}") 25 | private String title; 26 | 27 | @Value("${com.am.chat.bi.api.doc.version:1.0}") 28 | private String version; 29 | 30 | @Value("${com.am.chat.bi.api.doc.description:Chat BI Platform API doc}") 31 | private String description; 32 | 33 | @Bean 34 | public Docket createApi() { 35 | return new Docket(DocumentationType.SWAGGER_2) 36 | .apiInfo(apiInfo()) 37 | .pathMapping("/") 38 | .select() 39 | .apis(RequestHandlerSelectors.basePackage(path)) 40 | .paths(PathSelectors.any()) 41 | .build(); 42 | } 43 | 44 | private ApiInfo apiInfo() { 45 | return new ApiInfoBuilder() 46 | .title(title) 47 | .description(description) 48 | .version(version) 49 | .build(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /chat_rest/src/main/java/com/am/chat/bi/controller/LLMsController.java: -------------------------------------------------------------------------------- 1 | package com.am.chat.bi.controller; 2 | 3 | 4 | import com.am.chat.bi.comm.Result; 5 | import com.am.chat.bi.service.LLMsService; 6 | import io.swagger.annotations.Api; 7 | import io.swagger.annotations.ApiOperation; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.http.HttpStatus; 10 | import org.springframework.http.MediaType; 11 | import org.springframework.http.ResponseEntity; 12 | import org.springframework.web.bind.annotation.PostMapping; 13 | import org.springframework.web.bind.annotation.RequestBody; 14 | import org.springframework.web.bind.annotation.RequestMapping; 15 | import org.springframework.web.bind.annotation.RestController; 16 | 17 | @RestController 18 | @RequestMapping("/chat") 19 | @Api(value = "大模型服务", description = "大模型服务", tags = {"LLMs APIß"}) 20 | public class LLMsController { 21 | 22 | @Autowired 23 | LLMsService llMsService; 24 | 25 | @PostMapping(value = "/intention", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) 26 | @ApiOperation(value = "查询意图", notes = "查询意图", response = Result.class) 27 | public ResponseEntity intention(@RequestBody String queryContent) { 28 | Result result = llMsService.getIntention(queryContent); 29 | return new ResponseEntity<>(result, HttpStatus.OK); 30 | } 31 | 32 | @PostMapping(value = "/dimMetrics", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) 33 | @ApiOperation(value = "查询维度指标", notes = "查询维度指标", response = Result.class) 34 | public ResponseEntity dimMetrics(@RequestBody String queryContent) { 35 | Result result = llMsService.getDimMetric(queryContent); 36 | return new ResponseEntity<>(result, HttpStatus.OK); 37 | } 38 | 39 | @PostMapping(value = "/querySql", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) 40 | @ApiOperation(value = "生成查询sql", notes = "生成查询sql", response = Result.class) 41 | public ResponseEntity querySql(@RequestBody String queryContent) { 42 | Result result = llMsService.getSql(queryContent); 43 | return new ResponseEntity<>(result, HttpStatus.OK); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /chat_rest/src/main/java/com/am/chat/bi/domain/dao/SchemaMetaInfo.java: -------------------------------------------------------------------------------- 1 | package com.am.chat.bi.domain.dao; 2 | 3 | public class SchemaMetaInfo { 4 | } 5 | -------------------------------------------------------------------------------- /chat_rest/src/main/java/com/am/chat/bi/domain/vo/ResponseVo.java: -------------------------------------------------------------------------------- 1 | package com.am.chat.bi.domain.vo; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author wpl 7 | * @param 8 | */ 9 | @Data 10 | public class ResponseVo { 11 | //返回插入或者修改的主键id 12 | private String name; 13 | private T value; 14 | } 15 | -------------------------------------------------------------------------------- /chat_rest/src/main/java/com/am/chat/bi/service/LLMsService.java: -------------------------------------------------------------------------------- 1 | package com.am.chat.bi.service; 2 | 3 | import com.am.chat.bi.comm.Result; 4 | 5 | public interface LLMsService { 6 | Result getIntention(String queryContent); 7 | Result getDimMetric(String queryContent); 8 | Result getSql(String queryContent); 9 | } 10 | -------------------------------------------------------------------------------- /chat_rest/src/main/java/com/am/chat/bi/service/impl/LLMsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.am.chat.bi.service.impl; 2 | 3 | import com.am.chat.bi.comm.ErrorCode; 4 | import com.am.chat.bi.comm.Result; 5 | import com.am.chat.bi.domain.vo.ResponseVo; 6 | import com.am.chat.bi.service.LLMsService; 7 | import com.am.chat.bi.utils.AliLLMsUtil; 8 | import com.am.chat.bi.utils.LLMsResultUtil; 9 | import com.am.chat.bi.utils.PromptUtil; 10 | import com.google.gson.JsonElement; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | import org.springframework.stereotype.Service; 14 | 15 | @Service 16 | public class LLMsServiceImpl implements LLMsService { 17 | 18 | private static final Logger LOG = LoggerFactory.getLogger(LLMsServiceImpl.class); 19 | 20 | @Override 21 | public Result getIntention(String queryContent) { 22 | LOG.info("chat query content: {}", queryContent); 23 | try { 24 | String intentionPrompt = PromptUtil.getIntentionPrompt(queryContent); 25 | String intentionResult = AliLLMsUtil.getResult(intentionPrompt); 26 | String result = LLMsResultUtil.getIntentionResult(intentionResult); 27 | 28 | ResponseVo responseVo = new ResponseVo(); 29 | responseVo.setName("result"); 30 | responseVo.setValue(result); 31 | 32 | return Result.success().withResponse(responseVo); 33 | } catch (Exception e) { 34 | LOG.error("用户查询意图大模型结果判断异常:", e); 35 | return Result.fail(ErrorCode.FAIL_LLMs).withErrorMsg(e.getMessage()); 36 | } 37 | } 38 | 39 | @Override 40 | public Result getDimMetric(String queryContent) { 41 | LOG.info("chat query content: {}", queryContent); 42 | try { 43 | String dimensionMetricPrompt = PromptUtil.getDimensionMetricPrompt(queryContent); 44 | String dimensionMetricResult = AliLLMsUtil.getResult(dimensionMetricPrompt); 45 | 46 | String dimMetricJson = LLMsResultUtil.getDimMetricJson(dimensionMetricResult); 47 | 48 | JsonElement dimensions = LLMsResultUtil.getJsonValue(dimMetricJson, "dimensions"); 49 | JsonElement metrics = LLMsResultUtil.getJsonValue(dimMetricJson, "metrics"); 50 | 51 | ResponseVo responseVo = new ResponseVo(); 52 | responseVo.setName("dimensions"); 53 | responseVo.setValue(dimensions); 54 | 55 | responseVo.setName("metrics"); 56 | responseVo.setValue(metrics); 57 | return Result.success().withResponse(responseVo); 58 | } catch (Exception e) { 59 | LOG.error("用户查询大模型维度指标解析异常:", e); 60 | return Result.fail(ErrorCode.FAIL_LLMs).withErrorMsg(e.getMessage()); 61 | } 62 | } 63 | 64 | @Override 65 | public Result getSql(String queryContent) { 66 | LOG.info("chat query content: {}", queryContent); 67 | try { 68 | //TODO: 待补充数据库类型,基于解析的元数据信息 69 | String schemaInfo = "{\n" + 70 | " \"schema\":\"report_db\",\n" + 71 | " \"tables\":[\n" + 72 | " \"dim_table\",\n" + 73 | " \"metric_table\"\n" + 74 | " ],\n" + 75 | " \"dim_table\":[\n" + 76 | " {\n" + 77 | " \"dim_date\":\"date\",\n" + 78 | " \"dim_app_id\":\"int\",\n" + 79 | " \"dim_app_name\":\"varchar\"\n" + 80 | " },\n" + 81 | " {\n" + 82 | " \"count_date\":\"date\",\n" + 83 | " \"app_id\":\"int\",\n" + 84 | " \"app_pv\":\"bigint\",\n" + 85 | " \"app_uv\":\"bigint\"\n" + 86 | " }\n" + 87 | " ]\n" + 88 | "}"; 89 | 90 | String sqlPrompt = PromptUtil.getSqlPrompt(queryContent,"postgresql",schemaInfo, null); 91 | LOG.info("LLMs sql prompt content: {}", sqlPrompt); 92 | String sqlResult = AliLLMsUtil.getResult(sqlPrompt); 93 | String result = LLMsResultUtil.getSqlResult(sqlResult); 94 | 95 | ResponseVo responseVo = new ResponseVo(); 96 | responseVo.setName("result"); 97 | responseVo.setValue(result); 98 | 99 | return Result.success().withResponse(responseVo); 100 | } catch (Exception e) { 101 | LOG.error("用户查询大模型生成sql异常:", e); 102 | return Result.fail(ErrorCode.FAIL_LLMs).withErrorMsg(e.getMessage()); 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /chat_rest/src/main/resources/application-dev.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8498 3 | 4 | security: 5 | basic: 6 | enabled=false: 7 | 8 | spring: 9 | datasource: 10 | name: dev 11 | url: jdbc:mysql://127.0.0.1:3306/chat_bi?characterEncoding=UTF-8&useSSL=false&allowMultiQueries=true&rewriteBatchedStatements=true 12 | username: root 13 | password: 123456 14 | -------------------------------------------------------------------------------- /chat_rest/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | context-path: /chatBI 3 | tomcat: 4 | accesslog: 5 | enabled: false 6 | buffered: false 7 | directory: 8 | pattern: common 9 | awaitTerminationInSec: 30 10 | 11 | spring: 12 | profiles: 13 | ## dev, test, prod 14 | active: dev 15 | datasource: 16 | type: com.alibaba.druid.pool.DruidDataSource 17 | driver-class-name: com.mysql.jdbc.Driver 18 | druid: 19 | filters: 20 | # 初始化大小,最小,最大 21 | initial-size: 1 22 | max-active: 20 23 | min-idle: 1 24 | # 配置获取连接等待超时的时间 25 | max-wait: 5000 26 | # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 27 | time-between-eviction-runs-millis: 60000 28 | # 配置一个连接在池中最小生存的时间,单位是毫秒 29 | min-evictable-idle-time-millis: 30000 30 | validation-query: select 'x' 31 | test-while-idle: true 32 | test-on-borrow: false 33 | test-on-return: false 34 | pool-prepared-statements: true 35 | max-open-prepared-statements: 20 36 | # 配置监控页面密码登录 37 | # stat-view-servlet: 38 | # login-password: druid 39 | # login-username: druid 40 | http: 41 | multipart: 42 | max-file-size: 1024MB 43 | max-request-size: 1024MB 44 | 45 | mybatis: 46 | mapperLocations: classpath:mapper/*.xml 47 | configuration: 48 | log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 49 | 50 | pagehelper: 51 | helperDialect: mysql 52 | reasonable: true 53 | 54 | management: 55 | health: 56 | redis: 57 | enabled: false -------------------------------------------------------------------------------- /chat_rest/src/main/resources/assembly.xml: -------------------------------------------------------------------------------- 1 | 5 | ${project.version} 6 | 7 | 8 | tar.gz 9 | 10 | 11 | true 12 | 13 | 14 | 15 | 16 | 17 | 18 | lib 19 | false 20 | 21 | 22 | 23 | 24 | 25 | 26 | ${project.basedir} 27 | / 28 | 29 | README* 30 | LICENSE* 31 | NOTICE* 32 | 33 | 34 | 35 | 36 | 37 | src/main/resources 38 | config/ 39 | 40 | 41 | *.xml 42 | *.yml 43 | static/ 44 | templates/ 45 | mapper/ 46 | 47 | 48 | logback-test.xml 49 | generatorConfig.xml 50 | application-*.yml 51 | 52 | 53 | 54 | 55 | src/main/resources 56 | config/ 57 | 58 | application-${env}.yml 59 | 60 | 61 | 62 | 63 | 64 | ${project.build.scriptSourceDirectory} 65 | bin 66 | 67 | *.* 68 | 69 | true 70 | 0755 71 | 72 | 73 | 74 | src/main/resources/${env} 75 | bin 76 | 77 | setenv.sh 78 | 79 | 80 | 81 | 82 | 83 | ${project.build.directory} 84 | 85 | 86 | *.jar 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /chat_rest/src/main/resources/dev/setenv.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | PRG="$0" 3 | PRGDIR=`dirname "$PRG"` 4 | BASE_HOME=`cd "$PRGDIR/.." >/dev/null; pwd` 5 | 6 | #server内存配置 7 | export JAVA_MEM_OPTS="$JAVA_MEM_OPTS -server -Xms1G -Xmx1G -Xmn512M -XX:PermSize=128M -XX:MaxPermSize=256M -Xss512k -XX:SurvivorRatio=8" 8 | 9 | #gc 10 | export JAVA_MEM_OPTS="$JAVA_MEM_OPTS -XX:MaxTenuringThreshold=4 -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=2 -XX:+ExplicitGCInvokesConcurrent -XX:+CMSScavengeBeforeRemark" 11 | 12 | #gc日志 13 | export JAVA_MEM_OPTS="$JAVA_MEM_OPTS -Xloggc:$BASE_HOME/logs/jvm/gc.log.`date +%Y-%m-%d_%H_%M_%S` \ 14 | -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime -XX:PrintFLSStatistics=1" 15 | 16 | #内存溢出 17 | export JAVA_MEM_OPTS="$JAVA_MEM_OPTS -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$BASE_HOME/logs/heapdump.hprof" 18 | -------------------------------------------------------------------------------- /chat_rest/src/main/resources/logback-dev.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | UTF-8 9 | %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /chat_rest/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | UTF-8 9 | %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n 10 | 11 | 12 | 13 | 14 | 15 | 16 | INFO 17 | 18 | 19 | DEBUG 20 | 21 | 22 | 23 | 24 | ${log.home}/label_%d{yyyy-MM-dd}_%i.log 25 | 26 | 100MB 27 | 7 28 | 10GB 29 | 30 | 31 | UTF-8 32 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /chat_rest/src/main/resources/press/setenv.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | PRG="$0" 3 | PRGDIR=`dirname "$PRG"` 4 | BASE_HOME=`cd "$PRGDIR/.." >/dev/null; pwd` 5 | 6 | #server内存配置 7 | export JAVA_MEM_OPTS="$JAVA_MEM_OPTS -server -Xms4G -Xmx4G -Xmn2G -XX:PermSize=256M -XX:MaxPermSize=512M -Xss1M -XX:SurvivorRatio=8" 8 | 9 | #gc 10 | export JAVA_MEM_OPTS="$JAVA_MEM_OPTS -XX:MaxTenuringThreshold=4 -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=2 -XX:+ExplicitGCInvokesConcurrent -XX:+CMSScavengeBeforeRemark" 11 | 12 | #gc日志 13 | export JAVA_MEM_OPTS="$JAVA_MEM_OPTS -Xloggc:$BASE_HOME/logs/jvm/gc.log.`date +%Y-%m-%d_%H_%M_%S` \ 14 | -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime -XX:PrintFLSStatistics=1" 15 | 16 | #内存溢出 17 | export JAVA_MEM_OPTS="$JAVA_MEM_OPTS -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$BASE_HOME/logs/heapdump.hprof" 18 | -------------------------------------------------------------------------------- /chat_rest/src/main/resources/prod/setenv.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | PRG="$0" 3 | PRGDIR=`dirname "$PRG"` 4 | BASE_HOME=`cd "$PRGDIR/.." >/dev/null; pwd` 5 | 6 | #server内存配置 7 | export JAVA_MEM_OPTS="$JAVA_MEM_OPTS -server -Xms4G -Xmx4G -Xmn2G -XX:PermSize=256M -XX:MaxPermSize=512M -Xss1M -XX:SurvivorRatio=8" 8 | 9 | #gc 10 | export JAVA_MEM_OPTS="$JAVA_MEM_OPTS -XX:MaxTenuringThreshold=4 -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=2 -XX:+ExplicitGCInvokesConcurrent -XX:+CMSScavengeBeforeRemark" 11 | 12 | #gc日志 13 | export JAVA_MEM_OPTS="$JAVA_MEM_OPTS -Xloggc:$BASE_HOME/logs/jvm/gc.log.`date +%Y-%m-%d_%H_%M_%S` \ 14 | -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime -XX:PrintFLSStatistics=1" 15 | 16 | #内存溢出 17 | export JAVA_MEM_OPTS="$JAVA_MEM_OPTS -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$BASE_HOME/logs/heapdump.hprof" 18 | -------------------------------------------------------------------------------- /chat_rest/src/main/resources/sql/mysql.sql: -------------------------------------------------------------------------------- 1 | USE chat_bi; 2 | DROP TABLE IF EXISTS `scheam_meta_info`; 3 | CREATE TABLE `scheam_meta_info` ( 4 | `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID', 5 | `meta_name` varchar(64) NOT NULL COMMENT '维度,指标名称', 6 | `meta_zh_name` varchar(128) NOT NULL COMMENT '维度,指标中文名称', 7 | `meta_type` int(1) NOT NULL DEFAULT '1' COMMENT '维度1,指标2', 8 | `meta_expression` varchar(128) DEFAULT NULL COMMENT '维度,指标表达式', 9 | `meta_table_name` varchar(64) DEFAULT NULL COMMENT '维度,指标来源表名称', 10 | `meta_state` int(1) NOT NULL DEFAULT '0' COMMENT '操作类型,0:新增,1:更新,2:删除', 11 | `create_time` timestamp NULL DEFAULT NULL COMMENT '创建时间', 12 | `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 13 | PRIMARY KEY (`id`) 14 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='维度指标元数据信息表'; 15 | -------------------------------------------------------------------------------- /chat_rest/src/main/resources/test/setenv.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | PRG="$0" 3 | PRGDIR=`dirname "$PRG"` 4 | BASE_HOME=`cd "$PRGDIR/.." >/dev/null; pwd` 5 | 6 | #server内存配置 7 | export JAVA_MEM_OPTS="$JAVA_MEM_OPTS -d64 -server -Xms4G -Xmx4G -Xmn2G -XX:PermSize=256M -XX:MaxPermSize=512M -Xss1M -XX:SurvivorRatio=8" 8 | 9 | #gc 10 | export JAVA_MEM_OPTS="$JAVA_MEM_OPTS -XX:MaxTenuringThreshold=4 -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=2 -XX:+ExplicitGCInvokesConcurrent -XX:+CMSScavengeBeforeRemark" 11 | 12 | #gc日志 13 | export JAVA_MEM_OPTS="$JAVA_MEM_OPTS -Xloggc:$BASE_HOME/logs/jvm/gc.log.`date +%Y-%m-%d_%H_%M_%S` \ 14 | -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime -XX:PrintFLSStatistics=1" 15 | 16 | #内存溢出 17 | export JAVA_MEM_OPTS="$JAVA_MEM_OPTS -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$BASE_HOME/logs/heapdump.hprof" 18 | -------------------------------------------------------------------------------- /chat_rest/src/main/shell/comm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # resolve links - $0 may be a softlink 4 | PRG="$0" 5 | 6 | while [ -h "$PRG" ]; do 7 | ls=`ls -ld "$PRG"` 8 | link=`expr "$ls" : '.*-> \(.*\)$'` 9 | if expr "$link" : '/.*' > /dev/null; then 10 | PRG="$link" 11 | else 12 | PRG=`dirname "$PRG"`/"$link" 13 | fi 14 | done 15 | 16 | COMMAND="$1" 17 | 18 | # Get standard environment variables 19 | PRG_DIR=`dirname "$PRG"` 20 | PLATFORM_HOME=`cd "$PRG_DIR/.." >/dev/null; pwd` 21 | export PLATFORM_HOME 22 | 23 | PLATFORM_CONF_DIR="$PLATFORM_HOME/config" 24 | PLATFORM_LIB_DIR="$PLATFORM_HOME/lib" 25 | export PLATFORM_LIB_DIR 26 | 27 | LIB_JARS=`ls $PLATFORM_LIB_DIR | grep -E '.jar$' | awk '{print "'$PLATFORM_LIB_DIR'/"$0}' | tr "\n" ":"` 28 | 29 | PRO_NAME=${project.artifactId} 30 | PIDFILE="$PLATFORM_HOME/$(basename $PRO_NAME).pid" 31 | PID=0 32 | if [[ -f $PIDFILE ]]; then 33 | PID=`cat $PIDFILE` 34 | fi 35 | 36 | JAVA_OPTS="" 37 | JAVA_MEM_OPTS="" 38 | JAVA_SPRING_OPTS=" --spring.profiles.active=${env}" 39 | 40 | PLATFORM_MAIN_CLASS=${start-class} 41 | 42 | 43 | running() { 44 | if [[ -z $1 || $1 == 0 ]]; then 45 | echo 0 46 | return 47 | fi 48 | if ps -p $1 > /dev/null; then 49 | echo 1 50 | return 51 | fi 52 | echo 0 53 | return 54 | } 55 | 56 | set_env() { 57 | if [ -r "$PLATFORM_HOME/bin/setenv.sh" ]; then 58 | source "$PLATFORM_HOME/bin/setenv.sh" 59 | else 60 | JAVA_MEM_OPTS=" -server -Xms4g -Xmx4g -XX:SurvivorRatio=2 -XX:+UseParallelGC " 61 | fi 62 | } 63 | 64 | start() { 65 | if [[ $(running $PID) != 0 ]]; then 66 | echo "$PRO_NAME is running" 67 | return 68 | fi 69 | echo "### starting $PRO_NAME `date '+%Y-%m-%d %H:%M:%S'` ###" >> /dev/null 2>&1 & 70 | set_env 71 | echo "$JAVA_HOME/bin/java $JAVA_OPTS $JAVA_MEM_OPTS -classpath $PLATFORM_CONF_DIR:$LIB_JARS $PLATFORM_MAIN_CLASS $JAVA_SPRING_OPTS" 72 | START_CMD="$JAVA_HOME/bin/java $JAVA_OPTS $JAVA_MEM_OPTS -classpath $PLATFORM_CONF_DIR:$LIB_JARS $PLATFORM_MAIN_CLASS $JAVA_SPRING_OPTS" 73 | print_env 74 | nohup $START_CMD >> $PLATFORM_HOME/server.log 2>&1 & 75 | if [[ $(running $!) == 0 ]]; then 76 | echo "failed to start $PRO_NAME" 77 | exit 1 78 | fi 79 | PID=$! 80 | echo $! > $PIDFILE 81 | # echo "new pid $!" 82 | } 83 | 84 | stop() { 85 | if [[ $(running $PID) == 0 ]]; then 86 | echo "no $PRO_NAME is running" 87 | return 88 | fi 89 | echo "stopping $PID of $PRO_NAME ..." 90 | kill $PID 91 | } 92 | 93 | restart() { 94 | stop 95 | start 96 | } 97 | 98 | print_env() { 99 | echo "JRE_HOME: $JAVA_HOME" 100 | echo "ENV: ${env}" 101 | echo "JAVA_OPTS: $JAVA_OPTS" 102 | echo "JAVA_MEM_OPTS: $JAVA_MEM_OPTS" 103 | echo "JAVA_SPRING_OPTS: $JAVA_SPRING_OPTS" 104 | echo "START_CMD: $START_CMD" 105 | } 106 | 107 | print_usage() { 108 | echo "Usage: label.sh (start|stop)" 109 | } 110 | 111 | case $COMMAND in 112 | 113 | (start) 114 | start 115 | ;; 116 | 117 | (stop) 118 | stop 119 | ;; 120 | 121 | (*) 122 | print_usage 123 | exit 1 124 | ;; 125 | esac -------------------------------------------------------------------------------- /chat_rest/src/main/shell/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | PRG="$0" 3 | PRGDIR=`dirname "$PRG"` 4 | PLATFORM_HOME=`cd "$PRGDIR/.." >/dev/null; pwd` 5 | EXECUTABLE=comm.sh 6 | exec "$PRGDIR"/"$EXECUTABLE" start "$@" 7 | -------------------------------------------------------------------------------- /chat_rest/src/main/shell/stop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | PRG="$0" 3 | PRGDIR=`dirname "$PRG"` 4 | PLATFORM_HOME=`cd "$PRGDIR/.." >/dev/null; pwd` 5 | EXECUTABLE=comm.sh 6 | exec "$PRGDIR"/"$EXECUTABLE" stop "$@" 7 | -------------------------------------------------------------------------------- /chat_ui/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | chatBI 7 | com.am 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | chat_ui 13 | 14 | 15 | -------------------------------------------------------------------------------- /doc/photo/模块架构.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ambition119/chatBI/785185c9a6a24d4ba6388b7e05631292f1196d93/doc/photo/模块架构.jpeg -------------------------------------------------------------------------------- /doc/photo/自动生成图表.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ambition119/chatBI/785185c9a6a24d4ba6388b7e05631292f1196d93/doc/photo/自动生成图表.png -------------------------------------------------------------------------------- /plugins/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | chatBI 7 | com.am 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | plugins 13 | 14 | plugins 15 | 16 | 17 | 18 | com.google.code.gson 19 | gson 20 | 21 | 22 | 23 | com.alibaba 24 | dashscope-sdk-java 25 | 26 | 27 | ch.qos.logback 28 | logback-classic 29 | 30 | 31 | ch.qos.logback 32 | logback-core 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /plugins/src/main/java/com/am/chat/bi/utils/AliLLMsUtil.java: -------------------------------------------------------------------------------- 1 | package com.am.chat.bi.utils; 2 | 3 | 4 | import com.alibaba.dashscope.aigc.generation.Generation; 5 | import com.alibaba.dashscope.aigc.generation.GenerationResult; 6 | import com.alibaba.dashscope.aigc.generation.models.QwenParam; 7 | import com.alibaba.dashscope.common.ResultCallback; 8 | import com.alibaba.dashscope.utils.Constants; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | import java.util.concurrent.Semaphore; 13 | 14 | 15 | public class AliLLMsUtil { 16 | private static final Logger LOG = LoggerFactory.getLogger(AliLLMsUtil.class); 17 | 18 | static { 19 | Constants.apiKey = "sk-547"; 20 | } 21 | 22 | public static String getResult(String prompt) throws Exception { 23 | Generation gen = new Generation(); 24 | QwenParam param = QwenParam.builder().model(Generation.Models.QWEN_TURBO).prompt(prompt) 25 | .topP(0.8).build(); 26 | Semaphore semaphore = new Semaphore(0); 27 | 28 | final String[] result = {null}; 29 | gen.call(param, new ResultCallback() { 30 | 31 | @Override 32 | public void onEvent(GenerationResult message) { 33 | System.out.println(message); 34 | 35 | result[0] = message.getOutput().getText(); 36 | LOG.info("阿里大模型返回结果:{}",message); 37 | } 38 | @Override 39 | public void onError(Exception ex){ 40 | System.out.println(ex.getMessage()); 41 | semaphore.release(); 42 | } 43 | @Override 44 | public void onComplete(){ 45 | System.out.println("onComplete"); 46 | semaphore.release(); 47 | } 48 | 49 | }); 50 | semaphore.acquire(); 51 | 52 | return result[0]; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /plugins/src/main/java/com/am/chat/bi/utils/LLMsResultUtil.java: -------------------------------------------------------------------------------- 1 | package com.am.chat.bi.utils; 2 | 3 | import com.google.gson.JsonElement; 4 | import com.google.gson.JsonObject; 5 | import com.google.gson.JsonParser; 6 | 7 | import java.util.regex.Matcher; 8 | import java.util.regex.Pattern; 9 | 10 | public class LLMsResultUtil { 11 | 12 | public static String getIntentionResult(String result){ 13 | String intentionResult = null; 14 | 15 | Pattern pattern = Pattern.compile("(\\d+)"); 16 | Matcher matcher = pattern.matcher(result); 17 | if (matcher.find()) { 18 | intentionResult = matcher.group(); 19 | } 20 | 21 | return intentionResult; 22 | } 23 | 24 | public static JsonElement getJsonValue(String result, String name) { 25 | JsonParser parser = new JsonParser(); 26 | JsonObject jsonObject = parser.parse(result).getAsJsonObject(); 27 | return jsonObject.get(name); 28 | } 29 | 30 | public static String getDimMetricJson(String result){ 31 | String sqlResult = null; 32 | // Pattern pattern = Pattern.compile("```json(.*?)```"); 33 | Pattern pattern = Pattern.compile("\\{.*\\}"); 34 | Matcher matcher = pattern.matcher(result); 35 | if (matcher.find()) { 36 | sqlResult = matcher.group(); 37 | } 38 | 39 | return sqlResult; 40 | } 41 | 42 | public static String getSqlResult(String result){ 43 | String sqlResult = null; 44 | 45 | Pattern pattern = Pattern.compile("querySql: \"(.*?)\"}"); 46 | Matcher matcher = pattern.matcher(result); 47 | if (matcher.find()) { 48 | sqlResult = matcher.group(); 49 | } 50 | 51 | return sqlResult; 52 | } 53 | 54 | 55 | } 56 | -------------------------------------------------------------------------------- /plugins/src/main/java/com/am/chat/bi/utils/PromptUtil.java: -------------------------------------------------------------------------------- 1 | package com.am.chat.bi.utils; 2 | 3 | public class PromptUtil { 4 | 5 | /** 6 | * 查询意图 7 | * @param queryContent 8 | * @return 9 | */ 10 | public static String getIntentionPrompt(String queryContent) { 11 | String intentionPrompt = "“" + queryContent + "” 请帮忙判断这句话的意图是需要" + 12 | "知识库还是数据查询。如果意图是知识库的话result返回值是1,是数据查询的话result返回值是2。" + 13 | "最后返回值采用json数据格式,返回值格式为{result:result_$返回值}" 14 | ; 15 | 16 | return intentionPrompt; 17 | 18 | } 19 | 20 | public static String getDimensionMetricPrompt(String queryContent) { 21 | String dimMetricPrompt = "“" + queryContent + "” 请帮忙解析这句话中含有的维度与指标。解析要求:" + 22 | "1,语句中除了指标名词外,默认其他名词为维度。" + 23 | "2,最后的返回结果采用json数据格式,指定返回格式为{dimensions:array[$维度名称],metrics:array[$指标名称]}。"; 24 | 25 | return dimMetricPrompt; 26 | } 27 | 28 | public static String getSqlPrompt(String queryContent, String dbType, String schemaInfo, String dbDialect) { 29 | String sqlPrompt = "假设你是"+dbType+"的专家,需要通过问题描述和指令语句两部分内容帮忙生成对应查询SQL语句。第一部分问题说明:\n" + 30 | "“" + queryContent + "” \n" + 31 | "第二部分指令内容:\n" + 32 | "1,不能幻觉出现新的字段,schema字段、表名称、表字段名称必须使用提供的元数据内容信息,元数据信息json格式数据 " + schemaInfo + " \n" + 33 | "2,可能需要关联表的查询SQL才满足问题内容的要求,关联的表和表字段一定存在已经提供的元数据内容。\n" + 34 | "3,生产的sql语句使用json格式返回,返回数据格式要求{querySQL: $生成的结果SQL}。"; 35 | 36 | return sqlPrompt; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | com.am 7 | chatBI 8 | pom 9 | 1.0-SNAPSHOT 10 | 11 | 12 | chat_rest 13 | chat_ui 14 | plugins 15 | 16 | 17 | 18 | UTF-8 19 | 8 20 | 8 21 | 1.5.9.RELEASE 22 | 4.3.13.RELEASE 23 | 1.3.2 24 | 1.1.10 25 | 1.1.1 26 | 3.7 27 | 1.2.47 28 | 2.7.0 29 | 1.2.3 30 | 1.18.0 31 | 2.7.2 32 | 5.1.46 33 | 34 | 35 | 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter 40 | ${spring-boot-starter-parent} 41 | 42 | 43 | logback-classic 44 | ch.qos.logback 45 | 46 | 47 | 48 | 49 | org.springframework.boot 50 | spring-boot-starter-web 51 | ${spring-boot-starter-parent} 52 | 53 | 54 | 55 | org.springframework 56 | spring-context-support 57 | ${spring-content.version} 58 | 59 | 60 | 61 | org.springframework.boot 62 | spring-boot-starter-websocket 63 | ${spring-boot-starter-parent} 64 | 65 | 66 | 67 | org.springframework.boot 68 | spring-boot-configuration-processor 69 | ${spring-boot-starter-parent} 70 | true 71 | 72 | 73 | 74 | org.springframework.boot 75 | spring-boot-starter-test 76 | ${spring-boot-starter-parent} 77 | test 78 | 79 | 80 | 81 | io.springfox 82 | springfox-swagger2 83 | ${swagger.version} 84 | 85 | 86 | 87 | io.springfox 88 | springfox-swagger-ui 89 | ${swagger.version} 90 | 91 | 92 | 93 | com.github.pagehelper 94 | pagehelper-spring-boot-starter 95 | ${pagehelper} 96 | 97 | 98 | mybatis-spring-boot-starter 99 | org.mybatis.spring.boot 100 | 101 | 102 | 103 | 104 | 105 | org.mybatis.spring.boot 106 | mybatis-spring-boot-starter 107 | ${mybatis-spring-boot-starter} 108 | 109 | 110 | org.springframework.boot 111 | spring-boot-starter 112 | 113 | 114 | 115 | 116 | 117 | com.alibaba 118 | druid-spring-boot-starter 119 | ${druid} 120 | 121 | 122 | 123 | mysql 124 | mysql-connector-java 125 | ${mysql.version} 126 | 127 | 128 | 129 | org.mybatis.spring.boot 130 | mybatis-spring-boot-starter-test 131 | ${mybatis-spring-boot-starter} 132 | 133 | 134 | 135 | org.projectlombok 136 | lombok 137 | ${lombok.version} 138 | 139 | 140 | 141 | org.apache.commons 142 | commons-lang3 143 | ${commons-lang3} 144 | 145 | 146 | 147 | ch.qos.logback 148 | logback-classic 149 | ${logback.version} 150 | 151 | 152 | logback-core 153 | ch.qos.logback 154 | 155 | 156 | 157 | 158 | ch.qos.logback 159 | logback-core 160 | ${logback.version} 161 | 162 | 163 | 164 | com.google.code.gson 165 | gson 166 | 2.10.1 167 | 168 | 169 | 170 | com.alibaba 171 | dashscope-sdk-java 172 | 2.6.1 173 | 174 | 175 | 176 | redis.clients 177 | jedis 178 | ${redis.version} 179 | 180 | 181 | 182 | 183 | --------------------------------------------------------------------------------