pinecone-1.0.0: src/Pinecone/Vectors.hs
-- | Vectors
module Pinecone.Vectors
( -- * Main types
Namespace(..)
, UpsertVectors(..)
, _UpsertVectors
, UpsertStats(..)
, Vectors(..)
, UpdateVector(..)
, _UpdateVector
, DeleteVectors(..)
, _DeleteVectors
, VectorIDs(..)
, Record(..)
, _Record
-- * Other types
, VectorObject(..)
, SparseValues(..)
, Usage(..)
-- * Servant
, API
) where
import Pinecone.Metadata (Filter, Scalar)
import Pinecone.Pagination (Pagination)
import Pinecone.Prelude
import Prelude hiding (id)
import qualified Data.Map as Map
-- | The namespace of a record
newtype Namespace = Namespace{ text :: Text }
deriving newtype (Eq, FromJSON, IsString, Show, ToHttpApiData, ToJSON)
-- | Request body for @\/vectors\/upsert@
data UpsertVectors = UpsertVectors
{ vectors :: Vector VectorObject
, namespace :: Maybe Namespace
} deriving stock (Eq, Generic, Show)
deriving anyclass (FromJSON, ToJSON)
-- | Default `UpsertVectors`
_UpsertVectors :: UpsertVectors
_UpsertVectors = UpsertVectors
{ namespace = Nothing
}
-- | Response body for @\/vectors\/upsert@
data UpsertStats = UpsertStats
{ upsertedCount :: Natural
} deriving stock (Eq, Generic, Show)
deriving anyclass (FromJSON, ToJSON)
-- | Response body for @\/vectors\/fetch@
data Vectors = Vectors
{ vectors :: Map Text VectorObject
, namespace :: Namespace
, usage :: Maybe Usage
} deriving stock (Eq, Generic, Show)
deriving anyclass (FromJSON, ToJSON)
-- | Request body for @\/vectors\/update@
data UpdateVector = UpdateVector
{ id :: Text
, values :: Maybe (Vector Double)
, sparseValues :: Maybe SparseValues
, setMetadata :: Maybe (Map Text Scalar)
, namespace :: Maybe Namespace
} deriving stock (Eq, Generic, Show)
deriving anyclass (FromJSON, ToJSON)
-- | Default `UpdateVector`
_UpdateVector :: UpdateVector
_UpdateVector = UpdateVector
{ values = Nothing
, sparseValues = Nothing
, setMetadata = Nothing
, namespace = Nothing
}
-- | Request body for @\/vectors\/delete@
data DeleteVectors = DeleteVectors
{ ids :: Maybe (Vector Text)
, deleteAll :: Maybe Bool
, namespace :: Maybe Namespace
, filter :: Maybe Filter
} deriving stock (Eq, Generic, Show)
deriving anyclass (FromJSON, ToJSON)
-- | Default `DeleteVectors`
_DeleteVectors :: DeleteVectors
_DeleteVectors = DeleteVectors
{ deleteAll = Nothing
, namespace = Nothing
, filter = Nothing
}
-- | Response body for @\/vectors\/list@
data VectorIDs = VectorIDs
{ vectors :: Vector Text
, pagination :: Maybe Pagination
, namespace :: Namespace
, usage :: Usage
} deriving stock (Eq, Generic, Show)
instance FromJSON VectorIDs where
parseJSON value = do
VectorIDs_{..} <- parseJSON value
return VectorIDs{ vectors = do VectorID{ id } <- vectors; return id, ..}
data VectorIDs_ = VectorIDs_
{ vectors :: Vector VectorID
, pagination :: Maybe Pagination
, namespace :: Namespace
, usage :: Usage
} deriving stock (Eq, Generic, Show)
deriving anyclass (FromJSON, ToJSON)
-- | Record to upsert
data Record = Record
{ id :: Text
, text :: Text
, metadata :: Maybe (Map Text Scalar)
} deriving stock (Eq, Generic, Show)
instance FromJSON Record where
parseJSON value = do
m <- parseJSON value
text <- case Map.lookup "text" m of
Nothing -> do
fail "Missing text field"
Just v -> do
parseJSON v
id <- case Map.lookup "_id" m of
Nothing -> do
fail "Missing id field"
Just v -> do
parseJSON v
metadata <- fmap Just (traverse parseJSON (Map.delete "_id" (Map.delete "text" m)))
return Record{..}
instance ToJSON Record where
toJSON Record{..} = toJSON (Map.union reserved nonReserved)
where
reserved =
[ ("_id", toJSON id)
, ("text", toJSON text)
]
nonReserved = case metadata of
Nothing -> Map.empty
Just m -> Map.map toJSON m
-- | Default `Record`
_Record :: Record
_Record = Record
{ metadata = Nothing
}
-- | A vector
data VectorObject = VectorObject
{ id :: Text
, values :: Maybe (Vector Double)
, sparseValues :: Maybe SparseValues
, metadata :: Maybe (Map Text Scalar)
} deriving stock (Eq, Generic, Show)
deriving anyclass (FromJSON, ToJSON)
-- | Vector sparse data
data SparseValues = SparseValues
{ indices :: Vector Natural
, values :: Vector Double
} deriving stock (Eq, Generic, Show)
deriving anyclass (FromJSON, ToJSON)
-- | Vector ID
data VectorID = VectorID
{ id :: Text
} deriving stock (Eq, Generic, Show)
deriving anyclass (FromJSON, ToJSON)
-- | Usage
data Usage = Usage
{ readUnits :: Natural
} deriving stock (Eq, Generic, Show)
deriving anyclass (FromJSON, ToJSON)
-- | Servant API
type API =
( "vectors"
:> ( ( "upsert"
:> ReqBody '[JSON] UpsertVectors
:> Post '[JSON] UpsertStats
)
:<|> ( "fetch"
:> QueryParams "ids" Text
:> QueryParam "namespace" Namespace
:> Get '[JSON] Vectors
)
:<|> ( "update"
:> ReqBody '[JSON] UpdateVector
:> Post '[JSON] NoContent
)
:<|> ( "delete"
:> ReqBody '[JSON] DeleteVectors
:> Post '[JSON] NoContent
)
:<|> ( "list"
:> QueryParam "prefix" Text
:> QueryParam "limit" Natural
:> QueryParam "paginationToken" Text
:> QueryParam "namespace" Namespace
:> Get '[JSON] VectorIDs
)
)
)
:<|> ( "records"
:> "namespaces"
:> Capture "namespace" Namespace
:> "upsert"
:> ReqBody '[JSON] Record
:> PostCreated '[JSON] NoContent
)