Skip to content

Commit

Permalink
All changes for V7 release (#41)
Browse files Browse the repository at this point in the history
* Generics for Slot/SlotMatch and make Slot an interface (#34)

* cleanup logging in InkBot class

* add generic type to Slot and SlotMatch classes and make Slot an interface

also some harmless code cleanup

* use helper method to capture wildcard where needed

* fix some typos

* add type param javadoc to SlotMatch class

* travis ci (#5)

* add .travis.yml

* add README badges

* fix travis ci setup (#6)

* change to JDK 8 (javadoc task is removed in java 11)

* add jacocoTestReport settings

* Updated version number.

* Upgrade blade ink 0.7.3 (#29)

* upgrade blade-ink 0.7.1 and update code using ExternalFunction (only 1
place)

* bump to blade-ink 0.7.3

* travis ci (#5)

* add .travis.yml

* add README badges

* fix travis ci setup (#6)

* change to JDK 8 (javadoc task is removed in java 11)

* add jacocoTestReport settings

* Upgrade blade ink 0.7.3 (#1)

* bump to blade-ink 0.7.3

* make CompoundIntentMatcher merge the scores when both matchers fail (#33)

* make CompoundIntentMatcher merge the scores when both matchers fail

- previously it would only take the second matchers scores
- this caused a TemplatedIntentMatcher (which had no scores) to override
the scores of a MachineLearningIntentMatcher
- wasn't an issue before v6 of mutters because the
TemplatedIntentMatchers never use to set any scores

* tweak to only combine the scores if needed

- i.e. if one set of scores is empty just returns the other

* let user define no match merging strategy in CompoundIntentMatcher

* travis ci (#5)

* add .travis.yml

* add README badges

* fix travis ci setup (#6)

* change to JDK 8 (javadoc task is removed in java 11)

* add jacocoTestReport settings

* add test for composing > 2 intent matchers with custom merge strategy

* Make Slot#match method return Optional<SlotMatch> rather than nullable SlotMatch (#38)

reduces null logic

* add constructor overloads with List parameters as alternative to arrays (#39)

* add constructor overloads with List parameters as alternative to arrays

* fix bad import

* tests for CompoundIntentMatcher static factories

* tests for CompoundSlot static factories

* create tests for CustomSlot/CustomSlotWithDefaultValue constructors and toString

* tests for FuzzySlot constructors and toString

* create common implementations of DefaultValueSlot (#36)

* create common implementations of DefaultValueSlot

* create defaults for long/double/localtime too

* tests for DefaultValueSlot default implementations

* override the Slot#getName method in AbstractSlot (#37)

* override the Slot#getName method in AbstractSlot

- since it is always implemented in the same way
- also some other minor changes (e.g. to Javadocs)

* make getName, equals, hashcode final in AbstractSlot

* tests for AbstractSlot methods

i.e. getName, equals, hashCode, toString

* Added method to return expected slot names + tests. (#40)

Co-authored-by: Will Molloy <[email protected]>
  • Loading branch information
rabidgremlin and will-molloy authored Feb 4, 2020
1 parent 5065e09 commit a9600cb
Show file tree
Hide file tree
Showing 85 changed files with 1,966 additions and 721 deletions.
17 changes: 17 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
language: java

before_install:
- chmod +x gradlew
# Amazon JDK -- https://docs.aws.amazon.com/corretto/latest/corretto-8-ug/downloads-list.html
- wget https://github.com/sormuras/bach/raw/master/install-jdk.sh
- source install-jdk.sh --url https://corretto.aws/downloads/latest/amazon-corretto-8-x64-linux-jdk.tar.gz
- echo JAVA_HOME = ${JAVA_HOME}
- java -version

script:
- ls -laRh
- printenv
- ./gradlew projects clean build jacocoTestReport --no-daemon --refresh-dependencies

after_success:
- bash <(curl -s https://codecov.io/bash)
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
[![Build Status](https://travis-ci.com/rabidgremlin/mutters.svg?branch=master)](https://travis-ci.com/rabidgremlin/mutters)
[![codecov](https://codecov.io/gh/rabidgremlin/mutters/branch/master/graph/badge.svg)](https://codecov.io/gh/rabidgremlin/mutters)
[![GitHub license](https://img.shields.io/github/license/rabidgremlin/mutters.svg)](https://github.com/rabidgremlin/mutters/blob/master/LICENSE)

# Mutters
A Java framework for building bot brains. Heavily inspired by Amazon Echo's natural language understanding model.

Expand Down
10 changes: 4 additions & 6 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
buildscript {
repositories {
//jcenter()
mavenCentral()
}
}

project.ext{
ext {
// plugin versions
pegdownDocletVersion = '1.3'
gradleDownloadTaskVersion = '4.0.0'
spotlessVersion = '3.25.0'

//dependencies versions
// dependencies versions
commonsLang3Version = '3.9'
slf4jVersion = '1.7.28'
junitVersion = '4.12'
Expand All @@ -20,8 +19,7 @@ project.ext{
jFastTextVersion = '0.4'
commonsIoVersion = '2.6'
mockitoVersion = '3.1.0'
bladeInkVersion = '0.6.0'
bladeInkVersion = '0.7.3'
openNlpVersion = '1.9.1'
nattyVersion = '0.13'

}
}
16 changes: 12 additions & 4 deletions buildpublish.gradle
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
buildscript {
repositories {
//jcenter()
mavenCentral()
}
dependencies {
classpath "ch.raffael.pegdown-doclet:pegdown-doclet:$rootProject.ext.pegdownDocletVersion"
classpath "com.diffplug.spotless:spotless-plugin-gradle:$rootProject.ext.spotlessVersion"
classpath "ch.raffael.pegdown-doclet:pegdown-doclet:$pegdownDocletVersion"
classpath "com.diffplug.spotless:spotless-plugin-gradle:$spotlessVersion"
}
}

Expand Down Expand Up @@ -106,4 +105,13 @@ tasks.withType(FindBugs) {
xml.enabled = false
html.enabled = true
}
}
}

apply plugin: 'jacoco'
jacocoTestReport {
reports {
xml.enabled = true
html.enabled = true
csv.enabled = false
}
}
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
version=6.0.0
version=7.0.0-SNAPSHOT

# These are place holder values. Real values should be set in user's home gradle.properties
# and are only needed when signing and uploading to central maven repo

ossrhUsername=null
ossrhPassword=null
ossrhPassword=null
15 changes: 7 additions & 8 deletions mutters-core/build.gradle
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
buildscript {
repositories {
//jcenter()
mavenCentral()
}
dependencies {
classpath "ch.raffael.pegdown-doclet:pegdown-doclet:$rootProject.ext.pegdownDocletVersion"
classpath "com.diffplug.spotless:spotless-plugin-gradle:$rootProject.ext.spotlessVersion"
classpath "ch.raffael.pegdown-doclet:pegdown-doclet:$pegdownDocletVersion"
classpath "com.diffplug.spotless:spotless-plugin-gradle:$spotlessVersion"
}
}

Expand All @@ -16,12 +15,12 @@ repositories {
}

dependencies {
compile "org.apache.commons:commons-lang3:$rootProject.ext.commonsLang3Version"
compile "org.slf4j:slf4j-api:$rootProject.ext.slf4jVersion"
compile "org.apache.commons:commons-lang3:$commonsLang3Version"
compile "org.slf4j:slf4j-api:$slf4jVersion"

testCompile "junit:junit:$rootProject.ext.junitVersion"
testCompile "org.slf4j:slf4j-simple:$rootProject.ext.slf4jVersion"
testCompile "org.hamcrest:hamcrest-all:$rootProject.ext.hamcrestAllVersion"
testCompile "junit:junit:$junitVersion"
testCompile "org.slf4j:slf4j-simple:$slf4jVersion"
testCompile "org.hamcrest:hamcrest-all:$hamcrestAllVersion"
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/* Licensed under Apache-2.0 */
package com.rabidgremlin.mutters.core;

import java.util.Objects;

/**
* Base class for creating slots. Slots are used to extract data from a user's
* utterance.
*
* @author rabidgremlin
* @author wilmol
*/
public abstract class AbstractSlot<T> implements Slot<T>
{
private final String name;

protected AbstractSlot(String name)
{
this.name = Objects.requireNonNull(name);
}

@Override
public final String getName()
{
return name;
}

@Override
public final boolean equals(Object o)
{
// HACK HACK assumes name match means equals. need to do this for SlotMatches
// list but is dog dog ugly
if (this == o)
{
return true;
}
if (o == null || getClass() != o.getClass())
{
return false;
}
Slot<?> that = (Slot<?>) o;
return Objects.equals(getName(), that.getName());
}

@Override
public final int hashCode()
{
// HACK HACK assumes name match means equals. need to do this for SlotMatches
// list but is dog dog ugly
return Objects.hash(getName());
}

@Override
public String toString()
{
return getClass().getSimpleName() + " [name=" + name + "]";
}
}
Original file line number Diff line number Diff line change
@@ -1,57 +1,161 @@
/* Licensed under Apache-2.0 */
package com.rabidgremlin.mutters.core;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.BinaryOperator;

/**
* An IntentMatcher that is a combination of two other intent matchers. Useful
* for instance for combining a TemplatedIntentMatcher and an implementation of
* an AbstractMachineLearningIntentMatcher. Class will stop on the first match
* returned by a matcher.
*
* @author rabidgremlin
*
* @author rabidgremlin
* @author wilmol
* @see #compose(IntentMatcher...)
* @see #compose(BinaryOperator, IntentMatcher...)
*/
public class CompoundIntentMatcher implements IntentMatcher
{
/** The first matcher. */
private IntentMatcher firstMatcher;
/**
* The first intent matcher.
*/
private final IntentMatcher firstMatcher;

/** The second matcher. */
private IntentMatcher secondMatcher;
/**
* The second intent matcher.
*/
private final IntentMatcher secondMatcher;

/**
* Strategy for merging {@link MatcherScores} if both matchers fail to match.
*/
private final BinaryOperator<MatcherScores> noMatchScoreMerger;

/**
* Constructor for the class.
*
* <p>
* Uses default no match score merging strategy which returns no scores.
*
* @param firstMatcher The first intent matcher.
* @param secondMatcher The second intent matcher.
*/
public CompoundIntentMatcher(IntentMatcher firstMatcher, IntentMatcher secondMatcher)
{
this(firstMatcher, secondMatcher, (a, b) -> new MatcherScores());
}

/**
* Constructor for the class.
*
* @param firstMatcher The first intent matcher.
* @param secondMatcher The second intent matcher.
* @param noMatchScoreMerger Strategy for merging {@link MatcherScores} if both
* matchers fail to match.
*/
public CompoundIntentMatcher(IntentMatcher firstMatcher, IntentMatcher secondMatcher,
BinaryOperator<MatcherScores> noMatchScoreMerger)
{
this.firstMatcher = Objects.requireNonNull(firstMatcher);
this.secondMatcher = Objects.requireNonNull(secondMatcher);
this.noMatchScoreMerger = Objects.requireNonNull(noMatchScoreMerger);
}

/*
* (non-Javadoc)
*
*
* @see com.rabidgremlin.mutters.core.IntentMatcher#match(String utterance,
* Context context, Set<String> expectedIntents)
*
*
*/
@Override
public IntentMatch match(String utterance, Context context, Set<String> expectedIntents)
{
// see if we can find match in first matcher
IntentMatch match = firstMatcher.match(utterance, context, expectedIntents);
IntentMatch firstMatch = firstMatcher.match(utterance, context, expectedIntents);

// no ? try second one
if (!match.matched())
if (firstMatch.matched())
{
return firstMatch;
}
else
{
match = secondMatcher.match(utterance, context, expectedIntents);
// no ? try second one
IntentMatch secondMatch = secondMatcher.match(utterance, context, expectedIntents);
if (secondMatch.matched())
{
return secondMatch;
}
else
{
// neither matcher matched, combine their scores
MatcherScores combinedScores = noMatchScoreMerger.apply(firstMatch.getMatcherScores(),
secondMatch.getMatcherScores());
return new NoIntentMatch(utterance, combinedScores);
}
}
}

return match;
/**
* Static factory for composing {@link IntentMatcher}s using
* {@link CompoundIntentMatcher}.
* <p>
* Uses default no match score merging strategy which returns no scores.
*
* @param intentMatchers intent matchers to compose
* @return composed intent matcher
*/
public static IntentMatcher compose(List<IntentMatcher> intentMatchers)
{
return compose((a, b) -> new MatcherScores(), intentMatchers);
}

/**
* Static factory for composing {@link IntentMatcher}s using
* {@link CompoundIntentMatcher}.
* <p>
* Uses default no match score merging strategy which returns no scores.
*
* @param intentMatchers intent matchers to compose
* @return composed intent matcher
*/
public static IntentMatcher compose(IntentMatcher... intentMatchers)
{
return compose(Arrays.asList(intentMatchers));
}

/**
* Static factory for composing {@link IntentMatcher}s using
* {@link CompoundIntentMatcher}.
*
* @param noMatchScoreMerger Strategy for merging {@link MatcherScores} if no
* matchers match.
* @param intentMatchers intent matchers to compose
* @return composed intent matcher
*/
public static IntentMatcher compose(BinaryOperator<MatcherScores> noMatchScoreMerger,
List<IntentMatcher> intentMatchers)
{
return intentMatchers.stream()
.reduce(
(firstMatcher, secondMatcher) -> new CompoundIntentMatcher(firstMatcher, secondMatcher, noMatchScoreMerger))
.orElseThrow(() -> new IllegalArgumentException("No intent matchers provided."));
}

/**
* Static factory for composing {@link IntentMatcher}s using
* {@link CompoundIntentMatcher}.
*
* @param noMatchScoreMerger Strategy for merging {@link MatcherScores} if no
* matchers match.
* @param intentMatchers intent matchers to compose
* @return composed intent matcher
*/
public static IntentMatcher compose(BinaryOperator<MatcherScores> noMatchScoreMerger, IntentMatcher... intentMatchers)
{
return compose(noMatchScoreMerger, Arrays.asList(intentMatchers));
}
}
Loading

0 comments on commit a9600cb

Please sign in to comment.