
    hhO                    &   d Z ddlmZ 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mZ ddlmZ ddlmZ ddlmZ dd	lmZ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%m&Z&m'Z' ddl(m)Z) ddl*m+Z+m,Z, ddl-m.Z.m/Z/m0Z0 ddl1m2Z2m3Z3m4Z4 ddl5m6Z6m7Z7 ddl8m9Z9 ddl:m;Z;m<Z<m=Z=m>Z>m?Z? ddl@mAZA  ede;          ZBeeeCef         eeB         ef         ZDeeeBf         ZE ejF        eG          ZHd$dZId%dZJ eddd !           G d" d#e                      ZKdS )&zWrapper around Perplexity APIs.    )annotationsN)
itemgetter)AnyDictIteratorListLiteralMappingOptionalTupleTypeTypeVarUnion)
deprecated)CallbackManagerForLLMRun)LanguageModelInput)BaseChatModelgenerate_from_stream)	AIMessageAIMessageChunkBaseMessageBaseMessageChunkChatMessageChatMessageChunkFunctionMessageChunkHumanMessageHumanMessageChunkSystemMessageSystemMessageChunkToolMessageChunk)UsageMetadata)JsonOutputParserPydanticOutputParser)ChatGenerationChatGenerationChunk
ChatResult)RunnableRunnableMapRunnablePassthrough)from_envget_pydantic_field_names)is_basemodel_subclass)	BaseModel
ConfigDictFieldTypeAdaptermodel_validator)Self_BM)boundobjr   returnboolc                J    t          | t                    ot          |           S N)
isinstancetyper,   )r5   s    g/var/www/FlaskApp/flask-venv/lib/python3.11/site-packages/langchain_community/chat_models/perplexity.py_is_pydantic_classr=   <   s     c4  ?%:3%?%??    token_usagedictr!   c                    |                      dd          }|                      dd          }|                      d||z             }t          |||          S )Nprompt_tokensr   completion_tokenstotal_tokensinput_tokensoutput_tokensrD   )getr!   )r?   rF   rG   rD   s       r<   _create_usage_metadatarI   @   sa    ???A66LOO$7;;M??><-3OPPL!#!   r>   z0.3.21z1.0z#langchain_perplexity.ChatPerplexity)sinceremovalalternative_importc                  "   e Zd ZU dZdZded<   dZded<   	 dZd	ed
<   	  ee	          Z
ded<   	  e edd          d          Zded<   	  edd          Zded<   	 dZded<   	 dZded<   	 dZded<   	  ed !          ZedPd$            Z ed%&          edQd(                        Z ed)&          dRd+            ZedSd,            ZdTd/ZdUd5ZdVd;Z	 	 dWdXd@Z	 	 dWdYdBZedZdC            Zed[dD            Z 	 d\dEdddFd]dOZ!dS )^ChatPerplexitya  `Perplexity AI` Chat models API.

    Setup:
        To use, you should have the ``openai`` python package installed, and the
        environment variable ``PPLX_API_KEY`` set to your API key.
        Any parameters that are valid to be passed to the openai.create call
        can be passed in, even if not explicitly saved on this class.

        .. code-block:: bash

            pip install openai
            export PPLX_API_KEY=your_api_key

        Key init args - completion params:
            model: str
                Name of the model to use. e.g. "llama-3.1-sonar-small-128k-online"
            temperature: float
                Sampling temperature to use. Default is 0.7
            max_tokens: Optional[int]
                Maximum number of tokens to generate.
            streaming: bool
                Whether to stream the results or not.

        Key init args - client params:
            pplx_api_key: Optional[str]
                API key for PerplexityChat API. Default is None.
            request_timeout: Optional[Union[float, Tuple[float, float]]]
                Timeout for requests to PerplexityChat completion API. Default is None.
            max_retries: int
                Maximum number of retries to make when generating.

        See full list of supported init args and their descriptions in the params section.

        Instantiate:
            .. code-block:: python

                from langchain_community.chat_models import ChatPerplexity

                llm = ChatPerplexity(
                    model="llama-3.1-sonar-small-128k-online",
                    temperature=0.7,
                )

        Invoke:
            .. code-block:: python

                messages = [
                    ("system", "You are a chatbot."),
                    ("user", "Hello!")
                ]
                llm.invoke(messages)

        Invoke with structured output:
            .. code-block:: python

                from pydantic import BaseModel

                class StructuredOutput(BaseModel):
                    role: str
                    content: str

                llm.with_structured_output(StructuredOutput)
                llm.invoke(messages)

        Invoke with perplexity-specific params:
            .. code-block:: python

                llm.invoke(messages, extra_body={"search_recency_filter": "week"})

        Stream:
            .. code-block:: python

                for chunk in llm.stream(messages):
                    print(chunk.content)

        Token usage:
            .. code-block:: python

                response = llm.invoke(messages)
                response.usage_metadata

        Response metadata:
            .. code-block:: python

                response = llm.invoke(messages)
                response.response_metadata

    Nr   clientz!llama-3.1-sonar-small-128k-onlinestrmodelgffffff?floattemperature)default_factoryDict[str, Any]model_kwargsPPLX_API_KEY)defaultapi_key)rT   aliaszOptional[str]pplx_api_keytimeout)rZ   z+Optional[Union[float, Tuple[float, float]]]request_timeout   intmax_retriesFr7   	streamingzOptional[int]
max_tokensT)populate_by_namer6   Dict[str, str]c                
    ddiS )Nr[   rW    selfs    r<   
lc_secretszChatPerplexity.lc_secrets   s    //r>   before)modevaluesc           
        t          |           }|                    di           }t          |          D ]Y}||v rt          d| d          ||vr<t                              d| d| d| d           |                    |          ||<   Z|                    |                                          }|rt          d| d	          ||d<   |S )
z>Build extra kwargs from additional params that were passed in.rV   zFound z supplied twice.z	WARNING! z1 is not a default parameter.
                    zJ was transferred to model_kwargs.
                    Please confirm that z is what you intended.zParameters za should be specified explicitly. Instead they were passed in as part of `model_kwargs` parameter.)	r+   rH   list
ValueErrorloggerwarningpopintersectionkeys)clsrl   all_required_field_namesextra
field_nameinvalid_model_kwargss         r<   build_extrazChatPerplexity.build_extra   s4    $<C#@#@ 

>2..v,, 		; 		;JU"" !F*!F!F!FGGG!999N* N NN N)3N N N  
 %+JJz$:$:j!7DDUZZ\\RR 	T2 T T T  
 "'~r>   afterr2   c                    	 ddl }n# t          $ r t          d          w xY w	 |                    | j        d          | _        n# t
          $ r t          d          w xY w| S )z?Validate that api key and python package exists in environment.r   NzTCould not import openai python package. Please install it with `pip install openai`.zhttps://api.perplexity.ai)rY   base_urlz`openai` has no `ChatCompletion` attribute, this is likely due to an old version of the openai package. Try upgrading it with `pip install --upgrade openai`.)openaiImportErrorOpenAIr[   rO   AttributeErrorro   )rh   r~   s     r<   validate_environmentz#ChatPerplexity.validate_environment   s    	MMMM 	 	 	?  	
		 --)4O (  DKK  	 	 	7  	 s    !!A A!c                :    | j         | j        | j        d| j        S )z:Get the default parameters for calling PerplexityChat API.)rb   streamrS   )rb   ra   rS   rV   rg   s    r<   _default_paramszChatPerplexity._default_params   s0     /n+
 
 	
 	
r>   messager   c                4   t          |t                    r|j        |j        d}nrt          |t                    rd|j        d}nRt          |t
                    rd|j        d}n2t          |t                    rd|j        d}nt          d|           |S )N)rolecontentsystemuser	assistantzGot unknown type )r:   r   r   r   r   r   r   	TypeError)rh   r   message_dicts      r<   _convert_message_to_dictz'ChatPerplexity._convert_message_to_dict  s    g{++ 		;$+LW_MMLL// 	;$,IILL.. 	;$*wGGLL++ 	;$/GOLLLL999:::r>   messagesList[BaseMessage]stopOptional[List[str]]+Tuple[List[Dict[str, Any]], Dict[str, Any]]c                     t           j                  }|d|v rt          d          ||d<    fd|D             }||fS )Nr   z2`stop` found in both the input and default params.c                :    g | ]}                     |          S rf   )r   ).0mrh   s     r<   
<listcomp>z8ChatPerplexity._create_message_dicts.<locals>.<listcomp>  s'    LLLa66q99LLLr>   )r@   _invocation_paramsro   )rh   r   r   paramsmessage_dictss   `    r<   _create_message_dictsz$ChatPerplexity._create_message_dicts  sb     d-.. !UVVV!F6NLLLL8LLLf$$r>   _dictMapping[str, Any]default_classType[BaseMessageChunk]r   c                   |                     d          }|                     d          pd}i }|                     d          r+t          |d                   }d|v r|d         d|d<   ||d<   |                     d          r|d         |d<   |dk    s|t          k    rt          |          S |d	k    s|t          k    rt          ||
          S |dk    s|t          k    rt	          |          S |dk    s|t
          k    rt          ||d                   S |dk    s|t          k    rt          ||d                   S |s|t          k    rt          ||          S  ||          S )Nr   r    function_callname
tool_callsr   )r   r   )r   additional_kwargsr   function)r   r   tooltool_call_id)r   r   )r   r   )rH   r@   r   r   r   r   r    r   )rh   r   r   r   r   r   r   s          r<   _convert_delta_to_message_chunkz.ChatPerplexity._convert_delta_to_message_chunk  s    yy  ))I&&,""$99_%% 	? !788M&&=+@+H(*f%1>o.99\"" 	B.3L.Al+6>>].???$W5555[  M^$C$C!'EVWWWWX2D!D!D%g6666Z=4H#H#H'eFmLLLLV^^}0@@@#G%BWXXXX 	2]&666#G$???? =1111r>   run_manager"Optional[CallbackManagerForLLMRun]kwargsIterator[ChatGenerationChunk]c              +    K   |                      ||          \  }}i ||}t          }|                    dd            |r||d<    | j        j        j        j        d|dd|}d}	d }
|D ]}t          |t                    s|                                }|	                    d          x}rJt          |          }|
r4|d         |
d         z
  |d         |
d         z
  |d         |
d         z
  d	}n|}|}
nd }t          |d
                   dk    r|d
         d         }i }|	r-|	                    dg           |d<   dD ]}||v r||         ||<   |                     |d         |          }t          |t                    r	|r||_        |	r|xj        |z  c_        d}	|	                    d          }|t          |          nd }|j        }t!          ||          }|r|                    |j        |           |V  d S )Nr   stop_sequencesT)r   r   usagerF   rG   rD   rE   choicesr   	citationsimagesrelated_questionsdeltaFfinish_reason)r   )r   generation_info)chunkrf   )r   r   rr   rO   chatcompletionscreater:   r@   rH   rI   lenr   usage_metadatar   	__class__r%   on_llm_new_tokentext)rh   r   r   r   r   r   r   default_chunk_classstream_respfirst_chunkprev_total_usager   total_usagelc_total_usager   choicer   attrr   r   s                       r<   _streamzChatPerplexity._stream9  s      !% : :8T J Jv%F%f%,

8T""" 	,'+F#$9dk&29 
"4
 
39
 
 48  2	 2	EeT** %

#ii000{ &!7!D!D# 
4(6~(F*>:);)7)H*?;*<(6~(F*>:);? ?NN &4N#1  !%5#$$))9%a(F " >16;1K1K!+.; > >Du}}27+)$/88w!4 E %00 6^ 6'5$ $''+<<''#"JJ77M5B5N=1111TX  #(/'WWWE F,,UZu,EEEKKKKe2	 2	r>   r&   c                *   | j         r" | j        |f||d|}|rt          |          S |                     ||          \  }}i ||} | j        j        j        j        d
d|i|}t          |dd           x}	r"t          |	
                                          }
nd }
d|j        i}dD ]%}t          ||          rt          ||          ||<   &t          |j        d         j        j        ||
          }t#          t%          |          g	          S )N)r   r   r   r   r   r   r   )r   r   r   )r   )generationsrf   )ra   r   r   r   rO   r   r   r   getattrrI   
model_dumpr   hasattrr   r   r   r   r&   r$   )rh   r   r   r   r   stream_iterr   r   responser   r   r   r   r   s                 r<   	_generatezChatPerplexity._generate  so    > 	9&$,# @F K  9+K888 $ : :8T J Jv%F%f%64;#/6XXXQWXXHgt4445 	"3E4D4D4F4FGGNN!N((*<=3 	B 	BDx&& B*1(D*A*A!$'$Q'/7/)
 
 

 ~g'F'F'F&GHHHHr>   c                *    d| j         i}i || j        S )z,Get the parameters used to invoke the model.rQ   )rQ   r   )rh   
pplx_credss     r<   r   z!ChatPerplexity._invocation_params  s'     TZ&

 6*5 455r>   c                    dS )zReturn type of chat model.perplexitychatrf   rg   s    r<   	_llm_typezChatPerplexity._llm_type  s
      r>   json_schema)methodinclude_rawstrictschemaOptional[_DictOrPydanticClass]r   Literal['json_schema']r   r   Optional[bool]-Runnable[LanguageModelInput, _DictOrPydantic]c                  |dv rd}|dk    r|t          d          t          |          }|r%t          |d          r|                                }nj|r|                                }nSt          |t                    r|}n;t          |          j        dk    r#t          |          }|
                                }|                     dd|id	          }	|rt          |
          nt                      }
nt          d| d          |rht          j        t!          d          |
z  d           }t          j        d           }|                    |gd          }t%          |	          |z  S |	|
z  S )aP  Model wrapper that returns outputs formatted to match the given schema for Preplexity.
        Currently, Preplexity only supports "json_schema" method for structured output
        as per their official documentation: https://docs.perplexity.ai/guides/structured-outputs

        Args:
            schema:
                The output schema. Can be passed in as:

                - a JSON Schema,
                - a TypedDict class,
                - or a Pydantic class

            method: The method for steering model generation, currently only support:

                - "json_schema": Use the JSON Schema to parse the model output


            include_raw:
                If False then only the parsed structured output is returned. If
                an error occurs during model output parsing it will be raised. If True
                then both the raw model response (a BaseMessage) and the parsed model
                response will be returned. If an error occurs during output parsing it
                will be caught and returned as well. The final output is always a dict
                with keys "raw", "parsed", and "parsing_error".

            kwargs: Additional keyword args aren't supported.

        Returns:
            A Runnable that takes same inputs as a :class:`langchain_core.language_models.chat.BaseChatModel`.

            | If ``include_raw`` is False and ``schema`` is a Pydantic class, Runnable outputs an instance of ``schema`` (i.e., a Pydantic object). Otherwise, if ``include_raw`` is False then Runnable outputs a dict.

            | If ``include_raw`` is True, then Runnable outputs a dict with keys:

            - "raw": BaseMessage
            - "parsed": None if there was a parsing error, otherwise the type depends on the ``schema`` as described above.
            - "parsing_error": Optional[BaseException]

        )function_calling	json_moder   NzIschema must be specified when method is not 'json_schema'. Received None.model_json_schema_TypedDictMetar   )r;   r   )response_format)pydantic_objectzSUnrecognized method argument. Expected 'json_schema' Received:                    ''rawc                    d S r9   rf   _s    r<   <lambda>z7ChatPerplexity.with_structured_output.<locals>.<lambda>  s    RV r>   )parsedparsing_errorc                    d S r9   rf   r   s    r<   r   z7ChatPerplexity.with_structured_output.<locals>.<lambda>  s    d r>   )r   r   )exception_key)r   )ro   r=   r   r   r   r:   r@   r;   __name__r0   r   bindr#   r"   r)   assignr   with_fallbacksr(   )rh   r   r   r   r   r   is_pydantic_schemar   adapterllmoutput_parserparser_assignparser_noneparser_with_fallbacks                 r<   with_structured_outputz%ChatPerplexity.with_structured_output  s   ` 666"F]""~ %   "4F!;!;! 
8g+' ' 
8 #)":":"<"<# 8"(--//FD)) 8"(f&*:::%f--")"5"5"7"7)))$,o#>! !   C &($V<<<<%'' M         
  
	'/6!%((=8  M .4NNKKKK#0#?#?_ $@ $ $  3'''*>>>&&r>   )r6   rd   )rl   rU   r6   r   )r6   r2   )r6   rU   )r   r   r6   rU   )r   r   r   r   r6   r   )r   r   r   r   r6   r   )NN)
r   r   r   r   r   r   r   r   r6   r   )
r   r   r   r   r   r   r   r   r6   r&   )r6   r   )r6   rP   r9   )r   r   r   r   r   r7   r   r   r   r   r6   r   )"r   
__module____qualname____doc__rO   __annotations__rQ   rS   r/   r@   rV   r*   r[   r]   r`   ra   rb   r.   model_configpropertyri   r1   classmethodrz   r   r   r   r   r   r   r   r   r   r   rf   r>   r<   rN   rN   K   s        W Wr F4E4444K+#(5#>#>#>L>>>>V"'% >>>i# # #L    =CH5ID D DO     RK<I/ $J$$$$/:  L 0 0 0 X0 _(###   [ $#2 _'"""   #"* 
 
 
 X
   	% 	% 	% 	%2 2 2 2@ %):>	D D D D DR %):>	I I I I IB 6 6 6 X6       X  26`' *7!!%`' `' `' `' `' `' `' `'r>   rN   )r5   r   r6   r7   )r?   r@   r6   r!   )Lr  
__future__r   loggingoperatorr   typingr   r   r   r   r	   r
   r   r   r   r   r   langchain_core._api.deprecationr   langchain_core.callbacksr   langchain_core.language_modelsr   *langchain_core.language_models.chat_modelsr   r   langchain_core.messagesr   r   r   r   r   r   r   r   r   r   r   r    langchain_core.messages.air!   langchain_core.output_parsersr"   r#   langchain_core.outputsr$   r%   r&   langchain_core.runnablesr'   r(   r)   langchain_core.utilsr*   r+   langchain_core.utils.pydanticr,   pydanticr-   r.   r/   r0   r1   typing_extensionsr2   r3   rP   _DictOrPydanticClass_DictOrPydantic	getLoggerr   rp   r=   rI   rN   rf   r>   r<   <module>r     sh   % % " " " " " "                                 7 6 6 6 6 6 = = = = = = = = = = = =                                   5 4 4 4 4 4 P P P P P P P P R R R R R R R R R R O O O O O O O O O O C C C C C C C C      P O O O O O O O O O O O O O " " " " " "ge9%%%T#s(^T#Y<= c	"		8	$	$@ @ @ @    
<  
}' }' }' }' }'] }' }' 
}' }' }'r>   