packages feed

llama-cpp-hs (empty) → 0.1.0.0

raw patch · 37 files changed

+4576/−0 lines, 37 filesdep +basedep +bytestringdep +derive-storablesetup-changed

Dependencies added: base, bytestring, derive-storable, llama-cpp-hs, tasty, tasty-hunit

Files

+ CHANGELOG.md view
@@ -0,0 +1,11 @@+# Changelog for `llama-cpp-hs`++All notable changes to this project will be documented in this file.++The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),+and this project adheres to the+[Haskell Package Versioning Policy](https://pvp.haskell.org/).++## Unreleased++## 0.1.0.0 - YYYY-MM-DD
+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2025 Tushar Adhatrao++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ README.md view
@@ -0,0 +1,86 @@+# llama-cpp-hs++Haskell bindings over [llama.cpp](https://github.com/ggml-org/llama.cpp)++This package provides both low-level and high-level interfaces to interact with the LLaMA C++ inference engine via Haskell FFI. +It allows you to run LLMs locally in pure C/C++, with support for GPU acceleration and quantized models.++## Features++- Low-level access to the full LLaMA C API using Haskell FFI.+- Higher-level convenience functions for easier model interaction.+- Examples provided for quickly getting started.++---++## Example Usage++Check out the `/examples` directory to see how to load and query models directly from Haskell.++---++## Setup++### 1. Using Nix (Recommended)++Ensure that [Nix](https://nixos.org/download.html) is installed on your system.++Then, enter the development shell:++```bash+nix-shell+```++Build the project using Stack:++```bash+stack build+```++### 2. Using Stack (Manual Setup)++If you prefer not to use Nix, follow these steps:++1. Clone and install [`llama.cpp`](https://github.com/ggml-org/llama.cpp) manually.+2. Make sure `llama.h` is available at `/usr/local/include/` and compiled `libllama.a` or `libllama.so` at `/usr/local/lib/`.+3. Install Stack if you haven’t already: https://docs.haskellstack.org/en/stable/install_and_upgrade/+4. Then proceed with:++```bash+stack build+```++---++## Models++To use this library, you'll need to download one of the many open-source GGUF models available on Hugging Face++Search for compatible GGUF models:+- [Hugging Face GGUF Models](https://huggingface.co/models?search=gguf)++---++## Current State++The codebase is still under active development and may undergo breaking changes. Use it with caution in production environments.++Pull requests, issues, and community contributions are highly encouraged!++---++## Contributing++Contributions are welcome!++---++## License++This project is licensed under [MIT](LICENSE).++---++## Thank You++Thanks to [ggml-org/llama.cpp](https://github.com/ggml-org/llama.cpp) for making local LLM inference fast, lightweight, and accessible!
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ cbits/helper.c view
@@ -0,0 +1,92 @@+#include <llama.h>+#include <stdlib.h>++void _llama_backend_init() {+    llama_backend_init(); +}++void _llama_backend_free() {+    llama_backend_free();     +}++void llama_batch_init_into(+    int32_t n_tokens,+    int32_t embd,+    int32_t n_seq_max,+    struct llama_batch * out) {+    +    if (out == NULL) return;++    *out = (struct llama_batch){+        .n_tokens = n_tokens,+        .token = NULL,       // Set by Haskell+        .embd = NULL,        // Set by Haskell+        .pos = NULL,         // Set by Haskell+        .n_seq_id = NULL,    // Set by Haskell+        .seq_id = NULL,      // Set by Haskell+        .logits = NULL,      // Set by Haskell+    };++    // Call the original llama_batch_init+    *out = llama_batch_init(n_tokens, embd, n_seq_max);+}++int32_t llama_decode_wrap(struct llama_context * ctx, struct llama_batch *batch) {+    llama_decode(ctx, *batch);+}++void llama_sampler_chain_default_params_into(struct llama_sampler_chain_params * out) {+    *out = llama_sampler_chain_default_params();+}++struct llama_model * llama_model_load_from_file_wrap (const char * path_model, const struct llama_model_params * params) {+    return llama_model_load_from_file(path_model, *params);+}++struct llama_context * llama_init_from_model_into(struct llama_model * model, const struct llama_context_params * params) {+    return llama_init_from_model(model, *params);+}++void llama_batch_free_wrap(struct llama_batch * batch) {+    llama_batch_free(*batch);+}++void llama_batch_get_one_into(llama_token * tokens+            , int32_t n_tokens, struct llama_batch * out_batch) {+    if (out_batch == NULL) {+        return; // invalid output pointer+    }+    *out_batch = llama_batch_get_one(tokens, n_tokens);+}++void llama_pooling_type_into(const struct llama_context * ctx, int * out) {+    *out = llama_pooling_type(ctx);+}++void llama_model_rope_type_into(const struct llama_model * model, int * out) {+    *out = llama_model_rope_type(model);+}++void llama_context_default_params_into(struct llama_context_params* out) {+    if (out != NULL) {+        *out = llama_context_default_params();+    }+}++void llama_kv_cache_view_init_into(const struct llama_context * ctx, int32_t n_seq_max, struct llama_kv_cache_view* out) {+    if (out != NULL) {+        *out = llama_kv_cache_view_init(ctx, n_seq_max);+    }+}++void llama_perf_context_into(const struct llama_context * ctx, struct llama_perf_context_data* out ) {+    if (out != NULL) {+        *out = llama_perf_context(ctx);+    }+}++void llama_perf_sampler_into(const struct llama_sampler * chain, struct llama_perf_sampler_data* out) {+    if (out != NULL) {+        *out = llama_perf_sampler(chain);+    }+}
+ llama-cpp-hs.cabal view
@@ -0,0 +1,94 @@+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.38.0.+--+-- see: https://github.com/sol/hpack++name:           llama-cpp-hs+version:        0.1.0.0+synopsis:       Haskell FFI bindings to the llama.cpp LLM inference library+description:    Haskell bindings for [llama.cpp](https://github.com/ggerganov/llama.cpp), a performant, C++-based inference engine for running large language models (LLMs) like LLaMA, Mistral, Qwen, and others directly on local hardware.+category:       ai, ffi, natural-language-processing+homepage:       https://github.com/tusharad/llama-cpp-hs#readme+bug-reports:    https://github.com/tusharad/llama-cpp-hs/issues+author:         tushar+maintainer:     tusharadhatrao@gmail.com+copyright:      2025 tushar+license:        MIT+license-file:   LICENSE+build-type:     Simple+extra-source-files:+    README.md+    CHANGELOG.md++source-repository head+  type: git+  location: https://github.com/tusharad/llama-cpp-hs++library+  exposed-modules:+      Llama.Adapter+      Llama.Backend+      Llama.ChatTemplate+      Llama.Context+      Llama.Decode+      Llama.Internal.Foreign+      Llama.Internal.Foreign.Adapter+      Llama.Internal.Foreign.Backend+      Llama.Internal.Foreign.ChatTemplate+      Llama.Internal.Foreign.Context+      Llama.Internal.Foreign.Decode+      Llama.Internal.Foreign.GGML+      Llama.Internal.Foreign.KVCache+      Llama.Internal.Foreign.Model+      Llama.Internal.Foreign.Performance+      Llama.Internal.Foreign.Sampler+      Llama.Internal.Foreign.Split+      Llama.Internal.Foreign.State+      Llama.Internal.Foreign.Tokenize+      Llama.Internal.Foreign.Vocab+      Llama.Internal.Types+      Llama.Internal.Types.Params+      Llama.KVCache+      Llama.Model+      Llama.Performance+      Llama.Sampler+      Llama.Split+      Llama.State+      Llama.Tokenize+      Llama.Vocab+  other-modules:+      Paths_llama_cpp_hs+  hs-source-dirs:+      src+  ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints+  include-dirs:+      cbits+  c-sources:+      cbits/helper.c+  extra-lib-dirs:+      /usr/local/lib+  extra-libraries:+      llama+  build-depends:+      base >=4.7 && <5+    , bytestring >=0.9 && <0.13+    , derive-storable >=0.2 && <0.4+  default-language: Haskell2010++test-suite llama-cpp-hs-test+  type: exitcode-stdio-1.0+  main-is: Spec.hs+  other-modules:+      Paths_llama_cpp_hs+  hs-source-dirs:+      test+  ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      base >=4.7 && <5+    , bytestring >=0.9 && <0.13+    , derive-storable >=0.2 && <0.4+    , llama-cpp-hs+    , tasty+    , tasty-hunit+  default-language: Haskell2010
+ src/Llama/Adapter.hs view
@@ -0,0 +1,92 @@+{- |+Module      : Llama.Adapter+Description : Adapter interface for llama-cpp+Copyright   : (c) 2025 Tushar Adhatrao+License     : MIT+Maintainer  : Tushar Adhatrao <tusharadhatrao@gmail.com>+-}+module Llama.Adapter (+    initAdapterLora+   , setAdapterLora+    , rmAdapterLora+    , clearAdapterLora+    , applyAdapterCVec+) where++import Foreign+import Foreign.C.String+import Llama.Internal.Foreign+import Llama.Internal.Types+import Foreign.C (CFloat)++{- | Initialize a LoRA adapter from a file path.+This function wraps the C function 'llama_adapter_lora_init'+and returns a managed AdapterLora object.+-}+initAdapterLora :: Model -> FilePath -> IO (Either String AdapterLora)+initAdapterLora (Model modelFPtr) path = do+  withForeignPtr modelFPtr $ \modelPtr -> do+    withCString path $ \cPath -> do+      adapter@(CLlamaAdapterLora adapterPtr) <-+        c_llama_adapter_lora_init (CLlamaModel modelPtr) cPath+      if adapter == CLlamaAdapterLora nullPtr+        then return $ Left "Failed to initialize LoRA adapter"+        else do+          -- We directly use c_llama_adapter_lora_free as the finalizer+          fp <- newForeignPtr p_llama_adapter_lora_free adapterPtr+          return $ Right $ AdapterLora fp++-- | Apply a LoRA adapter with a given scale.+setAdapterLora :: Context -> AdapterLora -> Float -> IO (Either String ())+setAdapterLora (Context ctxFPtr) (AdapterLora adapterFPtr) scale = do+  result <- withForeignPtr ctxFPtr $ \ctxPtr ->+    withForeignPtr adapterFPtr $ \adapterPtr ->+      c_llama_set_adapter_lora+        (CLlamaContext ctxPtr)+        (CLlamaAdapterLora adapterPtr)+        (realToFrac scale)+  if result == -1+    then return $ Left "Failed to set LoRA adapter"+    else return $ Right ()++-- | Remove a previously applied LoRA adapter.+rmAdapterLora :: Context -> AdapterLora -> IO (Either String ())+rmAdapterLora (Context ctxFPtr) (AdapterLora adapterFPtr) = do+  result <- withForeignPtr ctxFPtr $ \ctxPtr ->+    withForeignPtr adapterFPtr $ \adapterPtr ->+      c_llama_rm_adapter_lora (CLlamaContext ctxPtr) (CLlamaAdapterLora adapterPtr)+  if result == -1+    then return $ Left "Failed to remove LoRA adapter"+    else return $ Right ()++-- | Clear all active LoRA adapters from the context.+clearAdapterLora :: Context -> IO ()+clearAdapterLora (Context ctxFPtr) =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    c_llama_clear_adapter_lora (CLlamaContext ctxPtr)++-- | Apply a context vector (cvec).+applyAdapterCVec :: Context -> Maybe [Float] -> Int -> Int -> Int -> IO (Either String ())+applyAdapterCVec (Context ctxFPtr) mValues n_embd il_start il_end = do+  (ptr, len) <- case mValues of+    Nothing -> pure (nullPtr, 0 :: Int)+    Just vs -> do+      arrayPtr <- floatArrayToPtr vs+      pure (arrayPtr, length vs)+  result <- withForeignPtr ctxFPtr $ \ctxPtr ->+    c_llama_apply_adapter_cvec+      (CLlamaContext ctxPtr)+      ptr+      (fromIntegral len)+      (fromIntegral n_embd)+      (fromIntegral il_start)+      (fromIntegral il_end)+  if result == -1+    then return $ Left "Failed to apply context vector"+    else return $ Right ()++floatArrayToPtr :: [Float] -> IO (Ptr CFloat)+floatArrayToPtr xs = do+  ptr <- mallocBytes (length xs * sizeOf (undefined :: CFloat))+  pokeArray ptr (map realToFrac xs)+  return ptr
+ src/Llama/Backend.hs view
@@ -0,0 +1,22 @@+{- |+Module      : Llama.Backend+Description : Backend related functions for llama-cpp+Copyright   : (c) 2025 Tushar Adhatrao+License     : MIT+Maintainer  : Tushar Adhatrao <tusharadhatrao@gmail.com>+-}+module Llama.Backend (+    llamaBackendInit+    , llamaBackendFree+) where+{-+Backend and intialization related functions for Llama.cpp+-}++import Llama.Internal.Foreign.Backend++llamaBackendInit :: IO ()+llamaBackendInit = c_llama_backend_init++llamaBackendFree :: IO ()+llamaBackendFree = c_llama_backend_free
+ src/Llama/ChatTemplate.hs view
@@ -0,0 +1,104 @@+{- |+Module      : Llama.ChatTemplate+Description : Chat template related functions for llama-cpp+Copyright   : (c) 2025 Tushar Adhatrao+License     : MIT+Maintainer  : Tushar Adhatrao <tusharadhatrao@gmail.com>+-}+module Llama.ChatTemplate (+    ChatMessage (..)+    , toCLlamaChatMessage+   , chatApplyTemplate+   , chatGetBuiltinTemplates+  ) where++import Data.Functor+import Foreign+import Foreign.C.String+import Llama.Internal.Foreign+import Llama.Internal.Types++data ChatMessage = ChatMessage+  { chatRole :: String+  , chatContent :: String+  }+  deriving (Show, Eq)++toCLlamaChatMessage :: ChatMessage -> IO LlamaChatMessage+toCLlamaChatMessage msg = do+  rolePtr <- newCString (chatRole msg)+  contentPtr <- newCString (chatContent msg)+  return $ LlamaChatMessage rolePtr contentPtr++-- | Apply a chat template to format a conversation.+chatApplyTemplate ::+  -- | Optional custom template (uses built-in if Nothing)+  Maybe String ->+  -- | List of chat messages+  [ChatMessage] ->+  -- | Add assistant token at end?+  Bool ->+  -- | Buffer size (suggested: 4096)+  Int ->+  -- | Returns formatted string or error message+  IO (Either String String)+chatApplyTemplate mTemplate messages addAssist bufferSize = do+  let nMessages = length messages+      bufSize = max bufferSize (nMessages * 64) -- Heuristic fallback+  templateCString <- maybe (return nullPtr) newCString mTemplate+  msgs <- mapM toCLlamaChatMessage messages+  cMessages <- withArray msgs $ \ptr ->+    return ptr++  allocaBytes bufSize $ \bufPtr -> do+    result <-+      c_llama_chat_apply_template+        templateCString+        cMessages+        (fromIntegral nMessages)+        (if addAssist then 1 else 0)+        bufPtr+        (fromIntegral bufSize)++    if result < 0+      then return $ Left "Failed to apply chat template"+      else do+        let actualSize = fromIntegral result+        if actualSize >= bufSize+          then -- Need larger buffer+            allocaBytes actualSize $ \newBufPtr -> do+              result' <-+                c_llama_chat_apply_template+                  templateCString+                  cMessages+                  (fromIntegral nMessages)+                  (if addAssist then 1 else 0)+                  newBufPtr+                  (fromIntegral actualSize)+              if result' < 0+                then return $ Left "Failed to apply chat template after resize"+                else peekCString newBufPtr <&> Right+          else do+            str <- peekCString bufPtr+            return $ Right str++-- | Get list of available built-in chat templates.+chatGetBuiltinTemplates :: IO [String]+chatGetBuiltinTemplates = do+  -- First get number of templates+  numTemplates <- c_llama_chat_builtin_templates nullPtr 0+  let maxTemplates = fromIntegral numTemplates++  if numTemplates <= 0+    then return []+    else do+      -- Allocate array of CString pointers+      arrPtr <- mallocArray maxTemplates+      result <- c_llama_chat_builtin_templates arrPtr (fromIntegral maxTemplates)+      if result < 0+        then return []+        else do+          cstrs <- peekArray maxTemplates arrPtr+          strs <- mapM peekCString cstrs+          free arrPtr+          return strs
+ src/Llama/Context.hs view
@@ -0,0 +1,98 @@+{- |+Module      : Llama.Context+Description : High level context interface for llama-cpp+Copyright   : (c) 2025 Tushar Adhatrao+License     : MIT+Maintainer  : Tushar Adhatrao <tusharadhatrao@gmail.com>+-}+module Llama.Context (+    supportsRpc+, supportsGpuOffload+, supportsMLock+, supportsMMap+, getMaxDevices+, getTimeUs+, getContextSize+, getBatchSize+, getUnbatchedSize+, getMaxSeqCount+, getPoolingType+, detachThreadPool+, defaultContextParams+) where++import Llama.Internal.Foreign+import Llama.Internal.Types+import Llama.Internal.Types.Params+import Foreign++-- | Check if the backend supports remote procedure calls (RPC).+supportsRpc :: IO Bool+supportsRpc = toBool <$> llama_supports_rpc++-- | Check if the backend supports GPU offloading.+supportsGpuOffload :: IO Bool+supportsGpuOffload = toBool <$> llama_supports_gpu_offload++-- | Check if the backend supports locking model memory into RAM (no swapping).+supportsMLock :: IO Bool+supportsMLock = toBool <$> llama_supports_mlock++-- | Check if the backend supports memory mapping models.+supportsMMap :: IO Bool+supportsMMap = toBool <$> llama_supports_mmap++-- | Get maximum number of devices supported by the backend (e.g., GPUs).+getMaxDevices :: IO Int+getMaxDevices = fromIntegral <$> llama_max_devices++-- | Get current time in microseconds since some unspecified epoch.+getTimeUs :: IO Int+getTimeUs = fromIntegral <$> llama_time_us++-- | Get the maximum context size (n_ctx) of the model in the given context.+getContextSize :: Context -> IO Int+getContextSize (Context ctxFPtr) =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    fromIntegral <$> llama_n_ctx (CLlamaContext ctxPtr)++-- | Get the batch size (n_batch) used by the context.+getBatchSize :: Context -> IO Int+getBatchSize (Context ctxFPtr) =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    fromIntegral <$> llama_n_batch (CLlamaContext ctxPtr)++-- | Get the unbatched size (n_ubatch).+getUnbatchedSize :: Context -> IO Int+getUnbatchedSize (Context ctxFPtr) =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    fromIntegral <$> llama_n_ubatch (CLlamaContext ctxPtr)++-- | Get the maximum number of sequences supported.+getMaxSeqCount :: Context -> IO Int+getMaxSeqCount (Context ctxFPtr) =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    fromIntegral <$> llama_n_seq_max (CLlamaContext ctxPtr)++-- | Get the pooling type used by the context.+getPoolingType :: Context -> IO (Maybe LlamaPoolingType)+getPoolingType (Context ctxFPtr) =+  withForeignPtr ctxFPtr $ \ctxPtr -> alloca $ \outPtr -> do+    c_llama_pooling_type_into (CLlamaContext ctxPtr) outPtr+    val <- peek outPtr+    case val of+      -1 -> return Nothing+      _  -> return $ fromLlamaRopePoolingType val++-- | Detach the internal threadpool from the context.+detachThreadPool :: Context -> IO ()+detachThreadPool (Context ctxFPtr) =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    c_llama_detach_threadpool (CLlamaContext ctxPtr)++-- | Allocate and initialize a new 'LlamaContextParams' with defaults.+defaultContextParams :: IO LlamaContextParams+defaultContextParams = do+  alloca $ \ptr -> do+    c_llama_context_default_params_into (CLlamaContextParams ptr)+    peek ptr
+ src/Llama/Decode.hs view
@@ -0,0 +1,132 @@+{- |+Module      : Llama.Decode+Description : High level Decode interface for llama-cpp+Copyright   : (c) 2025 Tushar Adhatrao+License     : MIT+Maintainer  : Tushar Adhatrao <tusharadhatrao@gmail.com>+-}+module Llama.Decode+  ( batchInit+  , batchGetOne+  , freeBatch+  , encodeBatch+  , decodeBatch+  , setThreadCount+  , getThreadCount+  , getBatchThreadCount+  , setEmbeddingsEnabled+  , areEmbeddingsEnabled+  , setCausalAttention+  , setThreadCounts+  , setWarmupMode+  , synchronizeContext+  ) where++import Foreign+import Llama.Internal.Foreign+import Llama.Internal.Types++batchInit :: Int -> Int -> Int -> IO Batch+batchInit nTokens embd_ nSeqMax = do+  let cTokens = fromIntegral nTokens+      cEmb = fromIntegral embd_+      cSeqMax = fromIntegral nSeqMax+  alloca $ \ptr -> do+    c_llama_batch_init_into cTokens cEmb cSeqMax ptr+    return $ Batch ptr++-- | Create a batch from a list of tokens.+batchGetOne :: [LlamaToken] -> IO Batch+batchGetOne tokens = do+  let nTokens = length tokens+  alloca $ \ptr -> do+    withArray tokens $ \tokensPtr -> do+      c_llama_batch_get_one_into tokensPtr (fromIntegral nTokens) ptr+      return $ Batch ptr++-- | Free a batch of tokens allocated with initBatch+freeBatch :: Ptr LlamaBatch -> IO ()+freeBatch = c_llama_batch_free_wrap++-- | Encode tokens using the model context.+encodeBatch :: Context -> Batch -> IO (Either String ())+encodeBatch (Context ctxFPtr) (Batch batchPtr) = do+  result <- withForeignPtr ctxFPtr $ \ctxPtr ->+    c_llama_encode (CLlamaContext ctxPtr) batchPtr+  if result < 0+    then return $ Left "Encoding failed"+    else return $ Right ()++-- | Decode tokens using the model context.+decodeBatch :: Context -> Batch -> IO (Either String ())+decodeBatch (Context ctxFPtr) (Batch batchPtr) = do+  result <- withForeignPtr ctxFPtr $ \ctxPtr ->+    c_llama_decode_wrap (CLlamaContext ctxPtr) batchPtr+  if result < 0+    then return $ Left "Decoding failed"+    else return $ Right ()++-- | Set number of threads used for processing.+setThreadCount :: Context -> Int -> IO ()+setThreadCount ctx_ n = setThreadCounts ctx_ n n++-- | Set main and batch thread counts separately.+setThreadCounts :: Context -> Int -> Int -> IO ()+setThreadCounts (Context ctxFPtr) nThreads nBatchThreads =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    c_llama_set_n_threads+      (CLlamaContext ctxPtr)+      (fromIntegral nThreads)+      (fromIntegral nBatchThreads)++-- | Get current main thread count.+getThreadCount :: Context -> IO Int+getThreadCount (Context ctxFPtr) =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    fromIntegral <$> c_llama_n_threads (CLlamaContext ctxPtr)++-- | Get current batch thread count.+getBatchThreadCount :: Context -> IO Int+getBatchThreadCount (Context ctxFPtr) =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    fromIntegral <$> c_llama_n_threads_batch (CLlamaContext ctxPtr)++-- | Enable or disable embeddings output.+setEmbeddingsEnabled :: Context -> Bool -> IO ()+setEmbeddingsEnabled (Context ctxFPtr) enabled =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    c_llama_set_embeddings (CLlamaContext ctxPtr) (fromBool enabled)++-- | Check if embeddings are enabled.+areEmbeddingsEnabled :: Context -> IO Bool+areEmbeddingsEnabled (Context ctxFPtr) =+  withForeignPtr ctxFPtr $ \ctxPtr -> do+    resPtr <- c_llama_get_embeddings (CLlamaContext ctxPtr)+    toBool <$> peek resPtr++-- | Set causal attention mode.+setCausalAttention :: Context -> Bool -> IO ()+setCausalAttention (Context ctxFPtr) causal =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    c_llama_set_causal_attn (CLlamaContext ctxPtr) (fromBool causal)++-- | Set warmup mode (e.g. precompute KV cache).+setWarmupMode :: Context -> Bool -> IO ()+setWarmupMode (Context ctxFPtr) warm =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    c_llama_set_warmup (CLlamaContext ctxPtr) (fromBool warm)++{-+type AbortCallback = Ptr () -> IO CInt+-- | Set an abort callback to cancel long-running ops from another thread.+setAbortCallback :: Context -> FunPtr AbortCallback -> Ptr () -> IO ()+setAbortCallback (Context ctxFPtr) callback cbData =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    c_llama_set_abort_callback (CLlamaContext ctxPtr) callback cbData+    -}++-- | Block until all async work is complete.+synchronizeContext :: Context -> IO ()+synchronizeContext (Context ctxFPtr) =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    c_llama_synchronize (CLlamaContext ctxPtr)
+ src/Llama/Internal/Foreign.hs view
@@ -0,0 +1,29 @@+module Llama.Internal.Foreign+  ( module Llama.Internal.Foreign.Adapter+  , module Llama.Internal.Foreign.ChatTemplate+  , module Llama.Internal.Foreign.Context+  , module Llama.Internal.Foreign.Decode+  , module Llama.Internal.Foreign.KVCache+  , module Llama.Internal.Foreign.Model+  , module Llama.Internal.Foreign.Performance+  , module Llama.Internal.Foreign.Sampler+  , module Llama.Internal.Foreign.Split+  , module Llama.Internal.Foreign.State+  , module Llama.Internal.Foreign.Tokenize+  , module Llama.Internal.Foreign.Vocab+  , module Llama.Internal.Foreign.Backend+  ) where++import Llama.Internal.Foreign.Adapter+import Llama.Internal.Foreign.Backend+import Llama.Internal.Foreign.ChatTemplate+import Llama.Internal.Foreign.Context+import Llama.Internal.Foreign.Decode+import Llama.Internal.Foreign.KVCache+import Llama.Internal.Foreign.Model+import Llama.Internal.Foreign.Performance+import Llama.Internal.Foreign.Sampler+import Llama.Internal.Foreign.Split+import Llama.Internal.Foreign.State+import Llama.Internal.Foreign.Tokenize+import Llama.Internal.Foreign.Vocab
+ src/Llama/Internal/Foreign/Adapter.hs view
@@ -0,0 +1,80 @@+module Llama.Internal.Foreign.Adapter+  ( p_llama_adapter_lora_free+  , c_llama_adapter_lora_init+  , c_llama_adapter_lora_free+  , c_llama_set_adapter_lora+  , c_llama_rm_adapter_lora+  , c_llama_clear_adapter_lora+  , c_llama_apply_adapter_cvec+  ) where++import Foreign+import Foreign.C+import Llama.Internal.Types++{- | Foreign pointer to the C function for freeing LoRA adapters.+This allows Haskell's garbage collector to automatically free resources.+-}+foreign import ccall "&llama_adapter_lora_free"+  p_llama_adapter_lora_free :: FinalizerPtr CLlamaAdapterLora++{- | LLAMA_API struct llama_adapter_lora * llama_adapter_lora_init(+|             struct llama_model * model, const char * path_lora);+-}+foreign import ccall "llama_adapter_lora_init"+  c_llama_adapter_lora_init ::+    CLlamaModel -> -- model+    CString -> -- path_lora+    IO CLlamaAdapterLora++-- | LLAMA_API void llama_adapter_lora_free(struct llama_adapter_lora * adapter);+foreign import ccall "llama_adapter_lora_free"+  c_llama_adapter_lora_free ::+    CLlamaAdapterLora -> -- adapter+    IO ()++{- | LLAMA_API int32_t llama_set_adapter_lora(+|             struct llama_context * ctx,+|             struct llama_adapter_lora * adapter,+|             float scale);+-}+foreign import ccall "llama_set_adapter_lora"+  c_llama_set_adapter_lora ::+    CLlamaContext -> -- ctx+    CLlamaAdapterLora -> -- adapter+    CFloat -> -- scale+    IO CInt++{- | LLAMA_API int32_t llama_rm_adapter_lora(+|             struct llama_context * ctx,+|             struct llama_adapter_lora * adapter);+-}+foreign import ccall "llama_rm_adapter_lora"+  c_llama_rm_adapter_lora ::+    CLlamaContext -> -- ctx+    CLlamaAdapterLora -> -- adapter+    IO CInt++-- | LLAMA_API void llama_clear_adapter_lora(struct llama_context * ctx);+foreign import ccall "llama_clear_adapter_lora"+  c_llama_clear_adapter_lora ::+    CLlamaContext -> -- ctx+    IO ()++{- | LLAMA_API int32_t llama_apply_adapter_cvec(+|             struct llama_context * ctx,+|                    const float * data,+|                         size_t   len,+|                        int32_t   n_embd,+|                        int32_t   il_start,+|                        int32_t   il_end);+-}+foreign import ccall "llama_apply_adapter_cvec"+  c_llama_apply_adapter_cvec ::+    CLlamaContext -> -- ctx+    Ptr CFloat -> -- data (nullable)+    CSize -> -- len+    CInt -> -- n_embd+    CInt -> -- il_start+    CInt -> -- il_end+    IO CInt
+ src/Llama/Internal/Foreign/Backend.hs view
@@ -0,0 +1,11 @@+module Llama.Internal.Foreign.Backend+  ( -- * Backend+    c_llama_backend_init+  , c_llama_backend_free+  ) where++-- | Initialize the llama backend+foreign import ccall "_llama_backend_init" c_llama_backend_init :: IO ()++-- | Free the llama backend resources+foreign import ccall "_llama_backend_free" c_llama_backend_free :: IO ()
+ src/Llama/Internal/Foreign/ChatTemplate.hs view
@@ -0,0 +1,37 @@+module Llama.Internal.Foreign.ChatTemplate+  ( c_llama_chat_apply_template+  , c_llama_chat_builtin_templates+  ) where++import Foreign+import Foreign.C+import Llama.Internal.Types++{- | LLAMA_API int32_t llama_chat_apply_template(+|         const char * tmpl,+|         const struct llama_chat_message * chat,+|         size_t n_msg,+|         bool add_ass,+|         char * buf,+|         int32_t length);+-}+foreign import ccall "llama_chat_apply_template"+  c_llama_chat_apply_template ::+    CString -> -- tmpl (nullable)+    Ptr LlamaChatMessage -> -- chat (array of messages)+    CSize -> -- n_msg (number of messages)+    CBool -> -- add_ass (add assistant token)+    CString -> -- buf (output buffer)+    CInt -> -- length (size of buffer)++    -- | Returns required buffer size (if > length) or bytes written+    IO CInt++-- | LLAMA_API int32_t llama_chat_builtin_templates(const char ** output, size_t len);+foreign import ccall "llama_chat_builtin_templates"+  c_llama_chat_builtin_templates ::+    Ptr CString -> -- output (array of template names)+    CSize -> -- len (max number of names to write)++    -- | Returns total number of available templates+    IO CInt
+ src/Llama/Internal/Foreign/Context.hs view
@@ -0,0 +1,77 @@+module Llama.Internal.Foreign.Context+  ( llama_time_us+  , llama_max_devices+  , llama_supports_mmap+  , llama_supports_mlock+  , llama_supports_gpu_offload+  , llama_supports_rpc+  , llama_n_ctx+  , llama_n_batch+  , llama_n_ubatch+  , llama_n_seq_max+  , c_llama_pooling_type_into+  , c_llama_get_kv_self+  , c_llama_context_default_params_into+  , c_llama_detach_threadpool+  ) where++import Foreign+import Foreign.C+import Llama.Internal.Types+import Llama.Internal.Types.Params++-- LLAMA_API void llama_detach_threadpool(struct llama_context * ctx);+foreign import ccall "llama_detach_threadpool"+  c_llama_detach_threadpool :: CLlamaContext -> IO ()++foreign import ccall "llama_context_default_params_into"+  c_llama_context_default_params_into :: CLlamaContextParams -> IO ()++-- | Get current time in microseconds+foreign import ccall "llama_time_us"+  llama_time_us :: IO Int64++-- | Maximum number of devices supported+foreign import ccall "llama_max_devices"+  llama_max_devices :: IO CSize++-- | Features supported by backend+foreign import ccall "llama_supports_mmap"+  llama_supports_mmap :: IO CBool++foreign import ccall "llama_supports_mlock"+  llama_supports_mlock :: IO CBool++foreign import ccall "llama_supports_gpu_offload"+  llama_supports_gpu_offload :: IO CBool++foreign import ccall "llama_supports_rpc"+  llama_supports_rpc :: IO CBool++-- | Context-related accessors+foreign import ccall "llama_n_ctx"+  llama_n_ctx :: CLlamaContext -> IO CUInt++foreign import ccall "llama_n_batch"+  llama_n_batch :: CLlamaContext -> IO CUInt++foreign import ccall "llama_n_ubatch"+  llama_n_ubatch :: CLlamaContext -> IO CUInt++foreign import ccall "llama_n_seq_max"+  llama_n_seq_max :: CLlamaContext -> IO CUInt++-- | Get KV cache from context+foreign import ccall "llama_get_kv_self"+  c_llama_get_kv_self :: CLlamaContext -> IO CLlamaKVCache++-- | Get pooling type from context+foreign import ccall safe "llama_pooling_type_into"+  c_llama_pooling_type_into :: CLlamaContext -> Ptr CInt -> IO ()++-- llamaPoolingType :: CLlamaContext -> IO (Maybe LlamaPoolingType)+-- llamaPoolingType (CLlamaContext ctxPtr) =+--     alloca $ \outPtr -> do+--         c_llama_pooling_type_into ctxPtr outPtr+--         val <- peek outPtr+--         pure $ fromLlamaRopePoolingType val
+ src/Llama/Internal/Foreign/Decode.hs view
@@ -0,0 +1,147 @@+module Llama.Internal.Foreign.Decode (+  c_llama_batch_get_one_into+ , c_llama_batch_init_into+ , c_llama_batch_free_wrap+ , c_llama_encode+ , c_llama_decode_wrap+ , c_llama_set_n_threads+ , c_llama_n_threads+ , c_llama_n_threads_batch+ , c_llama_set_embeddings+ , c_llama_set_causal_attn+ , c_llama_set_warmup+ , c_llama_set_abort_callback+ , c_llama_synchronize+ , c_llama_get_logits+ , c_llama_get_logits_ith+ , c_llama_get_embeddings+ , c_llama_get_embeddings_ith+ , c_llama_get_embeddings_seq+) where++import Foreign+import Foreign.C+import Llama.Internal.Types++-- | LLAMA_API struct llama_batch llama_batch_get_one(llama_token * tokens, int32_t n_tokens);+foreign import ccall "llama_batch_get_one_into"+  c_llama_batch_get_one_into ::+    Ptr LlamaToken -> -- tokens+    CInt -> -- n_tokens+    Ptr LlamaBatch -> -- out_batch+    IO ()++-- | LLAMA_API struct llama_batch llama_batch_init(int32_t n_tokens, int32_t embd, int32_t n_seq_max);+foreign import ccall "llama_batch_init_into"+  c_llama_batch_init_into ::+    CInt -> -- n_tokens+    CInt -> -- embd+    CInt -> -- n_seq_max+    Ptr LlamaBatch -> -- out+    IO ()++-- | LLAMA_API void llama_batch_free(struct llama_batch batch);+foreign import ccall "llama_batch_free_wrap"+  c_llama_batch_free_wrap :: Ptr LlamaBatch -> IO ()++-- | LLAMA_API int32_t llama_encode(struct llama_context * ctx, struct llama_batch batch);+foreign import ccall "llama_encode"+  c_llama_encode ::+    CLlamaContext -> -- ctx+    Ptr LlamaBatch -> -- batch+    IO CInt++-- | LLAMA_API int32_t llama_decode(struct llama_context * ctx, struct llama_batch batch);+foreign import ccall "llama_decode_wrap"+  c_llama_decode_wrap ::+    CLlamaContext -> -- ctx+    Ptr LlamaBatch -> -- batch+    IO CInt++-- | LLAMA_API void llama_set_n_threads(struct llama_context * ctx, int32_t n_threads, int32_t n_threads_batch);+foreign import ccall "llama_set_n_threads"+  c_llama_set_n_threads ::+    CLlamaContext -> -- ctx+    CInt -> -- n_threads+    CInt -> -- n_threads_batch+    IO ()++-- | LLAMA_API int32_t llama_n_threads(struct llama_context * ctx);+foreign import ccall "llama_n_threads"+  c_llama_n_threads ::+    CLlamaContext -> -- ctx+    IO CInt++-- | LLAMA_API int32_t llama_n_threads_batch(struct llama_context * ctx);+foreign import ccall "llama_n_threads_batch"+  c_llama_n_threads_batch ::+    CLlamaContext -> -- ctx+    IO CInt++-- | LLAMA_API void llama_set_embeddings(struct llama_context * ctx, CBool embeddings);+foreign import ccall "llama_set_embeddings"+  c_llama_set_embeddings ::+    CLlamaContext -> -- ctx+    CBool -> -- embeddings+    IO ()++-- | LLAMA_API void llama_set_causal_attn(struct llama_context * ctx, CBool causal_attn);+foreign import ccall "llama_set_causal_attn"+  c_llama_set_causal_attn ::+    CLlamaContext -> -- ctx+    CBool -> -- causal_attn+    IO ()++-- | LLAMA_API void llama_set_warmup(struct llama_context * ctx, CBool warmup);+foreign import ccall "llama_set_warmup"+  c_llama_set_warmup ::+    CLlamaContext -> -- ctx+    CBool -> -- warmup+    IO ()++-- | LLAMA_API void llama_set_abort_callback(struct llama_context * ctx, ggml_abort_callback abort_callback, void * abort_callback_data);+foreign import ccall "llama_set_abort_callback"+  c_llama_set_abort_callback ::+    CLlamaContext -> -- ctx+    FunPtr (Ptr () -> IO CInt) -> -- abort_callback+    Ptr () -> -- abort_callback_data+    IO ()++-- | LLAMA_API void llama_synchronize(struct llama_context * ctx);+foreign import ccall "llama_synchronize"+  c_llama_synchronize ::+    CLlamaContext -> -- ctx+    IO ()++-- | LLAMA_API float * llama_get_logits(struct llama_context * ctx);+foreign import ccall "llama_get_logits"+  c_llama_get_logits ::+    CLlamaContext -> -- ctx+    IO (Ptr CFloat)++-- | LLAMA_API float * llama_get_logits_ith(struct llama_context * ctx, int32_t i);+foreign import ccall "llama_get_logits_ith"+  c_llama_get_logits_ith ::+    CLlamaContext -> -- ctx+    CInt -> -- i+    IO (Ptr CFloat)++-- | LLAMA_API float * llama_get_embeddings(struct llama_context * ctx);+foreign import ccall "llama_get_embeddings"+  c_llama_get_embeddings ::+    CLlamaContext -> -- ctx+    IO (Ptr CFloat)++-- | LLAMA_API float * llama_get_embeddings_ith(struct llama_context * ctx, int32_t i);+foreign import ccall "llama_get_embeddings_ith"+  c_llama_get_embeddings_ith ::+    CLlamaContext -> -- ctx+    CInt -> -- i+    IO (Ptr CFloat)++-- | LLAMA_API float * llama_get_embeddings_seq(struct llama_context * ctx, llama_seq_id seq_id);+foreign import ccall "llama_get_embeddings_seq"+  c_llama_get_embeddings_seq ::+    CLlamaContext -> -- ctx+    LlamaSeqId -> -- seq_id+    IO (Ptr CFloat)
+ src/Llama/Internal/Foreign/GGML.hs view
@@ -0,0 +1,4 @@+module Llama.Internal.Foreign.GGML where++-- GGML_API void               ggml_backend_load_all(void);+-- GGML_API int64_t ggml_time_us(void);
+ src/Llama/Internal/Foreign/KVCache.hs view
@@ -0,0 +1,141 @@+module Llama.Internal.Foreign.KVCache (+ +  c_llama_kv_cache_view_init_into+  , c_llama_kv_cache_view_free+  , c_llama_kv_cache_view_update+  , c_llama_kv_self_n_tokens+  , c_llama_kv_self_used_cells+  , c_llama_kv_self_clear+  , c_llama_kv_self_seq_rm+  , c_llama_kv_self_seq_cp+  , c_llama_kv_self_seq_keep+  , c_llama_kv_self_seq_add+  , c_llama_kv_self_seq_div+  , c_llama_kv_self_seq_pos_max+  , c_llama_kv_self_defrag+  , c_llama_kv_self_can_shift+  , c_llama_kv_self_update++) where++import Foreign+import Foreign.C+import Llama.Internal.Types++-- | LLAMA_API struct llama_kv_cache_view llama_kv_cache_view_init(const struct llama_context * ctx, int32_t n_seq_max);+foreign import ccall "llama_kv_cache_view_init_into"+    c_llama_kv_cache_view_init_into ::+        CLlamaContext ->  -- ctx+        CInt ->              -- n_seq_max+        Ptr LlamaKvCacheView ->+        IO ()++-- | LLAMA_API void llama_kv_cache_view_free(struct llama_kv_cache_view * view);+foreign import ccall "llama_kv_cache_view_free"+    c_llama_kv_cache_view_free ::+        Ptr LlamaKvCacheView ->  -- view+        IO ()++-- |LLAMA_API void llama_kv_cache_view_update(const struct llama_context * ctx, struct llama_kv_cache_view * view);+foreign import ccall "llama_kv_cache_view_update"+    c_llama_kv_cache_view_update ::+        CLlamaContext ->      -- ctx+        Ptr LlamaKvCacheView ->   -- view+        IO ()++-- | LLAMA_API int32_t llama_kv_self_n_tokens(const struct llama_context * ctx);+foreign import ccall "llama_kv_self_n_tokens"+  c_llama_kv_self_n_tokens ::+    CLlamaContext -> -- ctx+    IO CInt++-- | LLAMA_API int32_t llama_kv_self_used_cells(const struct llama_context * ctx);+foreign import ccall "llama_kv_self_used_cells"+  c_llama_kv_self_used_cells ::+    CLlamaContext -> -- ctx+    IO CInt++-- | LLAMA_API void llama_kv_self_clear(struct llama_context * ctx);+foreign import ccall "llama_kv_self_clear"+  c_llama_kv_self_clear ::+    CLlamaContext -> -- ctx+    IO ()++{- | LLAMA_API bool llama_kv_self_seq_rm(+|         struct llama_context * ctx, llama_seq_id seq_id, llama_pos p0, llama_pos p1);+-}+foreign import ccall "llama_kv_self_seq_rm"+  c_llama_kv_self_seq_rm ::+    CLlamaContext -> -- ctx+    LlamaSeqId -> -- seq_id+    LlamaPos -> -- p0+    LlamaPos -> -- p1+    IO CBool++{- | LLAMA_API void llama_kv_self_seq_cp(+|         struct llama_context * ctx, llama_seq_id seq_id_src, llama_seq_id seq_id_dst, llama_pos p0, llama_pos p1);+-}+foreign import ccall "llama_kv_self_seq_cp"+  c_llama_kv_self_seq_cp ::+    CLlamaContext -> -- ctx+    LlamaSeqId -> -- seq_id_src+    LlamaSeqId -> -- seq_id_dst+    LlamaPos -> -- p0+    LlamaPos -> -- p1+    IO ()++-- | LLAMA_API void llama_kv_self_seq_keep(struct llama_context * ctx, llama_seq_id seq_id);+foreign import ccall "llama_kv_self_seq_keep"+  c_llama_kv_self_seq_keep ::+    CLlamaContext -> -- ctx+    LlamaSeqId -> -- seq_id+    IO ()++{- | LLAMA_API void llama_kv_self_seq_add(+|         struct llama_context * ctx, llama_seq_id seq_id, llama_pos p0, llama_pos p1, llama_pos delta);+-}+foreign import ccall "llama_kv_self_seq_add"+  c_llama_kv_self_seq_add ::+    CLlamaContext -> -- ctx+    LlamaSeqId -> -- seq_id+    LlamaPos -> -- p0+    LlamaPos -> -- p1+    LlamaPos -> -- delta+    IO ()++{- | LLAMA_API void llama_kv_self_seq_div(+|         struct llama_context * ctx, llama_seq_id seq_id, llama_pos p0, llama_pos p1, int d);+-}+foreign import ccall "llama_kv_self_seq_div"+  c_llama_kv_self_seq_div ::+    CLlamaContext -> -- ctx+    LlamaSeqId -> -- seq_id+    LlamaPos -> -- p0+    LlamaPos -> -- p1+    CInt -> -- d+    IO ()++-- | LLAMA_API llama_pos llama_kv_self_seq_pos_max(struct llama_context * ctx, llama_seq_id seq_id);+foreign import ccall "llama_kv_self_seq_pos_max"+  c_llama_kv_self_seq_pos_max ::+    CLlamaContext -> -- ctx+    LlamaSeqId -> -- seq_id+    IO LlamaPos++-- | LLAMA_API void llama_kv_self_defrag(struct llama_context * ctx);+foreign import ccall "llama_kv_self_defrag"+  c_llama_kv_self_defrag ::+    CLlamaContext -> -- ctx+    IO ()++-- | LLAMA_API bool llama_kv_self_can_shift(const struct llama_context * ctx);+foreign import ccall "llama_kv_self_can_shift"+  c_llama_kv_self_can_shift ::+    Ptr CLlamaContext -> -- ctx+    IO CBool++-- | LLAMA_API void llama_kv_self_update(struct llama_context * ctx);+foreign import ccall "llama_kv_self_update"+  c_llama_kv_self_update ::+    CLlamaContext -> -- ctx+    IO ()
+ src/Llama/Internal/Foreign/Model.hs view
@@ -0,0 +1,212 @@+module Llama.Internal.Foreign.Model (+ +  p_llama_free+  , p_llama_model_free+  , c_llama_free+  , c_llama_init_from_model_wrap+  , c_llama_model_default_params+  , c_llama_model_load_from_file_wrap+  , c_llama_model_free+  , c_llama_model_get_vocab+  , c_llama_model_load_from_splits+  , c_llama_model_rope_type_into+  , c_llama_model_n_ctx_train+  , c_llama_model_n_embd+  , c_llama_model_n_layer+  , c_llama_model_n_head+  , c_llama_model_n_head_kv+  , c_llama_get_model+  , c_llama_model_rope_freq_scale_train+  , c_llama_vocab_type+  , c_llama_model_meta_val_str+  , c_llama_model_meta_count+  , c_llama_model_meta_key_by_index+  , c_llama_model_meta_val_str_by_index+  , c_llama_model_desc+  , c_llama_model_size+  , c_llama_model_chat_template+  , c_llama_model_n_params+  , c_llama_model_has_encoder+  , c_llama_model_has_decoder+  , c_llama_model_decoder_start_token+  , c_llama_model_is_recurrent+  , c_llama_model_quantize+  , c_llama_model_quantize_default_params++) where++import Foreign+import Foreign.C+import Llama.Internal.Types+import Llama.Internal.Types.Params++-- | Foreign pointer to the C function for freeing the context.+foreign import ccall "&llama_free"+  p_llama_free :: FinalizerPtr CLlamaContext++-- | Foreign pointer to the C function for freeing the model.+foreign import ccall "&llama_model_free"+  p_llama_model_free :: FinalizerPtr CLlamaModel++foreign import ccall "llama_free" c_llama_free :: CLlamaContext -> IO ()++foreign import ccall "llama_init_from_model_into"+  c_llama_init_from_model_wrap ::+    CLlamaModel -> CLlamaContextParams -> IO CLlamaContext++foreign import ccall "llama_model_default_params"+  c_llama_model_default_params :: CLlamaModelParams -> IO ()++foreign import ccall "llama_model_load_from_file_wrap"+  c_llama_model_load_from_file_wrap ::+    CString -> CLlamaModelParams -> IO CLlamaModel++foreign import ccall "llama_model_free"+  c_llama_model_free :: CLlamaModel -> IO ()++foreign import ccall "llama_model_get_vocab"+  c_llama_model_get_vocab :: CLlamaModel -> IO CLlamaVocab++-- LLAMA_API struct llama_model * llama_model_load_from_splits(+--                              const char ** paths,+--                                  size_t    n_paths,+--               struct llama_model_params    params);+foreign import ccall "llama_model_load_from_splits"+  c_llama_model_load_from_splits ::+    Ptr CString -> CSize -> CLlamaModelParams -> IO CLlamaModel++-- | Get RoPE type from model+foreign import ccall safe "llama_model_rope_type_into"+  c_llama_model_rope_type_into :: CLlamaModel -> Ptr CInt -> IO ()++-- | Get training context size+foreign import ccall "llama_model_n_ctx_train"+  c_llama_model_n_ctx_train :: CLlamaModel -> IO Int32++-- | Get embedding dimension+foreign import ccall "llama_model_n_embd"+  c_llama_model_n_embd :: CLlamaModel -> IO Int32++-- | Get number of layers+foreign import ccall "llama_model_n_layer"+  c_llama_model_n_layer :: CLlamaModel -> IO Int32++-- | Get number of heads+foreign import ccall "llama_model_n_head"+  c_llama_model_n_head :: CLlamaModel -> IO Int32++-- | Get number of key/value heads+foreign import ccall "llama_model_n_head_kv"+  c_llama_model_n_head_kv :: CLlamaModel -> IO Int32++-- | Get model from context+foreign import ccall "llama_get_model"+  c_llama_get_model :: CLlamaContext -> IO CLlamaModel++-- For float llama_model_rope_freq_scale_train(const struct llama_model * model);+foreign import ccall "llama_model_rope_freq_scale_train"+  c_llama_model_rope_freq_scale_train :: CLlamaModel -> IO CFloat++-- For enum llama_vocab_type llama_vocab_type(const struct llama_vocab * vocab);+foreign import ccall "llama_vocab_type"+  c_llama_vocab_type :: CLlamaVocab -> IO CInt++-- | LLAMA_API int32_t llama_model_meta_val_str(const struct llama_model * model, const char * key, char * buf, size_t buf_size);+foreign import ccall "llama_model_meta_val_str"+  c_llama_model_meta_val_str ::+    CLlamaModel -> -- model+    CString -> -- key+    CString -> -- buffer+    CSize -> -- buffer size+    IO CInt++-- | LLAMA_API int32_t llama_model_meta_count(const struct llama_model * model);+foreign import ccall "llama_model_meta_count"+  c_llama_model_meta_count ::+    CLlamaModel -> -- model+    IO CInt++-- | LLAMA_API int32_t llama_model_meta_key_by_index(const struct llama_model * model, int32_t i, char * buf, size_t buf_size);+foreign import ccall "llama_model_meta_key_by_index"+  c_llama_model_meta_key_by_index ::+    CLlamaModel -> -- model+    CInt -> -- index+    CString -> -- buffer+    CSize -> -- buffer size+    IO CInt++-- | LLAMA_API int32_t llama_model_meta_val_str_by_index(const struct llama_model * model, int32_t i, char * buf, size_t buf_size);+foreign import ccall "llama_model_meta_val_str_by_index"+  c_llama_model_meta_val_str_by_index ::+    CLlamaModel -> -- model+    CInt -> -- index+    CString -> -- buffer+    CSize -> -- buffer size+    IO CInt++-- | LLAMA_API int32_t llama_model_desc(const struct llama_model * model, char * buf, size_t buf_size);+foreign import ccall "llama_model_desc"+  c_llama_model_desc ::+    CLlamaModel -> -- model+    CString -> -- buffer+    CSize -> -- buffer size+    IO CInt++-- | LLAMA_API uint64_t llama_model_size(const struct llama_model * model);+foreign import ccall "llama_model_size"+  c_llama_model_size ::+    CLlamaModel -> -- model+    IO Word64++-- | LLAMA_API const char * llama_model_chat_template(const struct llama_model * model, const char * name);+foreign import ccall "llama_model_chat_template"+  c_llama_model_chat_template ::+    CLlamaModel -> -- model+    CString -> -- optional name (NULL = default)+    IO CString++-- | LLAMA_API uint64_t llama_model_n_params(const struct llama_model * model);+foreign import ccall "llama_model_n_params"+  c_llama_model_n_params ::+    CLlamaModel -> -- model+    IO Word64++-- | LLAMA_API bool llama_model_has_encoder(const struct llama_model * model);+foreign import ccall "llama_model_has_encoder"+  c_llama_model_has_encoder ::+    CLlamaModel -> -- model+    IO CBool++-- | LLAMA_API bool llama_model_has_decoder(const struct llama_model * model);+foreign import ccall "llama_model_has_decoder"+  c_llama_model_has_decoder ::+    CLlamaModel -> -- model+    IO CBool++-- | LLAMA_API llama_token llama_model_decoder_start_token(const struct llama_model * model);+foreign import ccall "llama_model_decoder_start_token"+  c_llama_model_decoder_start_token ::+    CLlamaModel -> -- model+    IO LlamaToken++-- | LLAMA_API bool llama_model_is_recurrent(const struct llama_model * model);+foreign import ccall "llama_model_is_recurrent"+  c_llama_model_is_recurrent ::+    CLlamaModel -> -- model+    IO CBool++{- | LLAMA_API uint32_t llama_model_quantize(+            const char * fname_inp,+            const char * fname_out,+            const llama_model_quantize_params * params);+-}+foreign import ccall "llama_model_quantize"+  c_llama_model_quantize ::+    CString -> -- fname_inp+    CString -> -- fname_out+    CLlamaModelQuantizeParams -> -- params+    IO Word32++-- LLAMA_API struct llama_model_quantize_params llama_model_quantize_default_params(void);+foreign import ccall "llama_model_quantize_default_params"+  c_llama_model_quantize_default_params :: IO CLlamaModelQuantizeParams
+ src/Llama/Internal/Foreign/Performance.hs view
@@ -0,0 +1,51 @@+module Llama.Internal.Foreign.Performance (+ +  c_llama_perf_context+  , c_llama_perf_context_print+  , c_llama_perf_context_reset+  , c_llama_perf_sampler+  , c_llama_perf_sampler_print+  , c_llama_perf_sampler_reset++) where++import Llama.Internal.Types+import Foreign++-- | LLAMA_API struct llama_perf_context_data llama_perf_context(const struct llama_context * ctx);+foreign import ccall "llama_perf_context_into"+    c_llama_perf_context ::+        CLlamaContext ->  -- ctx+        Ptr LlamaPerfContextData -> -- output buffer+        IO ()++-- | LLAMA_API void llama_perf_context_print(const struct llama_context * ctx);+foreign import ccall "llama_perf_context_print"+  c_llama_perf_context_print ::+    CLlamaContext -> -- ctx+    IO ()++-- | LLAMA_API void llama_perf_context_reset(struct llama_context * ctx);+foreign import ccall "llama_perf_context_reset"+  c_llama_perf_context_reset ::+    CLlamaContext -> -- ctx+    IO ()++-- | LLAMA_API struct llama_perf_sampler_data llama_perf_sampler(const struct llama_sampler * chain);+foreign import ccall "llama_perf_sampler_into"+    c_llama_perf_sampler ::+        (Ptr LlamaSampler) ->  -- chain+        Ptr LlamaPerfSamplerData ->  -- output buffer+        IO ()++-- | LLAMA_API void llama_perf_sampler_print(const struct llama_sampler * chain);+foreign import ccall "llama_perf_sampler_print"+  c_llama_perf_sampler_print ::+    (Ptr LlamaSampler) -> -- chain+    IO ()++-- | LLAMA_API void llama_perf_sampler_reset(struct llama_sampler * chain);+foreign import ccall "llama_perf_sampler_reset"+  c_llama_perf_sampler_reset ::+    Ptr LlamaSampler -> -- chain+    IO ()
+ src/Llama/Internal/Foreign/Sampler.hs view
@@ -0,0 +1,309 @@+module Llama.Internal.Foreign.Sampler (+  c_llama_sampler_init_greedy+  , c_llama_sampler_init_dist+  , c_llama_sampler_init_top_k+  , c_llama_sampler_init_top_p+  , c_llama_sampler_init_min_p+  , c_llama_sampler_init_typical+  , c_llama_sampler_init_temp+  , c_llama_sampler_init_temp_ext+  , c_llama_sampler_init_xtc+  , c_llama_sampler_init_top_n_sigma+  , c_llama_sampler_init_mirostat+  , c_llama_sampler_init_mirostat_v2+  , c_llama_sampler_init_grammar+  , c_llama_sampler_init_grammar_lazy_patterns+  , c_llama_sampler_init_penalties+  , c_llama_sampler_init_dry+  , c_llama_sampler_init_logit_bias+  , c_llama_sampler_init_infill+  , c_llama_sampler_sample+  , c_llama_sampler_get_seed+  , c_llama_sampler_chain_default_params_into+  , c_llama_sampler_init+  , c_llama_sampler_name+  , c_llama_sampler_accept+  , c_llama_sampler_apply+  , c_llama_sampler_reset+  , c_llama_sampler_clone+  , p_llama_sampler_free+  , c_llama_sampler_free+  , c_llama_sampler_chain_init+  , c_llama_sampler_chain_add+  , c_llama_sampler_chain_get+  , c_llama_sampler_chain_n+  , c_llama_sampler_chain_remove+) where++import Foreign+import Foreign.C+import Llama.Internal.Types+import Llama.Internal.Types.Params++foreign import ccall "llama_sampler_chain_default_params_into"+  c_llama_sampler_chain_default_params_into :: Ptr LlamaSamplerChainParams -> IO ()++-- | LLAMA_API struct llama_sampler * llama_sampler_init(const struct llama_sampler_i * iface, llama_sampler_context_t ctx);+foreign import ccall "llama_sampler_init"+  c_llama_sampler_init ::+    Ptr LlamaSamplerI -> -- iface (vtable)+    LlamaSamplerContext -> -- ctx (opaque context)+    IO (Ptr LlamaSampler)++-- | LLAMA_API const char * llama_sampler_name(const struct llama_sampler * smpl);+foreign import ccall "llama_sampler_name"+  c_llama_sampler_name ::+    Ptr LlamaSampler -> -- smpl+    IO CString++-- | LLAMA_API void llama_sampler_accept(struct llama_sampler * smpl, llama_token token);+foreign import ccall "llama_sampler_accept"+  c_llama_sampler_accept ::+    Ptr LlamaSampler -> -- smpl+    LlamaToken -> -- token+    IO ()++-- | LLAMA_API void llama_sampler_apply(struct llama_sampler * smpl, llama_token_data_array * cur_p);+foreign import ccall "llama_sampler_apply"+  c_llama_sampler_apply ::+    Ptr LlamaSampler -> -- smpl+    Ptr LlamaTokenDataArray -> -- cur_p+    IO ()++-- | LLAMA_API void llama_sampler_reset(struct llama_sampler * smpl);+foreign import ccall "llama_sampler_reset"+  c_llama_sampler_reset ::+    Ptr LlamaSampler -> -- smpl+    IO ()++-- | LLAMA_API struct llama_sampler * llama_sampler_clone(const struct llama_sampler * smpl);+foreign import ccall "llama_sampler_clone"+  c_llama_sampler_clone ::+    Ptr LlamaSampler -> -- smpl+    IO (Ptr LlamaSampler)++-- | Foreign pointer to the C function for freeing the SamplerChain.+foreign import ccall "&llama_sampler_free"+  p_llama_sampler_free :: FinalizerPtr LlamaSampler++-- | LLAMA_API void llama_sampler_free(struct llama_sampler * smpl);+foreign import ccall "llama_sampler_free"+  c_llama_sampler_free ::+    Ptr LlamaSampler -> -- smpl+    IO ()++-- | LLAMA_API struct llama_sampler * llama_sampler_chain_init(struct llama_sampler_chain_params params);+foreign import ccall "llama_sampler_chain_init"+  c_llama_sampler_chain_init ::+    LlamaSamplerChainParams -> -- params+    IO (Ptr LlamaSampler)++-- | LLAMA_API void llama_sampler_chain_add(struct llama_sampler * chain, struct llama_sampler * smpl);+foreign import ccall "llama_sampler_chain_add"+  c_llama_sampler_chain_add ::+    Ptr LlamaSampler -> -- chain+    Ptr LlamaSampler -> -- smpl+    IO ()++-- | LLAMA_API struct llama_sampler * llama_sampler_chain_get(const struct llama_sampler * chain, int32_t i);+foreign import ccall "llama_sampler_chain_get"+  c_llama_sampler_chain_get ::+    Ptr LlamaSampler -> -- chain+    CInt -> -- i+    IO (Ptr LlamaSampler)++-- | LLAMA_API int llama_sampler_chain_n(const struct llama_sampler * chain);+foreign import ccall "llama_sampler_chain_n"+  c_llama_sampler_chain_n ::+    Ptr LlamaSampler -> -- chain+    IO CInt++-- | LLAMA_API struct llama_sampler * llama_sampler_chain_remove(struct llama_sampler * chain, int32_t i);+foreign import ccall "llama_sampler_chain_remove"+  c_llama_sampler_chain_remove ::+    Ptr LlamaSampler -> -- chain+    CInt -> -- i+    IO (Ptr LlamaSampler)++-- | LLAMA_API struct llama_sampler * llama_sampler_init_greedy(void);+foreign import ccall "llama_sampler_init_greedy"+  c_llama_sampler_init_greedy ::+    IO (Ptr LlamaSampler)++-- | LLAMA_API struct llama_sampler * llama_sampler_init_dist(uint32_t seed);+foreign import ccall "llama_sampler_init_dist"+  c_llama_sampler_init_dist ::+    CUInt -> -- seed+    IO (Ptr LlamaSampler)++-- | LLAMA_API struct llama_sampler * llama_sampler_init_top_k(int32_t k);+foreign import ccall "llama_sampler_init_top_k"+  c_llama_sampler_init_top_k ::+    CInt -> -- k+    IO (Ptr LlamaSampler)++-- | LLAMA_API struct llama_sampler * llama_sampler_init_top_p(float p, size_t min_keep);+foreign import ccall "llama_sampler_init_top_p"+  c_llama_sampler_init_top_p ::+    CFloat -> -- p+    CSize -> -- min_keep+    IO (Ptr LlamaSampler)++-- | LLAMA_API struct llama_sampler * llama_sampler_init_min_p(float p, size_t min_keep);+foreign import ccall "llama_sampler_init_min_p"+  c_llama_sampler_init_min_p ::+    CFloat -> -- p+    CSize -> -- min_keep+    IO (Ptr LlamaSampler)++-- | LLAMA_API struct llama_sampler * llama_sampler_init_typical(float p, size_t min_keep);+foreign import ccall "llama_sampler_init_typical"+  c_llama_sampler_init_typical ::+    CFloat -> -- p+    CSize -> -- min_keep+    IO (Ptr LlamaSampler)++-- | LLAMA_API struct llama_sampler * llama_sampler_init_temp(float t);+foreign import ccall "llama_sampler_init_temp"+  c_llama_sampler_init_temp ::+    CFloat -> -- t+    IO (Ptr LlamaSampler)++-- | LLAMA_API struct llama_sampler * llama_sampler_init_temp_ext(float t, float delta, float exponent);+foreign import ccall "llama_sampler_init_temp_ext"+  c_llama_sampler_init_temp_ext ::+    CFloat -> -- t+    CFloat -> -- delta+    CFloat -> -- exponent+    IO (Ptr LlamaSampler)++-- | LLAMA_API struct llama_sampler * llama_sampler_init_xtc(float p, float t, size_t min_keep, uint32_t seed);+foreign import ccall "llama_sampler_init_xtc"+  c_llama_sampler_init_xtc ::+    CFloat -> -- p+    CFloat -> -- t+    CSize -> -- min_keep+    CUInt -> -- seed+    IO (Ptr LlamaSampler)++-- | LLAMA_API struct llama_sampler * llama_sampler_init_top_n_sigma(float n);+foreign import ccall "llama_sampler_init_top_n_sigma"+  c_llama_sampler_init_top_n_sigma ::+    CFloat -> -- n+    IO (Ptr LlamaSampler)++-- | LLAMA_API struct llama_sampler * llama_sampler_init_mirostat(int32_t n_vocab, uint32_t seed, float tau, float eta, int32_t m);+foreign import ccall "llama_sampler_init_mirostat"+  c_llama_sampler_init_mirostat ::+    CInt -> -- n_vocab+    CUInt -> -- seed+    CFloat -> -- tau+    CFloat -> -- eta+    CInt -> -- m+    IO (Ptr LlamaSampler)++-- | LLAMA_API struct llama_sampler * llama_sampler_init_mirostat_v2(uint32_t seed, float tau, float eta);+foreign import ccall "llama_sampler_init_mirostat_v2"+  c_llama_sampler_init_mirostat_v2 ::+    CUInt -> -- seed+    CFloat -> -- tau+    CFloat -> -- eta+    IO (Ptr LlamaSampler)++-- | LLAMA_API struct llama_sampler * llama_sampler_init_grammar(const struct llama_vocab * vocab, const char * grammar_str, const char * grammar_root);+foreign import ccall "llama_sampler_init_grammar"+  c_llama_sampler_init_grammar ::+    CLlamaVocab -> -- vocab+    CString -> -- grammar_str+    CString -> -- grammar_root+    IO (Ptr LlamaSampler)++{- | LLAMA_API struct llama_sampler * llama_sampler_init_grammar_lazy_patterns(+|         const struct llama_vocab * vocab,+|         const char * grammar_str,+|         const char * grammar_root,+|         const char ** trigger_patterns,+|         size_t num_trigger_patterns,+|         const llama_token * trigger_tokens,+|         size_t num_trigger_tokens);+-}+foreign import ccall "llama_sampler_init_grammar_lazy_patterns"+  c_llama_sampler_init_grammar_lazy_patterns ::+    CLlamaVocab -> -- vocab+    CString -> -- grammar_str+    CString -> -- grammar_root+    Ptr CString -> -- trigger_patterns (array of CStrings)+    CSize -> -- num_trigger_patterns+    Ptr LlamaToken -> -- trigger_tokens+    CSize -> -- num_trigger_tokens+    IO (Ptr LlamaSampler)++{- | LLAMA_API struct llama_sampler * llama_sampler_init_penalties(+|         int32_t penalty_last_n,+|         float penalty_repeat,+|         float penalty_freq,+|         float penalty_present);+-}+foreign import ccall "llama_sampler_init_penalties"+  c_llama_sampler_init_penalties ::+    CInt -> -- penalty_last_n+    CFloat -> -- penalty_repeat+    CFloat -> -- penalty_freq+    CFloat -> -- penalty_present+    IO (Ptr LlamaSampler)++{- | LLAMA_API struct llama_sampler * llama_sampler_init_dry(+|         const struct llama_vocab * vocab,+|         int32_t n_ctx_train,+|         float dry_multiplier,+|         float dry_base,+|         int32_t dry_allowed_length,+|         int32_t dry_penalty_last_n,+|         const char ** seq_breakers,+|         size_t num_breakers);+-}+foreign import ccall "llama_sampler_init_dry"+  c_llama_sampler_init_dry ::+    CLlamaVocab -> -- vocab+    CInt -> -- n_ctx_train+    CFloat -> -- dry_multiplier+    CFloat -> -- dry_base+    CInt -> -- dry_allowed_length+    CInt -> -- dry_penalty_last_n+    Ptr CString -> -- seq_breakers (array of CStrings)+    CSize -> -- num_breakers+    IO (Ptr LlamaSampler)++{- | LLAMA_API struct llama_sampler * llama_sampler_init_logit_bias(+|         int32_t n_vocab,+|         int32_t n_logit_bias,+|         const llama_logit_bias * logit_bias);+-}+foreign import ccall "llama_sampler_init_logit_bias"+  c_llama_sampler_init_logit_bias ::+    CInt -> -- n_vocab+    CInt -> -- n_logit_bias+    Ptr LlamaLogitBias -> -- logit_bias (opaque struct)+    IO (Ptr LlamaSampler)++-- | LLAMA_API struct llama_sampler * llama_sampler_init_infill(const struct llama_vocab * vocab);+foreign import ccall "llama_sampler_init_infill"+  c_llama_sampler_init_infill ::+    CLlamaVocab -> -- vocab+    IO (Ptr LlamaSampler)++-- | LLAMA_API uint32_t llama_sampler_get_seed(const struct llama_sampler * smpl);+foreign import ccall "llama_sampler_get_seed"+  c_llama_sampler_get_seed ::+    Ptr LlamaSampler -> -- smpl++    -- | Returns seed used by the sampler+    IO CUInt++-- | LLAMA_API llama_token llama_sampler_sample(struct llama_sampler * smpl, struct llama_context * ctx, int32_t idx);+foreign import ccall "llama_sampler_sample"+  c_llama_sampler_sample ::+    Ptr LlamaSampler -> -- smpl+    CLlamaContext -> -- ctx+    CInt -> -- idx+    IO LlamaToken
+ src/Llama/Internal/Foreign/Split.hs view
@@ -0,0 +1,46 @@+module Llama.Internal.Foreign.Split (+  c_llama_split_path+  , c_llama_split_prefix+  , c_llama_print_system_info+  , c_llama_log_set+) where++import Foreign+import Foreign.C++-- | LLAMA_API int llama_split_path(char * split_path, size_t maxlen, const char * path_prefix, int split_no, int split_count);+foreign import ccall "llama_split_path"+  c_llama_split_path ::+    CString -> -- split_path (output buffer)+    CSize -> -- maxlen+    CString -> -- path_prefix+    CInt -> -- split_no+    CInt -> -- split_count++    -- | Returns length of written string or required buffer size+    IO CInt++-- | LLAMA_API int llama_split_prefix(char * split_prefix, size_t maxlen, const char * split_path, int split_no, int split_count);+foreign import ccall "llama_split_prefix"+  c_llama_split_prefix ::+    CString -> -- split_prefix (output buffer)+    CSize -> -- maxlen+    CString -> -- split_path+    CInt -> -- split_no+    CInt -> -- split_count++    -- | Returns length of written string or required buffer size+    IO CInt++-- | LLAMA_API const char * llama_print_system_info(void);+foreign import ccall "llama_print_system_info"+  c_llama_print_system_info ::+    -- | Returns system info string+    IO CString++-- | LLAMA_API void llama_log_set(ggml_log_callback log_callback, void * user_data);+foreign import ccall "llama_log_set"+  c_llama_log_set ::+    FunPtr (CInt -> CString -> Ptr () -> IO ()) -> -- log_callback+    Ptr () -> -- user_data+    IO ()
+ src/Llama/Internal/Foreign/State.hs view
@@ -0,0 +1,92 @@+module Llama.Internal.Foreign.State where++import Foreign+import Foreign.C+import Llama.Internal.Types++-- | LLAMA_API size_t llama_state_get_size(struct llama_context * ctx);+foreign import ccall "llama_state_get_size"+  c_llama_state_get_size ::+    CLlamaContext -> -- ctx+    IO CSize++-- | LLAMA_API size_t llama_state_get_data(struct llama_context * ctx, uint8_t * dst, size_t size);+foreign import ccall "llama_state_get_data"+  c_llama_state_get_data ::+    CLlamaContext -> -- ctx+    Ptr Word8 -> -- dst (buffer)+    CSize -> -- size+    IO CSize++-- | LLAMA_API size_t llama_state_set_data(struct llama_context * ctx, const uint8_t * src, size_t size);+foreign import ccall "llama_state_set_data"+  c_llama_state_set_data ::+    CLlamaContext -> -- ctx+    Ptr Word8 -> -- src (buffer)+    CSize -> -- size+    IO CSize++-- | LLAMA_API bool llama_state_load_file(struct llama_context * ctx, const char * path_session, llama_token * tokens_out, size_t n_token_capacity, size_t * n_token_count_out);+foreign import ccall "llama_state_load_file"+  c_llama_state_load_file ::+    CLlamaContext -> -- ctx+    CString -> -- path_session+    Ptr LlamaToken -> -- tokens_out+    CSize -> -- n_token_capacity+    Ptr CSize -> -- n_token_count_out+    IO CBool++-- | LLAMA_API bool llama_state_save_file(struct llama_context * ctx, const char * path_session, const llama_token * tokens, size_t n_token_count);+foreign import ccall "llama_state_save_file"+  c_llama_state_save_file ::+    CLlamaContext -> -- ctx+    CString -> -- path_session+    Ptr LlamaToken -> -- tokens+    CSize -> -- n_token_count+    IO CBool++-- | LLAMA_API size_t llama_state_seq_get_size(struct llama_context * ctx, llama_seq_id seq_id);+foreign import ccall "llama_state_seq_get_size"+  c_llama_state_seq_get_size ::+    CLlamaContext -> -- ctx+    LlamaSeqId -> -- seq_id+    IO CSize++-- | LLAMA_API size_t llama_state_seq_get_data(struct llama_context * ctx, uint8_t * dst, size_t size, llama_seq_id seq_id);+foreign import ccall "llama_state_seq_get_data"+  c_llama_state_seq_get_data ::+    CLlamaContext -> -- ctx+    Ptr Word8 -> -- dst (buffer)+    CSize -> -- size+    LlamaSeqId -> -- seq_id+    IO CSize++-- | LLAMA_API size_t llama_state_seq_set_data(struct llama_context * ctx, const uint8_t * src, size_t size, llama_seq_id dest_seq_id);+foreign import ccall "llama_state_seq_set_data"+  c_llama_state_seq_set_data ::+    CLlamaContext -> -- ctx+    Ptr Word8 -> -- src (buffer)+    CSize -> -- size+    LlamaSeqId -> -- dest_seq_id+    IO CSize++-- | LLAMA_API size_t llama_state_seq_save_file(struct llama_context * ctx, const char * filepath, llama_seq_id seq_id, const llama_token * tokens, size_t n_token_count);+foreign import ccall "llama_state_seq_save_file"+  c_llama_state_seq_save_file ::+    CLlamaContext -> -- ctx+    CString -> -- filepath+    LlamaSeqId -> -- seq_id+    Ptr LlamaToken -> -- tokens+    CSize -> -- n_token_count+    IO CSize++-- | LLAMA_API size_t llama_state_seq_load_file(struct llama_context * ctx, const char * filepath, llama_seq_id dest_seq_id, llama_token * tokens_out, size_t n_token_capacity, size_t * n_token_count_out);+foreign import ccall "llama_state_seq_load_file"+  c_llama_state_seq_load_file ::+    CLlamaContext -> -- ctx+    CString -> -- filepath+    LlamaSeqId -> -- dest_seq_id+    Ptr LlamaToken -> -- tokens_out+    CSize -> -- n_token_capacity+    Ptr CSize -> -- n_token_count_out+    IO CSize
+ src/Llama/Internal/Foreign/Tokenize.hs view
@@ -0,0 +1,63 @@+module Llama.Internal.Foreign.Tokenize where++import Foreign+import Foreign.C+import Llama.Internal.Types++{- | LLAMA_API int32_t llama_tokenize(+|     const struct llama_vocab * vocab,+|     const char * text,+|     int32_t text_len,+|     llama_token * tokens,+|     int32_t n_tokens_max,+|     bool add_special,+|     bool parse_special);+-}+foreign import ccall "llama_tokenize"+  c_llama_tokenize ::+    CLlamaVocab -> -- vocab+    CString -> -- text+    CInt -> -- text_len+    Ptr LlamaToken -> -- tokens+    CInt -> -- n_tokens_max+    CBool -> -- add_special+    CBool -> -- parse_special+    IO CInt++{- | LLAMA_API int32_t llama_token_to_piece(+|     const struct llama_vocab * vocab,+|     llama_token token,+|     char * buf,+|     int32_t length,+|     int32_t lstrip,+|     bool special);+-}+foreign import ccall "llama_token_to_piece"+  c_llama_token_to_piece ::+    CLlamaVocab -> -- vocab+    LlamaToken -> -- token+    CString -> -- buf+    CInt -> -- length+    CInt -> -- lstrip+    CBool -> -- special+    IO CInt++{- | LLAMA_API int32_t llama_detokenize(+|     const struct llama_vocab * vocab,+|     const llama_token * tokens,+|     int32_t n_tokens,+|     char * text,+|     int32_t text_len_max,+|     bool remove_special,+|     bool unparse_special);+-}+foreign import ccall "llama_detokenize"+  c_llama_detokenize ::+    CLlamaVocab -> -- vocab+    Ptr LlamaToken -> -- tokens+    CInt -> -- n_tokens+    CString -> -- text+    CInt -> -- text_len_max+    CBool -> -- remove_special+    CBool -> -- unparse_special+    IO CInt
+ src/Llama/Internal/Foreign/Vocab.hs view
@@ -0,0 +1,133 @@+module Llama.Internal.Foreign.Vocab where++import Foreign.C+import Llama.Internal.Types++--LLAMA_API int32_t llama_n_vocab    (const struct llama_vocab * vocab)++foreign import ccall "llama_n_vocab" c_llama_n_vocab :: CLlamaVocab -> IO CInt++foreign import ccall "llama_vocab_n_tokens"+  c_llama_vocab_n_tokens ::+    CLlamaVocab -> IO CInt++-- | LLAMA_API const char * llama_vocab_get_text(const struct llama_vocab * vocab, llama_token token);+foreign import ccall "llama_vocab_get_text"+  c_llama_vocab_get_text ::+    CLlamaVocab -> -- vocab+    LlamaToken -> -- token+    IO CString++-- | LLAMA_API float llama_vocab_get_score(const struct llama_vocab * vocab, llama_token token);+foreign import ccall "llama_vocab_get_score"+  c_llama_vocab_get_score ::+    CLlamaVocab -> -- vocab+    LlamaToken -> -- token+    IO CFloat++-- | LLAMA_API enum llama_token_attr llama_vocab_get_attr(const struct llama_vocab * vocab, llama_token token);+foreign import ccall "llama_vocab_get_attr"+  c_llama_vocab_get_attr ::+    CLlamaVocab -> -- vocab+    LlamaToken -> -- token++    -- | Returns raw integer representing enum value+    IO CInt++-- | LLAMA_API bool llama_vocab_is_eog(const struct llama_vocab * vocab, llama_token token);+foreign import ccall "llama_vocab_is_eog"+  c_llama_vocab_is_eog ::+    CLlamaVocab -> -- vocab+    LlamaToken -> -- token+    IO CBool++-- | LLAMA_API bool llama_vocab_is_control(const struct llama_vocab * vocab, llama_token token);+foreign import ccall "llama_vocab_is_control"+  c_llama_vocab_is_control ::+    CLlamaVocab -> -- vocab+    LlamaToken -> -- token+    IO CBool++-- | LLAMA_API llama_token llama_vocab_bos(const struct llama_vocab * vocab); // beginning-of-sentence+foreign import ccall "llama_vocab_bos"+  c_llama_vocab_bos ::+    CLlamaVocab -> -- vocab+    IO LlamaToken++-- | LLAMA_API llama_token llama_vocab_eos(const struct llama_vocab * vocab); // end-of-sentence+foreign import ccall "llama_vocab_eos"+  c_llama_vocab_eos ::+    CLlamaVocab -> -- vocab+    IO LlamaToken++-- | LLAMA_API llama_token llama_vocab_eot(const struct llama_vocab * vocab); // end-of-turn+foreign import ccall "llama_vocab_eot"+  c_llama_vocab_eot ::+    CLlamaVocab -> -- vocab+    IO LlamaToken++-- | LLAMA_API llama_token llama_vocab_sep(const struct llama_vocab * vocab); // sentence separator+foreign import ccall "llama_vocab_sep"+  c_llama_vocab_sep ::+    CLlamaVocab -> -- vocab+    IO LlamaToken++-- | LLAMA_API llama_token llama_vocab_nl (const struct llama_vocab * vocab); // next-line+foreign import ccall "llama_vocab_nl"+  c_llama_vocab_nl ::+    CLlamaVocab -> -- vocab+    IO LlamaToken++-- | LLAMA_API llama_token llama_vocab_pad(const struct llama_vocab * vocab); // padding+foreign import ccall "llama_vocab_pad"+  c_llama_vocab_pad ::+    CLlamaVocab -> -- vocab+    IO LlamaToken++-- | LLAMA_API bool llama_vocab_get_add_bos(const struct llama_vocab * vocab);+foreign import ccall "llama_vocab_get_add_bos"+  c_llama_vocab_get_add_bos ::+    CLlamaVocab -> -- vocab+    IO CBool++-- | LLAMA_API bool llama_vocab_get_add_eos(const struct llama_vocab * vocab);+foreign import ccall "llama_vocab_get_add_eos"+  c_llama_vocab_get_add_eos ::+    CLlamaVocab -> -- vocab+    IO CBool++-- | LLAMA_API llama_token llama_vocab_fim_pre(const struct llama_vocab * vocab);+foreign import ccall "llama_vocab_fim_pre"+  c_llama_vocab_fim_pre ::+    CLlamaVocab -> -- vocab+    IO LlamaToken++-- | LLAMA_API llama_token llama_vocab_fim_suf(const struct llama_vocab * vocab);+foreign import ccall "llama_vocab_fim_suf"+  c_llama_vocab_fim_suf ::+    CLlamaVocab -> -- vocab+    IO LlamaToken++-- | LLAMA_API llama_token llama_vocab_fim_mid(const struct llama_vocab * vocab);+foreign import ccall "llama_vocab_fim_mid"+  c_llama_vocab_fim_mid ::+    CLlamaVocab -> -- vocab+    IO LlamaToken++-- | LLAMA_API llama_token llama_vocab_fim_pad(const struct llama_vocab * vocab);+foreign import ccall "llama_vocab_fim_pad"+  c_llama_vocab_fim_pad ::+    CLlamaVocab -> -- vocab+    IO LlamaToken++-- | LLAMA_API llama_token llama_vocab_fim_rep(const struct llama_vocab * vocab);+foreign import ccall "llama_vocab_fim_rep"+  c_llama_vocab_fim_rep ::+    CLlamaVocab -> -- vocab+    IO LlamaToken++-- | LLAMA_API llama_token llama_vocab_fim_sep(const struct llama_vocab * vocab);+foreign import ccall "llama_vocab_fim_sep"+  c_llama_vocab_fim_sep ::+    CLlamaVocab -> -- vocab+    IO LlamaToken
+ src/Llama/Internal/Types.hs view
@@ -0,0 +1,214 @@+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}++module Llama.Internal.Types+  ( -- * Types+    LlamaTokenData (..)+  , LlamaTokenDataArray (..)+  , LlamaBatch (..)+  , AddBos (..)+  , LlamaToken+  , LlamaKvCacheView (..)+  , LlamaSeqId+  , LlamaPos+  , LlamaChatMessage (..)+  , LlamaSamplerI (..)+  , LlamaSampler (..)+  , LlamaSamplerContext +  , LlamaPerfContextData (..)+  , LlamaPerfSamplerData (..)+  , LlamaLogitBias (..)++    -- * Raw pointers+  , CLlamaVocab (..)+  , CLlamaModel (..)+  , CLlamaContext (..)+  , CLlamaKVCache (..)+  , CLlamaAdapterLora (..)++    -- * Managed handles+  , Vocab (..)+  , Batch (..)+  , Model (..)+  , Context (..)+  , Sampler (..)+  , KVCache (..)+  , AdapterLora (..)+  ) where++import Foreign+import Foreign.C.String+import Foreign.C.Types+import Foreign.Storable.Generic+import GHC.Generics++data AddBos = Always | Never++data LlamaLogitBias = LlamaLogitBias+  { tokenLogitBias :: LlamaToken+  , bias  :: Float+  }+  deriving (Show, Eq, Generic, GStorable)++-- struct llama_adapter_lora++newtype CLlamaAdapterLora = CLlamaAdapterLora (Ptr CLlamaAdapterLora)+  deriving (Show, Eq)++-- | Raw pointer to llama_vocab struct+newtype CLlamaVocab = CLlamaVocab (Ptr CLlamaVocab)+  deriving (Show, Eq)++-- | Raw pointer to llama_model struct+newtype CLlamaModel = CLlamaModel (Ptr CLlamaModel)+  deriving (Show, Eq)++-- | Raw pointer to llama_context struct+newtype CLlamaContext = CLlamaContext (Ptr CLlamaContext)+  deriving (Show, Eq)++newtype CLlamaKVCache = CLlamaKVCache (Ptr CLlamaKVCache)+  deriving (Show, Eq)++-- | Managed batch pointer with automatic cleanup+newtype Batch = Batch (Ptr LlamaBatch)+  deriving (Show, Eq)++-- | Managed vocabulary handle with automatic cleanup.+newtype Vocab = Vocab (ForeignPtr CLlamaVocab)+  deriving (Show, Eq)++-- | Managed model handle with automatic cleanup.+newtype Model = Model (ForeignPtr CLlamaModel)+  deriving (Show, Eq)++-- | Managed context handle with automatic cleanup.+newtype Context = Context (ForeignPtr CLlamaContext)+  deriving (Show, Eq)++-- | Managed sampler handle with automatic cleanup.+newtype Sampler = Sampler (ForeignPtr LlamaSampler)+  deriving (Show, Eq)++newtype KVCache = KVCache (ForeignPtr CLlamaKVCache)+  deriving (Show, Eq)++newtype AdapterLora = AdapterLora (ForeignPtr CLlamaAdapterLora)+  deriving (Show, Eq)++-- type PtrLlamaContext = Ptr LlamaContext+type LlamaToken = CInt+type LlamaPos = CInt+type LlamaSeqId = CInt++data LlamaChatMessage = LlamaChatMessage+  { role :: CString+  -- ^ "system", "user", "assistant"+  , content :: CString+  -- ^ Message text+  }+  deriving (Show, Eq, Generic, GStorable)++data LlamaTokenData = LlamaTokenData+  { id :: LlamaToken+  -- ^ token id+  , logit :: CFloat+  -- ^ log-odds of the token+  , p :: CFloat+  -- ^ probability of the token+  }+  deriving (Show, Eq, Generic, GStorable)++data LlamaTokenDataArray = LlamaTokenDataArray+  { data_ :: Ptr LlamaTokenData+  , size_ :: CSize+  , selected :: CLong+  -- ^ this is the index in the data array (i.e. not the token id)+  , sorted :: CBool+  }+  deriving (Eq, Show, Generic, GStorable)++data LlamaBatch = LlamaBatch+  { n_tokens :: CInt+  , token :: Ptr CInt+  , embd :: Ptr CFloat+  , pos :: Ptr CInt+  , n_seq_id :: Ptr CInt+  , seq_id :: Ptr (Ptr CInt)+  , logits :: Ptr CSChar+  -- ^ TODO: rename this to "output"+  }+  deriving (Generic, GStorable, Eq, Show)++-- | Corresponds to `struct llama_kv_cache_view_cell`+newtype LlamaKvCacheViewCell = LlamaKvCacheViewCell+  { posKvCacheViewCell :: LlamaPos+  -- ^ Position in the KV cache (may be negative if unpopulated)+  }+  deriving (Show, Eq, Generic, GStorable)++-- | Corresponds to `struct llama_kv_cache_view`+data LlamaKvCacheView = LlamaKvCacheView+  { n_cells :: CInt+  -- ^ Total number of KV cache cells+  , n_seq_max :: CInt+  -- ^ Max sequences per cell (may not reflect actual)+  , token_count :: CInt+  -- ^ Total tokens in the cache+  , used_cells :: CInt+  -- ^ Number of populated cells+  , max_contiguous :: CInt+  -- ^ Max contiguous empty slots+  , max_contiguous_idx :: CInt+  -- ^ Index to start of max_contiguous (may be -1)+  , cells :: Ptr LlamaKvCacheViewCell+  -- ^ Array of view cells+  , cells_sequences :: Ptr LlamaSeqId+  -- ^ Sequence IDs for each cell (n_seq_max per cell)+  }+  deriving (Show, Eq, Generic, GStorable)++-- | Corresponds to `llama_sampler_context_t` (void *)+type LlamaSamplerContext = Ptr ()++-- | Corresponds to `struct llama_sampler_i`+data LlamaSamplerI = LlamaSamplerI+  { name :: FunPtr (Ptr LlamaSampler -> IO CString)+  -- ^ Optional: const char * (*name)(const struct llama_sampler *)+  , accept :: FunPtr (Ptr LlamaSampler -> LlamaToken -> IO ())+  -- ^ Optional: void (*accept)(struct llama_sampler *, llama_token)+  , apply :: FunPtr (Ptr LlamaSampler -> Ptr LlamaTokenDataArray -> IO ())+  -- ^ Required: void (*apply)(struct llama_sampler *, llama_token_data_array *)+  , reset :: FunPtr (Ptr LlamaSampler -> IO ())+  -- ^ Optional: void (*reset)(struct llama_sampler *)+  , clone :: FunPtr (Ptr LlamaSampler -> IO (Ptr LlamaSampler))+  -- ^ Optional: struct llama_sampler * (*clone)(const struct llama_sampler *)+  , free_ :: FunPtr (Ptr LlamaSampler -> IO ())+  -- ^ Optional: void (*free)(struct llama_sampler *)+  }+  deriving (Show, Eq, Generic, GStorable)++-- | Corresponds to `struct llama_sampler`+data LlamaSampler = LlamaSampler+  { iface :: Ptr LlamaSamplerI+  -- ^ Pointer to interface vtable+  , ctx :: LlamaSamplerContext+  -- ^ Opaque context pointer+  }+  deriving (Generic, Show, Eq, GStorable)++data LlamaPerfContextData = LlamaPerfContextData+    { t_start_ms   :: CDouble  -- ^ Start time in milliseconds+    , t_load_ms    :: CDouble  -- ^ Model load time in milliseconds+    , t_p_eval_ms  :: CDouble  -- ^ Prefill evaluation time in milliseconds+    , t_eval_ms    :: CDouble  -- ^ Generation evaluation time in milliseconds+    , n_p_eval     :: CInt     -- ^ Number of tokens in prefill phase+    , n_eval       :: CInt     -- ^ Number of tokens in generation phase+    }+    deriving (Show, Eq, Generic, GStorable)++data LlamaPerfSamplerData = LlamaPerfSamplerData+    { t_sample_ms  :: CDouble  -- ^ Sampling time in milliseconds+    , n_sample     :: CInt     -- ^ Number of sampling operations+    }+    deriving (Show, Eq, Generic, GStorable)
+ src/Llama/Internal/Types/Params.hs view
@@ -0,0 +1,566 @@+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}++module Llama.Internal.Types.Params+  ( LlamaSamplerChainParams (..)+  , LlamaContextParams (..)+  , LlamaModelParams (..)+  , LlamaModelQuantizeParams (..)+  , GgmlType (..)+  , LlamaRopeTypeScaling (..)+  , LlamaPoolingType (..)+  , LlamaAttentionType (..)+  , LlamaSplitMode (..)+  , CLlamaContextParams (..)+  , CLlamaModelParams (..)+  , CLlamaSamplerChainParams (..)+  , CLlamaModelQuantizeParams (..)+  , SamplerChainParamsPtr (..)+  , ModelQuantizeParamsPtr (..)+  , ContextParamsPtr (..)+  , ModelParamsPtr (..)+  , LlamaVocabType (..)+  , fromLlamaRopePoolingType+  , fromLlamaRopeTypeScaling+  , fromLlamaRopeVocabType +  ) where++import Foreign+import Foreign.C.Types+import Foreign.Storable.Generic+import GHC.Generics++-- | Raw pointer to llama_sampler_chain_params+newtype CLlamaSamplerChainParams = CLlamaSamplerChainParams (Ptr LlamaSamplerChainParams)+  deriving (Show, Eq)++-- | Raw pointer to llama_model_quantize_params+newtype CLlamaModelQuantizeParams = CLlamaModelQuantizeParams (Ptr LlamaModelQuantizeParams)+  deriving (Show, Eq)++-- | Raw pointer to llama_context_params+newtype CLlamaContextParams = CLlamaContextParams (Ptr LlamaContextParams)+  deriving (Show, Eq)++-- | Raw pointer to llama_model_params+newtype CLlamaModelParams = CLlamaModelParams (Ptr LlamaModelParams)+  deriving (Show, Eq)++-- | Safe wrapper for managed 'llama_sampler_chain_params'+newtype SamplerChainParamsPtr = SamplerChainParamsPtr (ForeignPtr CLlamaSamplerChainParams)+  deriving (Show, Eq)++-- | Safe wrapper for managed 'llama_model_quantize_params'+newtype ModelQuantizeParamsPtr = ModelQuantizeParamsPtr (ForeignPtr CLlamaModelQuantizeParams)+  deriving (Show, Eq)++-- | Safe wrapper for managed 'llama_context_params'+newtype ContextParamsPtr = ContextParamsPtr (ForeignPtr CLlamaContextParams)+  deriving (Show, Eq)++-- | Safe wrapper for managed 'llama_model_params'+newtype ModelParamsPtr = ModelParamsPtr (ForeignPtr CLlamaModelParams)+  deriving (Show, Eq)++-- Forward declarations for opaque C structs+data GgmlBackendDevT+data LlamaModelTensorBuftOverride+data LlamaModelKvOverride++-- Enum for llama_split_mode (assumed to be a 32-bit integer)+newtype LlamaSplitMode = LlamaSplitMode Int32+  deriving (Eq, Show, Read, Generic, GStorable)++-- Define the sampler chain parameters structure+newtype LlamaSamplerChainParams = LlamaSamplerChainParams+  { noPerf :: CBool -- whether to measure performance timings+  }+  deriving (Show, Eq, Generic, GStorable)++-- model quantization parameters+data LlamaModelQuantizeParams = LlamaModelQuantizeParams+  { nthread :: Int32+  , ftype :: LlamaFtype+  , outputTensorType :: GgmlType+  , tokenEmbeddingType :: GgmlType+  , allowRequantize :: Bool+  , quantizeOutputTensor :: Bool+  , onlyCopy :: Bool+  , pure_ :: Bool+  , keepSplit :: Bool+  , imatrix :: Ptr ()+  , kvOverridesQuantizeParams :: Ptr ()+  , tensorTypes :: Ptr ()+  }+  deriving (Show, Eq, Generic, GStorable)++data LlamaContextParams = LlamaContextParams+  { n_ctx :: CUInt+  -- ^ text context, 0 = from model+  , n_batch :: CUInt+  -- ^ logical maximum batch size that can be submitted to llama_decode+  , n_ubatch :: CUInt+  -- ^ physical maximum batch size+  , n_seq_max :: CUInt+  -- ^ max number of sequences (i.e. distinct states for recurrent models)+  , n_threads :: CInt+  -- ^ number of threads to use for generation+  , n_threads_batch :: CInt+  -- ^ number of threads to use for batch processing+  , rope_scaling_type :: LlamaRopeTypeScaling+  -- ^ RoPE scaling type, from `enum llama_rope_scaling_type`+  , pooling_type :: LlamaPoolingType+  -- ^ whether to pool (sum) embedding results by sequence id+  , attention_type :: LlamaAttentionType+  -- ^ attention type to use for embeddings+  , rope_freq_base :: CFloat+  -- ^ RoPE base frequency, 0 = from model+  , rope_freq_scale :: CFloat+  -- ^ RoPE frequency scaling factor, 0 = from model+  , yarn_ext_factor :: CFloat+  -- ^ YaRN extrapolation mix factor, negative = from model+  , yarn_attn_factor :: CFloat+  -- ^ YaRN magnitude scaling factor+  , yarn_beta_fast :: CFloat+  -- ^ YaRN low correction dim+  , yarn_beta_slow :: CFloat+  -- ^ YaRN high correction dim+  , yarn_orig_ctx :: CUInt+  -- ^ YaRN original context size+  , defrag_thold :: CFloat+  -- ^ defragment the KV cache if holes/size > thold, < 0 disabled (default)+  , cb_eval :: FunPtr (Ptr () -> IO ())+  , cb_eval_user_data :: Ptr ()+  , type_k :: GgmlType+  -- ^ data type for K cache [EXPERIMENTAL]+  , type_v :: GgmlType+  -- ^ data type for V cache [EXPERIMENTAL]+  , logits_all :: CBool+  -- ^ the llama_decode() call computes all logits, not just the last one (DEPRECATED - set llama_batch.logits instead)+  , embeddings :: CBool+  -- ^ if true, extract embeddings (together with logits)+  , offload_kqv :: CBool+  -- ^ whether to offload the KQV ops (including the KV cache) to GPU+  , flash_attn :: CBool+  -- ^ whether to use flash attention [EXPERIMENTAL]+  , no_perf :: CBool+  -- ^ whether to measure performance timings+  , abort_callback :: FunPtr (Ptr () -> IO CInt)+  , abort_callback_data :: Ptr ()+  }+  deriving (Show, Generic, GStorable)++-- Haskell representation of the C struct llama_model_params+data LlamaModelParams = LlamaModelParams+  { devices :: Ptr GgmlBackendDevT+  -- ^ NULL-terminated list of devices for offloading+  , tensorBuftOverrides :: Ptr LlamaModelTensorBuftOverride+  -- ^ NULL-terminated list of buffer type overrides+  , nGpuLayers :: Int32+  -- ^ Number of layers to store in VRAM+  , splitMode :: LlamaSplitMode+  -- ^ How to split the model across GPUs+  , mainGpu :: Int32+  -- ^ GPU used when split_mode is LLAMA_SPLIT_MODE_NONE+  , tensorSplit :: Ptr CFloat+  -- ^ Proportion of model offloaded to each GPU+  , progressCallback :: FunPtr (CFloat -> Ptr () -> IO CBool)+  -- ^ Callback for progress updates (returns true to continue)+  , progressCallbackUserData :: Ptr ()+  -- ^ User data for progress callback+  , kvOverrides :: Ptr LlamaModelKvOverride+  -- ^ Override for model metadata+  , vocabOnly :: CBool+  -- ^ Only load vocabulary, not weights+  , useMmap :: CBool+  -- ^ Use mmap if possible+  , useMlock :: CBool+  -- ^ Force model to stay in RAM+  , checkTensors :: CBool+  -- ^ Validate tensor data+  }+  deriving (Generic, GStorable, Eq, Show)++-- Helpers+data LlamaRopeTypeScaling+  = LLAMA_ROPE_SCALING_TYPE_UNSPECIFIED+  | LLAMA_ROPE_SCALING_TYPE_NONE+  | LLAMA_ROPE_SCALING_TYPE_LINEAR+  | LLAMA_ROPE_SCALING_TYPE_YARN+  | LLAMA_ROPE_SCALING_TYPE_LONGROPE+  | LLAMA_ROPE_SCALING_TYPE_MAX_VALUE+  deriving (Show, Eq)++toLlamaRopeTypeScaling :: LlamaRopeTypeScaling -> CInt+toLlamaRopeTypeScaling LLAMA_ROPE_SCALING_TYPE_UNSPECIFIED = -1+toLlamaRopeTypeScaling LLAMA_ROPE_SCALING_TYPE_NONE = 0+toLlamaRopeTypeScaling LLAMA_ROPE_SCALING_TYPE_LINEAR = 1+toLlamaRopeTypeScaling LLAMA_ROPE_SCALING_TYPE_YARN = 2+toLlamaRopeTypeScaling LLAMA_ROPE_SCALING_TYPE_LONGROPE = 3+toLlamaRopeTypeScaling LLAMA_ROPE_SCALING_TYPE_MAX_VALUE = 3++fromLlamaRopeTypeScaling :: CInt -> Maybe LlamaRopeTypeScaling+fromLlamaRopeTypeScaling (-1) = Just LLAMA_ROPE_SCALING_TYPE_UNSPECIFIED+fromLlamaRopeTypeScaling 0 = Just LLAMA_ROPE_SCALING_TYPE_NONE+fromLlamaRopeTypeScaling 1 = Just LLAMA_ROPE_SCALING_TYPE_LINEAR+fromLlamaRopeTypeScaling 2 = Just LLAMA_ROPE_SCALING_TYPE_YARN+fromLlamaRopeTypeScaling 3 = Just LLAMA_ROPE_SCALING_TYPE_LONGROPE+fromLlamaRopeTypeScaling _ = Nothing++instance Storable LlamaRopeTypeScaling where+  sizeOf _ = 4+  alignment _ = 4+  peek ptr = do+    mbVal <- fromLlamaRopeTypeScaling <$> peek (castPtr ptr)+    case mbVal of+      Nothing -> error "Invalid LlamaRopeTypeScaling value"+      Just val -> return val+  poke ptr val = do+    let val' = toLlamaRopeTypeScaling val+    poke (castPtr ptr) val'++data LlamaPoolingType+  = LLAMA_POOLING_TYPE_UNSPECIFIED+  | LLAMA_POOLING_TYPE_NONE+  | LLAMA_POOLING_TYPE_MEAN+  | LLAMA_POOLING_TYPE_CLS+  | LLAMA_POOLING_TYPE_LAST+  | LLAMA_POOLING_TYPE_RANK+  deriving (Show, Eq, Ord, Generic)++instance Storable LlamaPoolingType where+  sizeOf _ = 4+  alignment _ = 4+  peek ptr = do+    mbVal <- fromLlamaRopePoolingType <$> peek (castPtr ptr)+    case mbVal of+      Nothing -> error "Invalid LlamaPoolingType value"+      Just val -> return val+  poke ptr val = do+    let val' = toLlamaRopePoolingType val+    poke (castPtr ptr) val'++toLlamaRopePoolingType :: LlamaPoolingType -> CInt+toLlamaRopePoolingType LLAMA_POOLING_TYPE_UNSPECIFIED = -1+toLlamaRopePoolingType LLAMA_POOLING_TYPE_NONE = 0+toLlamaRopePoolingType LLAMA_POOLING_TYPE_MEAN = 1+toLlamaRopePoolingType LLAMA_POOLING_TYPE_CLS = 2+toLlamaRopePoolingType LLAMA_POOLING_TYPE_LAST = 3+toLlamaRopePoolingType LLAMA_POOLING_TYPE_RANK = 4++fromLlamaRopePoolingType :: CInt -> Maybe LlamaPoolingType+fromLlamaRopePoolingType (-1) = Just LLAMA_POOLING_TYPE_UNSPECIFIED+fromLlamaRopePoolingType 0 = Just LLAMA_POOLING_TYPE_NONE+fromLlamaRopePoolingType 1 = Just LLAMA_POOLING_TYPE_MEAN+fromLlamaRopePoolingType 2 = Just LLAMA_POOLING_TYPE_CLS+fromLlamaRopePoolingType 3 = Just LLAMA_POOLING_TYPE_LAST+fromLlamaRopePoolingType 4 = Just LLAMA_POOLING_TYPE_RANK+fromLlamaRopePoolingType _ = Nothing++data LlamaAttentionType+  = LLAMA_ATTENTION_TYPE_UNSPECIFIED+  | LLAMA_ATTENTION_TYPE_CAUSAL+  | LLAMA_ATTENTION_TYPE_NON_CAUSAL+  deriving (Show, Eq, Ord, Generic)++instance Storable LlamaAttentionType where+  sizeOf _ = sizeOf (undefined :: CUInt)++  alignment _ = sizeOf (undefined :: CUInt)++  peek ptr = do+    mbVal <- fromLlamaAttentionType <$> peek (castPtr ptr)+    case mbVal of+      Nothing -> error "Invalid LlamaAttentionType value"+      Just val -> return val+  poke ptr val = do+    let val' = toLlamaAttentionType val+    poke (castPtr ptr) val'++toLlamaAttentionType :: LlamaAttentionType -> CInt+toLlamaAttentionType LLAMA_ATTENTION_TYPE_UNSPECIFIED = -1+toLlamaAttentionType LLAMA_ATTENTION_TYPE_CAUSAL = 0+toLlamaAttentionType LLAMA_ATTENTION_TYPE_NON_CAUSAL = 1++fromLlamaAttentionType :: CInt -> Maybe LlamaAttentionType+fromLlamaAttentionType (-1) = Just LLAMA_ATTENTION_TYPE_UNSPECIFIED+fromLlamaAttentionType 0 = Just LLAMA_ATTENTION_TYPE_CAUSAL+fromLlamaAttentionType 1 = Just LLAMA_ATTENTION_TYPE_NON_CAUSAL+fromLlamaAttentionType _ = Nothing++data GgmlType+  = GGML_TYPE_F32+  | GGML_TYPE_F16+  | GGML_TYPE_Q4_0+  | GGML_TYPE_Q4_1+  | GGML_TYPE_Q5_0+  | GGML_TYPE_Q5_1+  | GGML_TYPE_Q8_0+  | GGML_TYPE_Q8_1+  | GGML_TYPE_Q2_K+  | GGML_TYPE_Q3_K+  | GGML_TYPE_Q4_K+  | GGML_TYPE_Q5_K+  | GGML_TYPE_Q6_K+  | GGML_TYPE_Q8_K+  | GGML_TYPE_IQ2_XXS+  | GGML_TYPE_IQ2_XS+  | GGML_TYPE_IQ3_XXS+  | GGML_TYPE_IQ1_S+  | GGML_TYPE_IQ4_NL+  | GGML_TYPE_IQ3_S+  | GGML_TYPE_IQ2_S+  | GGML_TYPE_IQ4_XS+  | GGML_TYPE_I8+  | GGML_TYPE_I16+  | GGML_TYPE_I32+  | GGML_TYPE_I64+  | GGML_TYPE_F64+  | GGML_TYPE_IQ1_M+  | GGML_TYPE_BF16+  | GGML_TYPE_TQ1_0+  | GGML_TYPE_TQ2_0+  | GGML_TYPE_COUNT+  deriving (Show, Eq, Ord, Generic)++toGgmlType :: GgmlType -> CInt+toGgmlType g =+  case g of+    GGML_TYPE_F32 -> 0+    GGML_TYPE_F16 -> 1+    GGML_TYPE_Q4_0 -> 2+    GGML_TYPE_Q4_1 -> 3+    GGML_TYPE_Q5_0 -> 6+    GGML_TYPE_Q5_1 -> 7+    GGML_TYPE_Q8_0 -> 8+    GGML_TYPE_Q8_1 -> 9+    GGML_TYPE_Q2_K -> 10+    GGML_TYPE_Q3_K -> 11+    GGML_TYPE_Q4_K -> 12+    GGML_TYPE_Q5_K -> 13+    GGML_TYPE_Q6_K -> 14+    GGML_TYPE_Q8_K -> 15+    GGML_TYPE_IQ2_XXS -> 16+    GGML_TYPE_IQ2_XS -> 17+    GGML_TYPE_IQ3_XXS -> 18+    GGML_TYPE_IQ1_S -> 19+    GGML_TYPE_IQ4_NL -> 20+    GGML_TYPE_IQ3_S -> 21+    GGML_TYPE_IQ2_S -> 22+    GGML_TYPE_IQ4_XS -> 23+    GGML_TYPE_I8 -> 24+    GGML_TYPE_I16 -> 25+    GGML_TYPE_I32 -> 26+    GGML_TYPE_I64 -> 27+    GGML_TYPE_F64 -> 28+    GGML_TYPE_IQ1_M -> 29+    GGML_TYPE_BF16 -> 30+    GGML_TYPE_TQ1_0 -> 34+    GGML_TYPE_TQ2_0 -> 35+    GGML_TYPE_COUNT -> 39++fromGgmlType :: CInt -> Maybe GgmlType+fromGgmlType num =+  case num of+    0 -> Just GGML_TYPE_F32+    1 -> Just GGML_TYPE_F16+    2 -> Just GGML_TYPE_Q4_0+    3 -> Just GGML_TYPE_Q4_1+    6 -> Just GGML_TYPE_Q5_0+    7 -> Just GGML_TYPE_Q5_1+    8 -> Just GGML_TYPE_Q8_0+    9 -> Just GGML_TYPE_Q8_1+    10 -> Just GGML_TYPE_Q2_K+    11 -> Just GGML_TYPE_Q3_K+    12 -> Just GGML_TYPE_Q4_K+    13 -> Just GGML_TYPE_Q5_K+    14 -> Just GGML_TYPE_Q6_K+    15 -> Just GGML_TYPE_Q8_K+    16 -> Just GGML_TYPE_IQ2_XXS+    17 -> Just GGML_TYPE_IQ2_XS+    18 -> Just GGML_TYPE_IQ3_XXS+    19 -> Just GGML_TYPE_IQ1_S+    20 -> Just GGML_TYPE_IQ4_NL+    21 -> Just GGML_TYPE_IQ3_S+    22 -> Just GGML_TYPE_IQ2_S+    23 -> Just GGML_TYPE_IQ4_XS+    24 -> Just GGML_TYPE_I8+    25 -> Just GGML_TYPE_I16+    26 -> Just GGML_TYPE_I32+    27 -> Just GGML_TYPE_I64+    28 -> Just GGML_TYPE_F64+    29 -> Just GGML_TYPE_IQ1_M+    30 -> Just GGML_TYPE_BF16+    34 -> Just GGML_TYPE_TQ1_0+    35 -> Just GGML_TYPE_TQ2_0+    39 -> Just GGML_TYPE_COUNT+    _ -> Nothing++instance Storable GgmlType where+  sizeOf _ = sizeOf (undefined :: CInt)+  alignment _ = sizeOf (undefined :: CInt)+  peek ptr = do+    mbVal <- fromGgmlType <$> peek (castPtr ptr)+    case mbVal of+      Nothing -> error "Invalid GgmlType value"+      Just val -> return val+  poke ptr val = do+    let val' = toGgmlType val+    poke (castPtr ptr) val'++data LlamaFtype+  = LLAMA_FTYPE_ALL_F32+  | LLAMA_FTYPE_MOSTLY_F16+  | LLAMA_FTYPE_MOSTLY_Q4_0+  | LLAMA_FTYPE_MOSTLY_Q4_1+  | LLAMA_FTYPE_MOSTLY_Q8_0+  | LLAMA_FTYPE_MOSTLY_Q5_0+  | LLAMA_FTYPE_MOSTLY_Q5_1+  | LLAMA_FTYPE_MOSTLY_Q2_K+  | LLAMA_FTYPE_MOSTLY_Q3_K_S+  | LLAMA_FTYPE_MOSTLY_Q3_K_M+  | LLAMA_FTYPE_MOSTLY_Q3_K_L+  | LLAMA_FTYPE_MOSTLY_Q4_K_S+  | LLAMA_FTYPE_MOSTLY_Q4_K_M+  | LLAMA_FTYPE_MOSTLY_Q5_K_S+  | LLAMA_FTYPE_MOSTLY_Q5_K_M+  | LLAMA_FTYPE_MOSTLY_Q6_K+  | LLAMA_FTYPE_MOSTLY_IQ2_XXS+  | LLAMA_FTYPE_MOSTLY_IQ2_XS+  | LLAMA_FTYPE_MOSTLY_Q2_K_S+  | LLAMA_FTYPE_MOSTLY_IQ3_XS+  | LLAMA_FTYPE_MOSTLY_IQ3_XXS+  | LLAMA_FTYPE_MOSTLY_IQ1_S+  | LLAMA_FTYPE_MOSTLY_IQ4_NL+  | LLAMA_FTYPE_MOSTLY_IQ3_S+  | LLAMA_FTYPE_MOSTLY_IQ3_M+  | LLAMA_FTYPE_MOSTLY_IQ2_S+  | LLAMA_FTYPE_MOSTLY_IQ2_M+  | LLAMA_FTYPE_MOSTLY_IQ4_XS+  | LLAMA_FTYPE_MOSTLY_IQ1_M+  | LLAMA_FTYPE_MOSTLY_BF16+  | LLAMA_FTYPE_MOSTLY_TQ1_0+  | LLAMA_FTYPE_MOSTLY_TQ2_0+  | LLAMA_FTYPE_GUESSED+  deriving (Show, Eq)++toLlamaFtype :: LlamaFtype -> CInt+toLlamaFtype LLAMA_FTYPE_ALL_F32 = 0+toLlamaFtype LLAMA_FTYPE_MOSTLY_F16 = 1+toLlamaFtype LLAMA_FTYPE_MOSTLY_Q4_0 = 2+toLlamaFtype LLAMA_FTYPE_MOSTLY_Q4_1 = 3+toLlamaFtype LLAMA_FTYPE_MOSTLY_Q8_0 = 7+toLlamaFtype LLAMA_FTYPE_MOSTLY_Q5_0 = 8+toLlamaFtype LLAMA_FTYPE_MOSTLY_Q5_1 = 9+toLlamaFtype LLAMA_FTYPE_MOSTLY_Q2_K = 10+toLlamaFtype LLAMA_FTYPE_MOSTLY_Q3_K_S = 11+toLlamaFtype LLAMA_FTYPE_MOSTLY_Q3_K_M = 12+toLlamaFtype LLAMA_FTYPE_MOSTLY_Q3_K_L = 13+toLlamaFtype LLAMA_FTYPE_MOSTLY_Q4_K_S = 14+toLlamaFtype LLAMA_FTYPE_MOSTLY_Q4_K_M = 15+toLlamaFtype LLAMA_FTYPE_MOSTLY_Q5_K_S = 16+toLlamaFtype LLAMA_FTYPE_MOSTLY_Q5_K_M = 17+toLlamaFtype LLAMA_FTYPE_MOSTLY_Q6_K = 18+toLlamaFtype LLAMA_FTYPE_MOSTLY_IQ2_XXS = 19+toLlamaFtype LLAMA_FTYPE_MOSTLY_IQ2_XS = 20+toLlamaFtype LLAMA_FTYPE_MOSTLY_Q2_K_S = 21+toLlamaFtype LLAMA_FTYPE_MOSTLY_IQ3_XS = 22+toLlamaFtype LLAMA_FTYPE_MOSTLY_IQ3_XXS = 23+toLlamaFtype LLAMA_FTYPE_MOSTLY_IQ1_S = 24+toLlamaFtype LLAMA_FTYPE_MOSTLY_IQ4_NL = 25+toLlamaFtype LLAMA_FTYPE_MOSTLY_IQ3_S = 26+toLlamaFtype LLAMA_FTYPE_MOSTLY_IQ3_M = 27+toLlamaFtype LLAMA_FTYPE_MOSTLY_IQ2_S = 28+toLlamaFtype LLAMA_FTYPE_MOSTLY_IQ2_M = 29+toLlamaFtype LLAMA_FTYPE_MOSTLY_IQ4_XS = 30+toLlamaFtype LLAMA_FTYPE_MOSTLY_IQ1_M = 31+toLlamaFtype LLAMA_FTYPE_MOSTLY_BF16 = 32+toLlamaFtype LLAMA_FTYPE_MOSTLY_TQ1_0 = 36+toLlamaFtype LLAMA_FTYPE_MOSTLY_TQ2_0 = 37+toLlamaFtype LLAMA_FTYPE_GUESSED = 1024++fromLlamaFtype :: CInt -> Maybe LlamaFtype+fromLlamaFtype 0 = Just LLAMA_FTYPE_ALL_F32+fromLlamaFtype 1 = Just LLAMA_FTYPE_MOSTLY_F16+fromLlamaFtype 2 = Just LLAMA_FTYPE_MOSTLY_Q4_0+fromLlamaFtype 3 = Just LLAMA_FTYPE_MOSTLY_Q4_1+fromLlamaFtype 7 = Just LLAMA_FTYPE_MOSTLY_Q8_0+fromLlamaFtype 8 = Just LLAMA_FTYPE_MOSTLY_Q5_0+fromLlamaFtype 9 = Just LLAMA_FTYPE_MOSTLY_Q5_1+fromLlamaFtype 10 = Just LLAMA_FTYPE_MOSTLY_Q2_K+fromLlamaFtype 11 = Just LLAMA_FTYPE_MOSTLY_Q3_K_S+fromLlamaFtype 12 = Just LLAMA_FTYPE_MOSTLY_Q3_K_M+fromLlamaFtype 13 = Just LLAMA_FTYPE_MOSTLY_Q3_K_L+fromLlamaFtype 14 = Just LLAMA_FTYPE_MOSTLY_Q4_K_S+fromLlamaFtype 15 = Just LLAMA_FTYPE_MOSTLY_Q4_K_M+fromLlamaFtype 16 = Just LLAMA_FTYPE_MOSTLY_Q5_K_S+fromLlamaFtype 17 = Just LLAMA_FTYPE_MOSTLY_Q5_K_M+fromLlamaFtype 18 = Just LLAMA_FTYPE_MOSTLY_Q6_K+fromLlamaFtype 19 = Just LLAMA_FTYPE_MOSTLY_IQ2_XXS+fromLlamaFtype 20 = Just LLAMA_FTYPE_MOSTLY_IQ2_XS+fromLlamaFtype 21 = Just LLAMA_FTYPE_MOSTLY_Q2_K_S+fromLlamaFtype 22 = Just LLAMA_FTYPE_MOSTLY_IQ3_XS+fromLlamaFtype 23 = Just LLAMA_FTYPE_MOSTLY_IQ3_XXS+fromLlamaFtype 24 = Just LLAMA_FTYPE_MOSTLY_IQ1_S+fromLlamaFtype 25 = Just LLAMA_FTYPE_MOSTLY_IQ4_NL+fromLlamaFtype 26 = Just LLAMA_FTYPE_MOSTLY_IQ3_S+fromLlamaFtype 27 = Just LLAMA_FTYPE_MOSTLY_IQ3_M+fromLlamaFtype 28 = Just LLAMA_FTYPE_MOSTLY_IQ2_S+fromLlamaFtype 29 = Just LLAMA_FTYPE_MOSTLY_IQ2_M+fromLlamaFtype 30 = Just LLAMA_FTYPE_MOSTLY_IQ4_XS+fromLlamaFtype 31 = Just LLAMA_FTYPE_MOSTLY_IQ1_M+fromLlamaFtype 32 = Just LLAMA_FTYPE_MOSTLY_BF16+fromLlamaFtype 36 = Just LLAMA_FTYPE_MOSTLY_TQ1_0+fromLlamaFtype 37 = Just LLAMA_FTYPE_MOSTLY_TQ2_0+fromLlamaFtype 1024 = Just LLAMA_FTYPE_GUESSED+fromLlamaFtype _ = Nothing++instance Storable LlamaFtype where+  sizeOf _ = 4+  alignment _ = 4+  peek ptr = do+    val <- peek (castPtr ptr) :: IO CInt+    case fromLlamaFtype val of+      Just v -> return v+      Nothing -> error $ "Invalid LlamaFtype value: " ++ show val+  poke ptr val = do+    let cVal = toLlamaFtype val+    poke (castPtr ptr) cVal++data LlamaVocabType+  = LLAMA_VOCAB_TYPE_NONE+  | LLAMA_VOCAB_TYPE_SPM+  | LLAMA_VOCAB_TYPE_BPE+  | LLAMA_VOCAB_TYPE_WPM+  | LLAMA_VOCAB_TYPE_UGM+  | LLAMA_VOCAB_TYPE_RWKV+  deriving (Show, Eq, Ord, Generic)++instance Storable LlamaVocabType where+  sizeOf _ = 4+  alignment _ = 4+  peek ptr = do+      mbVal <- fromLlamaRopeVocabType <$> peek (castPtr ptr)+      case mbVal of+        Nothing -> error "Invalid LlamaVocabType value"+        Just val -> return val+  poke ptr val = do+      let val' = toLlamaRopeVocabType val+      poke (castPtr ptr) val'++toLlamaRopeVocabType :: LlamaVocabType -> CInt+toLlamaRopeVocabType LLAMA_VOCAB_TYPE_NONE = 0+toLlamaRopeVocabType LLAMA_VOCAB_TYPE_SPM  = 1+toLlamaRopeVocabType LLAMA_VOCAB_TYPE_BPE  = 2+toLlamaRopeVocabType LLAMA_VOCAB_TYPE_WPM  = 3+toLlamaRopeVocabType LLAMA_VOCAB_TYPE_UGM  = 4+toLlamaRopeVocabType LLAMA_VOCAB_TYPE_RWKV = 5++fromLlamaRopeVocabType :: CInt -> Maybe LlamaVocabType+fromLlamaRopeVocabType 0 = Just LLAMA_VOCAB_TYPE_NONE+fromLlamaRopeVocabType 1 = Just LLAMA_VOCAB_TYPE_SPM+fromLlamaRopeVocabType 2 = Just LLAMA_VOCAB_TYPE_BPE+fromLlamaRopeVocabType 3 = Just LLAMA_VOCAB_TYPE_WPM+fromLlamaRopeVocabType 4 = Just LLAMA_VOCAB_TYPE_UGM+fromLlamaRopeVocabType 5 = Just LLAMA_VOCAB_TYPE_RWKV+fromLlamaRopeVocabType _ = Nothing
+ src/Llama/KVCache.hs view
@@ -0,0 +1,171 @@+{- |+Module      : Llama.KVCache+Description : High level KVCache interface for llama-cpp+Copyright   : (c) 2025 Tushar Adhatrao+License     : MIT+Maintainer  : Tushar Adhatrao <tusharadhatrao@gmail.com>+-}+module Llama.KVCache (+    kvCacheViewInit+, kvSelfSeqAdd+, kvSelfSeqDiv+, kvSelfSeqPosMax+, kvSelfDefrag+, kvSelfCanShift+, kvSelfUpdate+, kvSelfSeqKeep+, kvSelfSeqCopy+, kvSelfSeqRemove+, kvSelfClear+, kvSelfUsedCells+, kvSelfNumTokens+, kvCacheViewUpdate+) where++import Llama.Internal.Types+import Foreign+import Llama.Internal.Foreign++{-+TODO: no free function for struct llama_kv_cache *+No one is using struct llama_kv_cache+-- | Get the KV cache associated with this context.+getKVCache :: Context -> IO KVCache+getKVCache (Context ctxFPtr) =+  withForeignPtr ctxFPtr $ \ctxPtr -> do+    ptr <- c_llama_get_kv_self (CLlamaContext ctxPtr)+    -- We assume finalization is handled elsewhere or use a no-op finalizer+    fp <- newForeignPtr_ ptr -- assumes Ptr () is actually Ptr CLlamaKVCache+    return $ KVCache fp+-}++-- | Convenience wrapper that allocates a LlamaKvCacheView and initializes it+kvCacheViewInit :: Context -> Int -> IO LlamaKvCacheView+kvCacheViewInit (Context fPtr) n_seq_max_ = do+    withForeignPtr fPtr $ \contextPtr -> do+      alloca $ \pView -> do+        c_llama_kv_cache_view_init_into (CLlamaContext contextPtr) (fromIntegral n_seq_max_) pView+        peek pView++-- | Shift positions in a sequence by a delta.+kvSelfSeqAdd ::+  Context ->+  LlamaSeqId -> -- seq_id+  LlamaPos -> -- p0+  LlamaPos -> -- p1+  LlamaPos -> -- delta+  IO ()+kvSelfSeqAdd (Context ctxFPtr) seqId p0 p1 delta =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    c_llama_kv_self_seq_add (CLlamaContext ctxPtr) seqId p0 p1 delta++-- | Divide positions in a sequence by a factor (used for attention windowing).+kvSelfSeqDiv ::+  Context ->+  LlamaSeqId -> -- seq_id+  LlamaPos -> -- p0+  LlamaPos -> -- p1+  Int -> -- d+  IO ()+kvSelfSeqDiv (Context ctxFPtr) seqId p0 p1 d =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    c_llama_kv_self_seq_div (CLlamaContext ctxPtr) seqId p0 p1 (fromIntegral d)++-- | Get the maximum position stored in the KV cache for a given sequence.+kvSelfSeqPosMax ::+  Context ->+  LlamaSeqId -> -- seq_id+  IO LlamaPos+kvSelfSeqPosMax (Context ctxFPtr) seqId =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    c_llama_kv_self_seq_pos_max (CLlamaContext ctxPtr) seqId++-- | Defragment the KV cache to optimize memory usage.+kvSelfDefrag ::+  Context ->+  IO ()+kvSelfDefrag (Context ctxFPtr) =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    c_llama_kv_self_defrag (CLlamaContext ctxPtr)++-- | Check whether the KV cache can be shifted (e.g., due to full buffer).+kvSelfCanShift ::+  Context ->+  IO Bool+kvSelfCanShift (Context ctxFPtr) =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    toBool <$> c_llama_kv_self_can_shift (castPtr ctxPtr)++-- | Update the KV cache's internal state (e.g., after manual modifications).+kvSelfUpdate ::+  Context ->+  IO ()+kvSelfUpdate (Context ctxFPtr) =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    c_llama_kv_self_update (CLlamaContext ctxPtr)++-- | Prevent a sequence from being removed during KV cache cleanup.+kvSelfSeqKeep ::+  Context ->+  LlamaSeqId -> -- seq_id+  IO ()+kvSelfSeqKeep (Context ctxFPtr) seqId =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    c_llama_kv_self_seq_keep (CLlamaContext ctxPtr) seqId++-- | Copy a range of positions from one sequence to another.+kvSelfSeqCopy ::+  Context ->+  LlamaSeqId -> -- seq_id_src+  LlamaSeqId -> -- seq_id_dst+  LlamaPos -> -- p0+  LlamaPos -> -- p1+  IO ()+kvSelfSeqCopy (Context ctxFPtr) srcId dstId p0 p1 =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    c_llama_kv_self_seq_cp (CLlamaContext ctxPtr) srcId dstId p0 p1++-- | Remove a range of positions from a sequence.+kvSelfSeqRemove ::+  Context ->+  LlamaSeqId -> -- seq_id+  LlamaPos -> -- p0+  LlamaPos -> -- p1+  IO Bool+kvSelfSeqRemove (Context ctxFPtr) seqId p0 p1 =+  withForeignPtr ctxFPtr $ \ctxPtr -> do+    result <- c_llama_kv_self_seq_rm (CLlamaContext ctxPtr) seqId p0 p1+    return $ toBool result++-- | Clear all sequences from the KV cache.+kvSelfClear ::+  Context ->+  IO ()+kvSelfClear (Context ctxFPtr) =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    c_llama_kv_self_clear (CLlamaContext ctxPtr)++-- | Get number of used cells in the KV cache.+kvSelfUsedCells ::+  Context ->+  IO Int+kvSelfUsedCells (Context ctxFPtr) =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    fromIntegral <$> c_llama_kv_self_used_cells (CLlamaContext ctxPtr)++-- | Get total number of tokens currently stored in the KV cache.+kvSelfNumTokens ::+  Context ->+  IO Int+kvSelfNumTokens (Context ctxFPtr) =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    fromIntegral <$> c_llama_kv_self_n_tokens (CLlamaContext ctxPtr)++-- | Update the KV cache view to reflect current state.+kvCacheViewUpdate ::+  Context ->+  Ptr LlamaKvCacheView -> -- view+  IO ()+kvCacheViewUpdate (Context ctxFPtr) view =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    c_llama_kv_cache_view_update (CLlamaContext ctxPtr) view
+ src/Llama/Model.hs view
@@ -0,0 +1,338 @@+{- |+Module      : Llama.Model+Description : High level Model interface for llama-cpp+Copyright   : (c) 2025 Tushar Adhatrao+License     : MIT+Maintainer  : Tushar Adhatrao <tusharadhatrao@gmail.com>+-}+module Llama.Model (+    defaultModelParams+, loadModelFromFile+, initContextFromModel+, getModelVocab+, getContextModel+, getVocabType+, getModelRoPEFreqScale+, getModelNumKVHeads+, getModelNumHeads+, getModelNumLayers+, getModelEmbeddingDim+, getModelTrainingContextSize+, getModelSize+, getModelChatTemplate+, getModelHasEncoder+, getModelNumParams+, getModelHasDecoder+, getModelDecoderStartToken+, getModelIsRecurrent+, quantizeModel+, quantizeModelDefault+, defaultQuantizeParams+, getModelMetaCount+, getModelMetaValue+, getModelMetaKeyByIndex+, getModelMetaValueByIndex+, getModelDescription+, loadModelFromSplits+, getModelRopeType+) where++import Data.Functor+import Foreign+import Foreign.C.String+import Llama.Internal.Foreign+import Llama.Internal.Types+import Llama.Internal.Types.Params++-- | Default model parameters+defaultModelParams :: IO LlamaModelParams+defaultModelParams = do+  -- Convert to a pointer to pass to the C function+  alloca $ \paramsPtr -> do+    c_llama_model_default_params (CLlamaModelParams paramsPtr)+    peek paramsPtr++-- | Load a model from a file using the specified parameters+loadModelFromFile :: FilePath -> LlamaModelParams -> IO (Either String Model)+loadModelFromFile path params = do+  withCString path $ \cPath -> do+    withStorable params $ \paramsPtr -> do+      model <- c_llama_model_load_from_file_wrap cPath (CLlamaModelParams paramsPtr)+      if model == CLlamaModel nullPtr+        then return $ Left "Failed to load model"+        else do+          let (CLlamaModel modelPtr) = model+          fp <- newForeignPtr p_llama_model_free modelPtr+          return $ Right $ Model fp++-- | Create a context from a model using the specified parameters+initContextFromModel :: Model -> LlamaContextParams -> IO (Either String Context)+initContextFromModel (Model modelFPtr) params = do+  withForeignPtr modelFPtr $ \modelPtr -> do+    withStorable params $ \paramsPtr -> do+      context <-+        c_llama_init_from_model_wrap+          (CLlamaModel modelPtr)+          (CLlamaContextParams paramsPtr)+      if context == CLlamaContext nullPtr+        then return $ Left "Failed to initialize context"+        else do+          let (CLlamaContext contextPtr) = context+          fp <- newForeignPtr p_llama_free contextPtr+          return $ Right $ Context fp++-- | Get the vocabulary from a model+getModelVocab :: Model -> IO (Either String Vocab)+getModelVocab (Model modelFPtr) = do+  withForeignPtr modelFPtr $ \modelPtr -> do+    vocab <- c_llama_model_get_vocab (CLlamaModel modelPtr)+    if vocab == CLlamaVocab nullPtr+      then return $ Left "Failed to get vocabulary"+      else do+        -- For now, assuming it's owned by the model and doesn't need separate freeing+        let (CLlamaVocab vocabPtr) = vocab+        -- Using a dummy finalizer since vocab is owned by the model+        fp <- newForeignPtr_ vocabPtr+        return $ Right $ Vocab fp++-- | Convert Storable Haskell struct to pointer and run an action+withStorable :: Storable a => a -> (Ptr a -> IO b) -> IO b+withStorable x f = alloca $ \ptr -> do+  poke ptr x+  f ptr++-- | Get the model associated with a context.+getContextModel :: Context -> IO Model+getContextModel (Context ctxFPtr) =+  withForeignPtr ctxFPtr $ \ctxPtr -> do+    CLlamaModel modelPtr <- c_llama_get_model (CLlamaContext ctxPtr)+    fp <- newForeignPtr p_llama_model_free modelPtr+    return $ Model fp++-- | Get the vocabulary type.+getVocabType :: Vocab -> IO (Maybe LlamaVocabType)+getVocabType (Vocab vocabFPtr) =+  withForeignPtr vocabFPtr $ \vocabPtr ->+    fromLlamaRopeVocabType <$> c_llama_vocab_type (CLlamaVocab vocabPtr)++-- | Get RoPE frequency scaling factor used during training.+getModelRoPEFreqScale :: Model -> IO Float+getModelRoPEFreqScale (Model modelFPtr) =+  withForeignPtr modelFPtr $ \modelPtr ->+    realToFrac <$> c_llama_model_rope_freq_scale_train (CLlamaModel modelPtr)++-- | Get the number of key/value heads in the model.+getModelNumKVHeads :: Model -> IO Int+getModelNumKVHeads (Model modelFPtr) =+  withForeignPtr modelFPtr $ \modelPtr ->+    fromCInt <$> c_llama_model_n_head_kv (CLlamaModel modelPtr)++-- | Get the number of attention heads in the model.+getModelNumHeads :: Model -> IO Int+getModelNumHeads (Model modelFPtr) =+  withForeignPtr modelFPtr $ \modelPtr ->+    fromCInt <$> c_llama_model_n_head (CLlamaModel modelPtr)++-- | Get the number of transformer layers in the model.+getModelNumLayers :: Model -> IO Int+getModelNumLayers (Model modelFPtr) =+  withForeignPtr modelFPtr $ \modelPtr ->+    fromCInt <$> c_llama_model_n_layer (CLlamaModel modelPtr)++-- | Get the embedding dimension of the model.+getModelEmbeddingDim :: Model -> IO Int+getModelEmbeddingDim (Model modelFPtr) =+  withForeignPtr modelFPtr $ \modelPtr ->+    fromCInt <$> c_llama_model_n_embd (CLlamaModel modelPtr)++-- | Get the training context size of the model.+getModelTrainingContextSize :: Model -> IO Int+getModelTrainingContextSize (Model modelFPtr) =+  withForeignPtr modelFPtr $ \modelPtr ->+    fromCInt <$> c_llama_model_n_ctx_train (CLlamaModel modelPtr)++fromCInt :: Int32 -> Int+fromCInt = fromIntegral++-- | Get the size of the model in bytes+getModelSize :: Model -> IO Int64+getModelSize (Model modelFPtr) =+  withForeignPtr modelFPtr $ \modelPtr ->+    fromIntegral <$> c_llama_model_size (CLlamaModel modelPtr)++-- | Check if the model has an encoder+getModelHasEncoder :: Model -> IO Bool+getModelHasEncoder (Model modelFPtr) = do+  withForeignPtr modelFPtr $ \modelPtr -> do+    c_llama_model_has_encoder (CLlamaModel modelPtr) <&> (/= 0)++-- | Get the chat template from a model, optionally by name+getModelChatTemplate :: Model -> Maybe String -> IO (Either String String)+getModelChatTemplate (Model modelFPtr) mName = do+  withForeignPtr modelFPtr $ \modelPtr -> do+    cName <- maybe (pure nullPtr) newCString mName+    template <- c_llama_model_chat_template (CLlamaModel modelPtr) cName+    if template == nullPtr+      then return $ Left "Failed to get chat template"+      else Right <$> peekCString template++-- | Get the number of parameters in the model+getModelNumParams :: Model -> IO (Either String Int64)+getModelNumParams (Model modelFPtr) = do+  withForeignPtr modelFPtr $ \modelPtr -> do+    params <- c_llama_model_n_params (CLlamaModel modelPtr)+    if params == 0+      then return $ Left "Failed to get number of parameters"+      else return $ Right $ fromIntegral params++-- | Check if the model has a decoder+getModelHasDecoder :: Model -> IO Bool+getModelHasDecoder (Model modelFPtr) = do+  withForeignPtr modelFPtr $ \modelPtr -> do+    c_llama_model_has_decoder (CLlamaModel modelPtr) <&> (/= 0)++-- | Get the decoder start token from the model+getModelDecoderStartToken :: Model -> IO (Either String LlamaToken)+getModelDecoderStartToken (Model modelFPtr) = do+  withForeignPtr modelFPtr $ \modelPtr -> do+    token_ <- c_llama_model_decoder_start_token (CLlamaModel modelPtr)+    if token_ == -1+      then return $ Left "Failed to get decoder start token"+      else return $ Right token_++-- | Check if the model is recurrent+getModelIsRecurrent :: Model -> IO Bool+getModelIsRecurrent (Model modelFPtr) = do+  withForeignPtr modelFPtr $ \modelPtr -> do+    c_llama_model_is_recurrent (CLlamaModel modelPtr) <&> (/= 0)++-- | Quantize a model from a file to another file using specified parameters+quantizeModel ::+  FilePath ->+  FilePath ->+  LlamaModelQuantizeParams ->+  IO (Either String Word32)+quantizeModel inpPath outPath params = do+  withCString inpPath $ \cInpPath -> do+    withCString outPath $ \cOutPath -> do+      withStorable params $ \paramsPtr -> do+        result <-+          c_llama_model_quantize+            cInpPath+            cOutPath+            (CLlamaModelQuantizeParams paramsPtr)+        if result == 0+          then return $ Left "Failed to quantize model"+          else return $ Right result++-- | Quantize a model from a file to another file using default parameters+quantizeModelDefault :: FilePath -> FilePath -> IO (Either String Word32)+quantizeModelDefault inpPath outPath = do+  params <- defaultQuantizeParams+  quantizeModel inpPath outPath params++-- | Get the default quantization parameters+defaultQuantizeParams :: IO LlamaModelQuantizeParams+defaultQuantizeParams = do+  (CLlamaModelQuantizeParams paramsPtr) <- c_llama_model_quantize_default_params+  peek paramsPtr++-- | Get a metadata value as a string from a model+getModelMetaValue :: Model -> String -> IO (Either String String)+getModelMetaValue (Model modelFPtr) key = do+  withForeignPtr modelFPtr $ \modelPtr -> do+    withCString key $ \cKey -> do+      allocaArray 256 $ \bufPtr -> do+        result <- c_llama_model_meta_val_str (CLlamaModel modelPtr) cKey bufPtr 256+        if result == -1+          then return $ Left "Failed to get metadata value"+          else do+            str <- peekCString bufPtr+            return $ Right str++-- | Get the number of metadata entries in a model+getModelMetaCount :: Model -> IO Int+getModelMetaCount (Model modelFPtr) = do+  withForeignPtr modelFPtr $ \modelPtr -> do+    fromIntegral <$> c_llama_model_meta_count (CLlamaModel modelPtr)++-- | Get a metadata key by index from a model+getModelMetaKeyByIndex :: Model -> Int -> IO (Either String String)+getModelMetaKeyByIndex (Model modelFPtr) index = do+  withForeignPtr modelFPtr $ \modelPtr -> do+    allocaArray 256 $ \bufPtr -> do+      result <-+        c_llama_model_meta_key_by_index+          (CLlamaModel modelPtr)+          (fromIntegral index)+          bufPtr+          256+      if result == -1+        then return $ Left "Failed to get metadata key"+        else do+          str <- peekCString bufPtr+          return $ Right str++-- | Get a metadata value by index from a model+getModelMetaValueByIndex :: Model -> Int -> IO (Either String String)+getModelMetaValueByIndex (Model modelFPtr) index = do+  withForeignPtr modelFPtr $ \modelPtr -> do+    allocaArray 256 $ \bufPtr -> do+      result <-+        c_llama_model_meta_val_str_by_index+          (CLlamaModel modelPtr)+          (fromIntegral index)+          bufPtr+          256+      if result == -1+        then return $ Left "Failed to get metadata value"+        else do+          str <- peekCString bufPtr+          return $ Right str++-- | Get a model description+getModelDescription :: Model -> IO String+getModelDescription (Model modelFPtr) = do+  withForeignPtr modelFPtr $ \modelPtr -> do+    allocaArray 256 $ \bufPtr -> do+      _ <- c_llama_model_desc (CLlamaModel modelPtr) bufPtr 256+      peekCString bufPtr++-- | Load a model from multiple file paths using specified parameters+loadModelFromSplits :: [FilePath] -> LlamaModelParams -> IO (Either String Model)+loadModelFromSplits paths params = do+  withStorable params $ \paramsPtr -> do+    pathsPtr <- newArrayOfPtrs paths+    withForeignPtr pathsPtr $ \pathsPtr' -> do+      model <-+        c_llama_model_load_from_splits+          pathsPtr'+          (fromIntegral (length paths))+          (CLlamaModelParams paramsPtr)+      if model == CLlamaModel nullPtr+        then return $ Left "Failed to load model"+        else do+          let (CLlamaModel modelPtr) = model+          fp <- newForeignPtr p_llama_model_free modelPtr+          return $ Right $ Model fp++-- | Get the RoPE type from a model+getModelRopeType :: Model -> IO (Maybe LlamaRopeTypeScaling)+getModelRopeType (Model modelFPtr) = do+  withForeignPtr modelFPtr $ \modelPtr -> do+    alloca $ \outPtr -> do+      c_llama_model_rope_type_into (CLlamaModel modelPtr) outPtr+      val <- peek outPtr+      return $ fromLlamaRopeTypeScaling val++newArrayOfPtrs :: [FilePath] -> IO (ForeignPtr CString)+newArrayOfPtrs xs = do+  ptrs <- mallocBytes (length xs * sizeOf (undefined :: Ptr CString))+  mapM_+    ( \(i, x) -> withCString x $ \cstr ->+        poke+          (castPtr ptrs `plusPtr` (i * sizeOf (undefined :: Ptr CString)))+          cstr+    )+    (zip [0 ..] xs)+  newForeignPtr_ ptrs
+ src/Llama/Performance.hs view
@@ -0,0 +1,59 @@+{- |+Module      : Llama.Performance+Description : High level Performance interface for llama-cpp+Copyright   : (c) 2025 Tushar Adhatrao+License     : MIT+Maintainer  : Tushar Adhatrao <tusharadhatrao@gmail.com>+-}+module Llama.Performance (+    printContextPerformance+, resetContextPerformance+, printSamplerPerformance+, resetSamplerPerformance+, getContextPerformance+, getSamplerPerformance+  ) where++import Llama.Internal.Types+import Foreign+import Llama.Internal.Foreign++-- | Print performance information for a context+printContextPerformance :: Context -> IO ()+printContextPerformance (Context ctxFPtr) =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    c_llama_perf_context_print (CLlamaContext ctxPtr)++-- | Reset performance information for a context+resetContextPerformance :: Context -> IO ()+resetContextPerformance (Context ctxFPtr) =+  withForeignPtr ctxFPtr $ \ctxPtr ->+    c_llama_perf_context_reset (CLlamaContext ctxPtr)++-- | Print performance information for a sampler chain+printSamplerPerformance :: Sampler -> IO ()+printSamplerPerformance (Sampler samplerFPtr) =+  withForeignPtr samplerFPtr $ \samplerPtr ->+    c_llama_perf_sampler_print samplerPtr++-- | Reset performance information for a sampler chain+resetSamplerPerformance :: Sampler -> IO ()+resetSamplerPerformance (Sampler samplerFPtr) =+  withForeignPtr samplerFPtr $ \samplerPtr ->+    c_llama_perf_sampler_reset samplerPtr++-- | Get performance data for a context+getContextPerformance :: Context -> IO LlamaPerfContextData+getContextPerformance (Context ctxFPtr) = do+  alloca $ \perfDataPtr -> do+    withForeignPtr ctxFPtr $ \ctxPtr -> do+      c_llama_perf_context (CLlamaContext ctxPtr) perfDataPtr+    peek perfDataPtr++-- | Get performance data for a sampler chain+getSamplerPerformance :: Sampler -> IO LlamaPerfSamplerData+getSamplerPerformance (Sampler samplerFPtr) = do+  alloca $ \perfDataPtr -> do+    withForeignPtr samplerFPtr $ \samplerPtr -> do+      c_llama_perf_sampler samplerPtr perfDataPtr+    peek perfDataPtr
+ src/Llama/Sampler.hs view
@@ -0,0 +1,392 @@+{- |+Module      : Llama.Sampler+Description : High level Sampler interface for llama-cpp+Copyright   : (c) 2025 Tushar Adhatrao+License     : MIT+Maintainer  : Tushar Adhatrao <tusharadhatrao@gmail.com>+-}+module Llama.Sampler (+    defaultSamplerChainParams+, initSampler+, getSamplerName+, acceptTokenWithSampler+, applySampler+, resetSampler+, cloneSampler+, initSamplerChain+, addSamplerToChain+, getSamplerFromChain+, getSamplerChainLength+, removeSamplerFromChain+, initGreedySampler+, initDistributedSampler+, initTopKSampler+, initTopPSampler+, initMinPSampler+, initTypicalSampler+, initTempSampler+, initTempExtSampler+, initXTCSampler+, initTopNSigmaSampler+, initMirostatSampler+, initMirostatV2Sampler+, initGrammarSampler+, initGrammarLazyPatternsSampler+, initPenaltiesSampler+, initDrySampler+, initLogitBiasSampler+, initInfillSampler+, getSamplerSeed+, sampleWithSampler+) where++import Llama.Internal.Types+import Llama.Internal.Types.Params+import Foreign+import Llama.Internal.Foreign+import Foreign.C.String++-- | Convert Storable Haskell struct to pointer and run an action+withStorable :: Storable a => a -> (Ptr a -> IO b) -> IO b+withStorable x f = alloca $ \ptr -> do+  poke ptr x+  f ptr++-- | Get the default parameters for a sampler chain+defaultSamplerChainParams :: IO LlamaSamplerChainParams+defaultSamplerChainParams = alloca $ \paramsPtr -> do+      c_llama_sampler_chain_default_params_into paramsPtr+      peek paramsPtr++-- | Initialize a sampler+initSampler :: LlamaSamplerI -> LlamaSamplerContext -> IO (Either String Sampler)+initSampler iface_ ctx_ = do+  ifacePtr <- mallocBytes (sizeOf (undefined :: LlamaSamplerI))+  poke ifacePtr iface_+  samplerPtr <- c_llama_sampler_init ifacePtr ctx_+  if samplerPtr == nullPtr+    then return $ Left "Failed to initialize sampler"+    else do+      fp <- newForeignPtr p_llama_sampler_free samplerPtr+      return $ Right (Sampler fp)++-- | Get the name of a sampler+getSamplerName :: Sampler -> IO String+getSamplerName (Sampler samplerFPtr) = do+  withForeignPtr samplerFPtr $ \samplerPtr -> do+    name_ <- c_llama_sampler_name samplerPtr+    peekCString name_++-- | Accept a token with a sampler+acceptTokenWithSampler :: Sampler -> LlamaToken -> IO ()+acceptTokenWithSampler (Sampler samplerFPtr) token_ = do+  withForeignPtr samplerFPtr $ \samplerPtr ->+    c_llama_sampler_accept samplerPtr token_++-- | Apply a sampler to a token data array+applySampler :: Sampler -> LlamaTokenDataArray -> IO ()+applySampler (Sampler samplerFPtr) tokenDataArray = do+  withForeignPtr samplerFPtr $ \samplerPtr ->+    withStorable tokenDataArray $ \tokenDataArrayPtr ->+      c_llama_sampler_apply samplerPtr tokenDataArrayPtr++-- | Reset a sampler+resetSampler :: Sampler -> IO ()+resetSampler (Sampler samplerFPtr) = do+  withForeignPtr samplerFPtr $ \samplerPtr ->+    c_llama_sampler_reset (castPtr samplerPtr)++-- | Clone a sampler+cloneSampler :: Sampler -> IO (Either String Sampler)+cloneSampler (Sampler samplerFPtr) = do+  withForeignPtr samplerFPtr $ \samplerPtr -> do+    clonedSamplerPtr <- c_llama_sampler_clone (castPtr samplerPtr)+    if clonedSamplerPtr == nullPtr+      then return $ Left "Failed to clone sampler"+      else do+        fp <- newForeignPtr p_llama_sampler_free clonedSamplerPtr+        return $ Right $ Sampler fp++-- | Initialize a sampler chain+initSamplerChain :: LlamaSamplerChainParams -> IO (Either String Sampler)+initSamplerChain params = do+  chainPtr <- c_llama_sampler_chain_init params+  if chainPtr == nullPtr+    then return $ Left "Failed to initialize sampler chain"+    else do+      fp <- newForeignPtr p_llama_sampler_free chainPtr+      return $ Right $ Sampler fp++-- | Add a sampler to a sampler chain+addSamplerToChain :: Sampler -> Ptr LlamaSampler -> IO ()+addSamplerToChain (Sampler chainFPtr) samplerPtr = do+  withForeignPtr chainFPtr $ \chainPtr ->+      c_llama_sampler_chain_add chainPtr samplerPtr++getSamplerFromChain :: Sampler -> Int -> IO (Either String Sampler)+getSamplerFromChain (Sampler chainFPtr) index = do+  withForeignPtr chainFPtr $ \chainPtr -> do+    samplerPtr <- c_llama_sampler_chain_get chainPtr (fromIntegral index)+    if samplerPtr == nullPtr+      then return $ Left "Failed to get sampler from chain"+      else do+        fp <- newForeignPtr p_llama_sampler_free samplerPtr+        return $ Right $ Sampler fp++-- | Get the number of samplers in a sampler chain+getSamplerChainLength :: Sampler -> IO Int+getSamplerChainLength (Sampler chainFPtr) = do+  withForeignPtr chainFPtr $ \chainPtr -> do+    fromIntegral <$> c_llama_sampler_chain_n chainPtr++-- | Remove a sampler from a sampler chain+removeSamplerFromChain :: Sampler -> Int -> IO (Either String Sampler)+removeSamplerFromChain (Sampler chainFPtr) index = do+  withForeignPtr chainFPtr $ \chainPtr -> do+    samplerPtr <- c_llama_sampler_chain_remove chainPtr (fromIntegral index)+    if samplerPtr == nullPtr+      then return $ Left "Failed to remove sampler from chain"+      else do+        fp <- newForeignPtr p_llama_sampler_free samplerPtr+        return $ Right $ Sampler fp++-- | Initialize a greedy sampler+initGreedySampler :: IO (Either String (Ptr LlamaSampler))+initGreedySampler = do+  samplerPtr <- c_llama_sampler_init_greedy+  if samplerPtr == nullPtr+    then return $ Left "Failed to initialize greedy sampler"+    else do+      return $ Right samplerPtr++-- | Initialize a distributed sampler+initDistributedSampler :: Word32 -> IO (Either String Sampler)+initDistributedSampler seed = do+  samplerPtr <- c_llama_sampler_init_dist (fromIntegral seed)+  if samplerPtr == nullPtr+    then return $ Left "Failed to initialize distributed sampler"+    else do+      fp <- newForeignPtr p_llama_sampler_free samplerPtr+      return $ Right $ Sampler fp++-- | Initialize a top-k sampler+initTopKSampler :: Int -> IO (Either String Sampler)+initTopKSampler k = do+  samplerPtr <- c_llama_sampler_init_top_k (fromIntegral k)+  if samplerPtr == nullPtr+    then return $ Left "Failed to initialize top-k sampler"+    else do+      fp <- newForeignPtr p_llama_sampler_free samplerPtr+      return $ Right $ Sampler fp++-- | Initialize a top-p sampler+initTopPSampler :: Float -> Int -> IO (Either String Sampler)+initTopPSampler p1 minKeep = do+  samplerPtr <- c_llama_sampler_init_top_p (realToFrac p1) (fromIntegral minKeep)+  if samplerPtr == nullPtr+    then return $ Left "Failed to initialize top-p sampler"+    else do+      fp <- newForeignPtr p_llama_sampler_free samplerPtr+      return $ Right $ Sampler fp++-- | Initialize a min-p sampler+initMinPSampler :: Float -> Int -> IO (Either String Sampler)+initMinPSampler p1 minKeep = do+  samplerPtr <- c_llama_sampler_init_min_p (realToFrac p1) (fromIntegral minKeep)+  if samplerPtr == nullPtr+    then return $ Left "Failed to initialize min-p sampler"+    else do+      fp <- newForeignPtr p_llama_sampler_free samplerPtr+      return $ Right $ Sampler fp++-- | Initialize a typical sampler+initTypicalSampler :: Float -> Int -> IO (Either String Sampler)+initTypicalSampler p_ minKeep = do+  samplerPtr <- c_llama_sampler_init_typical (realToFrac p_) (fromIntegral minKeep)+  if samplerPtr == nullPtr+    then return $ Left "Failed to initialize typical sampler"+    else do+      fp <- newForeignPtr p_llama_sampler_free samplerPtr+      return $ Right $ Sampler fp++-- | Initialize a temperature sampler+initTempSampler :: Float -> IO (Either String Sampler)+initTempSampler t = do+  samplerPtr <- c_llama_sampler_init_temp (realToFrac t)+  if samplerPtr == nullPtr+    then return $ Left "Failed to initialize temperature sampler"+    else do+      fp <- newForeignPtr p_llama_sampler_free samplerPtr+      return $ Right $ Sampler fp++-- | Initialize an extended temperature sampler+initTempExtSampler :: Float -> Float -> Float -> IO (Either String Sampler)+initTempExtSampler t delta exponent_ = do+  samplerPtr <- c_llama_sampler_init_temp_ext (realToFrac t) (realToFrac delta) (realToFrac exponent_)+  if samplerPtr == nullPtr+    then return $ Left "Failed to initialize extended temperature sampler"+    else do+      fp <- newForeignPtr p_llama_sampler_free samplerPtr+      return $ Right $ Sampler fp++-- | Initialize an XTC sampler+initXTCSampler :: Float -> Float -> Int -> Word32 -> IO (Either String Sampler)+initXTCSampler p1 t minKeep seed = do+  samplerPtr <- c_llama_sampler_init_xtc (realToFrac p1) (realToFrac t) (fromIntegral minKeep) (fromIntegral seed)+  if samplerPtr == nullPtr+    then return $ Left "Failed to initialize XTC sampler"+    else do+      fp <- newForeignPtr p_llama_sampler_free samplerPtr+      return $ Right $ Sampler fp++-- | Initialize a top-N sigma sampler+initTopNSigmaSampler :: Float -> IO (Either String Sampler)+initTopNSigmaSampler n = do+  samplerPtr <- c_llama_sampler_init_top_n_sigma (realToFrac n)+  if samplerPtr == nullPtr+    then return $ Left "Failed to initialize top-N sigma sampler"+    else do+      fp <- newForeignPtr p_llama_sampler_free samplerPtr+      return $ Right $ Sampler fp++-- | Initialize a Mirostat sampler+initMirostatSampler :: Int -> Word32 -> Float -> Float -> Int -> IO (Either String Sampler)+initMirostatSampler nVocab seed tau eta m = do+  samplerPtr <- c_llama_sampler_init_mirostat (fromIntegral nVocab) (fromIntegral seed) (realToFrac tau) (realToFrac eta) (fromIntegral m)+  if samplerPtr == nullPtr+    then return $ Left "Failed to initialize Mirostat sampler"+    else do+      fp <- newForeignPtr p_llama_sampler_free samplerPtr+      return $ Right $ Sampler fp++-- | Initialize a Mirostat V2 sampler+initMirostatV2Sampler :: Word32 -> Float -> Float -> IO (Either String Sampler)+initMirostatV2Sampler seed tau eta = do+  samplerPtr <- c_llama_sampler_init_mirostat_v2 (fromIntegral seed) (realToFrac tau) (realToFrac eta)+  if samplerPtr == nullPtr+    then return $ Left "Failed to initialize Mirostat V2 sampler"+    else do+      fp <- newForeignPtr p_llama_sampler_free samplerPtr+      return $ Right $ Sampler fp++-- | Initialize a grammar sampler+initGrammarSampler :: Vocab -> String -> String -> IO (Either String Sampler)+initGrammarSampler (Vocab vocab) grammarStr grammarRoot = do+  withForeignPtr vocab $ \vocabPtr -> do+    withCString grammarStr $ \grammarStrPtr -> do+      withCString grammarRoot $ \grammarRootPtr -> do+        samplerPtr <- c_llama_sampler_init_grammar (CLlamaVocab vocabPtr) grammarStrPtr grammarRootPtr+        if samplerPtr == nullPtr+          then return $ Left "Failed to initialize grammar sampler"+          else do+            fp <- newForeignPtr p_llama_sampler_free samplerPtr+            return $ Right $ Sampler fp++-- | Initialize a grammar sampler with lazy patterns+initGrammarLazyPatternsSampler :: Vocab -> String -> String -> [String] -> [LlamaToken] -> IO (Either String Sampler)+initGrammarLazyPatternsSampler (Vocab vocab) grammarStr grammarRoot triggerPatterns triggerTokens = do+  withForeignPtr vocab $ \vocabPtr -> do+    withCString grammarStr $ \grammarStrPtr -> do+      withCString grammarRoot $ \grammarRootPtr -> do+        triggerPatternsPtr <- newArrayOfPtrs triggerPatterns+        withForeignPtr triggerPatternsPtr $ \triggerPatternsPtr' -> do+          triggerTokensPtr <- mallocBytes (length triggerTokens * sizeOf (undefined :: LlamaToken))+          pokeArray triggerTokensPtr triggerTokens+          samplerPtr <- c_llama_sampler_init_grammar_lazy_patterns+            (CLlamaVocab vocabPtr)+            grammarStrPtr+            grammarRootPtr+            triggerPatternsPtr'+            (fromIntegral (length triggerPatterns))+            triggerTokensPtr+            (fromIntegral (length triggerTokens))+          if samplerPtr == nullPtr+            then return $ Left "Failed to initialize grammar lazy patterns sampler"+            else do+              fp <- newForeignPtr p_llama_sampler_free samplerPtr+              return $ Right $ Sampler fp++-- | Initialize a penalties sampler+initPenaltiesSampler :: Int -> Float -> Float -> Float -> IO (Either String Sampler)+initPenaltiesSampler penaltyLastN penaltyRepeat penaltyFreq penaltyPresent = do+  samplerPtr <- c_llama_sampler_init_penalties+    (fromIntegral penaltyLastN)+    (realToFrac penaltyRepeat)+    (realToFrac penaltyFreq)+    (realToFrac penaltyPresent)+  if samplerPtr == nullPtr+    then return $ Left "Failed to initialize penalties sampler"+    else do+      fp <- newForeignPtr p_llama_sampler_free samplerPtr+      return $ Right $ Sampler fp++newArrayOfPtrs :: [String] -> IO (ForeignPtr CString)+newArrayOfPtrs xs = do+  ptrs <- mallocBytes (length xs * sizeOf (undefined :: Ptr CString))+  mapM_ (\(i, x) -> withCString x $ \cstr -> poke (castPtr ptrs `plusPtr` (i * sizeOf (undefined :: Ptr CString))) cstr) (zip [0..] xs)+  newForeignPtr_ ptrs++-- Helper function+withCStringArray :: [String] -> (Ptr CString -> IO a) -> IO a+withCStringArray xs f = do+  ptrs <- newArrayOfPtrs xs+  withForeignPtr ptrs $ \ptrs' ->+    f ptrs'++-- | Initialize a dry sampler+initDrySampler :: Vocab -> Int -> Float -> Float -> Int -> Int -> [String] -> IO (Either String Sampler)+initDrySampler (Vocab vocab) nCtxTrain dryMultiplier dryBase dryAllowedLength dryPenaltyLastN seqBreakers = do+  withForeignPtr vocab $ \vocabPtr -> do+    withCStringArray seqBreakers $ \seqBreakersPtr -> do+      samplerPtr <- c_llama_sampler_init_dry+        (CLlamaVocab vocabPtr)+        (fromIntegral nCtxTrain)+        (realToFrac dryMultiplier)+        (realToFrac dryBase)+        (fromIntegral dryAllowedLength)+        (fromIntegral dryPenaltyLastN)+        seqBreakersPtr+        (fromIntegral (length seqBreakers))+      if samplerPtr == nullPtr+        then return $ Left "Failed to initialize dry sampler"+        else do+          fp <- newForeignPtr p_llama_sampler_free samplerPtr+          return $ Right $ Sampler fp++-- | Initialize a logit bias sampler+initLogitBiasSampler :: Int -> [LlamaLogitBias] -> IO (Either String Sampler)+initLogitBiasSampler nVocab logitBiases = do+  allocaArray (length logitBiases) $ \logitBiasPtr -> do+    pokeArray logitBiasPtr logitBiases+    samplerPtr <- c_llama_sampler_init_logit_bias+      (fromIntegral nVocab)+      (fromIntegral (length logitBiases))+      logitBiasPtr+    if samplerPtr == nullPtr+      then return $ Left "Failed to initialize logit bias sampler"+      else do+        fp <- newForeignPtr p_llama_sampler_free samplerPtr+        return $ Right $ Sampler fp++-- | Initialize an infill sampler+initInfillSampler :: Vocab -> IO (Either String Sampler)+initInfillSampler (Vocab vocab) = do+  withForeignPtr vocab $ \vocabPtr -> do+    samplerPtr <- c_llama_sampler_init_infill (CLlamaVocab vocabPtr)+    if samplerPtr == nullPtr+      then return $ Left "Failed to initialize infill sampler"+      else do+        fp <- newForeignPtr p_llama_sampler_free samplerPtr+        return $ Right $ Sampler fp++-- | Get the seed used by a sampler+getSamplerSeed :: Sampler -> IO Word32+getSamplerSeed (Sampler samplerFPtr) = do+  withForeignPtr samplerFPtr (fmap fromIntegral . c_llama_sampler_get_seed)++-- | Sample with a sampler+sampleWithSampler :: Sampler -> Context -> Int -> IO LlamaToken+sampleWithSampler (Sampler samplerFPtr) (Context ctxFPtr) idx = do+  withForeignPtr samplerFPtr $ \samplerPtr -> do+    withForeignPtr ctxFPtr $ \ctxPtr ->+      c_llama_sampler_sample samplerPtr (CLlamaContext ctxPtr) (fromIntegral idx)
+ src/Llama/Split.hs view
@@ -0,0 +1,46 @@+{- |+Module      : Llama.Split+Description : High level Split interface for llama-cpp+Copyright   : (c) 2025 Tushar Adhatrao+License     : MIT+Maintainer  : Tushar Adhatrao <tusharadhatrao@gmail.com>+-}+module Llama.Split (+    splitPath+    , splitPrefix+   , printSystemInfo+) where++import Llama.Internal.Foreign+import Foreign+import Foreign.C.String++-- | Split a path into a prefix and a split number+splitPath :: FilePath -> Int -> Int -> IO (Either String String)+splitPath pathPrefix splitNo splitCount = do+  withCString pathPrefix $ \cPathPrefix -> do+    allocaArray 256 $ \splitPathPtr -> do+      requiredLen <- c_llama_split_path splitPathPtr 256 cPathPrefix (fromIntegral splitNo) (fromIntegral splitCount)+      if requiredLen < 0+        then return $ Left "Failed to split path"+        else do+          str <- peekCString splitPathPtr+          return $ Right str++-- | Get the prefix from a split path+splitPrefix :: FilePath -> Int -> Int -> IO (Either String String)+splitPrefix splitPath_ splitNo splitCount = do+  withCString splitPath_ $ \cSplitPath -> do+    allocaArray 256 $ \splitPrefixPtr -> do+      requiredLen <- c_llama_split_prefix splitPrefixPtr 256 cSplitPath (fromIntegral splitNo) (fromIntegral splitCount)+      if requiredLen < 0+        then return $ Left "Failed to get prefix from split path"+        else do+          str <- peekCString splitPrefixPtr+          return $ Right str++-- | Print system information+printSystemInfo :: IO String+printSystemInfo = do+  systemInfo <- c_llama_print_system_info+  peekCString systemInfo
+ src/Llama/State.hs view
@@ -0,0 +1,119 @@+{- |+Module      : Llama.State+Description : High level State interface for llama-cpp+Copyright   : (c) 2025 Tushar Adhatrao+License     : MIT+Maintainer  : Tushar Adhatrao <tusharadhatrao@gmail.com>+-}+module Llama.State (+   getStateSize+, getStateData+, setStateData+, loadStateFromFile+, saveStateToFile+, getSequenceStateSize+, setSequenceStateData+, saveSequenceStateToFile+, loadSequenceStateFromFile+) where++import Llama.Internal.Foreign+import Llama.Internal.Types+import Foreign+import Foreign.C.String+import qualified Data.ByteString as BS+import Data.ByteString (ByteString)++-- | Get the size of the state+getStateSize :: Context -> IO Word64+getStateSize (Context ctxFPtr) = do+  withForeignPtr ctxFPtr $ \ctxPtr ->+    fromIntegral <$> c_llama_state_get_size (CLlamaContext ctxPtr)++-- | Get the state data+getStateData :: Context -> IO ByteString+getStateData (Context ctxFPtr) = do+  withForeignPtr ctxFPtr $ \ctxPtr -> do+    size <- c_llama_state_get_size (CLlamaContext ctxPtr)+    allocaBytes (fromIntegral size) $ \dstPtr -> do+      _ <- c_llama_state_get_data (CLlamaContext ctxPtr) dstPtr size+      BS.pack <$> peekArray (fromIntegral size) dstPtr++-- | Set the state data+setStateData :: Context -> ByteString -> IO ()+setStateData (Context ctxFPtr) bs = do+  withForeignPtr ctxFPtr $ \ctxPtr -> do+    withArray (BS.unpack bs) $ \srcPtr -> do+      _ <- c_llama_state_set_data (CLlamaContext ctxPtr) srcPtr (fromIntegral (BS.length bs))+      return ()++-- | Load a state from a file+loadStateFromFile :: Context -> FilePath -> [LlamaToken] -> IO [LlamaToken]+loadStateFromFile (Context ctxFPtr) pathSession tokens = do+  withForeignPtr ctxFPtr $ \ctxPtr -> do+    withCString pathSession $ \cPathSession -> do+      allocaArray (length tokens) $ \tokensOutPtr -> do+        alloca $ \nTokenCountOutPtr -> do+          success <- c_llama_state_load_file+            (CLlamaContext ctxPtr)+            cPathSession+            tokensOutPtr+            (fromIntegral (length tokens))+            nTokenCountOutPtr+          if success == 0+            then return []+            else do+            tokenCount <- peek nTokenCountOutPtr+            peekArray (fromIntegral tokenCount) tokensOutPtr++-- | Save a state to a file+saveStateToFile :: Context -> FilePath -> [LlamaToken] -> IO Bool+saveStateToFile (Context ctxFPtr) pathSession tokens = do+  withForeignPtr ctxFPtr $ \ctxPtr -> do+    withCString pathSession $ \cPathSession -> do+      withArray tokens $ \tokensPtr -> do+        toBool <$> c_llama_state_save_file+          (CLlamaContext ctxPtr)+          cPathSession+          tokensPtr+          (fromIntegral (length tokens))++-- | Get the size of a sequence in the state+getSequenceStateSize :: Context -> LlamaSeqId -> IO Word64+getSequenceStateSize (Context ctxFPtr) seqId = do+  withForeignPtr ctxFPtr $ \ctxPtr ->+    fromIntegral <$> c_llama_state_seq_get_size (CLlamaContext ctxPtr) seqId++-- | Set the state data for a sequence+setSequenceStateData :: Context -> ByteString -> LlamaSeqId -> IO Word64+setSequenceStateData (Context ctxFPtr) bs seqId = do+  withForeignPtr ctxFPtr $ \ctxPtr -> do+    withArray (BS.unpack bs) $ \srcPtr -> do+      fromIntegral <$>+        c_llama_state_seq_set_data (CLlamaContext ctxPtr) srcPtr (fromIntegral (BS.length bs)) seqId++-- | Save a sequence state to a file+saveSequenceStateToFile :: Context -> FilePath -> LlamaSeqId -> [LlamaToken] -> IO Word64+saveSequenceStateToFile (Context ctxFPtr) filepath seqId tokens = do+  withForeignPtr ctxFPtr $ \ctxPtr -> do+    withArray tokens $ \tokenPtr -> do+      withCString filepath $ \cfilepath -> do+        fromIntegral <$>+          c_llama_state_seq_save_file (CLlamaContext ctxPtr) cfilepath seqId tokenPtr (fromIntegral (length tokens))++-- | Load a sequence state from a file+loadSequenceStateFromFile :: Context -> FilePath -> LlamaSeqId -> [LlamaToken] -> IO [LlamaToken]+loadSequenceStateFromFile (Context ctxFPtr) filepath destSeqId tokens = do+  withForeignPtr ctxFPtr $ \ctxPtr -> do+    withCString filepath $ \cfilepath -> do+      allocaArray (length tokens) $ \tokensOutPtr -> do+        alloca $ \nTokenCountOutPtr -> do+          _ <- c_llama_state_seq_load_file+            (CLlamaContext ctxPtr)+            cfilepath+            destSeqId+            tokensOutPtr+            (fromIntegral (length tokens))+            nTokenCountOutPtr+          tokenCount <- peek nTokenCountOutPtr+          peekArray (fromIntegral tokenCount) tokensOutPtr
+ src/Llama/Tokenize.hs view
@@ -0,0 +1,65 @@+{- |+Module      : Llama.Tokenize+Description : High level Tokenize interface for llama-cpp+Copyright   : (c) 2025 Tushar Adhatrao+License     : MIT+Maintainer  : Tushar Adhatrao <tusharadhatrao@gmail.com>+-}+module Llama.Tokenize (+    tokenize+  ,  tokenToPiece+  ,  detokenize+) where++import Llama.Internal.Foreign+import Llama.Internal.Types+import Foreign+import Foreign.C.String++-- | Tokenize a string into tokens+tokenize :: Vocab -> String -> Bool -> Bool -> IO ([LlamaToken], Int)+tokenize (Vocab vocab) text addSpecial parseSpecial = do+  withForeignPtr vocab $ \vocabPtr -> do+    withCString text $ \cText -> do+      let textLen = length text+      allocaArray textLen $ \tokensPtr -> do+        tokenCount <- c_llama_tokenize+          (CLlamaVocab vocabPtr)+          cText+          (fromIntegral textLen)+          tokensPtr+          (fromIntegral textLen)+          (fromBool addSpecial)+          (fromBool parseSpecial)+        tokens <- peekArray (fromIntegral tokenCount) tokensPtr+        return (tokens, fromIntegral tokenCount)++-- | Convert a token to a piece of text+tokenToPiece :: Vocab -> LlamaToken -> Bool -> IO String+tokenToPiece (Vocab vocab) token_ special = do+  withForeignPtr vocab $ \vocabPtr -> do+    allocaArray 256 $ \bufPtr -> do+      _ <- c_llama_token_to_piece+        (CLlamaVocab vocabPtr)+        token_+        bufPtr+        256+        0+        (fromBool special)+      peekCString bufPtr++-- | Detokenize tokens into a string+detokenize :: Vocab -> [LlamaToken] -> Bool -> Bool -> IO String+detokenize (Vocab vocab) tokens removeSpecial unparseSpecial = do+  withForeignPtr vocab $ \vocabPtr -> do+    allocaArray 256 $ \textPtr -> do+      withArray tokens $ \tokensPtr -> do+        _ <- c_llama_detokenize+            (CLlamaVocab vocabPtr)+            tokensPtr+            (fromIntegral $ length tokens)+            textPtr+            256+            (fromBool removeSpecial)+            (fromBool unparseSpecial)+        peekCString textPtr
+ src/Llama/Vocab.hs view
@@ -0,0 +1,155 @@+{- |+Module      : Llama.Tokenize+Description : High level Tokenize interface for llama-cpp+Copyright   : (c) 2025 Tushar Adhatrao+License     : MIT+Maintainer  : Tushar Adhatrao <tusharadhatrao@gmail.com>+-}+module Llama.Vocab (+    getVocabSize+, getVocabTokenCount+, getVocabTokenText+, getVocabTokenScore+, getVocabTokenAttr+, isVocabTokenEog+, isVocabTokenControl+, getVocabBosToken+, getVocabEosToken+, getVocabEotToken+, getVocabSepToken+, getVocabNlToken+, getVocabPadToken+, getVocabAddBOSToken+, getVocabAddEOSToken+, getVocabFIMPrefixToken+, getVocabFIMSuffixToken+, getVocabFIMMiddleToken+, getVocabFIMPADToken+, getVocabFIMSeparatorToken+) where++import Llama.Internal.Foreign+import Llama.Internal.Types+import Foreign+import Foreign.C.String++-- | Get the number of vocab entries+getVocabSize :: Vocab -> IO Int+getVocabSize (Vocab vocabFPtr) = do+  withForeignPtr vocabFPtr $ \vocabPtr ->+    fromIntegral <$> c_llama_n_vocab (CLlamaVocab vocabPtr)++-- | Get the number of tokens in the vocab+getVocabTokenCount :: Vocab -> IO Int+getVocabTokenCount (Vocab vocabFPtr) = do+  withForeignPtr vocabFPtr $ \vocabPtr ->+    fromIntegral <$> c_llama_vocab_n_tokens (CLlamaVocab vocabPtr)++-- | Get the text for a token+getVocabTokenText :: Vocab -> LlamaToken -> IO String+getVocabTokenText (Vocab vocabFPtr) token_ = do+  withForeignPtr vocabFPtr $ \vocabPtr -> do+    cText <- c_llama_vocab_get_text (CLlamaVocab vocabPtr) token_+    peekCString cText++-- | Get the score for a token+getVocabTokenScore :: Vocab -> LlamaToken -> IO Float+getVocabTokenScore (Vocab vocabFPtr) token_ = do+  withForeignPtr vocabFPtr $ \vocabPtr ->+    realToFrac <$> c_llama_vocab_get_score (CLlamaVocab vocabPtr) token_++-- | Get the attribute for a token+getVocabTokenAttr :: Vocab -> LlamaToken -> IO Int+getVocabTokenAttr (Vocab vocabFPtr) token_ = do+  withForeignPtr vocabFPtr $ \vocabPtr ->+    fromIntegral <$> c_llama_vocab_get_attr (CLlamaVocab vocabPtr) token_++-- | Check if a token is end-of-grammar+isVocabTokenEog :: Vocab -> LlamaToken -> IO Bool+isVocabTokenEog (Vocab vocabFPtr) token_ = do+  withForeignPtr vocabFPtr $ \vocabPtr ->+    (/= 0) <$> c_llama_vocab_is_eog (CLlamaVocab vocabPtr) token_++-- | Check if a token is a control token+isVocabTokenControl :: Vocab -> LlamaToken -> IO Bool+isVocabTokenControl (Vocab vocabFPtr) token_ = do+  withForeignPtr vocabFPtr $ \vocabPtr ->+    (/= 0) <$> c_llama_vocab_is_control (CLlamaVocab vocabPtr) token_++-- | Get the beginning-of-sentence token+getVocabBosToken :: Vocab -> IO LlamaToken+getVocabBosToken (Vocab vocabFPtr) = do+  withForeignPtr vocabFPtr $ \vocabPtr ->+    c_llama_vocab_bos (CLlamaVocab vocabPtr)++-- | Get the end-of-sentence token+getVocabEosToken :: Vocab -> IO LlamaToken+getVocabEosToken (Vocab vocabFPtr) = do+  withForeignPtr vocabFPtr $ \vocabPtr ->+    c_llama_vocab_eos (CLlamaVocab vocabPtr)++-- | Get the end-of-turn token+getVocabEotToken :: Vocab -> IO LlamaToken+getVocabEotToken (Vocab vocabFPtr) = do+  withForeignPtr vocabFPtr $ \vocabPtr ->+    c_llama_vocab_eot (CLlamaVocab vocabPtr)++-- | Get the sentence separator token+getVocabSepToken :: Vocab -> IO LlamaToken+getVocabSepToken (Vocab vocabFPtr) = do+  withForeignPtr vocabFPtr $ \vocabPtr ->+    c_llama_vocab_sep (CLlamaVocab vocabPtr)++-- | Get the next-line token+getVocabNlToken :: Vocab -> IO LlamaToken+getVocabNlToken (Vocab vocabFPtr) = do+  withForeignPtr vocabFPtr $ \vocabPtr ->+    c_llama_vocab_nl (CLlamaVocab vocabPtr)++-- | Get the padding token+getVocabPadToken :: Vocab -> IO LlamaToken+getVocabPadToken (Vocab vocabFPtr) = do+  withForeignPtr vocabFPtr $ \vocabPtr ->+    c_llama_vocab_pad (CLlamaVocab vocabPtr)++-- | Get whether to add BOS token automatically+getVocabAddBOSToken :: Vocab -> IO Bool+getVocabAddBOSToken (Vocab vocabFPtr) = do+  withForeignPtr vocabFPtr $ \vocabPtr ->+    (/= 0) <$> c_llama_vocab_get_add_bos (CLlamaVocab vocabPtr)++-- | Get whether to add EOS token automatically+getVocabAddEOSToken :: Vocab -> IO Bool+getVocabAddEOSToken (Vocab vocabFPtr) = do+  withForeignPtr vocabFPtr $ \vocabPtr ->+    (/= 0) <$> c_llama_vocab_get_add_eos (CLlamaVocab vocabPtr)++-- | Get the FIM prefix token+getVocabFIMPrefixToken :: Vocab -> IO LlamaToken+getVocabFIMPrefixToken (Vocab vocabFPtr) = do+  withForeignPtr vocabFPtr $ \vocabPtr ->+    c_llama_vocab_fim_pre (CLlamaVocab vocabPtr)++-- | Get the FIM suffix token+getVocabFIMSuffixToken :: Vocab -> IO LlamaToken+getVocabFIMSuffixToken (Vocab vocabFPtr) = do+  withForeignPtr vocabFPtr $ \vocabPtr ->+    c_llama_vocab_fim_suf (CLlamaVocab vocabPtr)++-- | Get the FIM middle token+getVocabFIMMiddleToken :: Vocab -> IO LlamaToken+getVocabFIMMiddleToken (Vocab vocabFPtr) = do+  withForeignPtr vocabFPtr $ \vocabPtr ->+    c_llama_vocab_fim_mid (CLlamaVocab vocabPtr)++-- | Get the FIM pad token+getVocabFIMPADToken :: Vocab -> IO LlamaToken+getVocabFIMPADToken (Vocab vocabFPtr) = do+  withForeignPtr vocabFPtr $ \vocabPtr ->+    c_llama_vocab_fim_pad (CLlamaVocab vocabPtr)++-- | Get the FIM separator token+getVocabFIMSeparatorToken :: Vocab -> IO LlamaToken+getVocabFIMSeparatorToken (Vocab vocabFPtr) = do+  withForeignPtr vocabFPtr $ \vocabPtr ->+    c_llama_vocab_fim_sep (CLlamaVocab vocabPtr)
+ test/Spec.hs view
@@ -0,0 +1,266 @@+import Control.Exception (bracket)+import Data.Either+import qualified Llama.Backend as Backend+import qualified Llama.ChatTemplate as ChatTemplate+import Llama.Context+import Llama.Model+import Test.Tasty (TestTree, defaultMain, testGroup)+import Test.Tasty.HUnit++main :: IO ()+main = defaultMain tests++tests :: TestTree+tests = do+  testGroup+    "tests"+    [ testBackend+    , testChatApplyTemplate+    , checkContextFunctions+    , checkIntFunctions+    , checkBoolFunctions+    , testModels+    -- , synchronizeContextTests ctx+    -- , warmupModeTests ctx+    -- , batchInitTests+    --  , batchGetOneTests+    --  , freeBatchTests+    -- , encodeDecodeTests ctx+    -- , threadCountTests ctx+    -- , embeddingsTests ctx+    -- , causalAttentionTests ctx+    ]++testBackend :: TestTree+testBackend =+  testGroup+    "Llama.Backend tests"+    [ testCase "llamaBackendInit and llamaBackendFree should not throw exceptions" $ do+        Backend.llamaBackendInit+        Backend.llamaBackendFree+        return ()+    , testCase "llamaBackendInit and llamaBackendFree should be idempotent" $ do+        Backend.llamaBackendInit+        Backend.llamaBackendFree+        Backend.llamaBackendFree+        return ()+    , testCase "llamaBackendInit can be called multiple times" $ do+        Backend.llamaBackendInit+        Backend.llamaBackendInit+        Backend.llamaBackendFree+        Backend.llamaBackendFree+        return ()+    , testCase "llamaBackendInit and llamaBackendFree should not throw exceptions" $ do+        bracket Backend.llamaBackendInit (const Backend.llamaBackendFree) $ \_ -> return ()+    ]++testChatApplyTemplate :: TestTree+testChatApplyTemplate =+  testGroup+    "chatApplyTemplate tests"+    [ testCase "chatApplyTemplate with no template" $ do+        messages <-+          ChatTemplate.chatApplyTemplate+            Nothing+            [ChatTemplate.ChatMessage "role" "content"]+            False+            4096+        assertBool "result is not Left" (isRight messages)+    , -- testCase "chatApplyTemplate with custom template" $ do+      --   messages <- ChatTemplate.chatApplyTemplate+      --        (Just "template") [ChatTemplate.ChatMessage "role" "content"] False 4096+      --   assertBool "result is not Left" (isRight messages), -- throwing error as of now+      testCase "chatApplyTemplate with empty messages" $ do+        messages <- ChatTemplate.chatApplyTemplate Nothing [] False 4096+        assertBool "result is not Left" (isRight messages)+    ]++checkBoolFunctions :: TestTree+checkBoolFunctions =+  testGroup+    "Boolean Functions"+    [ testCase "supportsRpc" $ do+        result <- supportsRpc+        assertBool "supportsRpc returns a boolean value" (not result) -- My env doesn't support+    , testCase "supportsGpuOffload" $ do+        result <- supportsGpuOffload+        assertBool "supportsGpuOffload returns a boolean value" (not result)+    , testCase "supportsMLock" $ do+        result <- supportsMLock+        assertBool "supportsMLock returns a boolean value" result+    , testCase "supportsMMap" $ do+        result <- supportsMMap+        assertBool "supportsMMap returns a boolean value" result+    ]++checkIntFunctions :: TestTree+checkIntFunctions =+  testGroup+    "Integer Functions"+    [ testCase "getMaxDevices" $ do+        result <- getMaxDevices+        assertBool "getMaxDevices returns a non-negative integer" (result >= 0)+    , testCase "getTimeUs" $ do+        result <- getTimeUs+        assertBool "getTimeUs returns a non-negative integer" (result >= 0)+    ]++checkContextFunctions :: TestTree+checkContextFunctions =+  testGroup+    "Context Functions"+    [ testCase "defaultContextParams" $ do+        params <- defaultContextParams+        assertBool+          "defaultContextParams returns a valid LlamaContextParams"+          (not $ null $ show params)+    ]++testModels :: TestTree+testModels =+  testGroup+    "Model functions"+    [ testCase "loadModelFromFile" testLoadModelFromFile+    , testCase "initContextFromModel" testInitContextFromModel+    , testCase "getModelVocab" testGetModelVocab+    ]++testLoadModelFromFile :: Assertion+testLoadModelFromFile = do+  params <- defaultModelParams+  result <- loadModelFromFile "Qwen3-0.6B-Q4_K_M.gguf" params+  case result of+    Right _ -> assertBool "model loaded successfully" True+    Left err -> assertFailure err++testInitContextFromModel :: Assertion+testInitContextFromModel = do+  params <- defaultModelParams+  result <- loadModelFromFile "Qwen3-0.6B-Q4_K_M.gguf" params+  case result of+    Right model -> do+      contextParams <- defaultContextParams+      result1 <- initContextFromModel model contextParams+      case result1 of+        Right _ -> assertBool "context initialized successfully" True+        Left err -> assertFailure err+    Left err -> assertFailure err++testGetModelVocab :: Assertion+testGetModelVocab = do+  params <- defaultModelParams+  result <- loadModelFromFile "Qwen3-0.6B-Q4_K_M.gguf" params+  case result of+    Right model -> do+      result1 <- getModelVocab model+      case result1 of+        Right _ -> assertBool "vocab retrieved successfully" True+        Left err -> assertFailure err+    Left err -> assertFailure err++{-+testGetContextModel :: Assertion+testGetContextModel = do+  params <- defaultModelParams+  result <- loadModelFromFile "Qwen3-0.6B-Q4_K_M.gguf" params+  case result of+    Right model -> do+      contextParams <- defaultContextParams+      result <- initContextFromModel model contextParams+      case result of+        Right context -> do+          model' <- getContextModel context+          assertEqual "models are equal" model model'+        Left err -> assertFailure err+    Left err -> assertFailure err++modelParams <- liftIO defaultModelParams+eModel <- liftIO $ loadModelFromFile "Qwen3-0.6B-Q4_K_M.gguf" modelParams+case eModel of+ Left err -> putStrLn $ "Something went wrong: " ++ err+ Right model -> do+   ctxParams <- defaultContextParams+   eCtx <- initContextFromModel model ctxParams+   case eCtx of+     Left e -> putStrLn $ "Something went wrong" ++ e+     Right ctx -> do++batchInitTests :: TestTree+batchInitTests = testGroup "batchInit tests"+    [ testCase "batchInit succeeds" $ do+        batch <- batchInit 10 256 1+        freeBatch (getBatchPtr batch)+    ]++batchGetOneTests :: TestTree+batchGetOneTests = testGroup "batchGetOne tests"+    [ testCase "batchGetOne succeeds" $ do+        batch <- batchGetOne [1, 2, 3]+        freeBatch (getBatchPtr batch)+    ]++freeBatchTests :: TestTree+freeBatchTests = testGroup "freeBatch tests"+    [ testCase "freeBatch succeeds" $ do+        batch <- batchInit 10 256 1+        freeBatch (getBatchPtr batch)+        -- No assertion, just check if it doesn't crash+    ]++getBatchPtr :: Batch -> Ptr LlamaBatch+getBatchPtr (Batch ptr) = ptr++encodeDecodeTests :: Context -> TestTree+encodeDecodeTests ctx = testGroup "encodeDecode tests"+    [ testCase "encodeBatch succeeds" $ do+        batch <- batchInit 10 256 1+        result <- encodeBatch ctx batch+        assertBool "Encoding failed" (isRight result)+        freeBatch (getBatchPtr batch)+        -- decodeBatch test+        result' <- decodeBatch ctx batch+        assertBool "Decoding failed" (isRight result')+    ]++threadCountTests :: Context -> TestTree+threadCountTests ctx = testGroup "threadCount tests"+    [ testCase "setThreadCount succeeds" $ do+        setThreadCount ctx 4+        count <- getThreadCount ctx+        assertBool "Thread count not set" (count == 4)+    , testCase "getBatchThreadCount succeeds" $ do+        setThreadCounts ctx 4 2+        count <- getBatchThreadCount ctx+        assertBool "Batch thread count not set" (count == 2)+    ]++embeddingsTests :: Context -> TestTree+embeddingsTests ctx = testGroup "embeddings tests"+    [ testCase "setEmbeddingsEnabled succeeds" $ do+        setEmbeddingsEnabled ctx True+        enabled <- areEmbeddingsEnabled ctx+        assertBool "Embeddings not enabled" enabled+    ]++causalAttentionTests ::  Context -> TestTree+causalAttentionTests ctx = testGroup "causalAttention tests"+    [ testCase "setCausalAttention succeeds" $ do+        setCausalAttention ctx True+        -- No assertion, just check if it doesn't crash+    ]++warmupModeTests :: Context -> TestTree+warmupModeTests ctx = testGroup "warmupMode tests"+    [ testCase "setWarmupMode succeeds" $ do+        setWarmupMode ctx True+        -- No assertion, just check if it doesn't crash+    ]++synchronizeContextTests :: Context -> TestTree+synchronizeContextTests ctx = testGroup "synchronizeContext tests"+    [ testCase "synchronizeContext succeeds" $ do+        synchronizeContext ctx+        -- No assertion, just check if it doesn't crash+    ]++-}