
    hh#                        d dl Z d dlmZ d dlmZmZmZmZmZm	Z	m
Z
mZmZmZ d dlmZ d dlZd dl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mZmZm Z m!Z! d d
l"m#Z# d dl$m%Z%m&Z& d dl'm(Z( d dl)m*Z*m+Z+ d dl,m-Z-m.Z. d dl/m0Z0 d dl1m2Z2 d dl3m4Z4 d dl5m6Z6 d dl7m8Z8m9Z9  e j:        e j;        dd            e j<        e=          Z>dede?fdZ@dee         deeeAef                  fdZBdejC        dee          fdZD G d de          ZEdS )     N)
itemgetter)
AnyCallableDictListLiteralOptionalSequenceTypeUnioncast)uuid4)	AIMessageChatGeneration
ChatResultHumanMessage)CallbackManagerForLLMRun)LanguageModelInput)BaseChatModel)AIMessageChunkBaseMessageSystemMessageToolCallToolMessage)	tool_call)JsonOutputParserPydanticOutputParser)OutputParserLike)JsonOutputKeyToolsParserPydanticToolsParser)RunnableRunnablePassthrough)RunnableMap)BaseToolconvert_to_openai_tool)is_basemodel_subclass)	BaseModelFieldz)%(asctime)s - %(levelname)s - %(message)sz%Y-%m-%d %H:%M:%S)levelformatdatefmtobjreturnc                 J    t          | t                    ot          |           S N)
isinstancetyper'   )r-   s    q/var/www/FlaskApp/flask-venv/lib/python3.11/site-packages/langchain_community/chat_models/cloudflare_workersai.py_is_pydantic_classr4   7   s     c4  ?%:3%?%??    messagesc                    g }| D ]}dt          |j        t                    r|j        ndd}t          |t                    rd|d<   nwt          |t                    r#d|d<   |j        rd |j        D             }||d<   n?t          |t                    rd|d<   n$t          |t                    rd	|d<   |j        |d
<   |	                    |           |S )z;Convert LangChain messages to Cloudflare Workers AI format. )rolecontentuserr9   	assistantc                 0    g | ]}|d          |d         dS )nameargs)r>   	arguments ).0r   s     r3   
<listcomp>z<_convert_messages_to_cloudflare_messages.<locals>.<listcomp>O   s:       ! 'v.Yv=NOO  r5   
tool_callssystemtooltool_call_id)
r1   r:   strr   r   rD   r   r   rG   append)r6   cloudflare_messagesmessagemsgrD   s        r3   (_convert_messages_to_cloudflare_messagesrM   ;   s     ( ( *4W_c*J*JRwPR
 
 g|,, 	 CKK++ 	%CK! / %,%7  
 %/L!// 	"CKK-- 	 CK$ 
 	""3''''r5   responsec           	         g }d|                                  d         v rm|                                  d         d         D ]L}|                    t          t          t	                                |d         |d                              M|S )z$Get tool calls from ollama response.rD   resultr>   r@   )idr>   r?   )jsonrI   r   rH   r   )rN   rD   tcs      r3   _get_tool_calls_from_responserT   b   s    Jx}}x000--//(+L9 	 	B577||FK      r5   c                       e Zd ZU dZ ed          Zeed<    ed          Zeed<    ed          Z	eed<   dZ
eed<   dZeed<   d	Zeed
<   dZeed<   deddf fdZ	 	 d dee         deee                  dee         dedef
dZdeeeeef         eedef         ef                  dedeeef         f fdZddddeeee         f         de dee!d                  dedeeeeef         f         f
dZ"e#defd            Z$ xZ%S )!ChatCloudflareWorkersAIz+Custom chat model for Cloudflare Workers AI.
account_id	api_tokenmodelr8   
ai_gatewayurlz-https://api.cloudflare.com/client/v4/accountsbase_urlz$https://gateway.ai.cloudflare.com/v1gateway_urlkwargsr.   Nc                      t                      j        di | | j        r(| j         d| j         d| j         d| j         | _        dS | j         d| j         d| j         | _        dS )z&Initialize with necessary credentials./z/workers-ai/run/z/ai/run/NrA   )super__init__rZ   r]   rW   rY   r[   r\   )selfr^   	__class__s     r3   rb   z ChatCloudflareWorkersAI.__init__|   s    ""6"""? 	P# A Ado A A?A A48JA A HHH
 -OO$/OO4:OODHHHr5   r6   stoprun_managerc                    t          |          }dd| j         i}d                    d |D                       }|d|v r|d         nddd |                                D             }|d         't	          |d         t
                    s|d         g|d<   t                              d	|            t          j	        | j
        ||
          }	t          |	          }
t          t          |	                                          t          t           |
                    }t#          |          }t%          |g          S )z3Generate a response based on the messages provided.AuthorizationzBearer 
c              3      K   | ]<}d |d          d|d          d|v rd|d          ndz   d|v rd|d          ndz   V  =d	S )
zrole: r9   z, content: r:   rD   z	, tools: r8   rG   z, tool_call_id: NrA   )rB   rL   s     r3   	<genexpr>z4ChatCloudflareWorkersAI._generate.<locals>.<genexpr>   s       	
 	
  >S[==S^==2>#2E2E.3|,...2O "S(( 93~#6888	
 	
 	
 	
 	
 	
r5   toolsN)promptrl   c                 "    i | ]\  }}|d v	||S ))rl   rA   )rB   keyvalues      r3   
<dictcomp>z5ChatCloudflareWorkersAI._generate.<locals>.<dictcomp>   s(    SSSjc5c>R>RsE>R>R>Rr5   z)Sending prompt to Cloudflare Workers AI: )headersrR   )r:   rD   )rK   )generations)rM   rX   joinitemsr1   list_loggerinforequestspostr[   rT   r   rH   rR   r   r   r   r   )rc   r6   re   rf   r^   formatted_messagesrr   rm   datarN   rD   
ai_messagechat_generations                r3   	_generatez!ChatCloudflareWorkersAI._generate   sg    FhOO"$>dn$>$>? 	
 	
 *	
 	
 	
 	
 	
 (/6(9(9VG__t
 
 TSFLLNNSSS
 =$ZWt-L-L$!']ODMGGGHHH=7FFF28<<
((T.*5U5U
 
 

 )<<<&78888r5   rl   c                 R    d |D             } t                      j        dd|i|S )z'Bind tools for use in model generation.c                 ,    g | ]}t          |          S rA   r%   )rB   rF   s     r3   rC   z6ChatCloudflareWorkersAI.bind_tools.<locals>.<listcomp>   s!    JJJD1$77JJJr5   rl   rA   )ra   bind)rc   rl   r^   formatted_toolsrd   s       r3   
bind_toolsz"ChatCloudflareWorkersAI.bind_tools   s:     KJEJJJuww|<</<V<<<r5   Ffunction_calling)include_rawmethodschemar   r   )	json_moder   c                   |                     dd          }|rt          d|           t          |          }|dk    rd}|dk    rk|t          d          t          |          d         d         }|                     |g|	          }|rt          |gd
          }	ndt          |d
          }	nR|dk    r9|                     ddi          }|rt          |          nt                      }	nt          d| d          |rht          j        t          d          |	z  d           }
t          j        d           }|
                    |gd          }t          |          |z  S ||	z  S )zGModel wrapper that returns outputs formatted to match the given schema.strictNzReceived unsupported arguments json_schemar   zJschema must be specified when method is 'function_calling'. Received None.functionr>   )tool_choiceT)rl   first_tool_only)key_namer   r   r2   json_object)response_format)pydantic_objectz\Unrecognized method argument. Expected one of 'function_calling' or 'json_mode'. Received: ''rawc                     d S r0   rA   _s    r3   <lambda>z@ChatCloudflareWorkersAI.with_structured_output.<locals>.<lambda>   s    RV r5   )parsedparsing_errorc                     d S r0   rA   r   s    r3   r   z@ChatCloudflareWorkersAI.with_structured_output.<locals>.<lambda>   s    d r5   )r   r   )exception_key)r   )pop
ValueErrorr4   r&   r   r    r   r   r   r   r"   assignr   with_fallbacksr#   )rc   r   r   r   r^   r   is_pydantic_schema	tool_namellmoutput_parserparser_assignparser_noneparser_with_fallbacks                r3   with_structured_outputz.ChatCloudflareWorkersAI.with_structured_output   s     JJx&& 	IGvGGHHH/77]"" (F'''~ %   /v66zB6JI//6(	/BBC! 2E!($(3 3 3
 !9&! ! ! {""))V],C)DDC &($V<<<<%'' M 5+15 5 5  
  
	'/6!%((=8  M .4NNKKKK#0#?#?_ $@ $ $  3'''*>>>&&r5   c                     dS )z9Return the type of the LLM (for Langchain compatibility).zcloudflare-workers-airA   )rc   s    r3   	_llm_typez!ChatCloudflareWorkersAI._llm_type   s
     '&r5   )NN)&__name__
__module____qualname____doc__r)   rW   rH   __annotations__rX   rY   rZ   r[   r\   r]   r   rb   r   r   r	   r   r   r   r
   r   r   r   r   r$   r!   r   r   r(   boolr   r   propertyr   __classcell__)rd   s   @r3   rV   rV   q   sZ        55eCjjJ   U3ZZIssE3JCMMMCHcCCC=K===	P 	P 	P 	P 	P 	P 	P 	P %):>	)9 )9{#)9 tCy!)9 67	)9
 )9 
)9 )9 )9 )9V=d38ndHS#X4FPQR= = 
$k1	2	= = = = = = "EW:' :' :'dDO+,:' 	:'
 !@AB:' :' 
$eD)O&<<	=:' :' :' :'x '3 ' ' ' X' ' ' ' 'r5   rV   )Floggingoperatorr   typingr   r   r   r   r   r	   r
   r   r   r   uuidr   ry   langchain.schemar   r   r   r   langchain_core.callbacksr   langchain_core.language_modelsr   *langchain_core.language_models.chat_modelsr   langchain_core.messagesr   r   r   r   r   langchain_core.messages.toolr   langchain_core.output_parsersr   r   "langchain_core.output_parsers.baser   *langchain_core.output_parsers.openai_toolsr   r    langchain_core.runnablesr!   r"   langchain_core.runnables.baser#   langchain_core.toolsr$   %langchain_core.utils.function_callingr&   langchain_core.utils.pydanticr'   pydanticr(   r)   basicConfigINFO	getLoggerr   rw   r   r4   rH   rM   ResponserT   rV   rA   r5   r3   <module>r      sL                                        P P P P P P P P P P P P = = = = = = = = = = = = D D D D D D              3 2 2 2 2 2        @ ? ? ? ? ?        C B B B B B B B 5 5 5 5 5 5 ) ) ) ) ) ) H H H H H H ? ? ? ? ? ? % % % % % % % %  
,6   
 '
H
%
%@C @D @ @ @ @$;$	$sCx.$ $ $ $NH,= $x.    I' I' I' I' I'm I' I' I' I' I'r5   