U
    hfB                     @  s@  d Z ddlmZ ddlZddlZddlmZmZmZm	Z	m
Z
mZmZ ddlmZ ddlmZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ eejejgef ZddddddZdddddZejG dd dZddddddZG dd deeej gejf ejd Z G d!d" d"e Z!G d#d$ d$e Z"dS )%zLLMFunction.    )annotationsN)AbstractSetAnyCallableIterableMappingOptionalSequence)llmfn_input_utils)llmfn_output_row)llmfn_outputs)llmfn_post_process)llmfn_post_process_cmds)model)prompt_utilsz#llmfn_output_row.LLMFnOutputRowViewbool)lhsrhsreturnc                 C  s   |   |  kS )z-Default function used when comparing outputs.)Zresult_value)r   r    r   Q/tmp/pip-unpacked-wheel-doshhd5e/google/generativeai/notebook/lib/llm_function.py_is_equal_fn+   s    r   zYCallable[[llmfn_output_row.LLMFnOutputRowView, llmfn_output_row.LLMFnOutputRowView], Any]4llmfn_post_process.LLMCompareFnPostProcessBatchAddFn)fnr   c                   s   ddd fdd}|S )z1Vectorize a single-row-based comparison function.zYSequence[tuple[llmfn_output_row.LLMFnOutputRowView, llmfn_output_row.LLMFnOutputRowView]]zSequence[Any])lhs_and_rhs_rowsr   c                   s    fdd| D S )Nc                   s   g | ]\}} ||qS r   r   ).0r   r   r   r   r   
<listcomp>F   s     zD_convert_compare_fn_to_batch_add_fn.<locals>._fn.<locals>.<listcomp>r   )r   r   r   r   _fn>   s    z0_convert_compare_fn_to_batch_add_fn.<locals>._fnr   )r   r   r   r   r   #_convert_compare_fn_to_batch_add_fn3   s    
r   c                   @  s6   e Zd ZU ded< ded< ded< ded< ded< d	S )
_PromptInfoint
prompt_numstrprompt	input_numzMapping[str, str]prompt_varsmodel_inputN)__name__
__module____qualname____annotations__r   r   r   r   r    K   s
   
r    Sequence[str]*llmfn_input_utils.LLMFunctionInputs | NonezIterable[_PromptInfo])promptsinputsr   c              	   c  sh   g }|dk	rt |}|s i g}t| D ]:\}}t|D ](\}}|jf |}t|||||dV  q8q(dS )a
  Generate a tuple of fields needed for processing prompts.

  Args:
    prompts: A list of prompts, with optional keyword placeholders.
    inputs: A list of key/value pairs to substitute into placeholders in
      `prompts`.

  Yields:
    A _PromptInfo instance.
  N)r"   r$   r%   r&   r'   )r
   Zto_normalized_inputs	enumerateformatr    )r.   r/   Znormalized_inputsr"   r$   r%   r&   r'   r   r   r   _generate_promptsT   s    
r2   c                   @  s   e Zd ZdZdddddZejddd	d
ZejdddddZddddddZ	ddd dddZ
ddd dddZddd dddZdS ) LLMFunctionz6Base class for LLMFunctionImpl and LLMCompareFunction.N3Callable[[llmfn_outputs.LLMFnOutputs], None] | Noneoutputs_ipython_display_fnc                 C  s   g | _ || _dS )zConstructor.

    Args:
      outputs_ipython_display_fn: Optional function that will be used to
        override how the outputs of this LLMFunction will be displayed in a
        notebook (See further documentation in LLMFnOutputs.__init__().)
    N)_post_process_cmds_outputs_ipython_display_fn)selfr6   r   r   r   __init__   s    zLLMFunction.__init__AbstractSet[str]r   c                 C  s   dS )zLReturns the placeholders that should be present in inputs for this function.Nr   r9   r   r   r   get_placeholders   s    zLLMFunction.get_placeholdersr-   (Sequence[llmfn_outputs.LLMFnOutputEntry]r/   r   c                 C  s   dS )z&Concrete implementation of __call__().Nr   )r9   r/   r   r   r   
_call_impl   s    zLLMFunction._call_implzllmfn_outputs.LLMFnOutputsc                 C  s   |  |}tj|| jdS )z+Runs and returns results based on `inputs`.)outputsZipython_display_fn)rA   r   LLMFnOutputsr8   )r9   r/   rB   r   r   r   __call__   s
    
 zLLMFunction.__call__r#   z1llmfn_post_process.LLMFnPostProcessBatchReorderFnnamer   r   c                 C  s   | j tj||d | S NrF   r   )r7   appendr   ZLLMFnPostProcessReorderCommandr9   rF   r   r   r   r   add_post_process_reorder_fn   s    z'LLMFunction.add_post_process_reorder_fnz-llmfn_post_process.LLMFnPostProcessBatchAddFnc                 C  s   | j tj||d | S rG   )r7   rI   r   ZLLMFnPostProcessAddCommandrJ   r   r   r   add_post_process_add_fn   s    z#LLMFunction.add_post_process_add_fnz1llmfn_post_process.LLMFnPostProcessBatchReplaceFnc                 C  s   | j tj||d | S rG   )r7   rI   r   ZLLMFnPostProcessReplaceCommandrJ   r   r   r   add_post_process_replace_fn   s    z'LLMFunction.add_post_process_replace_fn)N)N)r(   r)   r*   __doc__r:   abcabstractmethodr>   rA   rD   rK   rL   rM   r   r   r   r   r3   v   s     

r3   )	metaclassc                      s\   e Zd ZdZdddddd fdd	Zd
d
dddZddddZdddddZ  ZS )LLMFunctionImpla  Callable class that executes the contents of a Magics cell.

  An LLMFunction is constructed from the Magics command line and cell contents
  specified by the user. It is defined by:
  - A model instance,
  - Model arguments
  - A prompt template (e.g. "the opposite of hot is {word}") with an optional
    keyword placeholder.

  The LLMFunction takes as its input a sequence of dictionaries containing
  values for keyword replacement, e.g. [{"word": "hot"}, {"word": "tall"}].

  This will cause the model to be executed with the following prompts:
    "The opposite of hot is"
    "The opposite of tall is"

  The results will be returned in a LLMFnOutputs instance.
  Nzmodel_lib.AbstractModelr,   zmodel_lib.ModelArguments | Noner4   )r   r.   
model_argsr6   c                   s^   t  j|d || _|| _|dkr*t n|| _ti | _| jD ]}| j	t
|| _q@dS )a  Constructor.

    Args:
      model: The model that the prompts will execute on.
      prompts: A sequence of prompt templates with optional placeholders. The
        placeholders will be replaced by the inputs passed into this function.
      model_args: Optional set of model arguments to configure how the model
        executes the prompts.
      outputs_ipython_display_fn: See documentation in LLMFunction.__init__().
    r5   N)superr:   _model_prompts	model_libZModelArguments_model_args	frozenset_placeholdersunionr   r>   )r9   r   r.   rS   r6   r$   	__class__r   r   r:      s    

zLLMFunctionImpl.__init__)Sequence[llmfn_output_row.LLMFnOutputRow])resultsr   c                 C  s   | j D ]}z0t|tjr$||}ntdt|W q tjk
rR    Y q t	k
r } z"td|
 t|j|W 5 d}~X Y qX q|S z-Runs post-processing commands over `results`.z)Unsupported post-process command type: {}z Error executing "{}", got {}: {}N)r7   
isinstancer   LLMFnImplPostProcessCommandrunr   PostProcessExecutionErrorr1   typeRuntimeErrorrF   r(   )r9   r_   cmder   r   r   _run_post_processing_cmds   s$    
  z)LLMFunctionImpl._run_post_processing_cmdsr;   r<   c                 C  s   | j S NrZ   r=   r   r   r   r>     s    z LLMFunctionImpl.get_placeholdersr-   r?   r@   c                 C  s   g }t | j|dD ]}| jj|j| jd}g }t|jD ],\}}|t	j
tjj|tjj|itd q8|tj|j|j|j|j|j|| |d q|S )N)r.   r/   )r'   rS   dataZresult_type)r"   r%   r$   r&   r'   model_resultsoutput_rows)r2   rV   rU   Z
call_modelr'   rX   r0   Ztext_resultsrI   r   LLMFnOutputRowr   ColumnNames
RESULT_NUMZTEXT_RESULTr#   LLMFnOutputEntryr"   r%   r$   r&   ri   )r9   r/   r_   inforn   ro   
result_numZtext_resultr   r   r   rA     s<       	zLLMFunctionImpl._call_impl)NN)	r(   r)   r*   rN   r:   ri   r>   rA   __classcell__r   r   r\   r   rR      s      rR   c                      sr   e Zd ZdZdddddd fddZd	d	d	d	d
ddZddddZdddddZddddddZ  Z	S )LLMCompareFunctionzzLLMFunction for comparisons.

  LLMCompareFunction runs an input over a pair of LLMFunctions and compares the
  result.
  Nztuple[str, LLMFunction]z&Sequence[tuple[str, CompareFn]] | Noner4   )lhs_name_and_fnrhs_name_and_fncompare_name_and_fnsr6   c                   s   t  j|d |d | _|d | _|d | _|d | _t| j | j | _	|sdd| _
t| _n@|d \}}|| _
|| _|dd D ]\}}| j|t|d qdS )a  Constructor.

    Args:
      lhs_name_and_fn: Name and function for the left-hand side of the
        comparison.
      rhs_name_and_fn: Name and function for the right-hand side of the
        comparison.
      compare_name_and_fns: Optional names and functions for comparing the
        results of the left- and right-hand sides.
      outputs_ipython_display_fn: See documentation in LLMFunction.__init__().
    r5   r      Zis_equalNrH   )rT   r:   	_lhs_name_lhs_fn	_rhs_name_rhs_fnrY   r>   r[   rZ   _result_namer   _result_compare_fnadd_compare_post_process_add_fnr   )r9   rx   ry   rz   r6   rF   r   Zcmp_fnr\   r   r   r:   6  s&    



 zLLMCompareFunction.__init__r^   )lhs_output_rowsrhs_output_rowsr_   r   c                 C  s   | j D ]}zRt|tjr$||}n6t|tjrH|tt|||}ntd	t
|W q tjk
rt    Y q tk
r } z"td	| t
|j|W 5 d}~X Y qX q|S r`   )r7   ra   r   rb   rc   ZLLMCompareFnPostProcessCommandlistziprf   r1   re   r   rd   rF   r(   )r9   r   r   r_   rg   rh   r   r   r   ri   b  s2    
   z,LLMCompareFunction._run_post_processing_cmdsr;   r<   c                 C  s   | j S rj   rk   r=   r   r   r   r>     s    z#LLMCompareFunction.get_placeholdersr-   r?   r@   c                 C  s  |  |}| |}g }t||D ]\}}|j|jkrLtd|j|j|j|jkrltd|j|j|j|jkrtd|j|jtt	|j
t	|j
}|j
d | }|j
d | }	g }
tt||	D ]\}}|\}}tjj|| j| ||i}tj|td}|tjj|j | j|f| j|ffD ]@\}}| D ],\}}|tjjkr>|d||| q>q.|
| q|tj|j|j|j| j||	|
dd q"|S )NzPrompt num mismatch: {} vs {}zInput num mismatch: {} vs {}zPrompt vars mismatch: {} vs {}rl   z{}_{})r   r   r_   )r"   r%   r&   ro   )r~   r   r   r"   rf   r1   r%   r&   minlenro   r0   r   rq   rr   r   r   r   rp   r   addZPROMPT_VARSr}   r   itemsrI   rs   ri   )r9   r/   Zlhs_resultsZrhs_resultsrB   Z	lhs_entryZ	rhs_entryZnum_output_rowsr   r   ro   ru   Zlhs_and_rhs_output_rowZlhs_output_rowZrhs_output_rowZrow_dataZ
output_rowrF   rowkvr   r   r   rA     s    

   	 	     zLLMCompareFunction._call_implr#   r   r3   rE   c                 C  s   | j tj||d | S rG   )r7   rI   r   Z!LLMCompareFnPostProcessAddCommandrJ   r   r   r   r     s     z2LLMCompareFunction.add_compare_post_process_add_fn)NN)
r(   r)   r*   rN   r:   ri   r>   rA   r   rv   r   r   r\   r   rw   /  s   
  ,Zrw   )#rN   
__future__r   rO   Zdataclassestypingr   r   r   r   r   r   r	   Z google.generativeai.notebook.libr
   r   r   r   r   r   rW   r   ZLLMFnOutputRowViewZ	CompareFnr   r   Z	dataclassr    r2   ZLLMFunctionInputsrC   ABCMetar3   rR   rw   r   r   r   r   <module>   s>   $	
"

Kn