
    ǄgQ                        d dl mZmZmZmZ d dlZd dlmc mZ	 d dlm
Z
mZ d dlmZmZ d dlmZmZ g dZ	 	 	 ddeeee   eedf   f   d	ee   d
ee   defdZ eej,                  d      ZdddddddefdZej2                  fdededeeef   deeef   def
dZ	 	 	 	 	 d dedee   dee   dee   dee   dee   defdZdededefdZy)!    )ListOptionalTupleUnionN)SymIntTensor)_add_docstr_nested)_device_dtype)to_padded_tensoras_nested_tensornested_tensornested_tensor_from_jaggednarrowmasked_selectts.dtypedevicereturnc                 ~   t        | t        t        f      xr t        d | D              }t        | t              s|st        d      |rt        | t              st        |       } t        | t              r| j                         dk  rt        d      t        | t              r9| j                  r-|| j                  k(  r| j                  ||      S t        d      |t        j                  }|t        j                  k(  rt        | t              r| j                         j                  d      j                  ||      }t        j                  | D cg c]  }|j                    c}      }t        j"                  ||gt        j$                  |       S t        | t              sJ t        j&                  | |d|d      S |t        j(                  k(  rt        | t              r|| j*                  }| j                         j-                  d	d
      j                  ||      }| j                   d	   }	| j                   d
   }
t        j.                  d	|	|
z  d
z   |
|t        j0                        }d	dlm}  ||||
|
      S d	dlm} t        | t              sJ  || d||      \  }}|S t        d|       c c}w )a&  
    Constructs a nested tensor preserving autograd history from a tensor or a list / tuple of
    tensors.

    If a nested tensor is passed, it will be returned directly unless the device / dtype / layout
    differ. Note that converting device / dtype will result in a copy, while converting layout
    is not currently supported by this function.

    If a non-nested tensor is passed, it is treated as a batch of constituents of consistent size.
    A copy will be incurred if the passed device / dtype differ from those of the input OR if
    the input is non-contiguous. Otherwise, the input's storage will be used directly.

    If a tensor list is provided, tensors in the list are always copied during construction of
    the nested tensor.

    Args:
        ts (Tensor or List[Tensor] or Tuple[Tensor]): a tensor to treat as a nested tensor OR a
            list / tuple of tensors with the same ndim

    Keyword arguments:
        dtype (:class:`torch.dtype`, optional): the desired type of returned nested tensor.
            Default: if None, same :class:`torch.dtype` as leftmost tensor in the list.
        device (:class:`torch.device`, optional): the desired device of returned nested tensor.
            Default: if None, same :class:`torch.device` as leftmost tensor in the list
        layout (:class:`torch.layout`, optional): the desired layout of returned nested tensor.
            Only strided and jagged layouts are supported. Default: if None, the strided layout.

    Example::

        >>> a = torch.arange(3, dtype=torch.float, requires_grad=True)
        >>> b = torch.arange(5, dtype=torch.float, requires_grad=True)
        >>> nt = torch.nested.as_nested_tensor([a, b])
        >>> nt.is_leaf
        False
        >>> fake_grad = torch.nested.nested_tensor([torch.ones_like(a), torch.zeros_like(b)])
        >>> nt.backward(fake_grad)
        >>> a.grad
        tensor([1., 1., 1.])
        >>> b.grad
        tensor([0., 0., 0., 0., 0.])
        >>> c = torch.randn(3, 5, requires_grad=True)
        >>> nt2 = torch.nested.as_nested_tensor(c)
    c              3   <   K   | ]  }t        |t                y w)N)
isinstancer   ).0ts     ]/home/mcse/projects/flask_80/flask-venv/lib/python3.12/site-packages/torch/nested/__init__.py	<genexpr>z#as_nested_tensor.<locals>.<genexpr>H   s     :]UV:a;P:]s   zXas_nested_tensor(): Expected first argument to be a tensor or a list / tuple of tensors    z>as_nested_tensor(): Expected tensor argument to have dim() > 1r   r   zMas_nested_tensor(): Converting between nested tensor layouts is not supportedNr      nested_view_from_values_offsets)
min_seqlen
max_seqlenjagged_from_listoffsetsr   r   4Specified layout is unsupported for nested tensors: )r   listtupleallr   	TypeErrordimRuntimeError	is_nestedlayouttotorchstrided
contiguousviewtensorshape_nested_view_from_buffer*_nested_compute_contiguous_strides_offsets_nested_tensor_from_tensor_listjaggedr   flattenarangeint64$torch.nested._internal.nested_tensorr#   r'   )r   r   r   r2   is_tensor_listbufferr   nested_sizesvalues
batch_sizeseq_lenr)   r#   r'   nt_s                   r   r   r      s|   b  T5M2]s:]Z\:]7]Nb&!.f
 	
 jT2"X"f"&&(Q,[\\"f",,RYY55e544 _a a ~b&! ]]_))"-00e0LF <<"(=Q(=>L11Q AA,OQ Q
 b$'''88UD&RVWW	5<<	b&!~ ]]_,,Q255V55QF!JhhqkGll1j7&:Q&>*0EG ]2G  Nb$'''$RfEREBIQRXQYZ[[C )>s   J:a	  
to_padded_tensor(input, padding, output_size=None, out=None) -> Tensor

Returns a new (non-nested) Tensor by padding the :attr:`input` nested tensor.
The leading entries will be filled with the nested data,
while the trailing entries will be padded.

.. warning::

    :func:`to_padded_tensor` always copies the underlying data,
    since the nested and the non-nested tensors differ in memory layout.

Args:
    padding (float): The padding value for the trailing entries.

Keyword args:
    output_size (Tuple[int]): The size of the output tensor.
                              If given, it must be large enough to contain all nested data;
                              else, will infer by taking the max size of each nested sub-tensor along each dimension.
    out (Tensor, optional): the output tensor.

Example::

    >>> nt = torch.nested.nested_tensor([torch.randn((2, 5)), torch.randn((3, 4))])
    nested_tensor([
      tensor([[ 1.6862, -1.1282,  1.1031,  0.0464, -1.3276],
              [-1.9967, -1.0054,  1.8972,  0.9174, -1.4995]]),
      tensor([[-1.8546, -0.7194, -0.2918, -0.1846],
              [ 0.2773,  0.8793, -0.5183, -0.6447],
              [ 1.8009,  1.8468, -0.9832, -1.5272]])
    ])
    >>> pt_infer = torch.nested.to_padded_tensor(nt, 0.0)
    tensor([[[ 1.6862, -1.1282,  1.1031,  0.0464, -1.3276],
             [-1.9967, -1.0054,  1.8972,  0.9174, -1.4995],
             [ 0.0000,  0.0000,  0.0000,  0.0000,  0.0000]],
            [[-1.8546, -0.7194, -0.2918, -0.1846,  0.0000],
             [ 0.2773,  0.8793, -0.5183, -0.6447,  0.0000],
             [ 1.8009,  1.8468, -0.9832, -1.5272,  0.0000]]])
    >>> pt_large = torch.nested.to_padded_tensor(nt, 1.0, (2, 4, 6))
    tensor([[[ 1.6862, -1.1282,  1.1031,  0.0464, -1.3276,  1.0000],
             [-1.9967, -1.0054,  1.8972,  0.9174, -1.4995,  1.0000],
             [ 1.0000,  1.0000,  1.0000,  1.0000,  1.0000,  1.0000],
             [ 1.0000,  1.0000,  1.0000,  1.0000,  1.0000,  1.0000]],
            [[-1.8546, -0.7194, -0.2918, -0.1846,  1.0000,  1.0000],
             [ 0.2773,  0.8793, -0.5183, -0.6447,  1.0000,  1.0000],
             [ 1.8009,  1.8468, -0.9832, -1.5272,  1.0000,  1.0000],
             [ 1.0000,  1.0000,  1.0000,  1.0000,  1.0000,  1.0000]]])
    >>> pt_small = torch.nested.to_padded_tensor(nt, 2.0, (2, 2, 2))
    RuntimeError: Value in output_size is less than NestedTensor padded size. Truncation is not supported.

F)r   r2   r   requires_grad
pin_memoryc                   |t         j                  }|t         j                  k(  rt        j                  | ||||      S |t         j                  k(  r| D cg c])  }t        |t              r|nt        j                  |      + }}ddlm	} t        j                         5   ||d||      \  }	}
ddd       	j                  |       |r|	j                         }	|	S t        d|       c c}w # 1 sw Y   AxY w)a  
Constructs a nested tensor with no autograd history (also known as a "leaf tensor", see
:ref:`Autograd mechanics <autograd-mechanics>`) from :attr:`tensor_list` a list of tensors.

Args:
    tensor_list (List[array_like]): a list of tensors, or anything that can be passed to torch.tensor,
    where each element of the list has the same dimensionality.

Keyword arguments:
    dtype (:class:`torch.dtype`, optional): the desired type of returned nested tensor.
        Default: if None, same :class:`torch.dtype` as leftmost tensor in the list.
    layout (:class:`torch.layout`, optional): the desired layout of returned nested tensor.
        Only strided and jagged layouts are supported. Default: if None, the strided layout.
    device (:class:`torch.device`, optional): the desired device of returned nested tensor.
        Default: if None, same :class:`torch.device` as leftmost tensor in the list
    requires_grad (bool, optional): If autograd should record operations on the
        returned nested tensor. Default: ``False``.
    pin_memory (bool, optional): If set, returned nested tensor would be allocated in
        the pinned memory. Works only for CPU tensors. Default: ``False``.

Example::

    >>> a = torch.arange(3, dtype=torch.float, requires_grad=True)
    >>> b = torch.arange(5, dtype=torch.float, requires_grad=True)
    >>> nt = torch.nested.nested_tensor([a, b], requires_grad=True)
    >>> nt.is_leaf
    True
    N)r   r   rJ   rK   r   r&   r(   r*   )r4   r5   r
   r   r=   r   r   	as_tensorrA   r'   no_gradrequires_grad_rK   r0   )tensor_listr   r2   r   rJ   rK   r   list_of_tensorsr'   rH   rI   s              r   r   r      s    : ~$$'!# 	# 
5<<	WbcRS
1f 515??1;MMccI]]_ 	`$_d6Y^_EB	` 	-(B	QRXQYZ[[ d	` 	`s   .C,!C11C:r8   r/   startlengthc                 B   t        |t        t        t        f      st	        d      t        |t        t        t        f      st	        d      |t
        j                  k(  rlt        |t              st        |t              rt	        d      t        t        j                  |       t
        j                        j                  |||      }|S |t
        j                  k(  r|dk7  rt	        d      ddlm} t        |t        t        f      r1t        j                  |g| j                  t
        j                  	      }t        |t        t        f      r1t        j                  |g| j                  t
        j                  	      } || ||      \  }}}|S t	        d
|       )a  
Constructs a nested tensor (which might be a view) from :attr:`tensor`, a strided tensor. This follows
similar semantics to torch.Tensor.narrow, where in the :attr:`dim`-th dimension the new nested tensor
shows only the elements in the interval `[start, start+length)`. As nested representations
allow for a different `start` and `length` at each 'row' of that dimension, :attr:`start` and :attr:`length`
can also be tensors of shape `tensor.shape[0]`.

There's some differences depending on the layout you use for the nested tensor. If using strided layout,
torch.narrow will do a copy of the narrowed data into a contiguous NT with strided layout, while
jagged layout narrow() will create a non-contiguous view of your original strided tensor. This particular
representation is really useful for representing kv-caches in Transformer models, as specialized
SDPA kernels can deal with format easily, resulting in performance improvements.


Args:
    tensor (:class:`torch.Tensor`): a strided tensor, which will be used as the underlying data
        for the nested tensor if using the jagged layout or will be copied for the strided layout.
    dim (int): the dimension where narrow will be applied. Only `dim=1` is supported for the
        jagged layout, while strided supports all dim
    start (Union[int, :class:`torch.Tensor`]): starting element for the narrow operation
    length (Union[int, :class:`torch.Tensor`]): number of elements taken during the narrow op

Keyword arguments:
    layout (:class:`torch.layout`, optional): the desired layout of returned nested tensor.
        Only strided and jagged layouts are supported. Default: if None, the strided layout.

Example::

    >>> starts = torch.tensor([0, 1, 2, 3, 4], dtype=torch.int64)
    >>> lengths = torch.tensor([3, 2, 2, 1, 5], dtype=torch.int64)
    >>> narrow_base = torch.randn(5, 10, 20)
    >>> nt_narrowed = torch.nested.narrow(narrow_base, 1, starts, lengths, layout=torch.jagged)
    >>> nt_narrowed.is_contiguous()
    False
    z$start must be an integer or a tensorz%length must be an integer or a tensorz@start and length must be integers for the strided layout NT impl)r2   r!   z!jagged layout only supports dim=1r   )jagged_from_tensor_and_lengthsr   z3Specified layout is unsupported for nested narrow: )r   intr   r   r0   r4   r5   r   unbindr   r=   rA   rU   r8   r   r@   )r8   r/   rR   rS   r2   rH   rU   rI   s           r   r   r      sF   H ec6623ABBfsFF34BCCeV$
66(Babbell625==IPPQTV[]cd" I! 
5<<	!8BCCWec6]+LL%ekkREfsFm,\\6(6==TF1&%HAq I PQWPXYZZ    rE   r)   lengths
jagged_dimr$   r%   c                     ddl m}  |       rt        d      |4|t        d      t        j                  |j                  d      d      }d}|d}ddlm}  || |||||	      S )
aH  
Constructs a jagged layout nested tensor from the given jagged components. The jagged layout
consists of a required values buffer with the jagged dimension packed into a single dimension.
The offsets / lengths metadata determines how this dimension is split into batch elements
and are expected to be allocated on the same device as the values buffer.

Expected metadata formats:
    * offsets: Indices within the packed dimension splitting it into heterogeneously-sized
      batch elements. Example: [0, 2, 3, 6] indicates that a packed jagged dim of size 6
      should be conceptually split into batch elements of length [2, 1, 3]. Note that both the
      beginning and ending offsets are required for kernel convenience (i.e. shape batch_size + 1).
    * lengths: Lengths of the individual batch elements; shape == batch_size. Example: [2, 1, 3]
      indicates that a packed jagged dim of size 6 should be conceptually split into batch
      elements of length [2, 1, 3].

Note that it can be useful to provide both offsets and lengths. This describes a nested tensor
with "holes", where the offsets indicate the start position of each batch item and the length
specifies the total number of elements (see example below).

The returned jagged layout nested tensor will be a view of the input values tensor.

Args:
    values (:class:`torch.Tensor`): The underlying buffer in the shape of
        (sum_B(*), D_1, ..., D_N). The jagged dimension is packed into a single dimension,
        with the offsets / lengths metadata used to distinguish batch elements.
    offsets (optional :class:`torch.Tensor`): Offsets into the jagged dimension of shape B + 1.
    lengths (optional :class:`torch.Tensor`): Lengths of the batch elements of shape B.
    jagged_dim (optional int): Indicates which dimension in values is the packed jagged
        dimension. If None, this is set to dim=1 (i.e. the dimension immediately following
        the batch dimension). Default: None
    min_seqlen (optional int): If set, uses the specified value as the cached minimum sequence
        length for the returned nested tensor. This can be a useful alternative to computing
        this value on-demand, possibly avoiding a GPU -> CPU sync. Default: None
    max_seqlen (optional int): If set, uses the specified value as the cached maximum sequence
        length for the returned nested tensor. This can be a useful alternative to computing
        this value on-demand, possibly avoiding a GPU -> CPU sync. Default: None

Example::

    >>> values = torch.randn(12, 5)
    >>> offsets = torch.tensor([0, 3, 5, 6, 10, 12])
    >>> nt = nested_tensor_from_jagged(values, offsets)
    >>> # 3D shape with the middle dimension jagged
    >>> nt.shape
    torch.Size([5, j2, 5])
    >>> # Length of each item in the batch:
    >>> offsets.diff()
    tensor([3, 2, 1, 4, 2])

    >>> values = torch.randn(6, 5)
    >>> offsets = torch.tensor([0, 2, 3, 6])
    >>> lengths = torch.tensor([1, 1, 2])
    >>> # NT with holes
    >>> nt = nested_tensor_from_jagged(values, offsets, lengths)
    >>> a, b, c = nt.unbind()
    >>> # Batch item 1 consists of indices [0, 1)
    >>> torch.equal(a, values[0:1, :])
    True
    >>> # Batch item 2 consists of indices [2, 3)
    >>> torch.equal(b, values[2:3, :])
    True
    >>> # Batch item 3 consists of indices [3, 5)
    >>> torch.equal(c, values[3:5, :])
    True
    r   )is_fx_tracingztorch.nested.nested_tensor_from_jagged does not support tracing with fx.symbolic_trace. Use fx.wrap to wrap the function that calls nested_tensor_from_jagged.NzLnested_tensor_from_jagged(): At least one of offsets or lengths is required.r!   r   r!   )'nested_view_from_values_offsets_lengths)
ragged_idxr$   r%   )torch.fx._symbolic_tracer\   r0   FpadcumsumrA   r^   )rE   r)   rY   rZ   r$   r%   r\   r^   s           r   r   r   <  s    R 7U
 	

 ?^  eeGNN1-v6GG
\2ZJ[eg grX   maskc                    | j                   t        j                  k7  rt        d| j                          |j                   t        j                  k7  rt        d|j                          | j	                  |      }|j                  | j                        }|j                  | j                  dz
        j                  d      }ddl
m}  ||t        j                  |j                  d      d      	      S )
a  
    Constructs a nested tensor given a strided tensor input and a strided mask, the resulting jagged layout nested tensor
    will have values retain values where the mask is equal to True. The dimensionality of the mask is preserved and is
    represented with the offsets, this is unlike :func:`masked_select` where the output is collapsed to a 1D tensor.

    Args:
    tensor (:class:`torch.Tensor`): a strided tensor from which the jagged layout nested tensor is constructed from.
    mask (:class:`torch.Tensor`): a strided mask tensor which is applied to the tensor input

    Example::

    >>> tensor = torch.randn(3, 3)
    >>> mask = torch.tensor([[False, False, True], [True, False, True], [False, False, True]])
    >>> nt = torch.nested.masked_select(tensor, mask)
    >>> nt.shape
    torch.Size([3, j4])
    >>> # Length of each item in the batch:
    >>> nt.offsets().diff()
    tensor([1, 2, 1])

    >>> tensor = torch.randn(6, 5)
    >>> mask = torch.tensor([False])
    >>> nt = torch.nested.masked_select(tensor, mask)
    >>> nt.shape
    torch.Size([6, j5])
    >>> # Length of each item in the batch:
    >>> nt.offsets().diff()
    tensor([0, 0, 0, 0, 0, 0])
    z<torch.nested.masked_select requires a strided tensor, given z;torch.nested.masked_select requires a strided mask, given: r!   )r/   r    r   r"   r]   )rE   r)   )r2   r4   r5   r0   r   expandr9   sumndimr7   rA   r#   ra   rb   rc   )r8   rd   
res_valuesexpanded_maskres_lengthsr#   s         r   r   r     s    < }}%J6==/Z
 	
 {{emm#I$++W
 	
 %%d+JKK-M##a#8==bAK +k((Q(/8 rX   )NNN)NNNNN)typingr   r   r   r   r4   torch.nn.functionalnn
functionalra   r   r   torch._Cr	   r
   torch.typesr   Devicer   DType__all__r   nested_to_padded_tensorr   r   r5   rV   r   r   r    rX   r   <module>rw      s   / /      ) : "#	n\fd6lE&#+$667n\E?n\ Vn\
 n\h ##25 n )-T$V[hm 5\rx 5\p dicpcp ?6 ? ?E#v+,> ?cSYkHZ ?u{ ?H !% $ $ $ $agagfag fag 	ag
 ag ag agF2& 2 26 2rX   