mirror of
https://github.com/tencentmusic/supersonic.git
synced 2025-12-10 19:51:00 +00:00
Compare commits
172 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86bf40c8fb | ||
|
|
f90ab22119 | ||
|
|
8e7d224b7b | ||
|
|
29925a90ca | ||
|
|
fdf48d7bfd | ||
|
|
d9efe8f137 | ||
|
|
6afb2f0914 | ||
|
|
82ab9e3a6a | ||
|
|
f5ca33859c | ||
|
|
a0b4fb33c1 | ||
|
|
40705181a0 | ||
|
|
308178f299 | ||
|
|
410f2c93b9 | ||
|
|
767abc2b90 | ||
|
|
ab19b18169 | ||
|
|
406fe995c9 | ||
|
|
151963ea79 | ||
|
|
5583426115 | ||
|
|
9d1707eba1 | ||
|
|
f605cf0ef9 | ||
|
|
119e5b8c58 | ||
|
|
de764f3353 | ||
|
|
e4280e5516 | ||
|
|
886ee32e2f | ||
|
|
7544780ff7 | ||
|
|
26beff1080 | ||
|
|
88b8130d37 | ||
|
|
e7b8c68dba | ||
|
|
b753eda9b9 | ||
|
|
e6f2ce2598 | ||
|
|
a191bbbf6e | ||
|
|
65f48dd789 | ||
|
|
c14d4e59d4 | ||
|
|
6b2a14e589 | ||
|
|
d6cefaa6d2 | ||
|
|
278af3ce34 | ||
|
|
3b1cbd4fd7 | ||
|
|
500652da36 | ||
|
|
eee39f56a8 | ||
|
|
719b797037 | ||
|
|
7cb8208065 | ||
|
|
a03ababc80 | ||
|
|
a3565a0ae9 | ||
|
|
07a64375ce | ||
|
|
ec1e63e2f2 | ||
|
|
8487966888 | ||
|
|
4bbd2c7446 | ||
|
|
d9bab899fe | ||
|
|
e3b3e8861d | ||
|
|
69242f9f2d | ||
|
|
a21c7bce40 | ||
|
|
7379e3a833 | ||
|
|
b565b9c4e5 | ||
|
|
99ac17a5e4 | ||
|
|
4ccee8b107 | ||
|
|
eccd791a39 | ||
|
|
3d6878fe9f | ||
|
|
1e1803d148 | ||
|
|
343995fd8f | ||
|
|
71cb20eb4f | ||
|
|
741ed4191b | ||
|
|
2a6391a2ee | ||
|
|
405e846a0e | ||
|
|
155cf22841 | ||
|
|
e688422ec3 | ||
|
|
6047c787b3 | ||
|
|
c03166b622 | ||
|
|
617db611c3 | ||
|
|
f931951ad5 | ||
|
|
df7fea9ee3 | ||
|
|
24e8e756de | ||
|
|
ff5479f1a2 | ||
|
|
4ad3e1d9cf | ||
|
|
e4af83380b | ||
|
|
d30fe53ef3 | ||
|
|
9e0abc60be | ||
|
|
dc33cdce5a | ||
|
|
f5b8690ce0 | ||
|
|
fbb67f54ab | ||
|
|
5c4e80c8f8 | ||
|
|
0774c35589 | ||
|
|
553963a10a | ||
|
|
0bf171c8a6 | ||
|
|
f5549f7430 | ||
|
|
34816451c0 | ||
|
|
e1772c25c4 | ||
|
|
65653c0ee2 | ||
|
|
3addfb9a87 | ||
|
|
67be01f504 | ||
|
|
99aa7c9433 | ||
|
|
ccfdec8b45 | ||
|
|
dbd259adb0 | ||
|
|
ec151d7b53 | ||
|
|
5fbb1927a4 | ||
|
|
3bc13642af | ||
|
|
6b38a4f602 | ||
|
|
51f62438cf | ||
|
|
9d8b54072a | ||
|
|
0982c013d1 | ||
|
|
03a4719aed | ||
|
|
5c3fd75ed4 | ||
|
|
6dfc728b5b | ||
|
|
071ef8432e | ||
|
|
8ad5ffe20f | ||
|
|
49ba0e3f41 | ||
|
|
5a42ff4b78 | ||
|
|
20472dce88 | ||
|
|
057a7c9c6d | ||
|
|
63eff5c62a | ||
|
|
b824cd8ce7 | ||
|
|
eee82dea07 | ||
|
|
98656eb445 | ||
|
|
c8ff37e304 | ||
|
|
3fe726ac23 | ||
|
|
d5a253a781 | ||
|
|
6a5a95e543 | ||
|
|
a94a44826b | ||
|
|
31c8fea2dc | ||
|
|
13dcf0edb9 | ||
|
|
7bc64bc53b | ||
|
|
4991efe50c | ||
|
|
a87304b22b | ||
|
|
3701ade05f | ||
|
|
45ed5648c4 | ||
|
|
682d35b2b2 | ||
|
|
30f5fc9ab1 | ||
|
|
bc69d2221a | ||
|
|
592870f397 | ||
|
|
157c2999dc | ||
|
|
b6d984475c | ||
|
|
6a98ce9d28 | ||
|
|
c802c508fb | ||
|
|
545fb139ee | ||
|
|
c38507d50c | ||
|
|
c8b5c0f3a3 | ||
|
|
ef30e7a5b8 | ||
|
|
12417c66cd | ||
|
|
f00da45824 | ||
|
|
8d8440f724 | ||
|
|
55138986ed | ||
|
|
2c621a1338 | ||
|
|
c6b87d30a5 | ||
|
|
8c5c7c2e32 | ||
|
|
7fce9bacc2 | ||
|
|
8aedfbb6a0 | ||
|
|
eca92d2493 | ||
|
|
a4fc11887c | ||
|
|
e4b0129fba | ||
|
|
76e8d253b1 | ||
|
|
d173924efd | ||
|
|
465416e30c | ||
|
|
a8add4c013 | ||
|
|
02068f58c7 | ||
|
|
3c0edb67c7 | ||
|
|
5bab18e092 | ||
|
|
71d9f9c9e9 | ||
|
|
90f6a20516 | ||
|
|
898108d7e1 | ||
|
|
728e7647dc | ||
|
|
ac0f7ea982 | ||
|
|
20d7941d57 | ||
|
|
ddcdd99188 | ||
|
|
9267f8ed18 | ||
|
|
249728919d | ||
|
|
f3f84ab9af | ||
|
|
90e62ddccc | ||
|
|
fbd145fd92 | ||
|
|
f5a7068d5e | ||
|
|
d5c5c63a75 | ||
|
|
559ef974b0 | ||
|
|
8440f1f30e | ||
|
|
728235907d |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -15,4 +15,6 @@ assembly/runtime/*
|
||||
/assembly/deploy
|
||||
/runtime
|
||||
**/.flattened-pom.xml
|
||||
__pycache__/
|
||||
chm_db/
|
||||
__pycache__/
|
||||
/dict
|
||||
34
CHANGELOG.md
34
CHANGELOG.md
@@ -4,6 +4,40 @@
|
||||
- "Breaking Changes" describes any changes that may break existing functionality or cause
|
||||
compatibility issues with previous versions.
|
||||
|
||||
## SuperSonic [0.7.5] - 2023-10-13
|
||||
|
||||
### Added
|
||||
- add SQL generation improvement optimization, support LLM SQL, Logic SQL, and Physical SQL display.
|
||||
- add showcase functionality to support recommending similar questions.
|
||||
- add frontend modification of filtering conditions and re-querying feature.
|
||||
- support nested query functionality in semantic.
|
||||
- support switching queries between multiple parsers in the frontend.
|
||||
|
||||
### Updated
|
||||
- optimizing the build and deployment of the project.
|
||||
- overall optimization of the SQL Corrector functionality.
|
||||
|
||||
### Fixed
|
||||
- fix execute error on mysql <=5.7
|
||||
|
||||
## SuperSonic [0.7.4] - 2023-09-10
|
||||
|
||||
### Added
|
||||
- add llm parser config
|
||||
- add datasource agg_time option
|
||||
- add function name adaptor in clickhouse
|
||||
- add dimension and metric show in dsl
|
||||
|
||||
### Updated
|
||||
- update user guide doc
|
||||
- update query building of plugin in default model
|
||||
- update some core API constructs to keep naming consistency
|
||||
- update ConfigureDemo config
|
||||
- update the association mechanism so that invisible dimensions and metrics will no longer be associated
|
||||
|
||||
### Fixed
|
||||
- fix hasAggregateFunction logic in SqlParserSelectHelper
|
||||
|
||||
## SuperSonic [0.7.3] - 2023-08-29
|
||||
|
||||
### Added
|
||||
|
||||
40
README.md
40
README.md
@@ -1,27 +1,27 @@
|
||||
English | [中文](README_CN.md)
|
||||
[中文介绍](README_CN.md) | [文档中心](https://github.com/tencentmusic/supersonic/wiki)
|
||||
|
||||
# SuperSonic (超音数)
|
||||
|
||||
**SuperSonic is an out-of-the-box yet highly extensible framework for building a data chatbot**. SuperSonic provides a chat interface that empowers users to query data using natural language and visualize the results with suitable charts. To enable such experience, the only thing necessary is to build logical semantic models (definition of metrics/dimensions/entities, along with their meaning, context and relationships) on top of physical data models, and no data modification or copying is required. Meanwhile, SuperSonic is designed to be pluggable, allowing new functionalities to be added through plugins and core components to be integrated with other systems.
|
||||
**SuperSonic is an out-of-the-box yet highly extensible framework for building ChatBI**. SuperSonic provides a chat interface that empowers users to query data using natural language and visualize the results with suitable charts. To enable such experience, the only thing necessary is to build logical semantic models (definition of metrics/dimensions/entities, along with their meaning, context and relationships) on top of physical data models, and no data modification or copying is required. Meanwhile, SuperSonic is designed to be pluggable, allowing new functionalities to be added through plugins and core components to be integrated with other systems.
|
||||
|
||||
<img src="./docs/images/supersonic_demo.gif" height="100%" width="100%" align="center"/>
|
||||
|
||||
## Motivation
|
||||
|
||||
The emergence of Large Language Model (LLM) like ChatGPT is reshaping the way information is retrieved. In the field of data analytics, both academia and industry are primarily focused on leveraging LLM to convert natural language queries into SQL queries. While some works show promising results, they are still not applicable to real-world scenarios.
|
||||
The emergence of Large Language Model (LLM) like ChatGPT is reshaping the way information is retrieved. In the field of data analytics, both academia and industry are primarily focused on leveraging LLM to convert natural language into SQL (so called text2sql or nl2sql). While some works exhibit promising results, their **reliability** is inadequate for real-world applications.
|
||||
|
||||
From our perspective, the key to filling the real-world gap lies in three aspects:
|
||||
1. Complement the LLM-based semantic parser with rule-based semantic parsers to improve **efficiency**(in terms of latency and cost).
|
||||
2. Augment semantic parsing with schema mappers(as a kind of preprocessor) and semantic correctors(as a kind of postprocessor) to improve **accuracy** and **stability**.
|
||||
3. Introduce a semantic layer encapsulating underlying data context(joins, formulas, etc) to reduce **complexity**.
|
||||
1. Introduce a semantic layer encapsulating underlying data context(joins, formulas, etc) to reduce **complexity**.
|
||||
2. Augment the LLM with schema mappers(as a kind of preprocessor) and semantic correctors(as a kind of postprocessor) to mitigate **hallucination**.
|
||||
3. Utilize heuristic rules when necessary to improve **efficiency**(in terms of latency and cost).
|
||||
|
||||
With these ideas in mind, we develop SuperSonic as a practical reference implementation and use it to power our real-world products. Additionally, to facilitate further development of data chatbot, we decide to open source SuperSonic as an extensible framework.
|
||||
With these ideas in mind, we develop SuperSonic as a practical reference implementation and use it to power our real-world products. Additionally, to facilitate further development of ChatBI, we decide to open source SuperSonic as an extensible framework.
|
||||
|
||||
## Out-of-the-box Features
|
||||
|
||||
- Built-in CUI(Chat User Interface) for *business users* to enter data queries
|
||||
- Built-in GUI(Graphical User Interface) for *analytics engineers* to build semantic models
|
||||
- Built-in GUI for *system administrators* to manage chat plugins and agents
|
||||
- Built-in GUI for *system administrators* to manage chat agents and third-party plugins
|
||||
- Support input auto-completion as well as query recommendation
|
||||
- Support multi-turn conversation and history context management
|
||||
- Support four-level permission control: domain-level, model-level, column-level and row-level
|
||||
@@ -40,7 +40,7 @@ The high-level architecture and main process flow is as follows:
|
||||
|
||||
- **Semantic Corrector:** checks validity of extracted semantic information and performs correction and optimization if needed.
|
||||
|
||||
- **Semantic Layer:** performs execution according to extracted semantic information. It generates SQL queries and executes them against physical data models.
|
||||
- **Semantic Interpreter:** performs execution according to extracted semantic information. It generates SQL statements and executes them against physical data models.
|
||||
|
||||
- **Chat Plugin:** extends functionality with third-party tools. The LLM is going to select the most suitable one, given all configured plugins with function description and sample questions.
|
||||
|
||||
@@ -49,27 +49,15 @@ The high-level architecture and main process flow is as follows:
|
||||
SuperSonic comes with sample semantic models as well as chat conversations that can be used as a starting point. Please follow the steps:
|
||||
|
||||
- Download the latest prebuilt binary from the [release page](https://github.com/tencentmusic/supersonic/releases)
|
||||
- Run script "bin/start-standalone.sh" to start a standalone server
|
||||
- Run script "bin/supersonic-daemon.sh" to start services (one java process and one python process)
|
||||
- Visit http://localhost:9080 in the browser to start exploration
|
||||
|
||||
## How to Build
|
||||
## Build and Development
|
||||
|
||||
SuperSonic can be deployed in two modes: standalone (for a quick demo) and distributed (for production use).
|
||||
|
||||
### Build for Standalone Mode
|
||||
|
||||
Pull the source code and run script "assembly/bin/build-standalone.sh" to build a single packages.
|
||||
|
||||
### Build for Distributed Mode
|
||||
|
||||
Pull the source code and run scripts "assembly/bin/build-chat.sh" and "assembly/bin/build-semantic.sh" separately to build packages.
|
||||
|
||||
### Build for Local Development
|
||||
|
||||
Pull the source code and run script "assembly/bin/build-ide.sh" and run bootstrap class "StandaloneLauncher" in the IDE.
|
||||
Please refer to project [wiki](https://github.com/tencentmusic/supersonic/wiki).
|
||||
|
||||
## WeChat Contact
|
||||
|
||||
Please join the chat group to suggest feedbacks or ideas:
|
||||
Please follow SuperSonic wechat official account:
|
||||
|
||||
<img src="./docs/images/wechat_contact.jpeg" height="30%" width="30%" align="center"/>
|
||||
<img src="./docs/images/supersonic_wechat_oa.png" height="50%" width="50%" align="center"/>
|
||||
36
README_CN.md
36
README_CN.md
@@ -6,12 +6,12 @@
|
||||
|
||||
## 项目动机
|
||||
|
||||
大型语言模型(LLMs)如ChatGPT的出现正在重塑信息检索的方式。在数据分析领域,学术界和工业界主要关注利用深度学习模型将自然语言查询转换为SQL查询。虽然一些工作显示出有前景的结果,但它们还并不适用于实际场景。
|
||||
大型语言模型(LLMs)如ChatGPT的出现正在重塑信息检索的方式。在数据分析领域,学术界和工业界主要关注利用深度学习模型将自然语言查询转换为SQL查询。虽然一些工作显示出有前景的结果,但它们的可靠性还达不到生产可用的要求。
|
||||
|
||||
在我们看来,为了在实际场景发挥价值,有三个关键点:
|
||||
1. 在基于大模型语义解析器基础上,增加基于规则的解析器,提升语义解析的**效率**。
|
||||
2. 加入模式映射器和语义修正器,来增强语义解析能力,提升语义解析的**准确性**和**稳定性**。
|
||||
3. 引入语义模型层,封装底层数据的上下文(关联、公式等),降低语义解析的**复杂性**。
|
||||
1. 引入语义模型层,封装底层数据的上下文(关联、公式等),降低SQL生成的**复杂度**。
|
||||
2. 通过一前一后的模式映射器和语义修正器,来缓解LLM常见的**幻觉**现象。
|
||||
3. 设计启发式的规则,在一些特定场景提升语义解析的**效率**。
|
||||
|
||||
为了验证上述想法,我们开发了超音数项目,并将其应用在实际的内部产品中。与此同时,我们将超音数作为一个可扩展的框架开源,希望能够促进数据问答对话领域的进一步发展。
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
- 内置对话界面以便*业务用户*输入数据查询。
|
||||
- 内置图形界面以便*分析工程师*构建语义模型。
|
||||
- 内置图形界面以便*系统管理员*管理问答插件和助理。
|
||||
- 内置图形界面以便*系统管理员*管理第三方插件和对话助理。
|
||||
- 支持文本输入的联想和查询问题的推荐。
|
||||
- 支持多轮对话,根据语境自动切换上下文。
|
||||
- 支持四级权限控制:主题域级、模型级、列级、行级。
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
<img src="./docs/images/supersonic_components.png" height="65%" width="65%" align="center"/>
|
||||
|
||||
- **知识库(Knowledge Base):** 定期从语义模型中提取相关的模式信息,构建词典和索引,以便后续的模式映射。
|
||||
- **模型知识库(Knowledge Base):** 定期从语义模型中提取相关的模式信息,构建词典和索引,以便后续的模式映射。
|
||||
|
||||
- **模式映射器(Schema Mapper):** 将自然语言文本在知识库中进行匹配,为后续的语义解析提供相关信息。
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
- **语义修正器(Semantic Corrector):** 检查语义信息的合法性,对不合法的信息做修正和优化处理。
|
||||
|
||||
- **语义模型层(Semantic Layer):** 根据语义信息生成物理SQL执行查询。
|
||||
- **语义解释器(Semantic Interpreter):** 根据语义信息生成物理SQL执行查询。
|
||||
|
||||
- **问答插件(Chat Plugin):** 通过第三方工具扩展功能。给定所有配置的插件及其功能描述和示例问题,大语言模型将选择最合适的插件。
|
||||
|
||||
@@ -47,27 +47,15 @@
|
||||
超音数自带样例的语义模型和问答对话,只需以下三步即可快速体验:
|
||||
|
||||
- 从[release page](https://github.com/tencentmusic/supersonic/releases)下载预先构建好的发行包
|
||||
- 运行 "bin/start-standalone.sh"启动服务
|
||||
- 运行 "bin/supersonic-daemon.sh"启动服务(一个Java进程和一个Python进程)
|
||||
- 在浏览器访问http://localhost:9080 开启探索
|
||||
|
||||
## 如何构建
|
||||
## 如何构建和部署
|
||||
|
||||
超音数可以运行在两个模式:standalone(一般用于快速演示)和distributed(一般用于生产环境)。
|
||||
|
||||
### Standalone模式构建
|
||||
|
||||
下载源码包,运行脚本"assembly/bin/build-standalone.sh",将所有服务一起编译打包。
|
||||
|
||||
### Distributed模式构建
|
||||
|
||||
下载源码包,分别运行脚本"assembly/bin/build-chat.sh"、"assembly/bin/build-semantic.sh",为问答层服务和语义层服务编译打包。
|
||||
|
||||
### 本地开发构建
|
||||
|
||||
下载源码包,运行脚本"assembly/bin/build-ide.sh",然后在本地IDE运行启动类"StandaloneLauncher"。
|
||||
请参考项目[wiki](https://github.com/tencentmusic/supersonic/wiki)。
|
||||
|
||||
## 微信联系方式
|
||||
|
||||
欢迎加入微信群反馈建议:
|
||||
欢迎关注微信公众号:
|
||||
|
||||
<img src="./docs/images/wechat_contact.jpeg" height="30%" width="30%" align="center"/>
|
||||
<img src="./docs/images/supersonic_wechat_oa.png" height="50%" width="50%" align="center"/>
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
sbinDir=$(cd "$(dirname "$0")"; pwd)
|
||||
baseDir=$(cd "$sbinDir/.." && pwd -P)
|
||||
runtimeDir=$baseDir/runtime
|
||||
buildDir=$baseDir/build
|
||||
|
||||
cd $baseDir
|
||||
|
||||
#1. move package to build
|
||||
cp $baseDir/../launchers/chat/target/*.tar.gz ${buildDir}/supersonic-chat.tar.gz
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
sbinDir=$(cd "$(dirname "$0")"; pwd)
|
||||
baseDir=$(cd "$sbinDir/.." && pwd -P)
|
||||
buildDir=$baseDir/build
|
||||
|
||||
cd $baseDir/bin
|
||||
sh build-standalone.sh
|
||||
|
||||
cd $buildDir
|
||||
tar xvf supersonic-webapp.tar.gz
|
||||
mv supersonic-webapp webapp
|
||||
mv webapp ../../launchers/standalone/target/classes
|
||||
@@ -1,23 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
sbinDir=$(cd "$(dirname "$0")"; pwd)
|
||||
baseDir=$(cd "$sbinDir/.." && pwd -P)
|
||||
runtimeDir=$baseDir/runtime
|
||||
buildDir=$baseDir/build
|
||||
|
||||
cd $baseDir
|
||||
|
||||
#1. build semantic service
|
||||
rm -fr ${buildDir}/*.tar.gz
|
||||
rm -fr dist
|
||||
|
||||
mvn -f $baseDir/../ clean package -DskipTests
|
||||
|
||||
#2. move package to build
|
||||
cp $baseDir/../launchers/semantic/target/*.tar.gz ${buildDir}/supersonic-semantic.tar.gz
|
||||
|
||||
#3. build webapp
|
||||
chmod +x $baseDir/../webapp/start-fe-prod.sh
|
||||
cd ../webapp
|
||||
sh ./start-fe-prod.sh
|
||||
cp -fr ./supersonic-webapp.tar.gz ${buildDir}/
|
||||
@@ -1,23 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
sbinDir=$(cd "$(dirname "$0")"; pwd)
|
||||
baseDir=$(cd "$sbinDir/.." && pwd -P)
|
||||
runtimeDir=$baseDir/runtime
|
||||
buildDir=$baseDir/build
|
||||
|
||||
cd $baseDir
|
||||
|
||||
#1. build semantic chat service
|
||||
rm -fr ${buildDir}/*.tar.gz
|
||||
rm -fr dist
|
||||
|
||||
mvn -f $baseDir/../ clean package -DskipTests
|
||||
|
||||
#2. move package to build
|
||||
cp $baseDir/../launchers/standalone/target/*.tar.gz ${buildDir}/supersonic.tar.gz
|
||||
|
||||
#3. build webapp
|
||||
chmod +x $baseDir/../webapp/start-fe-prod.sh
|
||||
cd ../webapp
|
||||
sh ./start-fe-prod.sh
|
||||
cp -fr ./supersonic-webapp.tar.gz ${buildDir}/
|
||||
@@ -1,35 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
sbinDir=$(cd "$(dirname "$0")"; pwd)
|
||||
baseDir=$(cd "$sbinDir/.." && pwd -P)
|
||||
runtimeDir=$baseDir/../runtime
|
||||
buildDir=$baseDir/build
|
||||
|
||||
cd $baseDir
|
||||
|
||||
#2. package lib
|
||||
|
||||
tar -zxvf ${buildDir}/supersonic-chat.tar.gz -C ${runtimeDir}
|
||||
|
||||
mv ${runtimeDir}/launchers-chat-* ${runtimeDir}/supersonic-chat
|
||||
|
||||
tar -zxvf ${buildDir}/supersonic-webapp.tar.gz -C ${buildDir}
|
||||
|
||||
mkdir -p ${runtimeDir}/supersonic-chat/webapp
|
||||
|
||||
cp -fr ${buildDir}/supersonic-webapp/* ${runtimeDir}/supersonic-chat/webapp
|
||||
|
||||
rm -fr ${buildDir}/supersonic-webapp
|
||||
|
||||
json=$(cat ${runtimeDir}/supersonic-chat/webapp/supersonic.config.json)
|
||||
json=$(echo $json | jq '.env="chat"')
|
||||
echo $json > ${runtimeDir}/supersonic-chat/webapp/supersonic.config.json
|
||||
|
||||
#3. start service
|
||||
#3.1 start chat service
|
||||
echo ${runtimeDir}
|
||||
sh ${runtimeDir}/supersonic-chat/bin/service.sh restart
|
||||
|
||||
#3.2 start llm service
|
||||
sh ${runtimeDir}/supersonic-chat/llm/bin/service.sh restart
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
sbinDir=$(cd "$(dirname "$0")"; pwd)
|
||||
baseDir=$(cd "$sbinDir/.." && pwd -P)
|
||||
runtimeDir=$baseDir/../runtime
|
||||
buildDir=$baseDir/build
|
||||
|
||||
cd $baseDir
|
||||
|
||||
#1. clear file
|
||||
mkdir -p ${runtimeDir}
|
||||
rm -fr ${runtimeDir}/*
|
||||
|
||||
#2. package lib
|
||||
|
||||
tar -zxvf ${buildDir}/supersonic-semantic.tar.gz -C ${runtimeDir}
|
||||
|
||||
mv ${runtimeDir}/launchers-semantic-* ${runtimeDir}/supersonic-semantic
|
||||
|
||||
tar -zxvf ${buildDir}/supersonic-webapp.tar.gz -C ${buildDir}
|
||||
|
||||
mkdir -p ${runtimeDir}/supersonic-semantic/webapp
|
||||
|
||||
cp -fr ${buildDir}/supersonic-webapp/* ${runtimeDir}/supersonic-semantic/webapp
|
||||
|
||||
rm -fr ${buildDir}/supersonic-webapp
|
||||
|
||||
|
||||
json=$(cat ${runtimeDir}/supersonic-semantic/webapp/supersonic.config.json)
|
||||
json=$(echo $json | jq '.env="semantic"')
|
||||
echo $json > ${runtimeDir}/supersonic-semantic/webapp/supersonic.config.json
|
||||
|
||||
#3. start service
|
||||
sh ${runtimeDir}/supersonic-semantic/bin/service.sh restart
|
||||
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
sbinDir=$(cd "$(dirname "$0")"; pwd)
|
||||
baseDir=$(cd "$sbinDir/.." && pwd -P)
|
||||
runtimeDir=$baseDir/../runtime
|
||||
buildDir=$baseDir/build
|
||||
|
||||
cd $baseDir
|
||||
|
||||
#1. clear file
|
||||
mkdir -p ${runtimeDir}
|
||||
rm -fr ${runtimeDir}/*
|
||||
|
||||
#2. package lib
|
||||
|
||||
tar -zxvf ${buildDir}/supersonic.tar.gz -C ${runtimeDir}
|
||||
|
||||
mv ${runtimeDir}/launchers-standalone-* ${runtimeDir}/supersonic-standalone
|
||||
|
||||
tar -zxvf ${buildDir}/supersonic-webapp.tar.gz -C ${buildDir}
|
||||
|
||||
mkdir -p ${runtimeDir}/supersonic-standalone/webapp
|
||||
|
||||
cp -fr ${buildDir}/supersonic-webapp/* ${runtimeDir}/supersonic-standalone/webapp
|
||||
|
||||
rm -fr ${buildDir}/supersonic-webapp
|
||||
|
||||
#3. start service
|
||||
#start standalone service
|
||||
sh ${runtimeDir}/supersonic-standalone/bin/service.sh restart
|
||||
#start llm service
|
||||
sh ${runtimeDir}/supersonic-standalone/llm/bin/service.sh restart
|
||||
53
assembly/bin/supersonic-build.bat
Normal file
53
assembly/bin/supersonic-build.bat
Normal file
@@ -0,0 +1,53 @@
|
||||
@echo off
|
||||
setlocal
|
||||
chcp 65001
|
||||
set "sbinDir=%~dp0"
|
||||
set "baseDir=%~dp0.."
|
||||
set "buildDir=%baseDir%\build"
|
||||
set "runtimeDir=%baseDir%\..\runtime"
|
||||
set "pip_path=pip3"
|
||||
|
||||
rem 1. build backend java modules
|
||||
del /q "%buildDir%\*.tar.gz" 2>NUL
|
||||
call mvn -f "%baseDir%\..\pom.xml" clean package -DskipTests
|
||||
|
||||
rem 2. move package to build
|
||||
echo f|xcopy "%baseDir%\..\launchers\standalone\target\*.tar.gz" "%buildDir%\supersonic-standalone.tar.gz"
|
||||
|
||||
rem 3. build frontend webapp
|
||||
cd "%baseDir%\..\webapp"
|
||||
call start-fe-prod.bat
|
||||
copy /y "%baseDir%\..\webapp\supersonic-webapp.tar.gz" "%buildDir%\"
|
||||
|
||||
rem 4. copy webapp to java classpath
|
||||
cd "%buildDir%"
|
||||
tar -zxvf supersonic-webapp.tar.gz
|
||||
move supersonic-webapp webapp
|
||||
move webapp ..\..\launchers\standalone\target\classes
|
||||
|
||||
rem 5. build backend python modules
|
||||
echo "start installing python modules with pip: ${pip_path}"
|
||||
set requirementPath="%baseDir%/../chat/core/src/main/python/requirements.txt"
|
||||
%pip_path% install -r %requirementPath%
|
||||
echo "install python modules success"
|
||||
|
||||
call :BUILD_RUNTIME
|
||||
|
||||
:BUILD_RUNTIME
|
||||
rem 6. reset runtime
|
||||
rd /s /q "%runtimeDir%"
|
||||
mkdir "%runtimeDir%"
|
||||
tar -zxvf "%buildDir%\supersonic-standalone.tar.gz" -C "%runtimeDir%"
|
||||
for /d %%f in ("%runtimeDir%\launchers-standalone-*") do (
|
||||
move "%%f" "%runtimeDir%\supersonic-standalone"
|
||||
)
|
||||
|
||||
rem 7. copy webapp to runtime
|
||||
tar -zxvf "%buildDir%\supersonic-webapp.tar.gz" -C "%buildDir%"
|
||||
if not exist "%runtimeDir%\supersonic-standalone\webapp" mkdir "%runtimeDir%\supersonic-standalone\webapp"
|
||||
xcopy /s /e /h /y "%buildDir%\supersonic-webapp\*" "%runtimeDir%\supersonic-standalone\webapp"
|
||||
if not exist "%runtimeDir%\supersonic-standalone\conf\webapp" mkdir "%runtimeDir%\supersonic-standalone\conf\webapp"
|
||||
xcopy /s /e /h /y "%runtimeDir%\supersonic-standalone\webapp\*" "%runtimeDir%\supersonic-standalone\conf\webapp"
|
||||
rd /s /q "%buildDir%\supersonic-webapp"
|
||||
|
||||
endlocal
|
||||
48
assembly/bin/supersonic-build.sh
Executable file
48
assembly/bin/supersonic-build.sh
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -x
|
||||
sbinDir=$(cd "$(dirname "$0")"; pwd)
|
||||
chmod +x $sbinDir/supersonic-common.sh
|
||||
source $sbinDir/supersonic-common.sh
|
||||
|
||||
cd $baseDir
|
||||
|
||||
#1. build backend java modules
|
||||
rm -fr ${buildDir}/*.tar.gz
|
||||
rm -fr dist
|
||||
|
||||
set +x
|
||||
|
||||
mvn -f $baseDir/../ clean package -DskipTests
|
||||
|
||||
#2. move package to build
|
||||
cp $baseDir/../launchers/semantic/target/*.tar.gz ${buildDir}/supersonic-semantic.tar.gz
|
||||
cp $baseDir/../launchers/chat/target/*.tar.gz ${buildDir}/supersonic-chat.tar.gz
|
||||
cp $baseDir/../launchers/standalone/target/*.tar.gz ${buildDir}/supersonic-standalone.tar.gz
|
||||
|
||||
#3. build frontend webapp
|
||||
chmod +x $baseDir/../webapp/start-fe-prod.sh
|
||||
cd ../webapp
|
||||
sh ./start-fe-prod.sh
|
||||
cp -fr ./supersonic-webapp.tar.gz ${buildDir}/
|
||||
|
||||
#4. copy webapp to java classpath
|
||||
cd $buildDir
|
||||
tar xvf supersonic-webapp.tar.gz
|
||||
mv supersonic-webapp webapp
|
||||
cp -fr webapp ../../launchers/semantic/target/classes
|
||||
cp -fr webapp ../../launchers/chat/target/classes
|
||||
cp -fr webapp ../../launchers/standalone/target/classes
|
||||
rm -fr ${buildDir}/webapp
|
||||
|
||||
#5. build backend python modules
|
||||
echo "start installing python modules with pip: ${pip_path}"
|
||||
requirementPath=$baseDir/../chat/core/src/main/python/requirements.txt
|
||||
${pip_path} install -r ${requirementPath}
|
||||
echo "install python modules success"
|
||||
|
||||
#6. reset runtime
|
||||
rm -fr $runtimeDir/*
|
||||
moveAllToRuntime
|
||||
setEnvToWeb chat
|
||||
setEnvToWeb semantic
|
||||
105
assembly/bin/supersonic-common.sh
Executable file
105
assembly/bin/supersonic-common.sh
Executable file
@@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# environment parameters
|
||||
python_path=${PYTHON_PATH:-"python3"}
|
||||
pip_path=${PIP_PATH:-"pip3"}
|
||||
|
||||
sbinDir=$(cd "$(dirname "$0")"; pwd)
|
||||
baseDir=$(cd "$sbinDir/.." && pwd -P)
|
||||
runtimeDir=$baseDir/../runtime
|
||||
buildDir=$baseDir/build
|
||||
|
||||
readonly CHAT_APP_NAME="supersonic_chat"
|
||||
readonly SEMANTIC_APP_NAME="supersonic_semantic"
|
||||
readonly LLMPARSER_APP_NAME="supersonic_llmparser"
|
||||
readonly STANDALONE_APP_NAME="supersonic_standalone"
|
||||
readonly CHAT_SERVICE="chat"
|
||||
readonly SEMANTIC_SERVICE="semantic"
|
||||
readonly LLMPARSER_SERVICE="llmparser"
|
||||
readonly STANDALONE_SERVICE="standalone"
|
||||
readonly LLMPARSER_HOST="127.0.0.1"
|
||||
readonly LLMPARSER_PORT="9092"
|
||||
|
||||
function setEnvToWeb {
|
||||
model_name=$1
|
||||
json='{"env": "'$model_name'"}'
|
||||
echo $json > ${runtimeDir}/supersonic-${model_name}/webapp/supersonic.config.json
|
||||
echo $json > $baseDir/../launchers/${model_name}/target/classes/webapp/supersonic.config.json
|
||||
}
|
||||
|
||||
function moveToRuntime {
|
||||
model_name=$1
|
||||
tar -zxvf ${buildDir}/supersonic-${model_name}.tar.gz -C ${runtimeDir}
|
||||
mv ${runtimeDir}/launchers-${model_name}-* ${runtimeDir}/supersonic-${model_name}
|
||||
|
||||
mkdir -p ${runtimeDir}/supersonic-${model_name}/webapp
|
||||
cp -fr ${buildDir}/webapp/* ${runtimeDir}/supersonic-${model_name}/webapp
|
||||
}
|
||||
|
||||
function moveAllToRuntime {
|
||||
mkdir -p ${runtimeDir}
|
||||
tar xvf ${buildDir}/supersonic-webapp.tar.gz -C ${buildDir}
|
||||
mv ${buildDir}/supersonic-webapp ${buildDir}/webapp
|
||||
|
||||
moveToRuntime chat
|
||||
moveToRuntime semantic
|
||||
moveToRuntime standalone
|
||||
rm -fr ${buildDir}/webapp
|
||||
}
|
||||
|
||||
# run java service
|
||||
function runJavaService {
|
||||
javaRunDir=${runtimeDir}/supersonic-${model_name}
|
||||
local_app_name=$1
|
||||
libDir=$javaRunDir/lib
|
||||
confDir=$javaRunDir/conf
|
||||
|
||||
CLASSPATH=""
|
||||
CLASSPATH=$CLASSPATH:$confDir
|
||||
|
||||
for jarPath in $libDir/*.jar; do
|
||||
CLASSPATH=$CLASSPATH:$jarPath
|
||||
done
|
||||
|
||||
export CLASSPATH
|
||||
export LANG="zh_CN.UTF-8"
|
||||
|
||||
cd $javaRunDir
|
||||
if [[ "$JAVA_HOME" == "" ]]; then
|
||||
JAVA_HOME=$(ls /usr/jdk64/jdk* -d 2>/dev/null | xargs | awk '{print "'$local_app_name'"}')
|
||||
fi
|
||||
export PATH=$JAVA_HOME/bin:$PATH
|
||||
command="-Dfile.encoding="UTF-8" -Duser.language="Zh" -Duser.region="CN" -Duser.timezone="GMT+08" -Dapp_name=${local_app_name} -Xms1024m -Xmx2048m "$main_class
|
||||
|
||||
mkdir -p $javaRunDir/logs
|
||||
if [[ "$is_test" == "true" ]]; then
|
||||
java -Dspring.profiles.active="dev" $command >/dev/null 2>$javaRunDir/logs/error.log &
|
||||
else
|
||||
java $command $javaRunDir >/dev/null 2>$javaRunDir/logs/error.log &
|
||||
fi
|
||||
}
|
||||
|
||||
# run python service
|
||||
function runPythonService {
|
||||
pythonRunDir=${runtimeDir}/supersonic-${model_name}/llmparser
|
||||
cd $pythonRunDir
|
||||
nohup ${python_path} supersonic_llmparser.py > $pythonRunDir/llmparser.log 2>&1 &
|
||||
# add health check
|
||||
for i in {1..10}
|
||||
do
|
||||
echo "llmparser health check attempt $i..."
|
||||
response=$(curl -s http://${LLMPARSER_HOST}:${LLMPARSER_PORT}/health)
|
||||
echo "llmparser health check response: $response"
|
||||
status_ok="Healthy"
|
||||
if [[ $response == *$status_ok* ]] ; then
|
||||
echo "llmparser Health check passed."
|
||||
break
|
||||
else
|
||||
if [ "$i" -eq 10 ]; then
|
||||
echo "llmparser Health check failed after 10 attempts. Exiting."
|
||||
fi
|
||||
echo "Retrying after 5 seconds..."
|
||||
sleep 5
|
||||
fi
|
||||
done
|
||||
}
|
||||
118
assembly/bin/supersonic-daemon.bat
Normal file
118
assembly/bin/supersonic-daemon.bat
Normal file
@@ -0,0 +1,118 @@
|
||||
@echo off
|
||||
setlocal
|
||||
chcp 65001
|
||||
set "sbinDir=%~dp0"
|
||||
set "baseDir=%~dp0.."
|
||||
set "runtimeDir=%baseDir%\..\runtime"
|
||||
set "buildDir=%baseDir%\build"
|
||||
set "main_class=com.tencent.supersonic.StandaloneLauncher"
|
||||
set "python_path=python"
|
||||
set "pip_path=pip3"
|
||||
set "standalone_service=standalone"
|
||||
set "llmparser_service=llmparser"
|
||||
|
||||
set "javaRunDir=%runtimeDir%\supersonic-standalone"
|
||||
set "pythonRunDir=%runtimeDir%\supersonic-standalone\llmparser"
|
||||
|
||||
set "command=%~1"
|
||||
set "service=%~2"
|
||||
|
||||
if "%service%"=="" (
|
||||
set "service=%standalone_service%"
|
||||
)
|
||||
|
||||
call :BUILD_RUNTIME
|
||||
|
||||
if "%command%"=="restart" (
|
||||
call :STOP
|
||||
call :START
|
||||
goto :EOF
|
||||
) else if "%command%"=="start" (
|
||||
call :START
|
||||
goto :EOF
|
||||
) else if "%command%"=="stop" (
|
||||
call :STOP
|
||||
goto :EOF
|
||||
) else if "%command%"=="reload" (
|
||||
call :RELOAD_EXAMPLE
|
||||
goto :EOF
|
||||
) else (
|
||||
echo "Use command {start|stop|restart} to run."
|
||||
goto :EOF
|
||||
)
|
||||
|
||||
:START
|
||||
if "%service%"=="%llmparser_service%" (
|
||||
call :START_PYTHON
|
||||
goto :EOF
|
||||
)
|
||||
call :START_PYTHON
|
||||
call :START_JAVA
|
||||
goto :EOF
|
||||
|
||||
:STOP
|
||||
if "%service%"=="%llmparser_service%" (
|
||||
call :STOP_PYTHON
|
||||
goto :EOF
|
||||
)
|
||||
call :STOP_PYTHON
|
||||
call :STOP_JAVA
|
||||
goto :EOF
|
||||
|
||||
:START_PYTHON
|
||||
echo 'python service starting, see logs in llmparser/llmparser.log'
|
||||
cd "%pythonRunDir%"
|
||||
start /B %python_path% supersonic_llmparser.py > %pythonRunDir%\llmparser.log 2>&1
|
||||
timeout /t 10 >nul
|
||||
echo 'python service started'
|
||||
goto :EOF
|
||||
|
||||
:START_JAVA
|
||||
echo 'java service starting, see logs in logs/'
|
||||
cd "%javaRunDir%"
|
||||
if not exist "%runtimeDir%\supersonic-standalone\logs" mkdir "%runtimeDir%\supersonic-standalone\logs"
|
||||
set "libDir=%runtimeDir%\supersonic-%service%\lib"
|
||||
set "confDir=%runtimeDir%\supersonic-%service%\conf"
|
||||
set "webDir=%runtimeDir%\supersonic-%service%\webapp"
|
||||
set "classpath=%confDir%;%webDir%;%libDir%\*"
|
||||
set "java-command=-Dfile.encoding=UTF-8 -Duser.language=Zh -Duser.region=CN -Duser.timezone=GMT+08 -Xms1024m -Xmx2048m -cp %CLASSPATH% %MAIN_CLASS%"
|
||||
start /B java %java-command% >nul 2>&1
|
||||
timeout /t 10 >nul
|
||||
echo 'java service started'
|
||||
goto :EOF
|
||||
|
||||
:STOP_PYTHON
|
||||
for /f "tokens=2" %%i in ('tasklist ^| findstr /i "python"') do (
|
||||
taskkill /PID %%i /F
|
||||
echo "python service (PID = %%i) is killed."
|
||||
)
|
||||
goto :EOF
|
||||
|
||||
:STOP_JAVA
|
||||
for /f "tokens=2" %%i in ('tasklist ^| findstr /i "java"') do (
|
||||
taskkill /PID %%i /F
|
||||
echo "java service (PID = %%i) is killed."
|
||||
)
|
||||
goto :EOF
|
||||
|
||||
:RELOAD_EXAMPLE
|
||||
cd "%runtimeDir%\supersonic-standalone\llmparser\sql"
|
||||
start %python_path% examples_reload_run.py
|
||||
goto :EOF
|
||||
|
||||
:BUILD_RUNTIME
|
||||
rem 6. reset runtime
|
||||
if exist "%runtimeDir%" goto :EOF
|
||||
mkdir "%runtimeDir%"
|
||||
tar -zxvf "%buildDir%\supersonic-standalone.tar.gz" -C "%runtimeDir%"
|
||||
for /d %%f in ("%runtimeDir%\launchers-standalone-*") do (
|
||||
move "%%f" "%runtimeDir%\supersonic-standalone"
|
||||
)
|
||||
|
||||
rem 7. copy webapp to runtime
|
||||
tar -zxvf "%buildDir%\supersonic-webapp.tar.gz" -C "%buildDir%"
|
||||
if not exist "%runtimeDir%\supersonic-standalone\webapp" mkdir "%runtimeDir%\supersonic-standalone\webapp"
|
||||
xcopy /s /e /h /y "%buildDir%\supersonic-webapp\*" "%runtimeDir%\supersonic-standalone\webapp"
|
||||
if not exist "%runtimeDir%\supersonic-standalone\conf\webapp" mkdir "%runtimeDir%\supersonic-standalone\conf\webapp"
|
||||
xcopy /s /e /h /y "%runtimeDir%\supersonic-standalone\webapp\*" "%runtimeDir%\supersonic-standalone\conf\webapp"
|
||||
rd /s /q "%buildDir%\supersonic-webapp"
|
||||
147
assembly/bin/supersonic-daemon.sh
Executable file
147
assembly/bin/supersonic-daemon.sh
Executable file
@@ -0,0 +1,147 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -x
|
||||
sbinDir=$(cd "$(dirname "$0")"; pwd)
|
||||
chmod +x $sbinDir/supersonic-common.sh
|
||||
source $sbinDir/supersonic-common.sh
|
||||
|
||||
# 1.init environment parameters
|
||||
if [ ! -d "$runtimeDir" ]; then
|
||||
echo "the runtime dir does not exist move all to runtime"
|
||||
moveAllToRuntime
|
||||
fi
|
||||
set +x
|
||||
|
||||
command=$1
|
||||
service=$2
|
||||
if [ -z "$service" ]; then
|
||||
service=${STANDALONE_SERVICE}
|
||||
fi
|
||||
|
||||
app_name=$STANDALONE_APP_NAME
|
||||
main_class="com.tencent.supersonic.StandaloneLauncher"
|
||||
model_name=$service
|
||||
|
||||
if [ "$service" == "llmparser" ]; then
|
||||
model_name=${STANDALONE_SERVICE}
|
||||
fi
|
||||
|
||||
cd $baseDir
|
||||
|
||||
# 2.set main class
|
||||
function setMainClass {
|
||||
if [ "$service" == $CHAT_SERVICE ]; then
|
||||
main_class="com.tencent.supersonic.ChatLauncher"
|
||||
elif [ "$service" == $SEMANTIC_SERVICE ]; then
|
||||
main_class="com.tencent.supersonic.SemanticLauncher"
|
||||
fi
|
||||
}
|
||||
setMainClass
|
||||
# 3.set app name
|
||||
function setAppName {
|
||||
if [ "$service" == $CHAT_SERVICE ]; then
|
||||
app_name=$CHAT_APP_NAME
|
||||
elif [ "$service" == $SEMANTIC_SERVICE ]; then
|
||||
app_name=$SEMANTIC_APP_NAME
|
||||
elif [ "$service" == $LLMPARSER_SERVICE ]; then
|
||||
app_name=$LLMPARSER_APP_NAME
|
||||
fi
|
||||
}
|
||||
setAppName
|
||||
|
||||
function reloadExamples {
|
||||
pythonRunDir=${runtimeDir}/supersonic-${model_name}/llmparser
|
||||
cd $pythonRunDir/sql
|
||||
${python_path} examples_reload_run.py
|
||||
}
|
||||
|
||||
|
||||
function start()
|
||||
{
|
||||
local_app_name=$1
|
||||
pid=$(ps aux |grep ${local_app_name} | grep -v grep | awk '{print $2}')
|
||||
if [[ "$pid" == "" ]]; then
|
||||
if [[ ${local_app_name} == $LLMPARSER_APP_NAME ]]; then
|
||||
runPythonService ${local_app_name}
|
||||
else
|
||||
runJavaService ${local_app_name}
|
||||
fi
|
||||
else
|
||||
echo "Process (PID = $pid) is running."
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
function stop()
|
||||
{
|
||||
pid=$(ps aux | grep $1 | grep -v grep | awk '{print $2}')
|
||||
if [[ "$pid" == "" ]]; then
|
||||
echo "Process $1 is not running !"
|
||||
return 1
|
||||
else
|
||||
kill -9 $pid
|
||||
echo "Process (PID = $pid) is killed !"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
function reload()
|
||||
{
|
||||
if [[ $1 == $LLMPARSER_APP_NAME ]]; then
|
||||
reloadExamples
|
||||
fi
|
||||
}
|
||||
|
||||
# 4. execute command operation
|
||||
case "$command" in
|
||||
start)
|
||||
if [ "$service" == $STANDALONE_SERVICE ]; then
|
||||
echo "Starting $LLMPARSER_APP_NAME"
|
||||
start $LLMPARSER_APP_NAME
|
||||
echo "Starting $app_name"
|
||||
start $app_name
|
||||
else
|
||||
echo "Starting $app_name"
|
||||
start $app_name
|
||||
fi
|
||||
echo "Start success"
|
||||
;;
|
||||
stop)
|
||||
if [ "$service" == $STANDALONE_SERVICE ]; then
|
||||
echo "Stopping $LLMPARSER_APP_NAME"
|
||||
stop $LLMPARSER_APP_NAME
|
||||
echo "Stopping $app_name"
|
||||
stop $app_name
|
||||
else
|
||||
echo "Stopping $app_name"
|
||||
stop ${app_name}
|
||||
fi
|
||||
echo "Stop success"
|
||||
;;
|
||||
reload)
|
||||
echo "Reloading ${app_name}"
|
||||
reload ${app_name}
|
||||
echo "Reload success"
|
||||
;;
|
||||
restart)
|
||||
if [ "$service" == $STANDALONE_SERVICE ]; then
|
||||
echo "Stopping ${app_name}"
|
||||
stop ${app_name}
|
||||
echo "Stopping ${LLMPARSER_APP_NAME}"
|
||||
stop $LLMPARSER_APP_NAME
|
||||
echo "Starting ${LLMPARSER_APP_NAME}"
|
||||
start $LLMPARSER_APP_NAME
|
||||
echo "Starting ${app_name}"
|
||||
start ${app_name}
|
||||
else
|
||||
echo "Stopping ${app_name}"
|
||||
stop ${app_name}
|
||||
echo "Starting ${app_name}"
|
||||
start ${app_name}
|
||||
fi
|
||||
echo "Restart success"
|
||||
;;
|
||||
*)
|
||||
echo "Use command {start|stop|restart} to run."
|
||||
exit 1
|
||||
esac
|
||||
@@ -6,14 +6,6 @@
|
||||
<format>tar.gz</format>
|
||||
</formats>
|
||||
<fileSets>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.basedir}/src/main/bin</directory>
|
||||
<outputDirectory>bin</outputDirectory>
|
||||
<fileMode>0777</fileMode>
|
||||
<directoryMode>0755</directoryMode>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.basedir}/src/main/resources</directory>
|
||||
<outputDirectory>conf</outputDirectory>
|
||||
@@ -30,7 +22,7 @@
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>${project.basedir}/../../chat/core/src/main/python</directory>
|
||||
<outputDirectory>llm</outputDirectory>
|
||||
<outputDirectory>llmparser</outputDirectory>
|
||||
<fileMode>0777</fileMode>
|
||||
<directoryMode>0755</directoryMode>
|
||||
</fileSet>
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.tencent.supersonic.auth.api.authentication.adaptor;
|
||||
import com.tencent.supersonic.auth.api.authentication.pojo.Organization;
|
||||
import com.tencent.supersonic.auth.api.authentication.pojo.User;
|
||||
import com.tencent.supersonic.auth.api.authentication.request.UserReq;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
@@ -9,10 +9,12 @@ import org.springframework.context.annotation.Configuration;
|
||||
@Configuration
|
||||
public class AuthenticationConfig {
|
||||
|
||||
|
||||
@Value("${authentication.exclude.path:XXX}")
|
||||
private String excludePath;
|
||||
|
||||
@Value("${authentication.include.path:/api}")
|
||||
private String includePath;
|
||||
|
||||
@Value("${authentication.enable:false}")
|
||||
private boolean enabled;
|
||||
|
||||
@@ -22,5 +24,4 @@ public class AuthenticationConfig {
|
||||
@Value("${authentication.token.http.header.key:Authorization}")
|
||||
private String tokenHttpHeaderKey;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ public class UserConstants {
|
||||
|
||||
public static final String TOKEN_USER_EMAIL = "token_user_email";
|
||||
|
||||
public static final String TOKEN_IS_ADMIN = "token_is_admin";
|
||||
|
||||
public static final String TOKEN_ALGORITHM = "HS512";
|
||||
|
||||
public static final String TOKEN_CREATE_TIME = "token_create_time";
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package com.tencent.supersonic.auth.api.authentication.pojo;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class Organization {
|
||||
|
||||
|
||||
@@ -18,17 +18,22 @@ public class User {
|
||||
|
||||
private String email;
|
||||
|
||||
public static User get(Long id, String name, String displayName, String email) {
|
||||
return new User(id, name, displayName, email);
|
||||
private Integer isAdmin;
|
||||
|
||||
public static User get(Long id, String name, String displayName, String email, Integer isAdmin) {
|
||||
return new User(id, name, displayName, email, isAdmin);
|
||||
}
|
||||
|
||||
public static User getFakeUser() {
|
||||
return new User(1L, "admin", "admin", "admin@email");
|
||||
return new User(1L, "admin", "admin", "admin@email", 1);
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return StringUtils.isBlank(displayName) ? name : displayName;
|
||||
}
|
||||
|
||||
public boolean isSuperAdmin() {
|
||||
return isAdmin != null && isAdmin == 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,13 +9,14 @@ public class UserWithPassword extends User {
|
||||
|
||||
private String password;
|
||||
|
||||
public UserWithPassword(Long id, String name, String displayName, String email, String password) {
|
||||
super(id, name, displayName, email);
|
||||
public UserWithPassword(Long id, String name, String displayName, String email, String password, Integer isAdmin) {
|
||||
super(id, name, displayName, email, isAdmin);
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public static UserWithPassword get(Long id, String name, String displayName, String email, String password) {
|
||||
return new UserWithPassword(id, name, displayName, email, password);
|
||||
public static UserWithPassword get(Long id, String name, String displayName,
|
||||
String email, String password, Integer isAdmin) {
|
||||
return new UserWithPassword(id, name, displayName, email, password, isAdmin);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.tencent.supersonic.auth.api.authentication.service;
|
||||
import com.tencent.supersonic.auth.api.authentication.pojo.Organization;
|
||||
import com.tencent.supersonic.auth.api.authentication.pojo.User;
|
||||
import com.tencent.supersonic.auth.api.authentication.request.UserReq;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.tencent.supersonic.auth.api.authentication.service;
|
||||
|
||||
import com.tencent.supersonic.auth.api.authentication.pojo.User;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.tencent.supersonic.auth.api.authorization.request;
|
||||
import com.tencent.supersonic.auth.api.authorization.pojo.AuthRes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.tencent.supersonic.auth.api.authorization.pojo.AuthResGrp;
|
||||
import com.tencent.supersonic.auth.api.authorization.pojo.DimensionFilter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
|
||||
@@ -6,12 +6,11 @@ import com.tencent.supersonic.auth.api.authorization.request.QueryAuthResReq;
|
||||
import com.tencent.supersonic.auth.api.authorization.response.AuthorizedResourceResp;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public interface AuthService {
|
||||
|
||||
List<AuthGroup> queryAuthGroups(String domainId, Integer groupId);
|
||||
|
||||
void updateAuthGroup(AuthGroup group);
|
||||
void addOrUpdateAuthGroup(AuthGroup group);
|
||||
|
||||
void removeAuthGroup(AuthGroup group);
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@ import com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDO;
|
||||
import com.tencent.supersonic.auth.authentication.persistence.repository.UserRepository;
|
||||
import com.tencent.supersonic.auth.authentication.utils.UserTokenUtils;
|
||||
import com.tencent.supersonic.common.util.ContextUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
||||
public class DefaultUserAdaptor implements UserAdaptor {
|
||||
|
||||
@@ -71,7 +71,7 @@ public class DefaultUserAdaptor implements UserAdaptor {
|
||||
}
|
||||
if (userDO.getPassword().equals(userReq.getPassword())) {
|
||||
UserWithPassword user = UserWithPassword.get(userDO.getId(), userDO.getName(), userDO.getDisplayName(),
|
||||
userDO.getEmail(), userDO.getPassword());
|
||||
userDO.getEmail(), userDO.getPassword(), userDO.getIsAdmin());
|
||||
return userTokenUtils.generateToken(user);
|
||||
}
|
||||
throw new RuntimeException("password not correct, please try again");
|
||||
|
||||
@@ -42,6 +42,17 @@ public abstract class AuthenticationInterceptor implements HandlerInterceptor {
|
||||
return excludePaths.stream().anyMatch(uri::startsWith);
|
||||
}
|
||||
|
||||
protected boolean isIncludedUri(String uri) {
|
||||
String includePathStr = authenticationConfig.getIncludePath();
|
||||
if (Strings.isEmpty(includePathStr)) {
|
||||
return false;
|
||||
}
|
||||
List<String> includePaths = Arrays.asList(includePathStr.split(","));
|
||||
if (CollectionUtils.isEmpty(includePaths)) {
|
||||
return false;
|
||||
}
|
||||
return includePaths.stream().anyMatch(uri::startsWith);
|
||||
}
|
||||
|
||||
protected boolean isInternalRequest(HttpServletRequest request) {
|
||||
String internal = request.getHeader(UserConstants.INTERNAL);
|
||||
|
||||
@@ -46,6 +46,10 @@ public class DefaultAuthenticationInterceptor extends AuthenticationInterceptor
|
||||
}
|
||||
|
||||
String uri = request.getServletPath();
|
||||
if (!isIncludedUri(uri)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isExcludedUri(uri)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package com.tencent.supersonic.auth.authentication.interceptor;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Configuration
|
||||
public class InterceptorFactory implements WebMvcConfigurer {
|
||||
|
||||
|
||||
@@ -1,99 +1,129 @@
|
||||
package com.tencent.supersonic.auth.authentication.persistence.dataobject;
|
||||
|
||||
public class UserDO {
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
private String password;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
private String displayName;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* @return id
|
||||
*
|
||||
*/
|
||||
private Integer isAdmin;
|
||||
|
||||
/**
|
||||
*
|
||||
* @return id
|
||||
*/
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return name
|
||||
*
|
||||
* @return name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
*
|
||||
* @param name
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name == null ? null : name.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return password
|
||||
*
|
||||
* @return password
|
||||
*/
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param password
|
||||
*
|
||||
* @param password
|
||||
*/
|
||||
public void setPassword(String password) {
|
||||
this.password = password == null ? null : password.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return display_name
|
||||
*
|
||||
* @return display_name
|
||||
*/
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param displayName
|
||||
*
|
||||
* @param displayName
|
||||
*/
|
||||
public void setDisplayName(String displayName) {
|
||||
this.displayName = displayName == null ? null : displayName.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return email
|
||||
*
|
||||
* @return email
|
||||
*/
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param email
|
||||
*
|
||||
* @param email
|
||||
*/
|
||||
public void setEmail(String email) {
|
||||
this.email = email == null ? null : email.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return is_admin
|
||||
*/
|
||||
public Integer getIsAdmin() {
|
||||
return isAdmin;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param isAdmin
|
||||
*/
|
||||
public void setIsAdmin(Integer isAdmin) {
|
||||
this.isAdmin = isAdmin;
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class UserDOExample {
|
||||
|
||||
/**
|
||||
* s2_user
|
||||
*/
|
||||
@@ -31,6 +30,7 @@ public class UserDOExample {
|
||||
protected Integer limitEnd;
|
||||
|
||||
/**
|
||||
*
|
||||
* @mbg.generated
|
||||
*/
|
||||
public UserDOExample() {
|
||||
@@ -38,13 +38,7 @@ public class UserDOExample {
|
||||
}
|
||||
|
||||
/**
|
||||
* @mbg.generated
|
||||
*/
|
||||
public String getOrderByClause() {
|
||||
return orderByClause;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @mbg.generated
|
||||
*/
|
||||
public void setOrderByClause(String orderByClause) {
|
||||
@@ -52,13 +46,15 @@ public class UserDOExample {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @mbg.generated
|
||||
*/
|
||||
public boolean isDistinct() {
|
||||
return distinct;
|
||||
public String getOrderByClause() {
|
||||
return orderByClause;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @mbg.generated
|
||||
*/
|
||||
public void setDistinct(boolean distinct) {
|
||||
@@ -66,6 +62,15 @@ public class UserDOExample {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @mbg.generated
|
||||
*/
|
||||
public boolean isDistinct() {
|
||||
return distinct;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @mbg.generated
|
||||
*/
|
||||
public List<Criteria> getOredCriteria() {
|
||||
@@ -73,6 +78,7 @@ public class UserDOExample {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @mbg.generated
|
||||
*/
|
||||
public void or(Criteria criteria) {
|
||||
@@ -80,6 +86,7 @@ public class UserDOExample {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @mbg.generated
|
||||
*/
|
||||
public Criteria or() {
|
||||
@@ -89,6 +96,7 @@ public class UserDOExample {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @mbg.generated
|
||||
*/
|
||||
public Criteria createCriteria() {
|
||||
@@ -100,6 +108,7 @@ public class UserDOExample {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @mbg.generated
|
||||
*/
|
||||
protected Criteria createCriteriaInternal() {
|
||||
@@ -108,6 +117,7 @@ public class UserDOExample {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @mbg.generated
|
||||
*/
|
||||
public void clear() {
|
||||
@@ -117,6 +127,15 @@ public class UserDOExample {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @mbg.generated
|
||||
*/
|
||||
public void setLimitStart(Integer limitStart) {
|
||||
this.limitStart=limitStart;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @mbg.generated
|
||||
*/
|
||||
public Integer getLimitStart() {
|
||||
@@ -124,31 +143,25 @@ public class UserDOExample {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @mbg.generated
|
||||
*/
|
||||
public void setLimitStart(Integer limitStart) {
|
||||
this.limitStart = limitStart;
|
||||
public void setLimitEnd(Integer limitEnd) {
|
||||
this.limitEnd=limitEnd;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @mbg.generated
|
||||
*/
|
||||
public Integer getLimitEnd() {
|
||||
return limitEnd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @mbg.generated
|
||||
*/
|
||||
public void setLimitEnd(Integer limitEnd) {
|
||||
this.limitEnd = limitEnd;
|
||||
}
|
||||
|
||||
/**
|
||||
* s2_user null
|
||||
*/
|
||||
protected abstract static class GeneratedCriteria {
|
||||
|
||||
protected List<Criterion> criteria;
|
||||
|
||||
protected GeneratedCriteria() {
|
||||
@@ -528,6 +541,66 @@ public class UserDOExample {
|
||||
addCriterion("email not between", value1, value2, "email");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIsAdminIsNull() {
|
||||
addCriterion("is_admin is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIsAdminIsNotNull() {
|
||||
addCriterion("is_admin is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIsAdminEqualTo(Integer value) {
|
||||
addCriterion("is_admin =", value, "isAdmin");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIsAdminNotEqualTo(Integer value) {
|
||||
addCriterion("is_admin <>", value, "isAdmin");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIsAdminGreaterThan(Integer value) {
|
||||
addCriterion("is_admin >", value, "isAdmin");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIsAdminGreaterThanOrEqualTo(Integer value) {
|
||||
addCriterion("is_admin >=", value, "isAdmin");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIsAdminLessThan(Integer value) {
|
||||
addCriterion("is_admin <", value, "isAdmin");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIsAdminLessThanOrEqualTo(Integer value) {
|
||||
addCriterion("is_admin <=", value, "isAdmin");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIsAdminIn(List<Integer> values) {
|
||||
addCriterion("is_admin in", values, "isAdmin");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIsAdminNotIn(List<Integer> values) {
|
||||
addCriterion("is_admin not in", values, "isAdmin");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIsAdminBetween(Integer value1, Integer value2) {
|
||||
addCriterion("is_admin between", value1, value2, "isAdmin");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIsAdminNotBetween(Integer value1, Integer value2) {
|
||||
addCriterion("is_admin not between", value1, value2, "isAdmin");
|
||||
return (Criteria) this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -544,7 +617,6 @@ public class UserDOExample {
|
||||
* s2_user null
|
||||
*/
|
||||
public static class Criterion {
|
||||
|
||||
private String condition;
|
||||
|
||||
private Object value;
|
||||
@@ -561,6 +633,38 @@ public class UserDOExample {
|
||||
|
||||
private String typeHandler;
|
||||
|
||||
public String getCondition() {
|
||||
return condition;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public Object getSecondValue() {
|
||||
return secondValue;
|
||||
}
|
||||
|
||||
public boolean isNoValue() {
|
||||
return noValue;
|
||||
}
|
||||
|
||||
public boolean isSingleValue() {
|
||||
return singleValue;
|
||||
}
|
||||
|
||||
public boolean isBetweenValue() {
|
||||
return betweenValue;
|
||||
}
|
||||
|
||||
public boolean isListValue() {
|
||||
return listValue;
|
||||
}
|
||||
|
||||
public String getTypeHandler() {
|
||||
return typeHandler;
|
||||
}
|
||||
|
||||
protected Criterion(String condition) {
|
||||
super();
|
||||
this.condition = condition;
|
||||
@@ -596,37 +700,5 @@ public class UserDOExample {
|
||||
protected Criterion(String condition, Object value, Object secondValue) {
|
||||
this(condition, value, secondValue, null);
|
||||
}
|
||||
|
||||
public String getCondition() {
|
||||
return condition;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public Object getSecondValue() {
|
||||
return secondValue;
|
||||
}
|
||||
|
||||
public boolean isNoValue() {
|
||||
return noValue;
|
||||
}
|
||||
|
||||
public boolean isSingleValue() {
|
||||
return singleValue;
|
||||
}
|
||||
|
||||
public boolean isBetweenValue() {
|
||||
return betweenValue;
|
||||
}
|
||||
|
||||
public boolean isListValue() {
|
||||
return listValue;
|
||||
}
|
||||
|
||||
public String getTypeHandler() {
|
||||
return typeHandler;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,8 @@ package com.tencent.supersonic.auth.authentication.persistence.repository.impl;
|
||||
|
||||
import com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDO;
|
||||
import com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDOExample;
|
||||
import com.tencent.supersonic.auth.authentication.persistence.mapper.UserDOMapper;
|
||||
import com.tencent.supersonic.auth.authentication.persistence.repository.UserRepository;
|
||||
import com.tencent.supersonic.auth.authentication.persistence.mapper.UserDOMapper;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.tencent.supersonic.auth.api.authentication.service.UserService;
|
||||
import com.tencent.supersonic.auth.authentication.utils.ComponentFactory;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.tencent.supersonic.auth.authentication.utils;
|
||||
|
||||
import com.tencent.supersonic.auth.api.authentication.adaptor.UserAdaptor;
|
||||
import java.util.Objects;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ComponentFactory {
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.tencent.supersonic.auth.authentication.utils;
|
||||
|
||||
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_ALGORITHM;
|
||||
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_CREATE_TIME;
|
||||
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_IS_ADMIN;
|
||||
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_PREFIX;
|
||||
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_TIME_OUT;
|
||||
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_USER_DISPLAY_NAME;
|
||||
@@ -42,6 +43,7 @@ public class UserTokenUtils {
|
||||
claims.put(TOKEN_USER_PASSWORD, StringUtils.isEmpty(user.getPassword()) ? "" : user.getPassword());
|
||||
claims.put(TOKEN_USER_DISPLAY_NAME, user.getDisplayName());
|
||||
claims.put(TOKEN_CREATE_TIME, System.currentTimeMillis());
|
||||
claims.put(TOKEN_IS_ADMIN, user.getIsAdmin());
|
||||
return generate(claims);
|
||||
}
|
||||
|
||||
@@ -52,6 +54,7 @@ public class UserTokenUtils {
|
||||
claims.put(TOKEN_USER_PASSWORD, "admin");
|
||||
claims.put(TOKEN_USER_DISPLAY_NAME, "admin");
|
||||
claims.put(TOKEN_CREATE_TIME, System.currentTimeMillis());
|
||||
claims.put(TOKEN_IS_ADMIN, 1);
|
||||
return generate(claims);
|
||||
}
|
||||
|
||||
@@ -63,7 +66,9 @@ public class UserTokenUtils {
|
||||
String userName = String.valueOf(claims.get(TOKEN_USER_NAME));
|
||||
String email = String.valueOf(claims.get(TOKEN_USER_EMAIL));
|
||||
String displayName = String.valueOf(claims.get(TOKEN_USER_DISPLAY_NAME));
|
||||
return User.get(userId, userName, displayName, email);
|
||||
Integer isAdmin = claims.get(TOKEN_IS_ADMIN) == null
|
||||
? 0 : Integer.parseInt(claims.get(TOKEN_IS_ADMIN).toString());
|
||||
return User.get(userId, userName, displayName, email, isAdmin);
|
||||
}
|
||||
|
||||
public UserWithPassword getUserWithPassword(HttpServletRequest request) {
|
||||
@@ -79,7 +84,9 @@ public class UserTokenUtils {
|
||||
String email = String.valueOf(claims.get(TOKEN_USER_EMAIL));
|
||||
String displayName = String.valueOf(claims.get(TOKEN_USER_DISPLAY_NAME));
|
||||
String password = String.valueOf(claims.get(TOKEN_USER_PASSWORD));
|
||||
return UserWithPassword.get(userId, userName, displayName, email, password);
|
||||
Integer isAdmin = claims.get(TOKEN_IS_ADMIN) == null
|
||||
? 0 : Integer.parseInt(claims.get(TOKEN_IS_ADMIN).toString());
|
||||
return UserWithPassword.get(userId, userName, displayName, email, password, isAdmin);
|
||||
}
|
||||
|
||||
private Claims getClaims(String token) {
|
||||
|
||||
@@ -1,159 +1,118 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.tencent.supersonic.auth.authentication.persistence.mapper.UserDOMapper">
|
||||
<resultMap id="BaseResultMap"
|
||||
type="com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDO">
|
||||
<id column="id" jdbcType="BIGINT" property="id"/>
|
||||
<result column="name" jdbcType="VARCHAR" property="name"/>
|
||||
<result column="password" jdbcType="VARCHAR" property="password"/>
|
||||
<result column="display_name" jdbcType="VARCHAR" property="displayName"/>
|
||||
<result column="email" jdbcType="VARCHAR" property="email"/>
|
||||
</resultMap>
|
||||
<sql id="Example_Where_Clause">
|
||||
<where>
|
||||
<foreach collection="oredCriteria" item="criteria" separator="or">
|
||||
<if test="criteria.valid">
|
||||
<trim prefix="(" prefixOverrides="and" suffix=")">
|
||||
<foreach collection="criteria.criteria" item="criterion">
|
||||
<choose>
|
||||
<when test="criterion.noValue">
|
||||
and ${criterion.condition}
|
||||
</when>
|
||||
<when test="criterion.singleValue">
|
||||
and ${criterion.condition} #{criterion.value}
|
||||
</when>
|
||||
<when test="criterion.betweenValue">
|
||||
and ${criterion.condition} #{criterion.value} and
|
||||
#{criterion.secondValue}
|
||||
</when>
|
||||
<when test="criterion.listValue">
|
||||
and ${criterion.condition}
|
||||
<foreach close=")" collection="criterion.value" item="listItem"
|
||||
open="(" separator=",">
|
||||
#{listItem}
|
||||
</foreach>
|
||||
</when>
|
||||
</choose>
|
||||
</foreach>
|
||||
</trim>
|
||||
</if>
|
||||
<resultMap id="BaseResultMap" type="com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDO">
|
||||
<result column="id" jdbcType="BIGINT" property="id" />
|
||||
<result column="name" jdbcType="VARCHAR" property="name" />
|
||||
<result column="password" jdbcType="VARCHAR" property="password" />
|
||||
<result column="display_name" jdbcType="VARCHAR" property="displayName" />
|
||||
<result column="email" jdbcType="VARCHAR" property="email" />
|
||||
<result column="is_admin" jdbcType="INTEGER" property="isAdmin" />
|
||||
</resultMap>
|
||||
<sql id="Example_Where_Clause">
|
||||
<where>
|
||||
<foreach collection="oredCriteria" item="criteria" separator="or">
|
||||
<if test="criteria.valid">
|
||||
<trim prefix="(" prefixOverrides="and" suffix=")">
|
||||
<foreach collection="criteria.criteria" item="criterion">
|
||||
<choose>
|
||||
<when test="criterion.noValue">
|
||||
and ${criterion.condition}
|
||||
</when>
|
||||
<when test="criterion.singleValue">
|
||||
and ${criterion.condition} #{criterion.value}
|
||||
</when>
|
||||
<when test="criterion.betweenValue">
|
||||
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
|
||||
</when>
|
||||
<when test="criterion.listValue">
|
||||
and ${criterion.condition}
|
||||
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
|
||||
#{listItem}
|
||||
</foreach>
|
||||
</when>
|
||||
</choose>
|
||||
</foreach>
|
||||
</where>
|
||||
</sql>
|
||||
<sql id="Base_Column_List">
|
||||
id
|
||||
, name, password, display_name, email
|
||||
</sql>
|
||||
<select id="selectByExample"
|
||||
parameterType="com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDOExample"
|
||||
resultMap="BaseResultMap">
|
||||
select
|
||||
<if test="distinct">
|
||||
distinct
|
||||
</trim>
|
||||
</if>
|
||||
<include refid="Base_Column_List"/>
|
||||
from s2_user
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause"/>
|
||||
</if>
|
||||
<if test="orderByClause != null">
|
||||
order by ${orderByClause}
|
||||
</if>
|
||||
<if test="limitStart != null and limitStart>=0">
|
||||
limit #{limitStart} , #{limitEnd}
|
||||
</if>
|
||||
</select>
|
||||
<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
|
||||
select
|
||||
<include refid="Base_Column_List"/>
|
||||
from s2_user
|
||||
where id = #{id,jdbcType=BIGINT}
|
||||
</select>
|
||||
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
|
||||
delete
|
||||
from s2_user
|
||||
where id = #{id,jdbcType=BIGINT}
|
||||
</delete>
|
||||
<insert id="insert"
|
||||
parameterType="com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDO">
|
||||
insert into s2_user (id, name, password,
|
||||
display_name, email)
|
||||
values (#{id,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR},
|
||||
#{displayName,jdbcType=VARCHAR}, #{email,jdbcType=VARCHAR})
|
||||
</insert>
|
||||
<insert id="insertSelective"
|
||||
parameterType="com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDO">
|
||||
insert into s2_user
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">
|
||||
id,
|
||||
</if>
|
||||
<if test="name != null">
|
||||
name,
|
||||
</if>
|
||||
<if test="password != null">
|
||||
password,
|
||||
</if>
|
||||
<if test="displayName != null">
|
||||
display_name,
|
||||
</if>
|
||||
<if test="email != null">
|
||||
email,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">
|
||||
#{id,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="name != null">
|
||||
#{name,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="password != null">
|
||||
#{password,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="displayName != null">
|
||||
#{displayName,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="email != null">
|
||||
#{email,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
<select id="countByExample"
|
||||
parameterType="com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDOExample"
|
||||
resultType="java.lang.Long">
|
||||
select count(*) from s2_user
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause"/>
|
||||
</if>
|
||||
</select>
|
||||
<update id="updateByPrimaryKeySelective"
|
||||
parameterType="com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDO">
|
||||
update s2_user
|
||||
<set>
|
||||
<if test="name != null">
|
||||
name = #{name,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="password != null">
|
||||
password = #{password,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="displayName != null">
|
||||
display_name = #{displayName,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="email != null">
|
||||
email = #{email,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
where id = #{id,jdbcType=BIGINT}
|
||||
</update>
|
||||
<update id="updateByPrimaryKey"
|
||||
parameterType="com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDO">
|
||||
update s2_user
|
||||
set name = #{name,jdbcType=VARCHAR},
|
||||
password = #{password,jdbcType=VARCHAR},
|
||||
display_name = #{displayName,jdbcType=VARCHAR},
|
||||
email = #{email,jdbcType=VARCHAR}
|
||||
where id = #{id,jdbcType=BIGINT}
|
||||
</update>
|
||||
</foreach>
|
||||
</where>
|
||||
</sql>
|
||||
<sql id="Base_Column_List">
|
||||
id, name, password, display_name, email, is_admin
|
||||
</sql>
|
||||
<select id="selectByExample" parameterType="com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDOExample" resultMap="BaseResultMap">
|
||||
select
|
||||
<if test="distinct">
|
||||
distinct
|
||||
</if>
|
||||
<include refid="Base_Column_List" />
|
||||
from s2_user
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
<if test="orderByClause != null">
|
||||
order by ${orderByClause}
|
||||
</if>
|
||||
<if test="limitStart != null and limitStart>=0">
|
||||
limit #{limitStart} , #{limitEnd}
|
||||
</if>
|
||||
</select>
|
||||
<insert id="insert" parameterType="com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDO">
|
||||
insert into s2_user (id, name, password,
|
||||
display_name, email, is_admin
|
||||
)
|
||||
values (#{id,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR},
|
||||
#{displayName,jdbcType=VARCHAR}, #{email,jdbcType=VARCHAR}, #{isAdmin,jdbcType=INTEGER}
|
||||
)
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDO">
|
||||
insert into s2_user
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">
|
||||
id,
|
||||
</if>
|
||||
<if test="name != null">
|
||||
name,
|
||||
</if>
|
||||
<if test="password != null">
|
||||
password,
|
||||
</if>
|
||||
<if test="displayName != null">
|
||||
display_name,
|
||||
</if>
|
||||
<if test="email != null">
|
||||
email,
|
||||
</if>
|
||||
<if test="isAdmin != null">
|
||||
is_admin,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">
|
||||
#{id,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="name != null">
|
||||
#{name,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="password != null">
|
||||
#{password,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="displayName != null">
|
||||
#{displayName,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="email != null">
|
||||
#{email,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="isAdmin != null">
|
||||
#{isAdmin,jdbcType=INTEGER},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
<select id="countByExample" parameterType="com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDOExample" resultType="java.lang.Long">
|
||||
select count(*) from s2_user
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
</select>
|
||||
</mapper>
|
||||
@@ -35,10 +35,6 @@
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.tencent.supersonic</groupId>
|
||||
<artifactId>auth-authentication</artifactId>
|
||||
@@ -48,4 +44,4 @@
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
|
||||
@@ -53,7 +53,7 @@ public class AuthServiceImpl implements AuthService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAuthGroup(AuthGroup group) {
|
||||
public void addOrUpdateAuthGroup(AuthGroup group) {
|
||||
Gson g = new Gson();
|
||||
if (group.getGroupId() == null) {
|
||||
int nextGroupId = 1;
|
||||
|
||||
@@ -40,7 +40,7 @@ public class AuthController {
|
||||
@PostMapping("/createGroup")
|
||||
public void newAuthGroup(@RequestBody AuthGroup group) {
|
||||
group.setGroupId(null);
|
||||
authService.updateAuthGroup(group);
|
||||
authService.addOrUpdateAuthGroup(group);
|
||||
}
|
||||
|
||||
@PostMapping("/removeGroup")
|
||||
@@ -58,7 +58,7 @@ public class AuthController {
|
||||
if (group.getGroupId() == null || group.getGroupId() == 0) {
|
||||
throw new RuntimeException("groupId is empty");
|
||||
}
|
||||
authService.updateAuthGroup(group);
|
||||
authService.addOrUpdateAuthGroup(group);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,11 +3,8 @@ package com.tencent.supersonic.chat.api.component;
|
||||
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
||||
|
||||
/**
|
||||
* This interface defines the contract for a schema mapper that identifies references to schema
|
||||
* elements in natural language queries.
|
||||
*
|
||||
* The schema mapper matches queries against the knowledge base which is constructed using the
|
||||
* schema of semantic models.
|
||||
* A schema mapper identifies references to schema elements(metrics/dimensions/entities/values)
|
||||
* in user queries. It matches the query text against the knowledge base.
|
||||
*/
|
||||
public interface SchemaMapper {
|
||||
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
package com.tencent.supersonic.chat.api.component;
|
||||
|
||||
import com.tencent.supersonic.chat.api.pojo.CorrectionInfo;
|
||||
import com.tencent.supersonic.chat.api.pojo.SemanticCorrectInfo;
|
||||
import net.sf.jsqlparser.JSQLParserException;
|
||||
|
||||
/**
|
||||
* A semantic corrector checks validity of extracted semantic information and
|
||||
* performs correction and optimization if needed.
|
||||
*/
|
||||
public interface SemanticCorrector {
|
||||
CorrectionInfo corrector(CorrectionInfo correctionInfo) throws JSQLParserException;
|
||||
|
||||
void correct(SemanticCorrectInfo semanticCorrectInfo) throws JSQLParserException;
|
||||
}
|
||||
|
||||
@@ -8,9 +8,12 @@ import com.tencent.supersonic.semantic.api.model.request.PageDimensionReq;
|
||||
import com.tencent.supersonic.semantic.api.model.request.PageMetricReq;
|
||||
import com.tencent.supersonic.semantic.api.model.response.DomainResp;
|
||||
import com.tencent.supersonic.semantic.api.model.response.DimensionResp;
|
||||
import com.tencent.supersonic.semantic.api.model.response.ExplainResp;
|
||||
import com.tencent.supersonic.semantic.api.model.response.ModelResp;
|
||||
import com.tencent.supersonic.semantic.api.model.response.MetricResp;
|
||||
import com.tencent.supersonic.semantic.api.model.response.QueryResultWithSchemaResp;
|
||||
import com.tencent.supersonic.semantic.api.query.request.ExplainSqlReq;
|
||||
import com.tencent.supersonic.semantic.api.query.request.QueryDimValueReq;
|
||||
import com.tencent.supersonic.semantic.api.query.request.QueryDslReq;
|
||||
import com.tencent.supersonic.semantic.api.query.request.QueryMultiStructReq;
|
||||
import com.tencent.supersonic.semantic.api.query.request.QueryStructReq;
|
||||
@@ -18,10 +21,9 @@ import com.tencent.supersonic.semantic.api.query.request.QueryStructReq;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This interface defines the contract for a semantic layer that provides a simplified and
|
||||
* consistent view of data from multiple sources.
|
||||
* The semantic layer abstracts away the complexity of the underlying data sources and provides
|
||||
* a unified view of the data that is easier to understand and use.
|
||||
* A semantic layer provides a simplified and consistent view of data from multiple sources.
|
||||
* It abstracts away the complexity of the underlying data sources and provides a unified view
|
||||
* of the data that is easier to understand and use.
|
||||
* <p>
|
||||
* The interface defines methods for getting metadata as well as querying data in the semantic layer.
|
||||
* Implementations of this interface should provide concrete implementations that interact with the
|
||||
@@ -29,16 +31,30 @@ import java.util.List;
|
||||
* as proxy to a remote semantic service.
|
||||
* </p>
|
||||
*/
|
||||
public interface SemanticLayer {
|
||||
public interface SemanticInterpreter {
|
||||
|
||||
QueryResultWithSchemaResp queryByStruct(QueryStructReq queryStructReq, User user);
|
||||
|
||||
QueryResultWithSchemaResp queryByMultiStruct(QueryMultiStructReq queryMultiStructReq, User user);
|
||||
|
||||
QueryResultWithSchemaResp queryByDsl(QueryDslReq queryDslReq, User user);
|
||||
|
||||
QueryResultWithSchemaResp queryDimValue(QueryDimValueReq queryDimValueReq, User user);
|
||||
|
||||
List<ModelSchema> getModelSchema();
|
||||
|
||||
List<ModelSchema> getModelSchema(List<Long> ids);
|
||||
|
||||
ModelSchema getModelSchema(Long model, Boolean cacheEnable);
|
||||
|
||||
PageInfo<DimensionResp> getDimensionPage(PageDimensionReq pageDimensionCmd);
|
||||
PageInfo<MetricResp> getMetricPage(PageMetricReq pageMetricCmd);
|
||||
|
||||
PageInfo<MetricResp> getMetricPage(PageMetricReq pageMetricCmd, User user);
|
||||
|
||||
List<DomainResp> getDomainList(User user);
|
||||
|
||||
List<ModelResp> getModelList(AuthType authType, Long domainId, User user);
|
||||
|
||||
<T> ExplainResp explain(ExplainSqlReq<T> explainSqlReq, User user) throws Exception;
|
||||
|
||||
}
|
||||
@@ -5,11 +5,9 @@ import com.tencent.supersonic.chat.api.pojo.ChatContext;
|
||||
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
||||
|
||||
/**
|
||||
* This interface defines the contract for a semantic parser that can analyze natural language query
|
||||
* and extract meaning from it.
|
||||
*
|
||||
* The semantic parser uses either rule-based or model-based algorithms to identify query intent
|
||||
* and related semantic items described in the query.
|
||||
* A semantic parser understands user queries and extracts semantic information.
|
||||
* It could leverage either rule-based or LLM-based approach to identify query intent
|
||||
* and extract related semantic items from the query.
|
||||
*/
|
||||
public interface SemanticParser {
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@ package com.tencent.supersonic.chat.api.component;
|
||||
import com.tencent.supersonic.auth.api.authentication.pojo.User;
|
||||
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
|
||||
import com.tencent.supersonic.chat.api.pojo.response.QueryResult;
|
||||
import com.tencent.supersonic.semantic.api.model.response.ExplainResp;
|
||||
import org.apache.calcite.sql.parser.SqlParseException;
|
||||
|
||||
/**
|
||||
* This class defines the contract for a semantic query that executes specific type of
|
||||
* query based on the results of semantic parsing.
|
||||
* A semantic query executes specific type of query based on the results of semantic parsing.
|
||||
*/
|
||||
public interface SemanticQuery {
|
||||
|
||||
@@ -15,6 +15,8 @@ public interface SemanticQuery {
|
||||
|
||||
QueryResult execute(User user) throws SqlParseException;
|
||||
|
||||
ExplainResp explain(User user);
|
||||
|
||||
SemanticParseInfo getParseInfo();
|
||||
|
||||
void setParseInfo(SemanticParseInfo parseInfo);
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package com.tencent.supersonic.chat.api.pojo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ModelSchema {
|
||||
|
||||
@@ -2,11 +2,12 @@ package com.tencent.supersonic.chat.api.pojo;
|
||||
|
||||
import com.tencent.supersonic.chat.api.component.SemanticQuery;
|
||||
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class QueryContext {
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
package com.tencent.supersonic.chat.api.pojo;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.Builder;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Getter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class SchemaElement implements Serializable {
|
||||
|
||||
@@ -22,18 +22,12 @@ public class SchemaElement implements Serializable {
|
||||
private String bizName;
|
||||
private Long useCnt;
|
||||
private SchemaElementType type;
|
||||
|
||||
private List<String> alias;
|
||||
|
||||
public SchemaElement(Long model, Long id, String name, String bizName,
|
||||
Long useCnt, SchemaElementType type, List<String> alias) {
|
||||
this.model = model;
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.bizName = bizName;
|
||||
this.useCnt = useCnt;
|
||||
this.type = type;
|
||||
this.alias = alias;
|
||||
}
|
||||
private List<SchemaValueMap> schemaValueMaps;
|
||||
|
||||
private String defaultAgg;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
@@ -54,4 +48,5 @@ public class SchemaElement implements Serializable {
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(model, id, name, bizName, useCnt, type);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,6 +21,10 @@ public class SchemaMapInfo {
|
||||
return modelElementMatches;
|
||||
}
|
||||
|
||||
public void setModelElementMatches(Map<Long, List<SchemaElementMatch>> modelElementMatches) {
|
||||
this.modelElementMatches = modelElementMatches;
|
||||
}
|
||||
|
||||
public void setMatchedElements(Long model, List<SchemaElementMatch> elementMatches) {
|
||||
modelElementMatches.put(model, elementMatches);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.tencent.supersonic.chat.api.pojo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SchemaValueMap {
|
||||
|
||||
/**
|
||||
* dimension value in db
|
||||
*/
|
||||
private String techName;
|
||||
|
||||
/**
|
||||
* dimension value for result show
|
||||
*/
|
||||
private String bizName;
|
||||
|
||||
/**
|
||||
* dimension value for user query
|
||||
*/
|
||||
private List<String> alias = new ArrayList<>();
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import lombok.NoArgsConstructor;
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class CorrectionInfo {
|
||||
public class SemanticCorrectInfo {
|
||||
|
||||
private QueryFilters queryFilters;
|
||||
|
||||
@@ -18,4 +18,5 @@ public class CorrectionInfo {
|
||||
|
||||
private String sql;
|
||||
|
||||
private String preSql;
|
||||
}
|
||||
@@ -1,20 +1,21 @@
|
||||
package com.tencent.supersonic.chat.api.pojo;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.Comparator;
|
||||
|
||||
import com.tencent.supersonic.chat.api.pojo.request.QueryFilter;
|
||||
import com.tencent.supersonic.chat.api.pojo.response.EntityInfo;
|
||||
import com.tencent.supersonic.chat.api.pojo.response.SqlInfo;
|
||||
import com.tencent.supersonic.common.pojo.DateConf;
|
||||
import com.tencent.supersonic.common.pojo.Order;
|
||||
import com.tencent.supersonic.common.pojo.enums.AggregateTypeEnum;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import com.tencent.supersonic.common.pojo.enums.FilterType;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@@ -27,6 +28,7 @@ public class SemanticParseInfo {
|
||||
private Set<SchemaElement> dimensions = new LinkedHashSet();
|
||||
private SchemaElement entity;
|
||||
private AggregateTypeEnum aggType = AggregateTypeEnum.NONE;
|
||||
private FilterType filterType = FilterType.UNION;
|
||||
private Set<QueryFilter> dimensionFilters = new LinkedHashSet();
|
||||
private Set<QueryFilter> metricFilters = new LinkedHashSet();
|
||||
private Set<Order> orders = new LinkedHashSet();
|
||||
@@ -37,6 +39,8 @@ public class SemanticParseInfo {
|
||||
private List<SchemaElementMatch> elementMatches = new ArrayList<>();
|
||||
private Map<String, Object> properties = new HashMap<>();
|
||||
private EntityInfo entityInfo;
|
||||
private SqlInfo sqlInfo = new SqlInfo();
|
||||
|
||||
public Long getModelId() {
|
||||
return model != null ? model.getId() : 0L;
|
||||
}
|
||||
@@ -46,6 +50,7 @@ public class SemanticParseInfo {
|
||||
}
|
||||
|
||||
private static class SchemaNameLengthComparator implements Comparator<SchemaElement> {
|
||||
|
||||
@Override
|
||||
public int compare(SchemaElement o1, SchemaElement o2) {
|
||||
int len1 = o1.getName().length();
|
||||
|
||||
@@ -35,12 +35,28 @@ public class SemanticSchema implements Serializable {
|
||||
return dimensions;
|
||||
}
|
||||
|
||||
public List<SchemaElement> getDimensions(Long modelId) {
|
||||
List<SchemaElement> dimensions = getDimensions();
|
||||
return getElementsByModelId(modelId, dimensions);
|
||||
}
|
||||
|
||||
public List<SchemaElement> getMetrics() {
|
||||
List<SchemaElement> metrics = new ArrayList<>();
|
||||
modelSchemaList.stream().forEach(d -> metrics.addAll(d.getMetrics()));
|
||||
return metrics;
|
||||
}
|
||||
|
||||
public List<SchemaElement> getMetrics(Long modelId) {
|
||||
List<SchemaElement> metrics = getMetrics();
|
||||
return getElementsByModelId(modelId, metrics);
|
||||
}
|
||||
|
||||
private List<SchemaElement> getElementsByModelId(Long modelId, List<SchemaElement> elements) {
|
||||
return elements.stream()
|
||||
.filter(schemaElement -> modelId.equals(schemaElement.getModel()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<SchemaElement> getModels() {
|
||||
List<SchemaElement> models = new ArrayList<>();
|
||||
modelSchemaList.stream().forEach(d -> models.add(d.getModel()));
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package com.tencent.supersonic.chat.api.pojo.request;
|
||||
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class ChatAggConfigReq {
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package com.tencent.supersonic.chat.api.pojo.request;
|
||||
|
||||
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* extended information command about model
|
||||
*/
|
||||
|
||||
@@ -2,9 +2,10 @@ package com.tencent.supersonic.chat.api.pojo.request;
|
||||
|
||||
|
||||
import com.tencent.supersonic.common.pojo.Constants;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ChatDefaultConfigReq {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package com.tencent.supersonic.chat.api.pojo.request;
|
||||
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class ChatDetailConfigReq {
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.tencent.supersonic.chat.api.pojo.request;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
import static java.time.LocalDate.now;
|
||||
|
||||
@ToString
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class DictLatestTaskReq {
|
||||
|
||||
@NotNull
|
||||
private Long modelId;
|
||||
|
||||
private List<Long> dimIds;
|
||||
|
||||
private String createdAt = now().plusDays(-4).toString();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.tencent.supersonic.chat.api.pojo.request;
|
||||
|
||||
import com.tencent.supersonic.common.pojo.enums.TaskStatusEnum;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
@ToString
|
||||
@Data
|
||||
public class DictTaskFilterReq {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
private String createdBy;
|
||||
|
||||
private String createdAt;
|
||||
|
||||
private TaskStatusEnum status;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.tencent.supersonic.chat.api.pojo.request;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class DimensionValueReq {
|
||||
private Integer agentId;
|
||||
|
||||
private Long elementID;
|
||||
|
||||
private Long modelId;
|
||||
|
||||
private String bizName;
|
||||
|
||||
private Object value;
|
||||
}
|
||||
@@ -7,13 +7,12 @@ import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ExecuteQueryReq {
|
||||
|
||||
private User user;
|
||||
private Integer agentId;
|
||||
private Integer chatId;
|
||||
private String queryText;
|
||||
private Long queryId;
|
||||
private Integer parseId;
|
||||
private Long queryId = 7L;
|
||||
private Integer parseId = 2;
|
||||
private SemanticParseInfo parseInfo;
|
||||
private boolean saveAnswer = true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.tencent.supersonic.chat.api.pojo.request;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
@Data
|
||||
@ToString
|
||||
public class ItemNameVisibility {
|
||||
|
||||
private ItemNameVisibilityInfo aggVisibilityInfo;
|
||||
|
||||
private ItemNameVisibilityInfo detailVisibilityInfo;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.tencent.supersonic.chat.api.pojo.request;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Data
|
||||
@ToString
|
||||
public class ItemNameVisibilityInfo {
|
||||
|
||||
/**
|
||||
* invisible dimensions
|
||||
*/
|
||||
private List<String> blackDimNameList = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* invisible metrics
|
||||
*/
|
||||
private List<String> blackMetricNameList = new ArrayList<>();
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
package com.tencent.supersonic.chat.api.pojo.request;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* advanced knowledge config
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package com.tencent.supersonic.chat.api.pojo.request;
|
||||
|
||||
import com.tencent.supersonic.common.pojo.enums.TypeEnums;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
@@ -30,6 +32,4 @@ public class KnowledgeInfoReq {
|
||||
* advanced knowledge config for single item
|
||||
*/
|
||||
private KnowledgeAdvancedConfig knowledgeAdvancedConfig;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.tencent.supersonic.chat.api.pojo.request;
|
||||
|
||||
import lombok.Data;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class PageQueryInfoReq {
|
||||
@@ -11,27 +12,5 @@ public class PageQueryInfoReq {
|
||||
|
||||
private String userName;
|
||||
|
||||
public int getPageSize() {
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
public void setPageSize(int pageSize) {
|
||||
this.pageSize = pageSize;
|
||||
}
|
||||
|
||||
public int getCurrent() {
|
||||
return current;
|
||||
}
|
||||
|
||||
public void setCurrent(int current) {
|
||||
this.current = current;
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
private List<Long> ids;
|
||||
}
|
||||
|
||||
@@ -1,24 +1,21 @@
|
||||
package com.tencent.supersonic.chat.api.pojo.request;
|
||||
|
||||
|
||||
import com.tencent.supersonic.auth.api.authentication.pojo.User;
|
||||
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
|
||||
import com.tencent.supersonic.common.pojo.DateConf;
|
||||
import com.tencent.supersonic.common.pojo.Order;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class QueryDataReq {
|
||||
|
||||
String queryMode;
|
||||
SchemaElement model;
|
||||
Set<SchemaElement> metrics = new HashSet<>();
|
||||
Set<SchemaElement> dimensions = new HashSet<>();
|
||||
Set<QueryFilter> dimensionFilters = new HashSet<>();
|
||||
Set<QueryFilter> metricFilters = new HashSet<>();
|
||||
private Set<Order> orders = new HashSet<>();
|
||||
private User user;
|
||||
private Set<SchemaElement> metrics = new HashSet<>();
|
||||
private Set<SchemaElement> dimensions = new HashSet<>();
|
||||
private Set<QueryFilter> dimensionFilters = new HashSet<>();
|
||||
private Set<QueryFilter> metricFilters = new HashSet<>();
|
||||
private DateConf dateInfo;
|
||||
private Long limit;
|
||||
private Boolean nativeQuery = false;
|
||||
private Long queryId = 7L;
|
||||
private Integer parseId = 2;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.tencent.supersonic.chat.api.pojo.request;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.tencent.supersonic.semantic.api.query.enums.FilterOperatorEnum;
|
||||
import java.util.Objects;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
@@ -19,6 +19,8 @@ public class QueryFilter {
|
||||
|
||||
private Long elementID;
|
||||
|
||||
private String function;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
@@ -27,14 +29,15 @@ public class QueryFilter {
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
QueryFilter filter = (QueryFilter) o;
|
||||
return Objects.equals(bizName, filter.bizName) && Objects.equals(name, filter.name)
|
||||
&& operator == filter.operator && Objects.equals(value, filter.value) && Objects.equals(
|
||||
elementID, filter.elementID);
|
||||
QueryFilter that = (QueryFilter) o;
|
||||
return Objects.equal(bizName, that.bizName) && Objects.equal(name,
|
||||
that.name) && operator == that.operator && Objects.equal(value, that.value)
|
||||
&& Objects.equal(elementID, that.elementID) && Objects.equal(
|
||||
function, that.function);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(bizName, name, operator, value, elementID);
|
||||
return Objects.hashCode(bizName, name, operator, value, elementID, function);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,13 @@
|
||||
package com.tencent.supersonic.chat.api.pojo.request;
|
||||
|
||||
import lombok.Data;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class QueryFilters {
|
||||
|
||||
private List<QueryFilter> filters = new ArrayList<>();
|
||||
private Map<String, Object> params = new HashMap<>();
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class QueryReq {
|
||||
|
||||
private String queryText;
|
||||
private Integer chatId;
|
||||
private Long modelId = 0L;
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.tencent.supersonic.chat.api.pojo.request;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class SolvedQueryReq {
|
||||
|
||||
private Long queryId;
|
||||
|
||||
private Integer parseId;
|
||||
|
||||
private String queryText;
|
||||
|
||||
private Long modelId;
|
||||
|
||||
private Integer agentId;
|
||||
|
||||
}
|
||||
@@ -2,9 +2,10 @@ package com.tencent.supersonic.chat.api.pojo.response;
|
||||
|
||||
import com.tencent.supersonic.chat.api.pojo.request.KnowledgeAdvancedConfig;
|
||||
import com.tencent.supersonic.chat.api.pojo.request.KnowledgeInfoReq;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class ChatAggRichConfigResp {
|
||||
|
||||
|
||||
@@ -4,8 +4,10 @@ import com.tencent.supersonic.chat.api.pojo.request.ChatAggConfigReq;
|
||||
import com.tencent.supersonic.chat.api.pojo.request.ChatDetailConfigReq;
|
||||
import com.tencent.supersonic.chat.api.pojo.request.RecommendedQuestionReq;
|
||||
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.tencent.supersonic.chat.api.pojo.request.RecommendedQuestionReq;
|
||||
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
|
||||
@@ -4,9 +4,10 @@ package com.tencent.supersonic.chat.api.pojo.response;
|
||||
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
|
||||
import com.tencent.supersonic.chat.api.pojo.request.ChatDefaultConfigReq;
|
||||
import com.tencent.supersonic.common.pojo.Constants;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class ChatDefaultRichConfigResp {
|
||||
|
||||
|
||||
@@ -2,9 +2,10 @@ package com.tencent.supersonic.chat.api.pojo.response;
|
||||
|
||||
import com.tencent.supersonic.chat.api.pojo.request.KnowledgeAdvancedConfig;
|
||||
import com.tencent.supersonic.chat.api.pojo.request.KnowledgeInfoReq;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class ChatDetailRichConfigResp {
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.tencent.supersonic.chat.api.pojo.response;
|
||||
|
||||
import com.tencent.supersonic.common.pojo.enums.TaskStatusEnum;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ToString
|
||||
@Data
|
||||
public class DictLatestTaskResp {
|
||||
|
||||
private Long dimId;
|
||||
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
private String description;
|
||||
|
||||
private String command;
|
||||
|
||||
private TaskStatusEnum status;
|
||||
|
||||
private String createdBy;
|
||||
|
||||
private Date createdAt;
|
||||
|
||||
private Long elapsedMs;
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
package com.tencent.supersonic.chat.api.pojo.response;
|
||||
|
||||
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
|
||||
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class EntityRichInfoResp {
|
||||
|
||||
/**
|
||||
* entity alias
|
||||
* entity alias
|
||||
*/
|
||||
private List<String> names;
|
||||
|
||||
|
||||
@@ -8,5 +8,6 @@ import lombok.Data;
|
||||
public class ModelInfo extends DataInfo implements Serializable {
|
||||
|
||||
private List<String> words;
|
||||
private String primaryEntityName;
|
||||
private String primaryEntityBizName;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ public class ParseResp {
|
||||
private ParseState state;
|
||||
private List<SemanticParseInfo> selectedParses;
|
||||
private List<SemanticParseInfo> candidateParses;
|
||||
private List<SolvedQueryRecallResp> similarSolvedQuery;
|
||||
|
||||
public enum ParseState {
|
||||
COMPLETED,
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package com.tencent.supersonic.chat.api.pojo.response;
|
||||
|
||||
import com.tencent.supersonic.chat.api.pojo.request.RecommendedQuestionReq;
|
||||
import java.util.List;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class RecommendQuestionResp {
|
||||
|
||||
private Long modelId;
|
||||
private List<RecommendedQuestionReq> recommendedQuestions;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.tencent.supersonic.chat.api.pojo.response;
|
||||
|
||||
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class RecommendResp {
|
||||
|
||||
private List<SchemaElement> dimensions;
|
||||
private List<SchemaElement> metrics;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.tencent.supersonic.chat.api.pojo.response;
|
||||
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public class SolvedQueryRecallResp {
|
||||
|
||||
private Long queryId;
|
||||
|
||||
private Integer parseId;
|
||||
|
||||
private String queryText;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.tencent.supersonic.chat.api.pojo.response;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SqlInfo {
|
||||
|
||||
private String llmParseSql;
|
||||
private String logicSql;
|
||||
private String querySql;
|
||||
}
|
||||
@@ -136,6 +136,14 @@
|
||||
<artifactId>xk-time</artifactId>
|
||||
<version>${xk.time.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-inline</artifactId>
|
||||
<version>${mockito-inline.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -9,8 +9,9 @@ import lombok.NoArgsConstructor;
|
||||
@AllArgsConstructor
|
||||
public class AgentTool {
|
||||
|
||||
private String id;
|
||||
|
||||
private String name;
|
||||
|
||||
private AgentToolType type;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
//package com.tencent.supersonic.chat.aspect;
|
||||
//
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.aspectj.lang.JoinPoint;
|
||||
//import org.aspectj.lang.ProceedingJoinPoint;
|
||||
//import org.aspectj.lang.annotation.*;
|
||||
//import org.springframework.stereotype.Component;
|
||||
//
|
||||
//import java.util.HashMap;
|
||||
//import java.util.Map;
|
||||
//
|
||||
//@Aspect
|
||||
//@Component
|
||||
//@Slf4j
|
||||
//public class TimeCostAspect {
|
||||
//
|
||||
// ThreadLocal<Long> startTime = new ThreadLocal<>();
|
||||
//
|
||||
// ThreadLocal<Map<String, Long>> map = new ThreadLocal<>();
|
||||
//
|
||||
// @Pointcut("execution(public * com.tencent.supersonic.chat.mapper.HanlpDictMapper.*(*))")
|
||||
// //@Pointcut("execution(* public com.tencent.supersonic.chat.parser.*.*(..))")
|
||||
// //@Pointcut("execution(* com.tencent.supersonic.chat.mapper.*Mapper.map(..)) ")
|
||||
// //@Pointcut("execution(* com.tencent.supersonic.chat.mapper.HanlpDictMapper.map(..)) ")
|
||||
// //@Pointcut("execution(* com.tencent.supersonic.chat.parser.rule.QueryModeParser.*(..)) ")
|
||||
// public void point() {
|
||||
// }
|
||||
//
|
||||
// @Around("point()")
|
||||
// public void doAround(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
// long start = System.currentTimeMillis();
|
||||
// try {
|
||||
// log.info("切面开始");
|
||||
// Object result = joinPoint.proceed();
|
||||
// log.info("切面开始");
|
||||
// if (result == null) {
|
||||
// //如果切到了 没有返回类型的void方法,这里直接返回
|
||||
// //return null;
|
||||
// }
|
||||
// long end = System.currentTimeMillis();
|
||||
// log.info("===================");
|
||||
// String targetClassName = joinPoint.getSignature().getDeclaringTypeName();
|
||||
// String MethodName = joinPoint.getSignature().getName();
|
||||
// String typeStr = joinPoint.getSignature().getDeclaringType().toString().split(" ")[0];
|
||||
// log.info("类/接口:" + targetClassName + "(" + typeStr + ")");
|
||||
// log.info("方法:" + MethodName);
|
||||
// Long total = end - start;
|
||||
// log.info("耗时: " + total + " ms!");
|
||||
// map.get().put(targetClassName + "_" + MethodName, total);
|
||||
// //return result;
|
||||
// } catch (Throwable e) {
|
||||
// long end = System.currentTimeMillis();
|
||||
// log.info("====around " + joinPoint + "\tUse time : " + (end - start) + " ms with exception : "
|
||||
// + e.getMessage());
|
||||
// throw e;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//// //对Controller下面的方法执行前进行切入,初始化开始时间
|
||||
//// @Before(value = "execution(* com.appleyk.controller.*.*(..))")
|
||||
//// public void beforMehhod(JoinPoint jp) {
|
||||
//// startTime.set(System.currentTimeMillis());
|
||||
//// }
|
||||
////
|
||||
//// //对Controller下面的方法执行后进行切入,统计方法执行的次数和耗时情况
|
||||
//// //注意,这里的执行方法统计的数据不止包含Controller下面的方法,也包括环绕切入的所有方法的统计信息
|
||||
//// @AfterReturning(value = "execution(* com.appleyk.controller.*.*(..))")
|
||||
//// public void afterMehhod(JoinPoint jp) {
|
||||
//// long end = System.currentTimeMillis();
|
||||
//// long total = end - startTime.get();
|
||||
//// String methodName = jp.getSignature().getName();
|
||||
//// log.info("连接点方法为:" + methodName + ",执行总耗时为:" +total+"ms");
|
||||
////
|
||||
//// //重新new一个map
|
||||
//// Map<String, Long> map = new HashMap<>();
|
||||
//////从map2中将最后的 连接点方法给移除了,替换成最终的,避免连接点方法多次进行叠加计算
|
||||
//// //由于map2受ThreadLocal的保护,这里不支持remove,因此,需要单开一个map进行数据交接
|
||||
//// for(Map.Entry<String, Long> entry:map2.get().entrySet()){
|
||||
//// if(entry.getKey().equals(methodName)){
|
||||
//// map.put(methodName, total);
|
||||
////
|
||||
//// }else{
|
||||
//// map.put(entry.getKey(), entry.getValue());
|
||||
//// }
|
||||
//// }
|
||||
////
|
||||
//// for (Map.Entry<String, Long> entry :map1.get().entrySet()) {
|
||||
//// for(Map.Entry<String, Long> entry2 :map.entrySet()){
|
||||
//// if(entry.getKey().equals(entry2.getKey())){
|
||||
//// System.err.println(entry.getKey()+",被调用次数:"+entry.getValue()+",综合耗时:"+entry2.getValue()+"ms");
|
||||
//// }
|
||||
//// }
|
||||
////
|
||||
//// }
|
||||
//// }
|
||||
//
|
||||
//}
|
||||
*/
|
||||
@@ -3,12 +3,13 @@ package com.tencent.supersonic.chat.config;
|
||||
import com.tencent.supersonic.chat.api.pojo.request.ChatAggConfigReq;
|
||||
import com.tencent.supersonic.chat.api.pojo.request.ChatDetailConfigReq;
|
||||
import com.tencent.supersonic.chat.api.pojo.request.RecommendedQuestionReq;
|
||||
import com.tencent.supersonic.common.pojo.RecordInfo;
|
||||
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
|
||||
import java.util.List;
|
||||
import com.tencent.supersonic.common.pojo.RecordInfo;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@ToString
|
||||
public class ChatConfig {
|
||||
|
||||
@@ -7,13 +7,19 @@ import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@Data
|
||||
public class LLMConfig {
|
||||
public class LLMParserConfig {
|
||||
|
||||
|
||||
@Value("${llm.url:}")
|
||||
@Value("${llm.parser.url:}")
|
||||
private String url;
|
||||
|
||||
@Value("${query2sql.path:query2sql}")
|
||||
@Value("${query2sql.path:/query2sql}")
|
||||
private String queryToSqlPath;
|
||||
|
||||
@Value("${dimension.topn:5}")
|
||||
private Integer dimensionTopN;
|
||||
|
||||
@Value("${metric.topn:5}")
|
||||
private Integer metricTopN;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.tencent.supersonic.chat.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
|
||||
@Configuration
|
||||
@Data
|
||||
@PropertySource("classpath:optimization.properties")
|
||||
//@ComponentScan(basePackages = "com.tencent.supersonic.chat")
|
||||
public class OptimizationConfig {
|
||||
|
||||
@Value("${one.detection.size}")
|
||||
private Integer oneDetectionSize;
|
||||
@Value("${one.detection.max.size}")
|
||||
private Integer oneDetectionMaxSize;
|
||||
|
||||
@Value("${metric.dimension.min.threshold}")
|
||||
private Double metricDimensionMinThresholdConfig;
|
||||
|
||||
@Value("${metric.dimension.threshold}")
|
||||
private Double metricDimensionThresholdConfig;
|
||||
|
||||
@Value("${dimension.value.threshold}")
|
||||
private Double dimensionValueThresholdConfig;
|
||||
|
||||
@Value("${function.bonus.threshold}")
|
||||
private Double functionBonusThreshold;
|
||||
|
||||
@Value("${long.text.threshold}")
|
||||
private Double longTextThreshold;
|
||||
|
||||
@Value("${short.text.threshold}")
|
||||
private Double shortTextThreshold;
|
||||
|
||||
@Value("${query.text.length.threshold}")
|
||||
private Integer queryTextLengthThreshold;
|
||||
|
||||
@Value("${candidate.threshold}")
|
||||
private Double candidateThreshold;
|
||||
|
||||
}
|
||||
@@ -2,20 +2,32 @@ package com.tencent.supersonic.chat.corrector;
|
||||
|
||||
import com.tencent.supersonic.chat.api.component.SemanticCorrector;
|
||||
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
|
||||
import com.tencent.supersonic.chat.api.pojo.SemanticCorrectInfo;
|
||||
import com.tencent.supersonic.chat.api.pojo.SemanticSchema;
|
||||
import com.tencent.supersonic.common.pojo.enums.AggregateTypeEnum;
|
||||
import com.tencent.supersonic.common.util.ContextUtils;
|
||||
import com.tencent.supersonic.common.util.DateUtils;
|
||||
import com.tencent.supersonic.common.util.jsqlparser.SqlParserAddHelper;
|
||||
import com.tencent.supersonic.common.util.jsqlparser.SqlParserSelectHelper;
|
||||
import com.tencent.supersonic.knowledge.service.SchemaService;
|
||||
import com.tencent.supersonic.semantic.api.model.enums.TimeDimensionEnum;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@Slf4j
|
||||
public abstract class BaseSemanticCorrector implements SemanticCorrector {
|
||||
public static final String DATE_FIELD = "数据日期";
|
||||
protected Map<String, String> getFieldToBizName(Long modelId) {
|
||||
|
||||
public void correct(SemanticCorrectInfo semanticCorrectInfo) {
|
||||
semanticCorrectInfo.setPreSql(semanticCorrectInfo.getSql());
|
||||
}
|
||||
|
||||
protected Map<String, String> getFieldNameMap(Long modelId) {
|
||||
|
||||
SemanticSchema semanticSchema = ContextUtils.getBean(SchemaService.class).getSemanticSchema();
|
||||
|
||||
@@ -25,9 +37,56 @@ public abstract class BaseSemanticCorrector implements SemanticCorrector {
|
||||
|
||||
Map<String, String> result = dbAllFields.stream()
|
||||
.filter(entry -> entry.getModel().equals(modelId))
|
||||
.collect(Collectors.toMap(SchemaElement::getName, a -> a.getBizName(), (k1, k2) -> k1));
|
||||
result.put(DATE_FIELD, TimeDimensionEnum.DAY.getName());
|
||||
.collect(Collectors.toMap(SchemaElement::getName, a -> a.getName(), (k1, k2) -> k1));
|
||||
result.put(DateUtils.DATE_FIELD, DateUtils.DATE_FIELD);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void addFieldsToSelect(SemanticCorrectInfo semanticCorrectInfo, String sql) {
|
||||
Set<String> selectFields = new HashSet<>(SqlParserSelectHelper.getSelectFields(sql));
|
||||
Set<String> needAddFields = new HashSet<>(SqlParserSelectHelper.getGroupByFields(sql));
|
||||
needAddFields.addAll(SqlParserSelectHelper.getOrderByFields(sql));
|
||||
|
||||
if (CollectionUtils.isEmpty(selectFields) || CollectionUtils.isEmpty(needAddFields)) {
|
||||
return;
|
||||
}
|
||||
|
||||
needAddFields.removeAll(selectFields);
|
||||
needAddFields.remove(DateUtils.DATE_FIELD);
|
||||
String replaceFields = SqlParserAddHelper.addFieldsToSelect(sql, new ArrayList<>(needAddFields));
|
||||
semanticCorrectInfo.setSql(replaceFields);
|
||||
}
|
||||
|
||||
protected void addAggregateToMetric(SemanticCorrectInfo semanticCorrectInfo) {
|
||||
//add aggregate to all metric
|
||||
String sql = semanticCorrectInfo.getSql();
|
||||
Long modelId = semanticCorrectInfo.getParseInfo().getModel().getModel();
|
||||
|
||||
List<SchemaElement> metrics = getMetricElements(modelId);
|
||||
|
||||
Map<String, String> metricToAggregate = metrics.stream()
|
||||
.map(schemaElement -> {
|
||||
if (Objects.isNull(schemaElement.getDefaultAgg())) {
|
||||
schemaElement.setDefaultAgg(AggregateTypeEnum.SUM.name());
|
||||
}
|
||||
return schemaElement;
|
||||
}).collect(Collectors.toMap(a -> a.getName(), a -> a.getDefaultAgg(), (k1, k2) -> k1));
|
||||
|
||||
if (CollectionUtils.isEmpty(metricToAggregate)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String aggregateSql = SqlParserAddHelper.addAggregateToField(sql, metricToAggregate);
|
||||
semanticCorrectInfo.setSql(aggregateSql);
|
||||
}
|
||||
|
||||
protected List<SchemaElement> getMetricElements(Long modelId) {
|
||||
SemanticSchema semanticSchema = ContextUtils.getBean(SchemaService.class).getSemanticSchema();
|
||||
return semanticSchema.getMetrics(modelId);
|
||||
}
|
||||
|
||||
protected List<SchemaElement> getDimensionElements(Long modelId) {
|
||||
SemanticSchema semanticSchema = ContextUtils.getBean(SchemaService.class).getSemanticSchema();
|
||||
return semanticSchema.getDimensions(modelId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
package com.tencent.supersonic.chat.corrector;
|
||||
|
||||
import com.tencent.supersonic.chat.api.pojo.CorrectionInfo;
|
||||
import com.tencent.supersonic.chat.parser.llm.dsl.DSLDateHelper;
|
||||
import com.tencent.supersonic.common.util.jsqlparser.SqlParserSelectHelper;
|
||||
import com.tencent.supersonic.common.util.jsqlparser.SqlParserUpdateHelper;
|
||||
import java.util.List;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@Slf4j
|
||||
public class DateFieldCorrector extends BaseSemanticCorrector {
|
||||
|
||||
@Override
|
||||
public CorrectionInfo corrector(CorrectionInfo correctionInfo) {
|
||||
|
||||
String sql = correctionInfo.getSql();
|
||||
List<String> whereFields = SqlParserSelectHelper.getWhereFields(sql);
|
||||
if (CollectionUtils.isEmpty(whereFields) || !whereFields.contains(DATE_FIELD)) {
|
||||
String currentDate = DSLDateHelper.getCurrentDate(correctionInfo.getParseInfo().getModelId());
|
||||
sql = SqlParserUpdateHelper.addWhere(sql, DATE_FIELD, currentDate);
|
||||
}
|
||||
correctionInfo.setSql(sql);
|
||||
return correctionInfo;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package com.tencent.supersonic.chat.corrector;
|
||||
|
||||
import com.tencent.supersonic.chat.api.pojo.CorrectionInfo;
|
||||
import com.tencent.supersonic.common.util.jsqlparser.SqlParserUpdateHelper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class FieldCorrector extends BaseSemanticCorrector {
|
||||
|
||||
@Override
|
||||
public CorrectionInfo corrector(CorrectionInfo correctionInfo) {
|
||||
String replaceFields = SqlParserUpdateHelper.replaceFields(correctionInfo.getSql(),
|
||||
getFieldToBizName(correctionInfo.getParseInfo().getModelId()));
|
||||
correctionInfo.setSql(replaceFields);
|
||||
return correctionInfo;
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package com.tencent.supersonic.chat.corrector;
|
||||
|
||||
import com.tencent.supersonic.chat.api.pojo.CorrectionInfo;
|
||||
import com.tencent.supersonic.chat.parser.llm.dsl.DSLParseResult;
|
||||
import com.tencent.supersonic.chat.query.llm.dsl.LLMReq;
|
||||
import com.tencent.supersonic.chat.query.llm.dsl.LLMReq.ElementValue;
|
||||
import com.tencent.supersonic.common.pojo.Constants;
|
||||
import com.tencent.supersonic.common.util.JsonUtil;
|
||||
import com.tencent.supersonic.common.util.jsqlparser.SqlParserUpdateHelper;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@Slf4j
|
||||
public class FieldValueCorrector extends BaseSemanticCorrector {
|
||||
|
||||
@Override
|
||||
public CorrectionInfo corrector(CorrectionInfo correctionInfo) {
|
||||
|
||||
Object context = correctionInfo.getParseInfo().getProperties().get(Constants.CONTEXT);
|
||||
if (Objects.isNull(context)) {
|
||||
return correctionInfo;
|
||||
}
|
||||
|
||||
DSLParseResult dslParseResult = JsonUtil.toObject(JsonUtil.toString(context), DSLParseResult.class);
|
||||
if (Objects.isNull(dslParseResult) || Objects.isNull(dslParseResult.getLlmReq())) {
|
||||
return correctionInfo;
|
||||
}
|
||||
LLMReq llmReq = dslParseResult.getLlmReq();
|
||||
List<ElementValue> linking = llmReq.getLinking();
|
||||
if (CollectionUtils.isEmpty(linking)) {
|
||||
return correctionInfo;
|
||||
}
|
||||
|
||||
Map<String, Set<String>> fieldValueToFieldNames = linking.stream().collect(
|
||||
Collectors.groupingBy(ElementValue::getFieldValue,
|
||||
Collectors.mapping(ElementValue::getFieldName, Collectors.toSet())));
|
||||
|
||||
String sql = SqlParserUpdateHelper.replaceValueFields(correctionInfo.getSql(), fieldValueToFieldNames);
|
||||
correctionInfo.setSql(sql);
|
||||
return correctionInfo;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package com.tencent.supersonic.chat.corrector;
|
||||
|
||||
import com.tencent.supersonic.chat.api.pojo.CorrectionInfo;
|
||||
import com.tencent.supersonic.common.util.jsqlparser.SqlParserUpdateHelper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class FunctionCorrector extends BaseSemanticCorrector {
|
||||
|
||||
@Override
|
||||
public CorrectionInfo corrector(CorrectionInfo correctionInfo) {
|
||||
String replaceFunction = SqlParserUpdateHelper.replaceFunction(correctionInfo.getSql());
|
||||
correctionInfo.setSql(replaceFunction);
|
||||
return correctionInfo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.tencent.supersonic.chat.corrector;
|
||||
|
||||
import com.tencent.supersonic.chat.api.pojo.SemanticCorrectInfo;
|
||||
import com.tencent.supersonic.common.util.jsqlparser.SqlParserAddHelper;
|
||||
import com.tencent.supersonic.common.util.jsqlparser.SqlParserSelectFunctionHelper;
|
||||
import com.tencent.supersonic.common.util.jsqlparser.SqlParserSelectHelper;
|
||||
import java.util.Objects;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
|
||||
@Slf4j
|
||||
public class GlobalAfterCorrector extends BaseSemanticCorrector {
|
||||
|
||||
@Override
|
||||
public void correct(SemanticCorrectInfo semanticCorrectInfo) {
|
||||
|
||||
super.correct(semanticCorrectInfo);
|
||||
String sql = semanticCorrectInfo.getSql();
|
||||
if (!SqlParserSelectFunctionHelper.hasAggregateFunction(sql)) {
|
||||
return;
|
||||
}
|
||||
Expression havingExpression = SqlParserSelectHelper.getHavingExpression(sql);
|
||||
if (Objects.nonNull(havingExpression)) {
|
||||
String replaceSql = SqlParserAddHelper.addFunctionToSelect(sql, havingExpression);
|
||||
semanticCorrectInfo.setSql(replaceSql);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package com.tencent.supersonic.chat.corrector;
|
||||
|
||||
import com.tencent.supersonic.chat.api.pojo.SemanticCorrectInfo;
|
||||
import com.tencent.supersonic.chat.parser.llm.dsl.DSLParseResult;
|
||||
import com.tencent.supersonic.chat.query.llm.dsl.LLMReq;
|
||||
import com.tencent.supersonic.chat.query.llm.dsl.LLMReq.ElementValue;
|
||||
import com.tencent.supersonic.common.pojo.Constants;
|
||||
import com.tencent.supersonic.common.util.JsonUtil;
|
||||
import com.tencent.supersonic.common.util.jsqlparser.SqlParserReplaceHelper;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@Slf4j
|
||||
public class GlobalBeforeCorrector extends BaseSemanticCorrector {
|
||||
|
||||
@Override
|
||||
public void correct(SemanticCorrectInfo semanticCorrectInfo) {
|
||||
|
||||
super.correct(semanticCorrectInfo);
|
||||
|
||||
replaceAlias(semanticCorrectInfo);
|
||||
|
||||
updateFieldNameByLinkingValue(semanticCorrectInfo);
|
||||
|
||||
updateFieldValueByLinkingValue(semanticCorrectInfo);
|
||||
|
||||
correctFieldName(semanticCorrectInfo);
|
||||
}
|
||||
|
||||
private void replaceAlias(SemanticCorrectInfo semanticCorrectInfo) {
|
||||
String replaceAlias = SqlParserReplaceHelper.replaceAlias(semanticCorrectInfo.getSql());
|
||||
semanticCorrectInfo.setSql(replaceAlias);
|
||||
}
|
||||
|
||||
private void correctFieldName(SemanticCorrectInfo semanticCorrectInfo) {
|
||||
|
||||
Map<String, String> fieldNameMap = getFieldNameMap(semanticCorrectInfo.getParseInfo().getModelId());
|
||||
|
||||
String sql = SqlParserReplaceHelper.replaceFields(semanticCorrectInfo.getSql(), fieldNameMap);
|
||||
|
||||
semanticCorrectInfo.setSql(sql);
|
||||
}
|
||||
|
||||
private void updateFieldNameByLinkingValue(SemanticCorrectInfo semanticCorrectInfo) {
|
||||
List<ElementValue> linking = getLinkingValues(semanticCorrectInfo);
|
||||
if (CollectionUtils.isEmpty(linking)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, Set<String>> fieldValueToFieldNames = linking.stream().collect(
|
||||
Collectors.groupingBy(ElementValue::getFieldValue,
|
||||
Collectors.mapping(ElementValue::getFieldName, Collectors.toSet())));
|
||||
|
||||
String sql = SqlParserReplaceHelper.replaceFieldNameByValue(semanticCorrectInfo.getSql(),
|
||||
fieldValueToFieldNames);
|
||||
semanticCorrectInfo.setSql(sql);
|
||||
}
|
||||
|
||||
private List<ElementValue> getLinkingValues(SemanticCorrectInfo semanticCorrectInfo) {
|
||||
Object context = semanticCorrectInfo.getParseInfo().getProperties().get(Constants.CONTEXT);
|
||||
if (Objects.isNull(context)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
DSLParseResult dslParseResult = JsonUtil.toObject(JsonUtil.toString(context), DSLParseResult.class);
|
||||
if (Objects.isNull(dslParseResult) || Objects.isNull(dslParseResult.getLlmReq())) {
|
||||
return null;
|
||||
}
|
||||
LLMReq llmReq = dslParseResult.getLlmReq();
|
||||
return llmReq.getLinking();
|
||||
}
|
||||
|
||||
|
||||
private void updateFieldValueByLinkingValue(SemanticCorrectInfo semanticCorrectInfo) {
|
||||
List<ElementValue> linking = getLinkingValues(semanticCorrectInfo);
|
||||
if (CollectionUtils.isEmpty(linking)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, Map<String, String>> filedNameToValueMap = linking.stream().collect(
|
||||
Collectors.groupingBy(ElementValue::getFieldName,
|
||||
Collectors.mapping(ElementValue::getFieldValue, Collectors.toMap(
|
||||
oldValue -> oldValue,
|
||||
newValue -> newValue,
|
||||
(existingValue, newValue) -> newValue)
|
||||
)));
|
||||
|
||||
String sql = SqlParserReplaceHelper.replaceValue(semanticCorrectInfo.getSql(), filedNameToValueMap, false);
|
||||
semanticCorrectInfo.setSql(sql);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.tencent.supersonic.chat.corrector;
|
||||
|
||||
import com.tencent.supersonic.chat.api.pojo.SemanticCorrectInfo;
|
||||
import com.tencent.supersonic.chat.api.pojo.SemanticSchema;
|
||||
import com.tencent.supersonic.common.util.ContextUtils;
|
||||
import com.tencent.supersonic.common.util.DateUtils;
|
||||
import com.tencent.supersonic.common.util.jsqlparser.SqlParserAddHelper;
|
||||
import com.tencent.supersonic.common.util.jsqlparser.SqlParserSelectHelper;
|
||||
import com.tencent.supersonic.knowledge.service.SchemaService;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@Slf4j
|
||||
public class GroupByCorrector extends BaseSemanticCorrector {
|
||||
|
||||
@Override
|
||||
public void correct(SemanticCorrectInfo semanticCorrectInfo) {
|
||||
|
||||
super.correct(semanticCorrectInfo);
|
||||
|
||||
addGroupByFields(semanticCorrectInfo);
|
||||
|
||||
addAggregate(semanticCorrectInfo);
|
||||
}
|
||||
|
||||
private void addGroupByFields(SemanticCorrectInfo semanticCorrectInfo) {
|
||||
Long modelId = semanticCorrectInfo.getParseInfo().getModel().getModel();
|
||||
|
||||
//add dimension group by
|
||||
String sql = semanticCorrectInfo.getSql();
|
||||
SemanticSchema semanticSchema = ContextUtils.getBean(SchemaService.class).getSemanticSchema();
|
||||
Set<String> dimensions = semanticSchema.getDimensions(modelId).stream()
|
||||
.map(schemaElement -> schemaElement.getName()).collect(Collectors.toSet());
|
||||
dimensions.add(DateUtils.DATE_FIELD);
|
||||
List<String> selectFields = SqlParserSelectHelper.getSelectFields(sql);
|
||||
|
||||
if (CollectionUtils.isEmpty(selectFields) || CollectionUtils.isEmpty(dimensions)) {
|
||||
return;
|
||||
}
|
||||
List<String> aggregateFields = SqlParserSelectHelper.getAggregateFields(sql);
|
||||
Set<String> groupByFields = selectFields.stream()
|
||||
.filter(field -> dimensions.contains(field))
|
||||
.filter(field -> {
|
||||
if (!CollectionUtils.isEmpty(aggregateFields) && aggregateFields.contains(field)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.collect(Collectors.toSet());
|
||||
semanticCorrectInfo.setSql(SqlParserAddHelper.addGroupBy(sql, groupByFields));
|
||||
}
|
||||
|
||||
private void addAggregate(SemanticCorrectInfo semanticCorrectInfo) {
|
||||
List<String> sqlGroupByFields = SqlParserSelectHelper.getGroupByFields(semanticCorrectInfo.getSql());
|
||||
if (CollectionUtils.isEmpty(sqlGroupByFields)) {
|
||||
return;
|
||||
}
|
||||
addAggregateToMetric(semanticCorrectInfo);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user