ó
    >:jÝ†  ã                  ó  • S SK Jr  S SKrS SKrS SKJr   S SKJr  S SK
JrJr  S SKJr  S SKJrJr  S SKJrJrJrJr  S S	KJr  S S
KJr  S SKJrJr  \R<                  " \5      r  " S S\5      r!\!r"g! \ a	    S SK	Jr   Ndf = f)é    )ÚannotationsN)ÚPath)ÚSelf)ÚTensorÚnn)Úlogging)Úformat_modalityÚinfer_batch_modality)ÚMODALITY_TO_PROCESSOR_ARGÚModalityÚ	PairInputÚSingleInput)ÚInputModule)ÚModule)Úimport_from_stringÚload_dir_pathc                  óÎ  ^ • \ rS rSr% SS1r/ SQrS\S'   Sr   S         SU 4S jjjr\	SS	 j5       r
S
 r S     SS jjrSSS jjr\  S         SS jj5       r  S       S S jjrS!S jrS!S jrS"S jrS#S$S jjr   S%       S&S jjr\     S'             S(S jj5       r\	S 5       r\	S"S j5       r\R2                  S)S j5       rSrU =r$ )*ÚRouteré   ÚtaskÚmodality)Údefault_routeÚallow_empty_keyÚroute_mappingsz	list[str]Úconfig_keyszrouter_config.jsonc                óZ  >• [         TU ]  5         Ub  [        U5      S:X  a  [        S5      eUb-  X!;  a(  [        SU S[	        UR                  5       5       35      e[        R                  " UR                  5        VVs0 s H  u  pVU[        R                  " U6 _M     snn5      U l
        U(       aI  UR                  5        H5  u  u  pxn	X‘;  d  M  [        SU	 S[	        UR                  5       5       35      e   U(       a%  Uc"  [        [        UR                  5       5      5      nX l        X0l        U(       a\  UR                  5        VVV
s0 s H6  u  u  pxn
U[        U[         5      (       a  [!        [#        U5      5      OU4U
_M8     sn
nnU l        g0 U l        gs  snnf s  sn
nnf )a&.  
This model allows creating flexible SentenceTransformer models that dynamically route inputs to different
processing modules based on:

1. Task type (e.g., "query" or "document") for asymmetric retrieval models
2. Modality (e.g., "text", "image", or ("text", "image")) for crossmodal or multimodal models
3. Combination of both for complex routing scenarios

Tips:

- The ``task`` argument in ``model.encode()`` specifies which route to use
- ``model.encode_query()`` and ``model.encode_document()`` are convenient shorthands for ``task="query"`` and ``task="document"``
- Modality is automatically inferred from input data (text strings, PIL Images, etc.)
- You can override automatic inference by passing ``modality`` in ``model.encode()`` (and its variants) explicitly

Route Priority:

1. Exact match: ``(task, modality)`` - e.g., ``("query", "text")``
2. Task with any modality: ``(task, None)`` - e.g., ``("query", None)``
3. Any task with modality: ``(None, modality)`` - e.g., ``(None, "image")``
4. Catch-all: ``(None, None)``
5. Direct lookup by task name in ``sub_modules``
6. Direct lookup by modality name in ``sub_modules``
7. Fall back to ``default_route`` if set

In the below examples, the ``Router`` model is used to create asymmetric models with different encoders for
queries and documents. In these examples, the "query" route is efficient (e.g., using SparseStaticEmbedding),
while the "document" route uses a more complex model (e.g. a Transformers module). This allows for efficient
query encoding while still using a powerful document encoder, but the combinations are not limited to this.

Example:
    ::

        from sentence_transformers import SentenceTransformer
        from sentence_transformers.sentence_transformer.modules import Router, Normalize

        # Use a regular SentenceTransformer for the document embeddings, and a static embedding model for the query embeddings
        document_embedder = SentenceTransformer("mixedbread-ai/mxbai-embed-large-v1")
        query_embedder = SentenceTransformer("sentence-transformers/static-retrieval-mrl-en-v1")
        router = Router.for_query_document(
            query_modules=list(query_embedder.children()),
            document_modules=list(document_embedder.children()),
        )
        normalize = Normalize()

        # Create an asymmetric model with different encoders for queries and documents
        model = SentenceTransformer(
            modules=[router, normalize],
        )

        # ... requires more training to align the vector spaces

        # Use the query & document routes
        query_embedding = model.encode_query("What is the capital of France?")
        document_embedding = model.encode_document("Paris is the capital of France.")

    ::

        from sentence_transformers.sparse_encoder.modules import Router, SparseStaticEmbedding, SpladePooling, Transformer
        from sentence_transformers.sparse_encoder import SparseEncoder

        # Load an asymmetric model with different encoders for queries and documents
        doc_encoder = Transformer("opensearch-project/opensearch-neural-sparse-encoding-doc-v3-distill", transformer_task="fill-mask")
        router = Router.for_query_document(
            query_modules=[
                SparseStaticEmbedding.from_json(
                    "opensearch-project/opensearch-neural-sparse-encoding-doc-v3-distill",
                    tokenizer=doc_encoder.tokenizer,
                    frozen=True,
                ),
            ],
            document_modules=[
                doc_encoder,
                SpladePooling(pooling_strategy="max", activation_function="log1p_relu"),
            ],
        )

        model = SparseEncoder(modules=[router], similarity_fn_name="dot")

        query = "What's the weather in ny now?"
        document = "Currently New York is rainy."

        query_embed = model.encode_query(query)
        document_embed = model.encode_document(document)

        sim = model.similarity(query_embed, document_embed)
        print(f"Similarity: {sim}")

        # Visualize top tokens for each text
        top_k = 10
        print(f"Top tokens {top_k} for each text:")

        decoded_query = model.decode(query_embed, top_k=top_k)
        decoded_document = model.decode(document_embed)

        for i in range(min(top_k, len(decoded_query))):
            query_token, query_score = decoded_query[i]
            doc_score = next((score for token, score in decoded_document if token == query_token), 0)
            if doc_score != 0:
                print(f"Token: {query_token}, Query score: {query_score:.4f}, Document score: {doc_score:.4f}")

        '''
        Similarity: tensor([[11.1105]], device='cuda:0')
        Top tokens 10 for each text:
        Token: ny, Query score: 5.7729, Document score: 0.8049
        Token: weather, Query score: 4.5684, Document score: 0.9710
        Token: now, Query score: 3.5895, Document score: 0.4720
        Token: ?, Query score: 3.3313, Document score: 0.0286
        Token: what, Query score: 2.7699, Document score: 0.0787
        Token: in, Query score: 0.4989, Document score: 0.0417
        '''

    Multimodal Example:

    ::

        from PIL import Image
        from sentence_transformers import SentenceTransformer
        from sentence_transformers.sentence_transformer.modules import Dense, Pooling, Router, Transformer

        # Create separate encoders for different modalities
        text_encoder = Transformer("sentence-transformers/all-MiniLM-L6-v2")
        # Project to 768 dims to match image encoder
        text_dense = Dense(text_encoder.get_embedding_dimension(), 768, module_input_name="token_embeddings")
        image_encoder = Transformer(
            "ModernVBERT/modernvbert",
            model_kwargs={"trust_remote_code": True},
            processor_kwargs={"trust_remote_code": True},
            config_kwargs={"trust_remote_code": True},
        )
        pooling = Pooling(text_encoder.get_embedding_dimension())

        # Route based on modality
        router = Router(
            sub_modules={
                "text": [text_encoder, text_dense],
                "image": [image_encoder],
            },
            route_mappings={
                (None, "text"): "text",  # Any task with text goes to text encoder
                (None, ("text", "image")): "image",  # Any task with text-image together goes to image encoder
            },
        )

        model = SentenceTransformer(modules=[router, pooling])

        # Modality is automatically inferred
        text_embedding = model.encode("A photo of a cat")
        multimodal_embedding = model.encode({"text": "A photo of a <image>", "image": Image.open("cat.jpg")})

        # Compute the similarity; it'll be poor as the model hasn't yet been trained
        similarity = model.similarity(text_embedding, multimodal_embedding)

    Hybrid Asymmetric + Multimodal Example:

    ::

        from sentence_transformers import SentenceTransformer
        from sentence_transformers.sentence_transformer.modules import Router

        # Different encoders for query text, document text, and images
        router = Router(
            sub_modules={
                "query_text": [query_text_modules],
                "doc_text": [document_text_modules],
                "image": [image_modules],
            },
            route_mappings={
                ("query", "text"): "query_text",        # Query text uses efficient encoder
                ("document", "text"): "doc_text",       # Document text uses powerful encoder
                (None, ("text", "image")): "image",     # Any text-image together goes to image encoder
            },
        )

        model = SentenceTransformer(modules=[router])

        # Explicit task + automatic modality inference
        query_embedding = model.encode_query("Find images of cats")
        doc_embedding = model.encode_document("Article about cats")
        multimodal_embedding = model.encode({"text": "A photo of a cat", "image": Image.open("cat.jpg")})

.. note::

    When training models with the :class:`~sentence_transformers.base.modules.Router` module, you must use the
    ``router_mapping`` argument in the :class:`~sentence_transformers.sentence_transformer.training_args.SentenceTransformerTrainingArguments`
    or :class:`~sentence_transformers.sparse_encoder.training_args.SparseEncoderTrainingArguments` to map the
    training dataset columns to the correct route ("query" or "document"). For example, if your training dataset(s)
    have ``["question", "positive", "negative"]`` columns, then you can use the following mapping::

        args = SparseEncoderTrainingArguments(
            ...,
            router_mapping={
                "question": "query",
                "positive": "document",
                "negative": "document",
            }
        )

    Additionally, it is common to use a different learning rate for the different routes. For this, you should
    use the ``learning_rate_mapping`` argument in the :class:`~sentence_transformers.sentence_transformer.training_args.SentenceTransformerTrainingArguments`
    or :class:`~sentence_transformers.sparse_encoder.training_args.SparseEncoderTrainingArguments` to map parameter patterns
    to their learning rates. For example, if you want to use a learning rate of ``1e-3`` for an SparseStaticEmbedding module and
    ``2e-5`` for the rest of the model, you can do this::

        args = SparseEncoderTrainingArguments(
            ...,
            learning_rate=2e-5,
            learning_rate_mapping={
                r"SparseStaticEmbedding\.*": 1e-3,
            }
        )

Args:
    sub_modules: Mapping of route keys to lists of modules. Each key corresponds to a specific route name
        (e.g., "text_query", "text_document", "image", "multimodal"). Each route contains a list of modules
        that will be applied sequentially when that route is selected.
    default_route: The default route to use if no task type or modality is specified. If None, an exception
        will be thrown if no task type is specified. If ``allow_empty_key`` is True, the first key in
        sub_modules will be used as the default route. Defaults to None.
    allow_empty_key: If True, allows the default route to be set to the first key in `sub_modules` if
        ``default_route`` is None. Defaults to True.
    route_mappings: Optional dictionary mapping (task, modality) tuples to route keys in sub_modules.
        This enables sophisticated routing logic based on combinations of task and modality:

        - Use ``None`` as a wildcard for either task or modality to create catch-all rules
        - Modality can be a string (e.g., ``"text"``, ``"image"``) or tuple (e.g., ``("text", "image")``)
        - Routes are resolved with a priority order (see **Route Resolution Priority** above)
        - All mapped routes must exist in ``sub_modules`` (validated at initialization)

        Example mappings::

            {
                # Exact matches (highest priority)
                ("query", "text"): "efficient_text_encoder",
                ("document", "text"): "powerful_text_encoder",

                # Task with any modality
                ("query", None): "query_encoder",  # All query tasks

                # Any task with specific modality
                (None, "image"): "image_encoder",  # All image inputs
                (None, ("text", "image")): "multimodal_encoder",  # Multimodal inputs

                # Catch-all (lowest priority)
                (None, None): "default_encoder",
            }

        If not provided, the router will attempt direct lookup using the task or modality as the route key
        in ``sub_modules``, then fall back to ``default_route``.
Nr   z+The sub_modules dictionary cannot be empty.zDefault route 'z' not found in route keys: z$route_mappings contains mapping to 'z1' which is not in sub_modules. Available routes: )ÚsuperÚ__init__ÚlenÚ
ValueErrorÚlistÚkeysr   Ú
ModuleDictÚitemsÚ
SequentialÚsub_modulesÚnextÚiterr   r   Ú
isinstanceÚtupleÚsortedr   )Úselfr&   r   r   r   Ú
route_nameÚmodulesr   r   Útarget_routeÚrouteÚ	__class__s              €Úf/home/mande/repo/quber/.venv/lib/python3.13/site-packages/sentence_transformers/base/modules/router.pyr   ÚRouter.__init__   s£  ø€ ôB 	‰ÑÔØÑ¤# kÓ"2°aÓ"7ÜÐJÓKÐKØÑ$¨Ó)IÜ˜¨}¨oÐ=XÔY]Ð^i×^nÑ^nÓ^pÓYqÐXrÐsÓtÐtäŸ=š=ØLW×L]ÑL]ÔL_Ô`ÒL_Ñ5H°ZˆZœŸš¨Ð0Ò0ÑL_Ò`ó
ˆÔö
 Ø2@×2FÑ2FÖ2HÑ.Ñ � ,ØÕ2Ü$Ø>¸|¸nð M-Ü-1°+×2BÑ2BÓ2DÓ-EÐ,FðHóð ñ 3Iö ˜}Ñ4Ü ¤ k×&6Ñ&6Ó&8Ó!9Ó:ˆMØ*ÔØ.Ôö ð 0>×/CÑ/CÔ/Eõâ/EÑ+Ñ$�T eð ´*¸XÄu×2MÑ2M”uœV HÓ-Ô.ÐS[Ð\Ð^cÒcÙ/Eóð 	Õð ð 	Õùó' aùô(s   Â  F 
Å=F&c                ó²   • [        U R                  R                  5        VVs1 s H  n[        US   SS/5        H  nUiM     M      snn[        S9$ s  snnf )zBThe union of modalities supported by all sub-module input modules.r   Ú
modalitiesÚtext)Úkey)r+   r&   ÚvaluesÚgetattrÚstr)r,   r0   r   s      r2   r5   ÚRouter.modalitiesA  sc   € ô ð "×-Ñ-×4Ñ4Ô6ôâ6�EÜ '¨¨a©°,ÀÀ× I�Hó á Iñ Ù6òô
 ñ
ð 	
ùós   £%A
c           	     óà  • U R                   R                  5        Vs/ s H	  nSU< 3PM     nnU R                  R                  5        He  u  p4Uc  UR                  SU< 35        M  Uc   UR                  S[	        U5      < 35        MB  UR                  SU< S[	        U5      < S35        Mg     U(       d  g[        U5      S:X  a  US   $ S	R                  US S
 5      S-   US
   -   $ s  snf )Nztask=z	modality=z(task=ú, modality=Ú)Ú é   r   ú, éÿÿÿÿz and )r&   r"   r   Úappendr	   r   Újoin)r,   ÚnameÚroutesr   r   s        r2   Ú_get_routes_stringÚRouter._get_routes_stringM  sé   € à/3×/?Ñ/?×/DÑ/DÔ/FÓGÒ/F t�E˜$™Ó"Ñ/FˆÐGØ"×1Ñ1×6Ñ6Ö8‰NˆDØÑØ—‘  d¡XÐ.Ö/Ø‘Ø—‘ 	¬/¸(Ó*CÑ)FÐGÖHà—‘  t¡h¨k¼/È(Ó:SÑ9VÐVWÐXÖYñ 9ö ØÜ�‹[˜AÓØ˜!‘9ÐØ�y‰y˜  ˜Ó%¨Ñ/°&¸±*Ñ<Ð<ùò Hs   �C+c                ó  • [        U[        5      (       a  [        [        U5      5      nX4U R                  ;   a  U R                  X4   $ US4U R                  ;   a  U R                  US4   $ SU4U R                  ;   a  U R                  SU4   $ SU R                  ;   a  U R                  S   $ U(       a  XR                  ;   a  U$ U(       a  X R                  ;   a  U$ Ub  [        SU SU R                  5        35      eg)z÷
Resolve the route key based on task and modality.

Args:
    task: The task type (e.g., "query", "document")
    modality: The modality (e.g., "text", "image", ("text", "image"))

Returns:
    The resolved route key, or None if no route is found
N©NNzNo route found for task type 'z'. Available routes: )r)   r*   r+   r   r&   r    rG   )r,   r   r   s      r2   Ú_resolve_route_nameÚRouter._resolve_route_name]  s  € ô �h¤×&Ñ&ÜœV HÓ-Ó.ˆHð Ð˜t×2Ñ2Ó2Ø×&Ñ&¨Ð'7Ñ8Ð8ð �$ˆ<˜4×.Ñ.Ó.Ø×&Ñ&¨¨d |Ñ4Ð4ð �(Ð˜t×2Ñ2Ó2Ø×&Ñ&¨¨hÐ'7Ñ8Ð8ð ˜4×.Ñ.Ó.Ø×&Ñ& |Ñ4Ð4ö �D×,Ñ,Ó,ØˆKö ˜×$4Ñ$4Ó4ØˆOàÑÜÐ=¸d¸VÐCXÐY]×YpÑYpÓYrÐXsÐtÓuÐuð ó    c           	     ó†  • U R                  XS9nUc  U R                  nUc^  U R                  (       a  [        S5      eUb  [	        U5      OS nSU< SU< S3nUSU R                  5        S3-  nUS-  n[        U5      eX0R                  ;  a2  [        SU S	[        U R                  R                  5       5       35      eU$ )
N©r   r   zvYou must provide a `router_mapping` argument on the training arguments, or set a default route in the `Router` module.z#Could not determine route for task=r=   z. zAvailable routes: zgConsider specifying the `task` parameter in `model.encode`, or setting a default route in the `Router`.zResolved route 'z6' not found in sub_modules. Available submodule keys: )	rK   r   Útrainingr    r	   rG   r&   r!   r"   )r,   r   r   r0   Úmodality_displayÚ	error_msgs         r2   Ú_resolve_routeÚRouter._resolve_routeŒ  s÷   € Ø×(Ñ(¨dÐ(ÐFˆð ‰=Ø×&Ñ&ˆEð ‰=Ø�}�}Ü ðEóð ð
 =EÑ<Pœ¨xÔ8ÐVZÐØ=¸d¹XÀ[ÐQaÑPdÐdfÐgˆIØÐ-¨d×.EÑ.EÓ.GÐ-HÈÐKÑKˆIØð  Cñ  CˆIÜ˜YÓ'Ð'à×(Ñ(Ó(ÜØ" 5 'Ð)_Ô`dÐei×euÑeu×ezÑezÓe|Ó`}Ð_~Ðóð ð ˆrM   c                ó   • U " XS.UUS9$ )aO  
Creates a Router model specifically for query and document modules, allowing convenient usage via `model.encode_query`
and `model.encode_document`.

Args:
    query_modules: List of modules to be applied for the "query" task type.
    document_modules: List of modules to be applied for the "document" task type.
    default_route: The default route to use if no task type is specified. If None, an exception will be thrown
        if no task type is specified. If ``allow_empty_key`` is True, the first key in sub_modules will be used as
        the default route. Defaults to "document".
    allow_empty_key: If True, allows the default route to be set to the first key in `sub_modules` if
        ``default_route`` is None. Defaults to True.

Returns:
    Router: An instance of the Router model with the specified query and document modules.
)ÚqueryÚdocument)r&   r   r   © )ÚclsÚquery_modulesÚdocument_modulesr   r   s        r2   Úfor_query_documentÚRouter.for_query_document¨  s   € ñ0 Ø"/ÑNØ'Ø+ñ
ð 	
rM   c           	     ób  • Uc  UR                  SS5      nUc  UR                  SS5      nU R                  X#S9nX$S'   X4S'   U R                  U    HT  nUR                  5        VVs0 s H+  u  px[	        US5      (       d  M  XvR
                  ;   d  M)  Xx_M-     n	nnU" U40 U	D6nMV     U$ s  snnf )a1  Route ``features`` through the resolved sub-module pipeline.

Resolves the route from ``task`` and ``modality`` (falling back to values stored in
``features`` if not provided), then sequentially applies all modules in the matched route.

Args:
    features: Input features dictionary (e.g. from :meth:`preprocess`).
    task: Task type used for routing (e.g. ``"query"``, ``"document"``).
        Falls back to ``features["task"]`` if not provided.
    modality: Modality used for routing (e.g. ``"text"``, ``"image"``).
        Falls back to ``features["modality"]`` if not provided.
    **kwargs: Extra keyword arguments forwarded to each sub-module's ``forward``
        (filtered by each module's ``forward_kwargs``).

Returns:
    The features dictionary after passing through all modules in the resolved route.
Nr   r   rO   Úforward_kwargs)ÚgetrS   r&   r$   Úhasattrr_   )
r,   Úfeaturesr   r   Úkwargsr0   Úmoduler7   ÚvalueÚmodule_kwargss
             r2   ÚforwardÚRouter.forwardÆ  sÓ   € ð2 ‰<Ø—<‘< ¨Ó-ˆDð ÑØ—|‘| J°Ó5ˆHð ×#Ñ#¨Ð#ÐAˆð ˆv‰Ø%ˆzÑà×&Ñ& uÔ-ˆFð #)§,¡,¤.ôâ"0‘J�CÜ˜6Ð#3×4ó à9<×@UÑ@UÑ9Uó �’
Ù"0ð ñ ñ
 ˜hÑ8¨-Ñ8ŠHñ .ð ˆùós   Á'B+ÂB+ÂB+c                ó@   • [         R                  R                  U 5      $ ©N)r   r   Ú__repr__)r,   s    r2   rk   ÚRouter.__repr__ö  s   € ô �y‰y×!Ñ! $Ó'Ð'rM   c                óÞ   • / nU R                   b  UR                  SU R                   < 35        U R                  (       a  UR                  SU R                   35        SR                  U5      $ )Nzdefault_route=zroute_mappings=rA   )r   rC   r   rD   )r,   Úpartss     r2   Ú
extra_reprÚRouter.extra_reprû  s_   € ØˆØ×ÑÑ)Ø�L‰L˜>¨$×*<Ñ*<Ñ)?Ð@ÔAØ××Ø�L‰L˜?¨4×+>Ñ+>Ð*?Ð@ÔAØ�y‰y˜ÓÐrM   c           	     ót  • / nU R                   R                  5        HR  n[        U5       H@  nS H4  n[        X45      (       d  M  UR	                  [        X45      " 5       5          O   M?    MP     MT     U(       d  g [        [        U5      5      S:”  a"  [        R                  S[        U5       S35        US   $ )N)Úget_embedding_dimensionÚ get_sentence_embedding_dimensionÚget_word_embedding_dimensionr@   z7Different embedding dimensions detected across routes: z. Using the first value.r   )
r&   r8   Úreversedra   rC   r9   r   ÚsetÚloggerÚwarning_once)r,   Údimsr&   rd   rE   s        r2   rr   ÚRouter.get_embedding_dimension  s©   € ØˆØ×+Ñ+×2Ñ2Ö4ˆKÜ" ;Ö/�ó�Dô
 ˜v×,Ó,ØŸ™¤G¨FÔ$9Ó$;Ô<Ùññ Úó 0ñ 5ö ØÜŒs�4‹y‹>˜AÓÜ×ÑØIÌ#ÈdË)ÈÐTlÐmôð �A‰wˆrM   c           	     óî  • 0 n0 n0 nU R                   R                  5        H€  u  px/ Xg'   [        U5       Hh  u  pšU SU	 S[        U
5      R                   3nX¤U'   [        U
5      R
                   S[        U
5      R                   3X['   Xg   R                  U5        Mj     M‚     UR                  5        HY  u  pº[        R                  R                  U[        U5      5      n[        R                  " USS9   U
R                  " U4SU0UD6  M[     U R                  5       nSU;   a?  US   (       a5  US   R                  5        VVs0 s H  u  pï[        U5      U_M     snnUS'   [        [        R                  R                  XR                   5      SSS	9 n["        R$                  " UUUS
.USS9  S S S 5        g ! [         a    U
R                  U5         GM'  f = fs  snnf ! , (       d  f       g = f)NÚ_Ú.T)Úexist_okÚsafe_serializationr   ÚwÚutf8)Úencoding)ÚtypesÚ	structureÚ
parametersé   )Úindent)r&   r$   Ú	enumerateÚtypeÚ__name__Ú
__module__rC   ÚosÚpathrD   r:   ÚmakedirsÚsaveÚ	TypeErrorÚget_config_dictÚopenÚconfig_file_nameÚjsonÚdump)r,   Úoutput_pathr   rc   Úmodel_lookupÚmodel_typesÚmodel_structurerE   ÚmodelsÚ
module_idxÚmodelÚmodel_idÚ
model_pathÚconfig_dictr7   re   ÚfOuts                    r2   r�   ÚRouter.save  sÒ  € ØˆØˆØˆà ×,Ñ,×2Ñ2Ö4‰LˆDØ$&ˆOÑ!Ü%.¨vÖ%6Ñ!�
Ø"˜V 1 Z L°´$°u³+×2FÑ2FÐ1GÐH�Ø).˜XÑ&Ü+/°«;×+AÑ+AÐ*BÀ!ÄDÈÃK×DXÑDXÐCYÐ(Z�Ñ%ØÑ%×,Ñ,¨XÖ6ó	 &7ñ 5ð  ,×1Ñ1Ö3‰OˆHÜŸ™Ÿ™ k´3°x³=ÓAˆJÜ�KŠK˜
¨TÒ2ð'Ø—
’
˜:ÑWÐ:LÐWÐPVÔWñ	  4ð ×*Ñ*Ó,ˆØ˜{Ó*¨{Ð;K×/LàOZÐ[kÑOl×OrÑOrÔOtÔ,uÒOtÁÀ¬S°«X°uª_ÑOtÒ,uˆKÐ(Ñ)ä”"—'‘'—,‘,˜{×,AÑ,AÓBÀCÐRXÒYÐ]aÜ�IŠIà(Ø!0Ø"-ñð
 Øò÷ ZÐYøô ó 'à—
‘
˜:×&Ð&ð'üó -vçYÕYús$   Ã9F=ÅG ÆG&Æ=GÇGÇ&
G4c                ó*  • U(       a‘  [        US   [        5      (       ay  Ucv  [        S U 5       5      nU[        [        R                  " 5       5      -  (       d>  [        U5      S:”  a  [        S5      eUR                  5       nU Vs/ s H  owU   PM	     nnUc  U(       a   [        XR                  S9nU R                  X4S9nU R                  U   S   n	U	R                  " U4SU0UD6n
X:S'   Ub  XJS	'   U
$ s  snf ! [        [        4 a     NZf = f)
a  Resolve the route from ``task`` and ``modality``, then delegate preprocessing to the
first module of the matched route. The returned dictionary includes ``"task"`` and (if
available) ``"modality"`` keys so that :meth:`forward` can route without re-inference.
r   c              3  óR   #   • U  H  oR                  5         H  o"v •  M     M     g 7frj   )r"   )Ú.0r6   r7   s      r2   Ú	<genexpr>Ú$Router.preprocess.<locals>.<genexpr>Q  s   é € ÐJªF D¿i¹i¿k°sœC¹k™CªFùs   ‚%'r@   zÀYou cannot pass a list of dictionaries with different task types. Please ensure all dictionaries have the same task type key, or pass non-dictionary inputs while providing the `task` argument.)Úsupported_modalitiesrO   Úpromptr   r   )r)   Údictrv   r   r"   r   r    Úpopr
   r5   r�   rS   r&   Ú
preprocess)r,   Úinputsr¨   r   r   rc   Ú	dict_keysÚsampler0   Úinput_moduleÚ	tokenizeds              r2   r«   ÚRouter.preprocessB  s  € ö ”j ¨¡¬D×1Ñ1°d±läÑJ©FÓJÓJˆIà¤Ô$=×$BÒ$BÓ$DÓ E×EÜ�y“> AÓ%Ü$ð?óð ð !—}‘}“�Ù5;Ó<²V¨6 œ,±V�Ð<ð Ñ¦ðÜ/°Ï_É_Ñ]�ð ×#Ñ#¨Ð#ÐAˆà×'Ñ'¨Ñ.¨qÑ1ˆØ ×+Ò+¨FÑL¸6ÐLÀVÑLˆ	Ø �&ÑØÑØ$,�jÑ!ØÐùò% =øô ¤	Ð*ó áðús   Â	C:Â$C? Ã?DÄDc           
     óv  • UUUUS.nU R                   " SXS.UD6n	U	(       d  U R                   " SUSUS.UD6n	0 n
U	S   R                  5        HC  u  p¼[        U5      n UR                  " U4S[	        X+5      R                  5       0UDUD6nXêU'   ME     0 nU	S   R                  5        H*  u  nn/ UU'   U H  nUU   R                  X«   5        M     M,     U	S   R                  5       nS	U;   aI  US	   (       a?  0 nUS	   R                  5        H!  u  nn S
S K
nUR                  U5      nUUU'   M#     UUS	'   U " U40 UD6nU$ ! [         a9    [        SU[	        X+5      R                  5       S.UD6nUR                  U5      n Núf = f! [        [        4 a    [        R                  SU S35         M§  f = f)N)ÚtokenÚcache_folderÚrevisionÚlocal_files_only)Úmodel_name_or_pathÚ	subfolderzconfig.json)r·   Úconfig_filenamer¸   rƒ   r¸   r„   r…   r   r   z#Could not parse route_mapping key: z. Skipping.rX   )Úload_configr$   r   Úloadr   Úas_posixr�   r   rC   ÚcopyÚastÚliteral_evalr    ÚSyntaxErrorrw   Úwarning)rY   r·   r¸   r³   r´   rµ   r¶   rc   Ú
hub_kwargsÚconfigr.   r�   Ú
model_typeÚmodule_classrd   Ú
local_pathr™   Úkey_nameÚmodels_listr…   r   Úkey_strre   r¾   Ú	key_tuplerœ   s                             r2   r»   ÚRouter.loadp  s   € ð Ø(Ø Ø 0ñ	
ˆ
ð —’ÐjÐ4FÑjÐ_iÑjˆÞØ—_’_ð Ø#5À}Ð`iñØmwñˆFð ˆØ$*¨7¡O×$9Ñ$9Ö$;Ñ ˆHÜ#5°jÓ#AˆLð7Ø%×*Ò*Ø&ñÜ26°yÓ2K×2TÑ2TÓ2VðØZdðØhnñ�ð !'�HÓñ %<ð ˆØ%+¨KÑ%8×%>Ñ%>Ö%@Ñ!ˆH�kØ(*ˆO˜HÑ%Û'�Ø Ñ)×0Ñ0°Ñ1BÖCó (ñ &Að ˜LÑ)×.Ñ.Ó0ˆ
Ø˜zÓ)¨jÐ9I×.JØˆNØ",Ð-=Ñ">×"DÑ"DÖ"F‘�˜ð_Ûà #× 0Ñ 0°Ó 9�IØ05�N 9Ó-ñ #Gð ,:ˆJÐ'Ñ(á�OÑ2 zÑ2ˆØˆøô= ó 7Ü*ð Ø'9ÄTÈ)ÓE^×EgÑEgÓEiñØmwñ�
ð &×*Ñ*¨:Ó6’ð	7ûô2 #¤KÐ0ó _Ü—N‘NÐ%HÈÈ	ÐQ\Ð#]×^ð_ús%   Á.EÄFÅA FÆFÆ)F8Æ7F8c                ó¬   • U R                   R                  5        H6  nUS   n[        US5      (       d  M  UR                  c  M*  UR                  s  $    g )Nr   Ú	tokenizer)r&   r8   ra   rÍ   )r,   r&   r¯   s      r2   rÍ   ÚRouter.tokenizer®  sO   € ð  ×+Ñ+×2Ñ2Ö4ˆKØ(3°A©ˆLÜ�| [×1Ó1°l×6LÑ6LÓ6XØ#×-Ñ-Ò-ñ 5ð rM   c                ó|  • [        5       nU R                  R                  5        HJ  nUS   nU(       d  M  [        US5      (       d  M$  UR                  =n(       d  M9  UR                  U5        ML     U(       d  g [        U5      S:X  a  UR                  5       $ [        R                  SU S35        [        U5      $ )Nr   Úmax_seq_lengthr@   z$Different max_seq_lengths detected: z. Using the maximum value.)rv   r&   r8   ra   rÐ   Úaddr   rª   rw   rx   Úmax)r,   Úmax_seq_lengthsr.   r¯   rÐ   s        r2   rÐ   ÚRouter.max_seq_length·  s§   € ô ›%ˆØ×'Ñ'×.Ñ.Ö0ˆGØ(/°©
ˆLßˆwœ7 <Ð1A×BÓBØ%1×%@Ñ%@Ð@�>×@Ø#×'Ñ'¨Ö7ñ	 1ö ØÜ�Ó! QÓ&à"×&Ñ&Ó(Ð(ä×ÑÐ"FÀÐFWÐWqÐ rÔsÜ�Ó'Ð'rM   c                ó:  • / nU R                   R                  5        H5  u  p4U(       d  M  [        US   S5      (       d  M$  UR                  U5        M7     [	        U5      S:X  a  [
        R                  S5        g U H  nU R                   U   S   nXl        M     g )Nr   rÐ   z2No modules have a max_seq_length attribute to set.)r&   r$   ra   rC   r   rw   rÁ   rÐ   )r,   re   Úhas_max_seq_length_keysr7   rš   r¯   s         r2   rÐ   rÔ   Ê  sŽ   € ð #%ÐØ×+Ñ+×1Ñ1Ö3‰KˆCßˆvœ' &¨¡)Ð-=×>Ó>Ø'×.Ñ.¨sÖ3ñ 4ô Ð&Ó'¨1Ó,Ü�N‰NÐOÔPØã*ˆCØ(,×(8Ñ(8¸Ñ(=¸aÑ(@ˆLØ*/Ö'ò +rM   )r   r   r   r&   )NTN)
r&   zdict[str, list[Module]]r   ú
str | Noner   Úboolr   zAdict[tuple[str | None, str | tuple[str, ...] | None], str] | NoneÚreturnÚNone)rÙ   zlist[Modality]rJ   )r   r×   r   ústr | tuple[str, ...] | NonerÙ   r×   )rW   T)
rZ   úlist[Module]r[   rÜ   r   r×   r   rØ   rÙ   r   )rb   údict[str, Tensor]r   r×   r   rÛ   rÙ   rÝ   )rÙ   r:   )rÙ   z
int | None)T)r–   r:   r   rØ   )NNN)r¬   zlist[SingleInput | PairInput]r¨   r×   r   r×   r   zModality | None)r?   NNNF)r·   r:   r¸   r:   r³   zbool | str | Noner´   r×   rµ   r×   r¶   rØ   rÙ   r   )rÙ   rÚ   )rŠ   r‹   Ú__qualname__Ú__firstlineno__r_   r   Ú__annotations__r“   r   Úpropertyr5   rG   rK   rS   Úclassmethodr\   rg   rk   ro   rr   r�   r«   r»   rÍ   rÐ   ÚsetterÚ__static_attributes__Ú__classcell__)r1   s   @r2   r   r      s'  ø‡ Ø˜jÐ)€NÚS€K�ÓSØ+Ðð
 %)Ø $Ø\`ðb
à,ðb
ð "ðb
ð ð	b
ð
 Zðb
ð 
÷b
ð b
ðH	 ó	
ó ð	
ò=ð" QUð-Øð-Ø1Mð-à	õ-ö^ð8 ð
 %/Ø $ð
à#ð
ð 'ð
ð "ð	
ð
 ð
ð 
ô
ó ð
ð@  Ø15ð	.à#ð.ð ð.ð /ð	.ð 
õ.ô`(ô
 ôö0%ðT "ØØ$(ð,à-ð,ð ð,ð ð	,ð
 "õ,ð\ ð Ø#'Ø#'Ø#Ø!&ð;àð;ð ð;ð !ð	;ð
 !ð;ð ð;ð ð;ð 
ô;ó ð;ðz ñó ðð ó(ó ð(ð$ ×Ñó0ó ö0rM   r   )#Ú
__future__r   r”   rŒ   Úpathlibr   Útypingr   ÚImportErrorÚtyping_extensionsÚtorchr   r   Útransformers.utilsr   Ú#sentence_transformers.base.modalityr	   r
   Ú)sentence_transformers.base.modality_typesr   r   r   r   Ú/sentence_transformers.base.modules.input_moduler   Ú)sentence_transformers.base.modules.moduler   Úsentence_transformers.utilr   r   Ú
get_loggerrŠ   rw   r   ÚAsymrX   rM   r2   Ú<module>rô      sn   ðÝ "ã Û 	Ý ð'Ý÷ Ý &ç Uß qÓ qÝ GÝ <ß Hà	×	Ò	˜HÓ	%€ô@0ˆ[ô @0ðH �øðg ó 'ß&ð'ús   –A2 Á2BÂ B