ollama-haskell-0.3.0.0: src/Ollama/API/Embed.hs
{- |
Module : Ollama.API.Embed
Copyright : (c) 2024-2026 Tushar Adhatrao
License : MIT
Maintainer : tusharadhatrao@gmail.com
Stability : stable
Portability : portable
Vector embeddings API endpoint (@/api/embed@).
@since 1.0.0.0
-}
module Ollama.API.Embed (
EmbedRequest (..),
EmbedResponse (..),
embedRequest,
embed,
-- * Deprecated Legacy API
EmbeddingsRequest (..),
EmbeddingsResponse (..),
embeddings,
) where
import Control.Monad.IO.Class (MonadIO)
import Data.Aeson
import Data.Maybe (catMaybes)
import Data.Text (Text)
import GHC.Generics (Generic)
import Ollama.Client (OllamaClient)
import Ollama.Client.Internal (request)
import Ollama.Error (OllamaError)
import Ollama.Types.Common (Duration, ModelName)
import Ollama.Types.Options (ModelOptions)
{- | Embedding request payload for single text or batch list of texts.
@since 1.0.0.0
-}
data EmbedRequest = EmbedRequest
{ embModel :: !ModelName
, embInput :: !(Either Text [Text])
, embTruncate :: !(Maybe Bool)
, embOptions :: !(Maybe ModelOptions)
, embKeepAlive :: !(Maybe Text)
, embDimensions :: !(Maybe Int)
}
deriving stock (Eq, Show, Generic)
instance ToJSON EmbedRequest where
toJSON EmbedRequest {..} =
object $
catMaybes
[ Just $ "model" .= embModel
, Just $ case embInput of
Left single -> "input" .= single
Right multiple -> "input" .= multiple
, ("truncate" .=) <$> embTruncate
, ("options" .=) <$> embOptions
, ("keep_alive" .=) <$> embKeepAlive
, ("dimensions" .=) <$> embDimensions
]
{- | Create an 'EmbedRequest' for a list of input texts.
@since 1.0.0.0
-}
embedRequest :: ModelName -> [Text] -> EmbedRequest
embedRequest model inputs =
EmbedRequest
{ embModel = model
, embInput = Right inputs
, embTruncate = Nothing
, embOptions = Nothing
, embKeepAlive = Nothing
, embDimensions = Nothing
}
{- | Embedding response payload containing vector embeddings.
@since 1.0.0.0
-}
data EmbedResponse = EmbedResponse
{ erModel :: !ModelName
, erEmbeddings :: ![[Double]]
, erTotalDuration :: !(Maybe Duration)
, erLoadDuration :: !(Maybe Duration)
, erPromptEvalCount :: !(Maybe Int)
}
deriving stock (Eq, Show, Generic)
instance FromJSON EmbedResponse where
parseJSON = withObject "EmbedResponse" $ \v ->
EmbedResponse
<$> v .: "model"
<*> v .: "embeddings"
<*> v .:? "total_duration"
<*> v .:? "load_duration"
<*> v .:? "prompt_eval_count"
instance ToJSON EmbedResponse where
toJSON EmbedResponse {..} =
object
[ "model" .= erModel
, "embeddings" .= erEmbeddings
, "total_duration" .= erTotalDuration
, "load_duration" .= erLoadDuration
, "prompt_eval_count" .= erPromptEvalCount
]
{- | Generate vector embeddings.
@since 1.0.0.0
-}
embed :: (MonadIO m) => OllamaClient -> EmbedRequest -> m (Either OllamaError EmbedResponse)
embed client req = request client "POST" "/api/embed" (Just req)
{- | Legacy request payload for deprecated @/api/embeddings@ endpoint.
@since 1.0.0.0
-}
data EmbeddingsRequest = EmbeddingsRequest
{ ebrModel :: !ModelName
, ebrPrompt :: !Text
, ebrOptions :: !(Maybe ModelOptions)
, ebrKeepAlive :: !(Maybe Text)
}
deriving stock (Eq, Show, Generic)
instance ToJSON EmbeddingsRequest where
toJSON EmbeddingsRequest {..} =
object $
catMaybes
[ Just $ "model" .= ebrModel
, Just $ "prompt" .= ebrPrompt
, ("options" .=) <$> ebrOptions
, ("keep_alive" .=) <$> ebrKeepAlive
]
instance FromJSON EmbeddingsRequest where
parseJSON = withObject "EmbeddingsRequest" $ \v ->
EmbeddingsRequest
<$> v .: "model"
<*> v .: "prompt"
<*> v .:? "options"
<*> v .:? "keep_alive"
{- | Legacy response payload for deprecated @/api/embeddings@ endpoint.
@since 1.0.0.0
-}
newtype EmbeddingsResponse = EmbeddingsResponse
{ ebrEmbedding :: [Double]
}
deriving stock (Eq, Show, Generic)
instance FromJSON EmbeddingsResponse where
parseJSON = withObject "EmbeddingsResponse" $ \v ->
EmbeddingsResponse <$> v .: "embedding"
instance ToJSON EmbeddingsResponse where
toJSON EmbeddingsResponse {..} =
object ["embedding" .= ebrEmbedding]
{- | Generate vector embeddings using the deprecated @/api/embeddings@ endpoint.
@since 1.0.0.0
-}
embeddings ::
(MonadIO m) =>
OllamaClient ->
EmbeddingsRequest ->
m (Either OllamaError EmbeddingsResponse)
embeddings client req = request client "POST" "/api/embeddings" (Just req)
{-# DEPRECATED embeddings "Use embed instead" #-}