You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GATE JAPE语法纯否定匹配规则未按预期命中问题排查

问题背景

我在编写JAPE语法,需要关联匹配三类注解:地名词典标注的Anatomy解剖结构注解、前置流程标注的Numeric数值注解、地名词典标注的Units单位注解,计划通过针对特定注解的纯否定规则,拦截不符合要求的匹配模式。

最初编写的JAPE语法如下:

Phase: Test
Input: Anatomy Numeric Units Lookup
Options: control=Appelt negationGrouping=false


Rule: test_1
(

    ( {Anatomy.minorType=="sinus_of_valsalva"} ):context

// 拦截逻辑:context和value之间最多允许出现2个注解,这些注解不能是minorType为body_surface_area的Lookup注解,也不能是minorType为cm的Units注解
    ( {!Lookup.minorType=="body_surface_area",
       !Units.minorType=="cm"} )[0,2]

    ( {Numeric} ):value 

    ( {Units.minorType=="cm"} ):unit

):test
--> 
:test
{
    gate.AnnotationSet matchedVar    =(gate.AnnotationSet) bindings.get("value");
    gate.AnnotationSet matchedcontext=(gate.AnnotationSet) bindings.get("context");
    gate.AnnotationSet matchedunit   =(gate.AnnotationSet) bindings.get("unit");
    gate.AnnotationSet matchedAnns   =(gate.AnnotationSet) bindings.get("test");    
    gate.FeatureMap newFeatures      = Factory.newFeatureMap();
    newFeatures.put("vartype","test");
    newFeatures.put("varValue", stringFor(doc, matchedVar));
    newFeatures.put("context", stringFor(doc, matchedcontext));
    if(matchedunit != null) {
        newFeatures.put("unit", stringFor(doc, matchedunit));
    }else {
        newFeatures.put("unit", null);
    }
    outputAS.add(matchedAnns.firstNode(),matchedAnns.lastNode(),"test", newFeatures);
}
测试用例表现

我在以下测试用例运行规则时出现了不符合预期的结果:

  • 文本:SoV 75 cm
    预期输出:{vartype=test, context=SoV, value=75, unit=cm},实际可正常匹配
  • 文本:SoV other unimportant text 75 cm
    预期输出:{vartype=test, context=SoV, value=75, unit=cm},实际可正常匹配
  • 文本:SoV body surface area 75 cm
    预期结果:被拦截无匹配,实际可正常拦截
  • 文本:SoV is 75 cm
    预期结果:正常匹配,该用例始终无法命中,原因不明

GATE Developer GUI运行截图

根据我之前的理解,{!Annotation X}这类纯否定写法的作用是匹配所有满足否定条件的输入注解,相关说明如下:

仅包含{!Lookup}这类约束的规则实际效果可能和预期存在差异。任何仅包含否定约束的{...}匹配块,大致等价于对所有Input中声明的注解类型做或匹配,每个类型分支带上对应的否定约束:即等价于({A, !Lookup.....} | {B, !Lookup.....} | ....)的形式。

我怀疑自己对JAPE纯否定规则的核心逻辑存在理解偏差,需要定位问题原因。

可复现问题的完整JAPE代码

以下代码不需要依赖额外地名词典即可完整复现问题,所有标注逻辑都已内置:

Phase: AnatomyPhase
Input: Token
Options: control=Appelt  negationGrouping=false

Rule: anatomy
(
    {Token.string == "SoV"} 
    
):anatomy
-->
:anatomy.Anatomy = {majorType = "aorta", minorType="sinus_of_valsalva", language="en"}


Phase: UnitsPhase
Input: Token
Options: control=Appelt  negationGrouping=false

Rule: units
(
    {Token.string == "cm"} 
    
):units
-->
:units.Units = {majorType = "length", minorType="cm", language="en"}

Rule: units_2
(
    {Token.string == "is"} 
    
):units
-->
:units.Units = {majorType = "assertion", minorType="positive_assertion", language="en"}


Phase: LookupPhase
Input: Token
Options: control=Appelt  negationGrouping=false

Rule: lookup
Priority: 100
(
    {Token.string == "body"}{Token.string == "surface"}{Token.string == "area"}
    
):lookup
-->
:lookup.Lookup = {majorType = "body_surface_area", minorType="body_surface_area", language="en"}


Phase: TagNumeric
Input: Token SpaceToken Split Lookup
Options: control=Appelt  negationGrouping=false

Rule: double_tagger
Priority: 100
(
    {Token.kind == "number", Token notWithin Lookup} 
    ({SpaceToken, !Split})[0,1] 
    {Token.string ==~ "[.,]"} 
    {Token.kind == "number", Token notWithin Lookup}
    
):double_tagger
-->
:double_tagger.Numeric = {type = "double"}

Rule: int_tagger
Priority: 99
(
    {Token.kind == "number", Token notWithin Lookup}
):int_tagger
-->
:int_tagger.Numeric = {type = "integer"}



Phase: Test
Input: Lookup Numeric Units Anatomy
Options: control=Appelt negationGrouping=false


Rule: test_1
(
    ( {Anatomy.minorType=="sinus_of_valsalva"} ):context
    ( {!Lookup.minorType=="body_surface_area",
       !Units.minorType=="cm"} )[0,2]
    ( {Numeric} ):value 
    ( {Units.minorType=="cm"} ):unit

):test_var 
--> 
:test_var
{
    gate.AnnotationSet matchedVar    =(gate.AnnotationSet) bindings.get("value");
    gate.AnnotationSet matchedcontext=(gate.AnnotationSet) bindings.get("context");
    gate.AnnotationSet matchedunit   =(gate.AnnotationSet) bindings.get("unit");
    gate.AnnotationSet matchedAnns   =(gate.AnnotationSet) bindings.get("test_var");    
    gate.FeatureMap newFeatures      = Factory.newFeatureMap();
    newFeatures.put("varType","test_var");
    newFeatures.put("varValue", stringFor(doc, matchedVar));
    newFeatures.put("context", stringFor(doc, matchedcontext));
    if(matchedunit != null) {
        newFeatures.put("unit", stringFor(doc, matchedunit));
    }else {
        newFeatures.put("unit", null);
    }
    outputAS.add(matchedAnns.firstNode(),matchedAnns.lastNode(),"test", newFeatures);
}

内容的提问来源于stack exchange,提问作者Nicholas Sunderland

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 17:15:44