packages feed

langchain-hs-0.0.5.0: test/Test/Langchain/Integration/OllamaEmbeddingSpec.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}

module Test.Langchain.Integration.OllamaEmbeddingSpec (tests) where

import Control.Monad.Except (runExceptT)
import qualified Data.Map.Strict as Map
import qualified Data.Text.Lazy as TL
import Test.Tasty
import Test.Tasty.HUnit

import Langchain.DocumentLoader.Core (Document (..))
import Langchain.Embeddings.Ollama (OllamaEmbeddings (..))
import Langchain.VectorStore.Core (VectorStore (..))
import Langchain.VectorStore.InMemory (InMemory, fromDocuments)
import Test.Langchain.TestHelpers (defaultEmbedModel, withOllamaModel)

tests :: TestTree
tests =
  testGroup
    "Langchain.Integration.OllamaEmbeddingSpec"
    [ testCase "Ollama live embeddings and vector similarity search" $ do
        withOllamaModel defaultEmbedModel $ \mName -> do
          let embedModel = OllamaEmbeddings mName Nothing Nothing Nothing
              docs =
                [ Document "Haskell is a statically typed, purely functional programming language." Map.empty
                , Document "Python is a dynamic programming language commonly used for machine learning." Map.empty
                , Document "Rust is a systems language focused on memory safety without garbage collection." Map.empty
                ]
          resStore <- runExceptT $ fromDocuments embedModel docs
          case resStore of
            Left err -> putStrLn $ " [NOTICE] Ollama embeddings failed (model might need pull): " ++ show err
            Right (store :: InMemory OllamaEmbeddings) -> do
              resSearch <- runExceptT $ similaritySearch store "pure functional language with types" 1
              case resSearch of
                Left err -> assertFailure ("Similarity search failed: " ++ show err)
                Right matches -> case matches of
                  [topMatch] -> assertBool "Top match is Haskell" ("Haskell" `TL.isInfixOf` pageContent topMatch)
                  _ -> assertFailure ("Expected exactly 1 match, got " ++ show (length matches))
    ]