Skip to content

Commit adc87e3

Browse files
feat: Supports regex and wildcard comparisons (#4974)
* feat: support `regex` and `wildcard` comparison
1 parent c0d86ad commit adc87e3

File tree

7 files changed

+94
-1
lines changed

7 files changed

+94
-1
lines changed

apps/application/flow/compare/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@
2525
from .lt_compare import *
2626
from .not_contain_compare import *
2727
from .not_equal_compare import *
28+
from .regex_compare import RegexCompare
2829
from .start_with import StartWithCompare
30+
from .wildcard_compare import WildcardCompare
2931

3032
compare_handle_list = [GECompare(), GTCompare(), ContainCompare(), EqualCompare(), LTCompare(), LECompare(),
3133
LenLECompare(), LenGECompare(), LenEqualCompare(), LenGTCompare(), LenLTCompare(),
3234
IsNullCompare(),
3335
IsNotNullCompare(), NotContainCompare(), NotEqualCompare(), IsTrueCompare(), IsNotTrueCompare(), StartWithCompare(),
34-
EndWithCompare()]
36+
EndWithCompare(), RegexCompare(), WildcardCompare()]
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# coding=utf-8
2+
"""
3+
@project: maxkb
4+
@Author:wangliang181230
5+
@file: regex_compare.py
6+
@date:2026/3/30 12:11
7+
@desc:
8+
"""
9+
import re
10+
from typing import List
11+
12+
from application.flow.compare import Compare
13+
from common.cache.mem_cache import MemCache
14+
15+
16+
match_cache = MemCache('regex', {
17+
'TIMEOUT': 3600, # 缓存有效期为 1 小时
18+
'OPTIONS': {
19+
'MAX_ENTRIES': 500, # 最多缓存 500 个条目
20+
'CULL_FREQUENCY': 10, # 达到上限时,删除约 1/10 的缓存
21+
},
22+
})
23+
24+
25+
def compile_and_cache(regex):
26+
match = match_cache.get(regex)
27+
if not match:
28+
match = re.compile(regex).match
29+
match_cache.set(regex, match)
30+
return match
31+
32+
class RegexCompare(Compare):
33+
34+
def support(self, node_id, fields: List[str], source_value, compare, target_value):
35+
if compare == 'regex':
36+
return True
37+
38+
def compare(self, source_value, compare, target_value):
39+
match = compile_and_cache(str(target_value))
40+
return bool(match(str(source_value)))
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# coding=utf-8
2+
"""
3+
@project: maxkb
4+
@Author:wangliang181230
5+
@file: wildcard_compare.py
6+
@date:2026/3/30 12:11
7+
@desc:
8+
"""
9+
import fnmatch
10+
import re
11+
from typing import List
12+
13+
from application.flow.compare import Compare
14+
from common.cache.mem_cache import MemCache
15+
16+
17+
match_cache = MemCache('wildcard_to_regex', {
18+
'TIMEOUT': 3600, # 缓存有效期为 1 小时
19+
'OPTIONS': {
20+
'MAX_ENTRIES': 500, # 最多缓存 500 个条目
21+
'CULL_FREQUENCY': 10, # 达到上限时,删除约 1/10 的缓存
22+
},
23+
})
24+
25+
26+
def translate_and_compile_and_cache(wildcard):
27+
match = match_cache.get(wildcard)
28+
if not match:
29+
regex = fnmatch.translate(wildcard)
30+
match = re.compile(regex).match
31+
match_cache.set(wildcard, match)
32+
return match
33+
34+
class WildcardCompare(Compare):
35+
36+
def support(self, node_id, fields: List[str], source_value, compare, target_value):
37+
if compare == 'wildcard':
38+
return True
39+
40+
def compare(self, source_value, compare, target_value):
41+
# 转成正则,性能更高
42+
match = translate_and_compile_and_cache(str(target_value))
43+
return bool(match(str(source_value)))

ui/src/locales/lang/en-US/workflow.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,8 @@ You are a master of problem optimization, adept at accurately inferring user int
538538
len_lt: 'Length less than',
539539
is_true: 'Is true',
540540
is_not_true: 'Is not true',
541+
regex: 'Regex matching',
542+
wildcard: 'Wildcard matching',
541543
},
542544
SystemPromptPlaceholder: 'System Prompt, can reference variables in the system, such as',
543545
UserPromptPlaceholder: 'User Prompt, can reference variables in the system, such as',

ui/src/locales/lang/zh-CN/workflow.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,8 @@ export default {
529529
len_lt: '长度小于',
530530
is_true: '为真',
531531
is_not_true: '不为真',
532+
regex: '正则匹配',
533+
wildcard: '通配符匹配',
532534
},
533535
SystemPromptPlaceholder: '系统提示词,可以引用系统中的变量:如',
534536
UserPromptPlaceholder: '用户提示词,可以引用系统中的变量:如',

ui/src/locales/lang/zh-Hant/workflow.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,8 @@ export default {
523523
len_lt: '長度小於',
524524
is_true: '為真',
525525
is_not_true: '不為真',
526+
regex: '正則匹配',
527+
wildcard: '通配符匹配',
526528
},
527529
SystemPromptPlaceholder: '系統提示詞,可以引用系統中的變量:如',
528530
UserPromptPlaceholder: '用戶提示詞,可以引用系統中的變量:如',

ui/src/workflow/common/data.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,6 +1135,8 @@ export const compareList = [
11351135
{ value: 'is_not_true', label: t('workflow.compare.is_not_true') },
11361136
{ value: 'start_with', label: 'startWith' },
11371137
{ value: 'end_with', label: 'endWith' },
1138+
{ value: 'regex', label: t('workflow.compare.regex') },
1139+
{ value: 'wildcard', label: t('workflow.compare.wildcard') },
11381140
]
11391141
export const nodeDict: any = {
11401142
[WorkflowType.AiChat]: aiChatNode,

0 commit comments

Comments
 (0)