Natural Language Processing

Understanding Dates and Times in Natural Language

One of the more challenging aspects of understanding natural language is dealing with date and time expressions. There are many different ways a user could refer to a specific date and time. They might say “Next Tuesday at 4pm”, they might give a specific date in any of several different forms, they might refer to other time ranges “First Tuesday in January 2012 at 4pm” etc.

Whilst my natural language engine can’t understand every possible date time expression (e.g. the second Wednesday after the first Friday in May 2010) it does handle a huge variety.

Clearly the .NET provided DateTime class is wholly inadequate to express the kinds of date/time expressions your users might enter. To deal with that I’ve created my own classes that represent items like a specific Time of day, a DateTimeRange, a DateTimeRangeCollection, …

TemporalSets are the most general result of parsing a datetime expression since they can represent any date time expression. Broadly they split into two categories: finite and infinite expressions. “Tuesday at 5pm” is an infinite time expression. “Tuesday at 5pm January 2012″ is a finite time expression. Sometimes you will want to accept an infinite expression and interpret it as a future or past finite occurrence. For that I have a MergePreferPast and MergePreferFuture method that operate on a TemporalSetCollection. The demonstration code on BitBucket shows this in action.

TemporalSets also have unique capabilities around both providing query expressions (for database searches) and generative expressions (for adding dates to a calendar).

If you’d like to try out the latest date / time expression parsing code in my Natural Language Engine you can visit the demo and try typing “define” followed by a date / time expression.

If you find any expressions that ought to work, please feel free to email or Tweet them to me.

Here’s a sample session:

define june 23rd 2010
Absolute:[DATETIMERANGE 6/23/2010 at 12:00 AM to 6/23/2010 at 11:59 PM]

define January 19th
Future:[Thursday 1/19/2012], [Saturday 1/19/2013], [Sunday 1/19/2014], [Monday 1/19/2015], [Tuesday 1/19/2016], [Thursday 1/19/2017], [Friday 1/19/2018], [Saturday 1/19/2019], [Sunday 1/19/2020], [Tuesday 1/19/2021]
Past: [Wednesday 1/19/2011] ...

Integrating Wordnet with Natural Language Processing (NLP)

I’ve been working to get a release of my NLP Engine out the door but wanted to boost the built in dictionary / thesaurus before release. So this weekend I integrated Wordnet into the engine. Wordnet is available in RDF as a series of triples. As well as all the word definitions grouped into synonym sets (synsets) it also includes relationships like class relationships ‘hyponym‘ or ‘isa’ and part relationships ‘meronym‘ or ‘holonym‘.

By building a simple in-memory graph of all these relationships my engine can now use them to infer interface types on objects. To define an interface corresponding to a Wordnet synset like a mammal (wn30:synset-mammal-noun-1) you simply define an interface in the namespace ‘Noun’ having a name of ‘mammal1′. Through the type inheritance specified in the Wordnet file all mammals now inherit that interface automatically and you can write natural language rules that ask for a mammal and they will get any type of mammal defined in Wordnet.

For example:

Wordnet integration with Natural Language Engine

“Remember Everything” … a long-term project

Remember Everything using Natural Language Interface

Here's a working example of the kind of semantic and mathematical summarization possible.

One of my long-term project ideas that is gradually coming together piece-by-piece is a system I call “Remember Everything” (for want of a better name).

“Remember Everything” connects nearly all of my projects into one giant solution that, well, remembers everything and has a natural language interface over it.

As inputs it will take information from my home automation system, my whole-network storage crawler, Google calendar, email, Twitter, blog, web crawler, an address-monitoring browser add-on I plan to write, the weather and traffic feeds, and, of course my natural language engine.

All this data will be put into MongoDB and can then be queried. Relationships between entities will be created using a semantic-web triple store and reasoner.

Together these capabilities will allow queries like:-

* Copy all the photos I took last week onto c:\vacationPhotos
* Send img_0938.jpg to mum.
* Who called last Monday?
* Show pictures from last month taken on sunny days.
* What was happening two weeks ago when X called?
* Who called yesterday when I was in a meeting?
* What song was playing around 9pm last night?
* How long did I spend on the phone to my accountant last week?
* What web pages did I read last week about the Semantic Web?
* Send the web page I tweeted about last night to my Kindle.
* We need butter and olives.
* What do I need to buy from QFC? (a semantic shopping list concept, more on that later …)

In addition to the shopping lists concept (that’s already in my home automation system but lacks the semantic reasoning) the system will take any subject-verb-object phrase and remember it and then allow you to query it back later, e.g.

* My son read 20 pages tonight (making the weekly reading report easier)
* How many pages did he read this week?
* I took the red pill at 10AM
* I walked 2 miles this morning
* I ran 4 miles
* How much exercise did I do this week when it wasn’t raining? (summarizing values semantically and mathematically)
* The Audi was serviced this week (remembering schedules so you can check if an item is overdue)
* My BA frequent flyer number is #### (remembering numbers you need to look up often)
* I took the day off on friday (vacation reporting)
* I spent $12.95 on lunch (expense reporting)

Whenever you have anything you need to remember the system will be able to remember it, recall it, and where possible aggregate or summarize it using math and/or semantic reasoning (e.g. running subClassOf exercise, butter subClassOf dairy product, dairy products areSoldAt QFC, …).

By linking my natural language engine to a triple store I can even allow users to teach it new concepts:

Using Natural Language to populate a triple store

An in progress demonstration using English language input to populate a triple store

By silently monitoring your email, Twitter stream, calendar, activity in the house, … it will be able to answer questions based on the context not just on the content in ways that we take for granted as humans but which are not possible for computers today.

What if … you could define and query an Ontology using natural language?

Tonight as an experiment I connected my NLP engine to my MongoDB triple-store and built a reasoner that does simple-entailment over just RDFS:subClassOf and OWL:disjointWith

Try it out at http://nlp.abodit.com/demo

Ignore the instructions on the right and try building a simple ontology,

Start by creating some root level class:

car is a class

Now expand it:

A BMW is a car
An Audi is a car
what is a BMW
BMW is a car
what is an Audi
Audi is a car
is an Audi a BMW
I don’t know, under the open world assumption it could be
an Audi is not a BMW
is an Audi a BMW
No

Simple but promising.

C# Natural Language Engine connected to Microsoft Dynamics CRM 2011 Online

In an earlier post I discussed some ideas around a Semantic CRM.

Recently I’ve been doing some clean up work on my C# Natural Language Engine and decided to do a quick test connecting it to a real CRM. As you may know from reading my blog, this natural language engine is already heavily used in my home automation system to control lights, sprinklers, HVAC, music and more and to query caller ID logs and other information.

I recently refactored it to use the Autofac dependency injection framework and in the process realized just how close my NLP engine is to ASP.NET MVC 3 in its basic structure and philosophy! To use it you create Controller classes and put action methods in them. Those controller classes use Autofac to get all of the dependencies they may need (services like an email service, a repository, a user service, an HTML email formattting service, …) and then the methods in them represents a specific sentence parse using the various token types that the NLP engine supports. Unlike ASP.NET MVC3 there is no Route registration; the method itself represents the route (i.e. sentence structure) that it used to decide which method to call. Internally my NLP engine has its own code to match incoming words and phrases to tokens and then on to the action methods. In a sense the engine itself is one big dependency injection framework working against the action methods. I sometimes wish ASP.NET MVC 3 had the same route-registration-free approach to designing web applications (but also appreciate all the reasons why it doesn’t).

Another improvement I made recently to the NLP Engine was to develop a connector for the Twilio SMS service. This means that my home automation system can now accept SMS messages as well as all the other communication formats it supports: email, web chat, XMPP chat and direct URL commands. My Twilio connector to NLP supports message splitting and batching so it will buffer up outgoing messages to reach the limit of a single SMS and will send that. This lowers SMS charges and also allows responses that are longer than a single SMS message.

Using this new, improved version of my Natural Language Engine I decided to try connecting it to a CRM. I chose Microsoft Dynamics CRM 2011 and elected to use the strongly-typed, early-bound objects that you can generate for any instance of the CRM service. I added some simple sentences in an NLPRules project that allow you to tell it who you met, and to input some of their details. Unlike a traditional forms-based approach the user can decide what information to enter and what order to enter it in. The Natural Language Engine supports the concept of a conversation and can remember what you were discussing allowing a much more natural style of conversation that some simple rule-based engines and even allowing it to ask questions and get answers from the user.

Here’s a screenshot showing a sample conversation using Google Talk (XMPP/Jabber) and the resulting CRM record in Microsoft CRM 2011 Online. You could have the same conversation over SMS or email. Click to enlarge.

A natural language interface to CRM

Based on my limited testing this looks like another promising area where a truly fluent, conversational-style natural language engine could play a significant role. Note how it understands email addresses, phone numbers and such like and in code these all become strongly typed objects. Where it really excels is in temporal expressions where it can understand things like “who called on a Saturday in May last year?” and can construct an efficient SQL query from that.

A strongly-typed natural language engine (C# NLP)

Here is an explanation of the natural language engine that powers my home automation system. It’s a strongly-typed natural language engine with tokens and sentences being defined in code. It currently understands sentences to control lights, heating, music, sprinklers, … You can ask it who called, you can tell it to play music in a particular room, … it tells you when a car comes down the drive, when the traffic is bad on I-90, when there’s fresh snow in the mountains, when it finds new podcasts from NPR, … and much more.

The natural language engine itself is a separate component that I hope one day to use in other applications.

Existing Natural Language Engines

  • Have a large, STATIC dictionary data file
  • Can parse complex sentence structure
  • Hand back a tree of tokens (strings)
  • Don’t handle conversations

C# NLP Engine

  • Defines strongly-typed tokens in code
  • Uses type inheritance to model ‘is a’
  • Defines sentences in code
  • Rules engine executes sentences
  • Understands context (conversation history)

Sample conversation

Goals

  • Make it easy to define tokens and sentences (not XML)
  • Safe, compile-time checked definition of the syntax and grammar (not XML)
  • Model real-world inheritance with C# class inheritance:
  • ‘a labrador’ is ‘a dog’ is ‘an animal’ is ‘a thing’
  • Handle ambiguity, e.g.
play something in the air tonight in the kitchen
remind me at 4pm to call john at 5pm

C# NLP Engine Structure

Tokens – Token Definition

  • A hierarchy of Token-derived classes
  • Uses inheritance, e.g. TokenOn is a TokenOnOff is a TokenState is a Token. This allows a single sentence rule to handle multiple cases, e.g. On and Off
  • Derived from base Token class
  • Simple tokens are a set of words, e.g. « is | are »
  • Complex tokens have a parser, e.g. TokenDouble

A Simple Token Definition

public class TokenPersonalPronoun : TokenGenericNoun
{
   internal static string wordz { get { return "he,him,she,her,them"; } }
}
  • Recognizes any of the words specified
  • Can use inheritance (as in this example)

A Complex Token

public abstract class TokenNumber : Token
{
  public static IEnumerable<TokenResult> Initialize(string input)
  {
  …
  • Initialize method parses input and returns one or more possible parses.

TokenNumber is a good example:

  • Parses any numeric value and returns one or more of TokenInt, TokenLong, TokenIntOrdinal, TokenDouble, or TokenPercentage results.

The catch-all TokenPhrase

public class TokenPhrase : Token

TokenPhrase matches anything, especially anything in quote marks

   e.g. add a reminder "call Bruno at 4pm"

The sentence signature to recognize this could be

(…, TokenAdd, TokenReminder, TokenPhrase, TokenExactTime)

This would match the rule too …

add a reminder discuss 6pm conference call with Bruno at 4pm

TemporalTokens

A complete set of tokens and related classes for representing time

  • Point in time, e.g. today at 5pm
  • Approximate time, e.g. who called at 5pm today
  • Finite sequence, e.g. every Thursday in May 2009
  • Infinite sequence, e.g. every Thursday
  • Ambiguous time with context, e.g. remind me on Tuesday (context means it is next Tuesday)
  • Null time
  • Unknowable/incomprehensible time

TemporalTokens (Cont.)

Code to merge any sequence of temporal tokens to the smallest canonical representation,

e.g.

the first thursday in may 2009

->
{TIMETHEFIRST the first} + {THURSDAY thursday} + {MAY in may} + {INT 2009 -> 2009}

->
[TEMPORALSETFINITESINGLEINTERVAL [Thursday 5/7/2009] ]

TemporalTokens (Cont.)

Finite TemporalClasses provide

  • A way to enumerate the DateTimeRanges they cover
  • All TemporalClasses provide

  • A LINQ expression generator and Entity-SQL expression generator allowing them to be used to query a database
  • Existing Token Types

    • Numbers (double, long, int, percentage, phone, temperature)
    • File names, Directories
    • URLs, Domain names
    • Names, Companies, Addresses
    • Rooms, Lights, Sensors, Sprinklers, …
    • States (On, Off, Dim, Bright, Loud, Quiet, …)
    • Units of Time, Weight, Distance
    • Songs, albums, artists, genres, tags
    • Temporal expressions
    • Commands, verbs, nouns, pronouns, …

    Rules – A simple rule

       /// &lt;summary&gt;
       /// Set a light to a given state
       /// &lt;/summary&gt;
       private static void LightState(NLPState st, TokenLight tlight, TokenStateOnOff ts)
       {
          if (ts.IsTrueState == true) tlight.ForceOn(st.Actor);
          if (ts.IsTrueState == false) tlight.ForceOff(st.Actor);
          st.Say("I turned it " + ts.LowerCased);
       }
    

    Any method matching this signature is a sentence rule:-  NLPState, Token*

    Rule matching respects inheritance, and variable repeats … (NLPState st, TokenThing tt, TokenState tokenState, TokenTimeConstraint[] constraints)

    Rules are discovered on startup using Reflection and an efficient parse graph is built allowing rapid detection and rejection of incoming sentences.

    State – NLPState

    • Every sentence method takes an NLPState first parameter
    • State includes RememberedObject(s) allowing sentences to react to anything that happened earlier in a conversation
    • Non-interactive uses can pass a dummy state
    • State can be per-user or per-conversation for non-realtime conversations like email
      • Chat (e.g Jabber/Gtalk)
      • Web chat
      • Email
      • Calendar (do X at time Y)
      • Rich client application
      • Strongly-typed natural language engine
      • Compile time checking, inheritance, …
      • Define tokens and sentences (rules) in C#
      • Strongly-typed tokens: numbers, percentages, times, dates, file names, urls, people, business objects, …
      • Builds an efficient parse graph
      • Tracks conversation history
    • User Interface

      Works with a variety of user interfaces

      Summary

      Future plans

      Expanded corpus of knowledge

    • Company names, locations, documents, …
    • Generate iCal/Gdata Recurrence

    • From TimeExpressions