128 Commits

Author SHA1 Message Date
Willy-J
47c2595fb8 (fix)(headless) preserve model join order by using LinkedHashSet in probeRelatedModels (#2299)
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-07-09 17:22:44 +08:00
wangyong
9bddd4457e fixed bug 2281 (#2309) 2025-07-09 17:22:04 +08:00
wangyong
55ac3d1aa5 (fix)(headless-server)sqlExecuteReq.getSql() 兼容sql前后有换行符CASE,导致sql语句结尾";"无法被正确删除 (#2327) 2025-07-09 17:21:33 +08:00
andybj0228
0427917624 (fix)(headless) DictUtils.constructQuerySqlReq针对sql query增加别名 (#2320) 2025-07-09 17:21:16 +08:00
木鱼和尚
d8fe2ed2b3 Dimension and metric retrieval and percentage display issue fixes (#2301) 2025-07-09 17:20:49 +08:00
FredTsang
11d1264d38 (fix)(chat-sdk): Export data based on queryColumns (#2297) 2025-07-09 17:19:16 +08:00
FredTsang
32675387d7 (fix)(chat-sdk) rm table defaultSortOrder (#2295) 2025-07-09 17:18:45 +08:00
mroldx
e408204690 Update sql-update-mysql.sql (#2293) 2025-07-09 17:18:08 +08:00
wangyong
269f146c11 (fix)(headless-server)语意建模-X模型-维度管理-维度搜索带key查询时,返回的维度结果范围超出了X模型范围 (#2328)
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-07-07 17:19:59 +08:00
jerryjzhang
6f497b142e [fix][chat]Memory deletion should disable it first.
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-07-02 18:59:56 +08:00
jerryjzhang
79a44b27ee [fix][heaadless]Fix NPE issues.
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-06-28 08:51:04 +08:00
jerryjzhang
76cc5ee111 [opt][heaadless]Add user field to QueryStatement for consistency.
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-06-27 19:46:00 +08:00
jerryjzhang
320fcf04bd [fix][heaadless]bizName of ModelResp is not necessarily equal to table name.
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-06-25 23:14:16 +08:00
jerryjzhang
75fc83010c [fix][heaadless]Fix dim value replacement. 2025-06-25 22:22:12 +08:00
superhero
37673c82da Merge pull request #2303 from Willy-J/fixbug2
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
(fix)(headless) add empty check for metric alias to prevent incorrect DataFormatType assignment
2025-06-23 17:31:03 +08:00
superhero
3ae0d645a7 Merge pull request #2307 from guilinlewis/lewis-pr
(improvement)(common|headless|chat|auth) 鉴权优化与召回优化
2025-06-23 17:29:21 +08:00
superhero
256a6bcb3f Merge pull request #2306 from 1985312383/master
(improvement)(headless | chat | launchers | webapp) Added assistant function! Call LLM to optimize SQL code performance before final SQL execution
2025-06-23 17:25:43 +08:00
guilinlewis
1faf84e372 (improvement)(common|headless|chat|auth) 鉴权优化与召回优化
1 修复生成的用户token 一生成就失效的问题
2 如果用户设置的token ,需校验是否数据库存在,因为用户可设置一年的token 有泄露风险
3 结果解析优化, 去除不可以解析的情况,解析问题需要改写后的问,
4 召回样例,用相似度,保住至少有一个样例是高相似度的
5 数据集召回,填加完全匹配格式筛选逻辑
2025-06-23 10:03:17 +08:00
guilinlewis
7e6639df83 (improvement)(common|headless|chat|auth) 鉴权优化与召回优化
1 修复生成的用户token 一生成就失效的问题
2 如果用户设置的token ,需校验是否数据库存在,因为用户可设置一年的token 有泄露风险
3 结果解析优化, 去除不可以解析的情况,解析问题需要改写后的问,
4 召回样例,用相似度,保住至少有一个样例是高相似度的
5 数据集召回,填加完全匹配格式筛选逻辑
2025-06-23 09:47:48 +08:00
柯慕灵
075ae4c0af Merge branch 'master' of https://github.com/1985312383/supersonic 2025-06-21 05:19:52 +08:00
柯慕灵
08133ccbfb Update LLMPhysicalSqlCorrector.java
修正为合适的prompt
2025-06-21 05:19:42 +08:00
柯慕灵
164d2a9e23 update supersonic-build.bat
增加路径创建时的判断,增加环境检测,修正打包的路径问题,与supersonic-daemen.bat 命令,符合文档中的运行方式
2025-06-21 05:00:54 +08:00
柯慕灵
f899d23b63 add new chat corrector
在助理最终执行物理SQL前,加入一步LLM优化性能功能
2025-06-21 04:57:04 +08:00
柯慕灵
944beddafc Merge branch 'tencentmusic:master' into master 2025-06-21 04:50:36 +08:00
Willy-J
019d737f07 (fix)(headless) add empty check for metric alias to prevent incorrect DataFormatType assignment 2025-06-18 15:03:40 +08:00
supersonicbi
0721df2e66 (fix)(headless)Add null handling to avoid NPEs.
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-06-15 19:15:25 +08:00
Willy-J
303392f492 (fix)(headless) use database name as catalog when catalog is empty (#2291)
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-06-12 13:56:22 +08:00
柯慕灵
e5a41765b4 fix windows daemon.bat path configuration (#2289)
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-06-11 10:29:13 +08:00
柯慕灵
87355533b4 fix windows daemon.bat path configuration 2025-06-11 09:20:09 +08:00
FredTsang
06fb6ba744 (feat)(chat-sdk) Optimize ChatMsg chart conditions (#2286)
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-06-08 07:35:19 +08:00
FredTsang
9ffdba956e (feat)(chat-sdk) extract formatByDataFormatType() (#2287)
* feat(Chat/constants.ts): rm unused code

* feat(chat-sdk): extract formatByDataFormatType()
2025-06-08 07:34:51 +08:00
supersonicbi
df70a3cf15 (fix)(headless)Empty filters should not give prompt info.
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-06-06 21:07:17 +08:00
FredTsang
2552e2ae4b (bug)(webapp) support negative number (#2284)
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-06-03 20:34:19 +08:00
wanglongqiang
4bfa10ba7c Update DataModelNode.java (#2279) 2025-05-29 22:12:41 +08:00
superhero
958aca945d Merge pull request #2282 from feelshana/develop_0.0.1
(fix)(common)记忆管理中更新sql,启用->待定,待定->启用向量库不更新
2025-05-29 18:24:24 +08:00
feelshana
fae9118c28 (feature)(chat)agent记忆管理启用的few-shot优先,避免shffle过程的随机性导致被全局的few-shot替代 2025-05-29 17:21:00 +08:00
feelshana
c24ba59bb5 (fix)(common)记忆管理中更新sql,启用->待定,待定->启用向量库不更新 2025-05-29 16:57:38 +08:00
guilinlewis
90c4f66770 (bug)(webapp) (#2278)
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
添加判空条件,防止上下文为空的情况
2025-05-27 14:42:07 +08:00
guilinlewis
b9dd6bb7c5 (improvement)(headless | chat |webapp) (#2266)
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
1  在使用多轮对话改写时,内容上面的问题,替换成改写的内容,可以让用户知道该回答原来什么问题
2  解决表格内容太长导致显示的问题
3  框架的字典都是以_开头的, 添加判断,如果配置了非 _ 开头的字典而引起的报错
4  大模型分析结果时,因为textResult 是必填的参数,所以如果发现 textResult 未null 就不做分析了
2025-05-26 21:25:43 +08:00
WDEP
dff64b62f4 (fix)(chat)Fixed level 2 drilldown dimension error (#2276) 2025-05-26 21:19:31 +08:00
supersonicbi
8eeed87bac (feature)(headless)Add oracle engine type and db adaptor.
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-05-26 10:36:29 +08:00
supersonicbi
e171bdd97f (fix)(headless)Fix showType determination and date field setting in metric query.
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
(fix)(headless)Fix showType determination and date field setting in metric query.
2025-05-24 16:08:05 +08:00
wanglongqiang
0709575cd9 when sql script has variables, generate sql can't be executed, this commit supports variable replement (#2259)
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-05-20 22:35:28 +08:00
QJ_wonder
be0447ae15 修复headless中字段查询及多轮对话使用问题 (#2252)
* (fix)(headless)修复生成的SQL字段不在数据集内,导致查询异常的问题,由原来的字段数量判断更改为查询字段是否包含维度和度量字段

* (fix)(headless) <修复开启多轮对话会使用默认的gpt-4o-mini账号去进行过程检测而不是使用配置好的本地大模型的问题>

* 修复维度值导入字典时,维度值和度量值为英文名导致字段不匹配的问题

修复维度值导入字典时,维度值和度量值为英文名导致字段不匹配的问题。
维度值导入字典时会遍历调用到SqlQueryParser方法,这时的维度值或度量值为Bizname而非name,新增一个set用于添加Bizname,并在判断中新加入Bizname名的判断,只要两个条件符合一个即可

---------

Co-authored-by: unknown <qiji2@DC=corp,DC=conbagroup,DC=com.com>
Co-authored-by: QJ_wonder <38885395+xinpiannanhai@users.noreply.github.com>
2025-05-20 22:34:54 +08:00
WDEP
1b8cd7f0d3 (fix)(chat-sdk)Fix the pie chart display conditions (#2255) 2025-05-20 22:26:13 +08:00
WDEP
2fd82cc259 (fix)(supersonic-fe)Fix the issue of field display in model construction (#2254) 2025-05-20 22:25:25 +08:00
jerryjzhang
00814a3807 [fix][heaadless]Avoid duplicate semantic fields in modelDetail.
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-05-17 16:43:15 +08:00
supersonicbi
08705c9d3b (improvement)(chat)Remove unused DO objects.
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
(improvement)(chat)Remove unused DO objects.
2025-05-11 09:38:31 +08:00
supersonicbi
1c9cf788cb (feature)(auth)Support deletion of user. 2025-05-07 14:11:01 +08:00
supersonicbi
1ab5d9c7e6 (improvement)(chat)Default s2.parser.field.count.threshold set to 0.
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-05-06 15:56:50 +08:00
supersonicbi
2b13866c0b (improvement)(common)Support more date string formats. 2025-05-06 15:56:03 +08:00
supersonicbi
e812884802 (fix)(chat)Chat only should return queries with empty query result. 2025-05-06 09:53:07 +08:00
supersonicbi
e2ae7e21ad (improvement)(common)Remove unused chat model parameters.
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-05-05 19:42:29 +08:00
beat4ocean
3fc1ec42be [Improvement][headless] Implement Generational ZGC (#2236)
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-05-05 15:51:49 +08:00
beat4ocean
c4992501bd [Improvement][headless] Only expose OPEN_AI/OLLAMA/DIFY chat model providers. (#2237) 2025-05-05 15:51:26 +08:00
beat4ocean
acffc03c79 [Improvement][headless] Replace deprecated LangChain4j APIs (#2235) 2025-05-05 15:47:51 +08:00
WDEP
763def2de0 dev_add_show-pie (#2241)
Great, thanks!
2025-05-05 15:47:18 +08:00
WDEP
d0a67af684 fix_show-markdown (#2243) 2025-05-05 15:46:32 +08:00
supersonicbi
be8b56bdde (improvement)(common)Only expose OPEN_AI/OLLAMA/DIFY chat model providers.
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-04-27 12:59:23 +08:00
supersonicbi
9f2c0c7699 (improvement)(headless)Add default jdbc URL for typical database types. 2025-04-27 12:58:36 +08:00
supersonicbi
c1fa9d7442 (improvement)(headless)Support ordering in chat model and database tables. 2025-04-27 12:57:25 +08:00
superhero
0d5da763b3 Merge pull request #2234 from beat4ocean/master
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
[Fix][headless-fe] Error when copying access token
2025-04-27 09:42:42 +08:00
beat4ocean
d1b4863a27 [Fix][headless-fe] Error when copying access token 2025-04-26 10:31:26 +08:00
supersonicbi
dce9a8a58c (fix)(chat)Fix NPE in getParseInfo.
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-04-25 20:41:04 +08:00
jerryjzhang
fbf048cb00 (fix)(headless)Fix show type and retrieve issues.
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-04-21 14:41:31 +08:00
jerryjzhang
48a8f69cca [fix][heaadless]Use columnName as fieldName.
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-04-15 21:25:04 +08:00
jerryjzhang
ecdf65da3e (fix)(headless)Fix bizName and name NPE issue.
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-04-14 21:09:37 +08:00
poncheen
5585b9e222 Fix/ts errors in fe (#2218)
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-04-11 20:58:35 +08:00
Antgeek
97710a90c4 (improve)(benchmark) improve benchmark, add analysis of parsing results (#2215)
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-04-10 08:57:25 +08:00
jerryjzhang
0ab7643299 [fix][heaadless]Optimize logic of determine number types.
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-04-10 00:25:56 +08:00
Antgeek
d2aa73b85e (fix)(headless) fix ModelCreateForm.tsx error (#2214)
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-04-08 20:49:37 +08:00
chixiaopao
8828964e53 (fix)(headless) fix dfs NullPointerException when model is null. (#2212)
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-04-07 20:55:41 +08:00
beat4ocean
b188da8595 [Fix] cannot save schema-mapping and semantic-S2SQL modification. (#2210)
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-04-07 08:57:06 +08:00
jerryjzhang
2e7ba468c9 (fix)(chat)Return chat id when creating new one.
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-04-05 18:43:16 +08:00
naimehao
d26c9180ed fix headless-core (#2208)
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-04-04 08:19:20 +08:00
Antgeek
ca96aa725d (fix)(headless) method getProperties maybe cause NullPointerException (#2202)
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-04-02 17:48:41 +08:00
kino
614917ba76 [Improvement] Reduce Docker image size #2204 (#2205) 2025-04-02 17:26:19 +08:00
jerryjzhang
1fed8ca4d9 (fix)(headless)Fix hash code issue of MetricSchemaResp and DimensionSchemaResp.
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-03-30 07:20:07 +08:00
beat4ocean
232a202275 [Improvement] Upgrade dependencies and fix vulnerabilities. (#2190)
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-03-28 09:07:49 +08:00
jerryjzhang
791c493a6a Merge remote-tracking branch 'origin/master'
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-03-28 01:19:01 +08:00
jerryjzhang
f9d4ce2128 [fix][auth]Fix last_login of user not being selected. 2025-03-28 01:18:48 +08:00
coosir
8abfc923a0 (fix)(supersonic-fe) support needMultiply100 for bar chart to show correct percentage value (#2189)
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-03-26 10:11:52 +08:00
beat4ocean
e6598a79bb [Fix] Fix MetricServiceImpl and PromptHelper NPE issue (#2191)
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-03-25 13:34:35 +08:00
jerryjzhang
d2a43a99c8 (feature)(headless)Support offset clause in struct query.
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-03-23 14:30:56 +08:00
iridescentpeo
db8f340e2d 修复同一模型被多个数据集引用时: (#2183) 2025-03-23 14:14:08 +08:00
Kun Gu
2e81b190a4 将utf8的编码修改为utf8mb4,解决部分因为字符出现的BUG (#2182)
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-03-21 22:54:34 +08:00
guilinlewis
81cd60d2da fix-common-因缓存无法存记忆 (#2181) 2025-03-21 22:30:38 +08:00
jerryjzhang
3ffc8c3d9e (improvement)(headless)Make rule-based corrector switchable. 2025-03-21 22:10:41 +08:00
jerryjzhang
18db24c011 (fix)(headless)Fix issue of dimension value not replaced by alias. #2074 2025-03-21 21:49:47 +08:00
Hwting
cd698ac367 Update docker-compose.yml (#2184) 2025-03-21 21:38:29 +08:00
jerryjzhang
58b640b087 (fix)(headless)Fix issue of dimension value not replaced by alias. 2025-03-21 21:33:40 +08:00
jerryjzhang
1f28aaeaed (feature)(auth)Add last_login field to User. 2025-03-21 20:58:59 +08:00
jerryjzhang
35b835172b (fix)(headless)Updating dimension should update modelDetail as well.
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-03-19 10:05:04 +08:00
jerryjzhang
1c85bcecc5 Merge remote-tracking branch 'origin/master'
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-03-14 23:11:51 +08:00
jerryjzhang
c3483ae340 (fix)(assembly)Increase minimum heap size to avoid not enough space issue. 2025-03-14 23:11:44 +08:00
williamhliu
a5051c7225 (improvement)(supersonic-fe) remove listColumnsBySql (#2173)
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-03-14 08:51:37 +08:00
jerryjzhang
12f6cfa42d (fix)(headless)Metric filters do not take effect in struct query.
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-03-13 18:53:13 +08:00
jerryjzhang
4c94f2b816 Merge remote-tracking branch 'origin/master' 2025-03-13 18:52:39 +08:00
jerryjzhang
c81aa5859d (improvement)(headless)Add unit test case for variable if statement. 2025-03-13 18:52:30 +08:00
guilinlewis
21e213fb19 (improvement)(headless | chat ) 向量数据被重置后,记忆不会再次添加到向量数据库 (#2164)
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-03-12 22:19:51 +08:00
jerryjzhang
f67bf3eeac (fix)(chat)Fix bug in creating chat model. 2025-03-12 16:47:40 +08:00
jerryjzhang
9d13038599 (fix)(headless)Fix schema corrector in that aliases should not be replaced. 2025-03-12 16:31:43 +08:00
beat4ocean
0c8c2d4804 [fix][headless] Fix issue filterSql is not working. (#2157)
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-03-12 13:53:08 +08:00
williamhliu
f05a4b523c (fix)(supersonic-fe) show tip when register failed and replace icon when login failed and fix metric style issue (#2160) 2025-03-12 08:22:46 +08:00
jerryjzhang
b7369abcca [improvement][docker]Facilitate database configuration when running with docker.
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-03-11 23:14:40 +08:00
jerryjzhang
b40cb13740 (fix)(chat)Should check permission when returning data set tree.
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-03-11 15:32:12 +08:00
williamhliu
6f8cf9853b (fix)(supersonic-fe) fix the issue where there is no prompt when saving the dataset (#2154)
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-03-11 10:36:03 +08:00
williamhliu
75906037ac (fix)(supersonic-fe) fix the issue where there is no prompt when saving the dataset (#2152) 2025-03-11 09:19:22 +08:00
jerryjzhang
b58e041e8d [improvement][chat]Adopt accept pattern to parsers and executors.
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-03-11 00:27:06 +08:00
jerryjzhang
93d585c0d5 [feature][common]Add permission management to chat model. 2025-03-10 23:58:19 +08:00
jerryjzhang
0dbf56d357 [fix][chat]Fix query time cost bug. 2025-03-10 23:21:07 +08:00
zyclove
a3293e6788 fix:java.lang.NullPointerException: Cannot invoke "com.tencent.supersonic.common.pojo.DateConf.getDateField()" because "dateConf" is null (#2142)
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-03-09 13:44:07 +08:00
jerryjzhang
a99f5985f5 (improvement)(headless)Set fields of model detail when restoring model.
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-03-09 10:58:49 +08:00
jerryjzhang
91243005bc (fix)(launcher)Change join_condition to type text to avoid "value too long for column". 2025-03-09 09:18:29 +08:00
jerryjzhang
a76b5a4300 (improvement)(headless)Add unit to measure. 2025-03-09 09:15:13 +08:00
jerryjzhang
c1f9df963c (improvement)(headless)Add expr to semantic column. 2025-03-09 08:31:48 +08:00
Shaofeng Shi
954aa4eea5 fix: https://github.com/tencentmusic/supersonic/issues/2132 for Trino syntax (#2144)
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-03-08 21:41:35 +08:00
jerryjzhang
33bd0de604 (improvement)(headless)Set fields of model detail when creating model. 2025-03-08 21:16:10 +08:00
jerryjzhang
881d891d70 (license)Update communication email address.
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-03-06 09:31:51 +08:00
jerryjzhang
d9db455dab (improvement)(headless)Optimize compatibility and robustness in ontology query translation.
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-03-05 20:47:57 +08:00
jerryjzhang
e0dc3fbf1a (improvement)(headless)Optimize compatibility and robustness in ontology query translation.
(improvement)(headless)Optimize compatibility and robustness in ontology query translation.
2025-03-05 17:11:59 +08:00
zyclove
efddf4cacf fix: https://github.com/tencentmusic/supersonic/issues/2132 (#2137) 2025-03-05 14:54:16 +08:00
jerryjzhang
732222ab98 (fix)(headless)Fix database permission check.
(fix)(headless)Fix database permission check.
2025-03-05 14:39:53 +08:00
jerryjzhang
5b994c4f8f (fix)(github)Upgrade actions/cache from 2 to 4. 2025-03-05 12:51:15 +08:00
Dack Wang
5d2ebdf680 (fix)(README) 404 docs link (#2133) 2025-03-05 12:36:56 +08:00
coosir
f1bc18ef65 Update docker-compose.yml (#2127)
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
fix data persistence issue
2025-03-05 08:36:04 +08:00
jerryjzhang
8f361f9932 (improvement)(auth)Use interface in place of impl class.
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-03-04 17:56:41 +08:00
jerryjzhang
f532088e38 (feature)(releaes)Start 1.0.0-SNAPSHOT release.
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-03-04 10:11:00 +08:00
253 changed files with 3044 additions and 2507 deletions

View File

@@ -11,7 +11,7 @@ jobs:
build:
runs-on: ubuntu-latest
container:
image: quay.io/centos/centos:stream8 # 使用 CentOS Stream 8 容器
image: almalinux:9 # maven >=3.6.3
strategy:
matrix:
@@ -28,9 +28,10 @@ jobs:
- name: Reset DNF repositories
run: |
cd /etc/yum.repos.d/
sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
sed -e 's|^mirrorlist=|#mirrorlist=|g' \
-e 's|^# baseurl=https://repo.almalinux.org|baseurl=https://mirrors.aliyun.com|g' \
/etc/yum.repos.d/almalinux*.repo
- name: Update DNF package index
run: dnf makecache
@@ -47,7 +48,7 @@ jobs:
mvn -version
- name: Cache Maven packages
uses: actions/cache@v2
uses: actions/cache@v4
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}

View File

@@ -17,21 +17,27 @@ jobs:
java-version: [21] # Define the JDK versions to test
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up JDK ${{ matrix.java-version }}
uses: actions/setup-java@v2
uses: actions/setup-java@v3
with:
java-version: ${{ matrix.java-version }}
distribution: 'adopt'
distribution: 'temurin'
- name: Cache Maven packages
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: ~/Library/Caches/Maven # macOS Maven cache path
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Install system dependencies
run: |
brew update
brew install cmake
brew install gcc
- name: Build with Maven
run: mvn -B package --file pom.xml

View File

@@ -26,7 +26,7 @@ jobs:
distribution: 'adopt'
- name: Cache Maven packages
uses: actions/cache@v2
uses: actions/cache@v4
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}

View File

@@ -26,7 +26,7 @@ jobs:
distribution: 'adopt' # You might need to change this if 'adopt' doesn't support JDK 21
- name: Cache Maven packages
uses: actions/cache@v2
uses: actions/cache@v4
with:
path: ~\.m2 # Windows uses a backslash for paths
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}

3
.gitignore vendored
View File

@@ -20,4 +20,5 @@ chm_db/
__pycache__/
/dict
assembly/build/*-SNAPSHOT
**/node_modules/
**/node_modules/
benchmark/res/

View File

@@ -14,7 +14,7 @@ code and logo.
b. a commercial license must be obtained from the author if you want to develop and distribute a derivative work based
on SuperSonic.
Please contact zhangjun2915@163.com by email to inquire about licensing matters.
Please contact supersonicbi@qq.com by email to inquire about licensing matters.
2. As a contributor, you should agree that:

View File

@@ -75,7 +75,7 @@ SuperSonic comes with sample semantic models as well as chat conversations that
## Build and Development
Please refer to project [Docs](https://supersonicbi.github.io/docs/%E7%B3%BB%E7%BB%9F%E9%83%A8%E7%BD%B2/%E7%BC%96%E8%AF%91%E6%9E%84%E5%BB%BA/).
Please refer to project [Docs](https://supersonicbi.github.io/docs/%E7%B3%BB%E7%BB%9F%E9%83%A8%E7%BD%B2/%E6%BA%90%E7%A0%81%E7%BC%96%E8%AF%91%E9%83%A8%E7%BD%B2/).
## WeChat Contact

View File

@@ -75,7 +75,7 @@ SuperSonic自带样例的语义模型和问答对话只需以下三步即可
## 如何构建和部署
请参考项目[文档](https://supersonicbi.github.io/docs/%E7%B3%BB%E7%BB%9F%E9%83%A8%E7%BD%B2/%E7%BC%96%E8%AF%91%E6%9E%84%E5%BB%BA/)。
请参考项目[文档](https://supersonicbi.github.io/docs/%E7%B3%BB%E7%BB%9F%E9%83%A8%E7%BD%B2/%E6%BA%90%E7%A0%81%E7%BC%96%E8%AF%91%E9%83%A8%E7%BD%B2/)。
## 微信联系方式

View File

@@ -71,7 +71,7 @@ SuperSonicには、サンプルのセマンティックモデルとチャット
## ビルドと開発
プロジェクト[ドキュメント](https://supersonicbi.github.io/docs/%E7%B3%BB%E7%BB%9F%E9%83%A8%E7%BD%B2/%E7%BC%96%E8%AF%91%E6%9E%84%E5%BB%BA/)を参照してください。
プロジェクト[ドキュメント](https://supersonicbi.github.io/docs/%E7%B3%BB%E7%BB%9F%E9%83%A8%E7%BD%B2/%E6%BA%90%E7%A0%81%E7%BC%96%E8%AF%91%E9%83%A8%E7%BD%B2/)を参照してください。
## WeChat連絡先

View File

@@ -43,10 +43,26 @@ if "%service%"=="webapp" (
call mvn -f %projectDir% clean package -DskipTests -Dspotless.skip=true
IF ERRORLEVEL 1 (
ECHO Failed to build backend Java modules.
ECHO Please check Maven and Java versions are compatible.
ECHO Current Java: %JAVA_HOME%
ECHO Current Maven: %MAVEN_HOME%
EXIT /B 1
)
REM extract and copy files to deployment directory
cd %projectDir%\launchers\%model_name%\target
if exist "launchers-%model_name%-%MVN_VERSION%-bin.tar.gz" (
echo "Extracting launchers-%model_name%-%MVN_VERSION%-bin.tar.gz..."
tar -xf "launchers-%model_name%-%MVN_VERSION%-bin.tar.gz"
if exist "launchers-%model_name%-%MVN_VERSION%" (
echo "Copying files to deployment directory..."
xcopy /E /Y "launchers-%model_name%-%MVN_VERSION%\*" "%buildDir%\supersonic-%model_name%-%MVN_VERSION%\"
)
)
copy /y %projectDir%\launchers\%model_name%\target\*.tar.gz %buildDir%\
echo "finished building supersonic-%model_name% service"
cd %baseDir%
goto :EOF
@@ -72,22 +88,55 @@ if "%service%"=="webapp" (
cd %buildDir%
if exist %release_dir% rmdir /s /q %release_dir%
if exist %release_dir%.zip del %release_dir%.zip
mkdir %release_dir%
rem package webapp
tar xvf supersonic-webapp.tar.gz
move /y supersonic-webapp webapp
echo {"env": ""} > webapp\supersonic.config.json
move /y webapp %release_dir%
rem package java service
tar xvf %service_name%-bin.tar.gz
for /d %%D in ("%service_name%\*") do (
move "%%D" "%release_dir%"
rem check if release directory already exists from buildJavaService
if exist %release_dir% (
echo "Release directory already prepared by buildJavaService"
) else (
mkdir %release_dir%
rem package java service
tar xvf %service_name%-bin.tar.gz 2>nul
if errorlevel 1 (
echo "Warning: tar command failed, trying PowerShell extraction..."
powershell -Command "Expand-Archive -Path '%service_name%-bin.tar.gz' -DestinationPath '.' -Force"
)
for /d %%D in ("%service_name%\*") do (
move "%%D" "%release_dir%"
)
rmdir /s /q %service_name% 2>nul
)
rem package webapp
if exist supersonic-webapp.tar.gz (
tar xvf supersonic-webapp.tar.gz 2>nul
if errorlevel 1 (
echo "Warning: tar command failed, trying PowerShell extraction..."
powershell -Command "Expand-Archive -Path 'supersonic-webapp.tar.gz' -DestinationPath '.' -Force"
)
move /y supersonic-webapp webapp
echo {"env": ""} > webapp\supersonic.config.json
move /y webapp %release_dir%
del supersonic-webapp.tar.gz 2>nul
)
rem verify deployment structure
if exist "%release_dir%\lib\launchers-%model_name%-%MVN_VERSION%.jar" (
echo "Deployment structure verified successfully"
) else (
echo "Warning: Main jar file not found in deployment structure"
echo "Expected: %release_dir%\lib\launchers-%model_name%-%MVN_VERSION%.jar"
)
rem generate zip file
powershell Compress-Archive -Path %release_dir% -DestinationPath %release_dir%.zip
del %service_name%-bin.tar.gz
del supersonic-webapp.tar.gz
rmdir /s /q %service_name%
powershell -Command "Compress-Archive -Path '%release_dir%' -DestinationPath '%release_dir%.zip' -Force"
if errorlevel 1 (
echo "Warning: PowerShell compression failed, release directory still available: %release_dir%"
) else (
echo "Successfully created release package: %release_dir%.zip"
)
del %service_name%-bin.tar.gz 2>nul
echo "finished packaging supersonic release"
goto :EOF

View File

@@ -20,7 +20,9 @@ if "%profile%"=="" (
set "model_name=%service%"
cd %baseDir%
REM fix path configuration - point to the correct release package directory
set "releaseDir=%buildDir%\supersonic-%service%-1.0.0-SNAPSHOT"
cd %releaseDir%
if "%command%"=="restart" (
call :stop
@@ -50,20 +52,58 @@ if "%command%"=="restart" (
:runJavaService
echo 'java service starting, see logs in logs/'
set "libDir=%baseDir%\lib"
set "confDir=%baseDir%\conf"
set "webDir=%baseDir%\webapp"
set "logDir=%baseDir%\logs"
set "classpath=%baseDir%;%webDir%;%libDir%\*;%confDir%"
set "property=-Dfile.encoding=UTF-8 -Duser.language=Zh -Duser.region=CN -Duser.timezone=GMT+08 -Dspring.profiles.active=%profile%"
set "java-command=%property% -Xms1024m -Xmx1024m -cp %CLASSPATH% %MAIN_CLASS%"
echo 'Using release directory: %releaseDir%'
REM use release package directory as base path
set "libDir=%releaseDir%\lib"
set "confDir=%releaseDir%\conf"
set "webDir=%releaseDir%\webapp"
set "logDir=%releaseDir%\logs"
REM fix variable name matching problem
set "CLASSPATH=%releaseDir%;%webDir%;%libDir%\*;%confDir%"
set "MAIN_CLASS=%main_class%"
REM add port configuration
set "property=-Dfile.encoding=UTF-8 -Duser.language=Zh -Duser.region=CN -Duser.timezone=GMT+08 -Dspring.profiles.active=%profile% -Dserver.port=9080"
set "java_command=%property% -Xms1024m -Xmx2048m -cp "%CLASSPATH%" %MAIN_CLASS%"
if not exist %logDir% mkdir %logDir%
start /B java %java-command% >nul 2>&1
timeout /t 10 >nul
REM check if the main jar file exists
if not exist "%libDir%\launchers-standalone-1.0.0-SNAPSHOT.jar" (
echo "Error: Main jar file not found in %libDir%"
echo "Please make sure the application has been built and packaged correctly."
goto :EOF
)
echo 'Main Class: %MAIN_CLASS%'
echo 'Profile: %profile%'
echo 'Starting Java service...'
REM start service and save logs
start /B java %java_command% > "%logDir%\supersonic.log" 2>&1
timeout /t 15 >nul
REM check service status
netstat -an | findstr ":9080" >nul
if errorlevel 1 (
echo "Warning: Port 9080 is not listening"
echo "Please check the log file: %logDir%\supersonic.log"
if exist "%logDir%\supersonic.log" (
echo "Recent log entries:"
powershell -Command "Get-Content '%logDir%\supersonic.log' | Select-Object -Last 10"
)
) else (
echo "Service started successfully on port 9080"
echo "You can access the application at: http://localhost:9080"
)
echo 'java service started'
goto :EOF
:stopJavaService
echo 'Stopping Java service...'
for /f "tokens=2" %%i in ('tasklist ^| findstr /i "java"') do (
taskkill /PID %%i /F
echo "java service (PID = %%i) is killed."

View File

@@ -60,7 +60,8 @@ function runJavaService {
JAVA_HOME=$(ls /usr/jdk64/jdk* -d 2>/dev/null | xargs | awk '{print "'$local_app_name'"}')
fi
export PATH=$JAVA_HOME/bin:$PATH
command="-Dfile.encoding=UTF-8 -Duser.language=Zh -Duser.region=CN -Duser.timezone=GMT+08 -Dapp_name=${local_app_name} -Xms1024m -Xmx1024m $main_class"
command="-Dfile.encoding=UTF-8 -Duser.language=Zh -Duser.region=CN -Duser.timezone=GMT+08
-Dapp_name=${local_app_name} -Xms1024m -Xmx2048m -XX:+UseZGC -XX:+ZGenerational $main_class"
mkdir -p $javaRunDir/logs
java -Dspring.profiles.active="$profile" $command >/dev/null 2>$javaRunDir/logs/error.log &

View File

@@ -0,0 +1,5 @@
#!/usr/bin/env sh
export SUPERSONIC_VERSION=latest
docker-compose -f docker-compose.yml -p supersonic up

View File

@@ -0,0 +1,23 @@
#!/usr/bin/env sh
export SUPERSONIC_VERSION=latest
#### Set below DB configs to connect to your own database
# Supported DB_TYPE: h2, mysql, postgres
export S2_DB_TYPE=h2
export S2_DB_HOST=
export S2_DB_PORT=
export S2_DB_USER=
export S2_DB_PASSWORD=
export S2_DB_DATABASE=
docker run --rm -it -d \
--name supersonic_standalone \
-p 9080:9080 \
-e S2_DB_TYPE=${S2_DB_TYPE} \
-e S2_DB_HOST=${S2_DB_HOST} \
-e S2_DB_PORT=${S2_DB_PORT} \
-e S2_DB_USER=${S2_DB_USER} \
-e S2_DB_PASSWORD=${S2_DB_PASSWORD} \
-e S2_DB_DATABASE=${S2_DB_DATABASE} \
supersonicbi/supersonic:${SUPERSONIC_VERSION}

View File

@@ -1,10 +1,11 @@
#!/usr/bin/env bash
#### Set below DB configs to connect to your own database
# Comment out below exports to config your DB connection
# Supported DB_TYPE: h2, mysql, postgres
export S2_DB_TYPE=h2
export S2_DB_HOST=
export S2_DB_PORT=
export S2_DB_USER=
export S2_DB_PASSWORD=
export S2_DB_DATABASE=
#export S2_DB_TYPE=h2
#export S2_DB_HOST=
#export S2_DB_PORT=
#export S2_DB_USER=
#export S2_DB_PASSWORD=
#export S2_DB_DATABASE=

View File

@@ -34,8 +34,8 @@
</dependencies>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
</properties>
</project>

View File

@@ -21,6 +21,8 @@ public interface UserAdaptor {
void register(UserReq userReq);
void deleteUser(long userId);
String login(UserReq userReq, HttpServletRequest request);
String login(UserReq userReq, String appKey);

View File

@@ -24,7 +24,7 @@ public class UserWithPassword extends User {
public UserWithPassword(Long id, String name, String displayName, String email, String password,
Integer isAdmin) {
super(id, name, displayName, email, isAdmin);
super(id, name, displayName, email, isAdmin, null);
this.password = password;
}

View File

@@ -23,6 +23,8 @@ public interface UserService {
void register(UserReq userCmd);
void deleteUser(long userId);
String login(UserReq userCmd, HttpServletRequest request);
String login(UserReq userCmd, String appKey);

View File

@@ -18,6 +18,8 @@ import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.Set;
@@ -90,6 +92,12 @@ public class DefaultUserAdaptor implements UserAdaptor {
userRepository.addUser(userDO);
}
@Override
public void deleteUser(long userId) {
UserRepository userRepository = ContextUtils.getBean(UserRepository.class);
userRepository.deleteUser(userId);
}
@Override
public String login(UserReq userReq, HttpServletRequest request) {
TokenService tokenService = ContextUtils.getBean(TokenService.class);
@@ -102,7 +110,9 @@ public class DefaultUserAdaptor implements UserAdaptor {
TokenService tokenService = ContextUtils.getBean(TokenService.class);
try {
UserWithPassword user = getUserWithPassword(userReq);
return tokenService.generateToken(UserWithPassword.convert(user), appKey);
String token = tokenService.generateToken(UserWithPassword.convert(user), appKey);
updateLastLogin(userReq.getName());
return token;
} catch (Exception e) {
log.error("", e);
throw new RuntimeException("password encrypt error, please try again");
@@ -213,8 +223,9 @@ public class DefaultUserAdaptor implements UserAdaptor {
new UserWithPassword(userDO.getId(), userDO.getName(), userDO.getDisplayName(),
userDO.getEmail(), userDO.getPassword(), userDO.getIsAdmin());
String token =
tokenService.generateToken(UserWithPassword.convert(userWithPassword), expireTime);
// 使用令牌名称作为生成key 这样可以区分正常请求和api 请求api 的令牌失效时间很长,需考虑令牌泄露的情况
String token = tokenService.generateToken(UserWithPassword.convert(userWithPassword),
"SysDbToken:" + name, (new Date().getTime() + expireTime));
UserTokenDO userTokenDO = saveUserToken(name, userName, token, expireTime);
return convertUserToken(userTokenDO);
}
@@ -267,4 +278,11 @@ public class DefaultUserAdaptor implements UserAdaptor {
userToken.setExpireDate(userTokenDO.getExpireDateTime());
return userToken;
}
private void updateLastLogin(String userName) {
UserRepository userRepository = ContextUtils.getBean(UserRepository.class);
UserDO userDO = userRepository.getUser(userName);
userDO.setLastLogin(new Timestamp(System.currentTimeMillis()));
userRepository.updateUser(userDO);
}
}

View File

@@ -1,7 +1,7 @@
package com.tencent.supersonic.auth.authentication.interceptor;
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
import com.tencent.supersonic.auth.authentication.service.UserServiceImpl;
import com.tencent.supersonic.auth.api.authentication.service.UserService;
import com.tencent.supersonic.auth.authentication.utils.TokenService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
@@ -16,7 +16,7 @@ public abstract class AuthenticationInterceptor implements HandlerInterceptor {
protected AuthenticationConfig authenticationConfig;
protected UserServiceImpl userServiceImpl;
protected UserService userService;
protected TokenService tokenService;

View File

@@ -3,7 +3,7 @@ package com.tencent.supersonic.auth.authentication.interceptor;
import com.tencent.supersonic.auth.api.authentication.annotation.AuthenticationIgnore;
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
import com.tencent.supersonic.auth.api.authentication.pojo.UserWithPassword;
import com.tencent.supersonic.auth.authentication.service.UserServiceImpl;
import com.tencent.supersonic.auth.api.authentication.service.UserService;
import com.tencent.supersonic.auth.authentication.utils.TokenService;
import com.tencent.supersonic.common.pojo.exception.AccessException;
import com.tencent.supersonic.common.util.ContextUtils;
@@ -16,12 +16,7 @@ import org.springframework.web.method.HandlerMethod;
import java.lang.reflect.Method;
import java.util.Optional;
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_IS_ADMIN;
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_USER_DISPLAY_NAME;
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_USER_EMAIL;
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_USER_ID;
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_USER_NAME;
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_USER_PASSWORD;
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.*;
@Slf4j
public class DefaultAuthenticationInterceptor extends AuthenticationInterceptor {
@@ -30,7 +25,7 @@ public class DefaultAuthenticationInterceptor extends AuthenticationInterceptor
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws AccessException {
authenticationConfig = ContextUtils.getBean(AuthenticationConfig.class);
userServiceImpl = ContextUtils.getBean(UserServiceImpl.class);
userService = ContextUtils.getBean(UserService.class);
tokenService = ContextUtils.getBean(TokenService.class);
if (!authenticationConfig.isEnabled()) {
return true;

View File

@@ -3,7 +3,11 @@ package com.tencent.supersonic.auth.authentication.persistence.dataobject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.sql.Timestamp;
@Data
@TableName("s2_user")
public class UserDO {
@@ -27,71 +31,25 @@ public class UserDO {
/** */
private Integer isAdmin;
/** @return id */
public Long getId() {
return id;
}
/** @param id */
public void setId(Long id) {
this.id = id;
}
/** @return name */
public String getName() {
return name;
}
private Timestamp lastLogin;
/** @param name */
public void setName(String name) {
this.name = name == null ? null : name.trim();
}
/** @return password */
public String getPassword() {
return password;
}
/** @param password */
public void setPassword(String password) {
this.password = password == null ? null : password.trim();
}
public String getSalt() {
return salt;
}
public void setSalt(String salt) {
this.salt = salt == null ? null : salt.trim();
}
/** @return display_name */
public String getDisplayName() {
return displayName;
}
/** @param displayName */
public void setDisplayName(String displayName) {
this.displayName = displayName == null ? null : displayName.trim();
}
/** @return email */
public String getEmail() {
return email;
}
/** @param email */
public void setEmail(String email) {
this.email = email == null ? null : email.trim();
}
/** @return is_admin */
public Integer getIsAdmin() {
return isAdmin;
}
/** @param isAdmin */
public void setIsAdmin(Integer isAdmin) {
this.isAdmin = isAdmin;
}
}

View File

@@ -21,7 +21,11 @@ public interface UserRepository {
UserTokenDO getUserToken(Long tokenId);
UserTokenDO getUserTokenByName(String tokenName);
void deleteUserTokenByName(String userName);
void deleteUserToken(Long tokenId);
void deleteUser(long userId);
}

View File

@@ -65,6 +65,13 @@ public class UserRepositoryImpl implements UserRepository {
return userTokenDOMapper.selectById(tokenId);
}
@Override
public UserTokenDO getUserTokenByName(String tokenName) {
QueryWrapper<UserTokenDO> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(UserTokenDO::getName, tokenName);
return userTokenDOMapper.selectOne(queryWrapper);
}
@Override
public void deleteUserTokenByName(String userName) {
QueryWrapper<UserTokenDO> queryWrapper = new QueryWrapper<>();
@@ -76,4 +83,9 @@ public class UserRepositoryImpl implements UserRepository {
public void deleteUserToken(Long tokenId) {
userTokenDOMapper.deleteById(tokenId);
}
@Override
public void deleteUser(long userId) {
userDOMapper.deleteById(userId);
}
}

View File

@@ -9,13 +9,7 @@ import com.tencent.supersonic.common.pojo.User;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Set;
@@ -67,6 +61,16 @@ public class UserController {
userService.register(userCmd);
}
@DeleteMapping("/delete/{userId}")
public void delete(@PathVariable("userId") long userId, HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) throws IllegalAccessException {
User user = userService.getCurrentUser(httpServletRequest, httpServletResponse);
if (user.getIsAdmin() != 1) {
throw new IllegalAccessException("only admin can delete user");
}
userService.deleteUser(userId);
}
@PostMapping("/login")
public String login(@RequestBody UserReq userCmd, HttpServletRequest request) {
return userService.login(userCmd, request);

View File

@@ -70,6 +70,11 @@ public class UserServiceImpl implements UserService {
ComponentFactory.getUserAdaptor().register(userReq);
}
@Override
public void deleteUser(long userId) {
ComponentFactory.getUserAdaptor().deleteUser(userId);
}
@Override
public String login(UserReq userReq, HttpServletRequest request) {
return ComponentFactory.getUserAdaptor().login(userReq, request);

View File

@@ -6,7 +6,10 @@ import javax.crypto.spec.SecretKeySpec;
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
import com.tencent.supersonic.auth.api.authentication.pojo.UserWithPassword;
import com.tencent.supersonic.auth.authentication.persistence.dataobject.UserTokenDO;
import com.tencent.supersonic.auth.authentication.persistence.repository.UserRepository;
import com.tencent.supersonic.common.pojo.exception.AccessException;
import com.tencent.supersonic.common.util.ContextUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
@@ -71,6 +74,7 @@ public class TokenService {
return generateToken(UserWithPassword.convert(appUser), request);
}
public Optional<Claims> getClaims(HttpServletRequest request) {
String token = request.getHeader(authenticationConfig.getTokenHttpHeaderKey());
String appKey = getAppKey(request);
@@ -90,6 +94,14 @@ public class TokenService {
public Optional<Claims> getClaims(String token, String appKey) {
try {
if (StringUtils.isNotBlank(appKey) && appKey.startsWith("SysDbToken:")) {// 如果是配置的长期令牌,需校验数据库是否存在该配置
UserRepository userRepository = ContextUtils.getBean(UserRepository.class);
UserTokenDO dbToken =
userRepository.getUserTokenByName(appKey.substring("SysDbToken:".length()));
if (dbToken == null || !dbToken.getToken().equals(token.replace("Bearer ", ""))) {
throw new AccessException("Token does not exist :" + appKey);
}
}
String tokenSecret = getTokenSecret(appKey);
Claims claims =
Jwts.parser().setSigningKey(tokenSecret.getBytes(StandardCharsets.UTF_8))
@@ -122,6 +134,16 @@ public class TokenService {
Map<String, String> appKeyToSecretMap = authenticationConfig.getAppKeyToSecretMap();
String secret = appKeyToSecretMap.get(appKey);
if (StringUtils.isBlank(secret)) {
if (StringUtils.isNotBlank(appKey) && appKey.startsWith("SysDbToken:")) { // 是配置的长期令牌
String realAppKey = appKey.substring("SysDbToken:".length());
String tmp =
"WIaO9YRRVt+7QtpPvyWsARFngnEcbaKBk783uGFwMrbJBaochsqCH62L4Kijcb0sZCYoSsiKGV/zPml5MnZ3uQ==";
if (tmp.length() <= realAppKey.length()) {
return realAppKey;
} else {
return realAppKey + tmp.substring(realAppKey.length());
}
}
throw new AccessException("get secret from appKey failed :" + appKey);
}
return secret;

View File

@@ -9,6 +9,7 @@
<result column="display_name" jdbcType="VARCHAR" property="displayName" />
<result column="email" jdbcType="VARCHAR" property="email" />
<result column="is_admin" jdbcType="INTEGER" property="isAdmin" />
<result column="last_login" jdbcType="TIMESTAMP" property="lastLogin" />
</resultMap>
<sql id="Example_Where_Clause">
<where>
@@ -40,7 +41,7 @@
</where>
</sql>
<sql id="Base_Column_List">
id, name, password, salt, display_name, email, is_admin
id, name, password, salt, display_name, email, is_admin, last_login
</sql>
<select id="selectByExample" parameterType="com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDOExample" resultMap="BaseResultMap">
select
@@ -136,6 +137,9 @@
<if test="isAdmin != null">
is_admin = #{isAdmin,jdbcType=INTEGER},
</if>
<if test="lastLogin != null">
last_login = #{lastLogin,jdbcType=TIMESTAMP},
</if>
</set>
where id = #{id,jdbcType=BIGINT}
</update>

View File

@@ -15,6 +15,68 @@ import requests
import time
import jwt
import traceback
import os
from datetime import datetime
class DataFrameAppender:
def __init__(self,file_name = "output"):
# 定义表头
columns = ['问题', '解析状态', '解析耗时', '执行状态', '执行耗时', '总耗时']
# 创建只有表头的 DataFrame
self.df = pd.DataFrame(columns=columns)
self.file_name = file_name
def append_data(self, new_data):
# 假设 new_data 是一维数组,将其转换为字典
columns = ['问题', '解析状态', '解析耗时', '执行状态', '执行耗时', '总耗时']
new_dict = dict(zip(columns, new_data))
# 使用 loc 方法追加数据
self.df.loc[len(self.df)] = new_dict
def print_analysis_result(self):
# 测试样例总数
total_samples = len(self.df)
# 解析成功数量
parse_success_count = (self.df['解析状态'] == '解析成功').sum()
# 执行成功数量
execute_success_count = (self.df['执行状态'] == '执行成功').sum()
# 解析平均耗时,保留两位小数
avg_parse_time = round(self.df['解析耗时'].mean(), 2)
# 执行平均耗时,保留两位小数
avg_execute_time = round(self.df['执行耗时'].mean(), 2)
# 总平均耗时,保留两位小数
avg_total_time = round(self.df['总耗时'].mean(), 2)
# 最长耗时,保留两位小数
max_time = round(self.df['总耗时'].max(), 2)
# 最短耗时,保留两位小数
min_time = round(self.df['总耗时'].min(), 2)
print(f"测试样例总数 : {total_samples}")
print(f"解析成功数量 : {parse_success_count}")
print(f"执行成功数量 : {execute_success_count}")
print(f"解析平均耗时 : {avg_parse_time}")
print(f"执行平均耗时 : {avg_execute_time}")
print(f"总平均耗时 : {avg_total_time}")
print(f"最长耗时 : {max_time}")
print(f"最短耗时 : {min_time}")
def write_to_csv(self):
# 检查 data 文件夹是否存在,如果不存在则创建
if not os.path.exists('res'):
os.makedirs('res')
# 获取当前时间戳
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
# 生成带时间戳的文件名
file_path = os.path.join('res', f'{self.file_name}_{timestamp}.csv')
self.df.to_csv(file_path, index=False)
print(f"测试结果已保存到 {file_path}")
class BatchTest:
def __init__(self, url, agentId, chatId, userName):
@@ -70,18 +132,35 @@ class BatchTest:
def benchmark(url:str, agentId:str, chatId:str, filePath:str, userName:str):
batch_test = BatchTest(url, agentId, chatId, userName)
df = batch_test.read_question_from_csv(filePath)
appender = DataFrameAppender(os.path.basename(filePath))
for index, row in df.iterrows():
question = row['question']
print('start to ask question:', question)
# 捕获异常,防止程序中断
try:
parse_resp = batch_test.parse(question)
batch_test.execute(agentId, question, parse_resp['data']['queryId'])
parse_status = '解析失败'
if parse_resp.get('data').get('errorMsg') is None:
parse_status = '解析成功'
parse_cost = parse_resp.get('data').get('parseTimeCost').get('parseTime')
execute_resp = batch_test.execute(agentId, question, parse_resp['data']['queryId'])
execute_status = '执行失败'
execute_cost = 0
if parse_status == '解析成功' and execute_resp.get('data').get('errorMsg') is None:
execute_status = '执行成功'
execute_cost = execute_resp.get('data').get('queryTimeCost')
res = [question.replace(',', '#'),parse_status,parse_cost/1000,execute_status,execute_cost/1000,(parse_cost+execute_cost)/1000]
appender.append_data(res)
except Exception as e:
print('error:', e)
traceback.print_exc()
continue
time.sleep(1)
# 打印分析结果
appender.print_analysis_result()
# 分析明细输出
appender.write_to_csv()
if __name__ == '__main__':

View File

@@ -5,5 +5,7 @@ import com.tencent.supersonic.chat.server.pojo.ExecuteContext;
public interface ChatQueryExecutor {
boolean accept(ExecuteContext executeContext);
QueryResult execute(ExecuteContext executeContext);
}

View File

@@ -37,11 +37,12 @@ public class PlainTextExecutor implements ChatQueryExecutor {
}
@Override
public QueryResult execute(ExecuteContext executeContext) {
if (!"PLAIN_TEXT".equals(executeContext.getParseInfo().getQueryMode())) {
return null;
}
public boolean accept(ExecuteContext executeContext) {
return "PLAIN_TEXT".equals(executeContext.getParseInfo().getQueryMode());
}
@Override
public QueryResult execute(ExecuteContext executeContext) {
AgentService agentService = ContextUtils.getBean(AgentService.class);
Agent chatAgent = agentService.getAgent(executeContext.getAgent().getId());
ChatApp chatApp = chatAgent.getChatAppConfig().get(APP_KEY);

View File

@@ -8,6 +8,11 @@ import com.tencent.supersonic.headless.api.pojo.SemanticParseInfo;
public class PluginExecutor implements ChatQueryExecutor {
@Override
public boolean accept(ExecuteContext executeContext) {
return PluginQueryManager.isPluginQuery(executeContext.getParseInfo().getQueryMode());
}
@Override
public QueryResult execute(ExecuteContext executeContext) {
SemanticParseInfo parseInfo = executeContext.getParseInfo();

View File

@@ -25,6 +25,11 @@ import java.util.Objects;
public class SqlExecutor implements ChatQueryExecutor {
@Override
public boolean accept(ExecuteContext executeContext) {
return true;
}
@SneakyThrows
@Override
public QueryResult execute(ExecuteContext executeContext) {
@@ -70,8 +75,12 @@ public class SqlExecutor implements ChatQueryExecutor {
return null;
}
QuerySqlReq sqlReq =
QuerySqlReq.builder().sql(parseInfo.getSqlInfo().getCorrectedS2SQL()).build();
// 使用querySQL它已经包含了所有修正包括物理SQL修正
String finalSql = StringUtils.isNotBlank(parseInfo.getSqlInfo().getQuerySQL())
? parseInfo.getSqlInfo().getQuerySQL()
: parseInfo.getSqlInfo().getCorrectedS2SQL();
QuerySqlReq sqlReq = QuerySqlReq.builder().sql(finalSql).build();
sqlReq.setSqlInfo(parseInfo.getSqlInfo());
sqlReq.setDataSetId(parseInfo.getDataSetId());
@@ -80,12 +89,12 @@ public class SqlExecutor implements ChatQueryExecutor {
queryResult.setQueryId(executeContext.getRequest().getQueryId());
queryResult.setChatContext(parseInfo);
queryResult.setQueryMode(parseInfo.getQueryMode());
queryResult.setQueryTimeCost(System.currentTimeMillis() - startTime);
SemanticQueryResp queryResp =
semanticLayer.queryByReq(sqlReq, executeContext.getRequest().getUser());
queryResult.setQueryTimeCost(System.currentTimeMillis() - startTime);
if (queryResp != null) {
queryResult.setQueryAuthorization(queryResp.getQueryAuthorization());
queryResult.setQuerySql(queryResp.getSql());
queryResult.setQuerySql(finalSql);
queryResult.setQueryResults(queryResp.getResultList());
queryResult.setQueryColumns(queryResp.getColumns());
queryResult.setQueryState(QueryState.SUCCESS);

View File

@@ -4,5 +4,7 @@ import com.tencent.supersonic.chat.server.pojo.ParseContext;
public interface ChatQueryParser {
boolean accept(ParseContext parseContext);
void parse(ParseContext parseContext);
}

View File

@@ -14,12 +14,12 @@ public class NL2PluginParser implements ChatQueryParser {
private final List<PluginRecognizer> pluginRecognizers =
ComponentFactory.getPluginRecognizers();
public boolean accept(ParseContext parseContext) {
return parseContext.getAgent().containsPluginTool();
}
@Override
public void parse(ParseContext parseContext) {
if (!parseContext.getAgent().containsPluginTool()) {
return;
}
pluginRecognizers.forEach(pluginRecognizer -> {
pluginRecognizer.recognize(parseContext);
log.info("{} recallResult:{}", pluginRecognizer.getClass().getSimpleName(),

View File

@@ -73,12 +73,12 @@ public class NL2SQLParser implements ChatQueryParser {
.build());
}
public boolean accept(ParseContext parseContext) {
return parseContext.enableNL2SQL();
}
@Override
public void parse(ParseContext parseContext) {
if (!parseContext.enableNL2SQL()) {
return;
}
// first go with rule-based parsers unless the user has already selected one parse.
if (Objects.isNull(parseContext.getRequest().getSelectedParse())) {
QueryNLReq queryNLReq = QueryReqConverter.buildQueryNLReq(parseContext);

View File

@@ -6,12 +6,12 @@ import com.tencent.supersonic.headless.api.pojo.response.ParseResp;
public class PlainTextParser implements ChatQueryParser {
public boolean accept(ParseContext parseContext) {
return !parseContext.getAgent().containsAnyTool();
}
@Override
public void parse(ParseContext parseContext) {
if (parseContext.getAgent().containsAnyTool()) {
return;
}
SemanticParseInfo parseInfo = new SemanticParseInfo();
parseInfo.setQueryMode("PLAIN_TEXT");
parseInfo.setId(1);

View File

@@ -1,11 +1,16 @@
package com.tencent.supersonic.chat.server.persistence.dataobject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("s2_chat")
public class ChatDO {
private long chatId;
@TableId(type = IdType.AUTO)
private Long chatId;
private Integer agentId;
private String chatName;
private String createTime;

View File

@@ -1,20 +0,0 @@
package com.tencent.supersonic.chat.server.persistence.dataobject;
import lombok.Data;
import java.util.Date;
@Data
public class DictConfDO {
private Long id;
private Long modelId;
private String dimValueInfos;
private String createdBy;
private String updatedBy;
private Date createdAt;
private Date updatedAt;
}

View File

@@ -1,38 +0,0 @@
package com.tencent.supersonic.chat.server.persistence.dataobject;
import lombok.Data;
import lombok.ToString;
import org.apache.commons.codec.digest.DigestUtils;
import java.util.Date;
@Data
@ToString
public class DictTaskDO {
private Long id;
private String name;
private String description;
private String command;
private String commandMd5;
private String dimIds;
private Integer status;
private String createdBy;
private Date createdAt;
private Double progress;
private Long elapsedMs;
public String getCommandMd5() {
return DigestUtils.md5Hex(command);
}
}

View File

@@ -148,7 +148,7 @@ public class ChatQueryRepositoryImpl implements ChatQueryRepository {
chatQueryDO.setUserName(chatParseReq.getUser().getName());
chatQueryDO.setQueryText(chatParseReq.getQueryText());
chatQueryDO.setAgentId(chatParseReq.getAgentId());
chatQueryDO.setQueryResult("");
chatQueryDO.setQueryResult("{}");
chatQueryDO.setQueryState(1);
try {
chatQueryDOMapper.insert(chatQueryDO);

View File

@@ -46,7 +46,9 @@ public class DataInterpretProcessor implements ExecuteResultProcessor {
public boolean accept(ExecuteContext executeContext) {
Agent agent = executeContext.getAgent();
ChatApp chatApp = agent.getChatAppConfig().get(APP_KEY);
return Objects.nonNull(chatApp) && chatApp.isEnable();
return Objects.nonNull(chatApp) && chatApp.isEnable()
&& StringUtils.isNotBlank(executeContext.getResponse().getTextResult()) // 如果都没结果,则无法处理
&& StringUtils.isBlank(executeContext.getResponse().getTextSummary()); // 如果已经有汇总的结果了,无法再次处理
}
@Override
@@ -56,7 +58,16 @@ public class DataInterpretProcessor implements ExecuteResultProcessor {
ChatApp chatApp = agent.getChatAppConfig().get(APP_KEY);
Map<String, Object> variable = new HashMap<>();
variable.put("question", executeContext.getRequest().getQueryText());
String question = executeContext.getResponse().getTextResult();// 结果解析应该用改写的问题,因为改写的内容信息量更大
if (executeContext.getParseInfo().getProperties() != null
&& executeContext.getParseInfo().getProperties().containsKey("CONTEXT")) {
Map<String, Object> context = (Map<String, Object>) executeContext.getParseInfo()
.getProperties().get("CONTEXT");
if (context.get("queryText") != null && "".equals(context.get("queryText"))) {
question = context.get("queryText").toString();
}
}
variable.put("question", question);
variable.put("data", queryResult.getTextResult());
Prompt prompt = PromptTemplate.from(chatApp.getPrompt()).apply(variable);

View File

@@ -66,8 +66,10 @@ public class ChatConfigController {
}
@GetMapping("/getDomainDataSetTree")
public List<ItemResp> getDomainDataSetTree() {
return semanticLayerService.getDomainDataSetTree();
public List<ItemResp> getDomainDataSetTree(HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return semanticLayerService.getDomainDataSetTree(user);
}
@GetMapping("/getDataSetSchema/{id}")

View File

@@ -22,11 +22,10 @@ public class ChatController {
private ChatManageService chatService;
@PostMapping("/save")
public Boolean save(@RequestParam(value = "chatName") String chatName,
public Long save(@RequestParam(value = "chatName") String chatName,
@RequestParam(value = "agentId", required = false) Integer agentId,
HttpServletRequest request, HttpServletResponse response) {
chatService.addChat(UserHolder.findUser(request, response), chatName, agentId);
return true;
return chatService.addChat(UserHolder.findUser(request, response), chatName, agentId);
}
@GetMapping("/getAll")

View File

@@ -22,6 +22,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
@@ -39,6 +40,7 @@ public class AgentServiceImpl extends ServiceImpl<AgentDOMapper, AgentDO> implem
private MemoryService memoryService;
@Autowired
@Lazy
private ChatQueryService chatQueryService;
@Autowired
@@ -161,9 +163,11 @@ public class AgentServiceImpl extends ServiceImpl<AgentDOMapper, AgentDO> implem
JsonUtil.toMap(agentDO.getChatModelConfig(), String.class, ChatApp.class));
agent.setVisualConfig(JsonUtil.toObject(agentDO.getVisualConfig(), VisualConfig.class));
agent.getChatAppConfig().values().forEach(c -> {
ChatModel chatModel = chatModelService.getChatModel(c.getChatModelId());
if (Objects.nonNull(chatModel)) {
c.setChatModelConfig(chatModelService.getChatModel(c.getChatModelId()).getConfig());
if (c.isEnable()) {// 优化,减少访问数据库的次数
ChatModel chatModel = chatModelService.getChatModel(c.getChatModelId());
if (Objects.nonNull(chatModel)) {
c.setChatModelConfig(chatModel.getConfig());
}
}
});
agent.setAdmins(JsonUtil.toList(agentDO.getAdmin(), String.class));

View File

@@ -233,6 +233,10 @@ public class ChatManageServiceImpl implements ChatManageService {
@Override
public SemanticParseInfo getParseInfo(Long questionId, int parseId) {
ChatParseDO chatParseDO = chatQueryRepository.getParseInfo(questionId, parseId);
return JSONObject.parseObject(chatParseDO.getParseInfo(), SemanticParseInfo.class);
if (chatParseDO == null) {
return null;
} else {
return JSONObject.parseObject(chatParseDO.getParseInfo(), SemanticParseInfo.class);
}
}
}

View File

@@ -49,6 +49,7 @@ import net.sf.jsqlparser.schema.Column;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
@@ -66,6 +67,7 @@ public class ChatQueryServiceImpl implements ChatQueryService {
@Autowired
private SemanticLayerService semanticLayerService;
@Autowired
@Lazy
private AgentService agentService;
private final List<ChatQueryParser> chatQueryParsers = ComponentFactory.getChatParsers();
@@ -95,7 +97,11 @@ public class ChatQueryServiceImpl implements ChatQueryService {
}
ParseContext parseContext = buildParseContext(chatParseReq, new ChatParseResp(queryId));
chatQueryParsers.forEach(p -> p.parse(parseContext));
for (ChatQueryParser parser : chatQueryParsers) {
if (parser.accept(parseContext)) {
parser.parse(parseContext);
}
}
for (ParseResultProcessor processor : parseResultProcessors) {
if (processor.accept(parseContext)) {
@@ -116,9 +122,11 @@ public class ChatQueryServiceImpl implements ChatQueryService {
QueryResult queryResult = new QueryResult();
ExecuteContext executeContext = buildExecuteContext(chatExecuteReq);
for (ChatQueryExecutor chatQueryExecutor : chatQueryExecutors) {
queryResult = chatQueryExecutor.execute(executeContext);
if (queryResult != null) {
break;
if (chatQueryExecutor.accept(executeContext)) {
queryResult = chatQueryExecutor.execute(executeContext);
if (queryResult != null) {
break;
}
}
}

View File

@@ -18,9 +18,11 @@ import com.tencent.supersonic.common.config.EmbeddingConfig;
import com.tencent.supersonic.common.pojo.Text2SQLExemplar;
import com.tencent.supersonic.common.pojo.User;
import com.tencent.supersonic.common.service.ExemplarService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
@@ -30,7 +32,8 @@ import java.util.Objects;
import java.util.stream.Collectors;
@Service
public class MemoryServiceImpl implements MemoryService {
@Slf4j
public class MemoryServiceImpl implements MemoryService, CommandLineRunner {
@Autowired
private ChatMemoryRepository chatMemoryRepository;
@@ -61,12 +64,17 @@ public class MemoryServiceImpl implements MemoryService {
ChatMemoryDO chatMemoryDO = chatMemoryRepository.getMemory(chatMemoryUpdateReq.getId());
boolean hadEnabled =
MemoryStatus.ENABLED.toString().equals(chatMemoryDO.getStatus().trim());
if (MemoryStatus.ENABLED.equals(chatMemoryUpdateReq.getStatus()) && !hadEnabled) {
if (MemoryStatus.ENABLED.equals(chatMemoryUpdateReq.getStatus())) {
// Update the latest SQL/Schema to vector DB once memory is enabled
chatMemoryDO.setS2sql(chatMemoryUpdateReq.getS2sql());
chatMemoryDO.setDbSchema(chatMemoryUpdateReq.getDbSchema());
enableMemory(chatMemoryDO);
} else if (MemoryStatus.DISABLED.equals(chatMemoryUpdateReq.getStatus()) && hadEnabled) {
} else if ((MemoryStatus.DISABLED.equals(chatMemoryUpdateReq.getStatus())
|| MemoryStatus.PENDING.equals(chatMemoryUpdateReq.getStatus())) && hadEnabled) {
// Remove from vector DB when transitioning: launched→disabled OR enabled→pending
disableMemory(chatMemoryDO);
}
LambdaUpdateWrapper<ChatMemoryDO> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(ChatMemoryDO::getId, chatMemoryDO.getId());
if (Objects.nonNull(chatMemoryUpdateReq.getStatus())) {
@@ -87,6 +95,12 @@ public class MemoryServiceImpl implements MemoryService {
updateWrapper.set(ChatMemoryDO::getHumanReviewCmt,
chatMemoryUpdateReq.getHumanReviewCmt());
}
if (Objects.nonNull(chatMemoryUpdateReq.getDbSchema())) {
updateWrapper.set(ChatMemoryDO::getDbSchema, chatMemoryUpdateReq.getDbSchema());
}
if (Objects.nonNull(chatMemoryUpdateReq.getS2sql())) {
updateWrapper.set(ChatMemoryDO::getS2sql, chatMemoryUpdateReq.getS2sql());
}
updateWrapper.set(ChatMemoryDO::getUpdatedAt, new Date());
updateWrapper.set(ChatMemoryDO::getUpdatedBy, user.getName());
@@ -95,6 +109,14 @@ public class MemoryServiceImpl implements MemoryService {
@Override
public void batchDelete(List<Long> ids) {
QueryWrapper<ChatMemoryDO> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().in(ChatMemoryDO::getId, ids);
List<ChatMemoryDO> chatMemoryDOS = chatMemoryRepository.getMemories(queryWrapper);
chatMemoryDOS.forEach(chatMemoryDO -> {
if (MemoryStatus.ENABLED.toString().equals(chatMemoryDO.getStatus().trim())) {
disableMemory(chatMemoryDO);
}
});
chatMemoryRepository.batchDelete(ids);
}
@@ -187,4 +209,25 @@ public class MemoryServiceImpl implements MemoryService {
return memory;
}
@Override
public void run(String... args) { // 优化,启动时检查,向量数据,将记忆放到向量数据库
loadSysExemplars();
}
public void loadSysExemplars() {
try {
List<ChatMemory> memories = this
.getMemories(ChatMemoryFilter.builder().status(MemoryStatus.ENABLED).build());
for (ChatMemory memory : memories) {
exemplarService.storeExemplar(
embeddingConfig.getMemoryCollectionName(memory.getAgentId()),
Text2SQLExemplar.builder().question(memory.getQuestion())
.sideInfo(memory.getSideInfo()).dbSchema(memory.getDbSchema())
.sql(memory.getS2sql()).build());
}
} catch (Exception e) {
log.error("Failed to load system exemplars", e);
}
}
}

View File

@@ -21,7 +21,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure-processor</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
@@ -33,7 +36,7 @@
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>${httpclient5.version}</version> <!-- 请确认使用最新稳定版本 -->
<version>${httpclient5.version}</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.apache.httpcomponents</groupId>-->
@@ -182,10 +185,6 @@
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-pgvector</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-azure-open-ai</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-embeddings-bge-small-zh</artifactId>
@@ -198,34 +197,6 @@
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-embeddings-all-minilm-l6-v2-q</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-qianfan</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-zhipu-ai</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-dashscope</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-chatglm</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-ollama</artifactId>
@@ -237,11 +208,6 @@
<version>${hanlp.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure-processor</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>

View File

@@ -21,7 +21,8 @@ public class LoadRemoveService {
List<String> resultList = new ArrayList<>(value);
if (!CollectionUtils.isEmpty(modelIdOrDataSetIds)) {
resultList.removeIf(nature -> {
if (Objects.isNull(nature)) {
if (Objects.isNull(nature) || !nature.startsWith("_")) { // 系统的字典是以 _ 开头的,
// 过滤因引用外部字典导致的异常
return false;
}
Long id = getId(nature);

View File

@@ -77,11 +77,6 @@ public class SemanticSqlConformance implements SqlConformance {
return SqlConformanceEnum.BIG_QUERY.isMinusAllowed();
}
@Override
public boolean isRegexReplaceCaptureGroupDollarIndexed() {
return SqlConformanceEnum.BIG_QUERY.isRegexReplaceCaptureGroupDollarIndexed();
}
@Override
public boolean isApplyAllowed() {
return SqlConformanceEnum.BIG_QUERY.isApplyAllowed();

View File

@@ -26,6 +26,16 @@ public class SqlDialectFactory {
.withLiteralQuoteString("'").withIdentifierQuoteString("\"")
.withLiteralEscapedQuoteString("''").withUnquotedCasing(Casing.UNCHANGED)
.withQuotedCasing(Casing.UNCHANGED).withCaseSensitive(true);
public static final Context PRESTO_CONTEXT =
SqlDialect.EMPTY_CONTEXT.withDatabaseProduct(DatabaseProduct.PRESTO)
.withLiteralQuoteString("'").withIdentifierQuoteString("\"")
.withLiteralEscapedQuoteString("''").withUnquotedCasing(Casing.UNCHANGED)
.withQuotedCasing(Casing.UNCHANGED).withCaseSensitive(true);
public static final Context KYUUBI_CONTEXT =
SqlDialect.EMPTY_CONTEXT.withDatabaseProduct(DatabaseProduct.BIG_QUERY)
.withLiteralQuoteString("'").withIdentifierQuoteString("`")
.withLiteralEscapedQuoteString("''").withUnquotedCasing(Casing.UNCHANGED)
.withQuotedCasing(Casing.UNCHANGED).withCaseSensitive(false);
private static Map<EngineType, SemanticSqlDialect> sqlDialectMap;
static {
@@ -35,6 +45,10 @@ public class SqlDialectFactory {
sqlDialectMap.put(EngineType.H2, new SemanticSqlDialect(DEFAULT_CONTEXT));
sqlDialectMap.put(EngineType.POSTGRESQL, new SemanticSqlDialect(POSTGRESQL_CONTEXT));
sqlDialectMap.put(EngineType.HANADB, new SemanticSqlDialect(HANADB_CONTEXT));
sqlDialectMap.put(EngineType.STARROCKS, new SemanticSqlDialect(DEFAULT_CONTEXT));
sqlDialectMap.put(EngineType.KYUUBI, new SemanticSqlDialect(KYUUBI_CONTEXT));
sqlDialectMap.put(EngineType.PRESTO, new SemanticSqlDialect(PRESTO_CONTEXT));
sqlDialectMap.put(EngineType.TRINO, new SemanticSqlDialect(PRESTO_CONTEXT));
}
public static SemanticSqlDialect getSqlDialect(EngineType engineType) {

View File

@@ -2,19 +2,11 @@ package com.tencent.supersonic.common.calcite;
import com.tencent.supersonic.common.pojo.enums.EngineType;
import lombok.extern.slf4j.Slf4j;
import org.apache.calcite.sql.SqlIdentifier;
import org.apache.calcite.sql.SqlLiteral;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.SqlNodeList;
import org.apache.calcite.sql.SqlOrderBy;
import org.apache.calcite.sql.SqlSelect;
import org.apache.calcite.sql.SqlWith;
import org.apache.calcite.sql.SqlWithItem;
import org.apache.calcite.sql.SqlWriterConfig;
import org.apache.calcite.sql.parser.SqlParseException;
import org.apache.calcite.sql.parser.SqlParser;
import org.apache.calcite.sql.parser.SqlParserPos;
import org.apache.calcite.sql.pretty.SqlPrettyWriter;
import net.sf.jsqlparser.expression.Alias;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.select.ParenthesedSelect;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.WithItem;
import java.util.ArrayList;
import java.util.List;
@@ -22,85 +14,37 @@ import java.util.List;
@Slf4j
public class SqlMergeWithUtils {
public static String mergeWith(EngineType engineType, String sql, List<String> parentSqlList,
List<String> parentWithNameList) throws SqlParseException {
SqlParser.Config parserConfig = Configuration.getParserConfig(engineType);
List<String> parentWithNameList) throws Exception {
// Parse the main SQL statement
SqlParser parser = SqlParser.create(sql, parserConfig);
SqlNode sqlNode1 = parser.parseQuery();
Select selectStatement = (Select) CCJSqlParserUtil.parse(sql);
List<WithItem> withItemList = new ArrayList<>();
// List to hold all WITH items
List<SqlNode> withItemList = new ArrayList<>();
// Iterate over each parentSql and parentWithName pair
for (int i = 0; i < parentSqlList.size(); i++) {
String parentSql = parentSqlList.get(i);
String parentWithName = parentWithNameList.get(i);
// Parse the parent SQL statement
parser = SqlParser.create(parentSql, parserConfig);
SqlNode sqlNode2 = parser.parseQuery();
Select parentSelect = (Select) CCJSqlParserUtil.parse(parentSql);
ParenthesedSelect select = new ParenthesedSelect();
select.setSelect(parentSelect);
// Create a new WITH item for parentWithName without quotes
SqlWithItem withItem = new SqlWithItem(SqlParserPos.ZERO,
new SqlIdentifier(parentWithName, SqlParserPos.ZERO), null, sqlNode2,
SqlLiteral.createBoolean(false, SqlParserPos.ZERO));
WithItem withItem = new WithItem();
withItem.setAlias(new Alias(parentWithName));
withItem.setSelect(select);
// Add the new WITH item to the list
withItemList.add(withItem);
}
// Check if the main SQL node contains an ORDER BY or LIMIT clause
SqlNode limitNode = null;
SqlNodeList orderByList = null;
if (sqlNode1 instanceof SqlOrderBy) {
SqlOrderBy sqlOrderBy = (SqlOrderBy) sqlNode1;
limitNode = sqlOrderBy.fetch;
orderByList = sqlOrderBy.orderList;
sqlNode1 = sqlOrderBy.query;
} else if (sqlNode1 instanceof SqlSelect) {
SqlSelect sqlSelect = (SqlSelect) sqlNode1;
limitNode = sqlSelect.getFetch();
sqlSelect.setFetch(null);
sqlNode1 = sqlSelect;
// Extract existing WITH items from mainSelectBody if it has any
if (selectStatement.getWithItemsList() != null) {
withItemList.addAll(selectStatement.getWithItemsList());
}
// Extract existing WITH items from sqlNode1 if it is a SqlWith
if (sqlNode1 instanceof SqlWith) {
SqlWith sqlWith = (SqlWith) sqlNode1;
withItemList.addAll(sqlWith.withList.getList());
sqlNode1 = sqlWith.body;
}
// Set the new WITH items list to the main select body
selectStatement.setWithItemsList(withItemList);
// Create a new SqlWith node
SqlWith finalSqlNode = new SqlWith(SqlParserPos.ZERO,
new SqlNodeList(withItemList, SqlParserPos.ZERO), sqlNode1);
// If there was an ORDER BY or LIMIT clause, wrap the finalSqlNode in a SqlOrderBy
SqlNode resultNode = finalSqlNode;
if (orderByList != null || limitNode != null) {
resultNode = new SqlOrderBy(SqlParserPos.ZERO, finalSqlNode,
orderByList != null ? orderByList : SqlNodeList.EMPTY, null, limitNode);
}
// Custom SqlPrettyWriter configuration to avoid quoting identifiers
SqlWriterConfig config = Configuration.getSqlWriterConfig(engineType);
// Pretty print the final SQL
SqlPrettyWriter writer = new SqlPrettyWriter(config);
return writer.format(resultNode);
}
public static boolean hasWith(EngineType engineType, String sql) throws SqlParseException {
SqlParser.Config parserConfig = Configuration.getParserConfig(engineType);
SqlParser parser = SqlParser.create(sql, parserConfig);
SqlNode sqlNode = parser.parseQuery();
SqlNode sqlSelect = sqlNode;
if (sqlNode instanceof SqlOrderBy) {
SqlOrderBy sqlOrderBy = (SqlOrderBy) sqlNode;
sqlSelect = sqlOrderBy.query;
} else if (sqlNode instanceof SqlSelect) {
sqlSelect = (SqlSelect) sqlNode;
}
return sqlSelect instanceof SqlWith;
return selectStatement.toString();
}
}

View File

@@ -1,9 +1,11 @@
package com.tencent.supersonic.common.config;
import com.google.common.collect.Lists;
import com.tencent.supersonic.common.pojo.ChatModelConfig;
import lombok.Data;
import java.util.Date;
import java.util.List;
@Data
public class ChatModel {
@@ -25,5 +27,11 @@ public class ChatModel {
private String admin;
private String viewer;
private List<String> viewers = Lists.newArrayList();
private Integer isOpen = 0;
public boolean isPublic() {
return isOpen != null && isOpen == 1;
}
}

View File

@@ -4,14 +4,10 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.tencent.supersonic.common.pojo.EmbeddingModelConfig;
import com.tencent.supersonic.common.pojo.Parameter;
import dev.langchain4j.provider.AzureModelFactory;
import dev.langchain4j.provider.DashscopeModelFactory;
import dev.langchain4j.provider.EmbeddingModelConstant;
import dev.langchain4j.provider.InMemoryModelFactory;
import dev.langchain4j.provider.OllamaModelFactory;
import dev.langchain4j.provider.OpenAiModelFactory;
import dev.langchain4j.provider.QianfanModelFactory;
import dev.langchain4j.provider.ZhipuModelFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -70,52 +66,31 @@ public class EmbeddingModelParameterConfig extends ParameterConfig {
private static ArrayList<String> getCandidateValues() {
return Lists.newArrayList(InMemoryModelFactory.PROVIDER, OpenAiModelFactory.PROVIDER,
OllamaModelFactory.PROVIDER, DashscopeModelFactory.PROVIDER,
QianfanModelFactory.PROVIDER, ZhipuModelFactory.PROVIDER,
AzureModelFactory.PROVIDER);
OllamaModelFactory.PROVIDER);
}
private static List<Parameter.Dependency> getBaseUrlDependency() {
return getDependency(EMBEDDING_MODEL_PROVIDER.getName(),
Lists.newArrayList(OpenAiModelFactory.PROVIDER, OllamaModelFactory.PROVIDER,
AzureModelFactory.PROVIDER, DashscopeModelFactory.PROVIDER,
QianfanModelFactory.PROVIDER, ZhipuModelFactory.PROVIDER),
Lists.newArrayList(OpenAiModelFactory.PROVIDER, OllamaModelFactory.PROVIDER),
ImmutableMap.of(OpenAiModelFactory.PROVIDER, OpenAiModelFactory.DEFAULT_BASE_URL,
OllamaModelFactory.PROVIDER, OllamaModelFactory.DEFAULT_BASE_URL,
AzureModelFactory.PROVIDER, AzureModelFactory.DEFAULT_BASE_URL,
DashscopeModelFactory.PROVIDER, DashscopeModelFactory.DEFAULT_BASE_URL,
QianfanModelFactory.PROVIDER, QianfanModelFactory.DEFAULT_BASE_URL,
ZhipuModelFactory.PROVIDER, ZhipuModelFactory.DEFAULT_BASE_URL));
OllamaModelFactory.PROVIDER, OllamaModelFactory.DEFAULT_BASE_URL));
}
private static List<Parameter.Dependency> getApiKeyDependency() {
return getDependency(EMBEDDING_MODEL_PROVIDER.getName(),
Lists.newArrayList(OpenAiModelFactory.PROVIDER, AzureModelFactory.PROVIDER,
DashscopeModelFactory.PROVIDER, QianfanModelFactory.PROVIDER,
ZhipuModelFactory.PROVIDER),
ImmutableMap.of(OpenAiModelFactory.PROVIDER, DEMO, AzureModelFactory.PROVIDER, DEMO,
DashscopeModelFactory.PROVIDER, DEMO, QianfanModelFactory.PROVIDER, DEMO,
ZhipuModelFactory.PROVIDER, DEMO));
Lists.newArrayList(OpenAiModelFactory.PROVIDER),
ImmutableMap.of(OpenAiModelFactory.PROVIDER, DEMO));
}
private static List<Parameter.Dependency> getModelNameDependency() {
return getDependency(EMBEDDING_MODEL_PROVIDER.getName(),
Lists.newArrayList(InMemoryModelFactory.PROVIDER, OpenAiModelFactory.PROVIDER,
OllamaModelFactory.PROVIDER, AzureModelFactory.PROVIDER,
DashscopeModelFactory.PROVIDER, QianfanModelFactory.PROVIDER,
ZhipuModelFactory.PROVIDER),
OllamaModelFactory.PROVIDER),
ImmutableMap.of(InMemoryModelFactory.PROVIDER, EmbeddingModelConstant.BGE_SMALL_ZH,
OpenAiModelFactory.PROVIDER,
OpenAiModelFactory.DEFAULT_EMBEDDING_MODEL_NAME,
OllamaModelFactory.PROVIDER,
OllamaModelFactory.DEFAULT_EMBEDDING_MODEL_NAME, AzureModelFactory.PROVIDER,
AzureModelFactory.DEFAULT_EMBEDDING_MODEL_NAME,
DashscopeModelFactory.PROVIDER,
DashscopeModelFactory.DEFAULT_EMBEDDING_MODEL_NAME,
QianfanModelFactory.PROVIDER,
QianfanModelFactory.DEFAULT_EMBEDDING_MODEL_NAME,
ZhipuModelFactory.PROVIDER,
ZhipuModelFactory.DEFAULT_EMBEDDING_MODEL_NAME));
OllamaModelFactory.DEFAULT_EMBEDDING_MODEL_NAME));
}
private static List<Parameter.Dependency> getModelPathDependency() {
@@ -126,7 +101,7 @@ public class EmbeddingModelParameterConfig extends ParameterConfig {
private static List<Parameter.Dependency> getSecretKeyDependency() {
return getDependency(EMBEDDING_MODEL_PROVIDER.getName(),
Lists.newArrayList(QianfanModelFactory.PROVIDER),
ImmutableMap.of(QianfanModelFactory.PROVIDER, DEMO));
Lists.newArrayList(OpenAiModelFactory.PROVIDER),
ImmutableMap.of(OpenAiModelFactory.PROVIDER, DEMO));
}
}

View File

@@ -91,7 +91,8 @@ public class FiledFilterReplaceVisitor extends ExpressionVisitorAdapter {
}
ExpressionList<?> leftFunctionParams = leftFunction.getParameters();
if (CollectionUtils.isEmpty(leftFunctionParams)) {
if (CollectionUtils.isEmpty(leftFunctionParams)
|| !(leftFunctionParams.get(0) instanceof Column)) {
return result;
}

View File

@@ -146,6 +146,10 @@ public class SqlReplaceHelper {
public static String replaceFields(String sql, Map<String, String> fieldNameMap,
boolean exactReplace) {
Select selectStatement = SqlSelectHelper.getSelect(sql);
// alias field should not be replaced
Set<String> aliases = SqlSelectHelper.getAliasFields(sql);
aliases.forEach(alias -> fieldNameMap.put(alias, alias));
Set<Select> plainSelectList = SqlSelectHelper.getAllSelect(selectStatement);
for (Select plainSelect : plainSelectList) {
if (plainSelect instanceof PlainSelect) {

View File

@@ -989,6 +989,15 @@ public class SqlSelectHelper {
for (SelectItem selectItem : selectItems) {
selectItem.accept(visitor);
}
if (plainSelect.getHaving() != null) {
plainSelect.getHaving().accept(visitor);
}
if (!CollectionUtils.isEmpty(plainSelect.getOrderByElements())) {
for (OrderByElement orderByElement : plainSelect.getOrderByElements()) {
orderByElement.getExpression().accept(visitor);
}
}
return !visitor.getFunctionNames().isEmpty();
}

View File

@@ -30,4 +30,6 @@ public class ChatModelDO {
private String admin;
private String viewer;
private Integer isOpen;
}

View File

@@ -2,15 +2,7 @@ package com.tencent.supersonic.common.pojo;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import dev.langchain4j.provider.AzureModelFactory;
import dev.langchain4j.provider.DashscopeModelFactory;
import dev.langchain4j.provider.DifyModelFactory;
import dev.langchain4j.provider.LocalAiModelFactory;
import dev.langchain4j.provider.ModelProvider;
import dev.langchain4j.provider.OllamaModelFactory;
import dev.langchain4j.provider.OpenAiModelFactory;
import dev.langchain4j.provider.QianfanModelFactory;
import dev.langchain4j.provider.ZhipuModelFactory;
import dev.langchain4j.provider.*;
import java.util.ArrayList;
import java.util.List;
@@ -21,7 +13,7 @@ public class ChatModelParameters {
public static final Parameter CHAT_MODEL_PROVIDER =
new Parameter("provider", ModelProvider.DEMO_CHAT_MODEL.getProvider(), "接口协议", "",
"list", MODULE_NAME, getCandidateValues());
"list", MODULE_NAME, getCandidateProviders());
public static final Parameter CHAT_MODEL_BASE_URL =
new Parameter("baseUrl", ModelProvider.DEMO_CHAT_MODEL.getBaseUrl(), "BaseUrl", "",
@@ -37,15 +29,6 @@ public class ChatModelParameters {
public static final Parameter CHAT_MODEL_API_VERSION = new Parameter("apiVersion", "2024-02-01",
"ApiVersion", "", "string", MODULE_NAME, null, getApiVersionDependency());
public static final Parameter CHAT_MODEL_ENDPOINT = new Parameter("endpoint", "llama_2_70b",
"Endpoint", "", "string", MODULE_NAME, null, getEndpointDependency());
public static final Parameter CHAT_MODEL_SECRET_KEY = new Parameter("secretKey", "demo",
"SecretKey", "", "password", MODULE_NAME, null, getSecretKeyDependency());
public static final Parameter CHAT_MODEL_ENABLE_SEARCH = new Parameter("enableSearch", "false",
"是否启用搜索增强功能设为false表示不启用", "", "bool", MODULE_NAME, null, getEnableSearchDependency());
public static final Parameter CHAT_MODEL_TEMPERATURE =
new Parameter("temperature", "0.0", "Temperature", "", "slider", MODULE_NAME);
@@ -53,42 +36,27 @@ public class ChatModelParameters {
new Parameter("timeOut", "60", "超时时间(秒)", "", "number", MODULE_NAME);
public static List<Parameter> getParameters() {
return Lists.newArrayList(CHAT_MODEL_PROVIDER, CHAT_MODEL_BASE_URL, CHAT_MODEL_ENDPOINT,
CHAT_MODEL_API_KEY, CHAT_MODEL_SECRET_KEY, CHAT_MODEL_NAME, CHAT_MODEL_API_VERSION,
CHAT_MODEL_ENABLE_SEARCH, CHAT_MODEL_TEMPERATURE, CHAT_MODEL_TIMEOUT);
return Lists.newArrayList(CHAT_MODEL_PROVIDER, CHAT_MODEL_BASE_URL, CHAT_MODEL_API_KEY,
CHAT_MODEL_NAME, CHAT_MODEL_API_VERSION, CHAT_MODEL_TEMPERATURE,
CHAT_MODEL_TIMEOUT);
}
private static List<String> getCandidateValues() {
private static List<String> getCandidateProviders() {
return Lists.newArrayList(OpenAiModelFactory.PROVIDER, OllamaModelFactory.PROVIDER,
QianfanModelFactory.PROVIDER, ZhipuModelFactory.PROVIDER,
LocalAiModelFactory.PROVIDER, DashscopeModelFactory.PROVIDER,
AzureModelFactory.PROVIDER, DifyModelFactory.PROVIDER);
DifyModelFactory.PROVIDER);
}
private static List<Parameter.Dependency> getBaseUrlDependency() {
return getDependency(CHAT_MODEL_PROVIDER.getName(), getCandidateValues(),
return getDependency(CHAT_MODEL_PROVIDER.getName(), getCandidateProviders(),
ImmutableMap.of(OpenAiModelFactory.PROVIDER, OpenAiModelFactory.DEFAULT_BASE_URL,
AzureModelFactory.PROVIDER, AzureModelFactory.DEFAULT_BASE_URL,
OllamaModelFactory.PROVIDER, OllamaModelFactory.DEFAULT_BASE_URL,
QianfanModelFactory.PROVIDER, QianfanModelFactory.DEFAULT_BASE_URL,
ZhipuModelFactory.PROVIDER, ZhipuModelFactory.DEFAULT_BASE_URL,
LocalAiModelFactory.PROVIDER, LocalAiModelFactory.DEFAULT_BASE_URL,
DashscopeModelFactory.PROVIDER, DashscopeModelFactory.DEFAULT_BASE_URL,
DifyModelFactory.PROVIDER, DifyModelFactory.DEFAULT_BASE_URL));
}
private static List<Parameter.Dependency> getApiKeyDependency() {
return getDependency(CHAT_MODEL_PROVIDER.getName(),
Lists.newArrayList(OpenAiModelFactory.PROVIDER, QianfanModelFactory.PROVIDER,
ZhipuModelFactory.PROVIDER, LocalAiModelFactory.PROVIDER,
AzureModelFactory.PROVIDER, DashscopeModelFactory.PROVIDER,
DifyModelFactory.PROVIDER),
Lists.newArrayList(OpenAiModelFactory.PROVIDER, DifyModelFactory.PROVIDER),
ImmutableMap.of(OpenAiModelFactory.PROVIDER,
ModelProvider.DEMO_CHAT_MODEL.getApiKey(), QianfanModelFactory.PROVIDER,
ModelProvider.DEMO_CHAT_MODEL.getApiKey(), ZhipuModelFactory.PROVIDER,
ModelProvider.DEMO_CHAT_MODEL.getApiKey(), LocalAiModelFactory.PROVIDER,
ModelProvider.DEMO_CHAT_MODEL.getApiKey(), AzureModelFactory.PROVIDER,
ModelProvider.DEMO_CHAT_MODEL.getApiKey(), DashscopeModelFactory.PROVIDER,
ModelProvider.DEMO_CHAT_MODEL.getApiKey(), DifyModelFactory.PROVIDER,
ModelProvider.DEMO_CHAT_MODEL.getApiKey()));
}
@@ -100,33 +68,28 @@ public class ChatModelParameters {
}
private static List<Parameter.Dependency> getModelNameDependency() {
return getDependency(CHAT_MODEL_PROVIDER.getName(), getCandidateValues(),
return getDependency(CHAT_MODEL_PROVIDER.getName(), getCandidateProviders(),
ImmutableMap.of(OpenAiModelFactory.PROVIDER, OpenAiModelFactory.DEFAULT_MODEL_NAME,
OllamaModelFactory.PROVIDER, OllamaModelFactory.DEFAULT_MODEL_NAME,
QianfanModelFactory.PROVIDER, QianfanModelFactory.DEFAULT_MODEL_NAME,
ZhipuModelFactory.PROVIDER, ZhipuModelFactory.DEFAULT_MODEL_NAME,
LocalAiModelFactory.PROVIDER, LocalAiModelFactory.DEFAULT_MODEL_NAME,
AzureModelFactory.PROVIDER, AzureModelFactory.DEFAULT_MODEL_NAME,
DashscopeModelFactory.PROVIDER, DashscopeModelFactory.DEFAULT_MODEL_NAME,
DifyModelFactory.PROVIDER, DifyModelFactory.DEFAULT_MODEL_NAME));
}
private static List<Parameter.Dependency> getEndpointDependency() {
return getDependency(CHAT_MODEL_PROVIDER.getName(),
Lists.newArrayList(QianfanModelFactory.PROVIDER), ImmutableMap
.of(QianfanModelFactory.PROVIDER, QianfanModelFactory.DEFAULT_ENDPOINT));
Lists.newArrayList(OpenAiModelFactory.PROVIDER), ImmutableMap
.of(OpenAiModelFactory.PROVIDER, OpenAiModelFactory.DEFAULT_MODEL_NAME));
}
private static List<Parameter.Dependency> getEnableSearchDependency() {
return getDependency(CHAT_MODEL_PROVIDER.getName(),
Lists.newArrayList(DashscopeModelFactory.PROVIDER),
ImmutableMap.of(DashscopeModelFactory.PROVIDER, "false"));
Lists.newArrayList(OpenAiModelFactory.PROVIDER),
ImmutableMap.of(OpenAiModelFactory.PROVIDER, "false"));
}
private static List<Parameter.Dependency> getSecretKeyDependency() {
return getDependency(CHAT_MODEL_PROVIDER.getName(),
Lists.newArrayList(QianfanModelFactory.PROVIDER), ImmutableMap.of(
QianfanModelFactory.PROVIDER, ModelProvider.DEMO_CHAT_MODEL.getApiKey()));
Lists.newArrayList(OpenAiModelFactory.PROVIDER), ImmutableMap.of(
OpenAiModelFactory.PROVIDER, ModelProvider.DEMO_CHAT_MODEL.getApiKey()));
}
private static List<Parameter.Dependency> getDependency(String dependencyParameterName,

View File

@@ -3,6 +3,7 @@ package com.tencent.supersonic.common.pojo;
import com.google.common.base.Objects;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import java.io.Serializable;
import static com.tencent.supersonic.common.pojo.Constants.ASC_UPPER;

View File

@@ -22,4 +22,6 @@ public class Text2SQLExemplar implements Serializable {
private String dbSchema;
private String sql;
protected double similarity; // 传递相似度,可以作为样本筛选的依据
}

View File

@@ -6,6 +6,7 @@ import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import java.io.Serializable;
import java.sql.Timestamp;
@Data
@NoArgsConstructor
@@ -22,26 +23,28 @@ public class User implements Serializable {
private Integer isAdmin;
private Timestamp lastLogin;
public static User get(Long id, String name, String displayName, String email,
Integer isAdmin) {
return new User(id, name, displayName, email, isAdmin);
return new User(id, name, displayName, email, isAdmin, null);
}
public static User get(Long id, String name) {
return new User(id, name, name, name, 0);
return new User(id, name, name, name, 0, null);
}
public static User getDefaultUser() {
return new User(1L, "admin", "admin", "admin@email", 1);
return new User(1L, "admin", "admin", "admin@email", 1, null);
}
public static User getVisitUser() {
return new User(1L, "visit", "visit", "visit@email", 0);
return new User(1L, "visit", "visit", "visit@email", 0, null);
}
public static User getAppUser(int appId) {
String name = String.format("app_%s", appId);
return new User(1L, name, name, "", 1);
return new User(1L, name, name, "", 1, null);
}
public String getDisplayName() {

View File

@@ -13,7 +13,8 @@ public enum EngineType {
STARROCKS(10, "STARROCKS"),
KYUUBI(11, "KYUUBI"),
PRESTO(12, "PRESTO"),
TRINO(13, "TRINO"),;
TRINO(13, "TRINO"),
ORACLE(14, "ORACLE");
private Integer code;

View File

@@ -7,7 +7,7 @@ import com.tencent.supersonic.common.pojo.User;
import java.util.List;
public interface ChatModelService {
List<ChatModel> getChatModels();
List<ChatModel> getChatModels(User user);
ChatModel getChatModel(Integer id);

View File

@@ -14,6 +14,7 @@ import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
@@ -23,8 +24,15 @@ import java.util.stream.Collectors;
public class ChatModelServiceImpl extends ServiceImpl<ChatModelMapper, ChatModelDO>
implements ChatModelService {
@Override
public List<ChatModel> getChatModels() {
return list().stream().map(this::convert).collect(Collectors.toList());
public List<ChatModel> getChatModels(User user) {
return list().stream().map(this::convert).filter(chatModel -> {
if (chatModel.isPublic() || user.isSuperAdmin()
|| chatModel.getCreatedBy().equals(user.getName())
|| chatModel.getViewers().contains(user.getName())) {
return true;
}
return false;
}).sorted(Comparator.comparingLong(ChatModel::getId)).collect(Collectors.toList());
}
@Override
@@ -41,10 +49,14 @@ public class ChatModelServiceImpl extends ServiceImpl<ChatModelMapper, ChatModel
chatModelDO.setCreatedBy(user.getName());
chatModelDO.setCreatedAt(new Date());
chatModelDO.setUpdatedBy(user.getName());
chatModelDO.setUpdatedAt(new Date());
chatModelDO.setUpdatedAt(chatModelDO.getCreatedAt());
chatModelDO.setIsOpen(chatModel.getIsOpen());
if (StringUtils.isBlank(chatModel.getAdmin())) {
chatModelDO.setAdmin(user.getName());
}
if (!chatModel.getViewers().isEmpty()) {
chatModelDO.setViewer(JsonUtil.toString(chatModel.getViewers()));
}
save(chatModelDO);
chatModel.setId(chatModelDO.getId());
return chatModel;
@@ -55,9 +67,13 @@ public class ChatModelServiceImpl extends ServiceImpl<ChatModelMapper, ChatModel
ChatModelDO chatModelDO = convert(chatModel);
chatModelDO.setUpdatedBy(user.getName());
chatModelDO.setUpdatedAt(new Date());
chatModelDO.setIsOpen(chatModel.getIsOpen());
if (StringUtils.isBlank(chatModel.getAdmin())) {
chatModel.setAdmin(user.getName());
}
if (!chatModel.getViewers().isEmpty()) {
chatModelDO.setViewer(JsonUtil.toString(chatModel.getViewers()));
}
updateById(chatModelDO);
return chatModel;
}
@@ -74,6 +90,7 @@ public class ChatModelServiceImpl extends ServiceImpl<ChatModelMapper, ChatModel
ChatModel chatModel = new ChatModel();
BeanUtils.copyProperties(chatModelDO, chatModel);
chatModel.setConfig(JsonUtil.toObject(chatModelDO.getConfig(), ChatModelConfig.class));
chatModel.setViewers(JsonUtil.toList(chatModelDO.getViewer(), String.class));
return chatModel;
}

View File

@@ -49,10 +49,10 @@ public class EmbeddingServiceImpl implements EmbeddingService {
try {
EmbeddingModel embeddingModel = ModelProvider.getEmbeddingModel();
Embedding embedding = embeddingModel.embed(question).content();
boolean existSegment = existSegment(embeddingStore, query, embedding);
if (existSegment) {
continue;
}
MetadataFilterBuilder filterBuilder =
new MetadataFilterBuilder(TextSegmentConvert.QUERY_ID);
Filter filter = filterBuilder.isEqualTo(TextSegmentConvert.getQueryId(query));
embeddingStore.removeAll(filter);
embeddingStore.add(embedding, query);
cache.put(TextSegmentConvert.getQueryId(query), true);
} catch (Exception e) {
@@ -62,14 +62,14 @@ public class EmbeddingServiceImpl implements EmbeddingService {
}
}
private boolean existSegment(EmbeddingStore embeddingStore, TextSegment query,
Embedding embedding) {
private boolean existSegment(String collectionName, EmbeddingStore embeddingStore,
TextSegment query, Embedding embedding) {
String queryId = TextSegmentConvert.getQueryId(query);
if (queryId == null) {
return false;
}
// Check cache first
Boolean cachedResult = cache.getIfPresent(queryId);
Boolean cachedResult = cache.getIfPresent(collectionName + queryId);
if (cachedResult != null) {
return cachedResult;
}
@@ -82,7 +82,7 @@ public class EmbeddingServiceImpl implements EmbeddingService {
EmbeddingSearchResult result = embeddingStore.search(request);
List<EmbeddingMatch<TextSegment>> relevant = result.matches();
boolean exists = CollectionUtils.isNotEmpty(relevant);
cache.put(queryId, exists);
cache.put(collectionName + queryId, exists);
return exists;
}

View File

@@ -72,7 +72,10 @@ public class ExemplarServiceImpl implements ExemplarService, CommandLineRunner {
embeddingService.retrieveQuery(collection, retrieveQuery, num);
results.forEach(ret -> {
ret.getRetrieval().forEach(r -> {
exemplars.add(JsonUtil.mapToObject(r.getMetadata(), Text2SQLExemplar.class));
Text2SQLExemplar tmp = // 传递相似度,可以作为样本筛选的依据
JsonUtil.mapToObject(r.getMetadata(), Text2SQLExemplar.class);
tmp.setSimilarity(r.getSimilarity());
exemplars.add(tmp);
});
});

View File

@@ -242,10 +242,8 @@ public class DateModeUtils {
return String.format("%s >= '%s' and %s <= '%s'", dateField,
dateInfo.getStartDate(), dateField, dateInfo.getEndDate());
}
LocalDate endData =
LocalDate.parse(dateInfo.getEndDate(), DateTimeFormatter.ofPattern(DAY_FORMAT));
LocalDate startData = LocalDate.parse(dateInfo.getStartDate(),
DateTimeFormatter.ofPattern(DAY_FORMAT));
LocalDate endData = DateUtils.parseDate(dateInfo.getEndDate());
LocalDate startData = DateUtils.parseDate(dateInfo.getStartDate());
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(MONTH_FORMAT);
return String.format("%s >= '%s' and %s <= '%s'", dateField,
startData.format(formatter), dateField, endData.format(formatter));
@@ -320,7 +318,7 @@ public class DateModeUtils {
}
public String getDateWhereStr(DateConf dateInfo, ItemDateResp dateDate) {
if (Objects.isNull(dateInfo)) {
if (Objects.isNull(dateInfo) || Objects.isNull(dateInfo.getDateField())) {
return "";
}
String dateStr = "";

View File

@@ -75,7 +75,7 @@ public class DateUtils {
}
public static String getBeforeDate(String currentDate, DatePeriodEnum datePeriodEnum) {
LocalDate specifiedDate = LocalDate.parse(currentDate, DEFAULT_DATE_FORMATTER2);
LocalDate specifiedDate = parseDate(currentDate);
LocalDate startDate;
switch (datePeriodEnum) {
case MONTH:
@@ -93,7 +93,7 @@ public class DateUtils {
public static String getBeforeDate(String currentDate, int intervalDay,
DatePeriodEnum datePeriodEnum) {
LocalDate specifiedDate = LocalDate.parse(currentDate, DEFAULT_DATE_FORMATTER2);
LocalDate specifiedDate = parseDate(currentDate);
LocalDate result = null;
switch (datePeriodEnum) {
case DAY:
@@ -161,11 +161,25 @@ public class DateUtils {
return !timeString.equals("00:00:00");
}
public static LocalDate parseDate(String timeString) {
DateTimeFormatter[] dateFormatters =
{DateTimeFormatter.ofPattern("yyyyMMdd"), DateTimeFormatter.ofPattern("yyyy-MM-dd"),
DateTimeFormatter.ofPattern("yyyy/MM/dd"),
DateTimeFormatter.ofPattern("yyyy-MM")};
for (DateTimeFormatter formatter : dateFormatters) {
try {
return LocalDate.parse(timeString, formatter);
} catch (DateTimeParseException ignored) {
}
}
return null;
}
public static List<String> getDateList(String startDateStr, String endDateStr,
DatePeriodEnum period) {
try {
LocalDate startDate = LocalDate.parse(startDateStr);
LocalDate endDate = LocalDate.parse(endDateStr);
LocalDate startDate = parseDate(startDateStr);
LocalDate endDate = parseDate(endDateStr);
List<String> datesInRange = new ArrayList<>();
LocalDate currentDate = startDate;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
@@ -189,7 +203,7 @@ public class DateUtils {
}
public static boolean isAnyDateString(String value) {
List<String> formats = Arrays.asList("yyyy-MM-dd", "yyyy-MM", "yyyy/MM/dd");
List<String> formats = Arrays.asList("yyyy-MM-dd", "yyyy-MM", "yyyy/MM/dd", "yyyyMMdd");
return isAnyDateString(value, formats);
}

View File

@@ -1,23 +0,0 @@
package dev.langchain4j.dashscope.spring;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
class ChatModelProperties {
String baseUrl;
String apiKey;
String modelName;
Double topP;
Integer topK;
Boolean enableSearch;
Integer seed;
Float repetitionPenalty;
Float temperature;
List<String> stops;
Integer maxTokens;
}

View File

@@ -1,84 +0,0 @@
package dev.langchain4j.dashscope.spring;
import dev.langchain4j.model.dashscope.QwenChatModel;
import dev.langchain4j.model.dashscope.QwenEmbeddingModel;
import dev.langchain4j.model.dashscope.QwenLanguageModel;
import dev.langchain4j.model.dashscope.QwenStreamingChatModel;
import dev.langchain4j.model.dashscope.QwenStreamingLanguageModel;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static dev.langchain4j.dashscope.spring.Properties.PREFIX;
@Configuration
@EnableConfigurationProperties(Properties.class)
public class DashscopeAutoConfig {
@Bean
@ConditionalOnProperty(PREFIX + ".chat-model.api-key")
QwenChatModel qwenChatModel(Properties properties) {
ChatModelProperties chatModelProperties = properties.getChatModel();
return QwenChatModel.builder().baseUrl(chatModelProperties.getBaseUrl())
.apiKey(chatModelProperties.getApiKey())
.modelName(chatModelProperties.getModelName()).topP(chatModelProperties.getTopP())
.topK(chatModelProperties.getTopK())
.enableSearch(chatModelProperties.getEnableSearch())
.seed(chatModelProperties.getSeed())
.repetitionPenalty(chatModelProperties.getRepetitionPenalty())
.temperature(chatModelProperties.getTemperature())
.stops(chatModelProperties.getStops()).maxTokens(chatModelProperties.getMaxTokens())
.build();
}
@Bean
@ConditionalOnProperty(PREFIX + ".streaming-chat-model.api-key")
QwenStreamingChatModel qwenStreamingChatModel(Properties properties) {
ChatModelProperties chatModelProperties = properties.getStreamingChatModel();
return QwenStreamingChatModel.builder().baseUrl(chatModelProperties.getBaseUrl())
.apiKey(chatModelProperties.getApiKey())
.modelName(chatModelProperties.getModelName()).topP(chatModelProperties.getTopP())
.topK(chatModelProperties.getTopK())
.enableSearch(chatModelProperties.getEnableSearch())
.seed(chatModelProperties.getSeed())
.repetitionPenalty(chatModelProperties.getRepetitionPenalty())
.temperature(chatModelProperties.getTemperature())
.stops(chatModelProperties.getStops()).maxTokens(chatModelProperties.getMaxTokens())
.build();
}
@Bean
@ConditionalOnProperty(PREFIX + ".language-model.api-key")
QwenLanguageModel qwenLanguageModel(Properties properties) {
ChatModelProperties languageModel = properties.getLanguageModel();
return QwenLanguageModel.builder().baseUrl(languageModel.getBaseUrl())
.apiKey(languageModel.getApiKey()).modelName(languageModel.getModelName())
.topP(languageModel.getTopP()).topK(languageModel.getTopK())
.enableSearch(languageModel.getEnableSearch()).seed(languageModel.getSeed())
.repetitionPenalty(languageModel.getRepetitionPenalty())
.temperature(languageModel.getTemperature()).stops(languageModel.getStops())
.maxTokens(languageModel.getMaxTokens()).build();
}
@Bean
@ConditionalOnProperty(PREFIX + ".streaming-language-model.api-key")
QwenStreamingLanguageModel qwenStreamingLanguageModel(Properties properties) {
ChatModelProperties languageModel = properties.getStreamingLanguageModel();
return QwenStreamingLanguageModel.builder().baseUrl(languageModel.getBaseUrl())
.apiKey(languageModel.getApiKey()).modelName(languageModel.getModelName())
.topP(languageModel.getTopP()).topK(languageModel.getTopK())
.enableSearch(languageModel.getEnableSearch()).seed(languageModel.getSeed())
.repetitionPenalty(languageModel.getRepetitionPenalty())
.temperature(languageModel.getTemperature()).stops(languageModel.getStops())
.maxTokens(languageModel.getMaxTokens()).build();
}
@Bean
@ConditionalOnProperty(PREFIX + ".embedding-model.api-key")
QwenEmbeddingModel qwenEmbeddingModel(Properties properties) {
EmbeddingModelProperties embeddingModelProperties = properties.getEmbeddingModel();
return QwenEmbeddingModel.builder().apiKey(embeddingModelProperties.getApiKey())
.modelName(embeddingModelProperties.getModelName()).build();
}
}

View File

@@ -1,12 +0,0 @@
package dev.langchain4j.dashscope.spring;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
class EmbeddingModelProperties {
private String apiKey;
private String modelName;
}

View File

@@ -1,29 +0,0 @@
package dev.langchain4j.dashscope.spring;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
@Getter
@Setter
@ConfigurationProperties(prefix = Properties.PREFIX)
public class Properties {
static final String PREFIX = "langchain4j.dashscope";
@NestedConfigurationProperty
ChatModelProperties chatModel;
@NestedConfigurationProperty
ChatModelProperties streamingChatModel;
@NestedConfigurationProperty
ChatModelProperties languageModel;
@NestedConfigurationProperty
ChatModelProperties streamingLanguageModel;
@NestedConfigurationProperty
EmbeddingModelProperties embeddingModel;
}

View File

@@ -1,9 +1,9 @@
package dev.langchain4j.inmemory.spring;
import dev.langchain4j.model.embedding.AllMiniLmL6V2QuantizedEmbeddingModel;
import dev.langchain4j.model.embedding.BgeSmallZhEmbeddingModel;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.embedding.S2OnnxEmbeddingModel;
import dev.langchain4j.model.embedding.onnx.allminilml6v2q.AllMiniLmL6V2QuantizedEmbeddingModel;
import dev.langchain4j.model.embedding.onnx.bgesmallzh.BgeSmallZhEmbeddingModel;
import dev.langchain4j.provider.EmbeddingModelConstant;
import dev.langchain4j.store.embedding.EmbeddingStoreFactory;
import org.apache.commons.lang3.StringUtils;

View File

@@ -9,6 +9,7 @@ import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.output.Response;
import lombok.Builder;
import lombok.Setter;
import java.util.List;
@@ -32,6 +33,7 @@ public class DifyAiChatModel implements ChatLanguageModel {
private final Double temperature;
private final Long timeOut;
@Setter
private String userName;
@Builder
@@ -54,7 +56,7 @@ public class DifyAiChatModel implements ChatLanguageModel {
@Override
public String generate(String message) {
DifyResult difyResult = this.difyClient.generate(message, this.getUserName());
return difyResult.getAnswer().toString();
return difyResult.getAnswer();
}
@Override
@@ -67,7 +69,7 @@ public class DifyAiChatModel implements ChatLanguageModel {
List<ToolSpecification> toolSpecifications) {
ensureNotEmpty(messages, "messages");
DifyResult difyResult =
this.difyClient.generate(messages.get(0).text(), this.getUserName());
this.difyClient.generate(messages.get(0).toString(), this.getUserName());
System.out.println(difyResult.toString());
if (!isNullOrEmpty(toolSpecifications)) {
@@ -84,12 +86,8 @@ public class DifyAiChatModel implements ChatLanguageModel {
toolSpecification != null ? singletonList(toolSpecification) : null);
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserName() {
return null == userName ? "zhaodongsheng" : userName;
return null == userName ? "admin" : userName;
}
}

View File

@@ -1,5 +1,8 @@
package dev.langchain4j.model.embedding;
import dev.langchain4j.model.embedding.onnx.AbstractInProcessEmbeddingModel;
import dev.langchain4j.model.embedding.onnx.OnnxBertBiEncoder;
import dev.langchain4j.model.embedding.onnx.PoolingMode;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
@@ -9,6 +12,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;
import java.util.concurrent.Executors;
/**
* An embedding model that runs within your Java application's process. Any BERT-based model (e.g.,
@@ -25,6 +29,7 @@ public class S2OnnxEmbeddingModel extends AbstractInProcessEmbeddingModel {
private static volatile String cachedVocabularyPath;
public S2OnnxEmbeddingModel(String pathToModel, String vocabularyPath) {
super(Executors.newSingleThreadExecutor());
if (shouldReloadModel(pathToModel, vocabularyPath)) {
synchronized (S2OnnxEmbeddingModel.class) {
if (shouldReloadModel(pathToModel, vocabularyPath)) {
@@ -61,8 +66,8 @@ public class S2OnnxEmbeddingModel extends AbstractInProcessEmbeddingModel {
static OnnxBertBiEncoder loadFromFileSystem(Path pathToModel, URL vocabularyFile) {
try {
return new OnnxBertBiEncoder(Files.newInputStream(pathToModel), vocabularyFile,
PoolingMode.MEAN);
return new OnnxBertBiEncoder(Files.newInputStream(pathToModel),
vocabularyFile.openStream(), PoolingMode.MEAN);
} catch (IOException e) {
throw new RuntimeException(e);
}

View File

@@ -52,7 +52,7 @@ import static dev.langchain4j.model.openai.InternalOpenAiHelper.toOpenAiMessages
import static dev.langchain4j.model.openai.InternalOpenAiHelper.toOpenAiResponseFormat;
import static dev.langchain4j.model.openai.InternalOpenAiHelper.toTools;
import static dev.langchain4j.model.openai.InternalOpenAiHelper.tokenUsageFrom;
import static dev.langchain4j.model.openai.OpenAiModelName.GPT_3_5_TURBO;
import static dev.langchain4j.model.openai.OpenAiChatModelName.GPT_3_5_TURBO;
import static dev.langchain4j.spi.ServiceHelper.loadFactories;
import static java.time.Duration.ofSeconds;
import static java.util.Collections.emptyList;
@@ -66,7 +66,6 @@ import static java.util.Collections.singletonList;
@Slf4j
public class OpenAiChatModel implements ChatLanguageModel, TokenCountEstimator {
public static final String ZHIPU = "bigmodel";
private final OpenAiClient client;
private final String baseUrl;
private final String modelName;
@@ -111,7 +110,7 @@ public class OpenAiChatModel implements ChatLanguageModel, TokenCountEstimator {
.connectTimeout(timeout).readTimeout(timeout).writeTimeout(timeout).proxy(proxy)
.logRequests(logRequests).logResponses(logResponses).userAgent(DEFAULT_USER_AGENT)
.customHeaders(customHeaders).build();
this.modelName = getOrDefault(modelName, GPT_3_5_TURBO);
this.modelName = getOrDefault(modelName, GPT_3_5_TURBO.name());
this.apiVersion = apiVersion;
this.temperature = getOrDefault(temperature, 0.7);
this.topP = topP;
@@ -130,7 +129,7 @@ public class OpenAiChatModel implements ChatLanguageModel, TokenCountEstimator {
this.strictTools = getOrDefault(strictTools, false);
this.parallelToolCalls = parallelToolCalls;
this.maxRetries = getOrDefault(maxRetries, 3);
this.tokenizer = getOrDefault(tokenizer, OpenAiTokenizer::new);
this.tokenizer = getOrDefault(tokenizer, () -> new OpenAiTokenizer(this.modelName));
this.listeners = listeners == null ? emptyList() : new ArrayList<>(listeners);
}
@@ -192,9 +191,7 @@ public class OpenAiChatModel implements ChatLanguageModel, TokenCountEstimator {
.responseFormat(responseFormat).seed(seed).user(user)
.parallelToolCalls(parallelToolCalls);
if (!(baseUrl.contains(ZHIPU))) {
requestBuilder.temperature(temperature);
}
requestBuilder.temperature(temperature);
if (toolSpecifications != null && !toolSpecifications.isEmpty()) {
requestBuilder.tools(toTools(toolSpecifications, strictTools));

View File

@@ -1,16 +0,0 @@
package dev.langchain4j.model.zhipu;
public enum ChatCompletionModel {
GLM_4("glm-4"), GLM_3_TURBO("glm-3-turbo"), CHATGLM_TURBO("chatglm_turbo");
private final String value;
ChatCompletionModel(String value) {
this.value = value;
}
@Override
public String toString() {
return this.value;
}
}

View File

@@ -1,100 +0,0 @@
package dev.langchain4j.model.zhipu;
import dev.langchain4j.agent.tool.ToolSpecification;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.output.Response;
import dev.langchain4j.model.zhipu.chat.ChatCompletionRequest;
import dev.langchain4j.model.zhipu.chat.ChatCompletionResponse;
import dev.langchain4j.model.zhipu.spi.ZhipuAiChatModelBuilderFactory;
import lombok.Builder;
import java.util.List;
import static dev.langchain4j.internal.RetryUtils.withRetry;
import static dev.langchain4j.internal.Utils.getOrDefault;
import static dev.langchain4j.internal.Utils.isNullOrEmpty;
import static dev.langchain4j.internal.ValidationUtils.ensureNotEmpty;
import static dev.langchain4j.model.zhipu.DefaultZhipuAiHelper.aiMessageFrom;
import static dev.langchain4j.model.zhipu.DefaultZhipuAiHelper.finishReasonFrom;
import static dev.langchain4j.model.zhipu.DefaultZhipuAiHelper.toTools;
import static dev.langchain4j.model.zhipu.DefaultZhipuAiHelper.toZhipuAiMessages;
import static dev.langchain4j.model.zhipu.DefaultZhipuAiHelper.tokenUsageFrom;
import static dev.langchain4j.model.zhipu.chat.ToolChoiceMode.AUTO;
import static dev.langchain4j.spi.ServiceHelper.loadFactories;
import static java.util.Collections.singletonList;
/**
* Represents an ZhipuAi language model with a chat completion interface, such as glm-3-turbo and
* glm-4. You can find description of parameters
* <a href="https://open.bigmodel.cn/dev/api">here</a>.
*/
public class ZhipuAiChatModel implements ChatLanguageModel {
private final String baseUrl;
private final Double temperature;
private final Double topP;
private final String model;
private final Integer maxRetries;
private final Integer maxToken;
private final ZhipuAiClient client;
@Builder
public ZhipuAiChatModel(String baseUrl, String apiKey, Double temperature, Double topP,
String model, Integer maxRetries, Integer maxToken, Boolean logRequests,
Boolean logResponses) {
this.baseUrl = getOrDefault(baseUrl, "https://open.bigmodel.cn/");
this.temperature = getOrDefault(temperature, 0.7);
this.topP = topP;
this.model = getOrDefault(model, ChatCompletionModel.GLM_4.toString());
this.maxRetries = getOrDefault(maxRetries, 3);
this.maxToken = getOrDefault(maxToken, 512);
this.client = ZhipuAiClient.builder().baseUrl(this.baseUrl).apiKey(apiKey)
.logRequests(getOrDefault(logRequests, false))
.logResponses(getOrDefault(logResponses, false)).build();
}
public static ZhipuAiChatModelBuilder builder() {
for (ZhipuAiChatModelBuilderFactory factories : loadFactories(
ZhipuAiChatModelBuilderFactory.class)) {
return factories.get();
}
return new ZhipuAiChatModelBuilder();
}
@Override
public Response<AiMessage> generate(List<ChatMessage> messages) {
return generate(messages, (ToolSpecification) null);
}
@Override
public Response<AiMessage> generate(List<ChatMessage> messages,
List<ToolSpecification> toolSpecifications) {
ensureNotEmpty(messages, "messages");
ChatCompletionRequest.Builder requestBuilder =
ChatCompletionRequest.builder().model(this.model).maxTokens(maxToken).stream(false)
.topP(topP).toolChoice(AUTO).messages(toZhipuAiMessages(messages));
if (!isNullOrEmpty(toolSpecifications)) {
requestBuilder.tools(toTools(toolSpecifications));
}
ChatCompletionResponse response =
withRetry(() -> client.chatCompletion(requestBuilder.build()), maxRetries);
return Response.from(aiMessageFrom(response), tokenUsageFrom(response.getUsage()),
finishReasonFrom(response.getChoices().get(0).getFinishReason()));
}
@Override
public Response<AiMessage> generate(List<ChatMessage> messages,
ToolSpecification toolSpecification) {
return generate(messages,
toolSpecification != null ? singletonList(toolSpecification) : null);
}
public static class ZhipuAiChatModelBuilder {
public ZhipuAiChatModelBuilder() {}
}
}

View File

@@ -1,51 +0,0 @@
package dev.langchain4j.provider;
import com.tencent.supersonic.common.pojo.ChatModelConfig;
import com.tencent.supersonic.common.pojo.EmbeddingModelConfig;
import dev.langchain4j.model.azure.AzureOpenAiChatModel;
import dev.langchain4j.model.azure.AzureOpenAiEmbeddingModel;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.embedding.EmbeddingModel;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
import java.time.Duration;
@Service
public class AzureModelFactory implements ModelFactory, InitializingBean {
public static final String PROVIDER = "AZURE";
public static final String DEFAULT_BASE_URL = "https://your-resource-name.openai.azure.com/";
public static final String DEFAULT_MODEL_NAME = "gpt-35-turbo";
public static final String DEFAULT_EMBEDDING_MODEL_NAME = "text-embedding-ada-002";
@Override
public ChatLanguageModel createChatModel(ChatModelConfig modelConfig) {
AzureOpenAiChatModel.Builder builder = AzureOpenAiChatModel.builder()
.endpoint(modelConfig.getBaseUrl()).apiKey(modelConfig.getApiKey())
.deploymentName(modelConfig.getModelName())
.temperature(modelConfig.getTemperature()).maxRetries(modelConfig.getMaxRetries())
.topP(modelConfig.getTopP())
.timeout(Duration.ofSeconds(
modelConfig.getTimeOut() == null ? 0L : modelConfig.getTimeOut()))
.logRequestsAndResponses(
modelConfig.getLogRequests() != null && modelConfig.getLogResponses());
return builder.build();
}
@Override
public EmbeddingModel createEmbeddingModel(EmbeddingModelConfig embeddingModelConfig) {
AzureOpenAiEmbeddingModel.Builder builder =
AzureOpenAiEmbeddingModel.builder().endpoint(embeddingModelConfig.getBaseUrl())
.apiKey(embeddingModelConfig.getApiKey())
.deploymentName(embeddingModelConfig.getModelName())
.maxRetries(embeddingModelConfig.getMaxRetries())
.logRequestsAndResponses(embeddingModelConfig.getLogRequests() != null
&& embeddingModelConfig.getLogResponses());
return builder.build();
}
@Override
public void afterPropertiesSet() {
ModelProvider.add(PROVIDER, this);
}
}

View File

@@ -1,39 +0,0 @@
package dev.langchain4j.provider;
import com.tencent.supersonic.common.pojo.ChatModelConfig;
import com.tencent.supersonic.common.pojo.EmbeddingModelConfig;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.dashscope.QwenChatModel;
import dev.langchain4j.model.dashscope.QwenEmbeddingModel;
import dev.langchain4j.model.dashscope.QwenModelName;
import dev.langchain4j.model.embedding.EmbeddingModel;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
@Service
public class DashscopeModelFactory implements ModelFactory, InitializingBean {
public static final String PROVIDER = "DASHSCOPE";
public static final String DEFAULT_BASE_URL = "https://dashscope.aliyuncs.com/api/v1";
public static final String DEFAULT_MODEL_NAME = QwenModelName.QWEN_PLUS;
public static final String DEFAULT_EMBEDDING_MODEL_NAME = "text-embedding-v2";
@Override
public ChatLanguageModel createChatModel(ChatModelConfig modelConfig) {
return QwenChatModel.builder().baseUrl(modelConfig.getBaseUrl())
.apiKey(modelConfig.getApiKey()).modelName(modelConfig.getModelName())
.temperature(modelConfig.getTemperature() == null ? 0L
: modelConfig.getTemperature().floatValue())
.topP(modelConfig.getTopP()).enableSearch(modelConfig.getEnableSearch()).build();
}
@Override
public EmbeddingModel createEmbeddingModel(EmbeddingModelConfig embeddingModelConfig) {
return QwenEmbeddingModel.builder().apiKey(embeddingModelConfig.getApiKey())
.modelName(embeddingModelConfig.getModelName()).build();
}
@Override
public void afterPropertiesSet() {
ModelProvider.add(PROVIDER, this);
}
}

View File

@@ -6,7 +6,7 @@ import com.tencent.supersonic.common.util.AESEncryptionUtil;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.dify.DifyAiChatModel;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.zhipu.ZhipuAiEmbeddingModel;
import dev.langchain4j.model.openai.OpenAiEmbeddingModel;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
@@ -27,8 +27,9 @@ public class DifyModelFactory implements ModelFactory, InitializingBean {
@Override
public EmbeddingModel createEmbeddingModel(EmbeddingModelConfig embeddingModelConfig) {
return ZhipuAiEmbeddingModel.builder().baseUrl(embeddingModelConfig.getBaseUrl())
.apiKey(embeddingModelConfig.getApiKey()).model(embeddingModelConfig.getModelName())
return OpenAiEmbeddingModel.builder().baseUrl(embeddingModelConfig.getBaseUrl())
.apiKey(embeddingModelConfig.getApiKey())
.modelName(embeddingModelConfig.getModelName())
.maxRetries(embeddingModelConfig.getMaxRetries())
.logRequests(embeddingModelConfig.getLogRequests())
.logResponses(embeddingModelConfig.getLogResponses()).build();

View File

@@ -1,8 +1,8 @@
package dev.langchain4j.provider;
import dev.langchain4j.model.embedding.AllMiniLmL6V2QuantizedEmbeddingModel;
import dev.langchain4j.model.embedding.BgeSmallZhEmbeddingModel;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.embedding.onnx.allminilml6v2q.AllMiniLmL6V2QuantizedEmbeddingModel;
import dev.langchain4j.model.embedding.onnx.bgesmallzh.BgeSmallZhEmbeddingModel;
import org.springframework.stereotype.Service;
@Service

View File

@@ -1,47 +0,0 @@
package dev.langchain4j.provider;
import com.tencent.supersonic.common.pojo.ChatModelConfig;
import com.tencent.supersonic.common.pojo.EmbeddingModelConfig;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.qianfan.QianfanChatModel;
import dev.langchain4j.model.qianfan.QianfanEmbeddingModel;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
@Service
public class QianfanModelFactory implements ModelFactory, InitializingBean {
public static final String PROVIDER = "QIANFAN";
public static final String DEFAULT_BASE_URL = "https://aip.baidubce.com";
public static final String DEFAULT_MODEL_NAME = "Llama-2-70b-chat";
public static final String DEFAULT_EMBEDDING_MODEL_NAME = "Embedding-V1";
public static final String DEFAULT_ENDPOINT = "llama_2_70b";
@Override
public ChatLanguageModel createChatModel(ChatModelConfig modelConfig) {
return QianfanChatModel.builder().baseUrl(modelConfig.getBaseUrl())
.apiKey(modelConfig.getApiKey()).secretKey(modelConfig.getSecretKey())
.endpoint(modelConfig.getEndpoint()).modelName(modelConfig.getModelName())
.temperature(modelConfig.getTemperature()).topP(modelConfig.getTopP())
.maxRetries(modelConfig.getMaxRetries()).logRequests(modelConfig.getLogRequests())
.logResponses(modelConfig.getLogResponses()).build();
}
@Override
public EmbeddingModel createEmbeddingModel(EmbeddingModelConfig embeddingModelConfig) {
return QianfanEmbeddingModel.builder().baseUrl(embeddingModelConfig.getBaseUrl())
.apiKey(embeddingModelConfig.getApiKey())
.secretKey(embeddingModelConfig.getSecretKey())
.modelName(embeddingModelConfig.getModelName())
.maxRetries(embeddingModelConfig.getMaxRetries())
.logRequests(embeddingModelConfig.getLogRequests())
.logResponses(embeddingModelConfig.getLogResponses()).build();
}
@Override
public void afterPropertiesSet() {
ModelProvider.add(PROVIDER, this);
}
}

View File

@@ -1,45 +0,0 @@
package dev.langchain4j.provider;
import com.tencent.supersonic.common.pojo.ChatModelConfig;
import com.tencent.supersonic.common.pojo.EmbeddingModelConfig;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.zhipu.ChatCompletionModel;
import dev.langchain4j.model.zhipu.ZhipuAiChatModel;
import dev.langchain4j.model.zhipu.ZhipuAiEmbeddingModel;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
import static java.time.Duration.ofSeconds;
@Service
public class ZhipuModelFactory implements ModelFactory, InitializingBean {
public static final String PROVIDER = "ZHIPU";
public static final String DEFAULT_BASE_URL = "https://open.bigmodel.cn/";
public static final String DEFAULT_MODEL_NAME = ChatCompletionModel.GLM_4.toString();
public static final String DEFAULT_EMBEDDING_MODEL_NAME = "embedding-2";
@Override
public ChatLanguageModel createChatModel(ChatModelConfig modelConfig) {
return ZhipuAiChatModel.builder().baseUrl(modelConfig.getBaseUrl())
.apiKey(modelConfig.getApiKey()).model(modelConfig.getModelName())
.temperature(modelConfig.getTemperature()).topP(modelConfig.getTopP())
.maxRetries(modelConfig.getMaxRetries()).logRequests(modelConfig.getLogRequests())
.logResponses(modelConfig.getLogResponses()).build();
}
@Override
public EmbeddingModel createEmbeddingModel(EmbeddingModelConfig embeddingModelConfig) {
return ZhipuAiEmbeddingModel.builder().baseUrl(embeddingModelConfig.getBaseUrl())
.apiKey(embeddingModelConfig.getApiKey()).model(embeddingModelConfig.getModelName())
.maxRetries(embeddingModelConfig.getMaxRetries()).callTimeout(ofSeconds(60))
.connectTimeout(ofSeconds(60)).writeTimeout(ofSeconds(60))
.readTimeout(ofSeconds(60)).logRequests(embeddingModelConfig.getLogRequests())
.logResponses(embeddingModelConfig.getLogResponses()).build();
}
@Override
public void afterPropertiesSet() {
ModelProvider.add(PROVIDER, this);
}
}

View File

@@ -1,21 +0,0 @@
package dev.langchain4j.qianfan.spring;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
class ChatModelProperties {
private String baseUrl;
private String apiKey;
private String secretKey;
private Double temperature;
private Integer maxRetries;
private Double topP;
private String modelName;
private String endpoint;
private String responseFormat;
private Double penaltyScore;
private Boolean logRequests;
private Boolean logResponses;
}

View File

@@ -1,18 +0,0 @@
package dev.langchain4j.qianfan.spring;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
class EmbeddingModelProperties {
private String baseUrl;
private String apiKey;
private String secretKey;
private Integer maxRetries;
private String modelName;
private String endpoint;
private String user;
private Boolean logRequests;
private Boolean logResponses;
}

View File

@@ -1,21 +0,0 @@
package dev.langchain4j.qianfan.spring;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
class LanguageModelProperties {
private String baseUrl;
private String apiKey;
private String secretKey;
private Double temperature;
private Integer maxRetries;
private Integer topK;
private Double topP;
private String modelName;
private String endpoint;
private Double penaltyScore;
private Boolean logRequests;
private Boolean logResponses;
}

View File

@@ -1,29 +0,0 @@
package dev.langchain4j.qianfan.spring;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
@Getter
@Setter
@ConfigurationProperties(prefix = Properties.PREFIX)
public class Properties {
static final String PREFIX = "langchain4j.qianfan";
@NestedConfigurationProperty
ChatModelProperties chatModel;
@NestedConfigurationProperty
ChatModelProperties streamingChatModel;
@NestedConfigurationProperty
LanguageModelProperties languageModel;
@NestedConfigurationProperty
LanguageModelProperties streamingLanguageModel;
@NestedConfigurationProperty
EmbeddingModelProperties embeddingModel;
}

View File

@@ -1,102 +0,0 @@
package dev.langchain4j.qianfan.spring;
import dev.langchain4j.model.qianfan.QianfanChatModel;
import dev.langchain4j.model.qianfan.QianfanEmbeddingModel;
import dev.langchain4j.model.qianfan.QianfanLanguageModel;
import dev.langchain4j.model.qianfan.QianfanStreamingChatModel;
import dev.langchain4j.model.qianfan.QianfanStreamingLanguageModel;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static dev.langchain4j.qianfan.spring.Properties.PREFIX;
@Configuration
@EnableConfigurationProperties(Properties.class)
public class QianfanAutoConfig {
@Bean
@ConditionalOnProperty(PREFIX + ".chat-model.api-key")
QianfanChatModel qianfanChatModel(Properties properties) {
ChatModelProperties chatModelProperties = properties.getChatModel();
return QianfanChatModel.builder().baseUrl(chatModelProperties.getBaseUrl())
.apiKey(chatModelProperties.getApiKey())
.secretKey(chatModelProperties.getSecretKey())
.endpoint(chatModelProperties.getEndpoint())
.penaltyScore(chatModelProperties.getPenaltyScore())
.modelName(chatModelProperties.getModelName())
.temperature(chatModelProperties.getTemperature())
.topP(chatModelProperties.getTopP())
.responseFormat(chatModelProperties.getResponseFormat())
.maxRetries(chatModelProperties.getMaxRetries())
.logRequests(chatModelProperties.getLogRequests())
.logResponses(chatModelProperties.getLogResponses()).build();
}
@Bean
@ConditionalOnProperty(PREFIX + ".streaming-chat-model.api-key")
QianfanStreamingChatModel qianfanStreamingChatModel(Properties properties) {
ChatModelProperties chatModelProperties = properties.getStreamingChatModel();
return QianfanStreamingChatModel.builder().endpoint(chatModelProperties.getEndpoint())
.penaltyScore(chatModelProperties.getPenaltyScore())
.temperature(chatModelProperties.getTemperature())
.topP(chatModelProperties.getTopP()).baseUrl(chatModelProperties.getBaseUrl())
.apiKey(chatModelProperties.getApiKey())
.secretKey(chatModelProperties.getSecretKey())
.modelName(chatModelProperties.getModelName())
.responseFormat(chatModelProperties.getResponseFormat())
.logRequests(chatModelProperties.getLogRequests())
.logResponses(chatModelProperties.getLogResponses()).build();
}
@Bean
@ConditionalOnProperty(PREFIX + ".language-model.api-key")
QianfanLanguageModel qianfanLanguageModel(Properties properties) {
LanguageModelProperties languageModelProperties = properties.getLanguageModel();
return QianfanLanguageModel.builder().endpoint(languageModelProperties.getEndpoint())
.penaltyScore(languageModelProperties.getPenaltyScore())
.topK(languageModelProperties.getTopK()).topP(languageModelProperties.getTopP())
.baseUrl(languageModelProperties.getBaseUrl())
.apiKey(languageModelProperties.getApiKey())
.secretKey(languageModelProperties.getSecretKey())
.modelName(languageModelProperties.getModelName())
.temperature(languageModelProperties.getTemperature())
.maxRetries(languageModelProperties.getMaxRetries())
.logRequests(languageModelProperties.getLogRequests())
.logResponses(languageModelProperties.getLogResponses()).build();
}
@Bean
@ConditionalOnProperty(PREFIX + ".streaming-language-model.api-key")
QianfanStreamingLanguageModel qianfanStreamingLanguageModel(Properties properties) {
LanguageModelProperties languageModelProperties = properties.getStreamingLanguageModel();
return QianfanStreamingLanguageModel.builder()
.endpoint(languageModelProperties.getEndpoint())
.penaltyScore(languageModelProperties.getPenaltyScore())
.topK(languageModelProperties.getTopK()).topP(languageModelProperties.getTopP())
.baseUrl(languageModelProperties.getBaseUrl())
.apiKey(languageModelProperties.getApiKey())
.secretKey(languageModelProperties.getSecretKey())
.modelName(languageModelProperties.getModelName())
.temperature(languageModelProperties.getTemperature())
.maxRetries(languageModelProperties.getMaxRetries())
.logRequests(languageModelProperties.getLogRequests())
.logResponses(languageModelProperties.getLogResponses()).build();
}
@Bean
@ConditionalOnProperty(PREFIX + ".embedding-model.api-key")
QianfanEmbeddingModel qianfanEmbeddingModel(Properties properties) {
EmbeddingModelProperties embeddingModelProperties = properties.getEmbeddingModel();
return QianfanEmbeddingModel.builder().baseUrl(embeddingModelProperties.getBaseUrl())
.endpoint(embeddingModelProperties.getEndpoint())
.apiKey(embeddingModelProperties.getApiKey())
.secretKey(embeddingModelProperties.getSecretKey())
.modelName(embeddingModelProperties.getModelName())
.user(embeddingModelProperties.getUser())
.maxRetries(embeddingModelProperties.getMaxRetries())
.logRequests(embeddingModelProperties.getLogRequests())
.logResponses(embeddingModelProperties.getLogResponses()).build();
}
}

View File

@@ -57,6 +57,7 @@ public class MilvusEmbeddingStore implements EmbeddingStore<TextSegment> {
private final ConsistencyLevelEnum consistencyLevel;
private final boolean retrieveEmbeddingsOnSearch;
private final boolean autoFlushOnInsert;
private final FieldDefinition fieldDefinition;
public MilvusEmbeddingStore(String host, Integer port, String collectionName, Integer dimension,
IndexType indexType, MetricType metricType, String uri, String token, String username,
@@ -78,11 +79,15 @@ public class MilvusEmbeddingStore implements EmbeddingStore<TextSegment> {
this.retrieveEmbeddingsOnSearch = getOrDefault(retrieveEmbeddingsOnSearch, false);
this.autoFlushOnInsert = getOrDefault(autoFlushOnInsert, false);
// Define the field structure for the collection
this.fieldDefinition = new FieldDefinition(ID_FIELD_NAME, TEXT_FIELD_NAME,
METADATA_FIELD_NAME, VECTOR_FIELD_NAME);
if (!hasCollection(this.milvusClient, this.collectionName)) {
createCollection(this.milvusClient, this.collectionName,
createCollection(this.milvusClient, this.collectionName, fieldDefinition,
ensureNotNull(dimension, "dimension"));
createIndex(this.milvusClient, this.collectionName, getOrDefault(indexType, FLAT),
this.metricType);
createIndex(this.milvusClient, this.collectionName, VECTOR_FIELD_NAME,
getOrDefault(indexType, FLAT), this.metricType);
}
loadCollectionInMemory(this.milvusClient, collectionName);
@@ -128,7 +133,7 @@ public class MilvusEmbeddingStore implements EmbeddingStore<TextSegment> {
public EmbeddingSearchResult<TextSegment> search(
EmbeddingSearchRequest embeddingSearchRequest) {
SearchParam searchParam = buildSearchRequest(collectionName,
SearchParam searchParam = buildSearchRequest(collectionName, fieldDefinition,
embeddingSearchRequest.queryEmbedding().vectorAsList(),
embeddingSearchRequest.filter(), embeddingSearchRequest.maxResults(), metricType,
consistencyLevel);
@@ -137,7 +142,7 @@ public class MilvusEmbeddingStore implements EmbeddingStore<TextSegment> {
CollectionOperationsExecutor.search(milvusClient, searchParam);
List<EmbeddingMatch<TextSegment>> matches = toEmbeddingMatches(milvusClient, resultsWrapper,
collectionName, consistencyLevel, retrieveEmbeddingsOnSearch);
collectionName, fieldDefinition, consistencyLevel, retrieveEmbeddingsOnSearch);
List<EmbeddingMatch<TextSegment>> result =
matches.stream().filter(match -> match.score() >= embeddingSearchRequest.minScore())
@@ -226,7 +231,7 @@ public class MilvusEmbeddingStore implements EmbeddingStore<TextSegment> {
@Override
public void removeAll(Filter filter) {
ensureNotNull(filter, "filter");
removeForVector(this.milvusClient, this.collectionName, map(filter));
removeForVector(this.milvusClient, this.collectionName, map(filter, METADATA_FIELD_NAME));
}
/**

View File

@@ -1,19 +0,0 @@
package dev.langchain4j.zhipu.spring;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
class ChatModelProperties {
String baseUrl;
String apiKey;
Double temperature;
Double topP;
String modelName;
Integer maxRetries;
Integer maxToken;
Boolean logRequests;
Boolean logResponses;
}

View File

@@ -1,16 +0,0 @@
package dev.langchain4j.zhipu.spring;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
class EmbeddingModelProperties {
String baseUrl;
String apiKey;
String model;
Integer maxRetries;
Boolean logRequests;
Boolean logResponses;
}

View File

@@ -1,23 +0,0 @@
package dev.langchain4j.zhipu.spring;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
@Getter
@Setter
@ConfigurationProperties(prefix = Properties.PREFIX)
public class Properties {
static final String PREFIX = "langchain4j.zhipu";
@NestedConfigurationProperty
ChatModelProperties chatModel;
@NestedConfigurationProperty
ChatModelProperties streamingChatModel;
@NestedConfigurationProperty
EmbeddingModelProperties embeddingModel;
}

View File

@@ -1,53 +0,0 @@
package dev.langchain4j.zhipu.spring;
import dev.langchain4j.model.zhipu.ZhipuAiChatModel;
import dev.langchain4j.model.zhipu.ZhipuAiEmbeddingModel;
import dev.langchain4j.model.zhipu.ZhipuAiStreamingChatModel;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static dev.langchain4j.zhipu.spring.Properties.PREFIX;
@Configuration
@EnableConfigurationProperties(Properties.class)
public class ZhipuAutoConfig {
@Bean
@ConditionalOnProperty(PREFIX + ".chat-model.api-key")
ZhipuAiChatModel zhipuAiChatModel(Properties properties) {
ChatModelProperties chatModelProperties = properties.getChatModel();
return ZhipuAiChatModel.builder().baseUrl(chatModelProperties.getBaseUrl())
.apiKey(chatModelProperties.getApiKey()).model(chatModelProperties.getModelName())
.temperature(chatModelProperties.getTemperature())
.topP(chatModelProperties.getTopP()).maxRetries(chatModelProperties.getMaxRetries())
.maxToken(chatModelProperties.getMaxToken())
.logRequests(chatModelProperties.getLogRequests())
.logResponses(chatModelProperties.getLogResponses()).build();
}
@Bean
@ConditionalOnProperty(PREFIX + ".streaming-chat-model.api-key")
ZhipuAiStreamingChatModel zhipuStreamingChatModel(Properties properties) {
ChatModelProperties chatModelProperties = properties.getStreamingChatModel();
return ZhipuAiStreamingChatModel.builder().baseUrl(chatModelProperties.getBaseUrl())
.apiKey(chatModelProperties.getApiKey()).model(chatModelProperties.getModelName())
.temperature(chatModelProperties.getTemperature())
.topP(chatModelProperties.getTopP()).maxToken(chatModelProperties.getMaxToken())
.logRequests(chatModelProperties.getLogRequests())
.logResponses(chatModelProperties.getLogResponses()).build();
}
@Bean
@ConditionalOnProperty(PREFIX + ".embedding-model.api-key")
ZhipuAiEmbeddingModel zhipuEmbeddingModel(Properties properties) {
EmbeddingModelProperties embeddingModelProperties = properties.getEmbeddingModel();
return ZhipuAiEmbeddingModel.builder().baseUrl(embeddingModelProperties.getBaseUrl())
.apiKey(embeddingModelProperties.getApiKey())
.model(embeddingModelProperties.getModel())
.maxRetries(embeddingModelProperties.getMaxRetries())
.logRequests(embeddingModelProperties.getLogRequests())
.logResponses(embeddingModelProperties.getLogResponses()).build();
}
}

View File

@@ -2,7 +2,6 @@ package com.tencent.supersonic.common.calcite;
import com.tencent.supersonic.common.pojo.enums.EngineType;
import lombok.extern.slf4j.Slf4j;
import org.apache.calcite.sql.parser.SqlParseException;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
@@ -12,7 +11,7 @@ import java.util.Collections;
class SqlWithMergerTest {
@Test
void test1() throws SqlParseException {
void test1() throws Exception {
String sql1 = "WITH DepartmentVisits AS (\n" + " SELECT department, SUM(pv) AS 总访问次数\n"
+ " FROM t_1\n"
+ " WHERE sys_imp_date >= '2024-09-01' AND sys_imp_date <= '2024-09-29'\n"
@@ -38,7 +37,7 @@ class SqlWithMergerTest {
}
@Test
void test2() throws SqlParseException {
void test2() throws Exception {
String sql1 =
"WITH DepartmentVisits AS (SELECT department, SUM(pv) AS 总访问次数 FROM t_1 WHERE sys_imp_date >= '2024-08-28' "
@@ -65,7 +64,7 @@ class SqlWithMergerTest {
}
@Test
void test3() throws SqlParseException {
void test3() throws Exception {
String sql1 = "SELECT COUNT(*) FROM DepartmentVisits WHERE 总访问次数 > 100 LIMIT 1000";
@@ -89,7 +88,7 @@ class SqlWithMergerTest {
}
@Test
void test4() throws SqlParseException {
void test4() throws Exception {
String sql1 = "SELECT COUNT(*) FROM DepartmentVisits WHERE 总访问次数 > 100";
String sql2 =
@@ -112,7 +111,7 @@ class SqlWithMergerTest {
}
@Test
void test5() throws SqlParseException {
void test5() throws Exception {
String sql1 = "SELECT COUNT(*) FROM Department join Visits WHERE 总访问次数 > 100";
@@ -132,13 +131,13 @@ class SqlWithMergerTest {
"WITH t_1 AS (SELECT `t3`.`sys_imp_date`, `t2`.`department`, `t3`.`s2_pv_uv_statis_pv` AS `pv` "
+ "FROM (SELECT `user_name`, `department` FROM `s2_user_department`) AS `t2` LEFT JOIN "
+ "(SELECT 1 AS `s2_pv_uv_statis_pv`, `imp_date` AS `sys_imp_date`, `user_name` FROM `s2_pv_uv_statis`) "
+ "AS `t3` ON `t2`.`user_name` = `t3`.`user_name`) SELECT COUNT(*) FROM Department INNER JOIN Visits "
+ "AS `t3` ON `t2`.`user_name` = `t3`.`user_name`) SELECT COUNT(*) FROM Department JOIN Visits "
+ "WHERE 总访问次数 > 100");
}
@Test
void test6() throws SqlParseException {
void test6() throws Exception {
String sql1 =
"SELECT COUNT(*) FROM Department join Visits WHERE 总访问次数 > 100 ORDER BY 总访问次数 LIMIT 10";
@@ -159,7 +158,36 @@ class SqlWithMergerTest {
"WITH t_1 AS (SELECT `t3`.`sys_imp_date`, `t2`.`department`, `t3`.`s2_pv_uv_statis_pv` AS `pv` FROM "
+ "(SELECT `user_name`, `department` FROM `s2_user_department`) AS `t2` LEFT JOIN (SELECT 1 AS `s2_pv_uv_statis_pv`,"
+ " `imp_date` AS `sys_imp_date`, `user_name` FROM `s2_pv_uv_statis`) AS `t3` ON `t2`.`user_name` = `t3`.`user_name`) "
+ "SELECT COUNT(*) FROM Department INNER JOIN Visits WHERE 总访问次数 > 100 ORDER BY 总访问次数 LIMIT 10");
+ "SELECT COUNT(*) FROM Department JOIN Visits WHERE 总访问次数 > 100 ORDER BY 总访问次数 LIMIT 10");
}
@Test
void test7() throws Exception {
String sql1 =
"SELECT COUNT(*) FROM Department join Visits WHERE 总访问次数 > 100 AND imp_date >= CURRENT_DATE - "
+ "INTERVAL '1 year' AND sys_imp_date < CURRENT_DATE ORDER"
+ " BY 总访问次数 LIMIT 10";
String sql2 =
"SELECT `t3`.`sys_imp_date`, `t2`.`department`, `t3`.`s2_pv_uv_statis_pv` AS `pv`\n"
+ "FROM\n" + "(SELECT `user_name`, `department`\n" + "FROM\n"
+ "`s2_user_department`) AS `t2`\n"
+ "LEFT JOIN (SELECT 1 AS `s2_pv_uv_statis_pv`, `imp_date` AS `sys_imp_date`, `user_name`\n"
+ "FROM\n"
+ "`s2_pv_uv_statis`) AS `t3` ON `t2`.`user_name` = `t3`.`user_name`";
String mergeSql = SqlMergeWithUtils.mergeWith(EngineType.MYSQL, sql1,
Collections.singletonList(sql2), Collections.singletonList("t_1"));
Assert.assertEquals(format(mergeSql),
"WITH t_1 AS (SELECT `t3`.`sys_imp_date`, `t2`.`department`, `t3`.`s2_pv_uv_statis_pv` AS `pv` FROM "
+ "(SELECT `user_name`, `department` FROM `s2_user_department`) AS `t2` LEFT JOIN (SELECT 1 AS `s2_pv_uv_statis_pv`,"
+ " `imp_date` AS `sys_imp_date`, `user_name` FROM `s2_pv_uv_statis`) AS `t3` ON `t2`.`user_name` = `t3`.`user_name`) "
+ "SELECT COUNT(*) FROM Department JOIN Visits WHERE 总访问次数 > 100 AND imp_date >= "
+ "CURRENT_DATE - INTERVAL '1 year' AND sys_imp_date < CURRENT_DATE ORDER BY 总访问次数 "
+ "LIMIT 10");
}
private static String format(String mergeSql) {

View File

@@ -1,12 +1,8 @@
FROM supersonicbi/supersonic:0.9.10-SNAPSHOT
FROM openjdk:21-jdk-bullseye as base
# Set the working directory in the container
WORKDIR /usr/src/app
# Delete old supersonic installation directory and the symbolic link
RUN rm -rf /usr/src/app/supersonic-standalone-0.9.10-SNAPSHOT
RUN rm -f /usr/src/app/supersonic-standalone-latest
# Argument to pass in the supersonic version at build time
ARG SUPERSONIC_VERSION
@@ -17,6 +13,17 @@ COPY assembly/build/supersonic-standalone-${SUPERSONIC_VERSION}.zip .
RUN unzip supersonic-standalone-${SUPERSONIC_VERSION}.zip && \
rm supersonic-standalone-${SUPERSONIC_VERSION}.zip
FROM openjdk:21-slim
# Set the working directory in the container
WORKDIR /usr/src/app
# Argument to pass in the supersonic version at build time
ARG SUPERSONIC_VERSION
# Copy the supersonic standalone folder into the container
COPY --from=base /usr/src/app/supersonic-standalone-${SUPERSONIC_VERSION} ./supersonic-standalone-${SUPERSONIC_VERSION}
# Create a symbolic link to the supersonic installation directory
RUN ln -s /usr/src/app/supersonic-standalone-${SUPERSONIC_VERSION} /usr/src/app/supersonic-standalone-latest
@@ -27,4 +34,4 @@ WORKDIR /usr/src/app/supersonic-standalone-${SUPERSONIC_VERSION}
EXPOSE 9080
# Command to run the supersonic daemon
RUN chmod +x bin/supersonic-daemon.sh
CMD ["bash", "-c", "bin/supersonic-daemon.sh restart standalone docker && tail -f /dev/null"]
CMD ["bash", "-c", "bin/supersonic-daemon.sh restart standalone ${S2_DB_TYPE} && tail -f /dev/null"]

View File

@@ -2,8 +2,8 @@
# Function to execute the build script
execute_build_script() {
echo "Executing build script: assembly/bin/supersonic-build.sh"
assembly/bin/supersonic-build.sh
echo "Executing build script: sh assembly/bin/supersonic-build.sh"
sh assembly/bin/supersonic-build.sh
}
# Function to build the Docker image

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