
    AhJ                       S r SSKJr  SSKJrJrJr  SSKJr  SSK	J
r
Jr  SSKJr  SSKJr  SSKJr  SS	KJr  SS
KJr  SSKJr  SSKJr  SSKJr  SSKJr  \" SSSS9 " S S\5      5       r " S S\\\ \ 4      5      r!g)z+Base classes for LLM-powered router chains.    )annotations)AnyOptionalcast)
deprecated)AsyncCallbackManagerForChainRunCallbackManagerForChainRun)OutputParserException)BaseLanguageModel)BaseOutputParser)BasePromptTemplate)parse_and_check_json_markdown)model_validator)SelfLLMChain)RouterChainz0.2.12z1.0zUse RunnableLambda to select from multiple prompt templates. See example in API reference: https://api.python.langchain.com/en/latest/chains/langchain.chains.router.llm_router.LLMRouterChain.html)sinceremovalmessagec                     ^  \ rS rSr% SrS\S'    \" SS9SS j5       r\SS j5       r	SU 4S	 jjr
 S     SS
 jjr S     SS jjr\        SS j5       rSrU =r$ )LLMRouterChain   aB  A router chain that uses an LLM chain to perform routing.

This class is deprecated. See below for a replacement, which offers several
benefits, including streaming and batch support.

Below is an example implementation:

    .. code-block:: python

        from operator import itemgetter
        from typing import Literal
        from typing_extensions import TypedDict

        from langchain_core.output_parsers import StrOutputParser
        from langchain_core.prompts import ChatPromptTemplate
        from langchain_core.runnables import RunnableLambda, RunnablePassthrough
        from langchain_openai import ChatOpenAI

        llm = ChatOpenAI(model="gpt-4o-mini")

        prompt_1 = ChatPromptTemplate.from_messages(
            [
                ("system", "You are an expert on animals."),
                ("human", "{query}"),
            ]
        )
        prompt_2 = ChatPromptTemplate.from_messages(
            [
                ("system", "You are an expert on vegetables."),
                ("human", "{query}"),
            ]
        )

        chain_1 = prompt_1 | llm | StrOutputParser()
        chain_2 = prompt_2 | llm | StrOutputParser()

        route_system = "Route the user's query to either the animal or vegetable expert."
        route_prompt = ChatPromptTemplate.from_messages(
            [
                ("system", route_system),
                ("human", "{query}"),
            ]
        )


        class RouteQuery(TypedDict):
            """Route query to destination."""
            destination: Literal["animal", "vegetable"]


        route_chain = (
            route_prompt
            | llm.with_structured_output(RouteQuery)
            | itemgetter("destination")
        )

        chain = {
            "destination": route_chain,  # "animal" or "vegetable"
            "query": lambda x: x["query"],  # pass through input query
        } | RunnableLambda(
            # if animal, chain_1. otherwise, chain_2.
            lambda x: chain_1 if x["destination"] == "animal" else chain_2,
        )

        chain.invoke({"query": "what color are carrots"})
r   	llm_chainafter)modec                f    U R                   R                  nUR                  c  Sn[        U5      eU $ )NzLLMRouterChain requires base llm_chain prompt to have an output parser that converts LLM text output to a dictionary with keys 'destination' and 'next_inputs'. Received a prompt with no output parser.)r   promptoutput_parser
ValueError)selfr   msgs      Z/var/www/html/shao/venv/lib/python3.13/site-packages/langchain/chains/router/llm_router.pyvalidate_promptLLMRouterChain.validate_prompth   s8    &&'  S/!    c                .    U R                   R                  $ )zDWill be whatever keys the LLM chain prompt expects.

:meta private:
)r   
input_keys)r!   s    r#   r(   LLMRouterChain.input_keysu   s     ~~(((r&   c                `   > [         TU ]  U5        [        US   [        5      (       d  [        eg )Nnext_inputs)super_validate_outputs
isinstancedictr    )r!   outputs	__class__s     r#   r-    LLMRouterChain._validate_outputs}   s-    !'*'-0$77 8r&   c                .   U=(       d    [         R                  " 5       nUR                  5       nU R                  R                  " SSU0UD6n[        [        [        [        4   U R                  R                  R                  R                  U5      5      $ N	callbacks )r	   get_noop_manager	get_childr   predictr   r/   strr   r   r   parse)r!   inputsrun_manager_run_managerr5   
predictions         r#   _callLLMRouterChain._call   sx    
 #S&@&Q&Q&S **,	^^++JiJ6J
cNNN!!//55jA
 	
r&   c                   #    U=(       d    [         R                  " 5       nUR                  5       n[        [        [
        [        4   U R                  R                  " SSU0UD6I S h  vN 5      $  N7fr4   )	r	   r7   r8   r   r/   r:   r   r   apredict_and_parse)r!   r<   r=   r>   r5   s        r#   _acallLLMRouterChain._acall   sa     
 #S&@&Q&Q&S **,	cN..33RiR6RR
 	
Rs   A'A4)A2
*	A4c                (    [        XS9nU " SSU0UD6$ )zConvenience constructor.)llmr   r   r6   r   )clsrG   r   kwargsr   s        r#   from_llmLLMRouterChain.from_llm   s!     4	1Y1&11r&   r6   )returnr   )rL   z	list[str])r0   dict[str, Any]rL   None)N)r<   rM   r=   z$Optional[CallbackManagerForChainRun]rL   rM   )r<   rM   r=   z)Optional[AsyncCallbackManagerForChainRun]rL   rM   )rG   r   r   r   rI   r   rL   r   )__name__
__module____qualname____firstlineno____doc____annotations__r   r$   propertyr(   r-   r@   rD   classmethodrJ   __static_attributes____classcell__)r1   s   @r#   r   r      s    AF +'"
 #
 ) ) =A

 :
 
	
" BF



 ?

 
	

 22 #2 	2
 
2 2r&   r   c                  N    \ rS rSr% SrSrS\S'   \rS\S'   Sr	S\S	'   SS
 jr
Srg)RouterOutputParser   z<Parser for output of router chain in the multi-prompt chain.DEFAULTr:   default_destinationtypenext_inputs_typeinputnext_inputs_inner_keyc                    SS/n[        X5      n[        US   [        5      (       d  Sn[        U5      e[        US   U R                  5      (       d  SU R                   S3n[        U5      eU R
                  US   0US'   US   R                  5       R                  5       U R                  R                  5       :X  a  S US'   U$ US   R                  5       US'    U$ ! [         a  nSU SU 3n[        U5      UeS nAff = f)Ndestinationr+   z&Expected 'destination' to be a string.zExpected 'next_inputs' to be .zParsing text
z
 raised following error:
)r   r.   r:   	TypeErrorr_   ra   striplowerr]   	Exceptionr
   )r!   textexpected_keysparsedr"   es         r#   r;   RouterOutputParser.parse   s$   	4*M:M24GFf]3S99>n$f]3T5J5JKK5d6K6K5LANn$%)%?%?AV$WF=!}%++-335++1134 )-}% 	 )/}(=(C(C(E}%   	4"4&(DQCHC',!3	4s   CC  C   
D*C>>Dr6   N)ri   r:   rL   rM   )rO   rP   rQ   rR   rS   r]   rT   r:   r_   ra   r;   rW   r6   r&   r#   rZ   rZ      s+    F(( d !(3(r&   rZ   N)"rS   
__future__r   typingr   r   r   langchain_core._apir   langchain_core.callbacksr   r	   langchain_core.exceptionsr
   langchain_core.language_modelsr   langchain_core.output_parsersr   langchain_core.promptsr   langchain_core.utils.jsonr   pydanticr   typing_extensionsr   langchain.chainsr   langchain.chains.router.baser   r   r/   r:   rZ   r6   r&   r#   <module>r{      s    1 " & & * < < : 5 C $ " % 4 
	s	D2[ D2D2N)$sCx.9 r&   