
    yjX                        d dl mZ d dlmZ d dlmZmZmZ d dlmZm	Z	m
Z
 d dlmZ d dlmZmZ d dlmZmZmZ d dlmZmZmZmZ d d	lmZ h d
Z G d d          ZdS )    )annotations)AsyncIterator)datetime	timedeltatimezone)AnyClassVarcast)	BaseModel)LLMErrorValidationException)CompletionResultStreamChunkToolCallResult)GeminiCacheHandlePromptCachePolicybuild_cache_keygemini_cache_store)repair_response_model_json>   SAFETY	BLOCKLIST
RECITATIONPROHIBITED_CONTENTc            
         e Zd ZU dZd:dZd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%Zd>d)Zd?d.Z	e
d@d/            Ze
dAd1            Ze
dBd2            Z eh d3          Zd4ed5<   e
dCd7            Ze
dDd9            ZdS )EGeminiBackendz/Provider backend wrapping the Google GenAI SDK.clientr   returnNonec                    || _         d S )N)_client)selfr   s     ?/DATA/AppData/hermes/projects/honcho/src/llm/backends/gemini.py__init__zGeminiBackend.__init__   s    "    N)	temperaturestoptoolstool_choiceresponse_formatthinking_budget_tokensthinking_effortmax_output_tokensextra_paramsmodelstrmessageslist[dict[str, Any]]
max_tokensintr%   float | Noner&   list[str] | Noner'   list[dict[str, Any]] | Noner(   str | dict[str, Any] | Noner)   'type[BaseModel] | dict[str, Any] | Noner*   
int | Noner+   
str | Noner,   r-   dict[str, Any] | Noner   c                 K   |                      |          \  }}|                     |p|||||||	|
|	  	        }|r||d<   |rd|v r|                    d          nd }t          |t                    rSt          |t
                    r>|r
|d d         ng }|                     |||||           d {V  d|v r|r
|dd          }t          |t
                    r|st          dd|	          | j        j	        j
                            |||pd 
           d {V }|                     |t          |t                    r|nd |          S )N	r2   r%   r&   r'   r(   r)   r*   r+   r-   system_instructioncache_policyr.   configr?   contentsr'   cached_content(No non-system messages to send to Geminigeminiproviderr.   r.   rC   rB   )responser)   
model_name)_convert_messages_build_configget
isinstancer   list_attach_cached_contentr   r    aiomodelsgenerate_content_normalize_responsetype)r!   r.   r0   r2   r%   r&   r'   r(   r)   r*   r+   r,   r-   rC   r>   rB   r?   	cacheablerJ   s                      r"   completezGeminiBackend.complete!   s       (,'='=h'G'G$$##(6J##+#9+% $ 

 

  	>+=F'(  ., > > ^,,, 	
 l$566 	):hPT;U;U 	))19"rI--)" .           6))h)#BCC=h%% 	h 	:!    )0AA>T B 
 
 
 
 
 
 
 

 ''/400OO ( 
 
 	
r$   AsyncIterator[StreamChunk]c                K   |                      |          \  }}|                     |p|||||||	|
|	  	        }|r||d<   |rd|v r|                    d          nd }t          |t                    rSt          |t
                    r>|r
|d d         ng }|                     |||||           d {V  d|v r|r
|dd          }t          |t
                    r|st          dd|	          | j        j	        j
                            |||pd 
           d {V }d }d}|2 3 d {V }|j        rd}t          |j                  W V  |}+6 d}d }|r:t          |dd           r)|j        d         j        r|j        d         j        j        }|r5t          |dd           r$t          |j        dd           r|j        j        pd }|s |t(          v rt          d| dd||          t          d||          W V  d S )Nr=   r>   r?   r@   rA   rD   rE   rF   rG   rI   FT)contentr&   
candidatesr   usage_metadatacandidates_token_count'Gemini response blocked (finish_reason=)rH   r.   finish_reason)is_donerb   output_tokens)rL   rM   rN   rO   r   rP   rQ   r   r    rR   rS   generate_content_streamtextr   getattrr\   rb   namer]   r^   GEMINI_BLOCKED_FINISH_REASONS)r!   r.   r0   r2   r%   r&   r'   r(   r)   r*   r+   r,   r-   rC   r>   rB   r?   rW   streamfinal_chunkany_textchunkrb   rd   s                           r"   rj   zGeminiBackend.streamf   s]       (,'='=h'G'G$$##(6J##+#9+% $ 

 

  	>+=F'(  ., > > ^,,, 	
 l$566 	):hPT;U;U 	))19"rI--)" .           6))h)#BCC=h%% 	h 	:!    |'.FF>T G 
 
 
 
 
 
 
 
 ! 	  	  	  	  	  	  	 %z 6!%*5555555KK	 " $(	I\488	I &q)7	I
 (215CHM	V%5t<<	V 24LdSS	V
 (6MUQUM  	M-JJJJ-JJJ!+	    ''
 
 
 	
 	
 	
 	
 	
 	
s   %Edict[str, Any]c       	           d|i}
|||
d<   |r||
d<   |r|                      |          |
d<   |r|                     |          |
d<   |d|
d<   ||
d<   n|	r|	                    d	          r|sd|
d<   i }|||d
<   |||d<   t          |          dk    rt	          d          |r||
d<   dD ]}|	r||	v r|	|         |
|<   |
S )Nr,   r%   stop_sequencesr'   tool_configzapplication/jsonresponse_mime_typeresponse_schema	json_modethinking_budgetthinking_level   zkGemini backend does not support sending both thinking_budget_tokens and thinking_effort in the same requestthinking_config)top_ptop_kfrequency_penaltypresence_penaltyseed)_convert_tools_convert_tool_choicerN   lenr   )r!   r2   r%   r&   r'   r(   r)   r*   r+   r-   rB   rx   keys                r"   rM   zGeminiBackend._build_config   s\     "
 "$/F=! 	,'+F#$ 	9"11%88F7O 	K$($=$=k$J$JF=!&+=F'((7F$%% 	>l..{;; 	>E 	>+=F'(*,!-1GO-.&0?O,-!##%}    	8(7F$%V 	0 	0C 0| 3 3*3/sr$   rJ   type[BaseModel] | NonerK   c               ^   |j         r|j         d         nd }||j        r|j        j        nd}g }g }|Ht          |dd           r7t	          t
          t                   d z  t          |j        dd                     nd }t          |t
                    r|D ]	}	t          |	dd           }
t          |
t                    r|
r|
                    |
           t          |	dd           }|t          |dd           }t          |dd           }t          |t                    s|
                    t          d	| d
t          |           ||r4t          t	          t          t          t          f         |                    ni t          |	dd                                t          |dd           }|s,t          |t                    r|r|
                    |           t	          t
          t                   d z  t          |dd                     }|st          |t
                    r|D ]}t          |dd           }t          |dd           }t          |t                    s:|
                    t          d	| d
t          |           ||r4t          t	          t          t          t          f         |                    ni                      |rd                    |          nd}|t          |dd           }t          ||          r|}nt          |t                    r|                    |          }nt          |t                    r|                    |          }nk|t"          v rt%          d| dd||          d                    |          }t'          |||          }n$|s"|s |t"          v rt%          d| dd||          |j        }d}|(t          |dd          }t          |t*                    r|}t-          ||r|j        nd|r|j        nd||||          S )Nr   r&   r[   partsrf   function_callrh   argscall__thought_signature)idrh   inputr   function_calls)r   rh   r   
 parsedr_   r`   rF   ra   cached_content_token_count)r[   input_tokensrd   cache_read_input_tokensrb   
tool_callsraw_response)r\   rb   rh   rg   r
   rP   r   r[   rO   r/   appendr   r   dictjoinmodel_validatemodel_validate_jsonri   r   r   r]   r3   r   prompt_token_countr^   )r!   rJ   r)   rK   	candidaterb   
text_partsr   candidate_partspart	part_textr   function_namefunction_argsresponse_textresponse_function_callsr[   parsed_responseraw_textusager   cached_tokenss                         r"   rU   z!GeminiBackend._normalize_response   s    /7.AKH'**t	 $)@$ #(( 	 !#
+-
 $It)L)L$ cT!79+<gt#L#LMMM 	
 ot,, 	'  #D&$77	i-- 1) 1%%i000 'ot D D ,$+M64$H$HM$+M64$H$HM%mS99 ! %%&H}HHs:HH!.,#$$tDcNM'J'J"K"K"K!#.5d<OQU.V.V  	 	 	  &$77 	-j<< 	- 	-m,,,"&IH.55#
 #
  	j)@$GG 	!8   'vt D D 'vt D D!-55 !!"D=DD3z??DD*( d4S#X#F#FGGG      1;Btyy,,,&%h$??O/?;; )OT22 )88IIOS11 )==oNN $AAA"R-RRR!)(&3	    77:..4#  
	
	 !>>>J-JJJ! +	    '"##E+GKKM--- 8*7'5:A11:?F%66Q$;'!!
 
 
 	
r$   rB   r?   r   rC   c          
       K   |j         dk    rd S t          |p)|                    d          p|                    d                    }|sd S t          |                     |          ||||                    d          |                    d                    }t          j        |          }||j        pd}	|                    d          |                    d          |                    d          |	 dd}
|r||
d	<   | j        j        j	        
                    ||

           d {V }t          |dd           }|/t          j        t          j                  t!          |	          z   }t          j        t%          ||j        |                    }|                    dd            |                    dd            |                    dd            |j        |d<   d S )Ngemini_cached_contentr>   r'   rq   )rB   r?   cacheable_messagesr'   r>   rq   i,  s)r>   r'   rq   ttlrC   )r.   rB   expire_time)seconds)r   cached_content_name
expires_atrD   )modeboolrN   r   _cache_model_configr   ttl_secondsr    rR   cachescreaterg   r   nowr   utcr   setr   rh   popr   )r!   r.   rB   r?   rC   r'   has_cacheable	cache_keycached_handler   cache_configrD   r   s                r"   rQ   z$GeminiBackend._attach_cached_contento  s0       777FO

#788OFJJw<O<O
 
  	F#++E22%'%zz*>??

=11
 
 
	 +.y99 &29cK&,jj1E&F&FG,,%zz-88%(((	, ,L  4+3Z(#'<#3#:#A#A# $B $ $      N !EEJ!%\(,77)K:X:X:XX
.2!!(6(;)   M 	

'...

7D!!!

=$'''#0#D   r$   c                (    ddl m}  |d|           S )Nr   )ModelConfigrF   )	transportr.   )
src.configr   )r.   r   s     r"   r   z!GeminiBackend._cache_model_config  s)    ******{XU;;;;r$   -tuple[list[dict[str, Any]] | str, str | None]c                   g }g }| D ]}|                     dd          }|dk    rDt          |                     d          t                    r|                    |d                    c|dk    rd}t          |                     d          t                    r/|                                }||d<   |                    |           t          |                     d          t                    r#|                    |d|d         igd	           t          |                     d          t                    r{g }|d         D ]V}|                     d
          }|dk    r|                    d|d         i           ;t          dd|dz   dz   dz             |r|                    ||d	           |rd                    |          nd }	||	fS )Nroleusersystemr[   	assistantr.   r   rf   )r   r   rV   z.Gemini backend cannot translate content block zof type z; translate to z.Gemini-native 'parts' via the history adapter zbefore passing to the backendz

)rN   rO   r/   r   rP   copyr   r   )
r0   system_messagesrC   messager   message_copyr   block
block_typer>   s
             r"   rL   zGeminiBackend._convert_messages  s    &()+ '	D '	DG;;vv..Dxgkk)44c:: ?#**79+=>>>{""'++g..55 &||~~'+V$---'++i00#66 &')BT9U8V W WXXX'++i00$77 D.0$Y/  E!&6!2!2J!V++feFm%<==== 2LFFFFGNO >>    DOOTE$B$BCCC=LVV[[999RV+++r$   c                <    | rd| d         v r| S dd | D             igS )Nfunction_declarationsr   c                n    g | ]2}|d          |d         t                               |d                   d3S )rh   descriptioninput_schema)rh   r   
parametersr   _sanitize_schema).0tools     r"   
<listcomp>z0GeminiBackend._convert_tools.<locals>.<listcomp>  s[     	* 	* 	*  !%V'+M':&3&D&D 0' ' 	* 	* 	*r$    )r'   s    r"   r~   zGeminiBackend._convert_tools  sP     	,a88L ( 	* 	* !&	* 	* 	*
 	
r$   >   enumrV   itemstitleformatmaximumminimummaxItemsminItemsnullablerequired
propertiesr   zClassVar[frozenset[str]]_GEMINI_ALLOWED_SCHEMA_KEYSschemac                $   t          | t                    s| S t          t          t          t          f         |           }i }|                                D ]9\  }}|t          j        vr|dk    r\t          |t                    rGd t          t          t          t          f         |                                          D             |d<   w|dk    rt                              |          |d<   |dk    rFt          |t                    r1t          t          t          t                   |                    |d<   |dk    rGt          |t                    r2t          t          t          t                   |                    |d<   4|||<   ;|S )uq  Recursively strip JSON-Schema keywords Gemini rejects.

        ``properties`` holds user-supplied field names → sub-schemas, so we
        recurse into its values but preserve its keys. ``required`` and
        ``enum`` are lists of literals (field names / allowed values) and are
        passed through verbatim. Everything else is a scalar schema keyword.
        r   c                J    i | ] \  }}|t                               |          !S r   r   )r   	prop_nameprop_schemas      r"   
<dictcomp>z2GeminiBackend._sanitize_schema.<locals>.<dictcomp>  s<     ) ) ).	; }==kJJ) ) )r$   r   r   r   )
rO   r   r
   r/   r   r   r   r   r   rP   )r   schema_dictcleanedr   values        r"   r   zGeminiBackend._sanitize_schema  sp    &$'' 	M4S>622"$%++-- 	% 	%JC-CCCl""z%'>'>") )26tCH~u2M2M2S2S2U2U) ) )%% #0#A#A%#H#H  
""z%'>'>"&*4S	5+A+A&B&B
##:eT#:#:"&tDIu'='=">">$r$   str | dict[str, Any]c                    t          | t                    rd| v rdd| d         gdiS | dk    rdddiiS | dv rdddiiS | d	k    rddd
iiS dd| gdiS )Nrh   function_calling_configANY)r   allowed_function_namesautor   AUTO>   anyr   noneNONE)rO   r   )r(   s    r"   r   z"GeminiBackend._convert_tool_choice+  s     k4(( 	V{-B-B)!/:6/B.C, ,  &  -/?@@----??&  -/?@@%+6-( (
 	
r$   )r   r   r   r   )r.   r/   r0   r1   r2   r3   r%   r4   r&   r5   r'   r6   r(   r7   r)   r8   r*   r9   r+   r:   r,   r9   r-   r;   r   r   )r.   r/   r0   r1   r2   r3   r%   r4   r&   r5   r'   r6   r(   r7   r)   r8   r*   r9   r+   r:   r,   r9   r-   r;   r   rY   )r2   r3   r%   r4   r&   r5   r'   r6   r(   r7   r)   r8   r*   r9   r+   r:   r-   r;   r   rn   )rJ   r   r)   r   rK   r/   r   r   )r.   r/   rB   rn   r?   r   rC   r1   r'   r6   r   r   )r.   r/   )r0   r1   r   r   )r'   r1   r   r1   )r   r   r   r   )r(   r   r   rn   )__name__
__module____qualname____doc__r#   rX   rj   rM   rU   rQ   staticmethodr   rL   r~   	frozensetr   __annotations__r   r   r   r$   r"   r   r      s        99# # # # %)!%-137CG-1&*(,.2C
 C
 C
 C
 C
 C
V %)!%-137CG-1&*(,.2f
 f
 f
 f
 f
 f
P+ + + +Zr
 r
 r
 r
h8E 8E 8E 8Et < < < \<
 0, 0, 0, \0,d 
 
 
 \
. =FI	
 	
 	
= =    $    \< 
 
 
 \
 
 
r$   r   N)
__future__r   collections.abcr   r   r   r   typingr   r	   r
   pydanticr   src.exceptionsr   r   src.llm.backendr   r   r   src.llm.cachingr   r   r   r   src.llm.structured_outputr   ri   r   r   r$   r"   <module>r	     sL   " " " " " " ) ) ) ) ) ) 2 2 2 2 2 2 2 2 2 2 & & & & & & & & & &       8 8 8 8 8 8 8 8 I I I I I I I I I I            A @ @ @ @ @! ! ! f
 f
 f
 f
 f
 f
 f
 f
 f
 f
r$   