Time/FR: don't parse 'a un'

Summary:
In French, the form "at hh" is not valid (it requires an hour indicator).
This fixes false positives such as in "John a un rendez-vous."

Fixes https://github.com/wit-ai/wit/issues/666.

Reviewed By: JonCoens

Differential Revision: D5530713

fbshipit-source-id: ecee1e5
This commit is contained in:
Julien Odent 2017-08-01 08:23:11 -07:00 committed by Facebook Github Bot
parent 8710b9d59b
commit ef461c3133
5 changed files with 530 additions and 552 deletions

File diff suppressed because it is too large Load Diff

View File

@ -10,6 +10,7 @@
module Duckling.Time.FR.Corpus
( corpus
, negativeCorpus
) where
import Data.String
@ -17,14 +18,21 @@ import Prelude
import Duckling.Lang
import Duckling.Resolve
import Duckling.Testing.Types hiding (examples)
import Duckling.Time.Corpus
import Duckling.Time.Types hiding (Month)
import Duckling.TimeGrain.Types hiding (add)
import Duckling.Testing.Types hiding (examples)
corpus :: Corpus
corpus = (testContext {lang = FR}, allExamples)
negativeCorpus :: NegativeCorpus
negativeCorpus = (testContext {lang = FR}, examples)
where
examples =
[ "Ana a un court de tennis"
]
allExamples :: [Example]
allExamples = concat
[ examples (datetime (2013, 2, 12, 4, 30, 0) Second)

View File

@ -718,7 +718,7 @@ ruleHourofdayInteger :: Rule
ruleHourofdayInteger = Rule
{ name = "<hour-of-day> <integer> (as relative minutes)"
, pattern =
[ Predicate isAnHourOfDay
[ Predicate $ liftM2 (&&) isAnHourOfDay hasNoDirection
, Predicate $ isIntegerBetween 1 59
]
, prod = \tokens -> case tokens of
@ -1587,11 +1587,10 @@ ruleVersTimeofday = Rule
{ name = "à|vers <time-of-day>"
, pattern =
[ regex "(vers|autour de|(a|\x00e0) environ|aux alentours de|(a|\x00e0))"
, Predicate isATimeOfDay
, Predicate $ liftM2 (&&) isATimeOfDay isNotLatent
]
, prod = \tokens -> case tokens of
(_:Token Time td:_) ->
tt $ notLatent td
(_:x:_) -> Just x
_ -> Nothing
}
@ -1667,7 +1666,7 @@ ruleLeCycleAprssuivantTime :: Rule
ruleLeCycleAprssuivantTime = Rule
{ name = "le <cycle> après|suivant <time>"
, pattern =
[ regex "l[ea']? ?"
[ regex "l[ea']?"
, dimension TimeGrain
, regex "suivante?|apr(e|\x00e8|\x00e9)s"
, dimension Time
@ -1689,7 +1688,12 @@ ruleEntreDdEtDdMonthinterval = Rule
, Predicate isAMonth
]
, prod = \tokens -> case tokens of
(_:Token RegexMatch (GroupMatch (m1:_)):_:Token RegexMatch (GroupMatch (m2:_)):Token Time td:_) -> do
(_:
Token RegexMatch (GroupMatch (m1:_)):
_:
Token RegexMatch (GroupMatch (m2:_)):
Token Time td:
_) -> do
n1 <- parseInt m1
n2 <- parseInt m2
from <- intersect (dayOfMonth n1) td
@ -1742,7 +1746,7 @@ ruleDudansLePartofday :: Rule
ruleDudansLePartofday = Rule
{ name = "du|dans le <part-of-day>"
, pattern =
[ regex "du|dans l[ae']? ?|au|en|l[ae' ]|d(\x00e8|e)s l?[ae']? ?"
[ regex "du|dans l[ae']? ?|au|en|l[ae' ]|d(\x00e8|e)s l?[ae']?"
, Predicate isAPartOfDay
]
, prod = \tokens -> case tokens of
@ -1787,7 +1791,7 @@ ruleMaintenant :: Rule
ruleMaintenant = Rule
{ name = "maintenant"
, pattern =
[ regex "maintenant|(tout de suite)"
[ regex "maintenant|tout de suite"
]
, prod = \_ -> tt $ cycleNth TG.Second 0
}
@ -1811,7 +1815,7 @@ ruleLeCycleAvantprcdentTime :: Rule
ruleLeCycleAvantprcdentTime = Rule
{ name = "le <cycle> avant|précédent <time>"
, pattern =
[ regex "l[ea']? ?"
[ regex "l[ea']?"
, dimension TimeGrain
, regex "avant|pr(\x00e9|e)c(\x00e9|e)dent"
, dimension Time
@ -1826,7 +1830,7 @@ ruleDayOfMonthPremier :: Rule
ruleDayOfMonthPremier = Rule
{ name = "day of month (premier)"
, pattern =
[ regex "premier|prem\\.?|1er|1 er"
[ regex "premier|prem\\.?|1 ?er"
]
, prod = \_ -> tt $ dayOfMonth 1
}

View File

@ -12,10 +12,10 @@
module Duckling.Time.Helpers
( -- Patterns
isADayOfWeek, isAMonth, isAnHourOfDay, isAPartOfDay, isATimeOfDay
, isDOMInteger, isDOMOrdinal, isDOMValue, isGrain, isGrainFinerThan
, isGrainOfTime, isIntegerBetween, isNotLatent, isOrdinalBetween
, isMidnightOrNoon, isNumeralSafeToUse
hasNoDirection, isADayOfWeek, isAMonth, isAnHourOfDay, isAPartOfDay
, isATimeOfDay, isDOMInteger, isDOMOrdinal, isDOMValue, isGrain
, isGrainFinerThan, isGrainOfTime, isIntegerBetween, isNotLatent
, isOrdinalBetween, isMidnightOrNoon, isNumeralSafeToUse
-- Production
, cycleLastOf, cycleN, cycleNth, cycleNthAfter, dayOfMonth, dayOfWeek
, daysOfWeekOfMonth, durationAfter, durationAgo, durationBefore, form, hour
@ -275,6 +275,10 @@ isNotLatent :: Predicate
isNotLatent (Token Time td) = not $ TTime.latent td
isNotLatent _ = False
hasNoDirection :: Predicate
hasNoDirection (Token Time td) = isNothing $ TTime.direction td
hasNoDirection _ = False
isIntegerBetween :: Int -> Int -> Predicate
isIntegerBetween low high (Token Numeral nd) =
TNumeral.isIntegerBetween (TNumeral.value nd) low high

View File

@ -20,4 +20,5 @@ import Duckling.Time.FR.Corpus
tests :: TestTree
tests = testGroup "FR Tests"
[ makeCorpusTest [This Time] corpus
, makeNegativeCorpusTest [This Time] negativeCorpus
]