mirror of
https://github.com/tencentmusic/supersonic.git
synced 2025-12-11 03:58:14 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
40e0a58502 | ||
|
|
9723c2496e | ||
|
|
4b99736a38 | ||
|
|
36fd737440 | ||
|
|
93ca060c45 | ||
|
|
e1911bc81b | ||
|
|
6fe9ab79ed | ||
|
|
5ee5ab116f | ||
|
|
a6c4d10d70 | ||
|
|
0d65d03bee | ||
|
|
acca5e4538 | ||
|
|
233899ca3e | ||
|
|
aa218898ff | ||
|
|
cf1b5336c3 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -14,4 +14,5 @@ assembly/runtime/*
|
|||||||
*.umi/
|
*.umi/
|
||||||
/assembly/deploy
|
/assembly/deploy
|
||||||
/runtime
|
/runtime
|
||||||
**/.flattened-pom.xml
|
**/.flattened-pom.xml
|
||||||
|
__pycache__/
|
||||||
10
CHANGELOG.md
10
CHANGELOG.md
@@ -4,7 +4,17 @@
|
|||||||
- "Breaking Changes" describes any changes that may break existing functionality or cause
|
- "Breaking Changes" describes any changes that may break existing functionality or cause
|
||||||
compatibility issues with previous versions.
|
compatibility issues with previous versions.
|
||||||
|
|
||||||
|
## SuperSonic [0.7.3] - 2023-08-29
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- meet checkstyle code requirements
|
||||||
|
- save parseInfo after parsing
|
||||||
|
- add time statistics
|
||||||
|
- add agent
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
- dsl where condition is used for front-end display
|
||||||
|
- dsl remove context inheritance
|
||||||
|
|
||||||
## SuperSonic [0.7.2] - 2023-08-12
|
## SuperSonic [0.7.2] - 2023-08-12
|
||||||
|
|
||||||
|
|||||||
44
README.md
44
README.md
@@ -10,35 +10,39 @@ English | [中文](README_CN.md)
|
|||||||
|
|
||||||
The emergence of Large Language Model (LLM) like ChatGPT is reshaping the way information is retrieved. In the field of data analytics, both academia and industry are primarily focused on leveraging LLM to convert natural language queries into SQL queries. While some works show promising results, they are still not applicable to real-world scenarios.
|
The emergence of Large Language Model (LLM) like ChatGPT is reshaping the way information is retrieved. In the field of data analytics, both academia and industry are primarily focused on leveraging LLM to convert natural language queries into SQL queries. While some works show promising results, they are still not applicable to real-world scenarios.
|
||||||
|
|
||||||
From our perspective, the key to filling the real-world gap lies in two aspects:
|
From our perspective, the key to filling the real-world gap lies in three aspects:
|
||||||
1. Utilize a combination of rule-based and model-based semantic parsers to deal with different scenarios.
|
1. Complement the LLM-based semantic parser with rule-based semantic parsers to improve **efficiency**(in terms of latency and cost).
|
||||||
2. Introduce a semantic model layer encapsulating the underlying data complexity(joins, formulas, etc) to simplify semantic parsing.
|
2. Augment semantic parsing with schema mappers(as a kind of preprocessor) and semantic correctors(as a kind of postprocessor) to improve **accuracy** and **stability**.
|
||||||
|
3. Introduce a semantic layer encapsulating underlying data context(joins, formulas, etc) to reduce **complexity**.
|
||||||
|
|
||||||
With these ideas in mind, we develop SuperSonic as a practical reference implementation and use it to power our real-world products. Additionally, to facilitate further development of data chatbot, we decide to open source SuperSonic as an extensible framework.
|
With these ideas in mind, we develop SuperSonic as a practical reference implementation and use it to power our real-world products. Additionally, to facilitate further development of data chatbot, we decide to open source SuperSonic as an extensible framework.
|
||||||
|
|
||||||
## Out-of-the-box Features
|
## Out-of-the-box Features
|
||||||
|
|
||||||
- Built-in graphical interface for business users to enter data queries
|
- Built-in CUI(Chat User Interface) for *business users* to enter data queries
|
||||||
- Built-in graphical interface for analytics engineers to manage semantic models
|
- Built-in GUI(Graphical User Interface) for *analytics engineers* to build semantic models
|
||||||
|
- Built-in GUI for *system administrators* to manage chat plugins and agents
|
||||||
- Support input auto-completion as well as query recommendation
|
- Support input auto-completion as well as query recommendation
|
||||||
- Support multi-turn conversation and history context management
|
- Support multi-turn conversation and history context management
|
||||||
- Support three-level permission control: domain-level, column-level and row-level
|
- Support four-level permission control: domain-level, model-level, column-level and row-level
|
||||||
|
|
||||||
## Extensible Components
|
## Extensible Components
|
||||||
|
|
||||||
The high-level architecture and main process flow is shown in below diagram:
|
The high-level architecture and main process flow is as follows:
|
||||||
|
|
||||||
<img src="./docs/images/supersonic_components.png" height="80%" width="80%" align="center"/>
|
<img src="./docs/images/supersonic_components.png" height="65%" width="65%" align="center"/>
|
||||||
|
|
||||||
- **Chat Interface:** accepts natural language queries and answer results with appropriate visualization charts. It supports input auto-completion as well as multi-turn conversation.
|
- **Knowledge Base:** extracts schema information periodically from the semantic models and build dictionary and index to facilitate schema mapping.
|
||||||
|
|
||||||
- **Modeling Interface:** empowers analytics engineers to visually define and maintain semantic models. The configurations related to access permission and chat conversation can also be set on the UI.
|
- **Schema Mapper:** identifies references to schema elements(metrics/dimensions/entities/values) in user queries. It matches the query text against the knowledge base.
|
||||||
|
|
||||||
- **Schema Mapper Chain:** identifies references to schema elements(metrics/dimensions/entities/values) in user queries. It matches the query text against a knowledge base constructed from the semantic models.
|
- **Semantic Parser:** understands user queries and extracts semantic information. It consists of a combination of rule-based and model-based parsers, each of which deals with specific scenarios.
|
||||||
|
|
||||||
- **Semantic Parser Chain:** understands user queries and extract semantic information. It consists of a combination of rule-based and model-based parsers, each of which deals with specific scenarios.
|
- **Semantic Corrector:** checks validity of extracted semantic information and performs correction and optimization if needed.
|
||||||
|
|
||||||
- **Semantic Query:** performs execution according to extracted semantic information. It generates SQL queries and executes them against physical data models.
|
- **Semantic Layer:** performs execution according to extracted semantic information. It generates SQL queries and executes them against physical data models.
|
||||||
|
|
||||||
|
- **Chat Plugin:** extends functionality with third-party tools. The LLM is going to select the most suitable one, given all configured plugins with function description and sample questions.
|
||||||
|
|
||||||
## Quick Demo
|
## Quick Demo
|
||||||
|
|
||||||
@@ -46,11 +50,11 @@ SuperSonic comes with sample semantic models as well as chat conversations that
|
|||||||
|
|
||||||
- Download the latest prebuilt binary from the [release page](https://github.com/tencentmusic/supersonic/releases)
|
- Download the latest prebuilt binary from the [release page](https://github.com/tencentmusic/supersonic/releases)
|
||||||
- Run script "bin/start-standalone.sh" to start a standalone server
|
- Run script "bin/start-standalone.sh" to start a standalone server
|
||||||
- Visit http://localhost:9080 in browser to start exploration
|
- Visit http://localhost:9080 in the browser to start exploration
|
||||||
|
|
||||||
## How to Build
|
## How to Build
|
||||||
|
|
||||||
SuperSonic can be deployed in two modes: standalone (intended for quick demo) and distributed (intended for production).
|
SuperSonic can be deployed in two modes: standalone (for a quick demo) and distributed (for production use).
|
||||||
|
|
||||||
### Build for Standalone Mode
|
### Build for Standalone Mode
|
||||||
|
|
||||||
@@ -59,3 +63,13 @@ Pull the source code and run script "assembly/bin/build-standalone.sh" to build
|
|||||||
### Build for Distributed Mode
|
### Build for Distributed Mode
|
||||||
|
|
||||||
Pull the source code and run scripts "assembly/bin/build-chat.sh" and "assembly/bin/build-semantic.sh" separately to build packages.
|
Pull the source code and run scripts "assembly/bin/build-chat.sh" and "assembly/bin/build-semantic.sh" separately to build packages.
|
||||||
|
|
||||||
|
### Build for Local Development
|
||||||
|
|
||||||
|
Pull the source code and run script "assembly/bin/build-ide.sh" and run bootstrap class "StandaloneLauncher" in the IDE.
|
||||||
|
|
||||||
|
## WeChat Contact
|
||||||
|
|
||||||
|
Please join the chat group to suggest feedbacks or ideas:
|
||||||
|
|
||||||
|
<img src="./docs/images/wechat_contact.jpeg" height="30%" width="30%" align="center"/>
|
||||||
42
README_CN.md
42
README_CN.md
@@ -8,35 +8,39 @@
|
|||||||
|
|
||||||
大型语言模型(LLMs)如ChatGPT的出现正在重塑信息检索的方式。在数据分析领域,学术界和工业界主要关注利用深度学习模型将自然语言查询转换为SQL查询。虽然一些工作显示出有前景的结果,但它们还并不适用于实际场景。
|
大型语言模型(LLMs)如ChatGPT的出现正在重塑信息检索的方式。在数据分析领域,学术界和工业界主要关注利用深度学习模型将自然语言查询转换为SQL查询。虽然一些工作显示出有前景的结果,但它们还并不适用于实际场景。
|
||||||
|
|
||||||
在我们看来,为了在实际场景发挥价值,有两个关键点:
|
在我们看来,为了在实际场景发挥价值,有三个关键点:
|
||||||
1. 将基于规则和基于模型的语义解析器相结合,发挥各自优势,以便处理不同的场景。
|
1. 在基于大模型语义解析器基础上,增加基于规则的解析器,提升语义解析的**效率**。
|
||||||
2. 引入语义模型层来封装数据底层的复杂性(关联、公式等),从而简化语义解析的求解空间。
|
2. 加入模式映射器和语义修正器,来增强语义解析能力,提升语义解析的**准确性**和**稳定性**。
|
||||||
|
3. 引入语义模型层,封装底层数据的上下文(关联、公式等),降低语义解析的**复杂性**。
|
||||||
|
|
||||||
为了验证上述想法,我们开发了超音数项目,并将其应用在实际的内部产品中。与此同时,我们将超音数作为一个可扩展的框架开源,希望能够促进数据问答对话领域的进一步发展。
|
为了验证上述想法,我们开发了超音数项目,并将其应用在实际的内部产品中。与此同时,我们将超音数作为一个可扩展的框架开源,希望能够促进数据问答对话领域的进一步发展。
|
||||||
|
|
||||||
## 开箱即用的特性
|
## 开箱即用的特性
|
||||||
|
|
||||||
- 内置图形界面以便业务用户输入数据查询。
|
- 内置对话界面以便*业务用户*输入数据查询。
|
||||||
- 内置图形界面以便分析工程师管理语义模型。
|
- 内置图形界面以便*分析工程师*构建语义模型。
|
||||||
|
- 内置图形界面以便*系统管理员*管理问答插件和助理。
|
||||||
- 支持文本输入的联想和查询问题的推荐。
|
- 支持文本输入的联想和查询问题的推荐。
|
||||||
- 支持多轮对话,根据语境自动切换上下文。
|
- 支持多轮对话,根据语境自动切换上下文。
|
||||||
- 支持三级权限控制:主题域级、列级、行级。
|
- 支持四级权限控制:主题域级、模型级、列级、行级。
|
||||||
|
|
||||||
## 易于扩展的组件
|
## 易于扩展的组件
|
||||||
|
|
||||||
超音数的整体架构和主流程如下图所示:
|
超音数的整体架构和主流程如下图所示:
|
||||||
|
|
||||||
<img src="./docs/images/supersonic_components.png" height="80%" width="80%" align="center"/>
|
<img src="./docs/images/supersonic_components.png" height="65%" width="65%" align="center"/>
|
||||||
|
|
||||||
- **问答对话界面(chat interface)**:接受用户查询并选择合适的可视化图表呈现结果,支持输入联想和多轮对话。
|
- **知识库(Knowledge Base):** 定期从语义模型中提取相关的模式信息,构建词典和索引,以便后续的模式映射。
|
||||||
|
|
||||||
- **语义建模界面(modeling interface)**:使分析工程师能够通过可视化方式定义和维护语义模型,与访问权限和聊天对话相关的配置也可以在用户界面上设置。
|
- **模式映射器(Schema Mapper):** 将自然语言文本在知识库中进行匹配,为后续的语义解析提供相关信息。
|
||||||
|
|
||||||
- **模式映射器(schema mapper chain)**:基于语义模型构建知识库,然后将自然语言文本在知识库中进行匹配,为后续的语义解析提供相关信息。
|
- **语义解析器(Semantic Parser):** 理解用户查询并抽取语义信息,其由一组基于规则和基于模型的解析器组成,每个解析器可应对不同的特定场景。
|
||||||
|
|
||||||
- **语义解析器(semantic parser chain)**:理解用户查询并抽取语义信息,其由一组基于规则和基于模型的解析器组成,每个解析器可应对不同的特定场景。
|
- **语义修正器(Semantic Corrector):** 检查语义信息的合法性,对不合法的信息做修正和优化处理。
|
||||||
|
|
||||||
- **语义查询(semantic query)**: 根据语义信息生成物理SQL执行查询。
|
- **语义模型层(Semantic Layer):** 根据语义信息生成物理SQL执行查询。
|
||||||
|
|
||||||
|
- **问答插件(Chat Plugin):** 通过第三方工具扩展功能。给定所有配置的插件及其功能描述和示例问题,大语言模型将选择最合适的插件。
|
||||||
|
|
||||||
## 快速体验
|
## 快速体验
|
||||||
|
|
||||||
@@ -52,8 +56,18 @@
|
|||||||
|
|
||||||
### Standalone模式构建
|
### Standalone模式构建
|
||||||
|
|
||||||
下载源码包,运行脚本"assembly/bin/build-standalone.sh",将所有服务一起编译打包
|
下载源码包,运行脚本"assembly/bin/build-standalone.sh",将所有服务一起编译打包。
|
||||||
|
|
||||||
### Distributed模式构建
|
### Distributed模式构建
|
||||||
|
|
||||||
下载源码包,分别运行脚本"assembly/bin/build-chat.sh"、"assembly/bin/build-semantic.sh",为问答层服务和语义层服务编译打包
|
下载源码包,分别运行脚本"assembly/bin/build-chat.sh"、"assembly/bin/build-semantic.sh",为问答层服务和语义层服务编译打包。
|
||||||
|
|
||||||
|
### 本地开发构建
|
||||||
|
|
||||||
|
下载源码包,运行脚本"assembly/bin/build-ide.sh",然后在本地IDE运行启动类"StandaloneLauncher"。
|
||||||
|
|
||||||
|
## 微信联系方式
|
||||||
|
|
||||||
|
欢迎加入微信群反馈建议:
|
||||||
|
|
||||||
|
<img src="./docs/images/wechat_contact.jpeg" height="30%" width="30%" align="center"/>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
sbinDir=$(cd "$(dirname "$0")"; pwd)
|
sbinDir=$(cd "$(dirname "$0")"; pwd)
|
||||||
baseDir=$(readlink -f $sbinDir/../)
|
baseDir=$(cd "$sbinDir/.." && pwd -P)
|
||||||
runtimeDir=$baseDir/runtime
|
runtimeDir=$baseDir/runtime
|
||||||
buildDir=$baseDir/build
|
buildDir=$baseDir/build
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
sbinDir=$(cd "$(dirname "$0")"; pwd)
|
sbinDir=$(cd "$(dirname "$0")"; pwd)
|
||||||
baseDir=$(readlink -f $sbinDir/../)
|
baseDir=$(cd "$sbinDir/.." && pwd -P)
|
||||||
buildDir=$baseDir/build
|
buildDir=$baseDir/build
|
||||||
|
|
||||||
cd $baseDir/bin
|
cd $baseDir/bin
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
sbinDir=$(cd "$(dirname "$0")"; pwd)
|
sbinDir=$(cd "$(dirname "$0")"; pwd)
|
||||||
baseDir=$(readlink -f $sbinDir/../)
|
baseDir=$(cd "$sbinDir/.." && pwd -P)
|
||||||
runtimeDir=$baseDir/runtime
|
runtimeDir=$baseDir/runtime
|
||||||
buildDir=$baseDir/build
|
buildDir=$baseDir/build
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
sbinDir=$(cd "$(dirname "$0")"; pwd)
|
sbinDir=$(cd "$(dirname "$0")"; pwd)
|
||||||
baseDir=$(readlink -f $sbinDir/../)
|
baseDir=$(cd "$sbinDir/.." && pwd -P)
|
||||||
runtimeDir=$baseDir/runtime
|
runtimeDir=$baseDir/runtime
|
||||||
buildDir=$baseDir/build
|
buildDir=$baseDir/build
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
sbinDir=$(cd "$(dirname "$0")"; pwd)
|
sbinDir=$(cd "$(dirname "$0")"; pwd)
|
||||||
baseDir=$(readlink -f $sbinDir/../)
|
baseDir=$(cd "$sbinDir/.." && pwd -P)
|
||||||
runtimeDir=$baseDir/../runtime
|
runtimeDir=$baseDir/../runtime
|
||||||
buildDir=$baseDir/build
|
buildDir=$baseDir/build
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
sbinDir=$(cd "$(dirname "$0")"; pwd)
|
sbinDir=$(cd "$(dirname "$0")"; pwd)
|
||||||
baseDir=$(readlink -f $sbinDir/../)
|
baseDir=$(cd "$sbinDir/.." && pwd -P)
|
||||||
runtimeDir=$baseDir/../runtime
|
runtimeDir=$baseDir/../runtime
|
||||||
buildDir=$baseDir/build
|
buildDir=$baseDir/build
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
sbinDir=$(cd "$(dirname "$0")"; pwd)
|
sbinDir=$(cd "$(dirname "$0")"; pwd)
|
||||||
baseDir=$(readlink -f $sbinDir/../)
|
baseDir=$(cd "$sbinDir/.." && pwd -P)
|
||||||
runtimeDir=$baseDir/../runtime
|
runtimeDir=$baseDir/../runtime
|
||||||
buildDir=$baseDir/build
|
buildDir=$baseDir/build
|
||||||
|
|
||||||
@@ -29,4 +29,4 @@ rm -fr ${buildDir}/supersonic-webapp
|
|||||||
#start standalone service
|
#start standalone service
|
||||||
sh ${runtimeDir}/supersonic-standalone/bin/service.sh restart
|
sh ${runtimeDir}/supersonic-standalone/bin/service.sh restart
|
||||||
#start llm service
|
#start llm service
|
||||||
sh ${runtimeDir}/supersonic-standalone/llm/bin/service.sh restart
|
sh ${runtimeDir}/supersonic-standalone/llm/bin/service.sh restart
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ public class AuthenticationConfig {
|
|||||||
@Value("${authentication.token.secret:secret}")
|
@Value("${authentication.token.secret:secret}")
|
||||||
private String tokenSecret;
|
private String tokenSecret;
|
||||||
|
|
||||||
@Value("${authentication.token.http.header.key:Auth}")
|
@Value("${authentication.token.http.header.key:Authorization}")
|
||||||
private String tokenHttpHeaderKey;
|
private String tokenHttpHeaderKey;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ import lombok.ToString;
|
|||||||
@ToString
|
@ToString
|
||||||
public class QueryAuthResReq {
|
public class QueryAuthResReq {
|
||||||
|
|
||||||
private String user;
|
|
||||||
|
|
||||||
private List<String> departmentIds = new ArrayList<>();
|
private List<String> departmentIds = new ArrayList<>();
|
||||||
|
|
||||||
private List<AuthRes> resources;
|
private List<AuthRes> resources;
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
package com.tencent.supersonic.auth.api.authorization.service;
|
package com.tencent.supersonic.auth.api.authorization.service;
|
||||||
|
|
||||||
|
import com.tencent.supersonic.auth.api.authentication.pojo.User;
|
||||||
import com.tencent.supersonic.auth.api.authorization.pojo.AuthGroup;
|
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.request.QueryAuthResReq;
|
||||||
import com.tencent.supersonic.auth.api.authorization.response.AuthorizedResourceResp;
|
import com.tencent.supersonic.auth.api.authorization.response.AuthorizedResourceResp;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
public interface AuthService {
|
public interface AuthService {
|
||||||
|
|
||||||
@@ -14,5 +15,5 @@ public interface AuthService {
|
|||||||
|
|
||||||
void removeAuthGroup(AuthGroup group);
|
void removeAuthGroup(AuthGroup group);
|
||||||
|
|
||||||
AuthorizedResourceResp queryAuthorizedResources(QueryAuthResReq req, HttpServletRequest request);
|
AuthorizedResourceResp queryAuthorizedResources(QueryAuthResReq req, User user);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
package com.tencent.supersonic.auth.authentication.config;
|
|
||||||
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Configuration
|
|
||||||
public class TppConfig {
|
|
||||||
|
|
||||||
@Value(value = "${auth.app.secret:}")
|
|
||||||
private String appSecret;
|
|
||||||
|
|
||||||
@Value(value = "${auth.app.key:}")
|
|
||||||
private String appKey;
|
|
||||||
|
|
||||||
@Value(value = "${auth.oa.url:}")
|
|
||||||
private String tppOaUrl;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.tencent.supersonic.auth.authentication.persistence.repository.Impl;
|
package com.tencent.supersonic.auth.authentication.persistence.repository.impl;
|
||||||
|
|
||||||
|
|
||||||
import com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDO;
|
import com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDO;
|
||||||
|
|||||||
@@ -11,12 +11,12 @@ import java.util.Set;
|
|||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/auth/user")
|
@RequestMapping("/api/auth/user")
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import static com.tencent.supersonic.auth.api.authentication.constant.UserConsta
|
|||||||
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_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_NAME;
|
||||||
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_USER_PASSWORD;
|
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_USER_PASSWORD;
|
||||||
|
|
||||||
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
|
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
|
||||||
import com.tencent.supersonic.auth.api.authentication.pojo.User;
|
import com.tencent.supersonic.auth.api.authentication.pojo.User;
|
||||||
import com.tencent.supersonic.auth.api.authentication.pojo.UserWithPassword;
|
import com.tencent.supersonic.auth.api.authentication.pojo.UserWithPassword;
|
||||||
@@ -22,9 +21,11 @@ import java.util.Date;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
public class UserTokenUtils {
|
public class UserTokenUtils {
|
||||||
|
|
||||||
@@ -68,7 +69,9 @@ public class UserTokenUtils {
|
|||||||
public UserWithPassword getUserWithPassword(HttpServletRequest request) {
|
public UserWithPassword getUserWithPassword(HttpServletRequest request) {
|
||||||
String token = request.getHeader(authenticationConfig.getTokenHttpHeaderKey());
|
String token = request.getHeader(authenticationConfig.getTokenHttpHeaderKey());
|
||||||
if (StringUtils.isBlank(token)) {
|
if (StringUtils.isBlank(token)) {
|
||||||
throw new AccessException("token is blank, get user failed");
|
String message = "token is blank, get user failed";
|
||||||
|
log.warn("{}, uri: {}", message, request.getServletPath());
|
||||||
|
throw new AccessException(message);
|
||||||
}
|
}
|
||||||
final Claims claims = getClaims(token);
|
final Claims claims = getClaims(token);
|
||||||
Long userId = Long.parseLong(claims.getOrDefault(TOKEN_USER_ID, 0).toString());
|
Long userId = Long.parseLong(claims.getOrDefault(TOKEN_USER_ID, 0).toString());
|
||||||
|
|||||||
@@ -2,27 +2,27 @@ package com.tencent.supersonic.auth.authorization.application;
|
|||||||
|
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
import com.tencent.supersonic.auth.api.authentication.pojo.User;
|
||||||
import com.tencent.supersonic.auth.api.authentication.service.UserService;
|
import com.tencent.supersonic.auth.api.authentication.service.UserService;
|
||||||
import com.tencent.supersonic.auth.api.authorization.pojo.AuthGroup;
|
|
||||||
import com.tencent.supersonic.auth.api.authorization.pojo.AuthRes;
|
import com.tencent.supersonic.auth.api.authorization.pojo.AuthRes;
|
||||||
import com.tencent.supersonic.auth.api.authorization.pojo.AuthResGrp;
|
import com.tencent.supersonic.auth.api.authorization.pojo.AuthResGrp;
|
||||||
import com.tencent.supersonic.auth.api.authorization.pojo.AuthRule;
|
|
||||||
import com.tencent.supersonic.auth.api.authorization.pojo.DimensionFilter;
|
import com.tencent.supersonic.auth.api.authorization.pojo.DimensionFilter;
|
||||||
import com.tencent.supersonic.auth.api.authorization.request.QueryAuthResReq;
|
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.response.AuthorizedResourceResp;
|
||||||
import com.tencent.supersonic.auth.api.authorization.service.AuthService;
|
import com.tencent.supersonic.auth.api.authorization.service.AuthService;
|
||||||
import java.util.ArrayList;
|
import com.tencent.supersonic.auth.api.authorization.pojo.AuthGroup;
|
||||||
import java.util.List;
|
import com.tencent.supersonic.auth.api.authorization.pojo.AuthRule;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@@ -33,7 +33,7 @@ public class AuthServiceImpl implements AuthService {
|
|||||||
private UserService userService;
|
private UserService userService;
|
||||||
|
|
||||||
public AuthServiceImpl(JdbcTemplate jdbcTemplate,
|
public AuthServiceImpl(JdbcTemplate jdbcTemplate,
|
||||||
UserService userService) {
|
UserService userService) {
|
||||||
this.jdbcTemplate = jdbcTemplate;
|
this.jdbcTemplate = jdbcTemplate;
|
||||||
this.userService = userService;
|
this.userService = userService;
|
||||||
}
|
}
|
||||||
@@ -78,12 +78,12 @@ public class AuthServiceImpl implements AuthService {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AuthorizedResourceResp queryAuthorizedResources(QueryAuthResReq req, HttpServletRequest request) {
|
public AuthorizedResourceResp queryAuthorizedResources(QueryAuthResReq req, User user) {
|
||||||
Set<String> userOrgIds = userService.getUserAllOrgId(req.getUser());
|
Set<String> userOrgIds = userService.getUserAllOrgId(user.getName());
|
||||||
if (!CollectionUtils.isEmpty(userOrgIds)) {
|
if (!CollectionUtils.isEmpty(userOrgIds)) {
|
||||||
req.setDepartmentIds(new ArrayList<>(userOrgIds));
|
req.setDepartmentIds(new ArrayList<>(userOrgIds));
|
||||||
}
|
}
|
||||||
List<AuthGroup> groups = getAuthGroups(req);
|
List<AuthGroup> groups = getAuthGroups(req, user.getName());
|
||||||
AuthorizedResourceResp resource = new AuthorizedResourceResp();
|
AuthorizedResourceResp resource = new AuthorizedResourceResp();
|
||||||
Map<String, List<AuthGroup>> authGroupsByModelId = groups.stream()
|
Map<String, List<AuthGroup>> authGroupsByModelId = groups.stream()
|
||||||
.collect(Collectors.groupingBy(AuthGroup::getModelId));
|
.collect(Collectors.groupingBy(AuthGroup::getModelId));
|
||||||
@@ -130,14 +130,14 @@ public class AuthServiceImpl implements AuthService {
|
|||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<AuthGroup> getAuthGroups(QueryAuthResReq req) {
|
private List<AuthGroup> getAuthGroups(QueryAuthResReq req, String userName) {
|
||||||
List<AuthGroup> groups = load().stream()
|
List<AuthGroup> groups = load().stream()
|
||||||
.filter(group -> {
|
.filter(group -> {
|
||||||
if (!Objects.equals(group.getModelId(), req.getModelId())) {
|
if (!Objects.equals(group.getModelId(), req.getModelId())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!CollectionUtils.isEmpty(group.getAuthorizedUsers()) && group.getAuthorizedUsers()
|
if (!CollectionUtils.isEmpty(group.getAuthorizedUsers()) && group.getAuthorizedUsers()
|
||||||
.contains(req.getUser())) {
|
.contains(userName)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for (String departmentId : req.getDepartmentIds()) {
|
for (String departmentId : req.getDepartmentIds()) {
|
||||||
@@ -148,7 +148,7 @@ public class AuthServiceImpl implements AuthService {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}).collect(Collectors.toList());
|
}).collect(Collectors.toList());
|
||||||
log.info("user:{} department:{} authGroups:{}", req.getUser(), req.getDepartmentIds(), groups);
|
log.info("user:{} department:{} authGroups:{}", userName, req.getDepartmentIds(), groups);
|
||||||
return groups;
|
return groups;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
package com.tencent.supersonic.auth.authorization.rest;
|
package com.tencent.supersonic.auth.authorization.rest;
|
||||||
|
|
||||||
import com.tencent.supersonic.auth.api.authorization.pojo.AuthGroup;
|
import com.tencent.supersonic.auth.api.authentication.pojo.User;
|
||||||
|
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
|
||||||
import com.tencent.supersonic.auth.api.authorization.request.QueryAuthResReq;
|
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.response.AuthorizedResourceResp;
|
||||||
import com.tencent.supersonic.auth.api.authorization.service.AuthService;
|
import com.tencent.supersonic.auth.api.authorization.service.AuthService;
|
||||||
|
import com.tencent.supersonic.auth.api.authorization.pojo.AuthGroup;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
@@ -62,12 +65,13 @@ public class AuthController {
|
|||||||
* 查询有权限访问的受限资源id
|
* 查询有权限访问的受限资源id
|
||||||
*
|
*
|
||||||
* @param req
|
* @param req
|
||||||
* @param request
|
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@PostMapping("/queryAuthorizedRes")
|
@PostMapping("/queryAuthorizedRes")
|
||||||
public AuthorizedResourceResp queryAuthorizedResources(@RequestBody QueryAuthResReq req,
|
public AuthorizedResourceResp queryAuthorizedResources(@RequestBody QueryAuthResReq req,
|
||||||
HttpServletRequest request) {
|
HttpServletRequest request,
|
||||||
return authService.queryAuthorizedResources(req, request);
|
HttpServletResponse response) {
|
||||||
|
User user = UserHolder.findUser(request, response);
|
||||||
|
return authService.queryAuthorizedResources(req, user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.tencent.supersonic.chat.api.component;
|
||||||
|
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.CorrectionInfo;
|
||||||
|
import net.sf.jsqlparser.JSQLParserException;
|
||||||
|
|
||||||
|
public interface SemanticCorrector {
|
||||||
|
CorrectionInfo corrector(CorrectionInfo correctionInfo) throws JSQLParserException;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,14 +6,15 @@ import com.tencent.supersonic.chat.api.pojo.ModelSchema;
|
|||||||
import com.tencent.supersonic.common.pojo.enums.AuthType;
|
import com.tencent.supersonic.common.pojo.enums.AuthType;
|
||||||
import com.tencent.supersonic.semantic.api.model.request.PageDimensionReq;
|
import com.tencent.supersonic.semantic.api.model.request.PageDimensionReq;
|
||||||
import com.tencent.supersonic.semantic.api.model.request.PageMetricReq;
|
import com.tencent.supersonic.semantic.api.model.request.PageMetricReq;
|
||||||
import com.tencent.supersonic.semantic.api.model.response.DimensionResp;
|
|
||||||
import com.tencent.supersonic.semantic.api.model.response.DomainResp;
|
import com.tencent.supersonic.semantic.api.model.response.DomainResp;
|
||||||
import com.tencent.supersonic.semantic.api.model.response.MetricResp;
|
import com.tencent.supersonic.semantic.api.model.response.DimensionResp;
|
||||||
import com.tencent.supersonic.semantic.api.model.response.ModelResp;
|
import com.tencent.supersonic.semantic.api.model.response.ModelResp;
|
||||||
|
import com.tencent.supersonic.semantic.api.model.response.MetricResp;
|
||||||
import com.tencent.supersonic.semantic.api.model.response.QueryResultWithSchemaResp;
|
import com.tencent.supersonic.semantic.api.model.response.QueryResultWithSchemaResp;
|
||||||
import com.tencent.supersonic.semantic.api.query.request.QueryDslReq;
|
import com.tencent.supersonic.semantic.api.query.request.QueryDslReq;
|
||||||
import com.tencent.supersonic.semantic.api.query.request.QueryMultiStructReq;
|
import com.tencent.supersonic.semantic.api.query.request.QueryMultiStructReq;
|
||||||
import com.tencent.supersonic.semantic.api.query.request.QueryStructReq;
|
import com.tencent.supersonic.semantic.api.query.request.QueryStructReq;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -31,22 +32,13 @@ import java.util.List;
|
|||||||
public interface SemanticLayer {
|
public interface SemanticLayer {
|
||||||
|
|
||||||
QueryResultWithSchemaResp queryByStruct(QueryStructReq queryStructReq, User user);
|
QueryResultWithSchemaResp queryByStruct(QueryStructReq queryStructReq, User user);
|
||||||
|
|
||||||
QueryResultWithSchemaResp queryByMultiStruct(QueryMultiStructReq queryMultiStructReq, User user);
|
QueryResultWithSchemaResp queryByMultiStruct(QueryMultiStructReq queryMultiStructReq, User user);
|
||||||
|
|
||||||
QueryResultWithSchemaResp queryByDsl(QueryDslReq queryDslReq, User user);
|
QueryResultWithSchemaResp queryByDsl(QueryDslReq queryDslReq, User user);
|
||||||
|
|
||||||
List<ModelSchema> getModelSchema();
|
List<ModelSchema> getModelSchema();
|
||||||
|
|
||||||
List<ModelSchema> getModelSchema(List<Long> ids);
|
List<ModelSchema> getModelSchema(List<Long> ids);
|
||||||
|
|
||||||
ModelSchema getModelSchema(Long model, Boolean cacheEnable);
|
ModelSchema getModelSchema(Long model, Boolean cacheEnable);
|
||||||
|
|
||||||
PageInfo<DimensionResp> getDimensionPage(PageDimensionReq pageDimensionCmd);
|
PageInfo<DimensionResp> getDimensionPage(PageDimensionReq pageDimensionCmd);
|
||||||
|
|
||||||
PageInfo<MetricResp> getMetricPage(PageMetricReq pageMetricCmd);
|
PageInfo<MetricResp> getMetricPage(PageMetricReq pageMetricCmd);
|
||||||
|
|
||||||
List<DomainResp> getDomainList(User user);
|
List<DomainResp> getDomainList(User user);
|
||||||
|
|
||||||
List<ModelResp> getModelList(AuthType authType, Long domainId, User user);
|
List<ModelResp> getModelList(AuthType authType, Long domainId, User user);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import lombok.Data;
|
|||||||
public class ChatContext {
|
public class ChatContext {
|
||||||
|
|
||||||
private Integer chatId;
|
private Integer chatId;
|
||||||
|
private Integer agentId;
|
||||||
private String queryText;
|
private String queryText;
|
||||||
private SemanticParseInfo parseInfo = new SemanticParseInfo();
|
private SemanticParseInfo parseInfo = new SemanticParseInfo();
|
||||||
private String user;
|
private String user;
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.tencent.supersonic.chat.api.pojo;
|
||||||
|
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.request.QueryFilters;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class CorrectionInfo {
|
||||||
|
|
||||||
|
private QueryFilters queryFilters;
|
||||||
|
|
||||||
|
private SemanticParseInfo parseInfo;
|
||||||
|
|
||||||
|
private String sql;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -32,6 +32,7 @@ public class ModelSchema {
|
|||||||
break;
|
break;
|
||||||
case VALUE:
|
case VALUE:
|
||||||
element = dimensionValues.stream().filter(e -> e.getId() == elementID).findFirst();
|
element = dimensionValues.stream().filter(e -> e.getId() == elementID).findFirst();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,19 @@
|
|||||||
package com.tencent.supersonic.chat.api.pojo;
|
package com.tencent.supersonic.chat.api.pojo;
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.Builder;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Getter
|
@Getter
|
||||||
@Builder
|
@Builder
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
//@AllArgsConstructor
|
|
||||||
public class SchemaElement implements Serializable {
|
public class SchemaElement implements Serializable {
|
||||||
|
|
||||||
private Long model;
|
private Long model;
|
||||||
@@ -23,11 +24,8 @@ public class SchemaElement implements Serializable {
|
|||||||
private SchemaElementType type;
|
private SchemaElementType type;
|
||||||
private List<String> alias;
|
private List<String> alias;
|
||||||
|
|
||||||
// public SchemaElement() {
|
|
||||||
// }
|
|
||||||
|
|
||||||
public SchemaElement(Long model, Long id, String name, String bizName,
|
public SchemaElement(Long model, Long id, String name, String bizName,
|
||||||
Long useCnt, SchemaElementType type, List<String> alias) {
|
Long useCnt, SchemaElementType type, List<String> alias) {
|
||||||
this.model = model;
|
this.model = model;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|||||||
@@ -1,23 +1,26 @@
|
|||||||
package com.tencent.supersonic.chat.api.pojo;
|
package com.tencent.supersonic.chat.api.pojo;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.request.QueryFilter;
|
import com.tencent.supersonic.chat.api.pojo.request.QueryFilter;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.response.EntityInfo;
|
||||||
import com.tencent.supersonic.common.pojo.DateConf;
|
import com.tencent.supersonic.common.pojo.DateConf;
|
||||||
import com.tencent.supersonic.common.pojo.Order;
|
import com.tencent.supersonic.common.pojo.Order;
|
||||||
import com.tencent.supersonic.common.pojo.enums.AggregateTypeEnum;
|
import com.tencent.supersonic.common.pojo.enums.AggregateTypeEnum;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.TreeSet;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class SemanticParseInfo {
|
public class SemanticParseInfo {
|
||||||
|
|
||||||
|
private Integer id;
|
||||||
private String queryMode;
|
private String queryMode;
|
||||||
private SchemaElement model;
|
private SchemaElement model;
|
||||||
private Set<SchemaElement> metrics = new TreeSet<>(new SchemaNameLengthComparator());
|
private Set<SchemaElement> metrics = new TreeSet<>(new SchemaNameLengthComparator());
|
||||||
@@ -33,7 +36,7 @@ public class SemanticParseInfo {
|
|||||||
private double score;
|
private double score;
|
||||||
private List<SchemaElementMatch> elementMatches = new ArrayList<>();
|
private List<SchemaElementMatch> elementMatches = new ArrayList<>();
|
||||||
private Map<String, Object> properties = new HashMap<>();
|
private Map<String, Object> properties = new HashMap<>();
|
||||||
|
private EntityInfo entityInfo;
|
||||||
public Long getModelId() {
|
public Long getModelId() {
|
||||||
return model != null ? model.getId() : 0L;
|
return model != null ? model.getId() : 0L;
|
||||||
}
|
}
|
||||||
@@ -43,7 +46,6 @@ public class SemanticParseInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class SchemaNameLengthComparator implements Comparator<SchemaElement> {
|
private static class SchemaNameLengthComparator implements Comparator<SchemaElement> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compare(SchemaElement o1, SchemaElement o2) {
|
public int compare(SchemaElement o1, SchemaElement o2) {
|
||||||
int len1 = o1.getName().length();
|
int len1 = o1.getName().length();
|
||||||
|
|||||||
@@ -9,8 +9,11 @@ import lombok.Data;
|
|||||||
public class ExecuteQueryReq {
|
public class ExecuteQueryReq {
|
||||||
|
|
||||||
private User user;
|
private User user;
|
||||||
|
private Integer agentId;
|
||||||
private Integer chatId;
|
private Integer chatId;
|
||||||
private String queryText;
|
private String queryText;
|
||||||
|
private Long queryId;
|
||||||
|
private Integer parseId;
|
||||||
private SemanticParseInfo parseInfo;
|
private SemanticParseInfo parseInfo;
|
||||||
private boolean saveAnswer = true;
|
private boolean saveAnswer = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,4 +12,5 @@ public class QueryReq {
|
|||||||
private User user;
|
private User user;
|
||||||
private QueryFilters queryFilters;
|
private QueryFilters queryFilters;
|
||||||
private boolean saveAnswer = true;
|
private boolean saveAnswer = true;
|
||||||
|
private Integer agentId;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,5 @@ import lombok.Data;
|
|||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class AggregateInfo {
|
public class AggregateInfo {
|
||||||
|
|
||||||
private List<MetricInfo> metricInfos = new ArrayList<>();
|
private List<MetricInfo> metricInfos = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
package com.tencent.supersonic.chat.api.pojo.response;
|
package com.tencent.supersonic.chat.api.pojo.response;
|
||||||
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
|
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
|
||||||
import java.util.List;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.Builder;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Getter
|
@Getter
|
||||||
@@ -14,9 +15,9 @@ import lombok.NoArgsConstructor;
|
|||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class ParseResp {
|
public class ParseResp {
|
||||||
|
|
||||||
private Integer chatId;
|
private Integer chatId;
|
||||||
private String queryText;
|
private String queryText;
|
||||||
|
private Long queryId;
|
||||||
private ParseState state;
|
private ParseState state;
|
||||||
private List<SemanticParseInfo> selectedParses;
|
private List<SemanticParseInfo> selectedParses;
|
||||||
private List<SemanticParseInfo> candidateParses;
|
private List<SemanticParseInfo> candidateParses;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.tencent.supersonic.chat.api.pojo.response;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class SearchResp {
|
public class SearchResp {
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.tencent.supersonic.chat.api.pojo.response;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ShowCaseResp {
|
||||||
|
|
||||||
|
private Map<Long, List<QueryResp>> showCaseMap;
|
||||||
|
|
||||||
|
private int pageSize;
|
||||||
|
|
||||||
|
private int current;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -40,12 +40,6 @@
|
|||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.github.plexpt</groupId>
|
|
||||||
<artifactId>chatgpt</artifactId>
|
|
||||||
<version>4.1.2</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.junit.jupiter</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
<artifactId>junit-jupiter</artifactId>
|
<artifactId>junit-jupiter</artifactId>
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package com.tencent.supersonic.chat.agent;
|
||||||
|
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.tencent.supersonic.chat.agent.tool.AgentToolType;
|
||||||
|
import com.tencent.supersonic.common.pojo.RecordInfo;
|
||||||
|
import java.util.Objects;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class Agent extends RecordInfo {
|
||||||
|
|
||||||
|
private Integer id;
|
||||||
|
private Integer enableSearch;
|
||||||
|
private String name;
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
//0 offline, 1 online
|
||||||
|
private Integer status;
|
||||||
|
private List<String> examples;
|
||||||
|
private String agentConfig;
|
||||||
|
public List<String> getTools(AgentToolType type) {
|
||||||
|
Map map = JSONObject.parseObject(agentConfig, Map.class);
|
||||||
|
if (CollectionUtils.isEmpty(map) || map.get("tools") == null) {
|
||||||
|
return Lists.newArrayList();
|
||||||
|
}
|
||||||
|
List<Map> toolList = (List) map.get("tools");
|
||||||
|
return toolList.stream()
|
||||||
|
.filter(tool -> {
|
||||||
|
if (Objects.isNull(type)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return type.name().equals(tool.get("type"));
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.map(JSONObject::toJSONString)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean enableSearch() {
|
||||||
|
return enableSearch != null && enableSearch == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.tencent.supersonic.chat.agent;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.tencent.supersonic.chat.agent.tool.AgentTool;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class AgentConfig {
|
||||||
|
|
||||||
|
List<AgentTool> tools = Lists.newArrayList();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.tencent.supersonic.chat.agent.tool;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class AgentTool {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private AgentToolType type;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.tencent.supersonic.chat.agent.tool;
|
||||||
|
|
||||||
|
public enum AgentToolType {
|
||||||
|
RULE,
|
||||||
|
DSL,
|
||||||
|
PLUGIN,
|
||||||
|
INTERPRET
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.tencent.supersonic.chat.agent.tool;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class DslTool extends AgentTool {
|
||||||
|
|
||||||
|
private List<Long> modelIds;
|
||||||
|
|
||||||
|
private List<String> exampleQuestions;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.tencent.supersonic.chat.agent.tool;
|
||||||
|
|
||||||
|
import com.tencent.supersonic.chat.parser.llm.interpret.MetricOption;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class MetricInterpretTool extends AgentTool {
|
||||||
|
|
||||||
|
private Long modelId;
|
||||||
|
|
||||||
|
private List<MetricOption> metricOptions;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.tencent.supersonic.chat.agent.tool;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class PluginTool extends AgentTool {
|
||||||
|
|
||||||
|
private List<Long> plugins;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.tencent.supersonic.chat.agent.tool;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class RuleQueryTool extends AgentTool {
|
||||||
|
|
||||||
|
private List<Long> modelIds;
|
||||||
|
|
||||||
|
private List<String> queryModes;
|
||||||
|
|
||||||
|
public boolean isContainsAllModel() {
|
||||||
|
return CollectionUtils.isNotEmpty(modelIds) && modelIds.contains(-1L);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
//package com.tencent.supersonic.chat.aspect;
|
||||||
|
//
|
||||||
|
//import lombok.extern.slf4j.Slf4j;
|
||||||
|
//import org.aspectj.lang.JoinPoint;
|
||||||
|
//import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
//import org.aspectj.lang.annotation.*;
|
||||||
|
//import org.springframework.stereotype.Component;
|
||||||
|
//
|
||||||
|
//import java.util.HashMap;
|
||||||
|
//import java.util.Map;
|
||||||
|
//
|
||||||
|
//@Aspect
|
||||||
|
//@Component
|
||||||
|
//@Slf4j
|
||||||
|
//public class TimeCostAspect {
|
||||||
|
//
|
||||||
|
// ThreadLocal<Long> startTime = new ThreadLocal<>();
|
||||||
|
//
|
||||||
|
// ThreadLocal<Map<String, Long>> map = new ThreadLocal<>();
|
||||||
|
//
|
||||||
|
// @Pointcut("execution(public * com.tencent.supersonic.chat.mapper.HanlpDictMapper.*(*))")
|
||||||
|
// //@Pointcut("execution(* public com.tencent.supersonic.chat.parser.*.*(..))")
|
||||||
|
// //@Pointcut("execution(* com.tencent.supersonic.chat.mapper.*Mapper.map(..)) ")
|
||||||
|
// //@Pointcut("execution(* com.tencent.supersonic.chat.mapper.HanlpDictMapper.map(..)) ")
|
||||||
|
// //@Pointcut("execution(* com.tencent.supersonic.chat.parser.rule.QueryModeParser.*(..)) ")
|
||||||
|
// public void point() {
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Around("point()")
|
||||||
|
// public void doAround(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||||
|
// long start = System.currentTimeMillis();
|
||||||
|
// try {
|
||||||
|
// log.info("切面开始");
|
||||||
|
// Object result = joinPoint.proceed();
|
||||||
|
// log.info("切面开始");
|
||||||
|
// if (result == null) {
|
||||||
|
// //如果切到了 没有返回类型的void方法,这里直接返回
|
||||||
|
// //return null;
|
||||||
|
// }
|
||||||
|
// long end = System.currentTimeMillis();
|
||||||
|
// log.info("===================");
|
||||||
|
// String targetClassName = joinPoint.getSignature().getDeclaringTypeName();
|
||||||
|
// String MethodName = joinPoint.getSignature().getName();
|
||||||
|
// String typeStr = joinPoint.getSignature().getDeclaringType().toString().split(" ")[0];
|
||||||
|
// log.info("类/接口:" + targetClassName + "(" + typeStr + ")");
|
||||||
|
// log.info("方法:" + MethodName);
|
||||||
|
// Long total = end - start;
|
||||||
|
// log.info("耗时: " + total + " ms!");
|
||||||
|
// map.get().put(targetClassName + "_" + MethodName, total);
|
||||||
|
// //return result;
|
||||||
|
// } catch (Throwable e) {
|
||||||
|
// long end = System.currentTimeMillis();
|
||||||
|
// log.info("====around " + joinPoint + "\tUse time : " + (end - start) + " ms with exception : "
|
||||||
|
// + e.getMessage());
|
||||||
|
// throw e;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//// //对Controller下面的方法执行前进行切入,初始化开始时间
|
||||||
|
//// @Before(value = "execution(* com.appleyk.controller.*.*(..))")
|
||||||
|
//// public void beforMehhod(JoinPoint jp) {
|
||||||
|
//// startTime.set(System.currentTimeMillis());
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// //对Controller下面的方法执行后进行切入,统计方法执行的次数和耗时情况
|
||||||
|
//// //注意,这里的执行方法统计的数据不止包含Controller下面的方法,也包括环绕切入的所有方法的统计信息
|
||||||
|
//// @AfterReturning(value = "execution(* com.appleyk.controller.*.*(..))")
|
||||||
|
//// public void afterMehhod(JoinPoint jp) {
|
||||||
|
//// long end = System.currentTimeMillis();
|
||||||
|
//// long total = end - startTime.get();
|
||||||
|
//// String methodName = jp.getSignature().getName();
|
||||||
|
//// log.info("连接点方法为:" + methodName + ",执行总耗时为:" +total+"ms");
|
||||||
|
////
|
||||||
|
//// //重新new一个map
|
||||||
|
//// Map<String, Long> map = new HashMap<>();
|
||||||
|
//////从map2中将最后的 连接点方法给移除了,替换成最终的,避免连接点方法多次进行叠加计算
|
||||||
|
//// //由于map2受ThreadLocal的保护,这里不支持remove,因此,需要单开一个map进行数据交接
|
||||||
|
//// for(Map.Entry<String, Long> entry:map2.get().entrySet()){
|
||||||
|
//// if(entry.getKey().equals(methodName)){
|
||||||
|
//// map.put(methodName, total);
|
||||||
|
////
|
||||||
|
//// }else{
|
||||||
|
//// map.put(entry.getKey(), entry.getValue());
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// for (Map.Entry<String, Long> entry :map1.get().entrySet()) {
|
||||||
|
//// for(Map.Entry<String, Long> entry2 :map.entrySet()){
|
||||||
|
//// if(entry.getKey().equals(entry2.getKey())){
|
||||||
|
//// System.err.println(entry.getKey()+",被调用次数:"+entry.getValue()+",综合耗时:"+entry2.getValue()+"ms");
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
*/
|
||||||
@@ -3,11 +3,9 @@ package com.tencent.supersonic.chat.config;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@Data
|
@Data
|
||||||
|
@Configuration
|
||||||
public class AggregatorConfig {
|
public class AggregatorConfig {
|
||||||
|
|
||||||
@Value("${metric.aggregator.ratio.enable:true}")
|
@Value("${metric.aggregator.ratio.enable:true}")
|
||||||
private Boolean enableRatio;
|
private Boolean enableRatio;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package com.tencent.supersonic.chat.corrector;
|
||||||
|
|
||||||
|
import com.tencent.supersonic.chat.api.component.SemanticCorrector;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.SemanticSchema;
|
||||||
|
import com.tencent.supersonic.common.util.ContextUtils;
|
||||||
|
import com.tencent.supersonic.knowledge.service.SchemaService;
|
||||||
|
import com.tencent.supersonic.semantic.api.model.enums.TimeDimensionEnum;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public abstract class BaseSemanticCorrector implements SemanticCorrector {
|
||||||
|
public static final String DATE_FIELD = "数据日期";
|
||||||
|
protected Map<String, String> getFieldToBizName(Long modelId) {
|
||||||
|
|
||||||
|
SemanticSchema semanticSchema = ContextUtils.getBean(SchemaService.class).getSemanticSchema();
|
||||||
|
|
||||||
|
List<SchemaElement> dbAllFields = new ArrayList<>();
|
||||||
|
dbAllFields.addAll(semanticSchema.getMetrics());
|
||||||
|
dbAllFields.addAll(semanticSchema.getDimensions());
|
||||||
|
|
||||||
|
Map<String, String> result = dbAllFields.stream()
|
||||||
|
.filter(entry -> entry.getModel().equals(modelId))
|
||||||
|
.collect(Collectors.toMap(SchemaElement::getName, a -> a.getBizName(), (k1, k2) -> k1));
|
||||||
|
result.put(DATE_FIELD, TimeDimensionEnum.DAY.getName());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.tencent.supersonic.chat.corrector;
|
||||||
|
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.CorrectionInfo;
|
||||||
|
import com.tencent.supersonic.chat.parser.llm.dsl.DSLDateHelper;
|
||||||
|
import com.tencent.supersonic.common.util.jsqlparser.SqlParserSelectHelper;
|
||||||
|
import com.tencent.supersonic.common.util.jsqlparser.SqlParserUpdateHelper;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class DateFieldCorrector extends BaseSemanticCorrector {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CorrectionInfo corrector(CorrectionInfo correctionInfo) {
|
||||||
|
|
||||||
|
String sql = correctionInfo.getSql();
|
||||||
|
List<String> whereFields = SqlParserSelectHelper.getWhereFields(sql);
|
||||||
|
if (CollectionUtils.isEmpty(whereFields) || !whereFields.contains(DATE_FIELD)) {
|
||||||
|
String currentDate = DSLDateHelper.getCurrentDate(correctionInfo.getParseInfo().getModelId());
|
||||||
|
sql = SqlParserUpdateHelper.addWhere(sql, DATE_FIELD, currentDate);
|
||||||
|
}
|
||||||
|
correctionInfo.setSql(sql);
|
||||||
|
return correctionInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.tencent.supersonic.chat.corrector;
|
||||||
|
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.CorrectionInfo;
|
||||||
|
import com.tencent.supersonic.common.util.jsqlparser.SqlParserUpdateHelper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class FieldCorrector extends BaseSemanticCorrector {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CorrectionInfo corrector(CorrectionInfo correctionInfo) {
|
||||||
|
String replaceFields = SqlParserUpdateHelper.replaceFields(correctionInfo.getSql(),
|
||||||
|
getFieldToBizName(correctionInfo.getParseInfo().getModelId()));
|
||||||
|
correctionInfo.setSql(replaceFields);
|
||||||
|
return correctionInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package com.tencent.supersonic.chat.corrector;
|
||||||
|
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.CorrectionInfo;
|
||||||
|
import com.tencent.supersonic.chat.parser.llm.dsl.DSLParseResult;
|
||||||
|
import com.tencent.supersonic.chat.query.llm.dsl.LLMReq;
|
||||||
|
import com.tencent.supersonic.chat.query.llm.dsl.LLMReq.ElementValue;
|
||||||
|
import com.tencent.supersonic.common.pojo.Constants;
|
||||||
|
import com.tencent.supersonic.common.util.JsonUtil;
|
||||||
|
import com.tencent.supersonic.common.util.jsqlparser.SqlParserUpdateHelper;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class FieldValueCorrector extends BaseSemanticCorrector {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CorrectionInfo corrector(CorrectionInfo correctionInfo) {
|
||||||
|
|
||||||
|
Object context = correctionInfo.getParseInfo().getProperties().get(Constants.CONTEXT);
|
||||||
|
if (Objects.isNull(context)) {
|
||||||
|
return correctionInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
DSLParseResult dslParseResult = JsonUtil.toObject(JsonUtil.toString(context), DSLParseResult.class);
|
||||||
|
if (Objects.isNull(dslParseResult) || Objects.isNull(dslParseResult.getLlmReq())) {
|
||||||
|
return correctionInfo;
|
||||||
|
}
|
||||||
|
LLMReq llmReq = dslParseResult.getLlmReq();
|
||||||
|
List<ElementValue> linking = llmReq.getLinking();
|
||||||
|
if (CollectionUtils.isEmpty(linking)) {
|
||||||
|
return correctionInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Set<String>> fieldValueToFieldNames = linking.stream().collect(
|
||||||
|
Collectors.groupingBy(ElementValue::getFieldValue,
|
||||||
|
Collectors.mapping(ElementValue::getFieldName, Collectors.toSet())));
|
||||||
|
|
||||||
|
String sql = SqlParserUpdateHelper.replaceValueFields(correctionInfo.getSql(), fieldValueToFieldNames);
|
||||||
|
correctionInfo.setSql(sql);
|
||||||
|
return correctionInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.tencent.supersonic.chat.corrector;
|
||||||
|
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.CorrectionInfo;
|
||||||
|
import com.tencent.supersonic.common.util.jsqlparser.SqlParserUpdateHelper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class FunctionCorrector extends BaseSemanticCorrector {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CorrectionInfo corrector(CorrectionInfo correctionInfo) {
|
||||||
|
String replaceFunction = SqlParserUpdateHelper.replaceFunction(correctionInfo.getSql());
|
||||||
|
correctionInfo.setSql(replaceFunction);
|
||||||
|
return correctionInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package com.tencent.supersonic.chat.corrector;
|
||||||
|
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.CorrectionInfo;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.request.QueryFilters;
|
||||||
|
import com.tencent.supersonic.common.pojo.Constants;
|
||||||
|
import com.tencent.supersonic.common.util.StringUtil;
|
||||||
|
import com.tencent.supersonic.common.util.jsqlparser.SqlParserUpdateHelper;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.sf.jsqlparser.JSQLParserException;
|
||||||
|
import net.sf.jsqlparser.expression.Expression;
|
||||||
|
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class QueryFilterAppend extends BaseSemanticCorrector {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CorrectionInfo corrector(CorrectionInfo correctionInfo) throws JSQLParserException {
|
||||||
|
String queryFilter = getQueryFilter(correctionInfo.getQueryFilters());
|
||||||
|
String sql = correctionInfo.getSql();
|
||||||
|
|
||||||
|
if (StringUtils.isNotEmpty(queryFilter)) {
|
||||||
|
log.info("add queryFilter to sql :{}", queryFilter);
|
||||||
|
Expression expression = CCJSqlParserUtil.parseCondExpression(queryFilter);
|
||||||
|
sql = SqlParserUpdateHelper.addWhere(sql, expression);
|
||||||
|
}
|
||||||
|
correctionInfo.setSql(sql);
|
||||||
|
return correctionInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getQueryFilter(QueryFilters queryFilters) {
|
||||||
|
if (Objects.isNull(queryFilters) || CollectionUtils.isEmpty(queryFilters.getFilters())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return queryFilters.getFilters().stream()
|
||||||
|
.map(filter -> {
|
||||||
|
String bizNameWrap = StringUtil.getSpaceWrap(filter.getBizName());
|
||||||
|
String operatorWrap = StringUtil.getSpaceWrap(filter.getOperator().getValue());
|
||||||
|
String valueWrap = StringUtil.getCommaWrap(filter.getValue().toString());
|
||||||
|
return bizNameWrap + operatorWrap + valueWrap;
|
||||||
|
})
|
||||||
|
.collect(Collectors.joining(Constants.AND_UPPER));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.tencent.supersonic.chat.corrector;
|
||||||
|
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.CorrectionInfo;
|
||||||
|
import com.tencent.supersonic.common.util.jsqlparser.SqlParserSelectHelper;
|
||||||
|
import com.tencent.supersonic.common.util.jsqlparser.SqlParserUpdateHelper;
|
||||||
|
import com.tencent.supersonic.semantic.api.model.enums.TimeDimensionEnum;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class SelectFieldAppendCorrector extends BaseSemanticCorrector {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CorrectionInfo corrector(CorrectionInfo correctionInfo) {
|
||||||
|
String sql = correctionInfo.getSql();
|
||||||
|
if (SqlParserSelectHelper.hasAggregateFunction(sql)) {
|
||||||
|
return correctionInfo;
|
||||||
|
}
|
||||||
|
Set<String> selectFields = new HashSet<>(SqlParserSelectHelper.getSelectFields(sql));
|
||||||
|
Set<String> whereFields = new HashSet<>(SqlParserSelectHelper.getWhereFields(sql));
|
||||||
|
|
||||||
|
if (CollectionUtils.isEmpty(selectFields) || CollectionUtils.isEmpty(whereFields)) {
|
||||||
|
return correctionInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
whereFields.addAll(SqlParserSelectHelper.getOrderByFields(sql));
|
||||||
|
whereFields.removeAll(selectFields);
|
||||||
|
whereFields.remove(TimeDimensionEnum.DAY.getName());
|
||||||
|
whereFields.remove(TimeDimensionEnum.WEEK.getName());
|
||||||
|
whereFields.remove(TimeDimensionEnum.MONTH.getName());
|
||||||
|
|
||||||
|
String replaceFields = SqlParserUpdateHelper.addFieldsToSelect(sql, new ArrayList<>(whereFields));
|
||||||
|
correctionInfo.setSql(replaceFields);
|
||||||
|
return correctionInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.tencent.supersonic.chat.corrector;
|
||||||
|
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.CorrectionInfo;
|
||||||
|
import com.tencent.supersonic.common.util.jsqlparser.SqlParserUpdateHelper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class TableNameCorrector extends BaseSemanticCorrector {
|
||||||
|
|
||||||
|
public static final String TABLE_PREFIX = "t_";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CorrectionInfo corrector(CorrectionInfo correctionInfo) {
|
||||||
|
Long modelId = correctionInfo.getParseInfo().getModelId();
|
||||||
|
String sqlOutput = correctionInfo.getSql();
|
||||||
|
String replaceTable = SqlParserUpdateHelper.replaceTable(sqlOutput, TABLE_PREFIX + modelId);
|
||||||
|
correctionInfo.setSql(replaceTable);
|
||||||
|
return correctionInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,19 +2,19 @@ package com.tencent.supersonic.chat.mapper;
|
|||||||
|
|
||||||
|
|
||||||
import com.tencent.supersonic.chat.api.component.SchemaMapper;
|
import com.tencent.supersonic.chat.api.component.SchemaMapper;
|
||||||
import com.tencent.supersonic.chat.api.pojo.ModelSchema;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaMapInfo;
|
import com.tencent.supersonic.chat.api.pojo.SchemaMapInfo;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.ModelSchema;
|
||||||
import com.tencent.supersonic.chat.service.SemanticService;
|
import com.tencent.supersonic.chat.service.SemanticService;
|
||||||
import com.tencent.supersonic.common.util.ContextUtils;
|
import com.tencent.supersonic.common.util.ContextUtils;
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@@ -33,7 +33,7 @@ public class EntityMapper implements SchemaMapper {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
List<SchemaElementMatch> valueSchemaElements = schemaElementMatchList.stream().filter(schemaElementMatch ->
|
List<SchemaElementMatch> valueSchemaElements = schemaElementMatchList.stream().filter(schemaElementMatch ->
|
||||||
SchemaElementType.VALUE.equals(schemaElementMatch.getElement().getType()))
|
SchemaElementType.VALUE.equals(schemaElementMatch.getElement().getType()))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
for (SchemaElementMatch schemaElementMatch : valueSchemaElements) {
|
for (SchemaElementMatch schemaElementMatch : valueSchemaElements) {
|
||||||
if (!entity.getId().equals(schemaElementMatch.getElement().getId())) {
|
if (!entity.getId().equals(schemaElementMatch.getElement().getId())) {
|
||||||
@@ -51,7 +51,7 @@ public class EntityMapper implements SchemaMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkExistSameEntitySchemaElements(SchemaElementMatch valueSchemaElementMatch,
|
private boolean checkExistSameEntitySchemaElements(SchemaElementMatch valueSchemaElementMatch,
|
||||||
List<SchemaElementMatch> schemaElementMatchList) {
|
List<SchemaElementMatch> schemaElementMatchList) {
|
||||||
List<SchemaElementMatch> entitySchemaElements = schemaElementMatchList.stream().filter(schemaElementMatch ->
|
List<SchemaElementMatch> entitySchemaElements = schemaElementMatchList.stream().filter(schemaElementMatch ->
|
||||||
SchemaElementType.ENTITY.equals(schemaElementMatch.getElement().getType()))
|
SchemaElementType.ENTITY.equals(schemaElementMatch.getElement().getType()))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ package com.tencent.supersonic.chat.mapper;
|
|||||||
|
|
||||||
import com.hankcs.hanlp.seg.common.Term;
|
import com.hankcs.hanlp.seg.common.Term;
|
||||||
import com.tencent.supersonic.chat.api.component.SchemaMapper;
|
import com.tencent.supersonic.chat.api.component.SchemaMapper;
|
||||||
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaMapInfo;
|
import com.tencent.supersonic.chat.api.pojo.SchemaMapInfo;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
|
||||||
import com.tencent.supersonic.chat.api.pojo.SemanticSchema;
|
import com.tencent.supersonic.chat.api.pojo.SemanticSchema;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
||||||
import com.tencent.supersonic.common.util.ContextUtils;
|
import com.tencent.supersonic.common.util.ContextUtils;
|
||||||
import com.tencent.supersonic.knowledge.service.SchemaService;
|
import com.tencent.supersonic.knowledge.service.SchemaService;
|
||||||
import com.tencent.supersonic.knowledge.utils.HanlpHelper;
|
import com.tencent.supersonic.knowledge.utils.HanlpHelper;
|
||||||
@@ -43,13 +43,13 @@ public class FuzzyNameMapper implements SchemaMapper {
|
|||||||
log.debug("after db mapper,mapInfo:{}", queryContext.getMapInfo());
|
log.debug("after db mapper,mapInfo:{}", queryContext.getMapInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void detectAndAddToSchema(QueryContext queryContext, List<Term> terms, List<SchemaElement> Models,
|
private void detectAndAddToSchema(QueryContext queryContext, List<Term> terms, List<SchemaElement> models,
|
||||||
SchemaElementType schemaElementType) {
|
SchemaElementType schemaElementType) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
Map<String, Set<SchemaElement>> ModelResultSet = getResultSet(queryContext, terms, Models);
|
Map<String, Set<SchemaElement>> modelResultSet = getResultSet(queryContext, terms, models);
|
||||||
|
|
||||||
addToSchemaMapInfo(ModelResultSet, queryContext.getMapInfo(), schemaElementType);
|
addToSchemaMapInfo(modelResultSet, queryContext.getMapInfo(), schemaElementType);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("detectAndAddToSchema error", e);
|
log.error("detectAndAddToSchema error", e);
|
||||||
@@ -57,20 +57,21 @@ public class FuzzyNameMapper implements SchemaMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, Set<SchemaElement>> getResultSet(QueryContext queryContext, List<Term> terms,
|
private Map<String, Set<SchemaElement>> getResultSet(QueryContext queryContext, List<Term> terms,
|
||||||
List<SchemaElement> Models) {
|
List<SchemaElement> models) {
|
||||||
|
|
||||||
String queryText = queryContext.getRequest().getQueryText();
|
String queryText = queryContext.getRequest().getQueryText();
|
||||||
|
|
||||||
MapperHelper mapperHelper = ContextUtils.getBean(MapperHelper.class);
|
MapperHelper mapperHelper = ContextUtils.getBean(MapperHelper.class);
|
||||||
|
Set<Long> modelIds = mapperHelper.getModelIds(queryContext.getRequest());
|
||||||
|
|
||||||
Double metricDimensionThresholdConfig = getThreshold(queryContext, mapperHelper);
|
Double metricDimensionThresholdConfig = getThreshold(queryContext, mapperHelper);
|
||||||
|
|
||||||
Map<String, Set<SchemaElement>> nameToItems = getNameToItems(Models);
|
Map<String, Set<SchemaElement>> nameToItems = getNameToItems(models);
|
||||||
|
|
||||||
Map<Integer, Integer> regOffsetToLength = terms.stream().sorted(Comparator.comparing(Term::length))
|
Map<Integer, Integer> regOffsetToLength = terms.stream().sorted(Comparator.comparing(Term::length))
|
||||||
.collect(Collectors.toMap(Term::getOffset, term -> term.word.length(), (value1, value2) -> value2));
|
.collect(Collectors.toMap(Term::getOffset, term -> term.word.length(), (value1, value2) -> value2));
|
||||||
|
|
||||||
Map<String, Set<SchemaElement>> ModelResultSet = new HashMap<>();
|
Map<String, Set<SchemaElement>> modelResultSet = new HashMap<>();
|
||||||
for (Integer startIndex = 0; startIndex <= queryText.length() - 1; ) {
|
for (Integer startIndex = 0; startIndex <= queryText.length() - 1; ) {
|
||||||
for (Integer endIndex = startIndex; endIndex <= queryText.length(); ) {
|
for (Integer endIndex = startIndex; endIndex <= queryText.length(); ) {
|
||||||
endIndex = mapperHelper.getStepIndex(regOffsetToLength, endIndex);
|
endIndex = mapperHelper.getStepIndex(regOffsetToLength, endIndex);
|
||||||
@@ -86,8 +87,12 @@ public class FuzzyNameMapper implements SchemaMapper {
|
|||||||
|| mapperHelper.getSimilarity(detectSegment, name) < metricDimensionThresholdConfig) {
|
|| mapperHelper.getSimilarity(detectSegment, name) < metricDimensionThresholdConfig) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Set<SchemaElement> preSchemaElements = ModelResultSet.putIfAbsent(detectSegment,
|
if (!CollectionUtils.isEmpty(modelIds)) {
|
||||||
schemaElements);
|
schemaElements = schemaElements.stream()
|
||||||
|
.filter(schemaElement -> modelIds.contains(schemaElement.getModel()))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
Set<SchemaElement> preSchemaElements = modelResultSet.putIfAbsent(detectSegment, schemaElements);
|
||||||
if (Objects.nonNull(preSchemaElements)) {
|
if (Objects.nonNull(preSchemaElements)) {
|
||||||
preSchemaElements.addAll(schemaElements);
|
preSchemaElements.addAll(schemaElements);
|
||||||
}
|
}
|
||||||
@@ -95,7 +100,7 @@ public class FuzzyNameMapper implements SchemaMapper {
|
|||||||
}
|
}
|
||||||
startIndex = mapperHelper.getStepIndex(regOffsetToLength, startIndex);
|
startIndex = mapperHelper.getStepIndex(regOffsetToLength, startIndex);
|
||||||
}
|
}
|
||||||
return ModelResultSet;
|
return modelResultSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Double getThreshold(QueryContext queryContext, MapperHelper mapperHelper) {
|
private Double getThreshold(QueryContext queryContext, MapperHelper mapperHelper) {
|
||||||
@@ -103,9 +108,9 @@ public class FuzzyNameMapper implements SchemaMapper {
|
|||||||
Double metricDimensionThresholdConfig = mapperHelper.getMetricDimensionThresholdConfig();
|
Double metricDimensionThresholdConfig = mapperHelper.getMetricDimensionThresholdConfig();
|
||||||
Double metricDimensionMinThresholdConfig = mapperHelper.getMetricDimensionMinThresholdConfig();
|
Double metricDimensionMinThresholdConfig = mapperHelper.getMetricDimensionMinThresholdConfig();
|
||||||
|
|
||||||
Map<Long, List<SchemaElementMatch>> ModelElementMatches = queryContext.getMapInfo()
|
Map<Long, List<SchemaElementMatch>> modelElementMatches = queryContext.getMapInfo()
|
||||||
.getModelElementMatches();
|
.getModelElementMatches();
|
||||||
boolean existElement = ModelElementMatches.entrySet().stream()
|
boolean existElement = modelElementMatches.entrySet().stream()
|
||||||
.anyMatch(entry -> entry.getValue().size() >= 1);
|
.anyMatch(entry -> entry.getValue().size() >= 1);
|
||||||
|
|
||||||
if (!existElement) {
|
if (!existElement) {
|
||||||
@@ -114,13 +119,13 @@ public class FuzzyNameMapper implements SchemaMapper {
|
|||||||
metricDimensionThresholdConfig = halfThreshold >= metricDimensionMinThresholdConfig ? halfThreshold
|
metricDimensionThresholdConfig = halfThreshold >= metricDimensionMinThresholdConfig ? halfThreshold
|
||||||
: metricDimensionMinThresholdConfig;
|
: metricDimensionMinThresholdConfig;
|
||||||
log.info("ModelElementMatches:{} , not exist Element metricDimensionThresholdConfig reduce by half:{}",
|
log.info("ModelElementMatches:{} , not exist Element metricDimensionThresholdConfig reduce by half:{}",
|
||||||
ModelElementMatches, metricDimensionThresholdConfig);
|
modelElementMatches, metricDimensionThresholdConfig);
|
||||||
}
|
}
|
||||||
return metricDimensionThresholdConfig;
|
return metricDimensionThresholdConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, Set<SchemaElement>> getNameToItems(List<SchemaElement> Models) {
|
private Map<String, Set<SchemaElement>> getNameToItems(List<SchemaElement> models) {
|
||||||
return Models.stream().collect(
|
return models.stream().collect(
|
||||||
Collectors.toMap(SchemaElement::getName, a -> {
|
Collectors.toMap(SchemaElement::getName, a -> {
|
||||||
Set<SchemaElement> result = new HashSet<>();
|
Set<SchemaElement> result = new HashSet<>();
|
||||||
result.add(a);
|
result.add(a);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
|
|||||||
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
|
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaMapInfo;
|
import com.tencent.supersonic.chat.api.pojo.SchemaMapInfo;
|
||||||
import com.tencent.supersonic.chat.service.SemanticService;
|
import com.tencent.supersonic.chat.service.SemanticService;
|
||||||
import com.tencent.supersonic.chat.utils.NatureHelper;
|
import com.tencent.supersonic.knowledge.utils.NatureHelper;
|
||||||
import com.tencent.supersonic.common.util.ContextUtils;
|
import com.tencent.supersonic.common.util.ContextUtils;
|
||||||
import com.tencent.supersonic.knowledge.dictionary.DictWordType;
|
import com.tencent.supersonic.knowledge.dictionary.DictWordType;
|
||||||
import com.tencent.supersonic.knowledge.dictionary.MapResult;
|
import com.tencent.supersonic.knowledge.dictionary.MapResult;
|
||||||
@@ -21,6 +21,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
@@ -37,10 +38,13 @@ public class HanlpDictMapper implements SchemaMapper {
|
|||||||
for (Term term : terms) {
|
for (Term term : terms) {
|
||||||
log.info("word:{},nature:{},frequency:{}", term.word, term.nature.toString(), term.getFrequency());
|
log.info("word:{},nature:{},frequency:{}", term.word, term.nature.toString(), term.getFrequency());
|
||||||
}
|
}
|
||||||
Long modelId = queryContext.getRequest().getModelId();
|
|
||||||
|
|
||||||
QueryMatchStrategy matchStrategy = ContextUtils.getBean(QueryMatchStrategy.class);
|
QueryMatchStrategy matchStrategy = ContextUtils.getBean(QueryMatchStrategy.class);
|
||||||
Map<MatchText, List<MapResult>> matchResult = matchStrategy.match(queryText, terms, modelId);
|
MapperHelper mapperHelper = ContextUtils.getBean(MapperHelper.class);
|
||||||
|
Set<Long> detectModelIds = mapperHelper.getModelIds(queryContext.getRequest());
|
||||||
|
|
||||||
|
Map<MatchText, List<MapResult>> matchResult = matchStrategy.match(queryContext.getRequest(), terms,
|
||||||
|
detectModelIds);
|
||||||
|
|
||||||
List<MapResult> matches = getMatches(matchResult);
|
List<MapResult> matches = getMatches(matchResult);
|
||||||
|
|
||||||
@@ -51,6 +55,7 @@ public class HanlpDictMapper implements SchemaMapper {
|
|||||||
convertTermsToSchemaMapInfo(matches, queryContext.getMapInfo(), terms);
|
convertTermsToSchemaMapInfo(matches, queryContext.getMapInfo(), terms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void convertTermsToSchemaMapInfo(List<MapResult> mapResults, SchemaMapInfo schemaMap, List<Term> terms) {
|
private void convertTermsToSchemaMapInfo(List<MapResult> mapResults, SchemaMapInfo schemaMap, List<Term> terms) {
|
||||||
if (CollectionUtils.isEmpty(mapResults)) {
|
if (CollectionUtils.isEmpty(mapResults)) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
package com.tencent.supersonic.chat.mapper;
|
package com.tencent.supersonic.chat.mapper;
|
||||||
|
|
||||||
import com.hankcs.hanlp.algorithm.EditDistance;
|
import com.hankcs.hanlp.algorithm.EditDistance;
|
||||||
import com.tencent.supersonic.chat.utils.NatureHelper;
|
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
|
||||||
|
import com.tencent.supersonic.chat.service.AgentService;
|
||||||
|
import com.tencent.supersonic.common.util.ContextUtils;
|
||||||
|
import com.tencent.supersonic.knowledge.utils.NatureHelper;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
@@ -19,7 +25,7 @@ import org.springframework.stereotype.Service;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class MapperHelper {
|
public class MapperHelper {
|
||||||
|
|
||||||
@Value("${one.detection.size:6}")
|
@Value("${one.detection.size:8}")
|
||||||
private Integer oneDetectionSize;
|
private Integer oneDetectionSize;
|
||||||
@Value("${one.detection.max.size:20}")
|
@Value("${one.detection.max.size:20}")
|
||||||
private Integer oneDetectionMaxSize;
|
private Integer oneDetectionMaxSize;
|
||||||
@@ -64,7 +70,7 @@ public class MapperHelper {
|
|||||||
*/
|
*/
|
||||||
public boolean existDimensionValues(List<String> natures) {
|
public boolean existDimensionValues(List<String> natures) {
|
||||||
for (String nature : natures) {
|
for (String nature : natures) {
|
||||||
if (NatureHelper.isDimensionValueClassId(nature)) {
|
if (NatureHelper.isDimensionValueModelId(nature)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,5 +90,24 @@ public class MapperHelper {
|
|||||||
detectSegment.length());
|
detectSegment.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<Long> getModelIds(QueryReq request) {
|
||||||
|
|
||||||
|
Long modelId = request.getModelId();
|
||||||
|
|
||||||
|
AgentService agentService = ContextUtils.getBean(AgentService.class);
|
||||||
|
|
||||||
|
Set<Long> detectModelIds = agentService.getDslToolsModelIds(request.getAgentId(), null);
|
||||||
|
if (Objects.nonNull(detectModelIds)) {
|
||||||
|
detectModelIds = detectModelIds.stream().filter(entry -> entry > 0).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
if (Objects.nonNull(modelId) && modelId > 0 && Objects.nonNull(detectModelIds)) {
|
||||||
|
if (detectModelIds.contains(modelId)) {
|
||||||
|
Set<Long> result = new HashSet<>();
|
||||||
|
result.add(modelId);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return detectModelIds;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,17 @@
|
|||||||
package com.tencent.supersonic.chat.mapper;
|
package com.tencent.supersonic.chat.mapper;
|
||||||
|
|
||||||
import com.hankcs.hanlp.seg.common.Term;
|
import com.hankcs.hanlp.seg.common.Term;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
|
||||||
import com.tencent.supersonic.knowledge.dictionary.MapResult;
|
import com.tencent.supersonic.knowledge.dictionary.MapResult;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* match strategy
|
* match strategy
|
||||||
*/
|
*/
|
||||||
public interface MatchStrategy {
|
public interface MatchStrategy {
|
||||||
|
|
||||||
Map<MatchText, List<MapResult>> match(String text, List<Term> terms, Long detectModelId);
|
Map<MatchText, List<MapResult>> match(QueryReq queryReq, List<Term> terms, Set<Long> detectModelId);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -3,25 +3,25 @@ package com.tencent.supersonic.chat.mapper;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.tencent.supersonic.chat.api.component.SchemaMapper;
|
import com.tencent.supersonic.chat.api.component.SchemaMapper;
|
||||||
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaMapInfo;
|
import com.tencent.supersonic.chat.api.pojo.SchemaMapInfo;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
|
||||||
import com.tencent.supersonic.chat.api.pojo.request.QueryFilter;
|
import com.tencent.supersonic.chat.api.pojo.request.QueryFilter;
|
||||||
import com.tencent.supersonic.chat.api.pojo.request.QueryFilters;
|
import com.tencent.supersonic.chat.api.pojo.request.QueryFilters;
|
||||||
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
|
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
|
||||||
import com.tencent.supersonic.common.pojo.Constants;
|
import com.tencent.supersonic.common.pojo.Constants;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.util.CollectionUtils;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class QueryFilterMapper implements SchemaMapper {
|
public class QueryFilterMapper implements SchemaMapper {
|
||||||
|
|
||||||
private Long FREQUENCY = 9999999L;
|
private Long frequency = 9999999L;
|
||||||
private double SIMILARITY = 1.0;
|
private double similarity = 1.0;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void map(QueryContext queryContext) {
|
public void map(QueryContext queryContext) {
|
||||||
@@ -49,7 +49,7 @@ public class QueryFilterMapper implements SchemaMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<SchemaElementMatch> addValueSchemaElementMatch(List<SchemaElementMatch> candidateElementMatches,
|
private List<SchemaElementMatch> addValueSchemaElementMatch(List<SchemaElementMatch> candidateElementMatches,
|
||||||
QueryFilters queryFilter) {
|
QueryFilters queryFilter) {
|
||||||
if (queryFilter == null || CollectionUtils.isEmpty(queryFilter.getFilters())) {
|
if (queryFilter == null || CollectionUtils.isEmpty(queryFilter.getFilters())) {
|
||||||
return candidateElementMatches;
|
return candidateElementMatches;
|
||||||
}
|
}
|
||||||
@@ -65,9 +65,9 @@ public class QueryFilterMapper implements SchemaMapper {
|
|||||||
.build();
|
.build();
|
||||||
SchemaElementMatch schemaElementMatch = SchemaElementMatch.builder()
|
SchemaElementMatch schemaElementMatch = SchemaElementMatch.builder()
|
||||||
.element(element)
|
.element(element)
|
||||||
.frequency(FREQUENCY)
|
.frequency(frequency)
|
||||||
.word(String.valueOf(filter.getValue()))
|
.word(String.valueOf(filter.getValue()))
|
||||||
.similarity(SIMILARITY)
|
.similarity(similarity)
|
||||||
.detectWord(Constants.EMPTY)
|
.detectWord(Constants.EMPTY)
|
||||||
.build();
|
.build();
|
||||||
candidateElementMatches.add(schemaElementMatch);
|
candidateElementMatches.add(schemaElementMatch);
|
||||||
@@ -76,7 +76,7 @@ public class QueryFilterMapper implements SchemaMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkExistSameValueSchemaElementMatch(QueryFilter queryFilter,
|
private boolean checkExistSameValueSchemaElementMatch(QueryFilter queryFilter,
|
||||||
List<SchemaElementMatch> schemaElementMatches) {
|
List<SchemaElementMatch> schemaElementMatches) {
|
||||||
List<SchemaElementMatch> valueSchemaElements = schemaElementMatches.stream().filter(schemaElementMatch ->
|
List<SchemaElementMatch> valueSchemaElements = schemaElementMatches.stream().filter(schemaElementMatch ->
|
||||||
SchemaElementType.VALUE.equals(schemaElementMatch.getElement().getType()))
|
SchemaElementType.VALUE.equals(schemaElementMatch.getElement().getType()))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package com.tencent.supersonic.chat.mapper;
|
package com.tencent.supersonic.chat.mapper;
|
||||||
|
|
||||||
import com.hankcs.hanlp.seg.common.Term;
|
import com.hankcs.hanlp.seg.common.Term;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
|
||||||
import com.tencent.supersonic.common.pojo.Constants;
|
import com.tencent.supersonic.common.pojo.Constants;
|
||||||
import com.tencent.supersonic.knowledge.dictionary.DictWordType;
|
|
||||||
import com.tencent.supersonic.knowledge.dictionary.MapResult;
|
import com.tencent.supersonic.knowledge.dictionary.MapResult;
|
||||||
import com.tencent.supersonic.knowledge.service.SearchService;
|
import com.tencent.supersonic.knowledge.service.SearchService;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -32,7 +32,8 @@ public class QueryMatchStrategy implements MatchStrategy {
|
|||||||
private MapperHelper mapperHelper;
|
private MapperHelper mapperHelper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<MatchText, List<MapResult>> match(String text, List<Term> terms, Long detectmodelId) {
|
public Map<MatchText, List<MapResult>> match(QueryReq queryReq, List<Term> terms, Set<Long> detectModelIds) {
|
||||||
|
String text = queryReq.getQueryText();
|
||||||
if (Objects.isNull(terms) || StringUtils.isEmpty(text)) {
|
if (Objects.isNull(terms) || StringUtils.isEmpty(text)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -43,22 +44,19 @@ public class QueryMatchStrategy implements MatchStrategy {
|
|||||||
List<Integer> offsetList = terms.stream().sorted(Comparator.comparing(Term::getOffset))
|
List<Integer> offsetList = terms.stream().sorted(Comparator.comparing(Term::getOffset))
|
||||||
.map(term -> term.getOffset()).collect(Collectors.toList());
|
.map(term -> term.getOffset()).collect(Collectors.toList());
|
||||||
|
|
||||||
log.debug("retryCount:{},terms:{},regOffsetToLength:{},offsetList:{},detectmodelId:{}", terms,
|
log.debug("retryCount:{},terms:{},regOffsetToLength:{},offsetList:{},detectModelIds:{}", terms,
|
||||||
regOffsetToLength, offsetList, detectmodelId);
|
regOffsetToLength, offsetList, detectModelIds);
|
||||||
|
|
||||||
List<MapResult> detects = detect(text, regOffsetToLength, offsetList, detectmodelId);
|
List<MapResult> detects = detect(queryReq, regOffsetToLength, offsetList, detectModelIds);
|
||||||
Map<MatchText, List<MapResult>> result = new HashMap<>();
|
Map<MatchText, List<MapResult>> result = new HashMap<>();
|
||||||
|
|
||||||
MatchText matchText = MatchText.builder()
|
result.put(MatchText.builder().regText(text).detectSegment(text).build(), detects);
|
||||||
.regText(text)
|
|
||||||
.detectSegment(text)
|
|
||||||
.build();
|
|
||||||
result.put(matchText, detects);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MapResult> detect(String text, Map<Integer, Integer> regOffsetToLength, List<Integer> offsetList,
|
private List<MapResult> detect(QueryReq queryReq, Map<Integer, Integer> regOffsetToLength, List<Integer> offsetList,
|
||||||
Long detectmodelId) {
|
Set<Long> detectModelIds) {
|
||||||
|
String text = queryReq.getQueryText();
|
||||||
List<MapResult> results = Lists.newArrayList();
|
List<MapResult> results = Lists.newArrayList();
|
||||||
|
|
||||||
for (Integer index = 0; index <= text.length() - 1; ) {
|
for (Integer index = 0; index <= text.length() - 1; ) {
|
||||||
@@ -69,7 +67,7 @@ public class QueryMatchStrategy implements MatchStrategy {
|
|||||||
int offset = mapperHelper.getStepOffset(offsetList, index);
|
int offset = mapperHelper.getStepOffset(offsetList, index);
|
||||||
i = mapperHelper.getStepIndex(regOffsetToLength, i);
|
i = mapperHelper.getStepIndex(regOffsetToLength, i);
|
||||||
if (i <= text.length()) {
|
if (i <= text.length()) {
|
||||||
List<MapResult> mapResults = detectByStep(text, detectmodelId, index, i, offset);
|
List<MapResult> mapResults = detectByStep(queryReq, detectModelIds, index, i, offset);
|
||||||
selectMapResultInOneRound(mapResultRowSet, mapResults);
|
selectMapResultInOneRound(mapResultRowSet, mapResults);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,16 +104,19 @@ public class QueryMatchStrategy implements MatchStrategy {
|
|||||||
return a.getName() + Constants.UNDERLINE + String.join(Constants.UNDERLINE, a.getNatures());
|
return a.getName() + Constants.UNDERLINE + String.join(Constants.UNDERLINE, a.getNatures());
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MapResult> detectByStep(String text, Long detectmodelId, Integer index, Integer i, int offset) {
|
private List<MapResult> detectByStep(QueryReq queryReq, Set<Long> detectModelIds, Integer index, Integer i,
|
||||||
|
int offset) {
|
||||||
|
String text = queryReq.getQueryText();
|
||||||
|
Integer agentId = queryReq.getAgentId();
|
||||||
String detectSegment = text.substring(index, i);
|
String detectSegment = text.substring(index, i);
|
||||||
Integer oneDetectionSize = mapperHelper.getOneDetectionSize();
|
|
||||||
// step1. pre search
|
// step1. pre search
|
||||||
LinkedHashSet<MapResult> mapResults = SearchService.prefixSearch(detectSegment,
|
Integer oneDetectionMaxSize = mapperHelper.getOneDetectionMaxSize();
|
||||||
mapperHelper.getOneDetectionMaxSize())
|
LinkedHashSet<MapResult> mapResults = SearchService.prefixSearch(detectSegment, oneDetectionMaxSize, agentId,
|
||||||
.stream().collect(Collectors.toCollection(LinkedHashSet::new));
|
detectModelIds).stream().collect(Collectors.toCollection(LinkedHashSet::new));
|
||||||
// step2. suffix search
|
// step2. suffix search
|
||||||
LinkedHashSet<MapResult> suffixMapResults = SearchService.suffixSearch(detectSegment, oneDetectionSize)
|
LinkedHashSet<MapResult> suffixMapResults = SearchService.suffixSearch(detectSegment, oneDetectionMaxSize,
|
||||||
.stream().collect(Collectors.toCollection(LinkedHashSet::new));
|
agentId, detectModelIds).stream().collect(Collectors.toCollection(LinkedHashSet::new));
|
||||||
|
|
||||||
mapResults.addAll(suffixMapResults);
|
mapResults.addAll(suffixMapResults);
|
||||||
|
|
||||||
@@ -125,28 +126,15 @@ public class QueryMatchStrategy implements MatchStrategy {
|
|||||||
// step3. merge pre/suffix result
|
// step3. merge pre/suffix result
|
||||||
mapResults = mapResults.stream().sorted((a, b) -> -(b.getName().length() - a.getName().length()))
|
mapResults = mapResults.stream().sorted((a, b) -> -(b.getName().length() - a.getName().length()))
|
||||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||||
// step4. filter by classId
|
|
||||||
if (Objects.nonNull(detectmodelId) && detectmodelId > 0) {
|
// step4. filter by similarity
|
||||||
log.debug("detectmodelId:{}, before parseResults:{}", mapResults);
|
|
||||||
mapResults = mapResults.stream().map(entry -> {
|
|
||||||
List<String> natures = entry.getNatures().stream().filter(
|
|
||||||
nature -> nature.startsWith(DictWordType.NATURE_SPILT + detectmodelId) || (nature.startsWith(
|
|
||||||
DictWordType.NATURE_SPILT))
|
|
||||||
).collect(Collectors.toList());
|
|
||||||
entry.setNatures(natures);
|
|
||||||
return entry;
|
|
||||||
}).collect(Collectors.toCollection(LinkedHashSet::new));
|
|
||||||
log.info("after modelId parseResults:{}", mapResults);
|
|
||||||
}
|
|
||||||
// step5. filter by similarity
|
|
||||||
mapResults = mapResults.stream()
|
mapResults = mapResults.stream()
|
||||||
.filter(term -> mapperHelper.getSimilarity(detectSegment, term.getName())
|
.filter(term -> mapperHelper.getSimilarity(detectSegment, term.getName())
|
||||||
>= mapperHelper.getThresholdMatch(term.getNatures()))
|
>= mapperHelper.getThresholdMatch(term.getNatures()))
|
||||||
.filter(term -> CollectionUtils.isNotEmpty(term.getNatures()))
|
.filter(term -> CollectionUtils.isNotEmpty(term.getNatures()))
|
||||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||||
|
|
||||||
log.debug("metricDimensionThreshold:{},dimensionValueThreshold:{},after isSimilarity parseResults:{}",
|
log.info("after isSimilarity parseResults:{}", mapResults);
|
||||||
mapResults);
|
|
||||||
|
|
||||||
mapResults = mapResults.stream().map(parseResult -> {
|
mapResults = mapResults.stream().map(parseResult -> {
|
||||||
parseResult.setOffset(offset);
|
parseResult.setOffset(offset);
|
||||||
@@ -154,7 +142,7 @@ public class QueryMatchStrategy implements MatchStrategy {
|
|||||||
return parseResult;
|
return parseResult;
|
||||||
}).collect(Collectors.toCollection(LinkedHashSet::new));
|
}).collect(Collectors.toCollection(LinkedHashSet::new));
|
||||||
|
|
||||||
// step6. take only one dimension or 10 metric/dimension value per rond.
|
// step5. take only one dimension or 10 metric/dimension value per rond.
|
||||||
List<MapResult> dimensionMetrics = mapResults.stream()
|
List<MapResult> dimensionMetrics = mapResults.stream()
|
||||||
.filter(entry -> mapperHelper.existDimensionValues(entry.getNatures()))
|
.filter(entry -> mapperHelper.existDimensionValues(entry.getNatures()))
|
||||||
.collect(Collectors.toList())
|
.collect(Collectors.toList())
|
||||||
@@ -165,7 +153,7 @@ public class QueryMatchStrategy implements MatchStrategy {
|
|||||||
if (CollectionUtils.isNotEmpty(dimensionMetrics)) {
|
if (CollectionUtils.isNotEmpty(dimensionMetrics)) {
|
||||||
return dimensionMetrics;
|
return dimensionMetrics;
|
||||||
} else {
|
} else {
|
||||||
return mapResults.stream().limit(oneDetectionSize).collect(Collectors.toList());
|
return mapResults.stream().limit(mapperHelper.getOneDetectionSize()).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,12 +2,14 @@ package com.tencent.supersonic.chat.mapper;
|
|||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.hankcs.hanlp.seg.common.Term;
|
import com.hankcs.hanlp.seg.common.Term;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
|
||||||
import com.tencent.supersonic.knowledge.dictionary.DictWordType;
|
import com.tencent.supersonic.knowledge.dictionary.DictWordType;
|
||||||
import com.tencent.supersonic.knowledge.dictionary.MapResult;
|
import com.tencent.supersonic.knowledge.dictionary.MapResult;
|
||||||
import com.tencent.supersonic.knowledge.service.SearchService;
|
import com.tencent.supersonic.knowledge.service.SearchService;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
@@ -23,9 +25,8 @@ public class SearchMatchStrategy implements MatchStrategy {
|
|||||||
private static final int SEARCH_SIZE = 3;
|
private static final int SEARCH_SIZE = 3;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<MatchText, List<MapResult>> match(String text, List<Term> originals,
|
public Map<MatchText, List<MapResult>> match(QueryReq queryReq, List<Term> originals, Set<Long> detectModelIds) {
|
||||||
Long detectModelId) {
|
String text = queryReq.getQueryText();
|
||||||
|
|
||||||
Map<Integer, Integer> regOffsetToLength = originals.stream()
|
Map<Integer, Integer> regOffsetToLength = originals.stream()
|
||||||
.filter(entry -> !entry.nature.toString().startsWith(DictWordType.NATURE_SPILT))
|
.filter(entry -> !entry.nature.toString().startsWith(DictWordType.NATURE_SPILT))
|
||||||
.collect(Collectors.toMap(Term::getOffset, value -> value.word.length(),
|
.collect(Collectors.toMap(Term::getOffset, value -> value.word.length(),
|
||||||
@@ -51,24 +52,16 @@ public class SearchMatchStrategy implements MatchStrategy {
|
|||||||
String detectSegment = text.substring(detectIndex);
|
String detectSegment = text.substring(detectIndex);
|
||||||
|
|
||||||
if (StringUtils.isNotEmpty(detectSegment)) {
|
if (StringUtils.isNotEmpty(detectSegment)) {
|
||||||
List<MapResult> mapResults = SearchService.prefixSearch(detectSegment);
|
List<MapResult> mapResults = SearchService.prefixSearch(detectSegment,
|
||||||
List<MapResult> suffixMapResults = SearchService.suffixSearch(detectSegment, SEARCH_SIZE);
|
SearchService.SEARCH_SIZE, queryReq.getAgentId(), detectModelIds);
|
||||||
|
List<MapResult> suffixMapResults = SearchService.suffixSearch(detectSegment, SEARCH_SIZE,
|
||||||
|
queryReq.getAgentId(), detectModelIds);
|
||||||
mapResults.addAll(suffixMapResults);
|
mapResults.addAll(suffixMapResults);
|
||||||
// remove entity name where search
|
// remove entity name where search
|
||||||
mapResults = mapResults.stream().filter(entry -> {
|
mapResults = mapResults.stream().filter(entry -> {
|
||||||
List<String> natures = entry.getNatures().stream()
|
List<String> natures = entry.getNatures().stream()
|
||||||
.filter(nature -> !nature.endsWith(DictWordType.ENTITY.getType()))
|
.filter(nature -> !nature.endsWith(DictWordType.ENTITY.getType()))
|
||||||
.filter(nature -> {
|
.collect(Collectors.toList());
|
||||||
if (Objects.isNull(detectModelId) || detectModelId <= 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (nature.startsWith(DictWordType.NATURE_SPILT + detectModelId)
|
|
||||||
&& nature.startsWith(DictWordType.NATURE_SPILT)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
).collect(Collectors.toList());
|
|
||||||
if (CollectionUtils.isEmpty(natures)) {
|
if (CollectionUtils.isEmpty(natures)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -84,4 +77,4 @@ public class SearchMatchStrategy implements MatchStrategy {
|
|||||||
);
|
);
|
||||||
return regTextMap;
|
return regTextMap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package com.tencent.supersonic.chat.parser;
|
|||||||
import com.tencent.supersonic.chat.api.component.SemanticQuery;
|
import com.tencent.supersonic.chat.api.component.SemanticQuery;
|
||||||
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
||||||
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
|
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
|
||||||
|
import com.tencent.supersonic.chat.query.llm.dsl.DslQuery;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,6 +22,9 @@ public class SatisfactionChecker {
|
|||||||
// check all the parse info in candidate
|
// check all the parse info in candidate
|
||||||
public static boolean check(QueryContext queryContext) {
|
public static boolean check(QueryContext queryContext) {
|
||||||
for (SemanticQuery query : queryContext.getCandidateQueries()) {
|
for (SemanticQuery query : queryContext.getCandidateQueries()) {
|
||||||
|
if (query.getQueryMode().equals(DslQuery.QUERY_MODE)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (checkThreshold(queryContext.getRequest().getQueryText(), query.getParseInfo())) {
|
if (checkThreshold(queryContext.getRequest().getQueryText(), query.getParseInfo())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -29,7 +33,7 @@ public class SatisfactionChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static boolean checkThreshold(String queryText, SemanticParseInfo semanticParseInfo) {
|
private static boolean checkThreshold(String queryText, SemanticParseInfo semanticParseInfo) {
|
||||||
int queryTextLength = queryText.length();
|
int queryTextLength = queryText.replaceAll(" ", "").length();
|
||||||
double degree = semanticParseInfo.getScore() / queryTextLength;
|
double degree = semanticParseInfo.getScore() / queryTextLength;
|
||||||
if (queryTextLength > QUERY_TEXT_LENGTH_THRESHOLD) {
|
if (queryTextLength > QUERY_TEXT_LENGTH_THRESHOLD) {
|
||||||
if (degree < LONG_TEXT_THRESHOLD) {
|
if (degree < LONG_TEXT_THRESHOLD) {
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
package com.tencent.supersonic.chat.parser.llm;
|
|
||||||
|
|
||||||
import com.tencent.supersonic.chat.plugin.PluginParseResult;
|
|
||||||
import com.tencent.supersonic.chat.query.dsl.LLMResp;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class DSLParseResult extends PluginParseResult {
|
|
||||||
|
|
||||||
private LLMResp llmResp;
|
|
||||||
}
|
|
||||||
@@ -1,231 +0,0 @@
|
|||||||
package com.tencent.supersonic.chat.parser.llm;
|
|
||||||
|
|
||||||
import com.tencent.supersonic.chat.api.component.SemanticParser;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.ChatContext;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.SemanticSchema;
|
|
||||||
import com.tencent.supersonic.chat.config.LLMConfig;
|
|
||||||
import com.tencent.supersonic.chat.parser.SatisfactionChecker;
|
|
||||||
import com.tencent.supersonic.chat.parser.function.ModelResolver;
|
|
||||||
import com.tencent.supersonic.chat.plugin.Plugin;
|
|
||||||
import com.tencent.supersonic.chat.plugin.PluginManager;
|
|
||||||
import com.tencent.supersonic.chat.query.QueryManager;
|
|
||||||
import com.tencent.supersonic.chat.query.dsl.DSLBuilder;
|
|
||||||
import com.tencent.supersonic.chat.query.dsl.DSLQuery;
|
|
||||||
import com.tencent.supersonic.chat.query.dsl.LLMReq;
|
|
||||||
import com.tencent.supersonic.chat.query.dsl.LLMReq.ElementValue;
|
|
||||||
import com.tencent.supersonic.chat.query.dsl.LLMResp;
|
|
||||||
import com.tencent.supersonic.chat.query.plugin.PluginSemanticQuery;
|
|
||||||
import com.tencent.supersonic.chat.utils.ComponentFactory;
|
|
||||||
import com.tencent.supersonic.common.pojo.Constants;
|
|
||||||
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.knowledge.service.SchemaService;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.http.HttpEntity;
|
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.http.HttpMethod;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.util.CollectionUtils;
|
|
||||||
import org.springframework.web.client.RestTemplate;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
public class LLMDSLParser implements SemanticParser {
|
|
||||||
|
|
||||||
public static final double FUNCTION_BONUS_THRESHOLD = 201;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void parse(QueryContext queryCtx, ChatContext chatCtx) {
|
|
||||||
final LLMConfig llmConfig = ContextUtils.getBean(LLMConfig.class);
|
|
||||||
if (StringUtils.isEmpty(llmConfig.getUrl()) || SatisfactionChecker.check(queryCtx)) {
|
|
||||||
log.info("llmConfig:{}, skip function parser, queryText:{}", llmConfig,
|
|
||||||
queryCtx.getRequest().getQueryText());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<Plugin> dslPlugins = PluginManager.getPlugins().stream()
|
|
||||||
.filter(plugin -> DSLQuery.QUERY_MODE.equalsIgnoreCase(plugin.getType()))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
if (CollectionUtils.isEmpty(dslPlugins)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Plugin plugin = dslPlugins.get(0);
|
|
||||||
List<Long> dslModels = plugin.getModelList();
|
|
||||||
|
|
||||||
try {
|
|
||||||
ModelResolver modelResolver = ComponentFactory.getModelResolver();
|
|
||||||
Long modelId = modelResolver.resolve(queryCtx, chatCtx, dslModels);
|
|
||||||
log.info("resolve modelId:{},dslModels:{}", modelId, dslModels);
|
|
||||||
|
|
||||||
if (Objects.isNull(modelId)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LLMResp llmResp = requestLLM(queryCtx, modelId);
|
|
||||||
if (Objects.isNull(llmResp)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PluginSemanticQuery semanticQuery = QueryManager.createPluginQuery(DSLQuery.QUERY_MODE);
|
|
||||||
|
|
||||||
SemanticParseInfo parseInfo = semanticQuery.getParseInfo();
|
|
||||||
if (Objects.nonNull(modelId) && modelId > 0) {
|
|
||||||
parseInfo.getElementMatches().addAll(queryCtx.getMapInfo().getMatchedElements(modelId));
|
|
||||||
}
|
|
||||||
DSLParseResult dslParseResult = new DSLParseResult();
|
|
||||||
dslParseResult.setRequest(queryCtx.getRequest());
|
|
||||||
dslParseResult.setLlmResp(llmResp);
|
|
||||||
dslParseResult.setPlugin(plugin);
|
|
||||||
|
|
||||||
Map<String, Object> properties = new HashMap<>();
|
|
||||||
properties.put(Constants.CONTEXT, dslParseResult);
|
|
||||||
parseInfo.setProperties(properties);
|
|
||||||
parseInfo.setScore(FUNCTION_BONUS_THRESHOLD);
|
|
||||||
parseInfo.setQueryMode(semanticQuery.getQueryMode());
|
|
||||||
SchemaElement Model = new SchemaElement();
|
|
||||||
Model.setModel(modelId);
|
|
||||||
Model.setId(modelId);
|
|
||||||
parseInfo.setModel(Model);
|
|
||||||
queryCtx.getCandidateQueries().add(semanticQuery);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("LLMDSLParser error", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private LLMResp requestLLM(QueryContext queryCtx, Long modelId) {
|
|
||||||
long startTime = System.currentTimeMillis();
|
|
||||||
String queryText = queryCtx.getRequest().getQueryText();
|
|
||||||
final LLMConfig llmConfig = ContextUtils.getBean(LLMConfig.class);
|
|
||||||
|
|
||||||
if (StringUtils.isEmpty(llmConfig.getUrl())) {
|
|
||||||
log.warn("llmConfig url is null, skip llm parser");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
SemanticSchema semanticSchema = ContextUtils.getBean(SchemaService.class).getSemanticSchema();
|
|
||||||
Map<Long, String> modelIdToName = semanticSchema.getModelIdToName();
|
|
||||||
|
|
||||||
LLMReq llmReq = new LLMReq();
|
|
||||||
llmReq.setQueryText(queryText);
|
|
||||||
LLMReq.LLMSchema llmSchema = new LLMReq.LLMSchema();
|
|
||||||
llmSchema.setModelName(modelIdToName.get(modelId));
|
|
||||||
llmSchema.setDomainName(modelIdToName.get(modelId));
|
|
||||||
List<String> fieldNameList = getFieldNameList(queryCtx, modelId, semanticSchema);
|
|
||||||
fieldNameList.add(DSLBuilder.DATA_Field);
|
|
||||||
llmSchema.setFieldNameList(fieldNameList);
|
|
||||||
llmReq.setSchema(llmSchema);
|
|
||||||
List<ElementValue> linking = new ArrayList<>();
|
|
||||||
linking.addAll(getValueList(queryCtx, modelId, semanticSchema));
|
|
||||||
llmReq.setLinking(linking);
|
|
||||||
String currentDate = getCurrentDate(modelId);
|
|
||||||
llmReq.setCurrentDate(currentDate);
|
|
||||||
|
|
||||||
log.info("requestLLM request, modelId:{},llmReq:{}", modelId, llmReq);
|
|
||||||
String questUrl = llmConfig.getUrl() + llmConfig.getQueryToSqlPath();
|
|
||||||
|
|
||||||
RestTemplate restTemplate = ContextUtils.getBean(RestTemplate.class);
|
|
||||||
|
|
||||||
try {
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
|
||||||
HttpEntity<String> entity = new HttpEntity<>(JsonUtil.toString(llmReq), headers);
|
|
||||||
ResponseEntity<LLMResp> responseEntity = restTemplate.exchange(questUrl, HttpMethod.POST, entity,
|
|
||||||
LLMResp.class);
|
|
||||||
|
|
||||||
log.info("requestLLM response,cost:{}, questUrl:{} \n entity:{} \n body:{}",
|
|
||||||
System.currentTimeMillis() - startTime, questUrl, entity, responseEntity.getBody());
|
|
||||||
return responseEntity.getBody();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("requestLLM error", e);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private String getCurrentDate(Long modelId) {
|
|
||||||
return DateUtils.getBeforeDate(4);
|
|
||||||
// ChatConfigFilter filter = new ChatConfigFilter();
|
|
||||||
// filter.setModelId(modelId);
|
|
||||||
//
|
|
||||||
// List<ChatConfigResp> configResps = ContextUtils.getBean(ConfigService.class).search(filter, null);
|
|
||||||
// if (CollectionUtils.isEmpty(configResps)) {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// ChatConfigResp chatConfigResp = configResps.get(0);
|
|
||||||
// chatConfigResp.getChatDetailConfig().getChatDefaultConfig().get
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<ElementValue> getValueList(QueryContext queryCtx, Long modelId, SemanticSchema semanticSchema) {
|
|
||||||
Map<Long, String> itemIdToName = getItemIdToName(modelId, semanticSchema);
|
|
||||||
|
|
||||||
List<SchemaElementMatch> matchedElements = queryCtx.getMapInfo().getMatchedElements(modelId);
|
|
||||||
if (CollectionUtils.isEmpty(matchedElements)) {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
Set<ElementValue> valueMatches = matchedElements.stream()
|
|
||||||
.filter(schemaElementMatch -> {
|
|
||||||
SchemaElementType type = schemaElementMatch.getElement().getType();
|
|
||||||
return SchemaElementType.VALUE.equals(type) || SchemaElementType.ID.equals(type);
|
|
||||||
})
|
|
||||||
.map(elementMatch ->
|
|
||||||
{
|
|
||||||
ElementValue elementValue = new ElementValue();
|
|
||||||
elementValue.setFieldName(itemIdToName.get(elementMatch.getElement().getId()));
|
|
||||||
elementValue.setFieldValue(elementMatch.getWord());
|
|
||||||
return elementValue;
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
return new ArrayList<>(valueMatches);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> getFieldNameList(QueryContext queryCtx, Long modelId, SemanticSchema semanticSchema) {
|
|
||||||
Map<Long, String> itemIdToName = getItemIdToName(modelId, semanticSchema);
|
|
||||||
|
|
||||||
List<SchemaElementMatch> matchedElements = queryCtx.getMapInfo().getMatchedElements(modelId);
|
|
||||||
if (CollectionUtils.isEmpty(matchedElements)) {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
Set<String> fieldNameList = matchedElements.stream()
|
|
||||||
.filter(schemaElementMatch -> {
|
|
||||||
SchemaElementType elementType = schemaElementMatch.getElement().getType();
|
|
||||||
return SchemaElementType.METRIC.equals(elementType) ||
|
|
||||||
SchemaElementType.DIMENSION.equals(elementType) ||
|
|
||||||
SchemaElementType.VALUE.equals(elementType);
|
|
||||||
})
|
|
||||||
.map(schemaElementMatch -> {
|
|
||||||
SchemaElementType elementType = schemaElementMatch.getElement().getType();
|
|
||||||
|
|
||||||
if (!SchemaElementType.VALUE.equals(elementType)) {
|
|
||||||
return schemaElementMatch.getWord();
|
|
||||||
}
|
|
||||||
return itemIdToName.get(schemaElementMatch.getElement().getId());
|
|
||||||
})
|
|
||||||
.filter(name -> StringUtils.isNotEmpty(name) && !name.contains("%"))
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
return new ArrayList<>(fieldNameList);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<Long, String> getItemIdToName(Long modelId, SemanticSchema semanticSchema) {
|
|
||||||
return semanticSchema.getDimensions().stream()
|
|
||||||
.filter(entry -> modelId.equals(entry.getModel()))
|
|
||||||
.collect(Collectors.toMap(SchemaElement::getId, SchemaElement::getName, (value1, value2) -> value2));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.tencent.supersonic.chat.parser.llm.dsl;
|
||||||
|
|
||||||
|
import com.tencent.supersonic.common.util.DateUtils;
|
||||||
|
|
||||||
|
public class DSLDateHelper {
|
||||||
|
|
||||||
|
public static String getCurrentDate(Long modelId) {
|
||||||
|
return DateUtils.getBeforeDate(4);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.tencent.supersonic.chat.parser.llm.dsl;
|
||||||
|
|
||||||
|
import com.tencent.supersonic.chat.agent.tool.DslTool;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
|
||||||
|
import com.tencent.supersonic.chat.query.llm.dsl.LLMReq;
|
||||||
|
import com.tencent.supersonic.chat.query.llm.dsl.LLMResp;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class DSLParseResult {
|
||||||
|
|
||||||
|
private LLMReq llmReq;
|
||||||
|
|
||||||
|
private LLMResp llmResp;
|
||||||
|
|
||||||
|
private QueryReq request;
|
||||||
|
|
||||||
|
private DslTool dslTool;
|
||||||
|
}
|
||||||
@@ -0,0 +1,380 @@
|
|||||||
|
package com.tencent.supersonic.chat.parser.llm.dsl;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.tencent.supersonic.chat.agent.tool.AgentToolType;
|
||||||
|
import com.tencent.supersonic.chat.agent.tool.DslTool;
|
||||||
|
import com.tencent.supersonic.chat.api.component.SemanticCorrector;
|
||||||
|
import com.tencent.supersonic.chat.api.component.SemanticParser;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.ChatContext;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.CorrectionInfo;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.SemanticSchema;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.request.QueryFilter;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
|
||||||
|
import com.tencent.supersonic.chat.config.LLMConfig;
|
||||||
|
import com.tencent.supersonic.chat.corrector.BaseSemanticCorrector;
|
||||||
|
import com.tencent.supersonic.chat.parser.SatisfactionChecker;
|
||||||
|
import com.tencent.supersonic.chat.parser.plugin.function.ModelResolver;
|
||||||
|
import com.tencent.supersonic.chat.query.QueryManager;
|
||||||
|
import com.tencent.supersonic.chat.query.llm.dsl.DslQuery;
|
||||||
|
import com.tencent.supersonic.chat.query.llm.dsl.LLMReq;
|
||||||
|
import com.tencent.supersonic.chat.query.llm.dsl.LLMReq.ElementValue;
|
||||||
|
import com.tencent.supersonic.chat.query.llm.dsl.LLMResp;
|
||||||
|
import com.tencent.supersonic.chat.query.plugin.PluginSemanticQuery;
|
||||||
|
import com.tencent.supersonic.chat.service.AgentService;
|
||||||
|
import com.tencent.supersonic.chat.utils.ComponentFactory;
|
||||||
|
import com.tencent.supersonic.common.pojo.Constants;
|
||||||
|
import com.tencent.supersonic.common.pojo.DateConf;
|
||||||
|
import com.tencent.supersonic.common.pojo.DateConf.DateMode;
|
||||||
|
import com.tencent.supersonic.common.util.ContextUtils;
|
||||||
|
import com.tencent.supersonic.common.util.JsonUtil;
|
||||||
|
import com.tencent.supersonic.common.util.jsqlparser.FilterExpression;
|
||||||
|
import com.tencent.supersonic.common.util.jsqlparser.SqlParserSelectHelper;
|
||||||
|
import com.tencent.supersonic.knowledge.service.SchemaService;
|
||||||
|
import com.tencent.supersonic.semantic.api.model.enums.TimeDimensionEnum;
|
||||||
|
import com.tencent.supersonic.semantic.api.query.enums.FilterOperatorEnum;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.http.HttpEntity;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class LLMDslParser implements SemanticParser {
|
||||||
|
|
||||||
|
public static final double function_bonus_threshold = 201;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parse(QueryContext queryCtx, ChatContext chatCtx) {
|
||||||
|
QueryReq request = queryCtx.getRequest();
|
||||||
|
LLMConfig llmConfig = ContextUtils.getBean(LLMConfig.class);
|
||||||
|
if (StringUtils.isEmpty(llmConfig.getUrl()) || SatisfactionChecker.check(queryCtx)) {
|
||||||
|
log.info("llmConfig:{}, skip function parser, queryText:{}", llmConfig, request.getQueryText());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Long modelId = getModelId(queryCtx, chatCtx, request.getAgentId());
|
||||||
|
if (Objects.isNull(modelId) || modelId <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DslTool dslTool = getDslTool(request, modelId);
|
||||||
|
if (Objects.isNull(dslTool)) {
|
||||||
|
log.info("no dsl tool in this agent, skip dsl parser");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLMReq llmReq = getLlmReq(queryCtx, modelId);
|
||||||
|
LLMResp llmResp = requestLLM(llmReq, modelId, llmConfig);
|
||||||
|
|
||||||
|
if (Objects.isNull(llmResp)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DSLParseResult dslParseResult = DSLParseResult.builder().request(request).dslTool(dslTool).llmReq(llmReq)
|
||||||
|
.llmResp(llmResp).build();
|
||||||
|
|
||||||
|
SemanticParseInfo parseInfo = getParseInfo(queryCtx, modelId, dslTool, dslParseResult);
|
||||||
|
|
||||||
|
String correctorSql = getCorrectorSql(queryCtx, parseInfo, llmResp.getSqlOutput());
|
||||||
|
|
||||||
|
llmResp.setCorrectorSql(correctorSql);
|
||||||
|
|
||||||
|
setFilter(correctorSql, modelId, parseInfo);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("LLMDSLParser error", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFilter(String correctorSql, Long modelId, SemanticParseInfo parseInfo) {
|
||||||
|
|
||||||
|
List<FilterExpression> expressions = SqlParserSelectHelper.getFilterExpression(correctorSql);
|
||||||
|
if (CollectionUtils.isEmpty(expressions)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//set dataInfo
|
||||||
|
try {
|
||||||
|
DateConf dateInfo = getDateInfo(expressions);
|
||||||
|
parseInfo.setDateInfo(dateInfo);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("set dateInfo error :", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
//set filter
|
||||||
|
try {
|
||||||
|
Map<String, SchemaElement> bizNameToElement = getBizNameToElement(modelId);
|
||||||
|
List<QueryFilter> result = getDimensionFilter(bizNameToElement, expressions);
|
||||||
|
parseInfo.getDimensionFilters().addAll(result);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("set dimensionFilter error :", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<QueryFilter> getDimensionFilter(Map<String, SchemaElement> bizNameToElement,
|
||||||
|
List<FilterExpression> filterExpressions) {
|
||||||
|
List<QueryFilter> result = Lists.newArrayList();
|
||||||
|
for (FilterExpression expression : filterExpressions) {
|
||||||
|
QueryFilter dimensionFilter = new QueryFilter();
|
||||||
|
dimensionFilter.setValue(expression.getFieldValue());
|
||||||
|
String bizName = expression.getFieldName();
|
||||||
|
SchemaElement schemaElement = bizNameToElement.get(bizName);
|
||||||
|
if (Objects.isNull(schemaElement)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String fieldName = schemaElement.getName();
|
||||||
|
dimensionFilter.setName(fieldName);
|
||||||
|
dimensionFilter.setBizName(bizName);
|
||||||
|
dimensionFilter.setElementID(schemaElement.getId());
|
||||||
|
|
||||||
|
FilterOperatorEnum operatorEnum = FilterOperatorEnum.getSqlOperator(expression.getOperator());
|
||||||
|
dimensionFilter.setOperator(operatorEnum);
|
||||||
|
result.add(dimensionFilter);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DateConf getDateInfo(List<FilterExpression> filterExpressions) {
|
||||||
|
List<FilterExpression> dateExpressions = filterExpressions.stream()
|
||||||
|
.filter(expression -> {
|
||||||
|
List<String> nameList = TimeDimensionEnum.getNameList();
|
||||||
|
if (StringUtils.isEmpty(expression.getFieldName())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return nameList.contains(expression.getFieldName().toLowerCase());
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
if (CollectionUtils.isEmpty(dateExpressions)) {
|
||||||
|
return new DateConf();
|
||||||
|
}
|
||||||
|
DateConf dateInfo = new DateConf();
|
||||||
|
dateInfo.setDateMode(DateMode.BETWEEN);
|
||||||
|
FilterExpression 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(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 boolean containOperators(FilterExpression expression, FilterOperatorEnum firstOperator,
|
||||||
|
FilterOperatorEnum... operatorEnums) {
|
||||||
|
return (Arrays.asList(operatorEnums).contains(firstOperator) && Objects.nonNull(expression.getFieldValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasSecondDate(List<FilterExpression> dateExpressions) {
|
||||||
|
return dateExpressions.size() > 1 && Objects.nonNull(dateExpressions.get(1).getFieldValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getCorrectorSql(QueryContext queryCtx, SemanticParseInfo parseInfo, String sql) {
|
||||||
|
|
||||||
|
CorrectionInfo correctionInfo = CorrectionInfo.builder()
|
||||||
|
.queryFilters(queryCtx.getRequest().getQueryFilters()).sql(sql)
|
||||||
|
.parseInfo(parseInfo).build();
|
||||||
|
|
||||||
|
List<SemanticCorrector> dslCorrections = ComponentFactory.getSqlCorrections();
|
||||||
|
|
||||||
|
dslCorrections.forEach(dslCorrection -> {
|
||||||
|
try {
|
||||||
|
dslCorrection.corrector(correctionInfo);
|
||||||
|
log.info("sqlCorrection:{} sql:{}", dslCorrection.getClass().getSimpleName(),
|
||||||
|
correctionInfo.getSql());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("sqlCorrection:{} execute error,correctionInfo:{}", dslCorrection, correctionInfo, e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return correctionInfo.getSql();
|
||||||
|
}
|
||||||
|
|
||||||
|
private SemanticParseInfo getParseInfo(QueryContext queryCtx, Long modelId, DslTool dslTool,
|
||||||
|
DSLParseResult dslParseResult) {
|
||||||
|
PluginSemanticQuery semanticQuery = QueryManager.createPluginQuery(DslQuery.QUERY_MODE);
|
||||||
|
SemanticParseInfo parseInfo = semanticQuery.getParseInfo();
|
||||||
|
parseInfo.getElementMatches().addAll(queryCtx.getMapInfo().getMatchedElements(modelId));
|
||||||
|
|
||||||
|
Map<String, Object> properties = new HashMap<>();
|
||||||
|
properties.put(Constants.CONTEXT, dslParseResult);
|
||||||
|
properties.put("type", "internal");
|
||||||
|
properties.put("name", dslTool.getName());
|
||||||
|
|
||||||
|
parseInfo.setProperties(properties);
|
||||||
|
parseInfo.setScore(function_bonus_threshold);
|
||||||
|
parseInfo.setQueryMode(semanticQuery.getQueryMode());
|
||||||
|
|
||||||
|
SemanticSchema semanticSchema = ContextUtils.getBean(SchemaService.class).getSemanticSchema();
|
||||||
|
Map<Long, String> modelIdToName = semanticSchema.getModelIdToName();
|
||||||
|
|
||||||
|
SchemaElement model = new SchemaElement();
|
||||||
|
model.setModel(modelId);
|
||||||
|
model.setId(modelId);
|
||||||
|
model.setName(modelIdToName.get(modelId));
|
||||||
|
parseInfo.setModel(model);
|
||||||
|
queryCtx.getCandidateQueries().add(semanticQuery);
|
||||||
|
return parseInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DslTool getDslTool(QueryReq request, Long modelId) {
|
||||||
|
AgentService agentService = ContextUtils.getBean(AgentService.class);
|
||||||
|
List<DslTool> dslTools = agentService.getDslTools(request.getAgentId(), AgentToolType.DSL);
|
||||||
|
Optional<DslTool> dslToolOptional = dslTools.stream().filter(tool -> tool.getModelIds().contains(modelId))
|
||||||
|
.findFirst();
|
||||||
|
return dslToolOptional.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long getModelId(QueryContext queryCtx, ChatContext chatCtx, Integer agentId) {
|
||||||
|
AgentService agentService = ContextUtils.getBean(AgentService.class);
|
||||||
|
Set<Long> distinctModelIds = agentService.getDslToolsModelIds(agentId, AgentToolType.DSL);
|
||||||
|
ModelResolver modelResolver = ComponentFactory.getModelResolver();
|
||||||
|
Long modelId = modelResolver.resolve(queryCtx, chatCtx, distinctModelIds);
|
||||||
|
log.info("resolve modelId:{},dslModels:{}", modelId, distinctModelIds);
|
||||||
|
return modelId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LLMResp requestLLM(LLMReq llmReq, Long modelId, LLMConfig llmConfig) {
|
||||||
|
String questUrl = llmConfig.getUrl() + llmConfig.getQueryToSqlPath();
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
log.info("requestLLM request, modelId:{},llmReq:{}", modelId, llmReq);
|
||||||
|
RestTemplate restTemplate = ContextUtils.getBean(RestTemplate.class);
|
||||||
|
try {
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
HttpEntity<String> entity = new HttpEntity<>(JsonUtil.toString(llmReq), headers);
|
||||||
|
ResponseEntity<LLMResp> responseEntity = restTemplate.exchange(questUrl, HttpMethod.POST, entity,
|
||||||
|
LLMResp.class);
|
||||||
|
|
||||||
|
log.info("requestLLM response,cost:{}, questUrl:{} \n entity:{} \n body:{}",
|
||||||
|
System.currentTimeMillis() - startTime, questUrl, entity, responseEntity.getBody());
|
||||||
|
return responseEntity.getBody();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("requestLLM error", e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LLMReq getLlmReq(QueryContext queryCtx, Long modelId) {
|
||||||
|
SemanticSchema semanticSchema = ContextUtils.getBean(SchemaService.class).getSemanticSchema();
|
||||||
|
Map<Long, String> modelIdToName = semanticSchema.getModelIdToName();
|
||||||
|
String queryText = queryCtx.getRequest().getQueryText();
|
||||||
|
LLMReq llmReq = new LLMReq();
|
||||||
|
llmReq.setQueryText(queryText);
|
||||||
|
LLMReq.LLMSchema llmSchema = new LLMReq.LLMSchema();
|
||||||
|
llmSchema.setModelName(modelIdToName.get(modelId));
|
||||||
|
llmSchema.setDomainName(modelIdToName.get(modelId));
|
||||||
|
List<String> fieldNameList = getFieldNameList(queryCtx, modelId, semanticSchema);
|
||||||
|
fieldNameList.add(BaseSemanticCorrector.DATE_FIELD);
|
||||||
|
llmSchema.setFieldNameList(fieldNameList);
|
||||||
|
llmReq.setSchema(llmSchema);
|
||||||
|
List<ElementValue> linking = new ArrayList<>();
|
||||||
|
linking.addAll(getValueList(queryCtx, modelId, semanticSchema));
|
||||||
|
llmReq.setLinking(linking);
|
||||||
|
String currentDate = DSLDateHelper.getCurrentDate(modelId);
|
||||||
|
llmReq.setCurrentDate(currentDate);
|
||||||
|
return llmReq;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ElementValue> getValueList(QueryContext queryCtx, Long modelId, SemanticSchema semanticSchema) {
|
||||||
|
Map<Long, String> itemIdToName = getItemIdToName(modelId, semanticSchema);
|
||||||
|
|
||||||
|
List<SchemaElementMatch> matchedElements = queryCtx.getMapInfo().getMatchedElements(modelId);
|
||||||
|
if (CollectionUtils.isEmpty(matchedElements)) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
Set<ElementValue> valueMatches = matchedElements
|
||||||
|
.stream()
|
||||||
|
.filter(elementMatch -> !elementMatch.isInherited())
|
||||||
|
.filter(schemaElementMatch -> {
|
||||||
|
SchemaElementType type = schemaElementMatch.getElement().getType();
|
||||||
|
return SchemaElementType.VALUE.equals(type) || SchemaElementType.ID.equals(type);
|
||||||
|
})
|
||||||
|
.map(elementMatch -> {
|
||||||
|
ElementValue elementValue = new ElementValue();
|
||||||
|
elementValue.setFieldName(itemIdToName.get(elementMatch.getElement().getId()));
|
||||||
|
elementValue.setFieldValue(elementMatch.getWord());
|
||||||
|
return elementValue;
|
||||||
|
}).collect(Collectors.toSet());
|
||||||
|
return new ArrayList<>(valueMatches);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected Map<String, SchemaElement> getBizNameToElement(Long modelId) {
|
||||||
|
SemanticSchema semanticSchema = ContextUtils.getBean(SchemaService.class).getSemanticSchema();
|
||||||
|
List<SchemaElement> dimensions = semanticSchema.getDimensions();
|
||||||
|
List<SchemaElement> metrics = semanticSchema.getMetrics();
|
||||||
|
|
||||||
|
List<SchemaElement> allElements = Lists.newArrayList();
|
||||||
|
allElements.addAll(dimensions);
|
||||||
|
allElements.addAll(metrics);
|
||||||
|
return allElements.stream()
|
||||||
|
.filter(schemaElement -> schemaElement.getModel().equals(modelId))
|
||||||
|
.collect(Collectors.toMap(SchemaElement::getBizName, Function.identity(), (value1, value2) -> value2));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private List<String> getFieldNameList(QueryContext queryCtx, Long modelId, SemanticSchema semanticSchema) {
|
||||||
|
Map<Long, String> itemIdToName = getItemIdToName(modelId, semanticSchema);
|
||||||
|
|
||||||
|
List<SchemaElementMatch> matchedElements = queryCtx.getMapInfo().getMatchedElements(modelId);
|
||||||
|
if (CollectionUtils.isEmpty(matchedElements)) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
Set<String> fieldNameList = matchedElements.stream()
|
||||||
|
.filter(schemaElementMatch -> {
|
||||||
|
SchemaElementType elementType = schemaElementMatch.getElement().getType();
|
||||||
|
return SchemaElementType.METRIC.equals(elementType)
|
||||||
|
|| SchemaElementType.DIMENSION.equals(elementType)
|
||||||
|
|| SchemaElementType.VALUE.equals(elementType);
|
||||||
|
})
|
||||||
|
.map(schemaElementMatch -> {
|
||||||
|
SchemaElementType elementType = schemaElementMatch.getElement().getType();
|
||||||
|
|
||||||
|
if (!SchemaElementType.VALUE.equals(elementType)) {
|
||||||
|
return schemaElementMatch.getWord();
|
||||||
|
}
|
||||||
|
return itemIdToName.get(schemaElementMatch.getElement().getId());
|
||||||
|
})
|
||||||
|
.filter(name -> StringUtils.isNotEmpty(name) && !name.contains("%"))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
return new ArrayList<>(fieldNameList);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<Long, String> getItemIdToName(Long modelId, SemanticSchema semanticSchema) {
|
||||||
|
return semanticSchema.getDimensions().stream()
|
||||||
|
.filter(entry -> modelId.equals(entry.getModel()))
|
||||||
|
.collect(Collectors.toMap(SchemaElement::getId, SchemaElement::getName, (value1, value2) -> value2));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
package com.tencent.supersonic.chat.parser.llm.interpret;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import com.tencent.supersonic.chat.agent.Agent;
|
||||||
|
import com.tencent.supersonic.chat.agent.tool.AgentToolType;
|
||||||
|
import com.tencent.supersonic.chat.agent.tool.MetricInterpretTool;
|
||||||
|
import com.tencent.supersonic.chat.api.component.SemanticLayer;
|
||||||
|
import com.tencent.supersonic.chat.api.component.SemanticParser;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.ChatContext;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.ModelSchema;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.request.QueryFilter;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
|
||||||
|
import com.tencent.supersonic.chat.parser.SatisfactionChecker;
|
||||||
|
import com.tencent.supersonic.chat.query.metricinterpret.MetricInterpretQuery;
|
||||||
|
import com.tencent.supersonic.chat.query.QueryManager;
|
||||||
|
import com.tencent.supersonic.chat.query.plugin.PluginSemanticQuery;
|
||||||
|
import com.tencent.supersonic.chat.service.AgentService;
|
||||||
|
import com.tencent.supersonic.chat.utils.ComponentFactory;
|
||||||
|
import com.tencent.supersonic.common.pojo.DateConf;
|
||||||
|
import com.tencent.supersonic.common.util.ContextUtils;
|
||||||
|
import com.tencent.supersonic.semantic.api.model.enums.TimeDimensionEnum;
|
||||||
|
import com.tencent.supersonic.semantic.api.query.enums.FilterOperatorEnum;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class MetricInterpretParser implements SemanticParser {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parse(QueryContext queryContext, ChatContext chatContext) {
|
||||||
|
if (SatisfactionChecker.check(queryContext)) {
|
||||||
|
log.info("skip MetricInterpretParser");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Map<Long, MetricInterpretTool> metricInterpretToolMap =
|
||||||
|
getMetricInterpretTools(queryContext.getRequest().getAgentId());
|
||||||
|
log.info("metric interpret tool : {}", metricInterpretToolMap);
|
||||||
|
if (CollectionUtils.isEmpty(metricInterpretToolMap)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Map<Long, List<SchemaElementMatch>> elementMatches = queryContext.getMapInfo().getModelElementMatches();
|
||||||
|
for (Long modelId : elementMatches.keySet()) {
|
||||||
|
MetricInterpretTool metricInterpretTool = metricInterpretToolMap.get(modelId);
|
||||||
|
if (metricInterpretTool == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (CollectionUtils.isEmpty(elementMatches.get(modelId))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
List<MetricOption> metricOptions = metricInterpretTool.getMetricOptions();
|
||||||
|
if (!CollectionUtils.isEmpty(metricOptions)) {
|
||||||
|
List<Long> metricIds = metricOptions.stream()
|
||||||
|
.map(MetricOption::getMetricId).collect(Collectors.toList());
|
||||||
|
String name = metricInterpretTool.getName();
|
||||||
|
buildQuery(modelId, queryContext, metricIds, elementMatches.get(modelId), name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildQuery(Long modelId, QueryContext queryContext,
|
||||||
|
List<Long> metricIds, List<SchemaElementMatch> schemaElementMatches, String toolName) {
|
||||||
|
PluginSemanticQuery metricInterpretQuery = QueryManager.createPluginQuery(MetricInterpretQuery.QUERY_MODE);
|
||||||
|
Set<SchemaElement> metrics = getMetrics(metricIds, modelId);
|
||||||
|
SemanticParseInfo semanticParseInfo = buildSemanticParseInfo(modelId, queryContext.getRequest(),
|
||||||
|
metrics, schemaElementMatches, toolName);
|
||||||
|
semanticParseInfo.setQueryMode(metricInterpretQuery.getQueryMode());
|
||||||
|
semanticParseInfo.getProperties().put("queryText", queryContext.getRequest().getQueryText());
|
||||||
|
metricInterpretQuery.setParseInfo(semanticParseInfo);
|
||||||
|
queryContext.getCandidateQueries().add(metricInterpretQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<SchemaElement> getMetrics(List<Long> metricIds, Long modelId) {
|
||||||
|
SemanticLayer semanticLayer = ComponentFactory.getSemanticLayer();
|
||||||
|
ModelSchema modelSchema = semanticLayer.getModelSchema(modelId, true);
|
||||||
|
Set<SchemaElement> metrics = modelSchema.getMetrics();
|
||||||
|
return metrics.stream().filter(schemaElement -> metricIds.contains(schemaElement.getId()))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<Long, MetricInterpretTool> getMetricInterpretTools(Integer agentId) {
|
||||||
|
AgentService agentService = ContextUtils.getBean(AgentService.class);
|
||||||
|
Agent agent = agentService.getAgent(agentId);
|
||||||
|
if (agent == null) {
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
List<String> tools = agent.getTools(AgentToolType.INTERPRET);
|
||||||
|
if (CollectionUtils.isEmpty(tools)) {
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
List<MetricInterpretTool> metricInterpretTools = tools.stream().map(tool ->
|
||||||
|
JSONObject.parseObject(tool, MetricInterpretTool.class))
|
||||||
|
.filter(tool -> !CollectionUtils.isEmpty(tool.getMetricOptions()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
Map<Long, MetricInterpretTool> metricInterpretToolMap = new HashMap<>();
|
||||||
|
for (MetricInterpretTool metricInterpretTool : metricInterpretTools) {
|
||||||
|
metricInterpretToolMap.putIfAbsent(metricInterpretTool.getModelId(),
|
||||||
|
metricInterpretTool);
|
||||||
|
}
|
||||||
|
return metricInterpretToolMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SemanticParseInfo buildSemanticParseInfo(Long modelId, QueryReq queryReq, Set<SchemaElement> metrics,
|
||||||
|
List<SchemaElementMatch> schemaElementMatches, String toolName) {
|
||||||
|
SchemaElement model = new SchemaElement();
|
||||||
|
model.setModel(modelId);
|
||||||
|
model.setId(modelId);
|
||||||
|
SemanticParseInfo semanticParseInfo = new SemanticParseInfo();
|
||||||
|
semanticParseInfo.setMetrics(metrics);
|
||||||
|
SchemaElement dimension = new SchemaElement();
|
||||||
|
dimension.setBizName(TimeDimensionEnum.DAY.getName());
|
||||||
|
semanticParseInfo.setDimensions(Sets.newHashSet(dimension));
|
||||||
|
semanticParseInfo.setElementMatches(schemaElementMatches);
|
||||||
|
semanticParseInfo.setModel(model);
|
||||||
|
semanticParseInfo.setScore(queryReq.getQueryText().length());
|
||||||
|
DateConf dateConf = new DateConf();
|
||||||
|
dateConf.setDateMode(DateConf.DateMode.RECENT);
|
||||||
|
dateConf.setUnit(15);
|
||||||
|
semanticParseInfo.setDateInfo(dateConf);
|
||||||
|
Map<String, Object> properties = new HashMap<>();
|
||||||
|
properties.put("type", "internal");
|
||||||
|
properties.put("name", toolName);
|
||||||
|
semanticParseInfo.setProperties(properties);
|
||||||
|
fillSemanticParseInfo(semanticParseInfo);
|
||||||
|
return semanticParseInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillSemanticParseInfo(SemanticParseInfo semanticParseInfo) {
|
||||||
|
List<SchemaElementMatch> schemaElementMatches = semanticParseInfo.getElementMatches();
|
||||||
|
if (!CollectionUtils.isEmpty(schemaElementMatches)) {
|
||||||
|
schemaElementMatches.stream().filter(schemaElementMatch ->
|
||||||
|
SchemaElementType.VALUE.equals(schemaElementMatch.getElement().getType())
|
||||||
|
|| SchemaElementType.ID.equals(schemaElementMatch.getElement().getType()))
|
||||||
|
.forEach(schemaElementMatch -> {
|
||||||
|
QueryFilter queryFilter = new QueryFilter();
|
||||||
|
queryFilter.setValue(schemaElementMatch.getWord());
|
||||||
|
queryFilter.setElementID(schemaElementMatch.getElement().getId());
|
||||||
|
queryFilter.setName(schemaElementMatch.getElement().getName());
|
||||||
|
queryFilter.setOperator(FilterOperatorEnum.EQUALS);
|
||||||
|
queryFilter.setBizName(schemaElementMatch.getElement().getBizName());
|
||||||
|
semanticParseInfo.getDimensionFilters().add(queryFilter);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.tencent.supersonic.chat.parser.llm.interpret;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class MetricOption {
|
||||||
|
|
||||||
|
private Long metricId;
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.tencent.supersonic.chat.parser.llm;
|
package com.tencent.supersonic.chat.parser.llm.time;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
@@ -6,8 +6,8 @@ import com.tencent.supersonic.chat.api.component.SemanticParser;
|
|||||||
import com.tencent.supersonic.chat.api.component.SemanticQuery;
|
import com.tencent.supersonic.chat.api.component.SemanticQuery;
|
||||||
import com.tencent.supersonic.chat.api.pojo.ChatContext;
|
import com.tencent.supersonic.chat.api.pojo.ChatContext;
|
||||||
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
||||||
import com.tencent.supersonic.chat.utils.ChatGptHelper;
|
|
||||||
import com.tencent.supersonic.common.pojo.DateConf;
|
import com.tencent.supersonic.common.pojo.DateConf;
|
||||||
|
import com.tencent.supersonic.common.util.ChatGptHelper;
|
||||||
import com.tencent.supersonic.common.util.ContextUtils;
|
import com.tencent.supersonic.common.util.ContextUtils;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
@@ -19,8 +19,8 @@ public class LLMTimeEnhancementParse implements SemanticParser {
|
|||||||
public void parse(QueryContext queryContext, ChatContext chatContext) {
|
public void parse(QueryContext queryContext, ChatContext chatContext) {
|
||||||
log.info("before queryContext:{},chatContext:{}", queryContext, chatContext);
|
log.info("before queryContext:{},chatContext:{}", queryContext, chatContext);
|
||||||
ChatGptHelper chatGptHelper = ContextUtils.getBean(ChatGptHelper.class);
|
ChatGptHelper chatGptHelper = ContextUtils.getBean(ChatGptHelper.class);
|
||||||
String inferredTime = chatGptHelper.inferredTime(queryContext.getRequest().getQueryText());
|
|
||||||
try {
|
try {
|
||||||
|
String inferredTime = chatGptHelper.inferredTime(queryContext.getRequest().getQueryText());
|
||||||
if (!queryContext.getCandidateQueries().isEmpty()) {
|
if (!queryContext.getCandidateQueries().isEmpty()) {
|
||||||
for (SemanticQuery query : queryContext.getCandidateQueries()) {
|
for (SemanticQuery query : queryContext.getCandidateQueries()) {
|
||||||
DateConf dateInfo = query.getParseInfo().getDateInfo();
|
DateConf dateInfo = query.getParseInfo().getDateInfo();
|
||||||
@@ -43,7 +43,8 @@ public class LLMTimeEnhancementParse implements SemanticParser {
|
|||||||
(Object) exception.getStackTrace());
|
(Object) exception.getStackTrace());
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info("after queryContext:{},chatContext:{}", queryContext, chatContext);
|
log.info("{} after queryContext:{},chatContext:{}",
|
||||||
|
LLMTimeEnhancementParse.class.getSimpleName(), queryContext, chatContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1,15 +1,14 @@
|
|||||||
package com.tencent.supersonic.chat.parser.embedding;
|
package com.tencent.supersonic.chat.parser.plugin.embedding;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.tencent.supersonic.chat.api.component.SemanticParser;
|
import com.tencent.supersonic.chat.api.component.SemanticParser;
|
||||||
import com.tencent.supersonic.chat.api.pojo.ChatContext;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.ModelSchema;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
|
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
|
import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
|
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaMapInfo;
|
import com.tencent.supersonic.chat.api.pojo.ChatContext;
|
||||||
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
|
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.ModelSchema;
|
||||||
import com.tencent.supersonic.chat.api.pojo.request.QueryFilter;
|
import com.tencent.supersonic.chat.api.pojo.request.QueryFilter;
|
||||||
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
|
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
|
||||||
import com.tencent.supersonic.chat.parser.ParseMode;
|
import com.tencent.supersonic.chat.parser.ParseMode;
|
||||||
@@ -17,17 +16,18 @@ import com.tencent.supersonic.chat.plugin.Plugin;
|
|||||||
import com.tencent.supersonic.chat.plugin.PluginManager;
|
import com.tencent.supersonic.chat.plugin.PluginManager;
|
||||||
import com.tencent.supersonic.chat.plugin.PluginParseResult;
|
import com.tencent.supersonic.chat.plugin.PluginParseResult;
|
||||||
import com.tencent.supersonic.chat.query.QueryManager;
|
import com.tencent.supersonic.chat.query.QueryManager;
|
||||||
|
import com.tencent.supersonic.chat.query.llm.dsl.DslQuery;
|
||||||
import com.tencent.supersonic.chat.query.plugin.PluginSemanticQuery;
|
import com.tencent.supersonic.chat.query.plugin.PluginSemanticQuery;
|
||||||
import com.tencent.supersonic.chat.service.PluginService;
|
|
||||||
import com.tencent.supersonic.chat.service.SemanticService;
|
import com.tencent.supersonic.chat.service.SemanticService;
|
||||||
import com.tencent.supersonic.common.pojo.Constants;
|
import com.tencent.supersonic.common.pojo.Constants;
|
||||||
import com.tencent.supersonic.common.util.ContextUtils;
|
import com.tencent.supersonic.common.util.ContextUtils;
|
||||||
import com.tencent.supersonic.semantic.api.query.enums.FilterOperatorEnum;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import com.tencent.supersonic.semantic.api.query.enums.FilterOperatorEnum;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
@@ -53,48 +53,32 @@ public class EmbeddingBasedParser implements SemanticParser {
|
|||||||
if (CollectionUtils.isEmpty(embeddingRetrievals)) {
|
if (CollectionUtils.isEmpty(embeddingRetrievals)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PluginService pluginService = ContextUtils.getBean(PluginService.class);
|
List<Plugin> plugins = getPluginList(queryContext);
|
||||||
List<Plugin> plugins = pluginService.getPluginList();
|
|
||||||
Map<Long, Plugin> pluginMap = plugins.stream().collect(Collectors.toMap(Plugin::getId, p -> p));
|
Map<Long, Plugin> pluginMap = plugins.stream().collect(Collectors.toMap(Plugin::getId, p -> p));
|
||||||
for (RecallRetrieval embeddingRetrieval : embeddingRetrievals) {
|
for (RecallRetrieval embeddingRetrieval : embeddingRetrievals) {
|
||||||
Plugin plugin = pluginMap.get(Long.parseLong(embeddingRetrieval.getId()));
|
Plugin plugin = pluginMap.get(Long.parseLong(embeddingRetrieval.getId()));
|
||||||
if (plugin == null) {
|
if (plugin == null || DslQuery.QUERY_MODE.equalsIgnoreCase(plugin.getType())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Pair<Boolean, List<Long>> pair = PluginManager.resolve(plugin, queryContext);
|
Pair<Boolean, Set<Long>> pair = PluginManager.resolve(plugin, queryContext);
|
||||||
log.info("embedding plugin resolve: {}", pair);
|
log.info("embedding plugin resolve: {}", pair);
|
||||||
if (pair.getLeft()) {
|
if (pair.getLeft()) {
|
||||||
List<Long> modelList = pair.getRight();
|
Set<Long> modelList = pair.getRight();
|
||||||
if (CollectionUtils.isEmpty(modelList)) {
|
if (CollectionUtils.isEmpty(modelList)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
modelList = distinctModelList(plugin, queryContext.getMapInfo(), modelList);
|
|
||||||
for (Long modelId : modelList) {
|
for (Long modelId : modelList) {
|
||||||
buildQuery(plugin, Double.parseDouble(embeddingRetrieval.getDistance()), modelId, queryContext,
|
buildQuery(plugin, Double.parseDouble(embeddingRetrieval.getDistance()), modelId, queryContext,
|
||||||
queryContext.getMapInfo().getMatchedElements(modelId));
|
queryContext.getMapInfo().getMatchedElements(modelId));
|
||||||
|
if (plugin.isContainsAllModel()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Long> distinctModelList(Plugin plugin, SchemaMapInfo schemaMapInfo, List<Long> modelList) {
|
|
||||||
if (!plugin.isContainsAllModel()) {
|
|
||||||
return modelList;
|
|
||||||
}
|
|
||||||
boolean noElementMatch = true;
|
|
||||||
for (Long model : modelList) {
|
|
||||||
List<SchemaElementMatch> schemaElementMatches = schemaMapInfo.getMatchedElements(model);
|
|
||||||
if (!CollectionUtils.isEmpty(schemaElementMatches)) {
|
|
||||||
noElementMatch = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (noElementMatch) {
|
|
||||||
return modelList.subList(0, 1);
|
|
||||||
}
|
|
||||||
return modelList;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void buildQuery(Plugin plugin, double distance, Long modelId,
|
private void buildQuery(Plugin plugin, double distance, Long modelId,
|
||||||
QueryContext queryContext, List<SchemaElementMatch> schemaElementMatches) {
|
QueryContext queryContext, List<SchemaElementMatch> schemaElementMatches) {
|
||||||
log.info("EmbeddingBasedParser Model: {} choose plugin: [{} {}]", modelId, plugin.getId(), plugin.getName());
|
log.info("EmbeddingBasedParser Model: {} choose plugin: [{} {}]", modelId, plugin.getId(), plugin.getName());
|
||||||
@@ -114,18 +98,20 @@ public class EmbeddingBasedParser implements SemanticParser {
|
|||||||
if (modelId == null && !CollectionUtils.isEmpty(plugin.getModelList())) {
|
if (modelId == null && !CollectionUtils.isEmpty(plugin.getModelList())) {
|
||||||
modelId = plugin.getModelList().get(0);
|
modelId = plugin.getModelList().get(0);
|
||||||
}
|
}
|
||||||
SchemaElement Model = new SchemaElement();
|
SchemaElement model = new SchemaElement();
|
||||||
Model.setModel(modelId);
|
model.setModel(modelId);
|
||||||
Model.setId(modelId);
|
model.setId(modelId);
|
||||||
SemanticParseInfo semanticParseInfo = new SemanticParseInfo();
|
SemanticParseInfo semanticParseInfo = new SemanticParseInfo();
|
||||||
semanticParseInfo.setElementMatches(schemaElementMatches);
|
semanticParseInfo.setElementMatches(schemaElementMatches);
|
||||||
semanticParseInfo.setModel(Model);
|
semanticParseInfo.setModel(model);
|
||||||
Map<String, Object> properties = new HashMap<>();
|
Map<String, Object> properties = new HashMap<>();
|
||||||
PluginParseResult pluginParseResult = new PluginParseResult();
|
PluginParseResult pluginParseResult = new PluginParseResult();
|
||||||
pluginParseResult.setPlugin(plugin);
|
pluginParseResult.setPlugin(plugin);
|
||||||
pluginParseResult.setRequest(queryReq);
|
pluginParseResult.setRequest(queryReq);
|
||||||
pluginParseResult.setDistance(distance);
|
pluginParseResult.setDistance(distance);
|
||||||
properties.put(Constants.CONTEXT, pluginParseResult);
|
properties.put(Constants.CONTEXT, pluginParseResult);
|
||||||
|
properties.put("type", "plugin");
|
||||||
|
properties.put("name", plugin.getName());
|
||||||
semanticParseInfo.setProperties(properties);
|
semanticParseInfo.setProperties(properties);
|
||||||
semanticParseInfo.setScore(distance);
|
semanticParseInfo.setScore(distance);
|
||||||
fillSemanticParseInfo(semanticParseInfo);
|
fillSemanticParseInfo(semanticParseInfo);
|
||||||
@@ -135,9 +121,9 @@ public class EmbeddingBasedParser implements SemanticParser {
|
|||||||
|
|
||||||
private void setEntity(Long modelId, SemanticParseInfo semanticParseInfo) {
|
private void setEntity(Long modelId, SemanticParseInfo semanticParseInfo) {
|
||||||
SemanticService semanticService = ContextUtils.getBean(SemanticService.class);
|
SemanticService semanticService = ContextUtils.getBean(SemanticService.class);
|
||||||
ModelSchema ModelSchema = semanticService.getModelSchema(modelId);
|
ModelSchema modelSchema = semanticService.getModelSchema(modelId);
|
||||||
if (ModelSchema != null && ModelSchema.getEntity() != null) {
|
if (modelSchema != null && modelSchema.getEntity() != null) {
|
||||||
semanticParseInfo.setEntity(ModelSchema.getEntity());
|
semanticParseInfo.setEntity(modelSchema.getEntity());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,4 +162,8 @@ public class EmbeddingBasedParser implements SemanticParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected List<Plugin> getPluginList(QueryContext queryContext) {
|
||||||
|
return PluginManager.getPluginAgentCanSupport(queryContext.getRequest().getAgentId());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.tencent.supersonic.chat.parser.embedding;
|
package com.tencent.supersonic.chat.parser.plugin.embedding;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
@@ -1,26 +1,26 @@
|
|||||||
package com.tencent.supersonic.chat.parser.embedding;
|
package com.tencent.supersonic.chat.parser.plugin.embedding;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.tencent.supersonic.chat.api.pojo.ChatContext;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
|
import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaMapInfo;
|
import com.tencent.supersonic.chat.api.pojo.SchemaMapInfo;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.ChatContext;
|
||||||
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
|
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
|
||||||
import com.tencent.supersonic.chat.api.pojo.request.QueryFilter;
|
import com.tencent.supersonic.chat.api.pojo.request.QueryFilter;
|
||||||
import com.tencent.supersonic.chat.api.pojo.request.QueryFilters;
|
import com.tencent.supersonic.chat.api.pojo.request.QueryFilters;
|
||||||
import com.tencent.supersonic.chat.service.ConfigService;
|
import com.tencent.supersonic.chat.service.ConfigService;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Component("EmbeddingEntityResolver")
|
@Component("EmbeddingEntityResolver")
|
||||||
public class EmbeddingEntityResolver {
|
public class EmbeddingEntityResolver {
|
||||||
|
|
||||||
private ConfigService configService;
|
private ConfigService configService;
|
||||||
|
|
||||||
public EmbeddingEntityResolver(ConfigService configService) {
|
public EmbeddingEntityResolver(ConfigService configService) {
|
||||||
@@ -39,8 +39,8 @@ public class EmbeddingEntityResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
entityId = getEntityValueFromSchemaMapInfo(modelId, queryCtx.getMapInfo(), entityElementId);
|
entityId = getEntityValueFromSchemaMapInfo(modelId, queryCtx.getMapInfo(), entityElementId);
|
||||||
log.info("get entity id:{} from schema map Info :{} ", entityId,
|
log.info("get entity id:{} from schema map Info :{} ",
|
||||||
JSONObject.toJSONString(queryCtx.getMapInfo()));
|
entityId, JSONObject.toJSONString(queryCtx.getMapInfo()));
|
||||||
if (entityId == null || entityId == 0) {
|
if (entityId == null || entityId == 0) {
|
||||||
Long entityIdFromChat = getEntityValueFromParseInfo(chatCtx.getParseInfo(), entityElementId);
|
Long entityIdFromChat = getEntityValueFromParseInfo(chatCtx.getParseInfo(), entityElementId);
|
||||||
if (entityIdFromChat != null && entityIdFromChat > 0) {
|
if (entityIdFromChat != null && entityIdFromChat > 0) {
|
||||||
@@ -95,4 +95,4 @@ public class EmbeddingEntityResolver {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.tencent.supersonic.chat.parser.embedding;
|
package com.tencent.supersonic.chat.parser.plugin.embedding;
|
||||||
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.tencent.supersonic.chat.parser.embedding;
|
package com.tencent.supersonic.chat.parser.plugin.embedding;
|
||||||
|
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.tencent.supersonic.chat.parser.function;
|
package com.tencent.supersonic.chat.parser.plugin.function;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.tencent.supersonic.chat.api.component.SemanticParser;
|
import com.tencent.supersonic.chat.api.component.SemanticParser;
|
||||||
@@ -14,23 +14,21 @@ import com.tencent.supersonic.chat.plugin.PluginManager;
|
|||||||
import com.tencent.supersonic.chat.plugin.PluginParseConfig;
|
import com.tencent.supersonic.chat.plugin.PluginParseConfig;
|
||||||
import com.tencent.supersonic.chat.plugin.PluginParseResult;
|
import com.tencent.supersonic.chat.plugin.PluginParseResult;
|
||||||
import com.tencent.supersonic.chat.query.QueryManager;
|
import com.tencent.supersonic.chat.query.QueryManager;
|
||||||
import com.tencent.supersonic.chat.query.dsl.DSLQuery;
|
|
||||||
import com.tencent.supersonic.chat.query.plugin.PluginSemanticQuery;
|
import com.tencent.supersonic.chat.query.plugin.PluginSemanticQuery;
|
||||||
|
import com.tencent.supersonic.chat.query.llm.dsl.DslQuery;
|
||||||
import com.tencent.supersonic.chat.service.PluginService;
|
import com.tencent.supersonic.chat.service.PluginService;
|
||||||
import com.tencent.supersonic.chat.utils.ComponentFactory;
|
import com.tencent.supersonic.chat.utils.ComponentFactory;
|
||||||
import com.tencent.supersonic.common.pojo.Constants;
|
import com.tencent.supersonic.common.pojo.Constants;
|
||||||
import com.tencent.supersonic.common.util.ContextUtils;
|
import com.tencent.supersonic.common.util.ContextUtils;
|
||||||
import com.tencent.supersonic.common.util.JsonUtil;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import com.tencent.supersonic.common.util.JsonUtil;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
@@ -46,11 +44,6 @@ import org.springframework.web.util.UriComponentsBuilder;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class FunctionBasedParser implements SemanticParser {
|
public class FunctionBasedParser implements SemanticParser {
|
||||||
|
|
||||||
public static final double FUNCTION_BONUS_THRESHOLD = 200;
|
|
||||||
|
|
||||||
public static final double SKIP_DSL_LENGTH = 10;
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void parse(QueryContext queryCtx, ChatContext chatCtx) {
|
public void parse(QueryContext queryCtx, ChatContext chatCtx) {
|
||||||
FunctionCallInfoConfig functionCallConfig = ContextUtils.getBean(FunctionCallInfoConfig.class);
|
FunctionCallInfoConfig functionCallConfig = ContextUtils.getBean(FunctionCallInfoConfig.class);
|
||||||
@@ -62,12 +55,21 @@ public class FunctionBasedParser implements SemanticParser {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
List<PluginParseConfig> functionDOList = getFunctionDO(queryCtx.getRequest().getModelId(), queryCtx);
|
List<PluginParseConfig> functionDOList = getFunctionDO(queryCtx.getRequest().getModelId(), queryCtx);
|
||||||
FunctionReq functionReq = FunctionReq.builder()
|
if (CollectionUtils.isEmpty(functionDOList)) {
|
||||||
.queryText(queryCtx.getRequest().getQueryText())
|
log.info("function call parser, plugin is empty, skip");
|
||||||
.pluginConfigs(functionDOList).build();
|
return;
|
||||||
FunctionResp functionResp = requestFunction(functionUrl, functionReq);
|
}
|
||||||
|
FunctionResp functionResp = new FunctionResp();
|
||||||
|
if (functionDOList.size() == 1) {
|
||||||
|
functionResp.setToolSelection(functionDOList.iterator().next().getName());
|
||||||
|
} else {
|
||||||
|
FunctionReq functionReq = FunctionReq.builder()
|
||||||
|
.queryText(queryCtx.getRequest().getQueryText())
|
||||||
|
.pluginConfigs(functionDOList).build();
|
||||||
|
functionResp = requestFunction(functionUrl, functionReq);
|
||||||
|
}
|
||||||
log.info("requestFunction result:{}", functionResp.getToolSelection());
|
log.info("requestFunction result:{}", functionResp.getToolSelection());
|
||||||
if (skipFunction(queryCtx, functionResp)) {
|
if (skipFunction(functionResp)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PluginParseResult functionCallParseResult = new PluginParseResult();
|
PluginParseResult functionCallParseResult = new PluginParseResult();
|
||||||
@@ -83,10 +85,10 @@ public class FunctionBasedParser implements SemanticParser {
|
|||||||
functionCallParseResult.setPlugin(plugin);
|
functionCallParseResult.setPlugin(plugin);
|
||||||
log.info("QueryManager PluginQueryModes:{}", QueryManager.getPluginQueryModes());
|
log.info("QueryManager PluginQueryModes:{}", QueryManager.getPluginQueryModes());
|
||||||
PluginSemanticQuery semanticQuery = QueryManager.createPluginQuery(toolSelection);
|
PluginSemanticQuery semanticQuery = QueryManager.createPluginQuery(toolSelection);
|
||||||
ModelResolver ModelResolver = ComponentFactory.getModelResolver();
|
ModelResolver modelResolver = ComponentFactory.getModelResolver();
|
||||||
log.info("plugin ModelList:{}", plugin.getModelList());
|
log.info("plugin ModelList:{}", plugin.getModelList());
|
||||||
Pair<Boolean, List<Long>> pluginResolveResult = PluginManager.resolve(plugin, queryCtx);
|
Pair<Boolean, Set<Long>> pluginResolveResult = PluginManager.resolve(plugin, queryCtx);
|
||||||
Long modelId = ModelResolver.resolve(queryCtx, chatCtx, pluginResolveResult.getRight());
|
Long modelId = modelResolver.resolve(queryCtx, chatCtx, pluginResolveResult.getRight());
|
||||||
log.info("FunctionBasedParser modelId:{}", modelId);
|
log.info("FunctionBasedParser modelId:{}", modelId);
|
||||||
if ((Objects.isNull(modelId) || modelId <= 0) && !plugin.isContainsAllModel()) {
|
if ((Objects.isNull(modelId) || modelId <= 0) && !plugin.isContainsAllModel()) {
|
||||||
log.info("Model is null, skip the parse, select tool: {}", toolSelection);
|
log.info("Model is null, skip the parse, select tool: {}", toolSelection);
|
||||||
@@ -102,47 +104,27 @@ public class FunctionBasedParser implements SemanticParser {
|
|||||||
functionCallParseResult.setRequest(queryCtx.getRequest());
|
functionCallParseResult.setRequest(queryCtx.getRequest());
|
||||||
Map<String, Object> properties = new HashMap<>();
|
Map<String, Object> properties = new HashMap<>();
|
||||||
properties.put(Constants.CONTEXT, functionCallParseResult);
|
properties.put(Constants.CONTEXT, functionCallParseResult);
|
||||||
|
properties.put("type", "plugin");
|
||||||
|
properties.put("name", plugin.getName());
|
||||||
parseInfo.setProperties(properties);
|
parseInfo.setProperties(properties);
|
||||||
parseInfo.setScore(FUNCTION_BONUS_THRESHOLD);
|
parseInfo.setScore(queryCtx.getRequest().getQueryText().length());
|
||||||
parseInfo.setQueryMode(semanticQuery.getQueryMode());
|
parseInfo.setQueryMode(semanticQuery.getQueryMode());
|
||||||
SchemaElement Model = new SchemaElement();
|
SchemaElement model = new SchemaElement();
|
||||||
Model.setModel(modelId);
|
model.setModel(modelId);
|
||||||
Model.setId(modelId);
|
model.setId(modelId);
|
||||||
parseInfo.setModel(Model);
|
parseInfo.setModel(model);
|
||||||
queryCtx.getCandidateQueries().add(semanticQuery);
|
queryCtx.getCandidateQueries().add(semanticQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean skipFunction(FunctionResp functionResp) {
|
||||||
private Set<Long> getMatchModels(QueryContext queryCtx) {
|
return Objects.isNull(functionResp) || StringUtils.isBlank(functionResp.getToolSelection());
|
||||||
Set<Long> result = new HashSet<>();
|
|
||||||
Long modelId = queryCtx.getRequest().getModelId();
|
|
||||||
if (Objects.nonNull(modelId) && modelId > 0) {
|
|
||||||
result.add(modelId);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return queryCtx.getMapInfo().getMatchedModels();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean skipFunction(QueryContext queryCtx, FunctionResp functionResp) {
|
|
||||||
if (Objects.isNull(functionResp) || StringUtils.isBlank(functionResp.getToolSelection())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
String queryText = queryCtx.getRequest().getQueryText();
|
|
||||||
|
|
||||||
if (functionResp.getToolSelection().equalsIgnoreCase(DSLQuery.QUERY_MODE)
|
|
||||||
&& queryText.length() < SKIP_DSL_LENGTH) {
|
|
||||||
log.info("queryText length is :{}, less than the threshold :{}, skip dsl.", queryText.length(),
|
|
||||||
SKIP_DSL_LENGTH);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<PluginParseConfig> getFunctionDO(Long modelId, QueryContext queryContext) {
|
private List<PluginParseConfig> getFunctionDO(Long modelId, QueryContext queryContext) {
|
||||||
log.info("user decide Model:{}", modelId);
|
log.info("user decide Model:{}", modelId);
|
||||||
List<Plugin> plugins = PluginManager.getPlugins();
|
List<Plugin> plugins = getPluginList(queryContext);
|
||||||
List<PluginParseConfig> functionDOList = plugins.stream().filter(plugin -> {
|
List<PluginParseConfig> functionDOList = plugins.stream().filter(plugin -> {
|
||||||
if (DSLQuery.QUERY_MODE.equalsIgnoreCase(plugin.getType())) {
|
if (DslQuery.QUERY_MODE.equalsIgnoreCase(plugin.getType())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (plugin.getParseModeConfig() == null) {
|
if (plugin.getParseModeConfig() == null) {
|
||||||
@@ -153,12 +135,12 @@ public class FunctionBasedParser implements SemanticParser {
|
|||||||
if (StringUtils.isBlank(pluginParseConfig.getName())) {
|
if (StringUtils.isBlank(pluginParseConfig.getName())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Pair<Boolean, List<Long>> pluginResolverResult = PluginManager.resolve(plugin, queryContext);
|
Pair<Boolean, Set<Long>> pluginResolverResult = PluginManager.resolve(plugin, queryContext);
|
||||||
log.info("embedding plugin [{}-{}] resolve: {}", plugin.getId(), plugin.getName(), pluginResolverResult);
|
log.info("plugin [{}-{}] resolve: {}", plugin.getId(), plugin.getName(), pluginResolverResult);
|
||||||
if (!pluginResolverResult.getLeft()) {
|
if (!pluginResolverResult.getLeft()) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
List<Long> resolveModel = pluginResolverResult.getRight();
|
Set<Long> resolveModel = pluginResolverResult.getRight();
|
||||||
if (modelId != null && modelId > 0) {
|
if (modelId != null && modelId > 0) {
|
||||||
if (plugin.isContainsAllModel()) {
|
if (plugin.isContainsAllModel()) {
|
||||||
return true;
|
return true;
|
||||||
@@ -172,20 +154,6 @@ public class FunctionBasedParser implements SemanticParser {
|
|||||||
return functionDOList;
|
return functionDOList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> getFunctionNames(Set<Long> matchedModels) {
|
|
||||||
List<Plugin> plugins = PluginManager.getPlugins();
|
|
||||||
Set<String> functionNames = plugins.stream()
|
|
||||||
.filter(entry -> {
|
|
||||||
if (!CollectionUtils.isEmpty(entry.getModelList()) && !CollectionUtils.isEmpty(matchedModels)) {
|
|
||||||
return entry.getModelList().stream().anyMatch(matchedModels::contains);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
).map(Plugin::getName).collect(Collectors.toSet());
|
|
||||||
functionNames.add(DSLQuery.QUERY_MODE);
|
|
||||||
return new ArrayList<>(functionNames);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FunctionResp requestFunction(String url, FunctionReq functionReq) {
|
public FunctionResp requestFunction(String url, FunctionReq functionReq) {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
@@ -205,4 +173,8 @@ public class FunctionBasedParser implements SemanticParser {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected List<Plugin> getPluginList(QueryContext queryContext) {
|
||||||
|
return PluginManager.getPluginAgentCanSupport(queryContext.getRequest().getAgentId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.tencent.supersonic.chat.parser.function;
|
package com.tencent.supersonic.chat.parser.plugin.function;
|
||||||
|
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.tencent.supersonic.chat.parser.function;
|
package com.tencent.supersonic.chat.parser.plugin.function;
|
||||||
|
|
||||||
import com.tencent.supersonic.chat.plugin.PluginParseConfig;
|
import com.tencent.supersonic.chat.plugin.PluginParseConfig;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.tencent.supersonic.chat.parser.function;
|
package com.tencent.supersonic.chat.parser.plugin.function;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@@ -1,38 +1,40 @@
|
|||||||
package com.tencent.supersonic.chat.parser.function;
|
package com.tencent.supersonic.chat.parser.plugin.function;
|
||||||
|
|
||||||
import com.tencent.supersonic.chat.api.component.SemanticQuery;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.ChatContext;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.SchemaMapInfo;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.ChatContext;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
|
import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
|
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaMapInfo;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
|
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
|
||||||
import java.util.HashMap;
|
import com.tencent.supersonic.chat.api.component.SemanticQuery;
|
||||||
import java.util.HashSet;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class HeuristicModelResolver implements ModelResolver {
|
public class HeuristicModelResolver implements ModelResolver {
|
||||||
|
|
||||||
protected static Long selectModelBySchemaElementCount(Map<Long, SemanticQuery> ModelQueryModes,
|
protected static Long selectModelBySchemaElementCount(Map<Long, SemanticQuery> modelQueryModes,
|
||||||
SchemaMapInfo schemaMap) {
|
SchemaMapInfo schemaMap) {
|
||||||
Map<Long, ModelMatchResult> ModelTypeMap = getModelTypeMap(schemaMap);
|
Map<Long, ModelMatchResult> modelTypeMap = getModelTypeMap(schemaMap);
|
||||||
if (ModelTypeMap.size() == 1) {
|
if (modelTypeMap.size() == 1) {
|
||||||
Long ModelSelect = ModelTypeMap.entrySet().stream().collect(Collectors.toList()).get(0).getKey();
|
Long modelSelect = modelTypeMap.entrySet().stream().collect(Collectors.toList()).get(0).getKey();
|
||||||
if (ModelQueryModes.containsKey(ModelSelect)) {
|
if (modelQueryModes.containsKey(modelSelect)) {
|
||||||
log.info("selectModel with only one Model [{}]", ModelSelect);
|
log.info("selectModel with only one Model [{}]", modelSelect);
|
||||||
return ModelSelect;
|
return modelSelect;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Map.Entry<Long, ModelMatchResult> maxModel = ModelTypeMap.entrySet().stream()
|
Map.Entry<Long, ModelMatchResult> maxModel = modelTypeMap.entrySet().stream()
|
||||||
.filter(entry -> ModelQueryModes.containsKey(entry.getKey()))
|
.filter(entry -> modelQueryModes.containsKey(entry.getKey()))
|
||||||
.sorted((o1, o2) -> {
|
.sorted((o1, o2) -> {
|
||||||
int difference = o2.getValue().getCount() - o1.getValue().getCount();
|
int difference = o2.getValue().getCount() - o1.getValue().getCount();
|
||||||
if (difference == 0) {
|
if (difference == 0) {
|
||||||
@@ -54,23 +56,24 @@ public class HeuristicModelResolver implements ModelResolver {
|
|||||||
*
|
*
|
||||||
* @return false will use context Model, true will use other Model , maybe include context Model
|
* @return false will use context Model, true will use other Model , maybe include context Model
|
||||||
*/
|
*/
|
||||||
protected static boolean isAllowSwitch(Map<Long, SemanticQuery> ModelQueryModes, SchemaMapInfo schemaMap,
|
protected static boolean isAllowSwitch(Map<Long, SemanticQuery> modelQueryModes, SchemaMapInfo schemaMap,
|
||||||
ChatContext chatCtx, QueryReq searchCtx, Long modelId, List<Long> restrictiveModels) {
|
ChatContext chatCtx, QueryReq searchCtx,
|
||||||
|
Long modelId, Set<Long> restrictiveModels) {
|
||||||
if (!Objects.nonNull(modelId) || modelId <= 0) {
|
if (!Objects.nonNull(modelId) || modelId <= 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// except content Model, calculate the number of types for each Model, if numbers<=1 will not switch
|
// except content Model, calculate the number of types for each Model, if numbers<=1 will not switch
|
||||||
Map<Long, ModelMatchResult> ModelTypeMap = getModelTypeMap(schemaMap);
|
Map<Long, ModelMatchResult> modelTypeMap = getModelTypeMap(schemaMap);
|
||||||
log.info("isAllowSwitch ModelTypeMap [{}]", ModelTypeMap);
|
log.info("isAllowSwitch ModelTypeMap [{}]", modelTypeMap);
|
||||||
long otherModelTypeNumBigOneCount = ModelTypeMap.entrySet().stream()
|
long otherModelTypeNumBigOneCount = modelTypeMap.entrySet().stream()
|
||||||
.filter(entry -> ModelQueryModes.containsKey(entry.getKey()) && !entry.getKey().equals(modelId))
|
.filter(entry -> modelQueryModes.containsKey(entry.getKey()) && !entry.getKey().equals(modelId))
|
||||||
.filter(entry -> entry.getValue().getCount() > 1).count();
|
.filter(entry -> entry.getValue().getCount() > 1).count();
|
||||||
if (otherModelTypeNumBigOneCount >= 1) {
|
if (otherModelTypeNumBigOneCount >= 1) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// if query text only contain time , will not switch
|
// if query text only contain time , will not switch
|
||||||
if (!CollectionUtils.isEmpty(ModelQueryModes.values())) {
|
if (!CollectionUtils.isEmpty(modelQueryModes.values())) {
|
||||||
for (SemanticQuery semanticQuery : ModelQueryModes.values()) {
|
for (SemanticQuery semanticQuery : modelQueryModes.values()) {
|
||||||
if (semanticQuery == null) {
|
if (semanticQuery == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -104,14 +107,14 @@ public class HeuristicModelResolver implements ModelResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Map<Long, ModelMatchResult> getModelTypeMap(SchemaMapInfo schemaMap) {
|
public static Map<Long, ModelMatchResult> getModelTypeMap(SchemaMapInfo schemaMap) {
|
||||||
Map<Long, ModelMatchResult> ModelCount = new HashMap<>();
|
Map<Long, ModelMatchResult> modelCount = new HashMap<>();
|
||||||
for (Map.Entry<Long, List<SchemaElementMatch>> entry : schemaMap.getModelElementMatches().entrySet()) {
|
for (Map.Entry<Long, List<SchemaElementMatch>> entry : schemaMap.getModelElementMatches().entrySet()) {
|
||||||
List<SchemaElementMatch> schemaElementMatches = schemaMap.getMatchedElements(entry.getKey());
|
List<SchemaElementMatch> schemaElementMatches = schemaMap.getMatchedElements(entry.getKey());
|
||||||
if (schemaElementMatches != null && schemaElementMatches.size() > 0) {
|
if (schemaElementMatches != null && schemaElementMatches.size() > 0) {
|
||||||
if (!ModelCount.containsKey(entry.getKey())) {
|
if (!modelCount.containsKey(entry.getKey())) {
|
||||||
ModelCount.put(entry.getKey(), new ModelMatchResult());
|
modelCount.put(entry.getKey(), new ModelMatchResult());
|
||||||
}
|
}
|
||||||
ModelMatchResult ModelMatchResult = ModelCount.get(entry.getKey());
|
ModelMatchResult modelMatchResult = modelCount.get(entry.getKey());
|
||||||
Set<SchemaElementType> schemaElementTypes = new HashSet<>();
|
Set<SchemaElementType> schemaElementTypes = new HashSet<>();
|
||||||
schemaElementMatches.stream()
|
schemaElementMatches.stream()
|
||||||
.forEach(schemaElementMatch -> schemaElementTypes.add(
|
.forEach(schemaElementMatch -> schemaElementTypes.add(
|
||||||
@@ -121,17 +124,17 @@ public class HeuristicModelResolver implements ModelResolver {
|
|||||||
((int) ((o2.getSimilarity() - o1.getSimilarity()) * 100))
|
((int) ((o2.getSimilarity() - o1.getSimilarity()) * 100))
|
||||||
).findFirst().orElse(null);
|
).findFirst().orElse(null);
|
||||||
if (schemaElementMatchMax != null) {
|
if (schemaElementMatchMax != null) {
|
||||||
ModelMatchResult.setMaxSimilarity(schemaElementMatchMax.getSimilarity());
|
modelMatchResult.setMaxSimilarity(schemaElementMatchMax.getSimilarity());
|
||||||
}
|
}
|
||||||
ModelMatchResult.setCount(schemaElementTypes.size());
|
modelMatchResult.setCount(schemaElementTypes.size());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ModelCount;
|
return modelCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Long resolve(QueryContext queryContext, ChatContext chatCtx, List<Long> restrictiveModels) {
|
public Long resolve(QueryContext queryContext, ChatContext chatCtx, Set<Long> restrictiveModels) {
|
||||||
Long modelId = queryContext.getRequest().getModelId();
|
Long modelId = queryContext.getRequest().getModelId();
|
||||||
if (Objects.nonNull(modelId) && modelId > 0) {
|
if (Objects.nonNull(modelId) && modelId > 0) {
|
||||||
if (CollectionUtils.isNotEmpty(restrictiveModels) && restrictiveModels.contains(modelId)) {
|
if (CollectionUtils.isNotEmpty(restrictiveModels) && restrictiveModels.contains(modelId)) {
|
||||||
@@ -147,41 +150,41 @@ public class HeuristicModelResolver implements ModelResolver {
|
|||||||
.filter(restrictiveModels::contains)
|
.filter(restrictiveModels::contains)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
Map<Long, SemanticQuery> ModelQueryModes = new HashMap<>();
|
Map<Long, SemanticQuery> modelQueryModes = new HashMap<>();
|
||||||
for (Long matchedModel : matchedModels) {
|
for (Long matchedModel : matchedModels) {
|
||||||
ModelQueryModes.put(matchedModel, null);
|
modelQueryModes.put(matchedModel, null);
|
||||||
}
|
}
|
||||||
if (ModelQueryModes.size() == 1) {
|
if (modelQueryModes.size() == 1) {
|
||||||
return ModelQueryModes.keySet().stream().findFirst().get();
|
return modelQueryModes.keySet().stream().findFirst().get();
|
||||||
}
|
}
|
||||||
return resolve(ModelQueryModes, queryContext, chatCtx,
|
return resolve(modelQueryModes, queryContext, chatCtx,
|
||||||
queryContext.getMapInfo(), restrictiveModels);
|
queryContext.getMapInfo(), restrictiveModels);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long resolve(Map<Long, SemanticQuery> ModelQueryModes, QueryContext queryContext,
|
public Long resolve(Map<Long, SemanticQuery> modelQueryModes, QueryContext queryContext,
|
||||||
ChatContext chatCtx, SchemaMapInfo schemaMap, List<Long> restrictiveModels) {
|
ChatContext chatCtx, SchemaMapInfo schemaMap, Set<Long> restrictiveModels) {
|
||||||
Long selectModel = selectModel(ModelQueryModes, queryContext.getRequest(), chatCtx, schemaMap,
|
Long selectModel = selectModel(modelQueryModes, queryContext.getRequest(),
|
||||||
restrictiveModels);
|
chatCtx, schemaMap, restrictiveModels);
|
||||||
if (selectModel > 0) {
|
if (selectModel > 0) {
|
||||||
log.info("selectModel {} ", selectModel);
|
log.info("selectModel {} ", selectModel);
|
||||||
return selectModel;
|
return selectModel;
|
||||||
}
|
}
|
||||||
// get the max SchemaElementType number
|
// get the max SchemaElementType number
|
||||||
return selectModelBySchemaElementCount(ModelQueryModes, schemaMap);
|
return selectModelBySchemaElementCount(modelQueryModes, schemaMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long selectModel(Map<Long, SemanticQuery> ModelQueryModes, QueryReq queryContext,
|
public Long selectModel(Map<Long, SemanticQuery> modelQueryModes, QueryReq queryContext,
|
||||||
ChatContext chatCtx,
|
ChatContext chatCtx,
|
||||||
SchemaMapInfo schemaMap, List<Long> restrictiveModels) {
|
SchemaMapInfo schemaMap, Set<Long> restrictiveModels) {
|
||||||
// if QueryContext has modelId and in ModelQueryModes
|
// if QueryContext has modelId and in ModelQueryModes
|
||||||
if (ModelQueryModes.containsKey(queryContext.getModelId())) {
|
if (modelQueryModes.containsKey(queryContext.getModelId())) {
|
||||||
log.info("selectModel from QueryContext [{}]", queryContext.getModelId());
|
log.info("selectModel from QueryContext [{}]", queryContext.getModelId());
|
||||||
return queryContext.getModelId();
|
return queryContext.getModelId();
|
||||||
}
|
}
|
||||||
// if ChatContext has modelId and in ModelQueryModes
|
// if ChatContext has modelId and in ModelQueryModes
|
||||||
if (chatCtx.getParseInfo().getModelId() > 0) {
|
if (chatCtx.getParseInfo().getModelId() > 0) {
|
||||||
Long modelId = chatCtx.getParseInfo().getModelId();
|
Long modelId = chatCtx.getParseInfo().getModelId();
|
||||||
if (!isAllowSwitch(ModelQueryModes, schemaMap, chatCtx, queryContext, modelId, restrictiveModels)) {
|
if (!isAllowSwitch(modelQueryModes, schemaMap, chatCtx, queryContext, modelId, restrictiveModels)) {
|
||||||
log.info("selectModel from ChatContext [{}]", modelId);
|
log.info("selectModel from ChatContext [{}]", modelId);
|
||||||
return modelId;
|
return modelId;
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.tencent.supersonic.chat.parser.function;
|
package com.tencent.supersonic.chat.parser.plugin.function;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
package com.tencent.supersonic.chat.parser.function;
|
package com.tencent.supersonic.chat.parser.plugin.function;
|
||||||
|
|
||||||
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.ChatContext;
|
import com.tencent.supersonic.chat.api.pojo.ChatContext;
|
||||||
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
||||||
import java.util.List;
|
import java.util.Set;
|
||||||
|
|
||||||
public interface ModelResolver {
|
public interface ModelResolver {
|
||||||
|
|
||||||
Long resolve(QueryContext queryContext, ChatContext chatCtx, List<Long> restrictiveModels);
|
Long resolve(QueryContext queryContext, ChatContext chatCtx, Set<Long> restrictiveModels);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.tencent.supersonic.chat.parser.function;
|
package com.tencent.supersonic.chat.parser.plugin.function;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package com.tencent.supersonic.chat.parser.rule;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.tencent.supersonic.chat.agent.Agent;
|
||||||
|
import com.tencent.supersonic.chat.agent.tool.AgentToolType;
|
||||||
|
import com.tencent.supersonic.chat.agent.tool.RuleQueryTool;
|
||||||
|
import com.tencent.supersonic.chat.api.component.SemanticParser;
|
||||||
|
import com.tencent.supersonic.chat.api.component.SemanticQuery;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.ChatContext;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
||||||
|
import com.tencent.supersonic.chat.service.AgentService;
|
||||||
|
import com.tencent.supersonic.common.util.ContextUtils;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class AgentCheckParser implements SemanticParser {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parse(QueryContext queryContext, ChatContext chatContext) {
|
||||||
|
List<SemanticQuery> queries = queryContext.getCandidateQueries();
|
||||||
|
agentCanSupport(queryContext.getRequest().getAgentId(), queries);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void agentCanSupport(Integer agentId, List<SemanticQuery> queries) {
|
||||||
|
AgentService agentService = ContextUtils.getBean(AgentService.class);
|
||||||
|
Agent agent = agentService.getAgent(agentId);
|
||||||
|
if (agent == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<RuleQueryTool> queryTools = getRuleTools(agentId);
|
||||||
|
if (CollectionUtils.isEmpty(queryTools)) {
|
||||||
|
queries.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log.info("queries resolved:{} {}", agent.getName(),
|
||||||
|
queries.stream().map(SemanticQuery::getQueryMode).collect(Collectors.toList()));
|
||||||
|
queries.removeIf(query -> {
|
||||||
|
for (RuleQueryTool tool : queryTools) {
|
||||||
|
if (!tool.getQueryModes().contains(query.getQueryMode())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (tool.isContainsAllModel() || tool.getModelIds().contains(query.getParseInfo().getModelId())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
log.info("rule queries witch can be supported by agent :{} {}", agent.getName(),
|
||||||
|
queries.stream().map(SemanticQuery::getQueryMode).collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<RuleQueryTool> getRuleTools(Integer agentId) {
|
||||||
|
AgentService agentService = ContextUtils.getBean(AgentService.class);
|
||||||
|
Agent agent = agentService.getAgent(agentId);
|
||||||
|
if (agent == null) {
|
||||||
|
return Lists.newArrayList();
|
||||||
|
}
|
||||||
|
List<String> tools = agent.getTools(AgentToolType.RULE);
|
||||||
|
if (CollectionUtils.isEmpty(tools)) {
|
||||||
|
return Lists.newArrayList();
|
||||||
|
}
|
||||||
|
return tools.stream().map(tool -> JSONObject.parseObject(tool, RuleQueryTool.class))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@ import com.tencent.supersonic.chat.api.component.SemanticQuery;
|
|||||||
import com.tencent.supersonic.chat.api.pojo.ChatContext;
|
import com.tencent.supersonic.chat.api.pojo.ChatContext;
|
||||||
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
||||||
import com.tencent.supersonic.common.pojo.enums.AggregateTypeEnum;
|
import com.tencent.supersonic.common.pojo.enums.AggregateTypeEnum;
|
||||||
|
|
||||||
import java.util.AbstractMap;
|
import java.util.AbstractMap;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -21,6 +22,7 @@ import java.util.regex.Matcher;
|
|||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|||||||
@@ -1,12 +1,5 @@
|
|||||||
package com.tencent.supersonic.chat.parser.rule;
|
package com.tencent.supersonic.chat.parser.rule;
|
||||||
|
|
||||||
import static com.tencent.supersonic.chat.api.pojo.SchemaElementType.DIMENSION;
|
|
||||||
import static com.tencent.supersonic.chat.api.pojo.SchemaElementType.ENTITY;
|
|
||||||
import static com.tencent.supersonic.chat.api.pojo.SchemaElementType.ID;
|
|
||||||
import static com.tencent.supersonic.chat.api.pojo.SchemaElementType.METRIC;
|
|
||||||
import static com.tencent.supersonic.chat.api.pojo.SchemaElementType.MODEL;
|
|
||||||
import static com.tencent.supersonic.chat.api.pojo.SchemaElementType.VALUE;
|
|
||||||
|
|
||||||
import com.tencent.supersonic.chat.api.component.SemanticParser;
|
import com.tencent.supersonic.chat.api.component.SemanticParser;
|
||||||
import com.tencent.supersonic.chat.api.component.SemanticQuery;
|
import com.tencent.supersonic.chat.api.component.SemanticQuery;
|
||||||
import com.tencent.supersonic.chat.api.pojo.ChatContext;
|
import com.tencent.supersonic.chat.api.pojo.ChatContext;
|
||||||
@@ -15,8 +8,8 @@ import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
|
|||||||
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
|
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
|
||||||
import com.tencent.supersonic.chat.query.QueryManager;
|
import com.tencent.supersonic.chat.query.QueryManager;
|
||||||
import com.tencent.supersonic.chat.query.rule.RuleSemanticQuery;
|
import com.tencent.supersonic.chat.query.rule.RuleSemanticQuery;
|
||||||
import com.tencent.supersonic.chat.query.rule.metric.MetricEntityQuery;
|
|
||||||
import com.tencent.supersonic.chat.query.rule.metric.MetricModelQuery;
|
import com.tencent.supersonic.chat.query.rule.metric.MetricModelQuery;
|
||||||
|
import com.tencent.supersonic.chat.query.rule.metric.MetricEntityQuery;
|
||||||
import com.tencent.supersonic.chat.query.rule.metric.MetricSemanticQuery;
|
import com.tencent.supersonic.chat.query.rule.metric.MetricSemanticQuery;
|
||||||
import java.util.AbstractMap;
|
import java.util.AbstractMap;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -28,6 +21,13 @@ import java.util.stream.Collectors;
|
|||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import static com.tencent.supersonic.chat.api.pojo.SchemaElementType.METRIC;
|
||||||
|
import static com.tencent.supersonic.chat.api.pojo.SchemaElementType.DIMENSION;
|
||||||
|
import static com.tencent.supersonic.chat.api.pojo.SchemaElementType.VALUE;
|
||||||
|
import static com.tencent.supersonic.chat.api.pojo.SchemaElementType.ENTITY;
|
||||||
|
import static com.tencent.supersonic.chat.api.pojo.SchemaElementType.MODEL;
|
||||||
|
import static com.tencent.supersonic.chat.api.pojo.SchemaElementType.ID;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class ContextInheritParser implements SemanticParser {
|
public class ContextInheritParser implements SemanticParser {
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package com.tencent.supersonic.chat.parser.rule;
|
package com.tencent.supersonic.chat.parser.rule;
|
||||||
|
|
||||||
import com.tencent.supersonic.chat.api.component.SemanticParser;
|
import com.tencent.supersonic.chat.api.component.SemanticParser;
|
||||||
import com.tencent.supersonic.chat.api.pojo.ChatContext;
|
|
||||||
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
|
import com.tencent.supersonic.chat.api.pojo.ChatContext;
|
||||||
import com.tencent.supersonic.chat.api.pojo.SchemaMapInfo;
|
import com.tencent.supersonic.chat.api.pojo.SchemaMapInfo;
|
||||||
|
import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
|
||||||
import com.tencent.supersonic.chat.query.rule.RuleSemanticQuery;
|
import com.tencent.supersonic.chat.query.rule.RuleSemanticQuery;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -15,12 +15,10 @@ public class QueryModeParser implements SemanticParser {
|
|||||||
@Override
|
@Override
|
||||||
public void parse(QueryContext queryContext, ChatContext chatContext) {
|
public void parse(QueryContext queryContext, ChatContext chatContext) {
|
||||||
SchemaMapInfo mapInfo = queryContext.getMapInfo();
|
SchemaMapInfo mapInfo = queryContext.getMapInfo();
|
||||||
|
|
||||||
// iterate all schemaElementMatches to resolve semantic query
|
// iterate all schemaElementMatches to resolve semantic query
|
||||||
for (Long modelId : mapInfo.getMatchedModels()) {
|
for (Long modelId : mapInfo.getMatchedModels()) {
|
||||||
List<SchemaElementMatch> elementMatches = mapInfo.getMatchedElements(modelId);
|
List<SchemaElementMatch> elementMatches = mapInfo.getMatchedElements(modelId);
|
||||||
List<RuleSemanticQuery> queries = RuleSemanticQuery.resolve(elementMatches, queryContext);
|
List<RuleSemanticQuery> queries = RuleSemanticQuery.resolve(elementMatches, queryContext);
|
||||||
|
|
||||||
for (RuleSemanticQuery query : queries) {
|
for (RuleSemanticQuery query : queries) {
|
||||||
query.fillParseInfo(modelId, queryContext, chatContext);
|
query.fillParseInfo(modelId, queryContext, chatContext);
|
||||||
queryContext.getCandidateQueries().add(query);
|
queryContext.getCandidateQueries().add(query);
|
||||||
|
|||||||
@@ -4,21 +4,23 @@ import com.tencent.supersonic.chat.api.component.SemanticParser;
|
|||||||
import com.tencent.supersonic.chat.api.component.SemanticQuery;
|
import com.tencent.supersonic.chat.api.component.SemanticQuery;
|
||||||
import com.tencent.supersonic.chat.api.pojo.ChatContext;
|
import com.tencent.supersonic.chat.api.pojo.ChatContext;
|
||||||
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
||||||
import com.tencent.supersonic.chat.query.QueryManager;
|
|
||||||
import com.tencent.supersonic.chat.query.rule.RuleSemanticQuery;
|
import com.tencent.supersonic.chat.query.rule.RuleSemanticQuery;
|
||||||
|
import com.tencent.supersonic.chat.query.QueryManager;
|
||||||
import com.tencent.supersonic.common.pojo.Constants;
|
import com.tencent.supersonic.common.pojo.Constants;
|
||||||
import com.tencent.supersonic.common.pojo.DateConf;
|
import com.tencent.supersonic.common.pojo.DateConf;
|
||||||
import com.xkzhangsan.time.nlp.TimeNLP;
|
|
||||||
import com.xkzhangsan.time.nlp.TimeNLPUtil;
|
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
import java.util.Stack;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Stack;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import com.xkzhangsan.time.nlp.TimeNLP;
|
||||||
|
import com.xkzhangsan.time.nlp.TimeNLPUtil;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.logging.log4j.util.Strings;
|
import org.apache.logging.log4j.util.Strings;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,206 @@
|
|||||||
|
package com.tencent.supersonic.chat.persistence.dataobject;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class AgentDO {
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 0 offline, 1 online
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
private String examples;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
private String config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
private String createdBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
private Date createdAt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
private String updatedBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
private Date updatedAt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
private Integer enableSearch;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return id
|
||||||
|
*/
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return name
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
*/
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name == null ? null : name.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return description
|
||||||
|
*/
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param description
|
||||||
|
*/
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description == null ? null : description.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 0 offline, 1 online
|
||||||
|
* @return status 0 offline, 1 online
|
||||||
|
*/
|
||||||
|
public Integer getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 0 offline, 1 online
|
||||||
|
* @param status 0 offline, 1 online
|
||||||
|
*/
|
||||||
|
public void setStatus(Integer status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return examples
|
||||||
|
*/
|
||||||
|
public String getExamples() {
|
||||||
|
return examples;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param examples
|
||||||
|
*/
|
||||||
|
public void setExamples(String examples) {
|
||||||
|
this.examples = examples == null ? null : examples.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return config
|
||||||
|
*/
|
||||||
|
public String getConfig() {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param config
|
||||||
|
*/
|
||||||
|
public void setConfig(String config) {
|
||||||
|
this.config = config == null ? null : config.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return created_by
|
||||||
|
*/
|
||||||
|
public String getCreatedBy() {
|
||||||
|
return createdBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param createdBy
|
||||||
|
*/
|
||||||
|
public void setCreatedBy(String createdBy) {
|
||||||
|
this.createdBy = createdBy == null ? null : createdBy.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return created_at
|
||||||
|
*/
|
||||||
|
public Date getCreatedAt() {
|
||||||
|
return createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param createdAt
|
||||||
|
*/
|
||||||
|
public void setCreatedAt(Date createdAt) {
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return updated_by
|
||||||
|
*/
|
||||||
|
public String getUpdatedBy() {
|
||||||
|
return updatedBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param updatedBy
|
||||||
|
*/
|
||||||
|
public void setUpdatedBy(String updatedBy) {
|
||||||
|
this.updatedBy = updatedBy == null ? null : updatedBy.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return updated_at
|
||||||
|
*/
|
||||||
|
public Date getUpdatedAt() {
|
||||||
|
return updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param updatedAt
|
||||||
|
*/
|
||||||
|
public void setUpdatedAt(Date updatedAt) {
|
||||||
|
this.updatedAt = updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return enable_search
|
||||||
|
*/
|
||||||
|
public Integer getEnableSearch() {
|
||||||
|
return enableSearch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param enableSearch
|
||||||
|
*/
|
||||||
|
public void setEnableSearch(Integer enableSearch) {
|
||||||
|
this.enableSearch = enableSearch;
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,142 @@
|
|||||||
|
package com.tencent.supersonic.chat.persistence.dataobject;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
|
||||||
|
public class ChatParseDO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* questionId
|
||||||
|
*/
|
||||||
|
private Long questionId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* chatId
|
||||||
|
*/
|
||||||
|
private Long chatId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* parseId
|
||||||
|
*/
|
||||||
|
private Integer parseId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* createTime
|
||||||
|
*/
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* queryText
|
||||||
|
*/
|
||||||
|
private String queryText;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* userName
|
||||||
|
*/
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* parseInfo
|
||||||
|
*/
|
||||||
|
private String parseInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* isCandidate
|
||||||
|
*/
|
||||||
|
private Integer isCandidate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return question_id
|
||||||
|
*/
|
||||||
|
public Long getQuestionId() {
|
||||||
|
return questionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* questionId
|
||||||
|
*/
|
||||||
|
public void setQuestionId(Long questionId) {
|
||||||
|
this.questionId = questionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return create_time
|
||||||
|
*/
|
||||||
|
public Date getCreateTime() {
|
||||||
|
return createTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* createTime
|
||||||
|
*/
|
||||||
|
public void setCreateTime(Date createTime) {
|
||||||
|
this.createTime = createTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return user_name
|
||||||
|
*/
|
||||||
|
public String getUserName() {
|
||||||
|
return userName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* userName
|
||||||
|
*/
|
||||||
|
public void setUserName(String userName) {
|
||||||
|
this.userName = userName == null ? null : userName.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return chat_id
|
||||||
|
*/
|
||||||
|
public Long getChatId() {
|
||||||
|
return chatId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* chatId
|
||||||
|
*/
|
||||||
|
public void setChatId(Long chatId) {
|
||||||
|
this.chatId = chatId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return query_text
|
||||||
|
*/
|
||||||
|
public String getQueryText() {
|
||||||
|
return queryText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* queryText
|
||||||
|
*/
|
||||||
|
public void setQueryText(String queryText) {
|
||||||
|
this.queryText = queryText == null ? null : queryText.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getIsCandidate() {
|
||||||
|
return isCandidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getParseId() {
|
||||||
|
return parseId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getParseInfo() {
|
||||||
|
return parseInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParseId(Integer parseId) {
|
||||||
|
this.parseId = parseId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsCandidate(Integer isCandidate) {
|
||||||
|
this.isCandidate = isCandidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParseInfo(String parseInfo) {
|
||||||
|
this.parseInfo = parseInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,177 +2,196 @@ package com.tencent.supersonic.chat.persistence.dataobject;
|
|||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
|
||||||
public class ChatQueryDO {
|
public class ChatQueryDO {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* questionId
|
|
||||||
*/
|
*/
|
||||||
private Long questionId;
|
private Long questionId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* createTime
|
*/
|
||||||
|
private Integer agentId;
|
||||||
|
|
||||||
|
/**
|
||||||
*/
|
*/
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* userName
|
|
||||||
*/
|
*/
|
||||||
private String userName;
|
private String userName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* queryState
|
|
||||||
*/
|
*/
|
||||||
private Integer queryState;
|
private Integer queryState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* chatId
|
|
||||||
*/
|
*/
|
||||||
private Long chatId;
|
private Long chatId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* score
|
|
||||||
*/
|
*/
|
||||||
private Integer score;
|
private Integer score;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* feedback
|
|
||||||
*/
|
*/
|
||||||
private String feedback;
|
private String feedback;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* queryText
|
|
||||||
*/
|
*/
|
||||||
private String queryText;
|
private String queryText;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* queryResponse
|
|
||||||
*/
|
*/
|
||||||
private String queryResult;
|
private String queryResult;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return question_id
|
* @return question_id
|
||||||
*/
|
*/
|
||||||
public Long getQuestionId() {
|
public Long getQuestionId() {
|
||||||
return questionId;
|
return questionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* questionId
|
* @param questionId
|
||||||
*/
|
*/
|
||||||
public void setQuestionId(Long questionId) {
|
public void setQuestionId(Long questionId) {
|
||||||
this.questionId = questionId;
|
this.questionId = questionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return create_time
|
* @return agent_id
|
||||||
|
*/
|
||||||
|
public Integer getAgentId() {
|
||||||
|
return agentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param agentId
|
||||||
|
*/
|
||||||
|
public void setAgentId(Integer agentId) {
|
||||||
|
this.agentId = agentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return create_time
|
||||||
*/
|
*/
|
||||||
public Date getCreateTime() {
|
public Date getCreateTime() {
|
||||||
return createTime;
|
return createTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* createTime
|
* @param createTime
|
||||||
*/
|
*/
|
||||||
public void setCreateTime(Date createTime) {
|
public void setCreateTime(Date createTime) {
|
||||||
this.createTime = createTime;
|
this.createTime = createTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return user_name
|
* @return user_name
|
||||||
*/
|
*/
|
||||||
public String getUserName() {
|
public String getUserName() {
|
||||||
return userName;
|
return userName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* userName
|
* @param userName
|
||||||
*/
|
*/
|
||||||
public void setUserName(String userName) {
|
public void setUserName(String userName) {
|
||||||
this.userName = userName == null ? null : userName.trim();
|
this.userName = userName == null ? null : userName.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return query_state
|
*
|
||||||
|
* @return query_state
|
||||||
*/
|
*/
|
||||||
public Integer getQueryState() {
|
public Integer getQueryState() {
|
||||||
return queryState;
|
return queryState;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* queryState
|
*
|
||||||
|
* @param queryState
|
||||||
*/
|
*/
|
||||||
public void setQueryState(Integer queryState) {
|
public void setQueryState(Integer queryState) {
|
||||||
this.queryState = queryState;
|
this.queryState = queryState;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return chat_id
|
*
|
||||||
|
* @return chat_id
|
||||||
*/
|
*/
|
||||||
public Long getChatId() {
|
public Long getChatId() {
|
||||||
return chatId;
|
return chatId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* chatId
|
*
|
||||||
|
* @param chatId
|
||||||
*/
|
*/
|
||||||
public void setChatId(Long chatId) {
|
public void setChatId(Long chatId) {
|
||||||
this.chatId = chatId;
|
this.chatId = chatId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return score
|
*
|
||||||
|
* @return score
|
||||||
*/
|
*/
|
||||||
public Integer getScore() {
|
public Integer getScore() {
|
||||||
return score;
|
return score;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* score
|
*
|
||||||
|
* @param score
|
||||||
*/
|
*/
|
||||||
public void setScore(Integer score) {
|
public void setScore(Integer score) {
|
||||||
this.score = score;
|
this.score = score;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return feedback
|
*
|
||||||
|
* @return feedback
|
||||||
*/
|
*/
|
||||||
public String getFeedback() {
|
public String getFeedback() {
|
||||||
return feedback;
|
return feedback;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* feedback
|
*
|
||||||
|
* @param feedback
|
||||||
*/
|
*/
|
||||||
public void setFeedback(String feedback) {
|
public void setFeedback(String feedback) {
|
||||||
this.feedback = feedback == null ? null : feedback.trim();
|
this.feedback = feedback == null ? null : feedback.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return query_text
|
*
|
||||||
|
* @return query_text
|
||||||
*/
|
*/
|
||||||
public String getQueryText() {
|
public String getQueryText() {
|
||||||
return queryText;
|
return queryText;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* queryText
|
*
|
||||||
|
* @param queryText
|
||||||
*/
|
*/
|
||||||
public void setQueryText(String queryText) {
|
public void setQueryText(String queryText) {
|
||||||
this.queryText = queryText == null ? null : queryText.trim();
|
this.queryText = queryText == null ? null : queryText.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return query_response
|
*
|
||||||
|
* @return query_result
|
||||||
*/
|
*/
|
||||||
public String getQueryResult() {
|
public String getQueryResult() {
|
||||||
return queryResult;
|
return queryResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* queryResponse
|
*
|
||||||
|
* @param queryResult
|
||||||
*/
|
*/
|
||||||
public void setQueryResult(String queryResult) {
|
public void setQueryResult(String queryResult) {
|
||||||
this.queryResult = queryResult == null ? null : queryResult.trim();
|
this.queryResult = queryResult == null ? null : queryResult.trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,47 +5,92 @@ import java.util.Date;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ChatQueryDOExample {
|
public class ChatQueryDOExample {
|
||||||
|
/**
|
||||||
|
* s2_chat_query
|
||||||
|
*/
|
||||||
protected String orderByClause;
|
protected String orderByClause;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* s2_chat_query
|
||||||
|
*/
|
||||||
protected boolean distinct;
|
protected boolean distinct;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* s2_chat_query
|
||||||
|
*/
|
||||||
protected List<Criteria> oredCriteria;
|
protected List<Criteria> oredCriteria;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* s2_chat_query
|
||||||
|
*/
|
||||||
protected Integer limitStart;
|
protected Integer limitStart;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* s2_chat_query
|
||||||
|
*/
|
||||||
protected Integer limitEnd;
|
protected Integer limitEnd;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @mbg.generated
|
||||||
|
*/
|
||||||
public ChatQueryDOExample() {
|
public ChatQueryDOExample() {
|
||||||
oredCriteria = new ArrayList<Criteria>();
|
oredCriteria = new ArrayList<Criteria>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getOrderByClause() {
|
/**
|
||||||
return orderByClause;
|
* @mbg.generated
|
||||||
}
|
*/
|
||||||
|
|
||||||
public void setOrderByClause(String orderByClause) {
|
public void setOrderByClause(String orderByClause) {
|
||||||
this.orderByClause = orderByClause;
|
this.orderByClause = orderByClause;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDistinct() {
|
/**
|
||||||
return distinct;
|
* @mbg.generated
|
||||||
|
*/
|
||||||
|
public String getOrderByClause() {
|
||||||
|
return orderByClause;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @mbg.generated
|
||||||
|
*/
|
||||||
public void setDistinct(boolean distinct) {
|
public void setDistinct(boolean distinct) {
|
||||||
this.distinct = distinct;
|
this.distinct = distinct;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @mbg.generated
|
||||||
|
*/
|
||||||
|
public boolean isDistinct() {
|
||||||
|
return distinct;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @mbg.generated
|
||||||
|
*/
|
||||||
public List<Criteria> getOredCriteria() {
|
public List<Criteria> getOredCriteria() {
|
||||||
return oredCriteria;
|
return oredCriteria;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @mbg.generated
|
||||||
|
*/
|
||||||
public void or(Criteria criteria) {
|
public void or(Criteria criteria) {
|
||||||
oredCriteria.add(criteria);
|
oredCriteria.add(criteria);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @mbg.generated
|
||||||
|
*/
|
||||||
public Criteria or() {
|
public Criteria or() {
|
||||||
Criteria criteria = createCriteriaInternal();
|
Criteria criteria = createCriteriaInternal();
|
||||||
oredCriteria.add(criteria);
|
oredCriteria.add(criteria);
|
||||||
return criteria;
|
return criteria;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @mbg.generated
|
||||||
|
*/
|
||||||
public Criteria createCriteria() {
|
public Criteria createCriteria() {
|
||||||
Criteria criteria = createCriteriaInternal();
|
Criteria criteria = createCriteriaInternal();
|
||||||
if (oredCriteria.size() == 0) {
|
if (oredCriteria.size() == 0) {
|
||||||
@@ -54,35 +99,55 @@ public class ChatQueryDOExample {
|
|||||||
return criteria;
|
return criteria;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @mbg.generated
|
||||||
|
*/
|
||||||
protected Criteria createCriteriaInternal() {
|
protected Criteria createCriteriaInternal() {
|
||||||
Criteria criteria = new Criteria();
|
Criteria criteria = new Criteria();
|
||||||
return criteria;
|
return criteria;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @mbg.generated
|
||||||
|
*/
|
||||||
public void clear() {
|
public void clear() {
|
||||||
oredCriteria.clear();
|
oredCriteria.clear();
|
||||||
orderByClause = null;
|
orderByClause = null;
|
||||||
distinct = false;
|
distinct = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getLimitStart() {
|
/**
|
||||||
return limitStart;
|
* @mbg.generated
|
||||||
}
|
*/
|
||||||
|
|
||||||
public void setLimitStart(Integer limitStart) {
|
public void setLimitStart(Integer limitStart) {
|
||||||
this.limitStart = limitStart;
|
this.limitStart = limitStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getLimitEnd() {
|
/**
|
||||||
return limitEnd;
|
* @mbg.generated
|
||||||
|
*/
|
||||||
|
public Integer getLimitStart() {
|
||||||
|
return limitStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @mbg.generated
|
||||||
|
*/
|
||||||
public void setLimitEnd(Integer limitEnd) {
|
public void setLimitEnd(Integer limitEnd) {
|
||||||
this.limitEnd = limitEnd;
|
this.limitEnd = limitEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract static class GeneratedCriteria {
|
/**
|
||||||
|
* @mbg.generated
|
||||||
|
*/
|
||||||
|
public Integer getLimitEnd() {
|
||||||
|
return limitEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* s2_chat_query null
|
||||||
|
*/
|
||||||
|
protected abstract static class GeneratedCriteria {
|
||||||
protected List<Criterion> criteria;
|
protected List<Criterion> criteria;
|
||||||
|
|
||||||
protected GeneratedCriteria() {
|
protected GeneratedCriteria() {
|
||||||
@@ -183,6 +248,66 @@ public class ChatQueryDOExample {
|
|||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Criteria andAgentIdIsNull() {
|
||||||
|
addCriterion("agent_id is null");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andAgentIdIsNotNull() {
|
||||||
|
addCriterion("agent_id is not null");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andAgentIdEqualTo(Integer value) {
|
||||||
|
addCriterion("agent_id =", value, "agentId");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andAgentIdNotEqualTo(Integer value) {
|
||||||
|
addCriterion("agent_id <>", value, "agentId");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andAgentIdGreaterThan(Integer value) {
|
||||||
|
addCriterion("agent_id >", value, "agentId");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andAgentIdGreaterThanOrEqualTo(Integer value) {
|
||||||
|
addCriterion("agent_id >=", value, "agentId");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andAgentIdLessThan(Integer value) {
|
||||||
|
addCriterion("agent_id <", value, "agentId");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andAgentIdLessThanOrEqualTo(Integer value) {
|
||||||
|
addCriterion("agent_id <=", value, "agentId");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andAgentIdIn(List<Integer> values) {
|
||||||
|
addCriterion("agent_id in", values, "agentId");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andAgentIdNotIn(List<Integer> values) {
|
||||||
|
addCriterion("agent_id not in", values, "agentId");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andAgentIdBetween(Integer value1, Integer value2) {
|
||||||
|
addCriterion("agent_id between", value1, value2, "agentId");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andAgentIdNotBetween(Integer value1, Integer value2) {
|
||||||
|
addCriterion("agent_id not between", value1, value2, "agentId");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
public Criteria andCreateTimeIsNull() {
|
public Criteria andCreateTimeIsNull() {
|
||||||
addCriterion("create_time is null");
|
addCriterion("create_time is null");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
@@ -564,6 +689,9 @@ public class ChatQueryDOExample {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* s2_chat_query
|
||||||
|
*/
|
||||||
public static class Criteria extends GeneratedCriteria {
|
public static class Criteria extends GeneratedCriteria {
|
||||||
|
|
||||||
protected Criteria() {
|
protected Criteria() {
|
||||||
@@ -571,8 +699,10 @@ public class ChatQueryDOExample {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* s2_chat_query null
|
||||||
|
*/
|
||||||
public static class Criterion {
|
public static class Criterion {
|
||||||
|
|
||||||
private String condition;
|
private String condition;
|
||||||
|
|
||||||
private Object value;
|
private Object value;
|
||||||
@@ -657,4 +787,4 @@ public class ChatQueryDOExample {
|
|||||||
return typeHandler;
|
return typeHandler;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.tencent.supersonic.chat.persistence.dataobject;
|
||||||
|
|
||||||
|
public enum CostType {
|
||||||
|
MAPPER(1, "mapper"),
|
||||||
|
PARSER(2, "parser"),
|
||||||
|
QUERY(3, "query");
|
||||||
|
|
||||||
|
private Integer type;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
CostType(Integer type, String name) {
|
||||||
|
this.type = type;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -254,4 +254,4 @@ public class PluginDO {
|
|||||||
public void setComment(String comment) {
|
public void setComment(String comment) {
|
||||||
this.comment = comment == null ? null : comment.trim();
|
this.comment = comment == null ? null : comment.trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -892,38 +892,6 @@ public class PluginDOExample {
|
|||||||
|
|
||||||
private String typeHandler;
|
private String typeHandler;
|
||||||
|
|
||||||
public String getCondition() {
|
|
||||||
return condition;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getSecondValue() {
|
|
||||||
return secondValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isNoValue() {
|
|
||||||
return noValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSingleValue() {
|
|
||||||
return singleValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isBetweenValue() {
|
|
||||||
return betweenValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isListValue() {
|
|
||||||
return listValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTypeHandler() {
|
|
||||||
return typeHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Criterion(String condition) {
|
protected Criterion(String condition) {
|
||||||
super();
|
super();
|
||||||
this.condition = condition;
|
this.condition = condition;
|
||||||
@@ -959,5 +927,37 @@ public class PluginDOExample {
|
|||||||
protected Criterion(String condition, Object value, Object secondValue) {
|
protected Criterion(String condition, Object value, Object secondValue) {
|
||||||
this(condition, value, secondValue, null);
|
this(condition, value, secondValue, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getCondition() {
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getSecondValue() {
|
||||||
|
return secondValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNoValue() {
|
||||||
|
return noValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSingleValue() {
|
||||||
|
return singleValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBetweenValue() {
|
||||||
|
return betweenValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isListValue() {
|
||||||
|
return listValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTypeHandler() {
|
||||||
|
return typeHandler;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package com.tencent.supersonic.chat.persistence.dataobject;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class StatisticsDO {
|
||||||
|
/**
|
||||||
|
* questionId
|
||||||
|
*/
|
||||||
|
private Long questionId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* chatId
|
||||||
|
*/
|
||||||
|
private Long chatId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* createTime
|
||||||
|
*/
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* queryText
|
||||||
|
*/
|
||||||
|
private String queryText;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* userName
|
||||||
|
*/
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* interface
|
||||||
|
*/
|
||||||
|
private String interfaceName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cost
|
||||||
|
*/
|
||||||
|
private Integer cost;
|
||||||
|
|
||||||
|
private Integer type;
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package com.tencent.supersonic.chat.persistence.mapper;
|
||||||
|
|
||||||
|
import com.tencent.supersonic.chat.persistence.dataobject.AgentDO;
|
||||||
|
import com.tencent.supersonic.chat.persistence.dataobject.AgentDOExample;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface AgentDOMapper {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @mbg.generated
|
||||||
|
*/
|
||||||
|
long countByExample(AgentDOExample example);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @mbg.generated
|
||||||
|
*/
|
||||||
|
int deleteByPrimaryKey(Integer id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @mbg.generated
|
||||||
|
*/
|
||||||
|
int insert(AgentDO record);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @mbg.generated
|
||||||
|
*/
|
||||||
|
int insertSelective(AgentDO record);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @mbg.generated
|
||||||
|
*/
|
||||||
|
List<AgentDO> selectByExample(AgentDOExample example);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @mbg.generated
|
||||||
|
*/
|
||||||
|
AgentDO selectByPrimaryKey(Integer id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @mbg.generated
|
||||||
|
*/
|
||||||
|
int updateByExampleSelective(@Param("record") AgentDO record, @Param("example") AgentDOExample example);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @mbg.generated
|
||||||
|
*/
|
||||||
|
int updateByExample(@Param("record") AgentDO record, @Param("example") AgentDOExample example);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @mbg.generated
|
||||||
|
*/
|
||||||
|
int updateByPrimaryKeySelective(AgentDO record);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @mbg.generated
|
||||||
|
*/
|
||||||
|
int updateByPrimaryKey(AgentDO record);
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.tencent.supersonic.chat.persistence.mapper;
|
||||||
|
|
||||||
|
import com.tencent.supersonic.chat.persistence.dataobject.ChatParseDO;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface ChatParseMapper {
|
||||||
|
|
||||||
|
boolean batchSaveParseInfo(@Param("list") List<ChatParseDO> list);
|
||||||
|
|
||||||
|
ChatParseDO getParseInfo(Long questionId, String userName, int parseId);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -14,4 +14,5 @@ public interface ChatQueryDOMapper {
|
|||||||
|
|
||||||
int updateByPrimaryKeyWithBLOBs(ChatQueryDO record);
|
int updateByPrimaryKeyWithBLOBs(ChatQueryDO record);
|
||||||
|
|
||||||
|
Boolean deleteByPrimaryKey(Long questionId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.tencent.supersonic.chat.persistence.mapper;
|
||||||
|
|
||||||
|
import com.tencent.supersonic.chat.persistence.dataobject.StatisticsDO;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface StatisticsMapper {
|
||||||
|
boolean batchSaveStatistics(@Param("list") List<StatisticsDO> list);
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user