openai-hs-0.2.0.0: test/ApiSpec.hs
module ApiSpec (apiSpec) where
import Network.HTTP.Client
import Network.HTTP.Client.TLS
import System.Environment (getEnv)
import Test.Hspec
import qualified Data.Text as T
import qualified Data.Vector as V
import OpenAI.Client
makeClient :: IO OpenAIClient
makeClient =
do manager <- newManager tlsManagerSettings
apiKey <- T.pack <$> getEnv "OPENAI_KEY"
pure (makeOpenAIClient apiKey manager 2)
forceSuccess :: (MonadFail m, Show a) => m (Either a b) -> m b
forceSuccess req =
req >>= \res ->
case res of
Left err -> fail (show err)
Right ok -> pure ok
apiSpec :: Spec
apiSpec =
describe "core api" apiTests
apiTests :: SpecWith ()
apiTests =
beforeAll makeClient $
do describe "file api" $
do it "allows creating one" $ \cli ->
do let file =
FileCreate
{ fcPurpose = "search"
, fcDocuments = [FileHunk "Test 1" Nothing, FileHunk "text 2" (Just "foo")]
}
res <- forceSuccess $ createFile cli file
_ <- forceSuccess $ deleteFile cli (fId res)
pure ()
describe "answer api" $
do it "works" $ \cli ->
do let file =
FileCreate
{ fcPurpose = "search"
, fcDocuments =
[ FileHunk "Cities in California: San Francisco, Los Angeles" (Just "cali")
, FileHunk "Tasty fruit: Apple, Orange" (Just "fruit")
, FileHunk "Cities in Germany: Freiburg, Berlin" (Just "germany")
]
}
res <- forceSuccess $ createFile cli file
let searchReq =
AnswerReq
{ arFile = Just (fId res)
, arDocuments = Nothing
, arQuestion = "Where is San Francisco?"
, arSearchModel = EngineId "babbage"
, arModel = EngineId "davinci"
, arExamplesContext = "Good programming languages: Haskell, PureScript"
, arExamples = [["Is PHP a good programming language?", "No, sorry."]]
, arReturnMetadata = True
}
answerRes <- forceSuccess $ getAnswer cli searchReq
T.unpack (head (arsAnswers answerRes)) `shouldContain` ("California" :: String)
_ <- forceSuccess $ deleteFile cli (fId res)
pure ()
describe "engines" $
do it "lists engines" $ \cli ->
do res <- forceSuccess $ listEngines cli
V.null (olData res) `shouldBe` False
it "retrieve engine" $ \cli ->
do engineList <- forceSuccess $ listEngines cli
let firstEngine = V.head (olData engineList)
engine <- forceSuccess $ getEngine cli (eId firstEngine)
engine `shouldBe` firstEngine
describe "text completion" $
do it "works (smoke test)" $ \cli ->
do firstEngine <- V.head . olData <$> forceSuccess (listEngines cli)
completionResults <-
forceSuccess $
completeText cli (eId firstEngine) $
(defaultTextCompletionCreate "Why is the house ")
{ tccrMaxTokens = Just 2 }
V.length (tcChoices completionResults) `shouldBe` 1
T.length (tccText (V.head (tcChoices completionResults))) `shouldNotBe` 0
describe "document search" $
do it "works (smoke test)" $ \cli ->
do firstEngine <- V.head . olData <$> forceSuccess (listEngines cli)
searchResults <-
forceSuccess $
searchDocuments cli (eId firstEngine) $
SearchResultCreate
{ sccrDocuments = Just $ V.fromList ["pool", "gym", "night club"]
, sccrFile = Nothing
, sccrQuery = "swimmer"
, sccrReturnMetadata = False
}
V.length (olData searchResults) `shouldBe` 3
describe "file based document search" $
do it "works" $ \cli ->
do let file =
FileCreate
{ fcPurpose = "search"
, fcDocuments =
[ FileHunk "pool" (Just "pool")
, FileHunk "gym" (Just "gym")
, FileHunk "night club" (Just "nc")
]
}
createRes <- forceSuccess $ createFile cli file
let searchReq =
SearchResultCreate
{ sccrFile = Just (fId createRes)
, sccrDocuments = Nothing
, sccrQuery = "pool"
, sccrReturnMetadata = True
}
searchRes <- forceSuccess $ searchDocuments cli (EngineId "ada") searchReq
let res = V.head (olData searchRes)
srDocument res `shouldBe` 0 -- pool
srMetadata res `shouldBe` Just "pool"
_ <- forceSuccess $ deleteFile cli (fId createRes)
pure ()