
    yj`A                        d dl mZ d dl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mZ d dlmZ d dlmZmZmZ d d	lmZmZ  ej        e          ZddZddZddZddZ G d d          ZdS )    )annotationsN)AsyncIterator)Anycast)BadRequestErrorLengthFinishReasonError)	BaseModelValidationError)ValidationException)CompletionResultStreamChunkToolCallResult)repair_response_model_jsonvalidate_structured_outputmodelstrreturnboolc                    |                                  }|dk    s*|                    d          s|                    d          rdS dD ]#}||k    s|                    |dz             r dS $dS )aH  OpenAI reasoning models (gpt-5 family + o-series) require
    ``max_completion_tokens`` instead of the classic ``max_tokens`` parameter.

    Matches: gpt-5, gpt-5-anything, gpt-5.anything (incl. gpt-5.4, gpt-5.4-mini),
    o1*, o3*, o4*. Anything else (gpt-4.x, gpt-4o, chat models on proxies)
    stays on ``max_tokens``.
    zgpt-5zgpt-5-zgpt-5.T)o1o3o4-F)lower
startswith)r   mprefixs      ?/DATA/AppData/hermes/projects/honcho/src/llm/backends/openai.py_uses_max_completion_tokensr      s|     	AG||q||H--|h1G1G|t$  ;;!,,v|44;44 5    responser   
str | Nonec                   	 | j         d         j        }t          |d          r|j        rg }|j        D ]}t	          |dd           }t          |t                    r|r|                    |           @t          |t                    rht          t          t          t          f         |          }|                    d          }t          |t                    r|r|                    |           |rd                    |          S t          |d          r|j        r|j        S n# t          t          t           f$ r Y d S w xY wd S )Nr   reasoning_detailscontent
reasoning_content)choicesmessagehasattrr$   getattr
isinstancer   appenddictr   r   getjoinr'   AttributeError
IndexError	TypeError)r!   r)   reasoning_partsdetaildetail_contentdetail_dictdict_contents          r    extract_openai_reasoning_contentr9   &   sc   "1%-7/00 	2W5N 	2)+O!3 = =!(D!A!Anc22 =~ =#**>::::-- ="&tCH~v">">K#.??9#=#=L!,44 = ='..|<<< 2yy1117/00 	-W5N 	-,,J	2   tt4s   DD( 	D( (EElist[dict[str, Any]]c                   	 | j         d         j        }t          |d          r|j        rg }|j        D ]}t          |d          rd|                                }t          |t                    r:|                    t          t          t          t          f         |                     wt          |t                    r;|                    t          t          t          t          f         |                     t          |dd           }t          |t                    r|r|                    d|i           |S n# t          t          t          f$ r g cY S w xY wg S )Nr   r$   
model_dumpr%   )r(   r)   r*   r$   r<   r,   r.   r-   r   r   r   r+   r1   r2   r3   )r!   r)   detailsr5   dumpedr6   s         r    extract_openai_reasoning_detailsr?   =   s]   "1%-7/00 	W5N 	,.G!3 
D 
D6<00 	D#..00F!&$// EtDcNF'C'CDDD-- DNN4S#X#?#?@@@@%,VY%E%EN!.#66 D> D	>'BCCCNJ	2   			Is   D=E EEusagetuple[int, int]c                T   | sdS d}t          | d          r,| j        r%| j        }t          |d          r|j        r|j        }|dk    r=t          | d          r| j        r| j        }nt          | d          r| j        r| j        }d}t          | d          r| j        r| j        }||fS )N)r   r   r   prompt_tokens_detailscached_tokenscache_read_input_tokenscache_creation_input_tokens)r*   rC   rD   rE   rF   )r@   
cache_readr=   cache_creations       r   extract_openai_cache_tokensrI   S   s     tJu-.. /53N /-7O,, 	/1F 	/ .JQ5344 	-9V 	-6JJUO,, 	-1D 	-,JN455;-; ::%%r    c            
          e Zd ZdZd1dZdddddddddd	d2d!Zdddddddddd	d3d#Zd4d%Zdd&d5d*Zd6d-Z	e
d7d/            Ze
d8d0            ZdS )9OpenAIBackendz&Provider backend wrapping AsyncOpenAI.clientr   r   Nonec                    || _         d S )N)_client)selfrL   s     r   __init__zOpenAIBackend.__init__p   s    "r    N)	temperaturestoptoolstool_choiceresponse_formatthinking_budget_tokensthinking_effortmax_output_tokensextra_paramsr   r   messagesr:   
max_tokensintrR   float | NonerS   list[str] | NonerT   list[dict[str, Any]] | NonerU   str | dict[str, Any] | NonerV   'type[BaseModel] | dict[str, Any] | NonerW   
int | NonerX   r"   rY   rZ   dict[str, Any] | Noner   c                 K   |	t          d          |                     |||p||||||
|	  	        }t          |t                    r||d<   	  | j        j        j        j        di | d {V }n# t          $ rR}|j	        }|j
        d         j        j        pd}t          |||          }|                     ||          cY d }~S d }~wt          t           j        t$          f$ rN |                     ||           d {V }|                     |||          }|                     ||          cY S w xY w|j
        d         j        j        }|j
        d         j        j        pd}|*|r(t          |||          }|                     ||          S |It-          |j
        d         j        dd           }|r|                     ||          S t          d	          |                     |t/          ||                    S |||d<   |r|                    d
          rddi|d<    | j        j        j        j        di | d {V }|                     |          S )NSOpenAI backend does not support thinking_budget_tokens; use thinking_effort instead	r   r[   r\   rR   rS   rT   rU   rX   rZ   rV   r    content_override)paramsrV   refusalz(No parsed content in structured response	json_modetypejson_object )r   _build_paramsr,   rn   rO   chatcompletionsparser   
completionr(   r)   r%   r   _normalize_responser   jsonJSONDecodeErrorr
   _create_structured_response#_parse_or_repair_structured_contentparsedr+   r   r/   create)rP   r   r[   r\   rR   rS   rT   rU   rV   rW   rX   rY   rZ   rk   r!   exc	truncatedraw_contentr%   fallback_responser{   rl   s                         r   completezOpenAIBackend.completes   ss       "-%e   ##(6J##+% $ 

 

 ot,, 2	(7F$%!D!2!>!D!N!Nv!N!NNNNNNN*   N	'/2:BHb4# 
 //%, 0         $T%9?K   *.*J*J!$3 +K + + % % % % % %! BB%# 
 //%%, 0      %a(07F"*1-5=CK~+~4# 
 //7/SSS~!("21"5"=y$OO 33 )0 4    **TUUU++!;FO!T!T ,    &(7F$% 	@L,,[99 	@)/(?F$%=*6=GGGGGGGGGG''111s&   "A3 3
D7=AC
D7
A*D76D7AsyncIterator[StreamChunk]c              ,  K   |	t          d          |                     |||p||||||
|	  	        }d|d<   ddi|d<   t          |t                    r#d|j        |                                dd	|d
<   n&|||d
<   n|r|                    d          rddi|d
<    | j        j        j	        j
        di | d {V }d }d}|2 3 d {V }|j        r?|j        d         j        j        r(t          |j        d         j        j                  W V  |j        r$|j        d         j        r|j        d         j        }t!          |d          r(|j        r!t          d||j        j                  W V  d}6 |s|rt          d|          W V  d S d S d S )Nrf   rg   Tstreaminclude_usagestream_optionsjson_schemanameschemarn   r   rV   rm   rn   ro   Fr   )r%   r@   )is_donefinish_reasonoutput_tokens)r   r   rp   )r   rq   r,   rn   __name__model_json_schemar/   rO   rr   rs   r|   r(   deltar%   r   r   r*   r@   completion_tokens)rP   r   r[   r\   rR   rS   rT   rU   rV   rW   rX   rY   rZ   rk   response_streamr   usage_chunk_receivedchunks                     r   r   zOpenAIBackend.stream   s       "-%e   ##(6J##+% $ 

 

  x$3T#: ot,, 	@ &+4-??AA   ) )F$%% ((7F$%% 	@l..{;; 	@)/(?F$% D 1 = D N Nv N NNNNNNN$($* 	, 	, 	, 	, 	, 	, 	,%} Jq!1!7!? J!%-*:*@*HIIIIIII} ?q!1!? ? %a 0 >ug&& ,5; ,! "/"'+"?      
 (,$ + $ 	I 	Id-HHHHHHHHH	I 	I 	I 	Is   E7dict[str, Any]c       	            ||d}
t          |          r(||
d<   |	r |	                    d          r|	d         |
d<   n||
d<   |||
d<   |r||
d<   |r||
d<   |r|                     |          |
d<   |||
d	<   |	rd
D ]}||	v r|	|         |
|<   |
S )N)r   r[   max_completion_tokens	verbosityr\   rR   reasoning_effortrS   rT   rU   )top_pfrequency_penaltypresence_penaltyseed)r   r/   _convert_tools)rP   r   r[   r\   rR   rS   rT   rU   rX   rZ   rk   keys               r   rq   zOpenAIBackend._build_params  s	     "
 "

 'u-- 	..8F*+ @ 0 0 = = @&2;&?{##-F< "$/F=! 	9)8F%& 	"!F6N 	4"11%88F7O&(3}% 	4 4 4 ,&&".s"3F3Kr    ri   r!   rj   
Any | Nonec                  |j         }|j        d         j        }g }|j        d         j        }t	          |dd           r|j        D ]}i }|j        j        ry	 t          j	        |j        j                  }nY# t          j
        t          f$ r@}	t                              d|j        j        |j        |	j        j                   Y d }	~	nd }	~	ww xY w|                    t'          |j        |j        j        |                     t)          |          \  }
}t+          ||n|j        pd|r|j        nd|r|j        nd|
||pd|t3          |          t5          |          |
  
        S )Nr   
tool_callsz+Malformed tool arguments for %s (id=%s): %s)idr   inputrh   rS   )
r%   input_tokensr   rF   rE   r   r   thinking_contentr$   raw_response)r@   r(   r   r)   r+   r   function	argumentsrw   loadsrx   r3   loggerwarningr   r   	__class__r   r-   r   rI   r   r%   prompt_tokensr   r9   r?   )rP   r!   rj   r@   r   r   r)   	tool_call
tool_inputr}   rH   rG   s               r   rv   z!OpenAIBackend._normalize_responseD  s     (+9+-
"1%-7L$// 	$/  	-/
%/ %)Z	0B0L%M%M

 0)< 	 	 	 I%.3%LM2	       		 !!"$<&/4(      &A%G%G"
+ %$/'R05<,,15:A%11(6$.'16!=hGG>xHH!
 
 
 	
s   A66C6CCrk   type[BaseModel]c                  K   t          |          }d|j        |                                dd|d<    | j        j        j        j        di | d {V S )Nr   r   r   rV   rp   )r.   r   r   rO   rr   rs   r|   )rP   rk   rV   structured_paramss       r   ry   z)OpenAIBackend._create_structured_responsev  s       !LL!'0);;== 0
 0
+, :T\&29NN<MNNNNNNNNNr    BaseModel | strc                    | j         d         j        j        pd}|rt          |||          S t	          | j         d         j        dd           }|r|S t          d          )Nr   rh   rl   z5No raw content available for structured output repair)r(   r)   r%   r   r+   r   )r!   rV   r   r   rl   s        r   rz   z1OpenAIBackend._parse_or_repair_structured_content  su     &q)19?R 	S-k?ERRR(*1-5y$GG 	N!C
 
 	
r    c                `    | r| d                              d          dk    r| S d | D             S )Nr   rn   r   c                D    g | ]}d |d         |d         |d         ddS )r   r   descriptioninput_schema)r   r   
parameters)rn   r   rp   ).0tools     r   
<listcomp>z0OpenAIBackend._convert_tools.<locals>.<listcomp>  sU     

 

 

  # L#'#6"&~"6  

 

 

r    )r/   )rT   s    r   r   zOpenAIBackend._convert_tools  sL     	aV,,
::L

 

 

 

 

 
	
r    )rL   r   r   rM   )r   r   r[   r:   r\   r]   rR   r^   rS   r_   rT   r`   rU   ra   rV   rb   rW   rc   rX   r"   rY   rc   rZ   rd   r   r   )r   r   r[   r:   r\   r]   rR   r^   rS   r_   rT   r`   rU   ra   rV   rb   rW   rc   rX   r"   rY   rc   rZ   rd   r   r   )r   r   r[   r:   r\   r]   rR   r^   rS   r_   rT   r`   rU   ra   rX   r"   rZ   rd   r   r   )r!   r   rj   r   r   r   )rk   r   rV   r   r   r   )r!   r   rV   r   r   r   r   r   )rT   r:   r   r:   )r   
__module____qualname____doc__rQ   r   r   rq   rv   ry   staticmethodrz   r   rp   r    r   rK   rK   m   sI       00# # # # %)!%-137CG-1&*(,.2[2 [2 [2 [2 [2 [2F %)!%-137CG-1&*(,.2BI BI BI BI BI BIH. . . .h (,	0
 0
 0
 0
 0
 0
dO O O O  
 
 
 \
 
 
 
 \
 
 
r    rK   )r   r   r   r   )r!   r   r   r"   )r!   r   r   r:   )r@   r   r   rA   ) 
__future__r   rw   loggingcollections.abcr   typingr   r   openair   r   pydanticr	   r
   src.exceptionsr   src.llm.backendr   r   r   src.llm.structured_outputr   r   	getLoggerr   r   r   r9   r?   rI   rK   rp   r    r   <module>r      s{   " " " " " "   ) ) ) ) ) )         ; ; ; ; ; ; ; ; / / / / / / / / . . . . . . I I I I I I I I I I       
 
	8	$	$   "   .   ,& & & &4~
 ~
 ~
 ~
 ~
 ~
 ~
 ~
 ~
 ~
r    