pinecone

Servant bindings to Pinecone

Stackage Nightly 2025-04-24:1.0.0
Latest on Hackage:1.0.0

See all snapshots pinecone appears in

BSD-3-Clause licensed by Gabriella Gonzalez
Maintained by [email protected]
This version can be pinned in stack with:pinecone-1.0.0@sha256:369a1eb2c330020f6e47f9b02ba391dd8f766c5bb6479e47a8732d6cd18e3898,3008

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"]

Changes

1.0.0:

  • Initial release