langchain-hs-0.0.3.0: src/Langchain/VectorStore/Core.hs
{- |
Module : Langchain.VectorStore.Core
Description : Core vector store abstraction for semantic search
Copyright : (c) 2025 Tushar Adhatrao
License : MIT
Maintainer : Tushar Adhatrao <tusharadhatrao@gmail.com>
Stability : experimental
Haskell implementation of LangChain's vector store interface, providing:
- Document storage with vector embeddings
- Similarity-based search capabilities
- Integration with Runnable workflows
Example usage with hypothetical FAISS store:
@
-- Create vector store instance
faissStore :: FAISSStore
faissStore = emptyFAISSStore
-- Add documents with embeddings
docs = [Document "Haskell is functional" mempty, ...]
updatedStore <- addDocuments faissStore docs
-- Perform similarity search
results <- similaritySearch updatedStore "functional programming" 5
-- Returns top 5 relevant documents
@
-}
module Langchain.VectorStore.Core (VectorStore (..))
where
import Control.Monad.IO.Class (MonadIO, liftIO)
import Data.Int (Int64)
import Data.Text (Text)
import Langchain.DocumentLoader.Core
import Langchain.Error (LangchainResult)
-- TODO: Add delete document mechanism, for this we need to generate and use id (Int)
{- | Vector store abstraction following LangChain's design patterns
Implementations should handle document storage, vectorization, and similarity search.
Example instance for an in-memory store:
@
data InMemoryStore = InMemoryStore
{ documents :: [Document]
, embeddings :: [[Float]]
}
instance VectorStore InMemoryStore where
addDocuments store docs = ...
similaritySearch store query k = ...
@
-}
class VectorStore vs where
{- | Add documents to the vector store
Example:
>>> addDocuments myStore [Document "Test content" mempty]
Right (updatedStoreWithNewDocs)
-}
addDocuments :: vs -> [Document] -> IO (LangchainResult vs)
addDocumentsM :: MonadIO m => vs -> [Document] -> m (LangchainResult vs)
addDocumentsM store docs = liftIO $ addDocuments store docs
{- |
Requires document ID tracking to be implemented in store instances.
Example usage (when implemented):
>>> delete myStore [123]
Right (storeWithoutDoc123)
-}
delete :: vs -> [Int64] -> IO (LangchainResult vs)
deleteM :: MonadIO m => vs -> [Int64] -> m (LangchainResult vs)
deleteM store ids = liftIO $ delete store ids
{- | Find documents similar to query text
Uses embedded vector representations for semantic search.
Example:
>>> similaritySearch store "Haskell monads" 3
Right [Document "Monads in FP...", ...]
-}
similaritySearch :: vs -> Text -> Int -> IO (LangchainResult [Document])
similaritySearchM :: MonadIO m => vs -> Text -> Int -> m (LangchainResult [Document])
similaritySearchM store query k = liftIO $ similaritySearch store query k
{- | Find documents similar to vector representation
For direct vector comparisons without text conversion.
Example:
>>> similaritySearchByVector store [0.1, 0.3, ...] 5
Right [mostSimilarDoc1, ...]
-}
similaritySearchByVector :: vs -> [Float] -> Int -> IO (LangchainResult [Document])
similaritySearchByVectorM :: MonadIO m => vs -> [Float] -> Int -> m (LangchainResult [Document])
similaritySearchByVectorM store vector k = liftIO $ similaritySearchByVector store vector k
{- $examples
Test case patterns:
1. Document addition
>>> addDocuments emptyStore [doc1, doc2]
Right (storeWithDocs)
2. Similarity search
>>> similaritySearch populatedStore "AI" 3
Right [relevantDoc1, relevantDoc2, relevantDoc3]
3. Vector-based search
>>> similaritySearchByVector store [0.5, 0.2, ...] 5
Right [top5MatchingDocs]
-}