pinecone
This provides a binding to Pinecone’s API using servant
Example usage:
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE OverloadedStrings #-}
import Pinecone
import Pinecone.Indexes
import Pinecone.Search
import Pinecone.Vectors
import qualified Control.Exception as Exception
import qualified Data.Text as Text
import qualified System.Environment as Environment
main :: IO ()
main = do
    controlEnv <- getClientEnv "https://api.pinecone.io"
    key <- Environment.getEnv "PINECONE_KEY"
    let token = Text.pack key
    let ControlMethods{..} = makeControlMethods controlEnv token
    let open = createIndexWithEmbedding _CreateIndexWithEmbedding
            { name = "test"
            , cloud = AWS
            , region = "us-east-1"
            , embed = EmbedRequest
                { model = "llama-text-embed-v2"
                , metric = Nothing
                , read_parameters = Nothing
                , write_parameters = Nothing
                }
            }
    let close IndexModel{ name } = deleteIndex name
    Exception.bracket open close \IndexModel{ name, host } -> do
        let waitUntilIndexReady = do
                IndexModel{ status } <- describeIndex name
                let Status{ ready } = status
                if ready
                    then return ()
                    else waitUntilIndexReady
        waitUntilIndexReady
        dataEnv <- getClientEnv host
        let DataMethods{..} = makeDataMethods dataEnv token
        upsertText "test" _Record{ id = "hi", text = "Hello, world!" }
        upsertText "test" _Record{ id = "bye", text = "Goodbye, world!" }
        -- Pinecone is eventually consistent, so we have to wait
        let waitUntilVectorsReady = do
                IndexStats{ totalVectorCount } <- getIndexStats _GetIndexStats
                if totalVectorCount == 2
                    then return ()
                    else waitUntilVectorsReady
        waitUntilVectorsReady
        Hits{ hits } <- searchWithText "test" SearchWithText
            { query = _Query{ top_k = 1, input = Just "best greeting"  }
            , fields = Nothing
            , rerank = Nothing
            }
        print (fmap _id hits) -- ["hi"]