o
    i{?                     @  s*  d dl mZ d dlZd dlmZ d dlmZmZ d dlmZm	Z	 d dl
mZ d dlmZmZmZ d dlmZmZ d	d
lmZ d	dlmZ dZedddG dd dZedddG dd deZedddG dd deZd"ddZedddedG dd deZedddG d d! d!ZdS )#    )annotationsN)copy)	dataclassfields)	AnnotatedAny)get_snapshot)AliasChoicesBeforeValidatorField)
deprecatedoverload   )_utils)UsageLimitExceeded)RequestUsageRunUsageUsageUsageLimitsFT)reprkw_onlyc                   @  s   e Zd ZU dZded< 	 dZded< 	 dZded< 	 dZded< 	 dZded	< 	 dZ	ded
< 	 dZ
ded< 	 ejedZded< 	 eedd!ddZeedd!ddZed!ddZd"ddZdd Zd#ddZd S )$	UsageBaser   zVAnnotated[int, Field(validation_alias=AliasChoices('input_tokens', 'request_tokens'))]input_tokensintcache_write_tokenscache_read_tokenszXAnnotated[int, Field(validation_alias=AliasChoices('output_tokens', 'response_tokens'))]output_tokensinput_audio_tokenscache_audio_read_tokensoutput_audio_tokensdefault_factoryz=Annotated[dict[str, int], BeforeValidator(lambda d: d or {})]detailsz:`request_tokens` is deprecated, use `input_tokens` insteadreturnc                 C     | j S N)r   self r(   W/var/www/html/karishye-ai-python/venv/lib/python3.10/site-packages/pydantic_ai/usage.pyrequest_tokens5      zUsageBase.request_tokensz<`response_tokens` is deprecated, use `output_tokens` insteadc                 C  r$   r%   )r   r&   r(   r(   r)   response_tokens:   r+   zUsageBase.response_tokensc                 C  s   | j | j S )z&Sum of `input_tokens + output_tokens`.)r   r   r&   r(   r(   r)   total_tokens?   s   zUsageBase.total_tokensdict[str, int]c                 C  s   i }| j r
| j |d< | jr| j|d< | j }| jr| j|d< | jr'| j|d< | jr/| j|d< | jr7| j|d< | jr?| j|d< |rTd}|	 D ]\}}|rS|||| < qG|S )	z7Get the token usage values as OpenTelemetry attributes.zgen_ai.usage.input_tokenszgen_ai.usage.output_tokensr   r   r   r   r   zgen_ai.usage.details.)
r   r   r"   r   r   r   r   r   r   items)r'   resultr"   prefixkeyvaluer(   r(   r)   opentelemetry_attributesD   s.   







z"UsageBase.opentelemetry_attributesc                   s2    fddt  D } jj dd| dS )Nc                 3  s0    | ]}t  |j r|j d V  qdS )=N)getattrname).0fr'   r3   r(   r)   	<genexpr>`   s   . z%UsageBase.__repr__.<locals>.<genexpr>(z, ))r   	__class____qualname__join)r'   kv_pairsr(   r:   r)   __repr___   s   zUsageBase.__repr__boolc                 C  s   t t|  S )z(Whether any values are set and non-zero.)anydataclassesasdictvaluesr&   r(   r(   r)   
has_valuesc   s   zUsageBase.has_valuesN)r#   r   )r#   r.   r#   rC   )__name__
__module__r?   r   __annotations__r   r   r   r   r   r   rE   fielddictr"   propertyr   r*   r,   r-   r4   rB   rH   r(   r(   r(   r)   r      s>   
 




r   c                   @  sF   e Zd ZdZedd ZdddZdd
dZeddddddZ	dS )r   zLLM usage associated with a single request.

    This is an implementation of `genai_prices.types.AbstractUsage` so it can be used to calculate the price of the
    request using [genai-prices](https://github.com/pydantic/genai-prices).
    c                 C  s   dS )Nr   r(   r&   r(   r(   r)   requestsp   s   zRequestUsage.requests
incr_usager#   Nonec                 C  s
   t | |S zhIncrement the usage in place.

        Args:
            incr_usage: The usage to increment by.
        )_incr_usage_tokensr'   rQ   r(   r(   r)   incrt   s   
zRequestUsage.incrotherc                 C     t | }|| |S )zAdd two RequestUsages together.

        This is provided so it's trivial to sum usage information from multiple parts of a response.

        **WARNING:** this CANNOT be used to sum multiple requests without breaking some pricing calculations.
        r   rV   r'   rW   	new_usager(   r(   r)   __add__|   s   
zRequestUsage.__add__defaultN)
api_flavorr"   datar   providerstrprovider_urlprovider_fallbackr^   r"   dict[str, Any] | Nonec             	   C  s   |pi }d|f|df|dffD ]4\}}z't  d||}	|	j||d\}
}| di dd |j D d|iW   S  tyC   Y qw | |dS )a  Extract usage information from the response data using genai-prices.

        Args:
            data: The response data from the model API.
            provider: The actual provider ID
            provider_url: The provider base_url
            provider_fallback: The fallback provider ID to use if the actual provider is not found in genai-prices.
                For example, an OpenAI model should set this to "openai" in case it has an obscure provider ID.
            api_flavor: The API flavor to use when extracting usage information,
                e.g. 'chat' or 'responses' for OpenAI.
            details: Becomes the `details` field on the returned `RequestUsage` for convenience.
        N)r^   c                 S  s   i | ]\}}|d ur||qS r%   r(   )r8   kvr(   r(   r)   
<dictcomp>   s    z(RequestUsage.extract.<locals>.<dictcomp>r"   )r"   r(   )r   find_providerextract_usage__dict__r/   	Exception)clsr_   r`   rb   rc   r^   r"   provider_idprovider_api_urlprovider_obj
_model_refextracted_usager(   r(   r)   extract   s   ,
zRequestUsage.extract)rQ   r   r#   rR   )rW   r   r#   r   )r_   r   r`   ra   rb   ra   rc   ra   r^   ra   r"   rd   r#   r   )
rJ   rK   r?   __doc__rO   rP   rV   r\   classmethodrr   r(   r(   r(   r)   r   h   s    


r   c                   @  s   e Zd ZU dZdZded< 	 dZded< 	 dZded< 	 dZded< 	 dZ	ded< 	 dZ
ded	< 	 dZded
< 	 dZded< 	 ejedZded< 	 dddZdddZdS )r   zLLM usage associated with an agent run.

    Responsibility for calculating request usage is on the model; Pydantic AI simply sums the usage information across requests.
    r   r   rP   
tool_callsr   r   r   r   r   r   r    r.   r"   rQ   RunUsage | RequestUsager#   rR   c                 C  s4   t |tr|  j|j7  _|  j|j7  _t| |S rS   )
isinstancer   rP   ru   rT   rU   r(   r(   r)   rV      s   

zRunUsage.incrrW   c                 C  rX   )z{Add two RunUsages together.

        This is provided so it's trivial to sum usage information from multiple runs.
        rY   rZ   r(   r(   r)   r\      s   
zRunUsage.__add__N)rQ   rv   r#   rR   )rW   rv   r#   r   )rJ   rK   r?   rs   rP   rL   ru   r   r   r   r   r   r   rE   rM   rN   r"   rV   r\   r(   r(   r(   r)   r      s,   
 
r   slfrv   rQ   r#   rR   c                 C  s   |  j |j 7  _ |  j|j7  _|  j|j7  _|  j|j7  _|  j|j7  _|  j|j7  _|j D ]\}}| j|d| | j|< q5dS )zIncrement the usage in place.

    Args:
        slf: The usage to increment.
        incr_usage: The usage to increment by.
    r   N)	r   r   r   r   r   r   r"   r/   get)rx   rQ   r2   r3   r(   r(   r)   rT      s   rT   z-`Usage` is deprecated, use `RunUsage` insteadc                   @  s   e Zd ZdZdS )r   z Deprecated alias for `RunUsage`.N)rJ   rK   r?   rs   r(   r(   r(   r)   r      s    r   c                	   @  s"  e Zd ZU dZdZded< 	 dZded< 	 dZded< 	 dZded< 	 dZ	ded	< 	 d
Z
ded< 	 eedd*ddZeedd*ddZedddddd
dd+ddZeeddddddd
dd,ddZdddddd
dddd-ddZd.dd Zd/d#d$Zd/d%d&Zd0d(d)ZejZdS )1r   aE  Limits on model usage.

    The request count is tracked by pydantic_ai, and the request limit is checked before each request to the model.
    Token counts are provided in responses from the model, and the token limits are checked after each response.

    Each of the limits can be set to `None` to disable that limit.
    2   
int | Nonerequest_limitNtool_calls_limitinput_tokens_limitoutput_tokens_limittotal_tokens_limitFrC   count_tokens_before_requestzF`request_tokens_limit` is deprecated, use `input_tokens_limit` insteadr#   c                 C  r$   r%   )r~   r&   r(   r(   r)   request_tokens_limit  r+   z UsageLimits.request_tokens_limitzH`response_tokens_limit` is deprecated, use `output_tokens_limit` insteadc                 C  r$   r%   )r   r&   r(   r(   r)   response_tokens_limit  r+   z!UsageLimits.response_tokens_limitr|   r}   r~   r   r   r   rR   c                C  (   || _ || _|| _|| _|| _|| _d S r%   r   )r'   r|   r}   r~   r   r   r   r(   r(   r)   __init__  s   
zUsageLimits.__init__zmUse `input_tokens_limit` instead of `request_tokens_limit` and `output_tokens_limit` and `total_tokens_limit`)r|   r}   r   r   r   r   r   r   c                C  r   r%   r   )r'   r|   r}   r   r   r   r   r(   r(   r)   r   -  s   
)r|   r}   r~   r   r   r   r   r   c          	      C  s0   || _ || _|p	|| _|p|| _|| _|| _d S r%   r   )	r'   r|   r}   r~   r   r   r   r   r   r(   r(   r)   r   B  s   


c                 C  s   t dd | j| j| jfD S )ax  Returns `True` if this instance places any limits on token counts.

        If this returns `False`, the `check_tokens` method will never raise an error.

        This is useful because if we have token limits, we need to check them after receiving each streamed message.
        If there are no limits, we can skip that processing in the streaming response iterator.
        c                 s  s    | ]}|d uV  qd S r%   r(   )r8   limitr(   r(   r)   r;   ^  s    
z/UsageLimits.has_token_limits.<locals>.<genexpr>)rD   r~   r   r   r&   r(   r(   r)   has_token_limitsV  s   zUsageLimits.has_token_limitsusager   c                 C  s   | j }|dur|j|krtd| |j}| jdur,|| jkr,td| j d|d|j}| jdurE|| jkrGtd| j d|ddS dS )z[Raises a `UsageLimitExceeded` exception if the next request would exceed any of the limits.Nz3The next request would exceed the request_limit of z8The next request would exceed the input_tokens_limit of  (input_tokens=r=   z8The next request would exceed the total_tokens_limit of  (total_tokens=)r|   rP   r   r   r~   r-   r   )r'   r   r|   r   r-   r(   r(   r)   check_before_requestb  s   z UsageLimits.check_before_requestc                 C  s   |j }| jdur|| jkrtd| j d|d|j}| jdur2|| jkr2td| j d|d|j}| jdurK|| jkrMtd| j d|ddS dS )	zURaises a `UsageLimitExceeded` exception if the usage exceeds any of the token limits.Nz#Exceeded the input_tokens_limit of r   r=   z$Exceeded the output_tokens_limit of z (output_tokens=z#Exceeded the total_tokens_limit of r   )r   r~   r   r   r   r-   r   )r'   r   r   r   r-   r(   r(   r)   check_tokenst  s   zUsageLimits.check_tokensprojected_usagec                 C  s:   | j }|j}|dur||krtd| d|ddS dS )zbRaises a `UsageLimitExceeded` exception if the next tool call(s) would exceed the tool call limit.Nz;The next tool call(s) would exceed the tool_calls_limit of z (tool_calls=z).)r}   ru   r   )r'   r   r}   ru   r(   r(   r)   check_before_tool_call  s   z"UsageLimits.check_before_tool_call)r#   r{   )r|   r{   r}   r{   r~   r{   r   r{   r   r{   r   rC   r#   rR   )r|   r{   r}   r{   r   r{   r   r{   r   r{   r   rC   r#   rR   )r|   r{   r}   r{   r~   r{   r   r{   r   r{   r   rC   r   r{   r   r{   rI   )r   r   r#   rR   )r   r   r#   rR   )rJ   rK   r?   rs   r|   rL   r}   r~   r   r   r   rO   r   r   r   r   r   r   r   r   r   r   dataclasses_no_defaults_reprrB   r(   r(   r(   r)   r      sj   
 




	r   )rx   rv   rQ   rv   r#   rR   )
__future__r   _annotationsrE   r   r   r   typingr   r   genai_prices.data_snapshotr   pydanticr	   r
   r   typing_extensionsr   r    r   
exceptionsr   __all__r   r   r   rT   r   r   r(   r(   r(   r)   <module>   s.    

U
@
6

