packages feed

ollama-haskell-0.2.0.0: src/Data/Ollama/Show.hs

{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE OverloadedStrings #-}

{- |
Module      : Data.Ollama.Show
Copyright   : (c) 2025 Tushar Adhatrao
License     : MIT
Maintainer  : Tushar Adhatrao <tusharadhatrao@gmail.com>
Stability   : experimental
Description : Functionality for retrieving detailed information about models in the Ollama client.

This module provides functions to fetch detailed information about a specific model on the Ollama server.
It includes both high-level ('showModel', 'showModelM') and low-level ('showModelOps', 'showModelOpsM') APIs
for retrieving model details, with support for verbose output. The operation is performed via a POST request
to the "/api//show" endpoint, returning a 'ShowModelResponse' containing comprehensive model metadata.

The 'ShowModelOps' type configures the request, and 'ShowModelResponse' and 'ShowModelInfo' represent the
response structure. The module also re-exports 'CT.ModelDetails' for completeness.

Note: Verbose mode parsing is currently not fully supported.

Example:

>>> showModel "gemma3"
Right (ShowModelResponse {modelFile = "...", ...})

@since 1.0.0.0
-}
module Data.Ollama.Show
  ( -- * Show Model Info API
    showModel
  , showModelM
  , showModelOps
  , showModelOpsM

    -- * Response Types
  , ShowModelResponse (..)
  , ShowModelInfo (..)
  , CT.ModelDetails (..)
  ) where

import Control.Monad.IO.Class (MonadIO (liftIO))
import Data.Aeson
import Data.Ollama.Common.Config (OllamaConfig)
import Data.Ollama.Common.Error (OllamaError)
import Data.Ollama.Common.Types qualified as CT
import Data.Ollama.Common.Utils (commonNonStreamingHandler, withOllamaRequest)
import Data.Text (Text)
import GHC.Generics
import GHC.Int (Int64)

-- | Configuration options for requesting model information.
data ShowModelOps = ShowModelOps
  { name :: !Text
  -- ^ The name of the model to query (e.g., "gemma3").
  , verbose :: !(Maybe Bool)
  -- ^ Optional flag to request verbose output. Note: Verbose mode parsing is currently incomplete.
  }
  deriving (Show, Eq, Generic, ToJSON)

-- | Response structure for model information.
data ShowModelResponse = ShowModelResponse
  { modelFile :: !Text
  -- ^ The content of the model's Modelfile.
  , parameters :: !(Maybe Text)
  -- ^ Optional model parameters (e.g., temperature settings).
  , template :: !(Maybe Text)
  -- ^ Optional template used for the model.
  , details :: !CT.ModelDetails
  -- ^ General details about the model (e.g., format, family).
  , modelInfo :: !ShowModelInfo
  -- ^ Detailed technical information about the model.
  , license :: !(Maybe Text)
  -- ^ Optional license information for the model.
  --
  -- @since 0.2.0.0
  , capabilities :: Maybe [Text]
  -- ^ Optional list of model capabilities.
  --
  -- @since 0.2.0.0
  }
  deriving (Show, Eq)

-- | Detailed technical information about a model.
data ShowModelInfo = ShowModelInfo
  { generalArchitecture :: !(Maybe Text)
  -- ^ The architecture of the model (e.g., "llama").
  , generalFileType :: !(Maybe Int)
  -- ^ The file type identifier for the model.
  , generalParameterCount :: !(Maybe Int64)
  -- ^ The number of parameters in the model.
  , generalQuantizationVersion :: !(Maybe Int)
  -- ^ The quantization version used by the model.
  , llamaAttentionHeadCount :: !(Maybe Int)
  -- ^ Number of attention heads in the LLaMA model.
  , llamaAttentionHeadCountKV :: !(Maybe Int)
  -- ^ Number of key-value attention heads in the LLaMA model.
  , llamaAttentionLayerNormRMSEpsilon :: !(Maybe Float)
  -- ^ RMS epsilon for layer normalization in the LLaMA model.
  , llamaBlockCount :: !(Maybe Int)
  -- ^ Number of blocks in the LLaMA model.
  , llamaContextLength :: !(Maybe Int)
  -- ^ Context length supported by the LLaMA model.
  , llamaEmbeddingLength :: !(Maybe Int)
  -- ^ Embedding length used by the LLaMA model.
  , llamaFeedForwardLength :: !(Maybe Int)
  -- ^ Feed-forward layer length in the LLaMA model.
  , llamaRopeDimensionCount :: !(Maybe Int)
  -- ^ RoPE dimension count in the LLaMA model.
  , llamaRopeFreqBase :: !(Maybe Int64)
  -- ^ Base frequency for RoPE in the LLaMA model.
  , llamaVocabSize :: !(Maybe Int64)
  -- ^ Vocabulary size of the LLaMA model.
  , tokenizerGgmlBosToken_id :: !(Maybe Int)
  -- ^ BOS (beginning of sequence) token ID for the GGML tokenizer.
  , tokenizerGgmlEosToken_id :: !(Maybe Int)
  -- ^ EOS (end of sequence) token ID for the GGML tokenizer.
  , tokenizerGgmlMerges :: !(Maybe [Text])
  -- ^ List of merges for the GGML tokenizer.
  , tokenizerGgmlMode :: !(Maybe Text)
  -- ^ Mode of the GGML tokenizer.
  , tokenizerGgmlPre :: !(Maybe Text)
  -- ^ Pre-tokenization configuration for the GGML tokenizer.
  , tokenizerGgmlTokenType :: !(Maybe [Text])
  -- ^ Token type information for the GGML tokenizer.
  , tokenizerGgmlTokens :: !(Maybe [Text])
  -- ^ List of tokens for the GGML tokenizer.
  }
  deriving (Show, Eq)

-- | JSON parsing instance for 'ShowModelResponse'.
instance FromJSON ShowModelResponse where
  parseJSON = withObject "ShowModelResponse" $ \v ->
    ShowModelResponse
      <$> v .: "modelfile"
      <*> v .:? "parameters"
      <*> v .:? "template"
      <*> v .: "details"
      <*> v .: "model_info"
      <*> v .:? "license"
      <*> v .:? "capabilities"

-- | JSON parsing instance for 'ShowModelInfo'.
instance FromJSON ShowModelInfo where
  parseJSON = withObject "ModelInfo" $ \v ->
    ShowModelInfo
      <$> v .:? "general.architecture"
      <*> v .:? "general.file_type"
      <*> v .:? "general.parameter_count"
      <*> v .:? "general.quantization_version"
      <*> v .:? "llama.attention.head_count"
      <*> v .:? "llama.attention.head_count_kv"
      <*> v .:? "llama.attention.layer_norm_rms_epsilon"
      <*> v .:? "llama.block_count"
      <*> v .:? "llama.context_length"
      <*> v .:? "llama.embedding_length"
      <*> v .:? "llama.feed_forward_length"
      <*> v .:? "llama.rope.dimension_count"
      <*> v .:? "llama.rope.freq_base"
      <*> v .:? "llama.vocab_size"
      <*> v .:? "tokenizer.ggml.bos_token_id"
      <*> v .:? "tokenizer.ggml.eos_token_id"
      <*> v .:? "tokenizer.ggml.merges"
      <*> v .:? "tokenizer.ggml.model"
      <*> v .:? "tokenizer.ggml.pre"
      <*> v .:? "tokenizer.ggml.token_type"
      <*> v .:? "tokenizer.ggml.tokens"

{- | Retrieves model information with configuration options.

Sends a POST request to the "/api//show" endpoint to fetch detailed information about
the specified model. Supports verbose output if 'verbose' is 'Just True' (though verbose
mode parsing is currently incomplete). Returns 'Right' with a 'ShowModelResponse' on
success or 'Left' with an 'OllamaError' on failure.
-}
showModelOps ::
  -- | Model name
  Text ->
  -- | Optional verbose flag
  Maybe Bool ->
  -- | Optional 'OllamaConfig' (defaults to 'defaultOllamaConfig' if 'Nothing')
  Maybe OllamaConfig ->
  IO (Either OllamaError ShowModelResponse)
showModelOps modelName verbose_ mbConfig = do
  withOllamaRequest
    "/api//show"
    "POST"
    ( Just $
        ShowModelOps
          { name = modelName
          , verbose = verbose_
          }
    )
    mbConfig
    commonNonStreamingHandler

{- | Simplified API for retrieving model information.

A higher-level function that fetches model information using default settings for
verbose output and Ollama configuration. Suitable for basic use cases.
-}
showModel ::
  -- | Model name
  Text ->
  IO (Either OllamaError ShowModelResponse)
showModel modelName =
  showModelOps modelName Nothing Nothing

{- | MonadIO version of 'showModel' for use in monadic contexts.

Lifts the 'showModel' function into a 'MonadIO' context, allowing it to be used in
monadic computations.
-}
showModelM :: MonadIO m => Text -> m (Either OllamaError ShowModelResponse)
showModelM t = liftIO $ showModel t

{- | MonadIO version of 'showModelOps' for use in monadic contexts.

Lifts the 'showModelOps' function into a 'MonadIO' context, allowing it to be used in
monadic computations with full configuration options.
-}
showModelOpsM ::
  MonadIO m =>
  Text ->
  Maybe Bool ->
  Maybe OllamaConfig ->
  m (Either OllamaError ShowModelResponse)
showModelOpsM t v mbCfg = liftIO $ showModelOps t v mbCfg