
    {ho                     >    d dl mZmZmZmZ d dlmZ  G d de      Zy)    )	BaseModelFieldmodel_validatorValidationInfo)	Generatorc                       e Zd ZU dZ ed      Zee   ed<    e	d      de
dd fd	       Z	 dd
edededeeeef   ddf   fdZdedeeeef   ddf   fdZy)CitationMixina  
    Helpful mixing that can use `validation_context={"context": context}` in `from_response` to find the span of the substring_phrase in the context.

    ## Usage

    ```python
    from pydantic import BaseModel, Field
    from instructor import CitationMixin

    class User(BaseModel):
        name: str = Field(description="The name of the person")
        age: int = Field(description="The age of the person")
        role: str = Field(description="The role of the person")


    context = "Betty was a student. Jason was a student. Jason is 20 years old"

    user = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=[
            {
                "role": "user",
                "content": "Extract jason from {context}",
            },
        response_model=User,
        validation_context={"context": context},
        ]
    )

    for quote in user.substring_quotes:
        assert quote in context

    print(user.model_dump())
    ```

    ## Result
    ```
    {
        "name": "Jason Liu",
        "age": 20,
        "role": "student",
        "substring_quotes": [
            "Jason was a student",
            "Jason is 20 years old",
        ]
    }
    ```

    zYList of unique and specific substrings of the quote that was used to answer the question.)descriptionsubstring_quotesafter)modeinforeturnc                     |j                   | S |j                   j                  dd      }t        | j                  |            }|D cg c]  }||d   |d     c}| _        | S c c}w )z
        For each substring_phrase, find the span of the substring_phrase in the context.
        If the span is not found, remove the substring_phrase from the list.
        Ncontextr      )r   getlist	get_spansr   )selfr   text_chunksspansspans        X/var/www/html/hubwallet-dev/venv/lib/python3.12/site-packages/instructor/dsl/citation.pyvalidate_sourceszCitationMixin.validate_sources<   sm     <<K ll&&y$7 T^^K01LQ RDT!WtAw!? R !Ss   	A%quoter   errsNc              #      K   dd l }|}|}d}|j                  d| d| d|      }|+||k  r&|dz  }|j                  d| d| d|      }|||k  r&||j                         E d {    y y 7 w)Nr   (z){e<=}r   )regexsearchr   )	r   r   r   r   r!   minormajorerrs_ss	            r   	_get_spanzCitationMixin._get_spanN   s      	LL1UG6%3U;iETMQJEqveWB7?A iETM =wwy    s   AA1A1(A/)A1c              #   f   K   | j                   D ]  }| j                  ||      E d {     y 7 w)N)r   r'   )r   r   r   s      r   r   zCitationMixin.get_spans_   s2     ** 	6E~~eW555	65s   %1/1)   )__name__
__module____qualname____doc__r   r   r   str__annotations__r   r   r   intr   tupler'   r        r   r	   r	      s    0d #(o#d3i  '"^   #$ 56!!#&!.1!	5c?D$.	/!"6 65c?D$3N)O 6r3   r	   N)pydanticr   r   r   r   collections.abcr   r	   r2   r3   r   <module>r6      s    F F %\6I \6r3   