{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE RecordWildCards #-} {-| Module : NLP.LUIS Description : An unofficial client for the LUIS NLP service. Copyright : (c) 2016 Micxjo Funkcio License : BSD3 Maintainer : micxjo@fastmail.com Stability : experimental -} module NLP.LUIS ( -- * Querying query , queryExc , Credentials(..) -- * Response Type , Response , responseQuery , responseIntents , responseEntities -- * Intent Type , Intent , intentType , intentScore , intentActions , Action , actionName , actionTriggered , actionParams , Param , paramName , paramRequired , paramValues , ParamValue , paramValueEntity , paramValueType , paramValueScore -- * Entity Type , Entity , entityType , entityScore , entityText , entityStartIndex , entityEndIndex -- * Errors , LUISError(..) ) where import Control.Exception (Exception(..), fromException, try) import Data.Data (Data) import Data.Maybe (isJust) import Data.Typeable (Typeable) import GHC.Generics (Generic) import Control.Lens import Data.Aeson import Data.Text (Text) import Data.Vector (Vector) import Network.HTTP.Client (HttpException) import Network.Wreq hiding (Response) data ParamValue = ParamValue { _paramValueEntity :: !Text , _paramValueType :: !Text , _paramValueScore :: !Double } deriving (Eq, Show, Read, Typeable, Data, Generic) makeLenses ''ParamValue instance FromJSON ParamValue where parseJSON = withObject "param value" $ \o -> ParamValue <$> o .: "entity" <*> o .: "type" <*> o .: "score" data Param = Param { _paramName :: !Text , _paramRequired :: !Bool , _paramValues :: !(Maybe (Vector ParamValue)) } deriving (Eq, Show, Read, Typeable, Data, Generic) makeLenses ''Param instance FromJSON Param where parseJSON = withObject "param" $ \o -> Param <$> o .: "name" <*> o .: "required" <*> o .: "value" data Action = Action { _actionName :: !Text , _actionTriggered :: !Bool , _actionParams :: !(Vector Param) } deriving (Eq, Show, Read, Typeable, Data, Generic) makeLenses ''Action instance FromJSON Action where parseJSON = withObject "action" $ \o -> Action <$> o .: "name" <*> o .: "triggered" <*> o .: "parameters" data Intent = Intent { _intentType :: !Text , _intentScore :: !Double , _intentActions :: !(Maybe (Vector Action)) } deriving (Eq, Show, Read, Typeable, Data, Generic) makeLenses ''Intent instance FromJSON Intent where parseJSON = withObject "intent" $ \o -> Intent <$> o .: "intent" <*> o .: "score" <*> o .: "actions" data Entity = Entity { _entityText :: !Text , _entityType :: !Text , _entityStartIndex :: !Int , _entityEndIndex :: !Int , _entityScore :: !Double } deriving (Eq, Show, Read, Typeable, Data, Generic) makeLenses ''Entity instance FromJSON Entity where parseJSON = withObject "entity" $ \o -> do _entityText <- o .: "entity" _entityType <- o .: "type" _entityStartIndex <- o .: "startIndex" _entityEndIndex <- o .: "endIndex" _entityScore <- o .: "score" pure Entity{..} data Response = Response { _responseQuery :: !Text , _responseIntents :: !(Vector Intent) , _responseEntities :: !(Vector Entity) } deriving (Eq, Show, Read, Typeable, Data, Generic) makeLenses ''Response instance FromJSON Response where parseJSON = withObject "luisResponse" $ \o -> Response <$> o .: "query" <*> o .: "intents" <*> o .: "entities" data LUISError = HttpError HttpException | ResponseError JSONError deriving (Show, Typeable, Generic) instance Exception LUISError where fromException e = if isJust he then he else je where he = HttpError <$> fromException e je = ResponseError <$> fromException e -- | Application credentials for a LUIS model. data Credentials = Credentials { applicationId :: !Text , subscriptionKey :: !Text } deriving (Show, Read, Eq, Typeable, Data, Generic) -- | Query a LUIS model. An 'HttpException' or 'JSONError' may be thrown. queryExc :: Credentials -> Text -> IO Response queryExc Credentials{..} str = do let opts = defaults & param "id" .~ [applicationId] & param "subscription-key" .~ [subscriptionKey] & param "q" .~ [str] resp <- getWith opts "https://api.projectoxford.ai/luis/v1/application" luisResp <- asJSON resp return (luisResp ^. responseBody) -- | Query a LUIS model. query :: Credentials -> Text -> IO (Either LUISError Response) query creds str = try (queryExc creds str)