packages feed

pinecone-1.0.0: tasty/Main.hs

{-# LANGUAGE BlockArguments        #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NamedFieldPuns        #-}
{-# LANGUAGE RecordWildCards       #-}
{-# LANGUAGE OverloadedStrings     #-}
{-# LANGUAGE OverloadedLists       #-}

module Main where

import Pinecone (DataMethods(..), ControlMethods(..))
import Pinecone.Embed (GenerateVectors(..))
import Pinecone.Rerank (Document(..), Documents(..), RerankResults(..))
import Prelude hiding (id)

import Pinecone.Indexes
    ( Cloud(..)
    , CreateIndexWithEmbedding(..)
    , ConfigureIndex(..)
    , EmbedRequest(..)
    , GetIndexStats(..)
    , IndexModel(..)
    , IndexStats(..)
    , Status(..)
    )
import Pinecone.Search
    ( Hit(..)
    , Hits(..)
    , Matches(..)
    , Query(..)
    , SearchWithText(..)
    , SearchWithVector(..)
    )
import Pinecone.Vectors
    ( DeleteVectors(..)
    , Record(..)
    , UpdateVector(..)
    , UpsertVectors(..)
    , UpsertStats(..)
    , VectorIDs(..)
    , VectorObject(..)
    , Vectors(..)
    )

import qualified Control.Exception as Exception
import qualified Data.Text as Text
import qualified Data.Vector as Vector
import qualified Pinecone
import qualified System.Environment as Environment
import qualified Test.Tasty as Tasty
import qualified Test.Tasty.HUnit as HUnit

main :: IO ()
main = do
    controlEnv <- Pinecone.getClientEnv "https://api.pinecone.io"

    key <- Environment.getEnv "PINECONE_KEY"

    let token = Text.pack key

    let ControlMethods{..} = Pinecone.makeControlMethods controlEnv token

    let namespace = "test"

    Tasty.defaultMain do
        HUnit.testCase "Vectors" do
            let open = do
                    createIndexWithEmbedding CreateIndexWithEmbedding
                        { name = "vectors-test"
                        , cloud = AWS
                        , region = "us-east-1"
                        , embed = EmbedRequest
                            { model = "llama-text-embed-v2"
                            , metric = Nothing
                            , read_parameters = Nothing
                            , write_parameters = Nothing
                            }
                        , deletion_protection = Nothing
                        , tags = Nothing
                        }

            let close IndexModel{ name } = deleteIndex name

            Exception.bracket open close \IndexModel{ name, host } -> do
                _ <- generateVectors GenerateVectors
                    { model = "llama-text-embed-v2"
                    , inputs = [ "Hello, world!" ]
                    , parameters = [ ("input_type", "query") ]
                    }

                let hello = Record
                        { id = "hi"
                        , text = "Hello, world"
                        , metadata = Nothing
                        }

                let goodbye = Record
                        { id = "bye"
                        , text = "Goodbye, world"
                        , metadata = Nothing
                        }

                Documents{ data_ = [ Document{ document = Just Record{ id = "hi" } } ] } <- rerankResults RerankResults
                    { model = "bge-reranker-v2-m3"
                    , query = "best greeting"
                    , documents = [ hello, goodbye ]
                    , top_n = Just 1
                    , return_documents = True
                    , parameters = [ ]
                    }

                dataEnv <- Pinecone.getClientEnv host

                let DataMethods{..} = Pinecone.makeDataMethods dataEnv token

                let waitUntilIndexReady = do
                        indexModel <- describeIndex name

                        let IndexModel{ status } = indexModel

                        let Status{ ready } = status

                        if ready
                            then return indexModel
                            else waitUntilIndexReady

                indexModel <- waitUntilIndexReady

                indexes <- listIndexes

                case indexes of
                    [ indexModel₀ ]
                        | indexModel == indexModel₀ -> return ()
                    _ -> HUnit.assertFailure "GET /indexes - wrong models"

                _ <- configureIndex name ConfigureIndex
                    { spec = Nothing
                    , deletion_protection = Nothing
                    , tags = Just [ ("foo", "bar") ]
                    , embed = Nothing
                    }

                IndexModel{ tags = Just [ ("foo", "bar") ] } <- describeIndex name

                UpsertStats{..} <- upsertVectors UpsertVectors
                    { vectors =
                        [ VectorObject
                            { id = "vector-0"
                            , values = Just (Vector.replicate 1024 0.1)
                            , sparseValues = Nothing
                            , metadata = Nothing
                            }
                        ]
                    , namespace = Just namespace
                    }

                HUnit.assertEqual "" 1 upsertedCount

                deleteVectors DeleteVectors
                    { ids = Just [ "vector-0" ]
                    , deleteAll = Nothing
                    , namespace = Just namespace
                    , filter = Nothing
                    }

                upsertText namespace hello

                upsertText namespace goodbye

                updateVector UpdateVector
                    { id = "hi"
                    , values = Nothing
                    , sparseValues = Nothing
                    , setMetadata = Just [ ("category", "greeting") ]
                    , namespace = Just namespace
                    }

                let waitUntilVectorsReady = do
                        IndexStats{..} <- getIndexStats GetIndexStats
                            { filter = Nothing
                            }

                        if totalVectorCount == 2
                            then return ()
                            else waitUntilVectorsReady

                waitUntilVectorsReady

                Vectors{ vectors = [ ("bye", _), ("hi", _) ] } <- fetchVectors [ "hi", "bye" ] (Just namespace)

                VectorIDs{ vectors = [ "bye", "hi" ] } <- listVectorIDs Nothing Nothing Nothing (Just namespace)

                Hits{ hits = [ Hit{ _id = "hi" } ] } <- searchWithText namespace SearchWithText
                    { query = Query
                        { top_k = 1
                        , filter = Nothing
                        , input = Just "Hi!"
                        , vector = Nothing
                        }
                    , fields = Nothing
                    , rerank = Nothing
                    }

                Matches{ matches } <- searchWithVector SearchWithVector
                    { topK = 1
                    , namespace = Just namespace
                    , filter = Nothing
                    , includeValues = Nothing
                    , includeMetadata = Nothing
                    , vector = Just (Vector.replicate 1024 0.1)
                    , sparseVector = Nothing
                    , id = Nothing
                    }

                HUnit.assertEqual "" 1 (Vector.length matches)

                deleteVectors DeleteVectors
                    { ids = Nothing
                    , deleteAll = Just True
                    , namespace = Just namespace
                    , filter = Nothing
                    }

                return ()