packages feed

genai-lib-1.3: src/lib/GenAILib/Common.hs

{-# LANGUAGE DuplicateRecordFields #-}

module GenAILib.Common
  where

import Control.Arrow ((&&&))
import Control.Monad (when)
import Data.Aeson (Key, ToJSON, Value (Number, String), object, toJSON)
import Data.Aeson.Key (fromString)
import Data.Aeson.Types (Pair)
import Data.Maybe (mapMaybe)
import Data.String.Conv (toS)
import Data.Text.Lazy qualified as TL
import GHC.Generics (Generic)


newtype Model = Model TL.Text
  deriving Generic

instance ToJSON Model


newtype Prompt = Prompt TL.Text
  deriving Generic

instance ToJSON Prompt


splitAtColon :: String -> Maybe (String, String)
splitAtColon combinedStr = do
  let (leftSide, rightSide) = takeWhile (/= ':') &&& dropWhile (/= ':') $ combinedStr
  when (null rightSide) Nothing
  pure (leftSide, tail rightSide)


newtype RawOutput = RawOutput Bool


newtype LLMOptions = LLMOptions { v :: Value }
  deriving Generic

instance ToJSON LLMOptions


-- For debugging the LLM options parsing, unused most of the time
debugOptsJSON :: LLMOptions -> Value
debugOptsJSON = toJSON

convertOptions :: [String] -> LLMOptions
convertOptions = LLMOptions . object . pairs'

pairs' :: [String] -> [Pair]
pairs' = map convertTypes . mapMaybe splitAtColon

convertTypes :: (String, String) -> (Key, Value)
-- Turns out the only non-number option we're interested in for Ollama is "stop"
convertTypes (keystr@"stop", valstr) = (fromString keystr, String . toS $ valstr)
convertTypes (keystr, valstr) = (fromString keystr, Number . read $ valstr)