41 Commits

Author SHA1 Message Date
pisces
f4be6f65ec Merge 5b45cfbad7 into 07f6be51c7 2024-12-12 11:07:08 +08:00
mislayming
07f6be51c7 SpringBoot3升级 (#1947)
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2024-12-11 17:09:20 +08:00
Jun Zhang
f6622319a4 [project]Fix centos unit tests. (#1955)
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2024-12-11 09:06:30 +08:00
Jun Zhang
4a6938956b [project]Only sanity test with JDK 21. (#1952)
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2024-12-10 21:15:38 +08:00
mislayming
848b4a1e44 (fix)(chat-api) 小范围整理一下lombok标签,增加默认构造函数避免高版本json框架无法实例化报错 (#1951) 2024-12-10 19:14:32 +08:00
mislayming
a298c670ed (improvement)(auth) 增强UserStrategy的可配置性 (#1949) 2024-12-10 19:09:22 +08:00
siriusbo
3db9a0dcec [improvement][headless-core] 提升join准确性,修复join条件错误问题 (#1945)
Some checks are pending
supersonic CentOS CI / build (11) (push) Waiting to run
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic CentOS CI / build (8) (push) Waiting to run
supersonic mac CI / build (11) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic mac CI / build (8) (push) Waiting to run
supersonic ubuntu CI / build (11) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (8) (push) Waiting to run
supersonic windows CI / build (11) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
supersonic windows CI / build (8) (push) Waiting to run
2024-12-09 22:13:27 +08:00
pisces
09ea5db0ba fix(agent): 助理管理列表切换分页后启用禁用状态展示错误 (#1946)
Some checks are pending
supersonic CentOS CI / build (11) (push) Waiting to run
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic CentOS CI / build (8) (push) Waiting to run
supersonic mac CI / build (11) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic mac CI / build (8) (push) Waiting to run
supersonic ubuntu CI / build (11) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (8) (push) Waiting to run
supersonic windows CI / build (11) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
supersonic windows CI / build (8) (push) Waiting to run
2024-12-09 18:46:52 +08:00
Jun Zhang
e55f43c737 [improvement]Use QueryWrapper in place of hard-coded SQLs (#1944)
Some checks are pending
supersonic CentOS CI / build (11) (push) Waiting to run
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic CentOS CI / build (8) (push) Waiting to run
supersonic mac CI / build (11) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic mac CI / build (8) (push) Waiting to run
supersonic ubuntu CI / build (11) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (8) (push) Waiting to run
supersonic windows CI / build (11) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
supersonic windows CI / build (8) (push) Waiting to run
* [improvement][launcher]Use API to get element ID avoiding hard-code.

* [fix][launcher]Fix mysql scripts.

* [improvement][launcher]Support DuckDB database and refactor translator code structure.

* [improvement][headless-fe] Revamped the interaction for semantic modeling routing and successfully implemented the switching between dimension and dataset management.

* [improvement][Headless] Add table ddl in Dbschema

* [improvement][Headless] Add get database by type

* [improvement][Headless] Supports automatic batch creation of models based on db table names.

* [improvement][Headless] Supports getting domain by bizName

* [improvement][launcher]Refactor unit tests and demo data.

* [fix][launcher]Change default vector dimension to 512.

* [improvement](Dict) add dimValueAliasMap info for KnowledgeBaseService

* [improvement][headless]Use QueryWrapper to replace hard-code SQL in mapper xml.

* [improvement][chat]Introduce ChatMemory to delegate ChatMemoryDO.

* [fix][common]Fix embedding store sys configs.

* [fix][common]Fix postgres schema, using varchar instead of char.

* [improvement][launcher]Change supersonic docker deployment from mysql to postgres.

* [Fix][launcher]Fix a number of issues related to semantic modeling.

* [Fix][headless]Fix the evaluation logic of agg type.

* [fix][assembly]Fix Dockerfile and add docker compose run script.

* [fix][chat]Fix "multiple assignments to same column "similar_queries".

* [improvement][headless]Use LamdaQueryWrapper to avoid hard-coded column names.

* [improvement][headless]Refactor headless infra to support advanced semantic modelling.

* [improvement][headless]Change class name `Dim` to `Dimension`.

* [improvement][chat]Introduce `TimeFieldMapper` to always map time field.

* [fix][headless]Remove unnecessary dimension existence check.

* [fix][chat]Fix adjusted filters don't take effect.

---------
2024-12-08 13:32:29 +08:00
pisces
5b45cfbad7 feat(chat-sdk/chatitem): 消息支持导出图表图片 2024-12-02 15:16:51 +08:00
Jun Zhang
0fc29304a8 [improvement][launcher]Refactor unit tests and demo data. (#1935) 2024-12-01 21:08:26 +08:00
pisces
639d1a78da perf: 在中文输入法的情况下,正在输入的过程中按下回车导致消息直接发送 (#1933) 2024-12-01 10:52:28 +08:00
Jun Zhang
82c63a7f22 [improvement][headless-fe] Revamped the interaction for semantic modeling routing and successfully implemented the switching between dimension and dataset management. (#1934)
Co-authored-by: tristanliu <tristanliu@tencent.com>
2024-11-30 20:03:41 +08:00
Jun Zhang
593597fe26 Refactor translator module (#1932)
* [improvement][Chat] Support agent permission management #1143

* [improvement][chat]Iterate LLM prompts of parsing and correction.

* [improvement][headless]Clean code logic of headless core.

* (fix) (chat) 记忆管理更新不生效 (#1912)

* [improvement][headless-fe] Added null-check conditions to the data formatting function.

* [improvement][headless]Clean code logic of headless translator.

* [improvement][headless-fe] Added permissions management for agents.

* [improvement][headless-fe] Unified the assistant's permission settings interaction to match the system style.

* [improvement](Dict)Support returns dict task list of dimensions by page

* [improvement][headless-fe] Revised the interaction for semantic modeling routing and implemented the initial version of metric management switching.

* [improvement][launcher]Set system property `s2.test` in junit tests in order to facilitate conditional breakpoints.

* [improvement][headless] add validateAndQuery interface in SqlQueryApiController

* [improvement][launcher]Use API to get element ID avoiding hard-code.

* [improvement][launcher]Support DuckDB database and refactor translator code structure.

---------

Co-authored-by: lxwcodemonkey <jolunoluo@tencent.com>
Co-authored-by: tristanliu <tristanliu@tencent.com>
Co-authored-by: daikon12 <1059907724@qq.com>
Co-authored-by: lexluo09 <39718951+lexluo09@users.noreply.github.com>
2024-11-30 00:27:33 +08:00
wangk
224c114d20 fix:重启服务后存在多个闲聊助手 (#1928) 2024-11-26 21:41:20 +08:00
Siri-Ray
722f40cdf7 (improvement)(auth) Add user email info to jwt claim (#1921) 2024-11-24 09:41:33 +08:00
Jun Zhang
cb183b7ac8 [improvement][Chat] Support agent permission management (#1923)
* [improvement][Chat] Support agent permission management #1143

* [improvement][chat]Iterate LLM prompts of parsing and correction.

* [improvement][headless-fe] Added null-check conditions to the data formatting function.

* [improvement][headless]Clean code logic of headless translator.

---------

Co-authored-by: lxwcodemonkey <jolunoluo@tencent.com>
Co-authored-by: tristanliu <tristanliu@tencent.com>
2024-11-23 09:09:04 +08:00
pisces
244052e806 fix(semanticModel): model options not exist when creating new dataset (#1919) 2024-11-22 10:37:15 +08:00
pisces
e990b37433 fix: 新建模型,存在多个度量的情况下,度量的扩展配置均会显示成第1个度量中的值; (#1909)
* fix(semantic-model): 新建模型,存在多个度量的情况下,度量的扩展配置均会显示成第1个度量中的值

* refactor(semantic-model): 新建模型,扩展配置的取值方式,find重构成解构

---------

Co-authored-by: tristanliu <37809633+sevenliu1896@users.noreply.github.com>
2024-11-20 12:04:05 +08:00
解(xie)先生🌽
534da49309 (fix) 同环比计算为null时最新日期的数据被覆盖前端显示一直为0 2024-11-18 23:10:37 +08:00
解(xie)先生🌽
5a8c20a00b (fix) (chat) 记忆管理更新不生效 (#1912) 2024-11-18 14:39:34 +08:00
Jun Zhang
e8c9855163 [improvement][launcher]Clean code logic of s2demos and remove tag-related constructs. 2024-11-16 17:23:35 +08:00
Jun Zhang
ba1938f04b Merge fixes and improvements (#1910)
Co-authored-by: tristanliu <tristanliu@tencent.com>
2024-11-16 13:57:54 +08:00
zhaodongsheng
5e22b412c6 (fix) CoreDictionaryPath Incorrect Assignment (#1903) 2024-11-14 22:34:59 +08:00
LXW
87729956e8 (improvement)(Headless) Refactor the SemanticModeller to rule first and then llm, and automatically infer field types in the rule method. (#1900)
Co-authored-by: lxwcodemonkey
2024-11-11 00:10:58 +08:00
jerryjzhang
ea6a9ebc5f [improvement][launcher]Refactor built-in demos. 2024-11-10 21:29:49 +08:00
jerryjzhang
14a19a901f [improvement][project]Simplify code logic in multiple modules. 2024-11-10 14:31:12 +08:00
lexluo09
ca4545bb15 [improvement][chat] Only vector retrieval is enabled in loose mode (#1899) 2024-11-10 10:39:17 +08:00
Jun Zhang
e0e167fd40 [improvement][chat]Refactor code logic in rule-based parsing. 2024-11-09 15:49:08 +08:00
lexluo09
d4a9d5a7e6 [fix][chat] The terms in the descriptor of the term no longer undergo descriptor mapping (#1897) 2024-11-09 14:16:55 +08:00
Jun Zhang
c9c6dc4e44 Merge a number of fixes and improvements (#1896) 2024-11-09 00:23:02 +08:00
yudong
524ec38edc [improvement][chat]记忆评估性能优化 (#1887) 2024-11-08 23:06:43 +08:00
xiao liang
9edcb9f91c chat接口,匹配数据集逻辑错误,导致智能匹配第一个数据集 (#1884) 2024-11-04 17:10:41 +08:00
jerryjzhang
6f2af79756 [improvement][chat]Move processor related logic from headless to chat. 2024-11-04 16:27:26 +08:00
tristanliu
7be885d9c8 [improvement][headless-fe] Fixed a logic error in the editing process of dimension value aliases in the question-answering dialogue of the assistant module (#1880)
* [improvement][semantic-fe] Updating the logic for the fieldName.

* [improvement][semantic-fe] Adjusting the position of the metrics tab.

* [improvement][semantic-fe] Changing the 字段名称 to 英文名称.

* [improvement][semantic-fe] Fix metric measurement deletion.

* [improvement][semantic-fe] UI optimization for metric details page.

* [improvement][semantic-fe] UI optimization for metric details page.

* [improvement][semantic-fe] UI adjustment for metric details page.

* [improvement][semantic-fe] The granularity field in the time type of model editing now supports setting it as empty.

* [improvement][semantic-fe] Added field type and metric type to the metric creation options.

* [improvement][semantic-fe] The organization structure selection feature has been added to the permission management.

* [improvement][semantic-fe] Improved user experience for the metric list.

* [improvement][semantic-fe] fix update the metric list.

* [improvement][headless-fe] Added view management functionality.

* [improvement][headless-fe] The view management functionality has been added. This feature allows users to create, edit, and manage different views within the system.

* [improvement][headless-fe] Added model editing side effect detection.

* [improvement][headless-fe] Fixed the logic error in view editing.

* [improvement][headless-fe] Fixed the issue with initializing dimension associations in metric settings.

* [improvement][headless-fe] Added the ability to hide the Q&A settings entry point.

* [improvement][headless-fe] Fixed the issue with selecting search results in metric field creation.

* [improvement][headless-fe] Added search functionality to the field list in model editing.

* [improvement][headless-fe] fix the field list in model editing

* [improvement][headless-fe] Restructured the data for the dimension value settings interface.

* [improvement][headless-fe] Added dynamic variable functionality to model creation based on SQL scripts.

* [improvement][headless-fe] Added support for passing dynamic variables as parameters in the executeSql function.

* [improvement][headless-fe] Resolved the issue where users were unable to select all options for dimensions, metrics, and fields in the metric generation process.

* [improvement][headless-fe] Replaced the term "view" with "dataset"

* [improvement][headless-fe] Added the ability to export metrics and dimensions to a specific target.

* [improvement][headless-fe] Enhanced dataset creation to support the tag mode.

* [improvement][headless-fe] Added tag value setting.

* [improvement][headless-fe] Optimized the tag setting system.

* [improvement][headless-fe] Optimized the tag setting system.

* [improvement][headless-fe] Updated the data initialization for model editing to use API requests instead.

* [improvement][headless-fe] Added search functionality to model management.

* [improvement][headless-fe] Removed field null validation during model editing.

* [improvement][headless-fe] Updated the batch operation button component.

* [improvement][headless-fe] Optimized the logic for initializing indicators in dimension value settings.

* [improvement][headless-fe] Adjusted the length of the input field for model editing names.

* [improvement][headless-fe]  Lock the version of the @ant-design/pro-table component and replace it with @ant-design/pro-components.

* [improvement][headless-fe] Optimized the style of the metrics market and tags market.

* [improvement][headless-fe] The quick creation of model fields now defaults to using the "comment" field for filling.

* [improvement][headless-fe] The quick creation of model fields now defaults to using the "comment" field for filling

* [improvement][headless-fe] The quick creation of model fields now defaults to using the "comment" field for filling.

* [improvement][headless-fe] Fixed the issue where the conditions for metric measurement creation were not being saved correctly.

* [improvement][headless-fe] Default value setting for hiding dimensions.

* [improvement][headless-fe] Updated the file imports in the project.

* [improvement][headless-fe] Adjusted the logic for displaying the tab in the theme domain.

* [improvement][headless-fe] Added term management functionality.

* [improvement][headless-fe] When creating a model, the current metric operator now allows for clearance.

* [improvement][headless-fe] Term management interface transformation

* [improvement][headless-fe] Migrating scaffold version to @umi/max

* [improvement][headless-fe] remove modle column

* [improvement][headless-fe] 1.Added configuration for the large language model in the agent; 2.upgraded React version from 17 to 18; 3.modified some UI effects.

* [improvement][headless-fe] Added a simplified mode to the question-answering system.

* [improvement][headless-fe] remove pnpm-lock

* [improvement][headless-fe] add pnpm-lock

* [improvement][headless-fe] Fixed the issue with passing the modelId during initialization.

* [improvement][headless-fe] Fixed the issue with abnormal comments during model creation.

* [improvement][headless-fe] fix  build bugs

* [improvement][headless-fe]  change build config

* [improvement][headless-fe] route config change

* [improvement][headless-fe] Optimized data updating when switching domains.

* [improvement][headless-fe] css change

* [improvement][semantic-fe] logo css change

* [improvement][semantic-fe] system config add defaultValue support

* [improvement][semantic-fe] tag mode wording change

* [improvement][semantic-fe] fix metric edit page init error

* [improvement][supersonic-fe] Updated the way chat projects are imported in supersonic-fe.

* [improvement][chat-engine] Added a background silent mode for watching chat projects.

* [improvement][supersonic-fe] fix proxy url

* [improvement][headless-fe] agent setting update

* [improvement][headless-fe] Agent configuration: Added connectivity testing for large models.

* [improvement][headless-fe] Chat: Enabled integration with agent configuration.

* [improvement][headless-fe] SQL formatter: Updated the import method.

* [improvement][headless-fe] login fixed

* [improvement][headless-fe] Agent: Optimized the logic for saving.

* [improvement][headless-fe] Model management: Integrated into the main theme domain.

* [improvement][headless-fe] Sensitivity: Added bulk modification functionality.

* [improvement][headless-fe] wording change

* [improvement][headless-fe] Prompt configuration: Added the ability to configure prompts.

* [improvement][headless-fe] Added the ability to configure embedding models.

* [improvement][headless-fe] hidden configure embedding models.

* [improvement][headless-fe] Connection test prompt update for large language model settings.

* [improvement][headless-fe]  add memory review config

* [improvement][headless-fe] Rollback of data structure for large language model configuration.

* [improvement][headless-fe] Added dependency relationships between various items in system configuration.

* [improvement][headless-fe] Added password parsing to the generation rules of system settings.

* [improvement][headless-fe] Added slider parsing to the generation rules of system settings.

* [improvement][headless-fe] Optimized the logic for initializing values in system settings.

* [improvement][headless-fe] Optimized the time format

* [improvement][headless-fe] Unified the SQL generation method for data sets to ensure consistency and improve efficiency.

* [improvement][headless-fe] Added support for data sets with non-partitioned time fields

* [improvement][headless-fe] Added support for editing time formats in dimension settings

* [improvement][headless-fe] Rolled back the time parameter in the metric details page to its previous state

* [improvement][headless-fe] Fixed the issue with hidden field validation when editing dimensions

* [improvement][headless-fe] Added a connectivity test for large models in the system settings

* [improvement][headless-fe] Changed the METRIC type in ChatContextType queryType to AGGREGATE

* [improvement][headless-fe] Added query and batch delete operations to the terminology management feature

* [improvement][headless-fe] Enhanced the memory management feature by adding sorting functionality and other optimization features.

* [improvement][headless-fe] Resolved the compatibility issue with the backend service where the updatedAt and other time fields were not being properly converted to the updated_at format for sorting purposes.

* [improvement][headless-fe] Added a configuration interface for large language models

* [improvement][headless-fe] Introduced a new configuration option in the assistant module specifically for large model applications.

* [improvement][headless-fe] Replaced the agentConfig with toolConfig

* [improvement][headless-fe] Resolved the issue with the test connection parameters for the large model configuration.

* [improvement][headless-fe] Implemented a new feature where the tool configuration types can be fetched from the backend API

* [improvement][headless-fe] Updated the dimension value settings to retrieve and display values from a dictionary.

* [improvement][headless-fe] Adjusted the pageSize of the dimension value settings list to 20.

* [improvement][headless-fe] Introduced a revamped configuration for the large model in the assistant module.

* [improvement][headless-fe] Added new functionality to the assistant's memory management system

* [improvement][headless-fe] Optimized the management of CSS styles in the assistant module.

* [improvement][headless] fixed build config

* [improvement][headless-fe] Revamped the dimension value settings in the assistant module.

* [improvement][headless-fe] Optimized the initialization process of dimension value settings in the assistant module.

* [improvement][headless-fe] Added support for user confirmation mode in the question-answering dialogue of the assistant module.

* [improvement][headless-be] As part of the ongoing improvements to the question-answering dialogue, the datasetId will now be included as a parameter in the API endpoint /api/chat/query/search for querying the question-answering dataset.

* [improvement][headless-be] Optimized the logic for intent confirmation and streamlined mode in the question-answering dialogue of the assistant module.

* [improvement][headless-be] rollback proxy config

* [improvement][headless-fe] Enhanced the display of errMsg and textSummary in the question-answering dialogue of the assistant module

* [improvement][headless-fe] Fixed a logic error in the editing process of dimension value aliases in the question-answering dialogue of the assistant module

---------

Co-authored-by: tristanliu <tristanliu@tencent.com>
2024-11-04 11:21:26 +08:00
jerryjzhang
9a05b5cce6 [improvement][headless]Deprecate and remove entity-related abstraction and logic.#1876 2024-11-04 10:17:30 +08:00
lexluo09
3b65b1c80b [improvement][headless] Remove entities from the dictionary and search interface (#1878) 2024-11-04 10:06:10 +08:00
jerryjzhang
1e5bf7909e [improvement][headless]Deprecate and remove entity-related abstraction and logic.#1876 2024-11-04 09:53:18 +08:00
lexluo09
6a4458a572 [improvement][build] Optimize pushing images through GitHub Actions (#1875) 2024-11-02 21:33:15 +08:00
lexluo09
1867447b6e [improvement][build] Support manual pushing of images through GitHub Actions (#1874) 2024-11-02 18:09:11 +08:00
jerryjzhang
ff7fb50030 [release]Kick off v0.9.10 snapshot. 2024-11-01 22:59:54 +08:00
544 changed files with 24038 additions and 32967 deletions

View File

@@ -15,11 +15,17 @@ jobs:
strategy:
matrix:
java-version: [8, 11, 21] # 定义要测试的JDK版本
java-version: [21] # 定义要测试的JDK版本
steps:
- uses: actions/checkout@v2
- name: Set up JDK ${{ matrix.java-version }}
uses: actions/setup-java@v2
with:
java-version: ${{ matrix.java-version }}
distribution: 'adopt'
- name: Reset DNF repositories
run: |
cd /etc/yum.repos.d/
@@ -29,21 +35,11 @@ jobs:
- name: Update DNF package index
run: dnf makecache
- name: Install Java and Maven with retry
- name: Install Maven with retry
run: |
if [ ${{ matrix.java-version }} -eq 8 ]; then
for i in {1..5}; do
dnf install -y java-1.8.0-openjdk-devel maven && break || sleep 15
done
elif [ ${{ matrix.java-version }} -eq 11 ]; then
for i in {1..5}; do
dnf install -y java-11-openjdk-devel maven && break || sleep 15
done
elif [ ${{ matrix.java-version }} -eq 21 ]; then
for i in {1..5}; do
dnf install -y java-21-openjdk-devel maven && break || sleep 15
done
fi
for i in {1..5}; do
dnf install -y maven && break || sleep 15
done
- name: Verify Java and Maven installation
run: |
@@ -61,4 +57,5 @@ jobs:
run: mvn -B package --file pom.xml
- name: Test with Maven
run: mvn test
run: mvn test

34
.github/workflows/docker-publish.yml vendored Normal file
View File

@@ -0,0 +1,34 @@
name: Docker Publish
on:
workflow_dispatch:
inputs:
version:
description: 'Version of the Docker image'
required: true
default: 'latest'
jobs:
build-and-publish:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Log in to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and publish Docker image
run: |
VERSION=${{ github.event.inputs.version }}
chmod +x docker/docker-build.sh
chmod +x docker/docker-publish.sh
sh docker/docker-build.sh $VERSION
sh docker/docker-publish.sh $VERSION

View File

@@ -14,7 +14,7 @@ jobs:
strategy:
matrix:
java-version: [8, 11, 21] # Define the JDK versions to test
java-version: [21] # Define the JDK versions to test
steps:
- uses: actions/checkout@v2

View File

@@ -14,7 +14,7 @@ jobs:
strategy:
matrix:
java-version: [8, 11, 21] # 定义要测试的JDK版本
java-version: [21] # 定义要测试的JDK版本
steps:
- uses: actions/checkout@v2

View File

@@ -14,7 +14,7 @@ jobs:
strategy:
matrix:
java-version: [8, 11, 21] # Add JDK 21 to the matrix
java-version: [21] # Add JDK 21 to the matrix
steps:
- uses: actions/checkout@v2

View File

@@ -7,11 +7,11 @@
## SuperSonic [0.9.8] - 2024-11-01
- Add LLM management module to reuse connection across agents.
- Add ChatAPP configuration sub-module in Agent Management.
- Add dimension value management sub-module.
- Enhance dimension value management sub-module.
- Enhance memory management and term management sub-module.
- Support semantic translation of complex S2SQL.
- Enhance semantic translation of complex S2SQL.
- Enhance user experience in Chat UI.
- Introduce LLM-based semantic corrector and data interpreter.
- Introduce new experience in Chat UI.
## SuperSonic [0.9.2] - 2024-06-01

View File

@@ -4,7 +4,7 @@
# SuperSonic
SuperSonic is the next-generation BI platform that unifies **Chat BI** (powered by LLM) and **Headless BI** (powered by semantic layer) paradigms. This unification ensures that Chat BI has access to the same curated and governed semantic data models as traditional BI. Furthermore, the implementation of both paradigms benefit from each other:
SuperSonic is the next-generation AI+BI platform that unifies **Chat BI** (powered by LLM) and **Headless BI** (powered by semantic layer) paradigms. This unification ensures that Chat BI has access to the same curated and governed semantic data models as traditional BI. Furthermore, the implementation of both paradigms benefit from each other:
- Chat BI's Text2SQL gets augmented with context-retrieval from semantic models.
- Headless BI's query interface gets extended with natural language API.

View File

@@ -4,7 +4,13 @@ sbinDir=$(cd "$(dirname "$0")"; pwd)
chmod +x $sbinDir/supersonic-common.sh
source $sbinDir/supersonic-common.sh
cd $projectDir
MVN_VERSION=$(mvn help:evaluate -Dexpression=project.version | grep -e '^[^\[]')
MVN_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout | grep -v '^\[' | sed -n '/^[0-9]/p')
if [ -z "$MVN_VERSION" ]; then
echo "Failed to retrieve Maven project version."
exit 1
fi
echo "Maven project version: $MVN_VERSION"
cd $baseDir
service=$1

View File

@@ -1,11 +1,11 @@
package com.tencent.supersonic.auth.api.authentication.adaptor;
import javax.servlet.http.HttpServletRequest;
import com.tencent.supersonic.auth.api.authentication.pojo.Organization;
import com.tencent.supersonic.auth.api.authentication.pojo.UserToken;
import com.tencent.supersonic.auth.api.authentication.request.UserReq;
import com.tencent.supersonic.common.pojo.User;
import jakarta.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Set;

View File

@@ -18,6 +18,9 @@ public class AuthenticationConfig {
@Value("${s2.authentication.include.path:/api}")
private String includePath;
@Value("${s2.authentication.strategy:http}")
private String strategy;
@Value("${s2.authentication.enable:false}")
private boolean enabled;

View File

@@ -11,6 +11,7 @@ import java.util.Map;
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_USER_DISPLAY_NAME;
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_USER_EMAIL;
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_USER_ID;
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_USER_NAME;
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_USER_PASSWORD;
@@ -38,6 +39,7 @@ public class UserWithPassword extends User {
claims.put(TOKEN_USER_NAME, StringUtils.isEmpty(user.getName()) ? "" : user.getName());
claims.put(TOKEN_USER_PASSWORD,
StringUtils.isEmpty(user.getPassword()) ? "" : user.getPassword());
claims.put(TOKEN_USER_EMAIL, StringUtils.isEmpty(user.getEmail()) ? "" : user.getEmail());
claims.put(TOKEN_USER_DISPLAY_NAME, user.getDisplayName());
claims.put(TOKEN_CREATE_TIME, System.currentTimeMillis());
claims.put(TOKEN_IS_ADMIN, user.getIsAdmin());

View File

@@ -1,7 +1,7 @@
package com.tencent.supersonic.auth.api.authentication.request;
import javax.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
@Data

View File

@@ -1,7 +1,6 @@
package com.tencent.supersonic.auth.api.authentication.request;
import javax.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
@Data

View File

@@ -1,12 +1,13 @@
package com.tencent.supersonic.auth.api.authentication.service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.tencent.supersonic.auth.api.authentication.pojo.Organization;
import com.tencent.supersonic.auth.api.authentication.pojo.UserToken;
import com.tencent.supersonic.auth.api.authentication.request.UserReq;
import com.tencent.supersonic.common.pojo.User;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Set;

View File

@@ -1,12 +1,13 @@
package com.tencent.supersonic.auth.api.authentication.service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.tencent.supersonic.common.pojo.User;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
public interface UserStrategy {
String getStrategyName();
boolean accept(boolean isEnableAuthentication);
User findUser(HttpServletRequest request, HttpServletResponse response);

View File

@@ -1,13 +1,12 @@
package com.tencent.supersonic.auth.api.authentication.utils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.tencent.supersonic.auth.api.authentication.service.UserStrategy;
import com.tencent.supersonic.common.config.SystemConfig;
import com.tencent.supersonic.common.pojo.User;
import com.tencent.supersonic.common.service.SystemConfigService;
import com.tencent.supersonic.common.util.ContextUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.util.CollectionUtils;
public final class UserHolder {

View File

@@ -1,7 +1,5 @@
package com.tencent.supersonic.auth.authentication.adaptor;
import javax.servlet.http.HttpServletRequest;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.tencent.supersonic.auth.api.authentication.adaptor.UserAdaptor;
@@ -16,6 +14,7 @@ import com.tencent.supersonic.auth.authentication.utils.TokenService;
import com.tencent.supersonic.common.pojo.User;
import com.tencent.supersonic.common.util.AESEncryptionUtil;
import com.tencent.supersonic.common.util.ContextUtils;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

View File

@@ -1,12 +1,11 @@
package com.tencent.supersonic.auth.authentication.interceptor;
import javax.servlet.http.HttpServletRequest;
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
import com.tencent.supersonic.auth.api.authentication.constant.UserConstants;
import com.tencent.supersonic.auth.authentication.service.UserServiceImpl;
import com.tencent.supersonic.auth.authentication.utils.TokenService;
import com.tencent.supersonic.common.util.S2ThreadContext;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.RequestFacade;
import org.apache.commons.lang3.StringUtils;

View File

@@ -1,8 +1,5 @@
package com.tencent.supersonic.auth.authentication.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.tencent.supersonic.auth.api.authentication.annotation.AuthenticationIgnore;
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
import com.tencent.supersonic.auth.api.authentication.pojo.UserWithPassword;
@@ -14,6 +11,8 @@ import com.tencent.supersonic.common.util.ContextUtils;
import com.tencent.supersonic.common.util.S2ThreadContext;
import com.tencent.supersonic.common.util.ThreadContext;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.method.HandlerMethod;

View File

@@ -51,7 +51,7 @@ public class UserRepositoryImpl implements UserRepository {
@Override
public List<UserTokenDO> getUserTokenListByName(String userName) {
QueryWrapper<UserTokenDO> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("user_name", userName);
queryWrapper.lambda().eq(UserTokenDO::getUserName, userName);
return userTokenDOMapper.selectList(queryWrapper);
}
@@ -68,7 +68,7 @@ public class UserRepositoryImpl implements UserRepository {
@Override
public void deleteUserTokenByName(String userName) {
QueryWrapper<UserTokenDO> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("user_name", userName);
queryWrapper.lambda().eq(UserTokenDO::getUserName, userName);
userTokenDOMapper.delete(queryWrapper);
}

View File

@@ -1,14 +1,13 @@
package com.tencent.supersonic.auth.authentication.rest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.tencent.supersonic.auth.api.authentication.pojo.Organization;
import com.tencent.supersonic.auth.api.authentication.pojo.UserToken;
import com.tencent.supersonic.auth.api.authentication.request.UserReq;
import com.tencent.supersonic.auth.api.authentication.request.UserTokenReq;
import com.tencent.supersonic.auth.api.authentication.service.UserService;
import com.tencent.supersonic.common.pojo.User;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

View File

@@ -1,8 +1,5 @@
package com.tencent.supersonic.auth.authentication.service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.tencent.supersonic.auth.api.authentication.pojo.Organization;
import com.tencent.supersonic.auth.api.authentication.pojo.UserToken;
import com.tencent.supersonic.auth.api.authentication.request.UserReq;
@@ -12,6 +9,8 @@ import com.tencent.supersonic.auth.authentication.utils.ComponentFactory;
import com.tencent.supersonic.common.config.SystemConfig;
import com.tencent.supersonic.common.pojo.User;
import com.tencent.supersonic.common.service.SystemConfigService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

View File

@@ -1,15 +1,21 @@
package com.tencent.supersonic.auth.authentication.strategy;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.tencent.supersonic.auth.api.authentication.service.UserStrategy;
import com.tencent.supersonic.common.pojo.User;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Service;
@Service
public class FakeUserStrategy implements UserStrategy {
public static final String STRATEGY_NAME = "fake";
@Override
public String getStrategyName() {
return STRATEGY_NAME;
}
@Override
public boolean accept(boolean isEnableAuthentication) {
return !isEnableAuthentication;

View File

@@ -1,13 +1,12 @@
package com.tencent.supersonic.auth.authentication.strategy;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.tencent.supersonic.auth.api.authentication.constant.UserConstants;
import com.tencent.supersonic.auth.api.authentication.service.UserStrategy;
import com.tencent.supersonic.auth.authentication.utils.TokenService;
import com.tencent.supersonic.common.pojo.User;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Service;
import java.util.Optional;
@@ -15,12 +14,18 @@ import java.util.Optional;
@Service
public class HttpHeaderUserStrategy implements UserStrategy {
public static final String STRATEGY_NAME = "http";
private final TokenService tokenService;
public HttpHeaderUserStrategy(TokenService tokenService) {
this.tokenService = tokenService;
}
@Override
public String getStrategyName() {
return STRATEGY_NAME;
}
@Override
public boolean accept(boolean isEnableAuthentication) {
return isEnableAuthentication;

View File

@@ -1,14 +1,15 @@
package com.tencent.supersonic.auth.authentication.strategy;
import javax.annotation.PostConstruct;
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
import com.tencent.supersonic.auth.api.authentication.service.UserStrategy;
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
import jakarta.annotation.PostConstruct;
import lombok.Data;
import org.springframework.context.annotation.Configuration;
import java.util.List;
import java.util.Optional;
@Configuration
@Data
@@ -26,10 +27,26 @@ public class UserStrategyFactory {
@PostConstruct
public void setUserStrategy() {
for (UserStrategy userStrategy : userStrategyList) {
if (userStrategy.accept(authenticationConfig.isEnabled())) {
UserHolder.setStrategy(userStrategy);
boolean enabled = authenticationConfig.isEnabled();
if (!enabled) {
for (UserStrategy userStrategy : userStrategyList) {
if (userStrategy.accept(authenticationConfig.isEnabled())) {
UserHolder.setStrategy(userStrategy);
}
}
return;
}
String strategy = authenticationConfig.getStrategy();
Optional<UserStrategy> strategyOptional = userStrategyList.stream()
.filter(t -> t.accept(true) && strategy.equalsIgnoreCase(t.getStrategyName()))
.findAny();
if (strategyOptional.isPresent()) {
UserHolder.setStrategy(strategyOptional.get());
} else {
throw new IllegalStateException("strategy is not found: " + strategy);
}
}
}

View File

@@ -1,7 +1,8 @@
package com.tencent.supersonic.auth.authentication.utils;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
import com.tencent.supersonic.auth.api.authentication.pojo.UserWithPassword;
@@ -9,6 +10,7 @@ import com.tencent.supersonic.common.pojo.exception.AccessException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

View File

@@ -12,8 +12,8 @@
<artifactId>auth-authorization</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
</properties>
<dependencies>

View File

@@ -1,14 +1,13 @@
package com.tencent.supersonic.auth.authorization.rest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
import com.tencent.supersonic.auth.api.authorization.pojo.AuthGroup;
import com.tencent.supersonic.auth.api.authorization.request.QueryAuthResReq;
import com.tencent.supersonic.auth.api.authorization.response.AuthorizedResourceResp;
import com.tencent.supersonic.auth.api.authorization.service.AuthService;
import com.tencent.supersonic.common.pojo.User;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

View File

@@ -8,7 +8,6 @@ import java.util.List;
/** extended information command about model */
@Data
@ToString
public class ChatConfigBaseReq {
private Long modelId;

View File

@@ -1,12 +1,17 @@
package com.tencent.supersonic.chat.api.pojo.request;
import javax.validation.constraints.NotNull;
import com.tencent.supersonic.chat.api.pojo.enums.MemoryReviewResult;
import com.tencent.supersonic.chat.api.pojo.enums.MemoryStatus;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ChatMemoryUpdateReq {
@NotNull(message = "id不可为空")

View File

@@ -1,22 +0,0 @@
package com.tencent.supersonic.chat.api.pojo.request;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.util.List;
/** the entity info about the model */
@Data
@AllArgsConstructor
@ToString
@NoArgsConstructor
public class Entity {
/** uniquely identifies an entity */
private Long entityId;
/** entity name list */
private List<String> names;
}

View File

@@ -4,7 +4,6 @@ import lombok.Data;
import lombok.ToString;
@Data
@ToString
public class ItemNameVisibility {
private ItemNameVisibilityInfo aggVisibilityInfo;

View File

@@ -7,7 +7,6 @@ import java.util.ArrayList;
import java.util.List;
@Data
@ToString
public class ItemNameVisibilityInfo {
/** invisible dimensions */

View File

@@ -7,7 +7,6 @@ import java.util.ArrayList;
import java.util.List;
@Data
@ToString
public class ItemVisibility {
/** invisible dimensions */

View File

@@ -1,8 +1,7 @@
package com.tencent.supersonic.chat.api.pojo.request;
import javax.validation.constraints.NotNull;
import com.tencent.supersonic.common.pojo.enums.TypeEnums;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/** information about dictionary about the model */

View File

@@ -6,7 +6,6 @@ import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class RecommendedQuestionReq {

View File

@@ -6,7 +6,6 @@ import lombok.ToString;
import java.util.Date;
@ToString
@Data
public class DictLatestTaskResp {

View File

@@ -1,14 +0,0 @@
package com.tencent.supersonic.chat.api.pojo.response;
import com.tencent.supersonic.headless.api.pojo.SchemaElement;
import lombok.Data;
import java.util.List;
@Data
public class EntityRichInfoResp {
/** entity alias */
private List<String> names;
private SchemaElement dimItem;
}

View File

@@ -3,7 +3,6 @@ package com.tencent.supersonic.chat.api.pojo.response;
import com.tencent.supersonic.common.pojo.QueryAuthorization;
import com.tencent.supersonic.common.pojo.QueryColumn;
import com.tencent.supersonic.headless.api.pojo.AggregateInfo;
import com.tencent.supersonic.headless.api.pojo.EntityInfo;
import com.tencent.supersonic.headless.api.pojo.SchemaElement;
import com.tencent.supersonic.headless.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.headless.api.pojo.response.QueryState;
@@ -26,7 +25,6 @@ public class QueryResult {
private String textResult;
private String textSummary;
private Long queryTimeCost;
private EntityInfo entityInfo;
private List<SchemaElement> recommendedDimensions;
private AggregateInfo aggregateInfo;
private String errorMsg;

View File

@@ -3,10 +3,12 @@ package com.tencent.supersonic.chat.api.pojo.response;
import com.tencent.supersonic.chat.api.pojo.request.RecommendedQuestionReq;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RecommendQuestionResp {
private Long modelId;

View File

@@ -1,10 +1,14 @@
package com.tencent.supersonic.chat.api.pojo.response;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SimilarQueryRecallResp {
private Long queryId;

View File

@@ -1,9 +1,11 @@
package com.tencent.supersonic.chat.server.agent;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.tencent.supersonic.chat.server.memory.MemoryReviewTask;
import com.tencent.supersonic.common.pojo.ChatApp;
import com.tencent.supersonic.common.pojo.RecordInfo;
import com.tencent.supersonic.common.pojo.User;
import lombok.Data;
import org.springframework.util.CollectionUtils;
@@ -12,6 +14,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
@Data
@@ -33,6 +36,8 @@ public class Agent extends RecordInfo {
private String toolConfig;
private Map<String, ChatApp> chatAppConfig = Collections.emptyMap();
private VisualConfig visualConfig;
private List<String> admins = Lists.newArrayList();
private List<String> viewers = Lists.newArrayList();
public List<String> getTools(AgentToolType type) {
Map<String, Object> map = JSONObject.parseObject(toolConfig, Map.class);
@@ -105,4 +110,9 @@ public class Agent extends RecordInfo {
.filter(dataSetIds -> !CollectionUtils.isEmpty(dataSetIds))
.flatMap(Collection::stream).collect(Collectors.toSet());
}
public boolean contains(User user, Function<Agent, List<String>> list) {
return list.apply(this).contains(user.getName());
}
}

View File

@@ -26,7 +26,7 @@ import java.util.stream.Collectors;
public class PlainTextExecutor implements ChatQueryExecutor {
public static final String APP_KEY = "SMALL_TALK";
private static final String INSTRUCTION = "" + "#Role: You are a nice person to talk to."
private static final String INSTRUCTION = "#Role: You are a nice person to talk to."
+ "\n#Task: Respond quickly and nicely to the user."
+ "\n#Rules: 1.ALWAYS use the same language as the `#Current Input`."
+ "\n#History Inputs: %s" + "\n#Current Input: %s" + "\n#Response: ";

View File

@@ -2,8 +2,8 @@ package com.tencent.supersonic.chat.server.executor;
import com.tencent.supersonic.chat.api.pojo.enums.MemoryStatus;
import com.tencent.supersonic.chat.api.pojo.response.QueryResult;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatMemoryDO;
import com.tencent.supersonic.chat.server.pojo.ChatContext;
import com.tencent.supersonic.chat.server.pojo.ChatMemory;
import com.tencent.supersonic.chat.server.pojo.ExecuteContext;
import com.tencent.supersonic.chat.server.service.ChatContextService;
import com.tencent.supersonic.chat.server.service.MemoryService;
@@ -44,7 +44,7 @@ public class SqlExecutor implements ChatQueryExecutor {
Text2SQLExemplar.class);
MemoryService memoryService = ContextUtils.getBean(MemoryService.class);
memoryService.createMemory(ChatMemoryDO.builder()
memoryService.createMemory(ChatMemory.builder()
.agentId(executeContext.getAgent().getId()).status(MemoryStatus.PENDING)
.question(exemplar.getQuestion()).sideInfo(exemplar.getSideInfo())
.dbSchema(exemplar.getDbSchema()).s2sql(exemplar.getSql())

View File

@@ -1,8 +1,10 @@
package com.tencent.supersonic.chat.server.memory;
import com.tencent.supersonic.chat.api.pojo.enums.MemoryReviewResult;
import com.tencent.supersonic.chat.api.pojo.enums.MemoryStatus;
import com.tencent.supersonic.chat.api.pojo.request.ChatMemoryFilter;
import com.tencent.supersonic.chat.server.agent.Agent;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatMemoryDO;
import com.tencent.supersonic.chat.server.pojo.ChatMemory;
import com.tencent.supersonic.chat.server.service.AgentService;
import com.tencent.supersonic.chat.server.service.MemoryService;
import com.tencent.supersonic.common.pojo.ChatApp;
@@ -21,6 +23,7 @@ import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -57,24 +60,36 @@ public class MemoryReviewTask {
@Scheduled(fixedDelay = 60 * 1000)
public void review() {
memoryService.getMemoriesForLlmReview().stream().forEach(memory -> {
try {
processMemory(memory);
} catch (Exception e) {
log.error("Exception occurred while processing memory with id {}: {}",
memory.getId(), e.getMessage(), e);
List<Agent> agentList = agentService.getAgents();
for (Agent agent : agentList) {
if (!agent.enableMemoryReview()) {
continue;
}
});
ChatMemoryFilter chatMemoryFilter =
ChatMemoryFilter.builder().agentId(agent.getId()).build();
memoryService.getMemories(chatMemoryFilter).forEach(memory -> {
try {
processMemory(memory, agent);
} catch (Exception e) {
log.error("Exception occurred while processing memory with id {}: {}",
memory.getId(), e.getMessage(), e);
}
});
}
}
private void processMemory(ChatMemoryDO m) {
Agent chatAgent = agentService.getAgent(m.getAgentId());
if (Objects.isNull(chatAgent)) {
private void processMemory(ChatMemory m, Agent agent) {
if (Objects.isNull(agent)) {
log.warn("Agent id {} not found or memory review disabled", m.getAgentId());
return;
}
ChatApp chatApp = chatAgent.getChatAppConfig().get(APP_KEY);
// if either LLM or human has reviewed, just return
if (Objects.nonNull(m.getLlmReviewRet()) || Objects.nonNull(m.getHumanReviewRet())) {
return;
}
ChatApp chatApp = agent.getChatAppConfig().get(APP_KEY);
if (Objects.isNull(chatApp) || !chatApp.isEnable()) {
return;
}
@@ -90,23 +105,23 @@ public class MemoryReviewTask {
response);
processResponse(response, m);
} else {
log.debug("ChatLanguageModel not found for agent:{}", chatAgent.getId());
log.debug("ChatLanguageModel not found for agent:{}", agent.getId());
}
}
private String createPromptString(ChatMemoryDO m, String promptTemplate) {
private String createPromptString(ChatMemory m, String promptTemplate) {
return String.format(promptTemplate, m.getQuestion(), m.getDbSchema(), m.getSideInfo(),
m.getS2sql());
}
private void processResponse(String response, ChatMemoryDO m) {
private void processResponse(String response, ChatMemory m) {
Matcher matcher = OUTPUT_PATTERN.matcher(response);
if (matcher.find()) {
m.setLlmReviewRet(MemoryReviewResult.getMemoryReviewResult(matcher.group(1)));
m.setLlmReviewCmt(matcher.group(2));
// directly enable memory if the LLM determines it positive
if (MemoryReviewResult.POSITIVE.equals(m.getLlmReviewRet())) {
memoryService.enableMemory(m);
m.setStatus(MemoryStatus.ENABLED);
}
memoryService.updateMemory(m);
}

View File

@@ -83,11 +83,15 @@ public class NL2SQLParser implements ChatQueryParser {
if (Objects.isNull(parseContext.getRequest().getSelectedParse())) {
QueryNLReq queryNLReq = QueryReqConverter.buildQueryNLReq(parseContext);
queryNLReq.setText2SQLType(Text2SQLType.ONLY_RULE);
if (parseContext.enableLLM()) {
queryNLReq.setText2SQLType(Text2SQLType.NONE);
}
// for every requested dataSet, recursively invoke rule-based parser with different
// mapModes
Set<Long> requestedDatasets = queryNLReq.getDataSetIds();
List<SemanticParseInfo> candidateParses = Lists.newArrayList();
StringBuilder errMsg = new StringBuilder();
for (Long datasetId : requestedDatasets) {
queryNLReq.setDataSetIds(Collections.singleton(datasetId));
ChatParseResp parseResp = new ChatParseResp(parseContext.getRequest().getQueryId());
@@ -100,6 +104,10 @@ public class NL2SQLParser implements ChatQueryParser {
queryNLReq.setMapModeEnum(MapModeEnum.LOOSE);
doParse(queryNLReq, parseResp);
}
if (parseResp.getSelectedParses().isEmpty()) {
errMsg.append(parseResp.getErrorMsg());
continue;
}
// for one dataset select the top 1 parse after sorting
SemanticParseInfo.sort(parseResp.getSelectedParses());
candidateParses.add(parseResp.getSelectedParses().get(0));
@@ -110,6 +118,10 @@ public class NL2SQLParser implements ChatQueryParser {
SemanticParseInfo.sort(candidateParses);
parseContext.getResponse().setSelectedParses(
candidateParses.subList(0, Math.min(parserShowCount, candidateParses.size())));
if (parseContext.getResponse().getSelectedParses().isEmpty()) {
parseContext.getResponse().setState(ParseResp.ParseState.FAILED);
parseContext.getResponse().setErrorMsg(errMsg.toString());
}
}
// next go with llm-based parsers unless LLM is disabled or use feedback is needed.

View File

@@ -40,4 +40,8 @@ public class AgentDO {
private String chatModelConfig;
private String visualConfig;
private String admin;
private String viewer;
}

View File

@@ -1,5 +1,8 @@
package com.tencent.supersonic.chat.server.persistence.dataobject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.ToString;
@@ -7,9 +10,10 @@ import java.util.Date;
@Data
@ToString
@TableName("s2_chat_config")
public class ChatConfigDO {
/** database auto-increment primary key */
@TableId(type = IdType.AUTO)
private Long id;
private Long modelId;

View File

@@ -1,16 +1,22 @@
package com.tencent.supersonic.chat.server.persistence.dataobject;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
import java.time.Instant;
@Data
@TableName("s2_chat_context")
public class ChatContextDO implements Serializable {
@TableId
private Integer chatId;
private Instant modifiedAt;
private String user;
@TableField("query_user")
private String queryUser;
private String queryText;
private String semanticParse;
}

View File

@@ -4,17 +4,17 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.tencent.supersonic.chat.api.pojo.enums.MemoryReviewResult;
import com.tencent.supersonic.chat.api.pojo.enums.MemoryStatus;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.ToString;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
@TableName("s2_chat_memory")
public class ChatMemoryDO {
@TableId(type = IdType.AUTO)
@@ -36,16 +36,16 @@ public class ChatMemoryDO {
private String s2sql;
@TableField("status")
private MemoryStatus status;
private String status;
@TableField("llm_review")
private MemoryReviewResult llmReviewRet;
private String llmReviewRet;
@TableField("llm_comment")
private String llmReviewCmt;
@TableField("human_review")
private MemoryReviewResult humanReviewRet;
private String humanReviewRet;
@TableField("human_comment")
private String humanReviewCmt;

View File

@@ -5,9 +5,6 @@ import lombok.Data;
@Data
public class QueryDO {
public String aggregator = "trend";
public String startTime;
public String endTime;
private long id;
private long questionId;
private String createTime;
@@ -25,7 +22,6 @@ public class QueryDO {
private int topNum;
private String querySql;
private Object queryColumn;
private Object entityInfo;
private int score;
private String feedback;
}

View File

@@ -1,5 +1,6 @@
package com.tencent.supersonic.chat.server.persistence.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tencent.supersonic.chat.server.config.ChatConfigFilterInternal;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatConfigDO;
import org.apache.ibatis.annotations.Mapper;
@@ -7,11 +8,7 @@ import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface ChatConfigMapper {
Long addConfig(ChatConfigDO chaConfigPO);
Long editConfig(ChatConfigDO chaConfigPO);
public interface ChatConfigMapper extends BaseMapper<ChatConfigDO> {
List<ChatConfigDO> search(ChatConfigFilterInternal filterInternal);

View File

@@ -1,14 +1,11 @@
package com.tencent.supersonic.chat.server.persistence.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatContextDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ChatContextMapper {
public interface ChatContextMapper extends BaseMapper<ChatContextDO> {
ChatContextDO getContextByChatId(Integer chatId);
int updateContext(ChatContextDO contextDO);
int addContext(ChatContextDO contextDO);
}

View File

@@ -32,15 +32,15 @@ public class ChatConfigRepositoryImpl implements ChatConfigRepository {
@Override
public Long createConfig(ChatConfig chaConfig) {
ChatConfigDO chaConfigDO = chatConfigHelper.chatConfig2DO(chaConfig);
chatConfigMapper.addConfig(chaConfigDO);
chatConfigMapper.insert(chaConfigDO);
return chaConfigDO.getId();
}
@Override
public Long updateConfig(ChatConfig chaConfig) {
ChatConfigDO chaConfigDO = chatConfigHelper.chatConfig2DO(chaConfig);
return chatConfigMapper.editConfig(chaConfigDO);
chatConfigMapper.updateById(chaConfigDO);
return chaConfigDO.getId();
}
@Override

View File

@@ -35,18 +35,13 @@ public class ChatContextRepositoryImpl implements ChatContextRepository {
@Override
public void updateContext(ChatContext chatCtx) {
ChatContextDO context = cast(chatCtx);
if (chatContextMapper.getContextByChatId(chatCtx.getChatId()) == null) {
chatContextMapper.addContext(context);
} else {
chatContextMapper.updateContext(context);
}
chatContextMapper.insertOrUpdate(cast(chatCtx));
}
private ChatContext cast(ChatContextDO contextDO) {
ChatContext chatContext = new ChatContext();
chatContext.setChatId(contextDO.getChatId());
chatContext.setUser(contextDO.getUser());
chatContext.setUser(contextDO.getQueryUser());
chatContext.setQueryText(contextDO.getQueryText());
if (contextDO.getSemanticParse() != null && !contextDO.getSemanticParse().isEmpty()) {
SemanticParseInfo semanticParseInfo =
@@ -60,7 +55,7 @@ public class ChatContextRepositoryImpl implements ChatContextRepository {
ChatContextDO chatContextDO = new ChatContextDO();
chatContextDO.setChatId(chatContext.getChatId());
chatContextDO.setQueryText(chatContext.getQueryText());
chatContextDO.setUser(chatContext.getUser());
chatContextDO.setQueryUser(chatContext.getUser());
if (chatContext.getParseInfo() != null) {
Gson g = new Gson();
chatContextDO.setSemanticParse(g.toJson(chatContext.getParseInfo()));

View File

@@ -20,7 +20,6 @@ import com.tencent.supersonic.chat.server.persistence.repository.ChatQueryReposi
import com.tencent.supersonic.common.util.JsonUtil;
import com.tencent.supersonic.common.util.PageUtils;
import com.tencent.supersonic.headless.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.headless.api.pojo.response.ParseResp;
import com.tencent.supersonic.headless.api.pojo.response.ParseTimeCostResp;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

View File

@@ -7,7 +7,7 @@ import java.util.Map;
public class PluginQueryManager {
private static Map<String, PluginSemanticQuery> pluginQueries = new HashMap<>();
private static final Map<String, PluginSemanticQuery> pluginQueries = new HashMap<>();
public static void register(String queryMode, PluginSemanticQuery pluginSemanticQuery) {
pluginQueries.put(queryMode, pluginSemanticQuery);

View File

@@ -0,0 +1,48 @@
package com.tencent.supersonic.chat.server.pojo;
import com.tencent.supersonic.chat.api.pojo.enums.MemoryReviewResult;
import com.tencent.supersonic.chat.api.pojo.enums.MemoryStatus;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.util.Date;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class ChatMemory {
private Long id;
private Integer agentId;
private String question;
private String sideInfo;
private String dbSchema;
private String s2sql;
private MemoryStatus status;
private MemoryReviewResult llmReviewRet;
private String llmReviewCmt;
private MemoryReviewResult humanReviewRet;
private String humanReviewCmt;
private String createdBy;
private Date createdAt;
private String updatedBy;
private Date updatedAt;
}

View File

@@ -117,8 +117,12 @@ public class MetricRatioCalcProcessor implements ExecuteResultProcessor {
CompletableFuture.allOf(metricInfoRoll, metricInfoOver).join();
metricInfo.setName(metricInfoRoll.get().getName());
metricInfo.setValue(metricInfoRoll.get().getValue());
if (metricInfoRoll.get().getName() != null) {
metricInfo.setName(metricInfoRoll.get().getName());
}
if (metricInfoOver.get().getValue() != null) {
metricInfo.setValue(metricInfoRoll.get().getValue());
}
metricInfo.getStatistics().putAll(metricInfoRoll.get().getStatistics());
metricInfo.getStatistics().putAll(metricInfoOver.get().getStatistics());

View File

@@ -39,7 +39,8 @@ public class MetricRecommendProcessor implements ExecuteResultProcessor {
}
private void fillSimilarMetric(SemanticParseInfo parseInfo) {
if (!parseInfo.getQueryType().equals(QueryType.AGGREGATE)
if (Objects.isNull(parseInfo.getQueryType())
|| !parseInfo.getQueryType().equals(QueryType.AGGREGATE)
|| parseInfo.getMetrics().size() > METRIC_RECOMMEND_SIZE
|| CollectionUtils.isEmpty(parseInfo.getMetrics())) {
return;

View File

@@ -1,13 +1,30 @@
package com.tencent.supersonic.chat.server.processor.parse;
import com.tencent.supersonic.chat.server.plugin.PluginQueryManager;
import com.google.common.collect.Lists;
import com.tencent.supersonic.chat.server.pojo.ParseContext;
import com.tencent.supersonic.common.jsqlparser.FieldExpression;
import com.tencent.supersonic.common.jsqlparser.SqlSelectFunctionHelper;
import com.tencent.supersonic.common.jsqlparser.SqlSelectHelper;
import com.tencent.supersonic.common.pojo.DateConf;
import com.tencent.supersonic.common.pojo.enums.FilterOperatorEnum;
import com.tencent.supersonic.common.pojo.enums.QueryType;
import com.tencent.supersonic.common.pojo.enums.TimeDimensionEnum;
import com.tencent.supersonic.common.util.ContextUtils;
import com.tencent.supersonic.headless.api.pojo.DataSetSchema;
import com.tencent.supersonic.headless.api.pojo.SchemaElement;
import com.tencent.supersonic.headless.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.headless.api.pojo.SqlInfo;
import com.tencent.supersonic.headless.api.pojo.request.QueryFilter;
import com.tencent.supersonic.headless.server.facade.service.SemanticLayerService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.util.CollectionUtils;
import java.util.Arrays;
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;
@@ -15,20 +32,21 @@ import java.util.stream.Collectors;
/**
* ParseInfoFormatProcessor formats parse info to make it more readable to the users.
**/
@Slf4j
public class ParseInfoFormatProcessor implements ParseResultProcessor {
@Override
public void process(ParseContext parseContext) {
parseContext.getResponse().getSelectedParses().forEach(p -> {
if (PluginQueryManager.isPluginQuery(p.getQueryMode())
|| "PLAIN_TEXT".equals(p.getQueryMode())) {
if (Objects.isNull(p.getDataSet()) || Objects.isNull(p.getSqlInfo().getParsedS2SQL())) {
return;
}
formatNL2SQLParseInfo(p);
buildParseInfoFromSQL(p);
buildTextInfo(p);
});
}
private static void formatNL2SQLParseInfo(SemanticParseInfo parseInfo) {
private void buildTextInfo(SemanticParseInfo parseInfo) {
StringBuilder textBuilder = new StringBuilder();
textBuilder.append("**数据集:** ").append(parseInfo.getDataSet().getName()).append(" ");
List<String> metricNames = parseInfo.getMetrics().stream().map(SchemaElement::getName)
@@ -60,4 +78,198 @@ public class ParseInfoFormatProcessor implements ParseResultProcessor {
}
parseInfo.setTextInfo(textBuilder.toString());
}
private void buildParseInfoFromSQL(SemanticParseInfo parseInfo) {
SqlInfo sqlInfo = parseInfo.getSqlInfo();
String s2SQL = sqlInfo.getCorrectedS2SQL();
if (StringUtils.isBlank(s2SQL)) {
return;
}
parseQueryType(parseInfo);
List<FieldExpression> expressions = SqlSelectHelper.getFilterExpression(s2SQL);
Long dataSetId = parseInfo.getDataSetId();
SemanticLayerService semanticLayerService =
ContextUtils.getBean(SemanticLayerService.class);
DataSetSchema dsSchema = semanticLayerService.getDataSetSchema(dataSetId);
// extract date filter from S2SQL
try {
if (parseInfo.getDateInfo() == null && !CollectionUtils.isEmpty(expressions)) {
parseInfo.setDateInfo(extractDateFilter(expressions, dsSchema));
}
} catch (Exception e) {
log.error("failed to extract date range:", e);
}
// extract dimension filters from S2SQL
try {
List<QueryFilter> queryFilters = extractDimensionFilter(dsSchema, expressions);
parseInfo.getDimensionFilters().addAll(queryFilters);
} catch (Exception e) {
log.error("failed to extract dimension filters:", e);
}
// extract metrics from S2SQL
List<String> allFields =
filterDateField(dsSchema, SqlSelectHelper.getAllSelectFields(s2SQL));
Set<SchemaElement> metrics = matchSchemaElements(allFields, dsSchema.getMetrics());
parseInfo.setMetrics(metrics);
// extract dimensions from S2SQL
if (QueryType.AGGREGATE.equals(parseInfo.getQueryType())) {
List<String> groupByFields = SqlSelectHelper.getGroupByFields(s2SQL);
List<String> groupByDimensions = filterDateField(dsSchema, groupByFields);
parseInfo.setDimensions(
matchSchemaElements(groupByDimensions, dsSchema.getDimensions()));
} else if (QueryType.DETAIL.equals(parseInfo.getQueryType())) {
List<String> selectFields = SqlSelectHelper.getSelectFields(s2SQL);
List<String> selectDimensions = filterDateField(dsSchema, selectFields);
parseInfo
.setDimensions(matchSchemaElements(selectDimensions, dsSchema.getDimensions()));
}
}
private Set<SchemaElement> matchSchemaElements(List<String> allFields,
Set<SchemaElement> elements) {
return elements.stream().filter(schemaElement -> {
if (CollectionUtils.isEmpty(schemaElement.getAlias())) {
return allFields.contains(schemaElement.getName());
}
Set<String> allFieldsSet = new HashSet<>(allFields);
Set<String> aliasSet = new HashSet<>(schemaElement.getAlias());
List<String> intersection =
allFieldsSet.stream().filter(aliasSet::contains).collect(Collectors.toList());
return allFields.contains(schemaElement.getName())
|| !CollectionUtils.isEmpty(intersection);
}).collect(Collectors.toSet());
}
private List<String> filterDateField(DataSetSchema dataSetSchema, List<String> allFields) {
return allFields.stream().filter(entry -> !isPartitionDimension(dataSetSchema, entry))
.collect(Collectors.toList());
}
private List<QueryFilter> extractDimensionFilter(DataSetSchema dsSchema,
List<FieldExpression> fieldExpressions) {
Map<String, SchemaElement> fieldNameToElement = getNameToElement(dsSchema);
List<QueryFilter> result = Lists.newArrayList();
for (FieldExpression expression : fieldExpressions) {
QueryFilter dimensionFilter = new QueryFilter();
dimensionFilter.setValue(expression.getFieldValue());
SchemaElement schemaElement = fieldNameToElement.get(expression.getFieldName());
if (Objects.isNull(schemaElement)
|| isPartitionDimension(dsSchema, schemaElement.getName())) {
continue;
}
dimensionFilter.setName(schemaElement.getName());
dimensionFilter.setBizName(schemaElement.getBizName());
dimensionFilter.setElementID(schemaElement.getId());
FilterOperatorEnum operatorEnum =
FilterOperatorEnum.getSqlOperator(expression.getOperator());
dimensionFilter.setOperator(operatorEnum);
dimensionFilter.setFunction(expression.getFunction());
result.add(dimensionFilter);
}
return result;
}
private DateConf extractDateFilter(List<FieldExpression> fieldExpressions,
DataSetSchema dataSetSchema) {
List<FieldExpression> dateExpressions = fieldExpressions.stream().filter(
expression -> isPartitionDimension(dataSetSchema, expression.getFieldName()))
.collect(Collectors.toList());
if (CollectionUtils.isEmpty(dateExpressions)) {
return null;
}
DateConf dateInfo = new DateConf();
dateInfo.setDateMode(DateConf.DateMode.BETWEEN);
FieldExpression firstExpression = dateExpressions.get(0);
FilterOperatorEnum firstOperator =
FilterOperatorEnum.getSqlOperator(firstExpression.getOperator());
if (FilterOperatorEnum.EQUALS.equals(firstOperator)
&& Objects.nonNull(firstExpression.getFieldValue())) {
dateInfo.setStartDate(firstExpression.getFieldValue().toString());
dateInfo.setEndDate(firstExpression.getFieldValue().toString());
dateInfo.setDateMode(DateConf.DateMode.BETWEEN);
return dateInfo;
}
if (containOperators(firstExpression, firstOperator, FilterOperatorEnum.GREATER_THAN,
FilterOperatorEnum.GREATER_THAN_EQUALS)) {
dateInfo.setStartDate(firstExpression.getFieldValue().toString());
if (hasSecondDate(dateExpressions)) {
dateInfo.setEndDate(dateExpressions.get(1).getFieldValue().toString());
}
}
if (containOperators(firstExpression, firstOperator, FilterOperatorEnum.MINOR_THAN,
FilterOperatorEnum.MINOR_THAN_EQUALS)) {
dateInfo.setEndDate(firstExpression.getFieldValue().toString());
if (hasSecondDate(dateExpressions)) {
dateInfo.setStartDate(dateExpressions.get(1).getFieldValue().toString());
}
}
return dateInfo;
}
private static boolean isPartitionDimension(DataSetSchema dataSetSchema, String sqlFieldName) {
if (TimeDimensionEnum.containsTimeDimension(sqlFieldName)) {
return true;
}
if (Objects.isNull(dataSetSchema) || Objects.isNull(dataSetSchema.getPartitionDimension())
|| Objects.isNull(dataSetSchema.getPartitionDimension().getName())) {
return false;
}
return sqlFieldName.equalsIgnoreCase(dataSetSchema.getPartitionDimension().getName());
}
private boolean containOperators(FieldExpression expression, FilterOperatorEnum firstOperator,
FilterOperatorEnum... operatorEnums) {
return (Arrays.asList(operatorEnums).contains(firstOperator)
&& Objects.nonNull(expression.getFieldValue()));
}
private boolean hasSecondDate(List<FieldExpression> dateExpressions) {
return dateExpressions.size() > 1
&& Objects.nonNull(dateExpressions.get(1).getFieldValue());
}
private Map<String, SchemaElement> getNameToElement(DataSetSchema dsSchema) {
Set<SchemaElement> dimensions = dsSchema.getDimensions();
Set<SchemaElement> metrics = dsSchema.getMetrics();
List<SchemaElement> allElements = Lists.newArrayList();
allElements.addAll(dimensions);
allElements.addAll(metrics);
// support alias
return allElements.stream().flatMap(schemaElement -> {
Set<Pair<String, SchemaElement>> result = new HashSet<>();
result.add(Pair.of(schemaElement.getName(), schemaElement));
List<String> aliasList = schemaElement.getAlias();
if (!org.springframework.util.CollectionUtils.isEmpty(aliasList)) {
for (String alias : aliasList) {
result.add(Pair.of(alias, schemaElement));
}
}
return result.stream();
}).collect(Collectors.toMap(Pair::getLeft, Pair::getRight, (value1, value2) -> value2));
}
private void parseQueryType(SemanticParseInfo parseInfo) {
parseInfo.setQueryType(QueryType.DETAIL);
SqlInfo sqlInfo = parseInfo.getSqlInfo();
if (Objects.isNull(sqlInfo) || StringUtils.isBlank(sqlInfo.getCorrectedS2SQL())) {
parseInfo.setQueryType(QueryType.DETAIL);
}
// 2. AGG queryType
if (Objects.nonNull(sqlInfo) && StringUtils.isNotBlank(sqlInfo.getParsedS2SQL())
&& SqlSelectFunctionHelper.hasAggregateFunction(sqlInfo.getCorrectedS2SQL())) {
parseInfo.setQueryType(QueryType.AGGREGATE);
}
}
}

View File

@@ -56,8 +56,7 @@ public class QueryRecommendProcessor implements ParseResultProcessor {
private void updateChatQuery(ChatQueryDO chatQueryDO) {
ChatQueryRepository chatQueryRepository = ContextUtils.getBean(ChatQueryRepository.class);
UpdateWrapper<ChatQueryDO> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("question_id", chatQueryDO.getQuestionId());
updateWrapper.set("similar_queries", chatQueryDO.getSimilarQueries());
updateWrapper.lambda().eq(ChatQueryDO::getQuestionId, chatQueryDO.getQuestionId());
chatQueryRepository.updateChatQuery(chatQueryDO, updateWrapper);
}
}

View File

@@ -1,13 +1,13 @@
package com.tencent.supersonic.chat.server.rest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
import com.tencent.supersonic.chat.server.agent.Agent;
import com.tencent.supersonic.chat.server.agent.AgentToolType;
import com.tencent.supersonic.chat.server.service.AgentService;
import com.tencent.supersonic.common.pojo.User;
import com.tencent.supersonic.common.pojo.enums.AuthType;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
@@ -15,6 +15,7 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@@ -48,8 +49,11 @@ public class AgentController {
}
@RequestMapping("/getAgentList")
public List<Agent> getAgentList() {
return agentService.getAgents();
public List<Agent> getAgentList(
@RequestParam(value = "authType", required = false) AuthType authType,
HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
User user = UserHolder.findUser(httpServletRequest, httpServletResponse);
return agentService.getAgents(user, authType);
}
@RequestMapping("/getToolTypes")

View File

@@ -1,8 +1,5 @@
package com.tencent.supersonic.chat.server.rest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
import com.tencent.supersonic.chat.api.pojo.request.ChatConfigBaseReq;
import com.tencent.supersonic.chat.api.pojo.request.ChatConfigEditReqReq;
@@ -14,6 +11,8 @@ import com.tencent.supersonic.common.pojo.User;
import com.tencent.supersonic.headless.api.pojo.DataSetSchema;
import com.tencent.supersonic.headless.api.pojo.response.ItemResp;
import com.tencent.supersonic.headless.server.facade.service.SemanticLayerService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

View File

@@ -1,8 +1,5 @@
package com.tencent.supersonic.chat.server.rest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.github.pagehelper.PageInfo;
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
import com.tencent.supersonic.chat.api.pojo.request.PageQueryInfoReq;
@@ -10,6 +7,8 @@ import com.tencent.supersonic.chat.api.pojo.response.QueryResp;
import com.tencent.supersonic.chat.api.pojo.response.ShowCaseResp;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatDO;
import com.tencent.supersonic.chat.server.service.ChatManageService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

View File

@@ -1,9 +1,5 @@
package com.tencent.supersonic.chat.server.rest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
import com.tencent.supersonic.chat.api.pojo.request.ChatExecuteReq;
import com.tencent.supersonic.chat.api.pojo.request.ChatParseReq;
@@ -14,6 +10,9 @@ import com.tencent.supersonic.common.pojo.User;
import com.tencent.supersonic.common.pojo.exception.InvalidArgumentException;
import com.tencent.supersonic.headless.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.headless.api.pojo.request.DimensionValueReq;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

View File

@@ -1,18 +1,17 @@
package com.tencent.supersonic.chat.server.rest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.github.pagehelper.PageInfo;
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
import com.tencent.supersonic.chat.api.pojo.enums.MemoryReviewResult;
import com.tencent.supersonic.chat.api.pojo.request.ChatMemoryCreateReq;
import com.tencent.supersonic.chat.api.pojo.request.ChatMemoryUpdateReq;
import com.tencent.supersonic.chat.api.pojo.request.PageMemoryReq;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatMemoryDO;
import com.tencent.supersonic.chat.server.pojo.ChatMemory;
import com.tencent.supersonic.chat.server.service.MemoryService;
import com.tencent.supersonic.common.pojo.User;
import com.tencent.supersonic.headless.api.pojo.request.MetaBatchReq;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@@ -32,7 +31,7 @@ public class MemoryController {
public Boolean createMemory(@RequestBody ChatMemoryCreateReq chatMemoryCreateReq,
HttpServletRequest request, HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
memoryService.createMemory(ChatMemoryDO.builder().agentId(chatMemoryCreateReq.getAgentId())
memoryService.createMemory(ChatMemory.builder().agentId(chatMemoryCreateReq.getAgentId())
.s2sql(chatMemoryCreateReq.getS2sql()).question(chatMemoryCreateReq.getQuestion())
.dbSchema(chatMemoryCreateReq.getDbSchema()).status(chatMemoryCreateReq.getStatus())
.humanReviewRet(MemoryReviewResult.POSITIVE).createdBy(user.getName())
@@ -49,7 +48,7 @@ public class MemoryController {
}
@RequestMapping("/pageMemories")
public PageInfo<ChatMemoryDO> pageMemories(@RequestBody PageMemoryReq pageMemoryReq) {
public PageInfo<ChatMemory> pageMemories(@RequestBody PageMemoryReq pageMemoryReq) {
return memoryService.pageMemories(pageMemoryReq);
}

View File

@@ -1,14 +1,13 @@
package com.tencent.supersonic.chat.server.rest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.tencent.supersonic.auth.api.authentication.annotation.AuthenticationIgnore;
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
import com.tencent.supersonic.chat.api.pojo.request.PluginQueryReq;
import com.tencent.supersonic.chat.server.plugin.ChatPlugin;
import com.tencent.supersonic.chat.server.service.PluginService;
import com.tencent.supersonic.common.pojo.User;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;

View File

@@ -2,10 +2,12 @@ package com.tencent.supersonic.chat.server.service;
import com.tencent.supersonic.chat.server.agent.Agent;
import com.tencent.supersonic.common.pojo.User;
import com.tencent.supersonic.common.pojo.enums.AuthType;
import java.util.List;
public interface AgentService {
List<Agent> getAgents(User user, AuthType authType);
List<Agent> getAgents();

View File

@@ -4,27 +4,22 @@ import com.github.pagehelper.PageInfo;
import com.tencent.supersonic.chat.api.pojo.request.ChatMemoryFilter;
import com.tencent.supersonic.chat.api.pojo.request.ChatMemoryUpdateReq;
import com.tencent.supersonic.chat.api.pojo.request.PageMemoryReq;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatMemoryDO;
import com.tencent.supersonic.chat.server.pojo.ChatMemory;
import com.tencent.supersonic.common.pojo.User;
import java.util.List;
public interface MemoryService {
void createMemory(ChatMemoryDO memory);
void createMemory(ChatMemory memory);
void updateMemory(ChatMemoryUpdateReq chatMemoryUpdateReq, User user);
void updateMemory(ChatMemoryDO memory);
void enableMemory(ChatMemoryDO memory);
void disableMemory(ChatMemoryDO memory);
void updateMemory(ChatMemory memory);
void batchDelete(List<Long> ids);
PageInfo<ChatMemoryDO> pageMemories(PageMemoryReq pageMemoryReq);
PageInfo<ChatMemory> pageMemories(PageMemoryReq pageMemoryReq);
List<ChatMemoryDO> getMemories(ChatMemoryFilter chatMemoryFilter);
List<ChatMemory> getMemories(ChatMemoryFilter chatMemoryFilter);
List<ChatMemoryDO> getMemoriesForLlmReview();
}

View File

@@ -6,14 +6,15 @@ import com.tencent.supersonic.chat.api.pojo.request.ChatParseReq;
import com.tencent.supersonic.chat.server.agent.Agent;
import com.tencent.supersonic.chat.server.agent.VisualConfig;
import com.tencent.supersonic.chat.server.persistence.dataobject.AgentDO;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatMemoryDO;
import com.tencent.supersonic.chat.server.persistence.mapper.AgentDOMapper;
import com.tencent.supersonic.chat.server.pojo.ChatMemory;
import com.tencent.supersonic.chat.server.service.AgentService;
import com.tencent.supersonic.chat.server.service.ChatQueryService;
import com.tencent.supersonic.chat.server.service.MemoryService;
import com.tencent.supersonic.common.config.ChatModel;
import com.tencent.supersonic.common.pojo.ChatApp;
import com.tencent.supersonic.common.pojo.User;
import com.tencent.supersonic.common.pojo.enums.AuthType;
import com.tencent.supersonic.common.service.ChatModelService;
import com.tencent.supersonic.common.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;
@@ -43,6 +44,27 @@ public class AgentServiceImpl extends ServiceImpl<AgentDOMapper, AgentDO> implem
private ExecutorService executorService = Executors.newFixedThreadPool(1);
@Override
public List<Agent> getAgents(User user, AuthType authType) {
return getAgentDOList().stream().map(this::convert)
.filter(agent -> filterByAuth(agent, user, authType)).collect(Collectors.toList());
}
private boolean filterByAuth(Agent agent, User user, AuthType authType) {
if (user.isSuperAdmin() || user.getName().equals(agent.getCreatedBy())) {
return true;
}
authType = authType == null ? AuthType.VIEWER : authType;
switch (authType) {
case ADMIN:
return agent.contains(user, Agent::getAdmins);
case VIEWER:
default:
return agent.contains(user, Agent::getAdmins)
|| agent.contains(user, Agent::getViewers);
}
}
@Override
public List<Agent> getAgents() {
return getAgentDOList().stream().map(this::convert).collect(Collectors.toList());
@@ -99,7 +121,7 @@ public class AgentServiceImpl extends ServiceImpl<AgentDOMapper, AgentDO> implem
ChatMemoryFilter chatMemoryFilter =
ChatMemoryFilter.builder().agentId(agent.getId()).questions(examples).build();
List<String> memoriesExisted = memoryService.getMemories(chatMemoryFilter).stream()
.map(ChatMemoryDO::getQuestion).collect(Collectors.toList());
.map(ChatMemory::getQuestion).collect(Collectors.toList());
for (String example : examples) {
if (memoriesExisted.contains(example)) {
continue;
@@ -135,6 +157,8 @@ public class AgentServiceImpl extends ServiceImpl<AgentDOMapper, AgentDO> implem
c.setChatModelConfig(chatModelService.getChatModel(c.getChatModelId()).getConfig());
}
});
agent.setAdmins(JsonUtil.toList(agentDO.getAdmin(), String.class));
agent.setViewers(JsonUtil.toList(agentDO.getViewer(), String.class));
return agent;
}
@@ -145,6 +169,8 @@ public class AgentServiceImpl extends ServiceImpl<AgentDOMapper, AgentDO> implem
agentDO.setExamples(JsonUtil.toString(agent.getExamples()));
agentDO.setChatModelConfig(JsonUtil.toString(agent.getChatAppConfig()));
agentDO.setVisualConfig(JsonUtil.toString(agent.getVisualConfig()));
agentDO.setAdmin(JsonUtil.toString(agent.getAdmins()));
agentDO.setViewer(JsonUtil.toString(agent.getViewers()));
if (agentDO.getStatus() == null) {
agentDO.setStatus(1);
}

View File

@@ -18,18 +18,12 @@ import com.tencent.supersonic.chat.server.service.ChatManageService;
import com.tencent.supersonic.chat.server.service.ChatQueryService;
import com.tencent.supersonic.chat.server.util.ComponentFactory;
import com.tencent.supersonic.chat.server.util.QueryReqConverter;
import com.tencent.supersonic.common.jsqlparser.FieldExpression;
import com.tencent.supersonic.common.jsqlparser.SqlAddHelper;
import com.tencent.supersonic.common.jsqlparser.SqlRemoveHelper;
import com.tencent.supersonic.common.jsqlparser.SqlReplaceHelper;
import com.tencent.supersonic.common.jsqlparser.SqlSelectHelper;
import com.tencent.supersonic.common.jsqlparser.*;
import com.tencent.supersonic.common.pojo.User;
import com.tencent.supersonic.common.pojo.enums.FilterOperatorEnum;
import com.tencent.supersonic.common.util.ContextUtils;
import com.tencent.supersonic.common.util.DateUtils;
import com.tencent.supersonic.common.util.JsonUtil;
import com.tencent.supersonic.headless.api.pojo.DataSetSchema;
import com.tencent.supersonic.headless.api.pojo.EntityInfo;
import com.tencent.supersonic.headless.api.pojo.SchemaElement;
import com.tencent.supersonic.headless.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.headless.api.pojo.SqlInfo;
@@ -50,11 +44,7 @@ import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.relational.ComparisonOperator;
import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList;
import net.sf.jsqlparser.expression.operators.relational.*;
import net.sf.jsqlparser.schema.Column;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
@@ -62,14 +52,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@@ -198,7 +181,7 @@ public class ChatQueryServiceImpl implements ChatQueryService {
handleRuleQueryMode(semanticQuery, dataSetSchema, user);
}
return executeQuery(semanticQuery, user, dataSetSchema);
return executeQuery(semanticQuery, user);
}
private List<String> getFieldsFromSql(SemanticParseInfo parseInfo) {
@@ -212,20 +195,22 @@ public class ChatQueryServiceImpl implements ChatQueryService {
private void handleLLMQueryMode(ChatQueryDataReq chatQueryDataReq, SemanticQuery semanticQuery,
DataSetSchema dataSetSchema, User user) throws Exception {
SemanticParseInfo parseInfo = semanticQuery.getParseInfo();
List<String> fields = getFieldsFromSql(parseInfo);
if (checkMetricReplace(fields, chatQueryDataReq.getMetrics())) {
log.info("llm begin replace metrics!");
String rebuiltS2SQL;
if (checkMetricReplace(chatQueryDataReq, parseInfo)) {
log.info("rebuild S2SQL with adjusted metrics!");
SchemaElement metricToReplace = chatQueryDataReq.getMetrics().iterator().next();
replaceMetrics(parseInfo, metricToReplace);
rebuiltS2SQL = replaceMetrics(parseInfo, metricToReplace);
} else {
log.info("llm begin revise filters!");
String correctorSql = reviseCorrectS2SQL(chatQueryDataReq, parseInfo, dataSetSchema);
parseInfo.getSqlInfo().setCorrectedS2SQL(correctorSql);
semanticQuery.setParseInfo(parseInfo);
SemanticQueryReq semanticQueryReq = semanticQuery.buildSemanticQueryReq();
SemanticTranslateResp explain = semanticLayerService.translate(semanticQueryReq, user);
parseInfo.getSqlInfo().setQuerySQL(explain.getQuerySQL());
log.info("rebuild S2SQL with adjusted filters!");
rebuiltS2SQL = replaceFilters(chatQueryDataReq, parseInfo, dataSetSchema);
}
// reset SqlInfo and request re-translation
parseInfo.getSqlInfo().setCorrectedS2SQL(rebuiltS2SQL);
parseInfo.getSqlInfo().setParsedS2SQL(rebuiltS2SQL);
parseInfo.getSqlInfo().setQuerySQL(null);
SemanticQueryReq semanticQueryReq = semanticQuery.buildSemanticQueryReq();
SemanticTranslateResp explain = semanticLayerService.translate(semanticQueryReq, user);
parseInfo.getSqlInfo().setQuerySQL(explain.getQuerySQL());
}
private void handleRuleQueryMode(SemanticQuery semanticQuery, DataSetSchema dataSetSchema,
@@ -233,23 +218,22 @@ public class ChatQueryServiceImpl implements ChatQueryService {
log.info("rule begin replace metrics and revise filters!");
validFilter(semanticQuery.getParseInfo().getDimensionFilters());
validFilter(semanticQuery.getParseInfo().getMetricFilters());
semanticQuery.initS2Sql(dataSetSchema, user);
semanticQuery.buildS2Sql(dataSetSchema);
}
private QueryResult executeQuery(SemanticQuery semanticQuery, User user,
DataSetSchema dataSetSchema) throws Exception {
private QueryResult executeQuery(SemanticQuery semanticQuery, User user) throws Exception {
SemanticQueryReq semanticQueryReq = semanticQuery.buildSemanticQueryReq();
SemanticParseInfo parseInfo = semanticQuery.getParseInfo();
QueryResult queryResult = doExecution(semanticQueryReq, parseInfo.getQueryMode(), user);
queryResult.setChatContext(semanticQuery.getParseInfo());
SemanticLayerService semanticService = ContextUtils.getBean(SemanticLayerService.class);
EntityInfo entityInfo = semanticService.getEntityInfo(parseInfo, dataSetSchema, user);
queryResult.setEntityInfo(entityInfo);
parseInfo.getSqlInfo().setQuerySQL(queryResult.getQuerySql());
return queryResult;
}
private boolean checkMetricReplace(List<String> oriFields, Set<SchemaElement> metrics) {
private boolean checkMetricReplace(ChatQueryDataReq chatQueryDataReq,
SemanticParseInfo parseInfo) {
List<String> oriFields = getFieldsFromSql(parseInfo);
Set<SchemaElement> metrics = chatQueryDataReq.getMetrics();
if (CollectionUtils.isEmpty(oriFields) || CollectionUtils.isEmpty(metrics)) {
return false;
}
@@ -258,7 +242,7 @@ public class ChatQueryServiceImpl implements ChatQueryService {
return !oriFields.containsAll(metricNames);
}
private String reviseCorrectS2SQL(ChatQueryDataReq queryData, SemanticParseInfo parseInfo,
private String replaceFilters(ChatQueryDataReq queryData, SemanticParseInfo parseInfo,
DataSetSchema dataSetSchema) {
String correctorSql = parseInfo.getSqlInfo().getCorrectedS2SQL();
log.info("correctorSql before replacing:{}", correctorSql);
@@ -296,7 +280,7 @@ public class ChatQueryServiceImpl implements ChatQueryService {
return correctorSql;
}
private void replaceMetrics(SemanticParseInfo parseInfo, SchemaElement metric) {
private String replaceMetrics(SemanticParseInfo parseInfo, SchemaElement metric) {
List<String> oriMetrics = parseInfo.getMetrics().stream().map(SchemaElement::getName)
.collect(Collectors.toList());
String correctorSql = parseInfo.getSqlInfo().getCorrectedS2SQL();
@@ -308,7 +292,7 @@ public class ChatQueryServiceImpl implements ChatQueryService {
correctorSql = SqlReplaceHelper.replaceAggFields(correctorSql, fieldMap);
}
log.info("after replaceMetrics:{}", correctorSql);
parseInfo.getSqlInfo().setCorrectedS2SQL(correctorSql);
return correctorSql;
}
private QueryResult doExecution(SemanticQueryReq semanticQueryReq, String queryMode, User user)
@@ -483,6 +467,9 @@ public class ChatQueryServiceImpl implements ChatQueryService {
}
private void mergeParseInfo(SemanticParseInfo parseInfo, ChatQueryDataReq queryData) {
if (Objects.nonNull(queryData.getDateInfo())) {
parseInfo.setDateInfo(queryData.getDateInfo());
}
if (LLMSqlQuery.QUERY_MODE.equals(parseInfo.getQueryMode())) {
return;
}
@@ -498,9 +485,7 @@ public class ChatQueryServiceImpl implements ChatQueryService {
if (!CollectionUtils.isEmpty(queryData.getMetricFilters())) {
parseInfo.setMetricFilters(queryData.getMetricFilters());
}
if (Objects.nonNull(queryData.getDateInfo())) {
parseInfo.setDateInfo(queryData.getDateInfo());
}
parseInfo.setSqlInfo(new SqlInfo());
}

View File

@@ -7,7 +7,6 @@ import com.tencent.supersonic.chat.api.pojo.request.ChatConfigEditReqReq;
import com.tencent.supersonic.chat.api.pojo.request.ChatConfigFilter;
import com.tencent.supersonic.chat.api.pojo.request.ChatDefaultConfigReq;
import com.tencent.supersonic.chat.api.pojo.request.ChatDetailConfigReq;
import com.tencent.supersonic.chat.api.pojo.request.Entity;
import com.tencent.supersonic.chat.api.pojo.request.ItemNameVisibilityInfo;
import com.tencent.supersonic.chat.api.pojo.request.ItemVisibility;
import com.tencent.supersonic.chat.api.pojo.request.KnowledgeInfoReq;
@@ -16,7 +15,6 @@ import com.tencent.supersonic.chat.api.pojo.response.ChatConfigResp;
import com.tencent.supersonic.chat.api.pojo.response.ChatConfigRichResp;
import com.tencent.supersonic.chat.api.pojo.response.ChatDefaultRichConfigResp;
import com.tencent.supersonic.chat.api.pojo.response.ChatDetailRichConfigResp;
import com.tencent.supersonic.chat.api.pojo.response.EntityRichInfoResp;
import com.tencent.supersonic.chat.api.pojo.response.ItemVisibilityInfo;
import com.tencent.supersonic.chat.server.config.ChatConfig;
import com.tencent.supersonic.chat.server.persistence.repository.ChatConfigRepository;
@@ -88,16 +86,6 @@ public class ConfigServiceImpl implements ConfigService {
return configEditCmd.getId();
}
public ItemNameVisibilityInfo getVisibilityByModelId(Long modelId) {
ChatConfigResp chatConfigResp = fetchConfigByModelId(modelId);
ChatConfig chatConfig = new ChatConfig();
chatConfig.setModelId(modelId);
chatConfig.setChatAggConfig(chatConfigResp.getChatAggConfig());
chatConfig.setChatDetailConfig(chatConfigResp.getChatDetailConfig());
ItemNameVisibilityInfo itemNameVisibility = getItemNameVisibility(chatConfig);
return itemNameVisibility;
}
public ItemNameVisibilityInfo getItemNameVisibility(ChatConfig chatConfig) {
Long modelId = chatConfig.getModelId();
@@ -240,19 +228,6 @@ public class ConfigServiceImpl implements ConfigService {
return detailRichConfig;
}
private EntityRichInfoResp generateRichEntity(Entity entity, DataSetSchema modelSchema) {
EntityRichInfoResp entityRichInfo = new EntityRichInfoResp();
if (Objects.isNull(entity) || Objects.isNull(entity.getEntityId())) {
return entityRichInfo;
}
BeanUtils.copyProperties(entity, entityRichInfo);
Map<Long, SchemaElement> dimIdAndRespPair = modelSchema.getDimensions().stream().collect(
Collectors.toMap(SchemaElement::getId, Function.identity(), (k1, k2) -> k1));
entityRichInfo.setDimItem(dimIdAndRespPair.get(entity.getEntityId()));
return entityRichInfo;
}
private ChatAggRichConfigResp fillChatAggRichConfig(DataSetSchema modelSchema,
ChatConfigResp chatConfigResp) {
if (Objects.isNull(chatConfigResp) || Objects.isNull(chatConfigResp.getChatAggConfig())) {
@@ -327,7 +302,7 @@ public class ConfigServiceImpl implements ConfigService {
}
Map<Long, SchemaElement> dimIdAndRespPair = modelSchema.getDimensions().stream().collect(
Collectors.toMap(SchemaElement::getId, Function.identity(), (k1, k2) -> k1));
knowledgeInfos.stream().forEach(knowledgeInfo -> {
knowledgeInfos.forEach(knowledgeInfo -> {
if (Objects.nonNull(knowledgeInfo)) {
SchemaElement dimSchemaResp = dimIdAndRespPair.get(knowledgeInfo.getItemId());
if (Objects.nonNull(dimSchemaResp)) {

View File

@@ -3,12 +3,14 @@ package com.tencent.supersonic.chat.server.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tencent.supersonic.chat.api.pojo.enums.MemoryReviewResult;
import com.tencent.supersonic.chat.api.pojo.enums.MemoryStatus;
import com.tencent.supersonic.chat.api.pojo.request.ChatMemoryFilter;
import com.tencent.supersonic.chat.api.pojo.request.ChatMemoryUpdateReq;
import com.tencent.supersonic.chat.api.pojo.request.PageMemoryReq;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatMemoryDO;
import com.tencent.supersonic.chat.server.persistence.repository.ChatMemoryRepository;
import com.tencent.supersonic.chat.server.pojo.ChatMemory;
import com.tencent.supersonic.chat.server.service.MemoryService;
import com.tencent.supersonic.common.config.EmbeddingConfig;
import com.tencent.supersonic.common.pojo.Text2SQLExemplar;
@@ -16,12 +18,15 @@ import com.tencent.supersonic.common.pojo.User;
import com.tencent.supersonic.common.service.ExemplarService;
import com.tencent.supersonic.common.util.BeanMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Service
public class MemoryServiceImpl implements MemoryService {
@@ -36,34 +41,36 @@ public class MemoryServiceImpl implements MemoryService {
private EmbeddingConfig embeddingConfig;
@Override
public void createMemory(ChatMemoryDO memory) {
public void createMemory(ChatMemory memory) {
// if an existing enabled memory has the same question, just skip
List<ChatMemoryDO> memories =
List<ChatMemory> memories =
getMemories(ChatMemoryFilter.builder().agentId(memory.getAgentId())
.question(memory.getQuestion()).status(MemoryStatus.ENABLED).build());
if (memories.size() == 0) {
chatMemoryRepository.createMemory(memory);
if (memories.isEmpty()) {
ChatMemoryDO memoryDO = getMemoryDO(memory);
chatMemoryRepository.createMemory(memoryDO);
}
}
@Override
public void updateMemory(ChatMemoryUpdateReq chatMemoryUpdateReq, User user) {
ChatMemoryDO chatMemoryDO = chatMemoryRepository.getMemory(chatMemoryUpdateReq.getId());
boolean hadEnabled =
MemoryStatus.ENABLED.toString().equals(chatMemoryDO.getStatus().trim());
chatMemoryDO.setUpdatedBy(user.getName());
chatMemoryDO.setUpdatedAt(new Date());
BeanMapper.mapper(chatMemoryUpdateReq, chatMemoryDO);
boolean hadEnabled = MemoryStatus.ENABLED.equals(chatMemoryDO.getStatus());
if (MemoryStatus.ENABLED.equals(chatMemoryUpdateReq.getStatus()) && !hadEnabled) {
enableMemory(chatMemoryDO);
} else if (MemoryStatus.DISABLED.equals(chatMemoryUpdateReq.getStatus()) && hadEnabled) {
disableMemory(chatMemoryDO);
}
updateMemory(chatMemoryDO);
chatMemoryRepository.updateMemory(chatMemoryDO);
}
@Override
public void updateMemory(ChatMemoryDO memory) {
chatMemoryRepository.updateMemory(memory);
public void updateMemory(ChatMemory memory) {
chatMemoryRepository.updateMemory(getMemoryDO(memory));
}
@Override
@@ -72,7 +79,7 @@ public class MemoryServiceImpl implements MemoryService {
}
@Override
public PageInfo<ChatMemoryDO> pageMemories(PageMemoryReq pageMemoryReq) {
public PageInfo<ChatMemory> pageMemories(PageMemoryReq pageMemoryReq) {
ChatMemoryFilter chatMemoryFilter = pageMemoryReq.getChatMemoryFilter();
chatMemoryFilter.setSort(pageMemoryReq.getSort());
chatMemoryFilter.setOrderCondition(pageMemoryReq.getOrderCondition());
@@ -81,7 +88,7 @@ public class MemoryServiceImpl implements MemoryService {
}
@Override
public List<ChatMemoryDO> getMemories(ChatMemoryFilter chatMemoryFilter) {
public List<ChatMemory> getMemories(ChatMemoryFilter chatMemoryFilter) {
QueryWrapper<ChatMemoryDO> queryWrapper = new QueryWrapper<>();
if (chatMemoryFilter.getAgentId() != null) {
queryWrapper.lambda().eq(ChatMemoryDO::getAgentId, chatMemoryFilter.getAgentId());
@@ -109,32 +116,52 @@ public class MemoryServiceImpl implements MemoryService {
queryWrapper.orderBy(true, chatMemoryFilter.isAsc(),
chatMemoryFilter.getOrderCondition());
}
return chatMemoryRepository.getMemories(queryWrapper);
List<ChatMemoryDO> chatMemoryDOS = chatMemoryRepository.getMemories(queryWrapper);
return chatMemoryDOS.stream().map(this::getMemory).collect(Collectors.toList());
}
@Override
public List<ChatMemoryDO> getMemoriesForLlmReview() {
QueryWrapper<ChatMemoryDO> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(ChatMemoryDO::getStatus, MemoryStatus.PENDING)
.isNull(ChatMemoryDO::getLlmReviewRet);
return chatMemoryRepository.getMemories(queryWrapper);
}
@Override
public void enableMemory(ChatMemoryDO memory) {
memory.setStatus(MemoryStatus.ENABLED);
private void enableMemory(ChatMemoryDO memory) {
memory.setStatus(MemoryStatus.ENABLED.toString());
exemplarService.storeExemplar(embeddingConfig.getMemoryCollectionName(memory.getAgentId()),
Text2SQLExemplar.builder().question(memory.getQuestion())
.sideInfo(memory.getSideInfo()).dbSchema(memory.getDbSchema())
.sql(memory.getS2sql()).build());
}
@Override
public void disableMemory(ChatMemoryDO memory) {
memory.setStatus(MemoryStatus.DISABLED);
private void disableMemory(ChatMemoryDO memory) {
memory.setStatus(MemoryStatus.DISABLED.toString());
exemplarService.removeExemplar(embeddingConfig.getMemoryCollectionName(memory.getAgentId()),
Text2SQLExemplar.builder().question(memory.getQuestion())
.sideInfo(memory.getSideInfo()).dbSchema(memory.getDbSchema())
.sql(memory.getS2sql()).build());
}
private ChatMemoryDO getMemoryDO(ChatMemory memory) {
ChatMemoryDO memoryDO = new ChatMemoryDO();
BeanUtils.copyProperties(memory, memoryDO);
memoryDO.setStatus(memory.getStatus().toString().trim());
if (Objects.nonNull(memory.getHumanReviewRet())) {
memoryDO.setHumanReviewRet(memory.getHumanReviewRet().toString().trim());
}
if (Objects.nonNull(memory.getLlmReviewRet())) {
memoryDO.setLlmReviewRet(memory.getLlmReviewRet().toString().trim());
}
return memoryDO;
}
private ChatMemory getMemory(ChatMemoryDO memoryDO) {
ChatMemory memory = new ChatMemory();
BeanUtils.copyProperties(memoryDO, memory);
memory.setStatus(MemoryStatus.valueOf(memoryDO.getStatus().trim()));
if (Objects.nonNull(memoryDO.getHumanReviewRet())) {
memory.setHumanReviewRet(
MemoryReviewResult.valueOf(memoryDO.getHumanReviewRet().trim()));
}
if (Objects.nonNull(memoryDO.getLlmReviewRet())) {
memory.setLlmReviewRet(MemoryReviewResult.valueOf(memoryDO.getLlmReviewRet().trim()));
}
return memory;
}
}

View File

@@ -20,54 +20,6 @@
<result column="updated_at" property="updatedAt"/>
</resultMap>
<insert id="addConfig"
parameterType="com.tencent.supersonic.chat.server.persistence.dataobject.ChatConfigDO"
useGeneratedKeys="true" keyProperty="id">
insert into s2_chat_config
(
model_id, `chat_detail_config`, chat_agg_config, recommended_questions, status, llm_examples, created_by, updated_by, created_at, updated_at
)
values
(
#{modelId}, #{chatDetailConfig}, #{chatAggConfig}, #{recommendedQuestions}, #{status}, #{llmExamples}, #{createdBy}, #{updatedBy}, #{createdAt}, #{updatedAt}
)
</insert>
<update id="editConfig">
update s2_chat_config
<set>
`updated_at` = #{updatedAt} ,
<if test="chatDetailConfig != null and chatDetailConfig != ''">
`chat_detail_config` = #{chatDetailConfig} ,
</if>
<if test="chatAggConfig != null and chatAggConfig != ''">
chat_agg_config = #{chatAggConfig} ,
</if>
<if test="recommendedQuestions != null and recommendedQuestions != ''">
recommended_questions = #{recommendedQuestions} ,
</if>
<if test="status != null and status != ''">
status = #{status} ,
</if>
<if test="updatedBy != null and updatedBy != ''">
updated_by = #{updatedBy} ,
</if>
<if test="llmExamples != null and llmExamples != ''">
llm_examples = #{llmExamples} ,
</if>
</set>
<where>
<if test="id != null and id != ''">
id = #{id}
</if>
<if test="modelId != null and modelId != ''">
and model_id = #{modelId}
</if>
</where>
</update>
<select id="search" resultMap="chaConfigDO">
select *
from s2_chat_config

View File

@@ -9,7 +9,7 @@
type="com.tencent.supersonic.chat.server.persistence.dataobject.ChatContextDO">
<id column="chat_id" property="chatId"/>
<result column="modified_at" property="modifiedAt"/>
<result column="user" property="user"/>
<result column="query_user" property="queryUser"/>
<result column="query_text" property="queryText"/>
<result column="semantic_parse" property="semanticParse"/>
<!--<result column="ext_data" property="extData"/>-->
@@ -20,11 +20,4 @@
from s2_chat_context where chat_id=#{chatId} limit 1
</select>
<insert id="addContext" parameterType="com.tencent.supersonic.chat.server.persistence.dataobject.ChatContextDO" >
insert into s2_chat_context (chat_id,user,query_text,semantic_parse) values (#{chatId}, #{user},#{queryText}, #{semanticParse})
</insert>
<update id="updateContext">
update s2_chat_context set query_text=#{queryText},semantic_parse=#{semanticParse} where chat_id=#{chatId}
</update>
</mapper>
</mapper>

View File

@@ -31,21 +31,21 @@
<!--http-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>${httpmime.version}</version>
<exclusions>
<exclusion>
<artifactId>httpclient</artifactId>
<groupId>org.apache.httpcomponents</groupId>
</exclusion>
</exclusions>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>${httpclient5.version}</version> <!-- 请确认使用最新稳定版本 -->
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.apache.httpcomponents</groupId>-->
<!-- <artifactId>httpmime</artifactId>-->
<!-- <version>${httpmime.version}</version>-->
<!-- <exclusions>-->
<!-- <exclusion>-->
<!-- <artifactId>httpclient</artifactId>-->
<!-- <groupId>org.apache.httpcomponents</groupId>-->
<!-- </exclusion>-->
<!-- </exclusions>-->
<!-- </dependency>-->
<dependency>
<groupId>com.alibaba</groupId>
@@ -130,7 +130,7 @@
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>${mybatis.plus.version}</version>
</dependency>

View File

@@ -19,19 +19,6 @@ public class Term {
this.nature = nature;
}
public Term(String word, Nature nature, int offset) {
this.word = word;
this.nature = nature;
this.offset = offset;
}
public Term(String word, Nature nature, int offset, int frequency) {
this.word = word;
this.nature = nature;
this.offset = offset;
this.frequency = frequency;
}
public int length() {
return this.word.length();
}

View File

@@ -38,14 +38,14 @@ public class EmbeddingStoreParameterConfig extends ParameterConfig {
new Parameter("s2.embedding.store.timeout", "60", "超时时间(秒)", "", "number", MODULE_NAME);
public static final Parameter EMBEDDING_STORE_DIMENSION =
new Parameter("s2.embedding.store.dimension", "", "", "", "number", MODULE_NAME, null,
getDimensionDependency());
new Parameter("s2.embedding.store.dimension", "", "向量维", "", "number", MODULE_NAME,
null, getDimensionDependency());
public static final Parameter EMBEDDING_STORE_DATABASE_NAME =
new Parameter("s2.embedding.store.databaseName", "", "DatabaseName", "", "string",
MODULE_NAME, null, getDatabaseNameDependency());
public static final Parameter EMBEDDING_STORE_POST = new Parameter("s2.embedding.store.post",
"", "端口", "", "number", MODULE_NAME, null, getPostDependency());
public static final Parameter EMBEDDING_STORE_POST = new Parameter("s2.embedding.store.port",
"", "端口", "", "number", MODULE_NAME, null, getPortDependency());
public static final Parameter EMBEDDING_STORE_USER = new Parameter("s2.embedding.store.user",
"", "用户名", "", "string", MODULE_NAME, null, getUserDependency());
@@ -101,10 +101,8 @@ public class EmbeddingStoreParameterConfig extends ParameterConfig {
private static List<Parameter.Dependency> getApiKeyDependency() {
return getDependency(EMBEDDING_STORE_PROVIDER.getName(),
Lists.newArrayList(EmbeddingStoreType.MILVUS.name(),
EmbeddingStoreType.PGVECTOR.name()),
ImmutableMap.of(EmbeddingStoreType.MILVUS.name(), DEMO,
EmbeddingStoreType.PGVECTOR.name(), DEMO));
Lists.newArrayList(EmbeddingStoreType.MILVUS.name()),
ImmutableMap.of(EmbeddingStoreType.MILVUS.name(), DEMO));
}
private static List<Parameter.Dependency> getPathDependency() {
@@ -118,7 +116,7 @@ public class EmbeddingStoreParameterConfig extends ParameterConfig {
Lists.newArrayList(EmbeddingStoreType.MILVUS.name(),
EmbeddingStoreType.PGVECTOR.name()),
ImmutableMap.of(EmbeddingStoreType.MILVUS.name(), "384",
EmbeddingStoreType.PGVECTOR.name(), "768"));
EmbeddingStoreType.PGVECTOR.name(), "512"));
}
private static List<Parameter.Dependency> getDatabaseNameDependency() {
@@ -129,7 +127,7 @@ public class EmbeddingStoreParameterConfig extends ParameterConfig {
EmbeddingStoreType.PGVECTOR.name(), "postgres"));
}
private static List<Parameter.Dependency> getPostDependency() {
private static List<Parameter.Dependency> getPortDependency() {
return getDependency(EMBEDDING_STORE_PROVIDER.getName(),
Lists.newArrayList(EmbeddingStoreType.PGVECTOR.name()),
ImmutableMap.of(EmbeddingStoreType.PGVECTOR.name(), "54333"));
@@ -140,12 +138,14 @@ public class EmbeddingStoreParameterConfig extends ParameterConfig {
Lists.newArrayList(EmbeddingStoreType.MILVUS.name(),
EmbeddingStoreType.PGVECTOR.name()),
ImmutableMap.of(EmbeddingStoreType.MILVUS.name(), "milvus",
EmbeddingStoreType.PGVECTOR.name(), "pgvector"));
EmbeddingStoreType.PGVECTOR.name(), "postgres"));
}
private static List<Parameter.Dependency> getPasswordDependency() {
return getDependency(EMBEDDING_STORE_PROVIDER.getName(),
Lists.newArrayList(EmbeddingStoreType.MILVUS.name()),
ImmutableMap.of(EmbeddingStoreType.MILVUS.name(), "milvus"));
Lists.newArrayList(EmbeddingStoreType.MILVUS.name(),
EmbeddingStoreType.PGVECTOR.name()),
ImmutableMap.of(EmbeddingStoreType.MILVUS.name(), "milvus",
EmbeddingStoreType.PGVECTOR.name(), "postgres"));
}
}

View File

@@ -1,9 +1,10 @@
package com.tencent.supersonic.common.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.tencent.supersonic.common.util.TraceIdUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

View File

@@ -528,7 +528,7 @@ public class SqlReplaceHelper {
}
}
private static Select replaceAggAliasOrderItem(Select selectStatement) {
private static Select replaceAggAliasOrderbyField(Select selectStatement) {
if (selectStatement instanceof PlainSelect) {
PlainSelect plainSelect = (PlainSelect) selectStatement;
if (Objects.nonNull(plainSelect.getOrderByElements())) {
@@ -564,15 +564,15 @@ public class SqlReplaceHelper {
if (plainSelect.getFromItem() instanceof ParenthesedSelect) {
ParenthesedSelect parenthesedSelect = (ParenthesedSelect) plainSelect.getFromItem();
parenthesedSelect
.setSelect(replaceAggAliasOrderItem(parenthesedSelect.getSelect()));
.setSelect(replaceAggAliasOrderbyField(parenthesedSelect.getSelect()));
}
return selectStatement;
}
return selectStatement;
}
public static String replaceAggAliasOrderItem(String sql) {
Select selectStatement = replaceAggAliasOrderItem(SqlSelectHelper.getSelect(sql));
public static String replaceAggAliasOrderbyField(String sql) {
Select selectStatement = replaceAggAliasOrderbyField(SqlSelectHelper.getSelect(sql));
return selectStatement.toString();
}

View File

@@ -74,7 +74,6 @@ public class SqlValidHelper {
CCJSqlParserUtil.parse(sql);
return true;
} catch (Exception e) {
log.error("isValidSQL parse:{}", e);
return false;
}
}

View File

@@ -1,8 +1,7 @@
package com.tencent.supersonic.common.pojo;
import javax.validation.constraints.NotBlank;
import com.tencent.supersonic.common.pojo.enums.AggOperatorEnum;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import java.util.List;

View File

@@ -8,7 +8,6 @@ import lombok.Data;
@Builder
public class DataItem {
/** * This field uses an underscore (_) at the end. */
private String id;
private String bizName;
@@ -19,9 +18,10 @@ public class DataItem {
private TypeEnums type;
/** * This field uses an underscore (_) at the end. */
private String modelId;
private String domainId;
private String defaultAgg;
public String getNewName() {

View File

@@ -2,6 +2,7 @@ package com.tencent.supersonic.common.pojo;
import com.tencent.supersonic.common.pojo.enums.FilterOperatorEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@@ -10,6 +11,7 @@ import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Filter {
private Relation relation = Relation.FILTER;

View File

@@ -1,5 +1,6 @@
package com.tencent.supersonic.common.pojo;
import com.google.common.collect.Lists;
import lombok.Data;
import java.util.List;
@@ -18,5 +19,5 @@ public class ModelRela extends RecordInfo {
// left join, inner join, right join, outer join
private String joinType;
private List<JoinCondition> joinConditions;
private List<JoinCondition> joinConditions = Lists.newArrayList();
}

View File

@@ -1,8 +1,7 @@
package com.tencent.supersonic.common.pojo;
import javax.validation.constraints.NotBlank;
import com.google.common.base.Objects;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import static com.tencent.supersonic.common.pojo.Constants.ASC_UPPER;

View File

@@ -1,5 +1,5 @@
package com.tencent.supersonic.common.pojo.enums;
public enum AuthType {
VISIBLE, ADMIN
VIEWER, ADMIN
}

View File

@@ -14,8 +14,6 @@ public enum DictWordType {
DATASET("dataSet"),
ENTITY("entity"),
NUMBER("m"),
TAG("tag"),

View File

@@ -8,7 +8,8 @@ public enum EngineType {
KAFKA(4, "kafka"),
H2(5, "h2"),
POSTGRESQL(6, "postgresql"),
OTHER(7, "other");
OTHER(7, "other"),
DUCKDB(8, "duckdb");
private Integer code;

View File

@@ -5,9 +5,7 @@ public enum QueryType {
/** queries with aggregation (optionally slice and dice by dimensions) */
AGGREGATE,
/** queries with field selection */
DETAIL,
/** queries with ID-based entity selection */
ID;
DETAIL;
public boolean isNativeAggQuery() {
return DETAIL.equals(this);

View File

@@ -1,7 +1,7 @@
package com.tencent.supersonic.common.pojo.enums;
public enum Text2SQLType {
ONLY_RULE, LLM_OR_RULE;
ONLY_RULE, LLM_OR_RULE, NONE;
public boolean enableLLM() {
return this.equals(LLM_OR_RULE);

View File

@@ -1,5 +1,5 @@
package com.tencent.supersonic.common.pojo.enums;
public enum TypeEnums {
METRIC, DIMENSION, TAG_OBJECT, TAG, DOMAIN, ENTITY, DATASET, MODEL, UNKNOWN
METRIC, DIMENSION, TAG, DOMAIN, DATASET, MODEL, UNKNOWN
}

View File

@@ -4,6 +4,7 @@ import com.tencent.supersonic.common.pojo.Constants;
import com.tencent.supersonic.common.pojo.DateConf;
import com.tencent.supersonic.common.pojo.ItemDateResp;
import com.tencent.supersonic.common.pojo.enums.DatePeriodEnum;
import com.tencent.supersonic.common.pojo.enums.TimeDimensionEnum;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
@@ -32,14 +33,9 @@ import static com.tencent.supersonic.common.pojo.Constants.MONTH_FORMAT;
@Data
public class DateModeUtils {
@Value("${s2.query.parameter.sys.date:sys_imp_date}")
private String sysDateCol;
@Value("${s2.query.parameter.sys.month:sys_imp_month}")
private String sysDateMonthCol;
@Value("${s2.query.parameter.sys.month:sys_imp_week}")
private String sysDateWeekCol;
private final String sysDateCol = TimeDimensionEnum.DAY.getName();
private final String sysDateMonthCol = TimeDimensionEnum.MONTH.getName();
private final String sysDateWeekCol = TimeDimensionEnum.WEEK.getName();
@Value("${s2.query.parameter.sys.zipper.begin:start_}")
private String sysZipperDateColBegin;

View File

@@ -16,6 +16,7 @@ import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Objects;
@@ -201,6 +202,13 @@ public class DateUtils {
return false;
}
public static Long calculateDiffMs(Date createAt) {
Calendar calendar = Calendar.getInstance();
Date now = calendar.getTime();
long milliseconds = now.getTime() - createAt.getTime();
return milliseconds;
}
public static boolean isDateString(String value, String format) {
try {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);

View File

@@ -26,7 +26,7 @@ public class PgvectorEmbeddingStoreFactory extends BaseEmbeddingStoreFactory {
embeddingStore.setPort(storeConfig.getPost());
embeddingStore.setDatabase(storeConfig.getDatabaseName());
embeddingStore.setUser(storeConfig.getUser());
embeddingStore.setPassword(storeConfig.getApiKey());
embeddingStore.setPassword(storeConfig.getPassword());
return embeddingStore;
}

View File

@@ -1,6 +1,7 @@
package dev.langchain4j.store.embedding;
import com.alibaba.fastjson.JSONObject;
import com.tencent.supersonic.common.pojo.Constants;
import com.tencent.supersonic.common.pojo.DataItem;
import dev.langchain4j.data.document.Metadata;
import dev.langchain4j.data.segment.TextSegment;
@@ -17,10 +18,18 @@ public class TextSegmentConvert {
public static final String QUERY_ID = "queryId";
public static List<TextSegment> convertToEmbedding(List<DataItem> dataItems) {
return dataItems.stream().map(dataItem -> {
Map meta = JSONObject.parseObject(JSONObject.toJSONString(dataItem), Map.class);
TextSegment textSegment = TextSegment.from(dataItem.getName(), new Metadata(meta));
addQueryId(textSegment, dataItem.getId() + dataItem.getType().name().toLowerCase());
return dataItems.stream().map(item -> {
// suffix with underscore to avoid embedding issue
DataItem newItem = DataItem.builder().domainId(item.getDomainId())
.bizName(item.getBizName()).type(item.getType()).newName(item.getNewName())
.defaultAgg(item.getDefaultAgg()).name(item.getName())
.id(item.getId() + Constants.UNDERLINE)
.modelId(item.getModelId() + Constants.UNDERLINE)
.domainId(item.getDomainId() + Constants.UNDERLINE).build();
Map meta = JSONObject.parseObject(JSONObject.toJSONString(newItem), Map.class);
TextSegment textSegment = TextSegment.from(newItem.getName(), new Metadata(meta));
addQueryId(textSegment, newItem.getId() + newItem.getType().name().toLowerCase());
return textSegment;
}).collect(Collectors.toList());
}

View File

@@ -325,10 +325,10 @@ class SqlReplaceHelperTest {
}
@Test
void testReplaceAggAliasOrderItem() {
void testReplaceAggAliasOrderbyField() {
String sql = "SELECT SUM(访问次数) AS top10总播放量 FROM (SELECT 部门, SUM(访问次数) AS 访问次数 FROM 超音数 "
+ "GROUP BY 部门 ORDER BY SUM(访问次数) DESC LIMIT 10) AS top10";
String replaceSql = SqlReplaceHelper.replaceAggAliasOrderItem(sql);
String replaceSql = SqlReplaceHelper.replaceAggAliasOrderbyField(sql);
Assert.assertEquals(
"SELECT SUM(访问次数) AS top10总播放量 FROM (SELECT 部门, SUM(访问次数) AS 访问次数 FROM 超音数 "
+ "GROUP BY 部门 ORDER BY 2 DESC LIMIT 10) AS top10",

View File

@@ -7,14 +7,13 @@ WORKDIR /usr/src/app
# Argument to pass in the supersonic version at build time
ARG SUPERSONIC_VERSION
# Install necessary packages, including MySQL client
RUN apt-get update && \
apt-get install -y default-mysql-client unzip && \
rm -rf /var/lib/apt/lists/*
RUN apt-get update
# Install necessary packages, including Postgres client
RUN apt-get update && apt-get install -y postgresql-client
# Install the vim editor.
RUN apt-get update && \
apt-get install -y vim && \
RUN apt-get update && apt-get install -y vim && \
rm -rf /var/lib/apt/lists/*
# Update the package list and install iputils-ping.
@@ -40,4 +39,4 @@ WORKDIR /usr/src/app/supersonic-standalone-${SUPERSONIC_VERSION}
EXPOSE 9080
# Command to run the supersonic daemon
RUN chmod +x bin/supersonic-daemon.sh
CMD ["bash", "-c", "bin/supersonic-daemon.sh restart standalone prd && tail -f /dev/null"]
CMD ["bash", "-c", "bin/supersonic-daemon.sh restart standalone docker && tail -f /dev/null"]

32
docker/DockerfileS2 Normal file
View File

@@ -0,0 +1,32 @@
# Use an official OpenJDK runtime as a parent image
FROM supersonicbi/supersonic:0.9.8
# Set the working directory in the container
WORKDIR /usr/src/app
# Argument to pass in the supersonic version at build time
ARG SUPERSONIC_VERSION
# Install necessary packages, including Postgres client
RUN apt-get install -y postgresql-client
RUN rm /usr/src/app/supersonic-standalone-latest
# Copy the supersonic standalone zip file into the container
COPY assembly/build/supersonic-standalone-${SUPERSONIC_VERSION}.zip .
# Unzip the supersonic standalone zip
RUN unzip supersonic-standalone-${SUPERSONIC_VERSION}.zip && \
rm supersonic-standalone-${SUPERSONIC_VERSION}.zip
# Create a symbolic link to the supersonic installation directory
RUN ln -s /usr/src/app/supersonic-standalone-${SUPERSONIC_VERSION} /usr/src/app/supersonic-standalone-latest
# Set the working directory to the supersonic installation directory
WORKDIR /usr/src/app/supersonic-standalone-${SUPERSONIC_VERSION}
# Expose the default port
EXPOSE 9080
# Command to run the supersonic daemon
RUN chmod +x bin/supersonic-daemon.sh
CMD ["bash", "-c", "bin/supersonic-daemon.sh restart standalone docker && tail -f /dev/null"]

Some files were not shown because too many files have changed in this diff Show More