o
    پi                     @   s   d dl mZ d dlmZmZmZmZmZ d dlZ	d dl
Z
d dlmZ er*d dlmZ eee
jedf Zdd Zdd	 ZG d
d deZdS )    )abstractmethod)TYPE_CHECKINGListProtocolTypeUnionN)NDArrayzmx.arrayc                 C   s2   zdd l m} W n
 ty   Y dS w t| |jS Nr   F)mlx.corecoreImportError
issubclassarray)
array_typemx r   ]/home/ubuntu/.local/lib/python3.10/site-packages/outlines/processors/base_logits_processor.pyis_mlx_array_type   s   r   c                 C   s>   zdd l }W n
 ty   Y dS w t| |jjpt| |jjS r	   )jaxlibr   r   xla_extension	ArrayImpl
isinstance)r   r   r   r   r   is_jax_array_type   s   r   c                   @   s   e Zd ZdZedeee  dejdejfddZ	e
 dededefddZed	edejfd
dZedejdedefddZdS )OutlinesLogitsProcessora  
    Base class for logits processors which normalizes types of logits:
    - ndarray (used by llama-cpp-python), converted to torch.Tensor
    - mlx.core.array (used by mlx-lm), converted to torch.Tensor
    - torch.Tensor (used by everything else)

    Normalization of types and conversion to torch.Tensor
    doesn't move memory, it just casts the type.

    Normalizing the types allows all logits processors inheriting from this class
    to implement a single method for all the business logit: `process_logits()`
    	input_idslogitsreturnc                 C   s   dS )aD  
        input_ids and logits are always 2D tensors for handling a batch of sequences.

        - input_ids -> List[List[tokens]]
        - logits -> 2D_Tensor[logit floats]

        Important to keep in mind when designing universal logits processors
        - logits processors are only used once and never re-applied for a new sequence generator
        - Some models only pass output_ids, some models such as llamacpp and transformers prefix with input_ids
        - Some sampling methods, such as beam search, result in unstable sequence ordering in models like vLLM
        Nr   )selfr   r   r   r   r   process_logits/   s   z&OutlinesLogitsProcessor.process_logitsc                 C   s   |  |}|  |}|jdd |jdd ksJ t|jdkr(| ||}nt|jdkr>| |d|dd}| |t|S )a  
        Apply logits processor

        1) Unify type
        - convert input_ids: either ndarray, mlx array, List[int], or Tensor -> List[List[int]]
        - convert logits: either ndarray, mlx array, or Tensor -> 2D float Tensor
        2) Unify shape, ensure logits and input_ids are 2D
        3) Call self.process_logits() to perform business logic
        4) Cast logits back to original array library type
        N      r   )	_to_torchshapelenr   	unsqueezesqueeze_from_torchtype)r   r   r   torch_logitsprocessed_logitsr   r   r   __call__@   s   

 z OutlinesLogitsProcessor.__call__tensor_likec                 C   s   t | tjr| S t | tjrt| S t | ttfrt| S t	t
| r9ddlm} ttj| |jddS tt
| rNddl}t|j| }|S tdt
|  d)z&Convert various types to torch.Tensor.r   NF)copyzyLogitsProcessor must be called with either np.NDArray, torch.Tensor, list, or mlx.core.array typed logits. Logits type: ``)r   torchTensornpndarray
from_numpylisttupletensorr   r(   r
   r   from_dlpackr   astypefloat32r   jaxdlpack	to_dlpack	TypeError)r,   r   r:   torch_tensorr   r   r   r"   a   s(   

z!OutlinesLogitsProcessor._to_torchr6   target_typec                 C   s   |t jkr| S |tjkr|   S |tkr|   S |tkr(t|   S t	|r;ddl
m} ||   S t|rIddl}|j| S td| d)z2Convert torch.Tensor to the specified target type.r   Nz0Failed to convert torch tensors to target_type `r.   )r/   r0   r1   r2   detachnumpyr4   tolistr5   r   r
   r   r   floatr   r:   r;   r7   r=   )r6   r?   r   r:   r   r   r   r'      s"   


z#OutlinesLogitsProcessor._from_torchN)__name__
__module____qualname____doc__r   r   intr/   r0   r   no_gradArrayr+   staticmethodr"   r   r'   r   r   r   r   r   !   s,    
  r   )abcr   typingr   r   r   r   r   rA   r1   r/   numpy.typingr   r
   r   r   r0   rJ   r   r   r   r   r   r   r   <module>   s    
