
    ^hc!              
           S SK r S SKrS SKrS SKJrJrJrJr  S SKrS\	S\	S\
4S jrS\
S\
S	\	S\4S
 jrSS\	S\
S\	4S jjrS\	S\
S\
S\\\	   \
4   4S jrSS\\	   S\
S\S\	4S jjrS\	S\4S jrS\	S\\	   4S jrS\	S\\\	\	4      4S jrg)    N)AnyDictListTuplemodelstringreturnc                     S[         S[         4S jn [        R                  " U" U 5      5      n[        UR	                  U5      5      nU$ ! [
         a     gf = f)z.Returns the number of tokens in a text string.sr	   c                 R    U R                  SS5      n[        U5      S:  a  US   $ U $ )N/   )splitlen)r   partss     I/home/james-whalen/.local/lib/python3.13/site-packages/llm_utils/utils.pyextract_after_slash)count_tokens.<locals>.extract_after_slash   s*    Qu:>uQx0q0    r   )strtiktokenencoding_for_modelr   encodeKeyError)r   r   r   encoding
num_tokenss        r   count_tokensr   
   s[    1s 1s 1
../B5/IJ01
 s   7A 
AAnum_input_tokensnum_output_tokens
model_typec           	      t   0 SSSS._SSSS._SSSS._SSSS._SSSS._S	SS
S._SSS
S._SS
SS._SS
SS._SSSS._SSSS._SSSS._SSSS._SSSS._SSSS._SSSS._nUR                  U5      =n(       d(  [        SU SSR                  S U 5       5       S 35      eU S!-  US"   -  US!-  US#   -  -   $ )$a+  
Calculate the cost of processing a request based on model type.

Args:
    num_input_tokens (int): Number of input tokens.
    num_output_tokens (int): Number of output tokens.
    model_type (str): The type of GPT model used (model name).

Returns:
    The cost of processing the request, in USD.
zgpt-4-0125-preview
      )inputoutputzgpt-4-turbo-previewzgpt-4-1106-previewzgpt-4-vision-previewzgpt-4-1106-vision-previewzgpt-4<   z
gpt-4-0613z	gpt-4-32kx   zgpt-4-32k-0613zgpt-3.5-turbo-0125g      ?g      ?zgpt-3.5-turbozgpt-3.5-turbo-1106r      zgpt-3.5-turbo-instructzgpt-3.5-turbo-16k      zgpt-3.5-turbo-0613zgpt-3.5-turbo-16k-0613zUnknown model "z". Choose from: z, c              3   $   #    U  H  ov   M     g 7f)N ).0ms     r   	<genexpr>!calculate_cost.<locals>.<genexpr>C   s     CcOb!AObs   .i@B r$   r%   )get
ValueErrorjoin)r   r   r    PRICING_PER_MILLIONprice_per_millions        r   calculate_costr7      s    8b98 	r:8 	b9	8
 	" ;8 	$rR%@8 	2,8 	b18 	rS18 	B#68 	s;8 	3#68 	Q78  	!C1"=!8" 	qA6#8$ 	q9%8& 	!A";'8, "5!8!8!DDDj\)9$))CcObCc:c9ddef
 	

 	9$'8'AA
i
'*;H*E
E	Fr   textwidthc                 F   / n/ n/ nSnU R                  S5       H  nUR                  S5      (       aZ  U(       a%  UR                  U5        UR                  U5        / nOUR                  U5        U/nUR                  U5        U(       + nMs  UR                  U5        M     UR                  U5        UR                  U5        / n/ n[        [	        U5      5       H  n	X9   (       a&  UR                  X)   5        UR                  S5        M2  / nX)    HJ  nU(       d/  U(       a&  UR                  U5        UR                  S5        / nM7  M9  UR                  U5        ML     U(       d  M  UR                  U5        UR                  S5        / nM     UnUn[        [	        U5      5       H9  n	X9   (       a  M  X)    V
s/ s H  n
[
        R                  " X5      PM     sn
X)'   M;     SR                  U Vs/ s H  nSR                  U5      PM     sn5      $ s  sn
f s  snf )aw  
Wraps text except for code blocks for nice terminal formatting.

Splits the text into paragraphs and wraps each paragraph,
except for paragraphs that are inside of code blocks denoted
by ` ``` `. Returns the updated text.

Args:
    text (str): The text to wrap.
    width (int): The width of the lines to wrap at, passed to `textwrap.fill`.

Returns:
    The wrapped text.
F
z```T

)r   
startswithappendranger   textwrapfillr4   )r8   r9   blocksis_code_blockblockin_code_blocklinecopied_blockscopied_is_code_blockilbs               r   word_wrap_except_code_blocksrL   L   s     FMEM

4 ??5!!T"e$e$  / --MLL ! MM%' M3v;  + ''-E	%,,U3,33E: " 
 LL& " u$$U+$++E2#  $ F(M 3v;:@)D)Qq0)DFI  
 ;;f5f		!f566 E 6s   ? H7H	file_path
start_lineend_linec                 J   SnS[         S[        S[         4S jn[        U S5       nUR                  5       nU Vs/ s H  ot" UR	                  5       U5      PM     nnSSS5        [        SU5      n[        [        W5      U5      nXaS-
  U U4$ s  snf ! , (       d  f       N== f)	a  
Read lines from a file.

Args:
    file_path (str): The path of the file to read.
    start_line (int): The line number of the first line to include (1-indexed). Will be bounded below by 1.
    end_line (int): The line number of the last line to include (1-indexed). Will be bounded above by file's line count.

Returns:
    The lines read as an array and the number of the first line included.

Raises:
    FileNotFoundError: If the file does not exist.
   r   rJ   r	   c                 4    [        U 5      U:  a  U $ U SU S-   $ )zP
Truncate the string to at most the given length, adding ellipses if truncated.
Nz...)r   )r   rJ   s     r   truncateread_lines.<locals>.truncate   s$     q6A:HRa55= r   rNr   )r   intopen	readlinesrstripmaxminr   )rM   rN   rO   max_chars_per_linerS   flinesrF   s           r   
read_linesr_      s      !C !C !C ! 
i	INO$++-);<O 

 Q
#J3u:x(Hq.8,j99 P 
	s   B BBB
B"groupfirststripc                 
   U(       a  U (       aC  U S   R                  5       (       d+  U SS n US-  nU (       a  U S   R                  5       (       d  M+  U (       a>  U S   R                  5       (       d&  U SS n U (       a  U S   R                  5       (       d  M&  U[        U 5      -   S-
  n[        [        U5      5      nSR                  [	        U 5       VVs/ s H  u  pVSR                  X-   XF5      PM     snn5      nU$ s  snnf )a  
Add line numbers for each line in the input list.

Args:
    group (List[str]): The lines to number.
    first (int): The number for the first line.
    strip (bool): Whether to strip leading and trailing blank lines.

Returns:
    A string concatenation of the numbered lines.
r   r   Nr;   z{0:>{1}} {2})rb   r   r   r4   	enumerateformat)r`   ra   rb   lastmax_line_number_lengthrI   rF   results           r   number_group_of_linesrj      s     E!HNN,,!"IEQJE E!HNN,, E"IOO--#2JE E"IOO-- 3u:!D T^YY %U+	
+ !!%)-CJ+	
F M	
s    C?
	my_stringc                 ,   U R                  S5      nU R                  S5      S-   nUS:X  d  US:X  a  gXU nSn[        R                  " US U[        R                  S	9n [
        R                  " US
S9$ ! [
        R                   a
  n SnAgSnAff = f)z
Parses JSON if valid, replacing any triple quotes with single quotes.
Returns the parsed JSON blob if successful, None if not.
{}r   rd   r   Nz"""(.*?)"""c                 L    [         R                  " U R                  S5      5      $ )Nr   )jsondumpsr`   )r.   s    r   <lambda>%contains_valid_json.<locals>.<lambda>   s    4::aggaj1r   )flagsF)strict)findrfindresubDOTALLrp   loadsJSONDecodeError)rk   	start_posend_posjson_stringpatternprocessed_stringes          r   contains_valid_jsonr      s     s#Iooc"Q&G B'Q,g.KGvv1;biizz*599  	s    A5 5BBc                     Sn[         R                  " X[         R                  5      nU Vs/ s H  o3S   R                  5       PM     sn$ s  snf )Nz```(python)?(.*?)```r   )rx   findallrz   rb   )r8   r   rB   rD   s       r   extract_code_blocksr      s<    %GZZryy1F*01&!HNN&111s   Alogc                     U R                  S5      n/ nU HN  nUR                  5       (       d  M  UR                  SS5      tpEU(       a  US   OSnUR                  XFS.5        MP     U$ )Nr<   z: r   r    )rolecontent)r   rb   r>   )r   entriesri   entryr   r   content_strs          r   parse_chatlogr      sb    iiGF{{}}T1-$+gajt<=  Mr   )P   )T)rx   rp   r@   typingr   r   r   r   r   r   rV   r   floatr7   rL   r_   boolrj   r   r   r   r,   r   r   <module>r      s   	   ) )  S S "...1.?B.
.bB7s B73 B7 B7J#:# #:3 #:# #:%S	SVBW #:Lc 3 t s <3 3 :2c 2d3i 2	s 	tDcN3 	r   