U
    ·ÜŸjØ‰  ã                   @  sP  U 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	 d dl
mZ ddlmZ G dd„ de	ƒZed	d
d�Zdddœdd„Zddddœdd„Zddgfddddœdd„Zd^ddddœdd„Zddgfddddœdd„Zdddœdd „Zdddœd!d"„Zdddœd#d$„Zdddœd%d&„Zdddœd'd(„Zdddœd)d*„Zdd+d,d-œd.d/„Zddgfddd0d1œd2d3„Zdddœd4d5„Zd	dd	d6œd7d8„Zdd9d9d:œd;d<„Z ddd9d=d>œd?d@„Z!ddAdœdBdC„Z"dd9ddDœdEdF„Z#ddGdœdHdI„Z$ddd9d9dAdJœdKdL„Z%dddœdMdN„Z&d_d+dddPœdQdR„Z'dSZ(dTe)dU< dVdWœdXdY„Z*ddd,dVd9dZdAd[œd\d]„Z+dS )`é    )ÚannotationsN)ÚAnyÚTypeVarÚCallableÚOptionalÚ
NamedTuple)Ú	TypeAliasé   )Úpandasc                   @  s^   e Zd ZU 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S )ÚRemediationÚstrÚnameNzOptional[str]Úimmediate_msgÚnecessary_msgzOptional[Callable[[Any], Any]]Únecessary_fnÚoptional_msgÚoptional_fnÚ	error_msg)
Ú__name__Ú
__module__Ú__qualname__Ú__annotations__r   r   r   r   r   r   © r   r   ú:/tmp/pip-unpacked-wheel-2qj3ofc_/openai/lib/_validators.pyr      s   
r   ÚOptionalDataFrameTzOptional[pd.DataFrame])Úboundúpd.DataFrame©ÚdfÚreturnc                 C  s8   d}t | ƒ|krdnd}dt | ƒ› d|› �}td|d�S )z’
    This validator will only print out the number of examples and recommend to the user to increase the number of examples if less than 100.
    éd   Ú z§. In general, we recommend having at least a few hundred examples. We've found that performance tends to linearly increase for every doubling of the number of examplesz
- Your file contains z prompt-completion pairsÚnum_examples©r   r   )Úlenr   )r   ZMIN_EXAMPLESZoptional_suggestionr   r   r   r   Únum_examples_validator   s    
ÿýr%   r   )r   Únecessary_columnr   c                   s’   ddddœdd„‰ d}d}d}d}ˆ| j kr€ˆdd„ | j D ƒkrtddd	œ‡ ‡fd
d„}|}dˆ› d�}dˆ› d�}ndˆ› d�}td||||d�S )z[
    This validator will ensure that the necessary column is present in the dataframe.
    r   r   ©r   Úcolumnr   c                   s2   ‡ fdd„| j D ƒ}| j|d ˆ  ¡ idd� | S )Nc                   s    g | ]}t |ƒ ¡ ˆ kr|‘qS r   ©r   Úlower©Ú.0Úc©r(   r   r   Ú
<listcomp>-   s      zInecessary_column_validator.<locals>.lower_case_column.<locals>.<listcomp>r   T)ÚcolumnsZinplace)r0   Úrenamer*   )r   r(   Úcolsr   r.   r   Úlower_case_column,   s    z5necessary_column_validator.<locals>.lower_case_columnNc                 S  s   g | ]}t |ƒ ¡ ‘qS r   r)   r+   r   r   r   r/   7   s     z.necessary_column_validator.<locals>.<listcomp>r   c                   s
   ˆ | ˆƒS ©Nr   )r   ©r3   r&   r   r   Úlower_case_column_creator9   s    z=necessary_column_validator.<locals>.lower_case_column_creatorz
- The `z ` column/key should be lowercasezLower case column name to `ú`z^` column/key is missing. Please make sure you name your columns/keys appropriately, then retryr&   )r   r   r   r   r   )r0   r   )r   r&   r   r   r   r   r6   r   r5   r   Únecessary_column_validator'   s&    
ûr8   ÚpromptÚ
completionz	list[str])r   Úfieldsr   c                   s°   g }d}d}d}t | jƒdkr ‡fdd„| jD ƒ}d}|D ]8‰ ‡ fdd„|D ƒ}t |ƒdkr:|dˆ › d	ˆ › d
�7 }q:d|› |› �}d|› �}dddœ‡fdd„}td|||d�S )zK
    This validator will remove additional columns from the dataframe.
    Nr	   c                   s   g | ]}|ˆ kr|‘qS r   r   r+   ©r;   r   r   r/   U   s      z/additional_column_validator.<locals>.<listcomp>r!   c                   s   g | ]}ˆ |kr|‘qS r   r   r+   )Úacr   r   r/   X   s      r   z9
  WARNING: Some of the additional columns/keys contain `z<` in their name. These will be ignored, and the column/key `z`` will be used instead. This could also result from a duplicate column/key in the provided file.zh
- The input file should contain exactly two columns/keys per row. Additional columns/keys present are: z Remove additional columns/keys: r   ©Úxr   c                   s   | ˆ  S r4   r   ©r?   r<   r   r   r   ^   s    z1additional_column_validator.<locals>.necessary_fnZadditional_column©r   r   r   r   )r$   r0   r   )r   r;   Zadditional_columnsr   r   r   Úwarn_messageZdupsr   )r=   r;   r   Úadditional_column_validatorK   s(    
ürC   )r   Úfieldr   c                   s¬   d}d}d}| ˆ    dd„ ¡ ¡ s2| ˆ   ¡  ¡ r–| ˆ  dk| ˆ   ¡ B }|  ¡ j|  ¡ }dˆ › d|› �}dddœ‡ fd	d
„}dt|ƒ› dˆ › d�}tdˆ › �|||d�S )zA
    This validator will ensure that no completion is empty.
    Nc                 S  s   | dkS )Nr!   r   r@   r   r   r   Ú<lambda>q   ó    z+non_empty_field_validator.<locals>.<lambda>r!   z
- `z?` column/key should not contain empty strings. These are rows: r   r>   c                   s   | | ˆ  dk j ˆ gd�S )Nr!   ©Zsubset)Zdropnar@   ©rD   r   r   r   v   s    z/non_empty_field_validator.<locals>.necessary_fnúRemove z rows with empty ÚsZempty_rA   )ÚapplyÚanyZisnullÚreset_indexÚindexÚtolistr$   r   )r   rD   r   r   r   Z
empty_rowsZempty_indexesr   rH   r   Únon_empty_field_validatori   s    &ürP   c                   sŠ   | j ˆ d�}|  ¡ j|  ¡ }d}d}d}t|ƒdkrzdt|ƒ› dd ˆ ¡› d|› �}dt|ƒ› d	�}d
d
dœ‡ fdd„}td|||d�S )zY
    This validator will suggest to the user to remove duplicate rows if they exist.
    rG   Nr   ú
- There are z duplicated ú-z sets. These are rows: rI   z duplicate rowsr   r>   c                   s   | j ˆ d�S )NrG   )Zdrop_duplicatesr@   r<   r   r   r   ‘   s    z.duplicated_rows_validator.<locals>.optional_fnÚduplicated_rows©r   r   r   r   )Z
duplicatedrM   rN   rO   r$   Újoinr   )r   r;   rS   Zduplicated_indexesr   r   r   r   r<   r   Úduplicated_rows_validatorƒ   s     ürV   c                   sŒ   d}d}d}t | ƒ}|dkr|dddœdd„‰ ˆ | ƒ‰tˆƒdkr|d	tˆƒ› d
ˆ› d�}dtˆƒ› d�}dddœ‡ ‡fdd„}td|||d�S )zW
    This validator will suggest to the user to remove examples that are too long.
    Núopen-ended generationr   r   )Údr   c                 S  s$   | j dd„ dd�}|  ¡ j|  ¡ S )Nc                 S  s   t | jƒt | jƒ dkS )Ni'  )r$   r9   r:   r@   r   r   r   rE   ¨   rF   zClong_examples_validator.<locals>.get_long_indexes.<locals>.<lambda>é   )Zaxis)rK   rM   rN   rO   )rX   Úlong_examplesr   r   r   Úget_long_indexes§   s    z1long_examples_validator.<locals>.get_long_indexesr   rQ   z. examples that are very long. These are rows: zf
For conditional generation, and for classification the examples shouldn't be longer than 2048 tokens.rI   z long examplesr>   c                   s8   ˆ | ƒ}ˆ|kr.t j dt|ƒ› d|› d�¡ |  |¡S )NzeThe indices of the long examples has changed as a result of a previously applied recommendation.
The z? long examples to be dropped are now at the following indices: Ú
)ÚsysÚstdoutÚwriter$   Údrop)r?   Zlong_indexes_to_drop©r[   Zlong_indexesr   r   r   ±   s    ÿz,long_examples_validator.<locals>.optional_fnrZ   rT   )Úinfer_task_typer$   r   )r   r   r   r   Úft_typer   ra   r   Úlong_examples_validatorœ   s"    ürd   c                   s’  d}d}d}d}d‰ddddddg}|D ]@}|dkrH| j j d	¡ ¡ rHq(| j jj|d
d� ¡ r`q(|‰ qjq(ˆ d	d¡}t| ƒ}|dkr�tdd�S ddddœdd„‰ t| j dd�}	| j |	k ¡ rÖd|	› d�}td|d�S |	dk�rP|	 d	d¡}
d|
› d�}t	|	ƒdk�r|d|› d�7 }| j jdt	|	ƒ … jj|	d
d� ¡ �rT|d|	› d�7 }nd }|	dk�r€d!|› d"�}ddd#œ‡ ‡fd$d%„}td&||||d'�S )(zœ
    This validator will suggest to add a common suffix to the prompt if one doesn't already exist in case of classification or conditional generation.
    Nz


### =>

z ->z

###

z

===

z

---

z

===>

z

--->

r\   F©Úregexú\nrW   Úcommon_suffix©r   r   ©r?   Úsuffixr   c                 S  s   | d  |7  < | S ©Nr9   r   ©r?   rk   r   r   r   Ú
add_suffixâ   s    z2common_prompt_suffix_validator.<locals>.add_suffixrk   ©ÚxfixzAll prompts are identical: `zt`
Consider leaving the prompts blank if you want to do open-ended generation, otherwise ensure prompts are different©r   r   r!   z 
- All prompts end with suffix `r7   é
   úR. This suffix seems very long. Consider replacing with a shorter suffix, such as `z5
  WARNING: Some of your prompts contain the suffix `zZ` more than once. We strongly suggest that you review your prompts and add a unique suffixa”  
- Your data does not contain a common separator at the end of your prompts. Having a separator string appended to the end of the prompt makes it clearer to the fine-tuned model where the completion should begin. See https://platform.openai.com/docs/guides/fine-tuning/preparing-your-dataset for more detail and examples. If you intend to do open-ended generation, then you should leave the prompts emptyzAdd a suffix separator `z` to all promptsr>   c                   s
   ˆ | ˆƒS r4   r   r@   ©rn   Zsuggested_suffixr   r   r   ù   s    z3common_prompt_suffix_validator.<locals>.optional_fnÚcommon_completion_suffix©r   r   r   r   r   )
r9   r   ÚcontainsrL   Úreplacerb   r   Úget_common_xfixÚallr$   )r   r   r   r   r   Úsuffix_optionsÚsuffix_optionÚdisplay_suggested_suffixrc   rh   Úcommon_suffix_new_line_handledr   rt   r   Úcommon_prompt_suffix_validatorÁ   s^    ú

(
ûr   c                   s´   d}d}d}d}t | jdd�‰ ˆ dkr0tdd�S dddd	œd
d„‰| jˆ k ¡ rZtdd�S ˆ dkr¤dˆ › d�}|tˆ ƒk r¤|d7 }dˆ › d�}dddœ‡ ‡fdd„}td|||d�S )zd
    This validator will suggest to remove a common prefix from the prompt if a long one exist.
    é   NÚprefixro   r!   Úcommon_prefixri   r   )r?   r�   r   c                 S  s   | d j t|ƒd … | d< | S rl   ©r   r$   )r?   r�   r   r   r   Úremove_common_prefix  s    z<common_prompt_prefix_validator.<locals>.remove_common_prefixz"
- All prompts start with prefix `r7   zÒ. Fine-tuning doesn't require the instruction specifying the task, or a few-shot example scenario. Most of the time you should only add the input data into the prompt, and the desired output into the completionúRemove prefix `z` from all promptsr>   c                   s
   ˆ| ˆ ƒS r4   r   r@   ©r‚   r„   r   r   r   !  s    z3common_prompt_prefix_validator.<locals>.optional_fnZcommon_prompt_prefixrT   )ry   r9   r   rz   r$   ©r   ZMAX_PREFIX_LENr   r   r   r   r†   r   Úcommon_prompt_prefix_validator  s,    

ürˆ   c                   s¬   d}t | jdd�‰ tˆ ƒdko(ˆ d dk‰tˆ ƒ|k r@tdd�S ddddd	œd
d„‰| jˆ k ¡ rltdd�S dˆ › d�}dˆ › d�}dddœ‡ ‡‡fdd„}td|||d�S )zh
    This validator will suggest to remove a common prefix from the completion if a long one exist.
    é   r�   ro   r   ú r‚   ri   r   )r?   r�   Ú	ws_prefixr   c                 S  s4   | d j t|ƒd … | d< |r0d| d › �| d< | S )Nr:   rŠ   rƒ   )r?   r�   r‹   r   r   r   r„   7  s    z@common_completion_prefix_validator.<locals>.remove_common_prefixz&
- All completions start with prefix `z_`. Most of the time you should only add the output data into the completion, without any prefixr…   z` from all completionsr>   c                   s   ˆ| ˆ ˆƒS r4   r   r@   ©r‚   r„   r‹   r   r   r   E  s    z7common_completion_prefix_validator.<locals>.optional_fnZcommon_completion_prefixrT   )ry   r:   r$   r   rz   r‡   r   rŒ   r   Ú"common_completion_prefix_validator,  s"    

ür�   c              	     sŠ  d}d}d}d}t | ƒ}|dks(|dkr2tdd�S t| jdd�}| j|k ¡ rld|› d	|› d
�}td|d�S d‰dddddddddg	}|D ]$}| jjj|dd� ¡ r¦qŠ|‰ q°qŠˆ dd¡}	ddddœdd„‰ |dk�rH| dd¡}
d|
› d
�}t	|ƒdk�r|d |	› d
�7 }| jjdt	|ƒ … jj|dd� ¡ �rL|d!|› d"�7 }nd#}|dk�rxd$|	› d%�}ddd&œ‡ ‡fd'd(„}td)||||d*�S )+z 
    This validator will suggest to add a common suffix to the completion if one doesn't already exist in case of classification or conditional generation.
    NrW   Úclassificationrh   ri   rk   ro   z All completions are identical: `zJ`
Ensure completions are different, otherwise the model will just repeat `r7   rq   z [END]r\   Ú.z ENDz***z+++z&&&z$$$z@@@z%%%Fre   rg   r   rj   c                 S  s   | d  |7  < | S ©Nr:   r   rm   r   r   r   rn   v  s    z6common_completion_suffix_validator.<locals>.add_suffixr!   z$
- All completions end with suffix `rr   rs   z9
  WARNING: Some of your completions contain the suffix `zU` more than once. We suggest that you review your completions and add a unique endingaH  
- Your data does not contain a common ending at the end of your completions. Having a common ending string appended to the end of the completion makes it clearer to the fine-tuned model where the completion should end. See https://platform.openai.com/docs/guides/fine-tuning/preparing-your-dataset for more detail and examples.zAdd a suffix ending `z` to all completionsr>   c                   s
   ˆ | ˆƒS r4   r   r@   rt   r   r   r   ˆ  s    z7common_completion_suffix_validator.<locals>.optional_fnru   rv   )
rb   r   ry   r:   rz   r   rw   rL   rx   r$   )r   r   r   r   r   rc   rh   r{   r|   r}   r~   r   rt   r   Ú"common_completion_suffix_validatorP  s^    
÷
(
ûr‘   c                 C  sd   dddœdd„}d}d}d}| j jdd…  ¡ dksH| j jd d dkrTd	}d
}|}td|||d�S )zŽ
    This validator will suggest to add a space at the start of the completion if it doesn't already exist. This helps with tokenization.
    r   r>   c                 S  s   | d   dd„ ¡| d< | S )Nr:   c                 S  s   |   d¡rdnd|  S )NrŠ   r!   )Ú
startswith)rJ   r   r   r   rE   š  rF   zLcompletions_space_start_validator.<locals>.add_space_start.<locals>.<lambda>)rK   r@   r   r   r   Úadd_space_start™  s    z:completions_space_start_validator.<locals>.add_space_startNrY   r   rŠ   zæ
- The completion should start with a whitespace character (` `). This tends to produce better results due to the tokenization we use. See https://platform.openai.com/docs/guides/fine-tuning/preparing-your-dataset for more detailsz=Add a whitespace character to the beginning of the completionZcompletion_space_startrT   )r:   r   ÚnuniqueÚvaluesr   )r   r“   r   r   r   r   r   r   Ú!completions_space_start_validator”  s    ,ür–   r   zRemediation | Noner'   c                   sv   dddœ‡ fdd„}| ˆ    dd„ ¡ ¡ }| ˆ    dd„ ¡ ¡ }|d |krrtd	d
ˆ › dˆ › d�dˆ › d�|d�S dS )zt
    This validator will suggest to lowercase the column values, if more than a third of letters are uppercase.
    r   r>   c                   s   | ˆ  j  ¡ | ˆ < | S r4   r)   r@   r.   r   r   Ú
lower_case²  s    z(lower_case_validator.<locals>.lower_casec                 S  s   t dd„ | D ƒƒS )Nc                 s  s"   | ]}|  ¡ r| ¡ rd V  qdS ©rY   N)ÚisalphaÚisupperr+   r   r   r   Ú	<genexpr>¶  s       ú9lower_case_validator.<locals>.<lambda>.<locals>.<genexpr>©Úsumr@   r   r   r   rE   ¶  rF   z&lower_case_validator.<locals>.<lambda>c                 S  s   t dd„ | D ƒƒS )Nc                 s  s"   | ]}|  ¡ r| ¡ rd V  qdS r˜   )r™   Úislowerr+   r   r   r   r›   ·  s       rœ   r�   r@   r   r   r   rE   ·  rF   r	   r—   z
- More than a third of your `z%` column/key is uppercase. Uppercase z÷s tends to perform worse than a mixture of case encountered in normal language. We recommend to lower case the data if that makes sense in your domain. See https://platform.openai.com/docs/guides/fine-tuning/preparing-your-dataset for more detailsz'Lowercase all your data in column/key `r7   rT   N)rK   rž   r   )r   r(   r—   Zcount_upperZcount_lowerr   r.   r   Úlower_case_validator­  s    
ür    z'tuple[pd.DataFrame | None, Remediation])Úfnamer;   r   c              
   C  sÆ  d}d}d}d}d}t j | ¡�r¢�z6|  ¡  d¡sB|  ¡  d¡rŽ|  ¡  d¡rTdnd\}}d|› d�}d|› d	�}tj| |td
� d¡}�nÊ|  ¡  d¡ràd}d}t 	| ¡}	|	j
}
t|
ƒdkrÈ|d7 }tj| td� d¡}�nx|  ¡  d¡�r@d}d}t| dƒ�4}| ¡ }tjdd„ | d¡D ƒ|td� d¡}W 5 Q R X �n|  ¡  d¡�r”tj| dtd� d¡}t|ƒdk�rXd}d}tj| td� d¡}n nÄ|  ¡  d¡�rzFtj| dtd� d¡}t|ƒdk�ràtj| td� d¡}nd }d}W n* tk
�r   tj| td� d¡}Y nX n@d!}d"| k�rH|d#| › d$|  d"¡d% › d&�7 }n|d#| › d'�7 }W nD ttfk
�rž   |  d"¡d%  ¡ }d(| › d)|› d*|› d+�}Y nX nd,| › d-�}td.|||d/�}||fS )0zÕ
    This function will read a file saved in .csv, .json, .txt, .xlsx or .tsv format using pandas.
     - for .xlsx it will read the first sheet
     - for .txt it will assume completions and split on newline
    Nz.csvz.tsv)ZCSVú,)ZTSVú	z=
- Based on your file extension, your file is formatted as a z filezYour format `z` will be converted to `JSONL`)ÚsepÚdtyper!   z.xlsxzH
- Based on your file extension, your file is formatted as an Excel filez/Your format `XLSX` will be converted to `JSONL`rY   z¥
- Your Excel file contains more than one sheet. Please either save as csv or ensure all data is present in the first sheet. WARNING: Reading only the first sheet...)r¥   z.txtz9
- Based on your file extension, you provided a text filez.Your format `TXT` will be converted to `JSONL`Úrc                 S  s   g | ]}d |g‘qS )r!   r   )r,   Úliner   r   r   r/   è  s     z#read_any_format.<locals>.<listcomp>r\   )r0   r¥   ú.jsonlT)Úlinesr¥   z^
- Your JSONL file appears to be in a JSON format. Your file will be converted to JSONL formatz/Your format `JSON` will be converted to `JSONL`z.jsonz^
- Your JSON file appears to be in a JSONL format. Your file will be converted to JSONL formatz]Your file must have one of the following extensions: .CSV, .TSV, .XLSX, .TXT, .JSON or .JSONLr�   z Your file `z` ends with the extension `.éÿÿÿÿz` which is not supported.z` is missing a file extension.zYour file `z!` does not appear to be in valid z9 format. Please ensure your file is formatted as a valid z file.zFile z does not exist.Úread_any_format)r   r   r   r   )ÚosÚpathÚisfiler*   ÚendswithÚpdZread_csvr   ZfillnaZ	ExcelFileZsheet_namesr$   Z
read_excelÚopenÚreadZ	DataFrameÚsplitÚ	read_jsonÚ
ValueErrorÚ	TypeErrorÚupperr   )r¡   r;   Úremediationr   r   r   r   Zfile_extension_strÚ	separatorZxlsZsheetsÚfÚcontentr   r   r   r«   Ã  s‚    
ÿ
ýüÿ
" ür«   c                 C  s,   t | ƒ}d}|dkr d|› d�}td|d�S )zÓ
    This validator will infer the likely fine-tuning format of the data, and display it to the user if it is classification.
    It will also suggest to use ada and explain train/validation split benefits.
    NrŽ   zK
- Based on your data it seems like you're trying to fine-tune a model for zã
- For classification, we recommend you try one of the faster and cheaper models, such as `ada`
- For classification, you can estimate the expected model performance by keeping a held out dataset, which is not used for trainingr"   r#   )rb   r   )r   rc   r   r   r   r   Úformat_inferrer_validator  s
    r¼   )r   r¸   r   c                 C  sb   |j dk	r2tj d|j› d|j › d�¡ t d¡ |jdk	rJtj |j¡ |jdk	r^| | ¡} | S )zs
    This function will apply a necessary remediation to a dataframe, or print an error message if one exists.
    Nz

ERROR in z validator: z

Aborting...rY   )	r   r]   Ústderrr_   r   Úexitr   r^   r   )r   r¸   r   r   r   Úapply_necessary_remediation(  s    




r¿   Úbool)Ú
input_textÚauto_acceptr   c                 C  s.   t j | ¡ |r t j d¡ dS tƒ  ¡ dkS )NzY
TÚn)r]   r^   r_   Úinputr*   )rÁ   rÂ   r   r   r   Úaccept_suggestion6  s
    rÅ   ztuple[pd.DataFrame, bool])r   r¸   rÂ   r   c                 C  sj   d}d|j › d�}|j dk	rBt||ƒrB|jdk	s4t‚| | ¡} d}|jdk	rbtj d|j› d�¡ | |fS )zc
    This function will apply an optional remediation to a dataframe, based on the user input.
    Fz- [Recommended] z [Y/n]: NTz- [Necessary] r\   )r   rÅ   r   ÚAssertionErrorr   r]   r^   r_   )r   r¸   rÂ   Úoptional_appliedrÁ   r   r   r   Úapply_optional_remediation>  s    



rÈ   ÚNonec                 C  sr   t | ƒ}d}|dkr&t| ƒ}|d }n| jdd� ¡ }|d }ddd	œd
d„}||d ƒ}tj d|› d�¡ dS )z?
    Estimate the time it'll take to fine-tune the dataset
    g      ð?rŽ   g
×£p=
÷?T)rN   g‘í|?5^ª?Úfloatr   )Útimer   c                 S  sh   | dk rt | dƒ› d�S | dk r4t | d dƒ› d�S | dk rPt | d dƒ› d�S t | d dƒ› d�S d S )	Né<   r	   z secondsi  z minutesi€Q z hoursz days)Úround)rË   r   r   r   Úformat_time]  s    z.estimate_fine_tuning_time.<locals>.format_timeéŒ   z:Once your model starts training, it'll approximately take z~ to train a `curie` model, and less for `ada` and `babbage`. Queue will approximately take half an hour per job ahead of you.
N)rb   r$   Zmemory_usagerž   r]   r^   r_   )r   Ú	ft_formatZexpected_timer"   ÚsizerÎ   Útime_stringr   r   r   Úestimate_fine_tuning_timeP  s    


ÿrÓ   )r¡   r³   r   c                   sf   |rddgndg}d}|dkr*d|› d�nd‰‡ ‡fdd„|D ƒ}t d	d
„ |D ƒƒsX|S |d7 }qd S )NZ_trainÚ_validr!   r   z (ú)c                   s,   g | ]$}t j ˆ ¡d  › d|› ˆ› d�‘qS )r   Z	_preparedr¨   )r¬   r­   Úsplitext)r,   rk   ©r¡   Zindex_suffixr   r   r/   r  s     z!get_outfnames.<locals>.<listcomp>c                 s  s   | ]}t j |¡V  qd S r4   )r¬   r­   r®   )r,   rº   r   r   r   r›   s  s     z get_outfnames.<locals>.<genexpr>rY   )rL   )r¡   r³   ÚsuffixesÚiZcandidate_fnamesr   r×   r   Úget_outfnamesm  s    rÚ   ztuple[int, object]c                 C  s.   | j  ¡ }d }|dkr&| j  ¡ jd }||fS )Nr	   r   )r:   r”   Zvalue_countsrN   )r   Ú	n_classesÚ	pos_classr   r   r   Úget_classification_hyperparamsx  s
    
rÝ   )r   r¡   Úany_remediationsrÂ   r   c                 C  sŠ  t | ƒ}t| jdd�}t| jdd�}d}d}|dkrBt||ƒrBd}d}	| dd	¡}
| dd	¡}t|ƒd
krvd|› d�nd}d}|s¸|s¸tj 	d|› d|	› d|
› d|› d�	¡ t
| ƒ �nÎt||ƒ�rzt||ƒ}|�r¸t|ƒdkrød|d
 krød|d ksüt‚d}tt| ƒ| tt| ƒd ƒƒ}| j|dd�}|  |j¡}|ddg j|d
 ddddd� |ddg j|d ddddd� t| ƒ\}}|	d7 }	|dk�r¨|	d |› d�7 }	n|	d!|› �7 }	n2t|ƒdk�sÊt‚| ddg j|d
 ddddd� |�rôd"ndd# d$ |¡ }|�rd%|d › d�nd}t|
ƒd
k�r2dn
d&|
› d�}tj 	d'|› d(|d
 › d|› |	› d)|› |› d�¡ t
| ƒ ntj 	d*¡ dS )+aQ  
    This function will write out a dataframe to a file, if the user would like to proceed, and also offer a fine-tuning command with the newly created file.
    For classification it will optionally ask the user if they would like to split the data into train/valid files, and modify the suggested command to include the valid set.
    rk   ro   FzQ- [Recommended] Would you like to split into training and validation set? [Y/n]: rŽ   Tr!   r\   rg   r   z Make sure to include `stop=["z;"]` so that the generated texts ends at the expected place.z@

Your data will be written to a new JSONL file. Proceed [Y/n]: zK
You can use your file for fine-tuning:
> openai api fine_tunes.create -t "ú"ue   

After youâ€™ve fine-tuned a model, remember that your prompt has to end with the indicator string `zX` for the model to start generating completions, rather than continuing with the prompt.r	   ZtrainÚvalidrY   iè  gš™™™™™é?é*   )rÃ   Zrandom_stater9   r:   ÚrecordsN)r©   ZorientZforce_asciiÚindentz! --compute_classification_metricsz" --classification_positive_class "z --classification_n_classes rJ   z to `z` and `z -v "uc   After youâ€™ve fine-tuned a model, remember that your prompt has to end with the indicator string `z
Wrote modified filezd`
Feel free to take a look!

Now use that file when fine-tuning:
> openai api fine_tunes.create -t "z

z#Aborting... did not write the file
)rb   ry   r9   r:   rÅ   rx   r$   r]   r^   r_   rÓ   rÚ   rÆ   ÚmaxÚintÚsampler`   rN   Zto_jsonrÝ   rU   )r   r¡   rÞ   rÂ   rÐ   Zcommon_prompt_suffixru   r³   rÁ   Zadditional_paramsZ%common_prompt_suffix_new_line_handledZ)common_completion_suffix_new_line_handledZoptional_ending_stringÚfnamesZMAX_VALID_EXAMPLESZn_trainZdf_trainZdf_validrÛ   rÜ   Zfiles_stringZvalid_stringZseparator_reminderr   r   r   Úwrite_out_file€  s†    

ÿýÿ
(    ÿ    ÿ
    ÿ
ÿ
ý(ÿ
rè   c                 C  s>   d}t | jj ¡ ƒdkrdS t| j ¡ ƒt| ƒ| k r:dS dS )z>
    Infer the likely fine-tuning task type from the data
    é   r   rW   rŽ   zconditional generation)rž   r9   r   r$   r:   Úunique)r   ZCLASSIFICATION_THRESHOLDr   r   r   rb   Ë  s    rb   rk   )Úseriesrp   r   c                 C  sl   d}|dkr$| j t|ƒd  d… n| j dt|ƒd … }| ¡ dkrJqhq||jd kr\qhq|jd }q|S )zQ
    Finds the longest common suffix or prefix of all the values in a series
    r!   rk   rY   Nr   )r   r$   r”   r•   )rë   rp   Zcommon_xfixZcommon_xfixesr   r   r   ry   Ù  s    4ÿry   z,Callable[[pd.DataFrame], Remediation | None]r   Ú	Validatorzlist[Validator])r   c                   C  s2   t dd„ dd„ tttttdd„ dd„ tttt	t
gS )Nc                 S  s
   t | dƒS rl   ©r8   r@   r   r   r   rE   ñ  rF   z get_validators.<locals>.<lambda>c                 S  s
   t | dƒS r�   rí   r@   r   r   r   rE   ò  rF   c                 S  s
   t | dƒS rl   ©r    r@   r   r   r   rE   ø  rF   c                 S  s
   t | dƒS r�   rî   r@   r   r   r   rE   ù  rF   )r%   rC   rP   r¼   rV   rd   r   rˆ   r�   r‘   r–   r   r   r   r   Úget_validatorsî  s     ñrï   zCallable[..., Any])r   r¡   r¸   Ú
validatorsrÂ   Úwrite_out_file_funcr   c                 C  sÆ   g }|d k	r|  |¡ |D ](}|| ƒ}|d k	r|  |¡ t| |ƒ} qtdd„ |D ƒƒ}tdd„ |D ƒƒ}	d}
|r tj d¡ |D ]}t| ||ƒ\} }|
pš|}
q€ntj d¡ |
p²|	}|| |||ƒ d S )Nc                 S  s$   g | ]}|j d k	s|jd k	r|‘qS r4   )r   r   ©r,   r¸   r   r   r   r/     s   
 
þz$apply_validators.<locals>.<listcomp>c                 S  s   g | ]}|j d k	r|‘qS r4   )r   rò   r   r   r   r/     s     
 Fz?

Based on the analysis we will perform the following actions:
z

No remediations found.
)Úappendr¿   rL   r]   r^   r_   rÈ   )r   r¡   r¸   rð   rÂ   rñ   Zoptional_remediationsZ	validatorZ&any_optional_or_necessary_remediationsZany_necessary_appliedZany_optional_appliedrÇ   Z!any_optional_or_necessary_appliedr   r   r   Úapply_validators  s2    

þÿÿrô   )r:   )rk   ),Ú
__future__r   r¬   r]   Útypingr   r   r   r   r   Útyping_extensionsr   Z_extrasr
   r°   r   r   r%   r8   rC   rP   rV   rd   r   rˆ   r�   r‘   r–   r    r«   r¼   r¿   rÅ   rÈ   rÓ   rÚ   rÝ   rè   rb   ry   rì   r   rï   rô   r   r   r   r   Ú<module>   sF    
$%D'$DÿYK