langchain-hs-0.0.5.0: src/Langchain/Embeddings/Ollama.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{- |
Module : Langchain.Embeddings.Ollama
Description : Ollama integration for text embeddings in LangChain Haskell
Copyright : (c) 2025-2026 Tushar Adhatrao
License : MIT
Maintainer : Tushar Adhatrao <tusharadhatrao@gmail.com>
Stability : experimental
Ollama implementation of LangChain's embedding interface using ollama-haskell 0.3.0.0.
-}
module Langchain.Embeddings.Ollama
( OllamaEmbeddings (..)
) where
import Control.Monad.Except (throwError)
import Control.Monad.IO.Class (liftIO)
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import Langchain.Core.Error (llmError)
import Langchain.DocumentLoader.Core (Document (..))
import Langchain.Embeddings.Core
import Ollama.API.Embed (EmbedRequest (..), EmbedResponse (..), embed)
import Ollama.Client (defaultClient)
import Ollama.Types.Common (ModelName (..))
import Ollama.Types.Options (ModelOptions)
data OllamaEmbeddings = OllamaEmbeddings
{ model :: Text
, defaultTruncate :: Maybe Bool
, defaultKeepAlive :: Maybe Text
, modelOptions :: Maybe ModelOptions
}
deriving (Show, Eq)
instance Embeddings OllamaEmbeddings where
embedDocuments (OllamaEmbeddings {..}) docs = do
client <- liftIO defaultClient
let inputs = map (TL.toStrict . pageContent) docs
req =
EmbedRequest
{ embModel = ModelName model
, embInput = Right inputs
, embTruncate = defaultTruncate
, embOptions = modelOptions
, embKeepAlive = defaultKeepAlive
, embDimensions = Nothing
}
eRes <- liftIO $ embed client req
case eRes of
Left ollamaErr -> throwError $ llmError (T.pack (show ollamaErr)) (Just "OllamaEmbeddings") Nothing
Right resp -> pure $ map (map realToFrac) (erEmbeddings resp)
embedQuery (OllamaEmbeddings {..}) query = do
client <- liftIO defaultClient
let req =
EmbedRequest
{ embModel = ModelName model
, embInput = Left query
, embTruncate = defaultTruncate
, embOptions = modelOptions
, embKeepAlive = defaultKeepAlive
, embDimensions = Nothing
}
eRes <- liftIO $ embed client req
case eRes of
Left err -> throwError $ llmError (T.pack (show err)) (Just "OllamaEmbeddings") Nothing
Right resp -> case erEmbeddings resp of
(vec : _) -> pure $ map realToFrac vec
[] -> throwError $ llmError "Embeddings are empty" (Just "OllamaEmbeddings") Nothing