+
    UV-j0  ã                   óN   € R t ^ RIt^ RIHt ^ RIHtHt ^ RIHt	  ! R R4      t
R# )a  Vision feature cache for multi-turn conversations.

Caches the output of vision_tower + embed_vision (projected image features
in language model space) keyed by image path or content hash, avoiding
expensive re-computation when the same image is discussed across turns.
N)ÚOrderedDict)ÚAnyÚOptionalc                   ó¦   a € ] tR t^t o RtRV 3R lR lltV 3R lR ltV 3R lR ltV 3R lR	 ltV 3R
 lR lt	V 3R lR lt
V 3R lR ltRtV tR# )ÚVisionFeatureCacheaA  LRU cache for vision features projected into language model space.

Cache keys are derived from image paths (for file/URL images) or content
hashes (for PIL images). Cached values are mx.array features after
vision_tower + embed_vision, ready for masked_scatter.

Cleanup is handled by three mechanisms:
- **LRU eviction**: oldest entry is dropped when max_size is exceeded.
- **Model unload**: server calls clear() when the model is swapped.
- **Process exit**: in-memory cache is freed automatically.

Args:
    max_size: Maximum number of cached image features. Default 20.
c                ó    <€ V ^8„  d   QhRS[ /# )é   Úmax_size©Úint)ÚformatÚ__classdict__s   "€Úe/Volumes/fast/ai/experiments/ui-tars-smoke/.venv/lib/python3.14/site-packages/mlx_vlm/vision_cache.pyÚ__annotate__ÚVisionFeatureCache.__annotate__   s   ø€ ÷ @ñ @¡ñ @ó    c                ó0   € Wn         \        4       V n        R # ©N)r	   r   Ú_cache)Úselfr	   s   &&r   Ú__init__ÚVisionFeatureCache.__init__   s   € Ø ŒÜ2=³-ˆŽr   c                ó&   <€ V ^8„  d   QhRS[ RS[/# ©r   Úimage_sourceÚreturn)r   Ústr)r   r   s   "€r   r   r   #   s   ø€ ÷ -ñ -¡cð -©cñ -r   c                óR  a € \        V\        4      '       d   V# \        V\        4      '       d   RP                  V 3R lV 4       4      # \	        VR4      '       d?   \
        P                  ! VP                  4       4      P                  4       R,          pRV 2# R\        V4       2# )z½Derive a cache key from an image source.

For str/Path: use the string directly (path or URL).
For lists: create a composite key from individual keys.
For PIL images: hash the image bytes.
Ú|c              3   óF   <"  € T F  pSP                  V4      x € K  	  R # 5ir   )Ú	_make_key)Ú.0Úimgr   s   & €r   Ú	<genexpr>Ú/VisionFeatureCache._make_key.<locals>.<genexpr>-   s   øé € ÐH¹<°C˜DŸN™N¨3×/Ð/»<ùs   ƒ!Útobytes:Né   Nzpil:zobj:)
Ú
isinstancer   ÚlistÚjoinÚhasattrÚhashlibÚsha256r%   Ú	hexdigestÚid)r   r   Úhs   f& r   r    ÚVisionFeatureCache._make_key#   s‹   ø€ ô �l¤C×(Ò(ØÐÜ˜¤d×+Ò+Ø—8‘8ÔH¹<ÓHÓHÐHä�| Y×/Ò/Ü—N’N <×#7Ñ#7Ó#9Ó:×DÑDÓFÀsÕK�Ø˜a˜S�zÐ!Øœ"˜\Ó*Ð+Ð,Ð,r   c                óJ   <€ V ^8„  d   QhRS[ RS[S[P                  ,          /# r   )r   r   ÚmxÚarray)r   r   s   "€r   r   r   4   s$   ø€ ÷ ñ ¡ð ©±·±Õ(:ñ r   c                ó¤   € V P                  V4      pW P                  9   d/   V P                  P                  V4       V P                  V,          # R# )z.Look up cached features. Returns None on miss.N)r    r   Úmove_to_end©r   r   Úkeys   && r   ÚgetÚVisionFeatureCache.get4   s>   € à�n‰n˜\Ó*ˆØ—+‘+ÔØ�K‰K×#Ñ# CÔ(Ø—;‘;˜sÕ#Ð#Ùr   c                ó>   <€ V ^8„  d   QhRS[ RS[P                  RR/# )r   r   Úfeaturesr   N)r   r2   r3   )r   r   s   "€r   r   r   <   s&   ø€ ÷ $ñ $¡ð $©r¯x©xð $¸Dñ $r   c                ó  € V P                  V4      pW0P                  9   d   V P                  P                  V4       M@\        V P                  4      V P                  8¼  d   V P                  P                  RR7       W P                  V&   R# )z2Store features in the cache, evicting LRU if full.F)ÚlastN)r    r   r5   Úlenr	   Úpopitem)r   r   r;   r7   s   &&& r   ÚputÚVisionFeatureCache.put<   sb   € à�n‰n˜\Ó*ˆØ—+‘+ÔØ�K‰K×#Ñ# CÕ(ä�4—;‘;Ó 4§=¡=Ô0Ø—‘×#Ñ#¨Ð#Ô/Ø#�‰�CÓr   c                ó   <€ V ^8„  d   QhRR/# )r   r   N© )r   r   s   "€r   r   r   F   s   ø€ ÷ ñ �tñ r   c                ó:   € V P                   P                  4        R# )zClear all cached features.N)r   Úclear©r   s   &r   rE   ÚVisionFeatureCache.clearF   s   € à�‰×ÑÖr   c                ó    <€ V ^8„  d   QhRS[ /# )r   r   r
   )r   r   s   "€r   r   r   J   s   ø€ ÷  ñ  ™ñ  r   c                ó,   € \        V P                  4      # r   )r>   r   rF   s   &r   Ú__len__ÚVisionFeatureCache.__len__J   s   € Ü�4—;‘;ÓÐr   c                ó&   <€ V ^8„  d   QhRS[ RS[/# r   )r   Úbool)r   r   s   "€r   r   r   M   s   ø€ ÷ "ñ "©ð "±ñ "r   c                ó@   € V P                  V4      pW P                  9   # r   )r    r   r6   s   && r   Ú__contains__ÚVisionFeatureCache.__contains__M   s   € Ø�n‰n˜\Ó*ˆØ—k‘kÑ!Ð!r   )r   r	   N)é   )Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r   r    r8   r@   rE   rJ   rO   Ú__static_attributes__Ú__classdictcell__)r   s   @r   r   r      sR   ø‡ € ñ÷@ò @÷-ð -÷"ð ÷$ð $÷ð ÷ ð  ÷"ö "r   r   )rV   r+   Úcollectionsr   Útypingr   r   Úmlx.coreÚcorer2   r   rC   r   r   Ú<module>r]      s$   ðñó Ý #ß  å ÷@"ó @"r   