diff --git a/csrc/hasktorch_finalizer.cpp b/csrc/hasktorch_finalizer.cpp
--- a/csrc/hasktorch_finalizer.cpp
+++ b/csrc/hasktorch_finalizer.cpp
@@ -6,6 +6,10 @@
   delete tensor;
 }
 
+void delete_optionaltensor(std::optional<at::Tensor>* tensor){
+  delete tensor;
+}
+
 void delete_tensorlist(std::vector<at::Tensor>* tensors){
   delete tensors;
 }
diff --git a/csrc/hasktorch_finalizer.h b/csrc/hasktorch_finalizer.h
--- a/csrc/hasktorch_finalizer.h
+++ b/csrc/hasktorch_finalizer.h
@@ -9,12 +9,15 @@
 #include <torch/optim.h>
 
 #include <array>
+#include <optional>
 #include <string>
 #include <tuple>
 #include <vector>
 
 extern "C" {
   void delete_tensor(at::Tensor* tensor);
+
+  void delete_optionaltensor(std::optional<at::Tensor>* tensor);
 
   void delete_tensorlist(std::vector<at::Tensor>* tensors);
 
diff --git a/libtorch-ffi.cabal b/libtorch-ffi.cabal
--- a/libtorch-ffi.cabal
+++ b/libtorch-ffi.cabal
@@ -1,6 +1,6 @@
 cabal-version:       3.0
 name:                libtorch-ffi
-version:             2.0.1.8
+version:             2.0.1.9
 -- The prefix(2.0) of this version("2.0.0.0") is the same as libtorch's one.
 synopsis:            Haskell bindings for PyTorch
 description:         This package provides Haskell bindings to libtorch, the C++ library underlying PyTorch, specifically designed for the Hasktorch ecosystem.
@@ -80,6 +80,7 @@
                     , Torch.Internal.Unmanaged.Type.TensorIndex
                     , Torch.Internal.Unmanaged.Type.StdString
                     , Torch.Internal.Unmanaged.Type.StdArray
+                    , Torch.Internal.Unmanaged.Type.StdOptional
                     , Torch.Internal.Unmanaged.Type.Context
 --                    , Torch.Internal.Unmanaged.Type.ConstQuantizerPtr
                     , Torch.Internal.Unmanaged.Type.Extra
@@ -140,6 +141,7 @@
                     , Torch.Internal.Managed.Type.C10Tuple
                     , Torch.Internal.Managed.Type.Module
                     , Torch.Internal.Managed.Type.StdVector
+                    , Torch.Internal.Managed.Type.StdOptional
                     , Torch.Internal.Unmanaged.Autograd
                     , Torch.Internal.Unmanaged.TensorFactories
                     , Torch.Internal.Unmanaged.Serialize
diff --git a/src/Torch/Internal/Managed/Cast.hs b/src/Torch/Internal/Managed/Cast.hs
--- a/src/Torch/Internal/Managed/Cast.hs
+++ b/src/Torch/Internal/Managed/Cast.hs
@@ -20,6 +20,7 @@
 import Torch.Internal.Managed.Type.C10Tuple
 import Torch.Internal.Managed.Type.C10Dict
 import Torch.Internal.Managed.Type.StdVector
+import Torch.Internal.Managed.Type.StdOptional
 
 instance Castable Int (ForeignPtr IntArray) where
   cast xs f = do
@@ -141,3 +142,18 @@
     forM_ xs $ \(k,v) -> (c10Dict_insert l k v)
     f l
   uncast xs f = f =<< c10Dict_toList xs
+
+instance Castable (Maybe (ForeignPtr Tensor)) (ForeignPtr (StdOptional Tensor)) where
+  cast Nothing f = do
+    optionalTensor <- stdOptionalTensor_empty
+    f optionalTensor
+  cast (Just tensor) f = do
+    optionalTensor <- stdOptionalTensor_create tensor
+    f optionalTensor
+  uncast optionalTensor f = do
+    hasValue <- stdOptionalTensor_has_value optionalTensor
+    if hasValue /= 0
+      then do
+        tensor <- stdOptionalTensor_value optionalTensor
+        f (Just tensor)
+      else f Nothing
diff --git a/src/Torch/Internal/Managed/Native/Native12.hs b/src/Torch/Internal/Managed/Native/Native12.hs
--- a/src/Torch/Internal/Managed/Native/Native12.hs
+++ b/src/Torch/Internal/Managed/Native/Native12.hs
@@ -1413,6 +1413,18 @@
   -> IO (ForeignPtr (StdTuple '(Tensor,Tensor)))
 _native_multi_head_attention_tttlltttt = _cast9 Unmanaged._native_multi_head_attention_tttlltttt
 
+scaled_dot_product_attention_tttqdbdb
+  :: ForeignPtr Tensor
+  -> ForeignPtr Tensor
+  -> ForeignPtr Tensor
+  -> ForeignPtr OptionalTensor
+  -> CDouble
+  -> CBool
+  -> CDouble
+  -> CBool
+  -> IO (ForeignPtr Tensor)
+scaled_dot_product_attention_tttqdbdb = _cast8 Unmanaged.scaled_dot_product_attention_tttqdbdb
+
 scaled_dot_product_attention_ttttdb
   :: ForeignPtr Tensor
   -> ForeignPtr Tensor
diff --git a/src/Torch/Internal/Managed/Type/StdOptional.hs b/src/Torch/Internal/Managed/Type/StdOptional.hs
new file mode 100644
--- /dev/null
+++ b/src/Torch/Internal/Managed/Type/StdOptional.hs
@@ -0,0 +1,31 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TypeFamilies #-}
+
+module Torch.Internal.Managed.Type.StdOptional where
+
+import Foreign
+import Foreign.C.String
+import Foreign.C.Types
+import Torch.Internal.Cast
+import Torch.Internal.Class
+import Torch.Internal.Objects
+import Torch.Internal.Type
+import qualified Torch.Internal.Unmanaged.Type.StdOptional as Unmanaged
+
+stdOptionalTensor_create :: ForeignPtr Tensor -> IO (ForeignPtr (StdOptional Tensor))
+stdOptionalTensor_create tensor = _cast1 Unmanaged.stdOptionalTensor_create tensor
+
+stdOptionalTensor_empty :: IO (ForeignPtr (StdOptional Tensor))
+stdOptionalTensor_empty = _cast0 Unmanaged.stdOptionalTensor_empty
+
+stdOptionalTensor_has_value :: ForeignPtr (StdOptional Tensor) -> IO CBool
+stdOptionalTensor_has_value optionalTensor = _cast1 Unmanaged.stdOptionalTensor_has_value optionalTensor
+
+stdOptionalTensor_value :: ForeignPtr (StdOptional Tensor) -> IO (ForeignPtr Tensor)
+stdOptionalTensor_value optionalTensor = _cast1 Unmanaged.stdOptionalTensor_value optionalTensor
diff --git a/src/Torch/Internal/Objects.hs b/src/Torch/Internal/Objects.hs
--- a/src/Torch/Internal/Objects.hs
+++ b/src/Torch/Internal/Objects.hs
@@ -369,6 +369,18 @@
   deletePtr ptr = c_delete_tensorindexlist' ptr
   {-# INLINE deletePtr #-}
 
+foreign import ccall unsafe "hasktorch_finalizer.h &delete_optionaltensor"
+  c_delete_optionaltensor :: FunPtr ( Ptr OptionalTensor -> IO ())
+
+foreign import ccall unsafe "hasktorch_finalizer.h delete_optionaltensor"
+  c_delete_optionaltensor' ::  Ptr OptionalTensor -> IO ()
+
+instance CppObject OptionalTensor where
+  fromPtr ptr = newForeignPtr c_delete_optionaltensor ptr
+  {-# INLINE fromPtr #-}
+  deletePtr ptr = c_delete_optionaltensor' ptr
+  {-# INLINE deletePtr #-}
+
 foreign import ccall unsafe "hasktorch_finalizer.h &delete_tensorlist"
   c_delete_tensorlist :: FunPtr ( Ptr TensorList -> IO ())
 
diff --git a/src/Torch/Internal/Type.hs b/src/Torch/Internal/Type.hs
--- a/src/Torch/Internal/Type.hs
+++ b/src/Torch/Internal/Type.hs
@@ -31,9 +31,16 @@
 -- std::tuple<a>
 data StdTuple a
 
+-- std::optional<a>
+data StdOptional a
+
 -- at::Tensor
 data Tensor
 
+
+-- std::optional<at::Tensor>
+type OptionalTensor = StdOptional Tensor
+
 -- std::vector<at::Tensor>
 type TensorList = StdVector Tensor
 
@@ -93,6 +100,7 @@
 typeTable :: Map.Map C.TypeSpecifier TH.TypeQ
 typeTable = Map.fromList [
         (C.TypeName "std::array", [t|StdArray|])
+      , (C.TypeName "std::optional", [t|StdOptional|])
       , (C.TypeName "std::vector", [t|StdVector|])
       , (C.TypeName "std::tuple", [t|StdTuple|])
       , (C.TypeName "at::Scalar", [t|Scalar|])
diff --git a/src/Torch/Internal/Unmanaged/Native/Native12.hs b/src/Torch/Internal/Unmanaged/Native/Native12.hs
--- a/src/Torch/Internal/Unmanaged/Native/Native12.hs
+++ b/src/Torch/Internal/Unmanaged/Native/Native12.hs
@@ -2434,6 +2434,28 @@
   , *$(at::Tensor* _proj_bias)));
   }|]
 
+scaled_dot_product_attention_tttqdbdb
+  :: Ptr Tensor
+  -> Ptr Tensor
+  -> Ptr Tensor
+  -> Ptr OptionalTensor
+  -> CDouble
+  -> CBool
+  -> CDouble
+  -> CBool
+  -> IO (Ptr Tensor)
+scaled_dot_product_attention_tttqdbdb _query _key _value _attn_mask _dropout_p _is_causal _scale _enable_gqa =
+  [C.throwBlock| at::Tensor* { return new at::Tensor(at::scaled_dot_product_attention(
+    *$(at::Tensor* _query)
+  , *$(at::Tensor* _key)
+  , *$(at::Tensor* _value)
+  , *$(std::optional<at::Tensor>* _attn_mask)
+  , $(double _dropout_p)
+  , $(bool _is_causal)
+  , $(double _scale)
+  , $(bool _enable_gqa)));
+  }|]
+
 scaled_dot_product_attention_ttttdb
   :: Ptr Tensor
   -> Ptr Tensor
diff --git a/src/Torch/Internal/Unmanaged/Type/StdOptional.hs b/src/Torch/Internal/Unmanaged/Type/StdOptional.hs
new file mode 100644
--- /dev/null
+++ b/src/Torch/Internal/Unmanaged/Type/StdOptional.hs
@@ -0,0 +1,46 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TypeFamilies #-}
+
+module Torch.Internal.Unmanaged.Type.StdOptional where
+
+import Foreign
+import Foreign.C.Types
+import qualified Language.C.Inline.Context as C
+import qualified Language.C.Inline.Cpp as C
+import qualified Language.C.Inline.Cpp.Unsafe as C
+import Torch.Internal.Type
+
+C.context $ C.cppCtx <> mempty {C.ctxTypesTable = typeTable}
+
+C.include "<ATen/Tensor.h>"
+C.include "<optional>"
+
+stdOptionalTensor_create :: Ptr Tensor -> IO (Ptr (StdOptional Tensor))
+stdOptionalTensor_create tensor =
+  [C.throwBlock| std::optional<at::Tensor>* {
+    return new std::optional<at::Tensor>(std::make_optional(*$(at::Tensor* tensor)));
+}|]
+
+stdOptionalTensor_empty :: IO (Ptr (StdOptional Tensor))
+stdOptionalTensor_empty =
+  [C.throwBlock| std::optional<at::Tensor>* {
+    return new std::optional<at::Tensor>(std::nullopt);
+}|]
+
+stdOptionalTensor_has_value :: Ptr (StdOptional Tensor) -> IO CBool
+stdOptionalTensor_has_value _obj =
+  [C.throwBlock| bool {
+    return $(std::optional<at::Tensor>* _obj)->has_value();
+}|]
+
+stdOptionalTensor_value :: Ptr (StdOptional Tensor) -> IO (Ptr Tensor)
+stdOptionalTensor_value _obj =
+  [C.throwBlock| at::Tensor* {
+    return new at::Tensor($(std::optional<at::Tensor>* _obj)->value());
+}|]
diff --git a/test/BasicSpec.hs b/test/BasicSpec.hs
--- a/test/BasicSpec.hs
+++ b/test/BasicSpec.hs
@@ -22,6 +22,7 @@
 import Torch.Internal.Managed.Type.Scalar
 import Torch.Internal.Managed.Type.Tuple
 import Torch.Internal.Managed.Type.Context
+import Torch.Internal.Managed.Type.StdOptional
 import Torch.Internal.Managed.Native
 
 intArray :: [Int64] -> IO (ForeignPtr IntArray)
@@ -407,6 +408,23 @@
     forM_ [0..(num-1)] $ \i -> do
       ap2 tensor_equal_t (at1 tensor i) (ap2 mul_ts (pure one) (newScalar_i (fromIntegral i))) `shouldReturn` 1
     at1 tensor 314 `shouldThrow` anyException
+
+  it "TestOptionalTensorEmpty" $ do
+    optTensor <- stdOptionalTensor_empty
+    hasValue <- stdOptionalTensor_has_value optTensor
+    hasValue `shouldBe` 0
+
+  it "TestOptionalTensorCreate" $ do
+    tensor <- new' ones_lo [2, 3] dtype
+    optTensor <- stdOptionalTensor_create tensor
+    hasValue <- stdOptionalTensor_has_value optTensor
+    hasValue `shouldBe` 1
+
+  it "TestOptionalTensorValue" $ do
+    tensor <- new' ones_lo [2, 3] dtype
+    optTensor <- stdOptionalTensor_create tensor
+    extractedTensor <- stdOptionalTensor_value optTensor
+    tensor_numel extractedTensor `shouldReturn` 6
 
 
 -- void TestIndexingByZerodimTensor() {
