packages feed

openai-servant-gen-0.1.0.0: test/Spec.hs

-- Test OpenAI.API and OpenAI.Types modules

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}

module Main where

import Test.Hspec
import OpenAI.API
import OpenAI.Types
--import Data.Aeson.Decoding
import Data.Aeson
import Data.Maybe (fromMaybe)
import Data.Function ((&))
import Data.List (stripPrefix)
import qualified Data.Char as Char
import qualified Data.Text as T

uncapitalize :: String -> String
uncapitalize (first:rest) = Char.toLower first : rest
uncapitalize [] = []

removeFieldLabelPrefix :: Bool -> String -> Options
removeFieldLabelPrefix forParsing prefix =
  defaultOptions
    { omitNothingFields  = True
    , fieldLabelModifier = uncapitalize . fromMaybe (error ("did not find prefix " ++ prefix)) . stripPrefix prefix . replaceSpecialChars
    }
  where
    replaceSpecialChars field = foldl (&) field (map mkCharReplacement specialChars)
    specialChars =
      [ ("$", "'Dollar")
      , ("^", "'Caret")
      , ("|", "'Pipe")
      , ("=", "'Equal")
      , ("*", "'Star")
      , ("-", "'Dash")
      , ("&", "'Ampersand")
      , ("%", "'Percent")
      , ("#", "'Hash")
      , ("@", "'At")
      , ("!", "'Exclamation")
      , ("+", "'Plus")
      , (":", "'Colon")
      , (";", "'Semicolon")
      , (">", "'GreaterThan")
      , ("<", "'LessThan")
      , (".", "'Period")
      , ("_", "Underscore")
      , ("?", "'Question_Mark")
      , (",", "'Comma")
      , ("'", "'Quote")
      , ("/", "'Slash")
      , ("(", "'Left_Parenthesis")
      , (")", "'Right_Parenthesis")
      , ("{", "'Left_Curly_Bracket")
      , ("}", "'Right_Curly_Bracket")
      , ("[", "'Left_Square_Bracket")
      , ("]", "'Right_Square_Bracket")
      , ("~", "'Tilde")
      , ("`", "'Backtick")
      , ("<=", "'Less_Than_Or_Equal_To")
      , (">=", "'Greater_Than_Or_Equal_To")
      , ("!=", "'Not_Equal")
      , ("<>", "'Not_Equal")
      , ("~=", "'Tilde_Equal")
      , ("\\", "'Back_Slash")
      , ("\"", "'Double_Quote")
      ]
    mkCharReplacement (replaceStr, searchStr) = T.unpack . replacer (T.pack searchStr) (T.pack replaceStr) . T.pack
    replacer =
      if forParsing
        then flip T.replace
        else T.replace


main :: IO ()
main = hspec $ do
  describe "OpenAI API" $ do
    it "Encode labels of CompletionUsage" $ do
        let options = removeFieldLabelPrefix False "completionUsage"
            replace = fieldLabelModifier options
        replace "completionUsagePromptUnderscoretokens" `shouldBe` "prompt_tokens"
    it "Decode labels of CompletionUsage" $ do
        let options = removeFieldLabelPrefix False "completionUsage"
            replace = fieldLabelModifier options
        replace "completionUsagePromptUnderscoretokens" `shouldBe` "prompt_tokens"
    it "Encode CompletionUsage" $ do
        let usage = CompletionUsage 8 9 17
        encode usage `shouldBe` "{\"completion_tokens\":8,\"prompt_tokens\":9,\"total_tokens\":17}"
    it "Decode CompletionUsage" $ do
        let jsonData = "{\n  \"prompt_tokens\": 9,\n  \"completion_tokens\": 8,\n  \"total_tokens\": 17\n}"
        let response = eitherDecode jsonData :: Either String CompletionUsage
        response `shouldBe` (Right $ CompletionUsage 8 9 17)
    it "Encode Request" $ do
        let jsonData = "{\"messages\":[{\"content\":\"Hello\",\"role\":\"user\"}],\"model\":\"gpt-3.5-turbo\",\"seed\":0}"
            request = eitherDecode jsonData :: Either String CreateChatCompletionRequest
        request `shouldBe` Right (CreateChatCompletionRequest
                                    { createChatCompletionRequestMessages = [
                                        ChatCompletionRequestMessage
                                        { chatCompletionRequestMessageContent = Just $ ChatCompletionRequestMessageContentText "Hello"
                                        -- 'User' is not one of ['system', 'assistant', 'user', 'function']
                                        , chatCompletionRequestMessageRole = "user"
                                        , chatCompletionRequestMessageName = Nothing
                                        , chatCompletionRequestMessageToolUnderscorecalls = Nothing
                                        , chatCompletionRequestMessageFunctionUnderscorecall = Nothing
                                        , chatCompletionRequestMessageToolUnderscorecallUnderscoreid = Nothing
                                        }
                                        ]
                                    , createChatCompletionRequestModel = CreateChatCompletionRequestModel "gpt-3.5-turbo"
                                    , createChatCompletionRequestFrequencyUnderscorepenalty = Nothing
                                    , createChatCompletionRequestLogitUnderscorebias = Nothing
                                    , createChatCompletionRequestLogprobs = Nothing
                                    , createChatCompletionRequestTopUnderscorelogprobs  = Nothing
                                    , createChatCompletionRequestMaxUnderscoretokens  = Nothing
                                    , createChatCompletionRequestN  = Nothing
                                    , createChatCompletionRequestPresenceUnderscorepenalty  = Nothing
                                    , createChatCompletionRequestResponseUnderscoreformat  = Nothing
                                    , createChatCompletionRequestSeed = Just 0
                                    , createChatCompletionRequestStop = Nothing
                                    , createChatCompletionRequestStream = Nothing
                                    , createChatCompletionRequestTemperature = Nothing
                                    , createChatCompletionRequestTopUnderscorep = Nothing
                                    , createChatCompletionRequestTools = Nothing
                                    , createChatCompletionRequestToolUnderscorechoice = Nothing
                                    , createChatCompletionRequestUser = Nothing
                                    , createChatCompletionRequestFunctionUnderscorecall = Nothing
                                    , createChatCompletionRequestFunctions = Nothing
                                    } )
    it "Load and save response types" $ do
        let jsonData = "{\n  \"id\": \"chatcmpl-8zKzKZVra3d7t082fFoB8ZAFxLSWf\",\n  \"object\": \"chat.completion\",\n  \"created\": 1709629378,\n  \"model\": \"gpt-3.5-turbo-0125\",\n  \"choices\": [\n    {\n      \"index\": 0,\n      \"message\": {\n        \"role\": \"assistant\",\n        \"content\": \"Hello! How can I assist you today?\"\n      },\n      \"logprobs\": null,\n      \"finish_reason\": \"stop\"\n    }\n  ],\n  \"usage\": {\n    \"prompt_tokens\": 8,\n    \"completion_tokens\": 9,\n    \"total_tokens\": 17\n  },\n  \"system_fingerprint\": \"fp_b9d4cef803\"\n}\n"
        let response = eitherDecode jsonData :: Either String CreateChatCompletionResponse
        response `shouldBe` (Right (
            CreateChatCompletionResponse
            { createChatCompletionResponseId = "chatcmpl-8zKzKZVra3d7t082fFoB8ZAFxLSWf"
            , createChatCompletionResponseObject = "chat.completion"
            , createChatCompletionResponseCreated = 1709629378
            , createChatCompletionResponseModel = "gpt-3.5-turbo-0125"
            , createChatCompletionResponseChoices = [
                CreateChatCompletionResponseChoicesInner
                { createChatCompletionResponseChoicesInnerIndex = 0
                , createChatCompletionResponseChoicesInnerMessage = ChatCompletionResponseMessage
                    { chatCompletionResponseMessageRole = "assistant"
                    , chatCompletionResponseMessageContent = Just "Hello! How can I assist you today?"
                    , chatCompletionResponseMessageToolUnderscorecalls = Nothing
                    , chatCompletionResponseMessageFunctionUnderscorecall = Nothing
                    }
                , createChatCompletionResponseChoicesInnerLogprobs = Nothing
                , createChatCompletionResponseChoicesInnerFinishUnderscorereason = "stop"
                }
                ]
            , createChatCompletionResponseUsage = Just $ CompletionUsage
                { completionUsagePromptUnderscoretokens = 8
                , completionUsageCompletionUnderscoretokens = 9
                , completionUsageTotalUnderscoretokens = 17
                }
            , createChatCompletionResponseSystemUnderscorefingerprint = Just "fp_b9d4cef803"
            }
            ))