never executed always true always false
    1 {-# LANGUAGE InstanceSigs #-}
    2 {-# LANGUAGE OverloadedStrings #-}
    3 
    4 {- |
    5 Module      : NITTA.Synthesis.MlBackend.Api
    6 Description : ML backend API client (DTOs, request wrappers)
    7 Copyright   : (c) Ilya Burakov, 2023
    8 License     : BSD3
    9 Maintainer  : aleksandr.penskoi@gmail.com
   10 Stability   : experimental
   11 -}
   12 module NITTA.Synthesis.MlBackend.Client (
   13     ScoringInput (..),
   14     ScoringTarget (..),
   15     predictScoresIO,
   16 ) where
   17 
   18 import Data.Aeson
   19 import Data.String.ToString
   20 import Data.Text.Encoding qualified as T
   21 import GHC.Generics
   22 import NITTA.Synthesis.Types hiding (scores)
   23 import NITTA.UIBackend.ViewHelper (NodeView, VarValTimeJSON)
   24 import Network.HTTP.Client.Conduit
   25 import Network.HTTP.Simple
   26 
   27 data ScoringTarget = ScoringTargetSid Sid | ScoringTargetAll
   28 
   29 instance ToJSON ScoringTarget where
   30     toJSON (ScoringTargetSid sid) = toJSON sid
   31     toJSON ScoringTargetAll = toJSON ("all" :: String)
   32 
   33 data ScoringInput tag v x t = ScoringInput
   34     { scoringTarget :: ScoringTarget
   35     , nodes :: [NodeView tag v x t]
   36     }
   37     deriving (Generic)
   38 
   39 instance (VarValTimeJSON v x t, ToJSON tag) => ToJSON (ScoringInput tag v x t)
   40 
   41 newtype PostScoreRequestBody tag v x t = PostScoreRequestBody
   42     { inputs :: [ScoringInput tag v x t]
   43     }
   44     deriving (Generic)
   45 
   46 instance (VarValTimeJSON v x t, ToJSON tag) => ToJSON (PostScoreRequestBody tag v x t)
   47 
   48 newtype MlBackendResponse d = MlBackendResponse
   49     { responseData :: d
   50     }
   51     deriving (Show, Generic)
   52 
   53 instance FromJSON d => FromJSON (MlBackendResponse d) where
   54     parseJSON = withObject "MlBackendResponse" $ \obj ->
   55         MlBackendResponse <$> obj .: "data" -- we are using the parameter's FromJSON
   56 
   57 instance ToJSON d => ToJSON (MlBackendResponse d) where
   58     toJSON :: MlBackendResponse d -> Value
   59     toJSON (MlBackendResponse{responseData}) = object ["data" .= responseData]
   60 
   61 newtype PostScoreResponseData = PostScoreResponseData
   62     {scores :: [[Float]]}
   63     deriving (Show, Generic)
   64 
   65 -- TODO: GeneralizedNewtypeDeriving vs DeriveAnyClass conflict? declaring instance manually for now
   66 instance ToJSON PostScoreResponseData
   67 instance FromJSON PostScoreResponseData
   68 
   69 getDefaultRequestIO baseUrl = do
   70     parseRequest (toString baseUrl)
   71 
   72 getScoreRequestIO baseUrl modelName scoringInputs =
   73     let path = T.encodeUtf8 $ "/models/" <> modelName <> "/score"
   74         body = PostScoreRequestBody{inputs = scoringInputs}
   75      in do
   76             setRequestMethod "POST"
   77                 . setRequestPath path
   78                 . setRequestBodyJSON body
   79                 <$> getDefaultRequestIO baseUrl
   80 
   81 predictScoresIO modelName baseUrl inputs = do
   82     request <- getScoreRequestIO baseUrl modelName inputs
   83     response <- httpJSON request
   84     return $ scores $ responseData $ getResponseBody response