
    BTh                     Z   d dl Z d dlmZ 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mZmZ d dlmZ d dlmZ d dlmZ d dlmZ d d	l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(m)Z)m*Z*m+Z+ ddl,m-Z-m.Z. ddl/m0Z0 ddl1m2Z2 eZ3ee	e%   e	e3   f   Z4 ede+      Z5dZ6g dZ7 G d d      Z8y)    N)BytesIO)urljoin)IterableListOptionalUnionDictTypeVarBinaryIO)ManageAssistantsApi)SearchCompletions)Chat)MessageModel)ContextOptionsModel)	Assistant)	ApiClient)	FileModel   )ContextOptionsMessageStreamChatResponseCitationStreamChatResponseContentDeltaStreamChatResponseMessageEndStreamChatResponseMessageStartChatResponseBaseStreamChatResponseChunk)StreamingChatCompletionChunkChatCompletionResponse)ContextResponse   )ContextRequestS)bound	assistant)gpt-4ozgpt-4.1zo4-minizclaude-3-5-sonnetzclaude-3-7-sonnetzgemini-2.5-proc                      e Zd ZdefdZd Zd Zd Z	 	 d(dede	e
eef      d	e	e   d
efdZ	 	 d(dedede	e
eef      d	e	e   d
ef
dZ	 	 d(dede	e
eef      d	e	e   d
efdZd)dede	e   d
efdZd*de	e
eef      d
ee   fdZd*ded	e	e   fdZedeee   ee   f   d
ee   fd       Z	 	 	 	 d+deee   ee   f   de	e
eef      dedeedf   de	e   d
eeee    f   fdZ!	 	 	 d,dee   dede
eef   de	e   d
ef
dZ"	 	 	 d,dee   dede	e
eef      de	e   d
ee    f
dZ#	 	 	 	 	 	 	 d-deee   ee   f   de	e
eef      dedeedf   de	e   deded e	ee$e
eef   f      d
ee%ee&   f   fd!Z'	 	 	 	 	 	 d.dee   dede	e   de
eef   deded e	e$   d
e%fd"Z(	 	 	 	 	 d/dee   dede	e   de	e
eef      ded e	e$   d
ee&   fd#Z)	 	 	 	 	 d0d$e	e   deee   ee   f   de	e
eef      d%e	e   d&e	e   f
d'Z*y)1AssistantModelr$   c                    || _         |j                  | _        t        | j                  t              | _        |r|ni | _         |t
        t        d| j                        | _        | j                   j                  | _        | j                   j                  | _	        | j                   j                  | _
        | j                   j                  | _        | j                   j                  | _        g | _        y )Nz2025-01)host)r$   r)   r   HOST_SUFFIXconfigr   DataApiClient_assistant_data_apiname
created_at
updated_atmetadatastatusctxs)selfr$   client_builderr+   s       /var/www/catia.catastroantioquia-mas.com/valormas/lib/python3.12/site-packages/pinecone_plugins/assistant/models/assistant_model.py__init__zAssistantModel.__init__-   s    "NN	DII{3	 &fB#1}idii$
  NN''	..33..33//nn++	    c                 ,    t        | j                        S N)strr$   r4   s    r6   __str__zAssistantModel.__str__>   s    4>>""r8   c                 ,    t        | j                        S r:   )reprr$   r<   s    r6   __repr__zAssistantModel.__repr__A   s    DNN##r8   c                 .    t        | j                  |      S r:   )getattrr$   )r4   attrs     r6   __getattr__zAssistantModel.__getattr__D   s    t~~t,,r8   N	file_pathr1   timeoutreturnc                     	 t        |d      5 }| j                  |||      cddd       S # 1 sw Y   yxY w# t        $ r t        d| d      t        $ r t        d| d      w xY w)a  
        Uploads a file from the specified path to this assistant for internal processing.

        :param file_path: The path to the file that needs to be uploaded.
        :type file_path: str, required

        :param metadata: Optional metadata dictionary to be attached to the file.
        :type metadata: Optional[dict[str, any]], optional

        :param timeout: Specify the number of seconds to wait until file processing is done. If None, wait indefinitely; if >=0, time out after this many seconds;
            if -1, return immediately and do not wait. Default: None
        :type timeout: int, optional


        :return: FileModel object with the following properties:
            - id: The UUID of the uploaded file.
            - name: The name of the uploaded file.
            - created_on: The timestamp of when the file was created.
            - updated_on: The timestamp of the last update to the file.
            - metadata: Metadata associated with the file.
            - status: The status of the file.

        Example:
        >>> assistant = (...).assistant.Assistant("assistant_name")
        >>> file_model = assistant.upload_file(file_path="/path/to/file.txt") # use the default timeout
        >>> print(file_model)
          {'created_on': '2024-06-02T19:48:00Z',
          'id': '070513b3-022f-4966-b583-a9b12e0920ff',
          'metadata': None,
          'name': 'tiny_file.txt',
          'status': 'Available',
          'updated_on': '2024-06-02T19:48:00Z'}
        rbNzError: The file at z was not found.z"Error: Could not read the file at .)open_upload_file_streamFileNotFoundError	ExceptionIOError)r4   rE   r1   rF   files        r6   upload_filezAssistantModel.upload_fileG   s    N	Oi& I$//hHI I I  	N1)OLMM 	O@1MNN	Os   7 +	7 47 7 0A'stream	file_namec                 6    ||_         | j                  |||      S )a  
        Uploads a file-like stream to the assistant for internal processing.

        Note: for text files, the stream must be encoded in UTF-8.

        :param stream: BytesIO stream containing the file bytes to be uploaded.
        :type stream: BytesIO, required

        :param file_name: The file name to associate with the stream.
        :type file_name: str, required

        :param metadata: Optional metadata dictionary to be attached to the file.
        :type metadata: Optional[dict[str, any]], optional

        :param timeout: Specify the number of seconds to wait until file processing is done. If None, wait indefinitely; if >=0, time out after this many seconds;
            if -1, return immediately and do not wait. Default: None
        :type timeout: int, optional

        :return: FileModel object representing the uploaded file.

        Example:
        >>> assistant = (...).assistant.Assistant("assistant_name")
        Example:
        >>> from io import BytesIO
        >>> # Create a BytesIO stream with some binary data.
        >>> text = "Hello, world!"
        >>> stream = BytesIO(text.encode("utf-8"))
        >>> # Instantiate your assistant object (assuming proper initialization).
        >>> assistant = Assistant("assistant_name")
        >>> # Upload the stream with a specified file name.
        >>> file_model = assistant.upload_bytes_stream(stream, "myfile.txt")
        >>> print(file_model)
        {'created_on': '2024-06-02T19:48:00Z',
         'id': '070513b3-022f-4966-b583-a9b12e0920ff',
         'metadata': None,
         'name': 'myfile.txt',
         'status': 'Available',
         'updated_on': '2024-06-02T19:48:00Z'}
        )r.   rL   )r4   rR   rS   r1   rF   s        r6   upload_bytes_streamz"AssistantModel.upload_bytes_streamv   s!    \  '''BBr8   file_streamc                    |rE| j                   j                  | j                  j                  |t	        j
                  |            n0| j                   j                  | j                  j                  |      }|dk(  rt        j                  |      S |w|j                  dk(  rt        j                  d       | j                  |j                        }|j                  dk(  rt        d|j                         |j                  dk(  rgn|j                  dk(  rv|dk\  rqt        j                  d       |dz  }| j                  |j                        }|j                  dk(  rt        d|j                         |j                  dk(  r|dk\  rq|r|dk  rt        d	| j                   d
      t        j                  |      S )N)assistant_namerP   r1   )rX   rP   
Processing   ProcessingFailedzFile processing failed. Error: r   z$Please call `pc.assistant.Assistant(z)` to confirm assistant status.)r-   rQ   r$   r.   jsondumpsr   from_openapir2   timesleepdescribe_fileidrN   error_messageTimeoutError)r4   rV   r1   rF   upload_resps        r6   rL   z"AssistantModel._upload_file_stream   s     ((44#'>>#6#6$!ZZ1 5  --99#'>>#6#6[ :   "} --k::!((L8JJqM"&"4"4[^^"DK"))-??'*I+JcJcId(eff	 "((L8 "((L8W\JJqMqLG"&"4"4[^^"DK"))-??'*I+JcJcId(eff "((L8W\ 7Q; >tyykIhi
 ))+66r8   file_idinclude_urlc                     |r@| j                   j                  | j                  |t        |      j	                               }n'| j                   j                  | j                  |      }t        j                  |      S )a'  
        Describes a file with the specified file_id from this assistant. Includes information on its status and metadata.

        :param : The file id of the file to be described
        :type file_id: str, required

        :param include_url: If True, the signed URL of the file is included in the response.
        :type include_url: bool, optional

        :return: FileModel object with the following properties:
            - id: The UUID of the requested file.
            - name: The name of the requested file.
            - created_on: The timestamp of when the file was created.
            - updated_on: The timestamp of the last update to the file.
            - metadata: Metadata associated with the file.
            - status: The status of the file.

        Example:
        >>> assistant = (...).assistant.Assistant("model_name")
        >>> file_model = assistant.upload_file(file_path="/path/to/file.txt") # use the default timeout
        >>> print(file_model)
          {'created_on': '2024-06-02T19:48:00Z',
          'id': '070513b3-022f-4966-b583-a9b12e0290ff',
          'metadata': None,
          'name': 'tiny_file.txt',
          'status': 'Available',
          'updated_on': '2024-06-02T19:48:00Z'}
        >>> assistant.describe_file(file_id='070513b3-022f-4966-b583-a9b12e0290ff')
          {'created_on': '2024-06-02T19:48:00Z',
          'id': '070513b3-022f-4966-b583-a9b12e0290ff',
          'metadata': None,
          'name': 'tiny_file.txt',
          'status': 'Available',
          'updated_on': '2024-06-02T19:48:00Z'}
        )rX   assistant_file_idrh   rX   rj   )r-   rb   r.   r;   lowerr   r_   )r4   rg   rh   rP   s       r6   rb   zAssistantModel.describe_file   sx    J ++99#yy"),224 : D ++99#yy") : D %%d++r8   filterc                 (   |r:| j                   j                  | j                  t        j                  |            n$| j                   j                  | j                        }|j
                  D cg c]  }t        j                  |       c}S c c}w )aZ  
        Lists all uploaded files in this assistant.

        :return: List of FileModel objects with the following properties:
            - id: The UUID of the requested file.
            - name: The name of the requested file.
            - created_on: The timestamp of when the file was created.
            - updated_on: The timestamp of the last update to the file.
            - metadata: Metadata associated with the file.
            - status: The status of the file.

        Example:
        >>> assistant = (...).assistant.Assistant("model_name")
        >>> assistant.list_files()
          [{'created_on': '2024-06-02T19:48:00Z',
          'id': '070513b3-022f-4966-b583-a9b12e0290ff',
          'metadata': None,
          'name': 'tiny_file.txt',
          'status': 'Available',
          'updated_on': '2024-06-02T19:48:00Z'}, ...]
        )rm   )r-   
list_filesr.   r]   r^   filesr   r_   )r4   rm   
files_resprP   s       r6   ro   zAssistantModel.list_files  s{    2  $$//		$**V"4 0 6 ))44TYY?	 	 :D9I9IJ	&&t,JJJs   0Bc                    | j                   j                  | j                  |       |dk(  ry|@| j                  |      }|rzt	        j
                  d       	 | j                  |      }|r+nN| j                  |      }|r:|dk\  r5t	        j
                  d       |dz  }	 | j                  |      }|r|dk\  r5|r |dk  rt        dj                  d            yy# t        $ r d}Y w xY w# t        $ r d}Y Iw xY w)	a  
        Deletes a file with the specified file_id from this assistant.

        :param file_path: The path to the file that needs to be uploaded.
        :type file_path: str, required

        :type timeout: int, optional
        :param timeout: Specify the number of seconds to wait until file processing is done. If None, wait indefinitely; if >=0, time out after this many seconds;
            if -1, return immediately and do not wait. Default: None

        Example:
        >>> assistant = (...).assistant.Assistant("model_name")
        >>> assistant.delete_file(file_id='070513b3-022f-4966-b583-a9b12e0290ff') # use the default timeout
        >>> assistant.list_files()
          []
        rk   rY   N)rg   r[   r   z@Please call the describe_model API ({}) to confirm model status.zDhttps://www.pinecone.io/docs/api/operation/assistant/describe_model/)	r-   delete_filer.   rb   r`   ra   rN   re   format)r4   rg   rF   rP   s       r6   rs   zAssistantModel.delete_file$  s%   " 	  ,,99 	- 	
 b=?%%g%6D

1 --g->D  %%g%6D7a<

11 --g->D	 7a< w{V]]^ #7 !  D  !  D s$   C! $C2 !C/.C/2D ?D messagesc                 v    |D cg c])  }t        |t              rt        j                  |      n|+ c}S c c}w r:   )
isinstancedictr   	from_dict)clsru   messages      r6   _parse_messageszAssistantModel._parse_messagesW  s0    dlmY`j$.G!!'*WTmmms   .6modeltemperaturec                     |d}n1|t         vr)t        ddj                  d t         D               d      | j                  |      }|r| j	                  ||||      S | j                  ||||      S )a  
        Performs a chat completion request to the following assistant. Use this method if you want the response output to be OpenAI's chat completion format.

        :param messages: The current context for the chat request. The final element in the list represents the user query to be made from this context.
        :type messages: List[Message] where Message requires the following:
            Message:
                - role: str, the role of the context ('user' or 'agent')
                - content: str, the content of the context

            Alternatively, you can pass a list of dictionaries with the following keys:
                - role: str, the role of the context ('user' or 'agent')
                - content: str, the content of the context

        :param model: The large language model to use for answer generation. If this flag is set to 'None', then the model used is OpenAI's GPT-4o.
        :type model: str | None (default 'gpt-4o' in case `None` is passed)

        :param temperature: Controls the randomness of the model's output: lower values make responses more deterministic, while higher values increase creativity and variability. If the model does not support a temperature parameter, the parameter will be ignored.
        :type temperature: float | None (default 0.0 in case `None` is passed)
        
        :param filter: Optional dictionary to filter which documents can be used in this query.
                       Use this to narrow down the context for the assistant's response.
        :type filter: Optional[dict[str, any]] (default None)

        Example filter:
            {
                "genre": {"$ne": "documentary"}
            }
        This filter would exclude documents with the genre "documentary" from being used in the query.

        :param stream: If this flag is turned on, then the return type is an Iterable[StreamingChatCompletionChunk] whether data is returned as a generator/stream
        :type stream: bool (default false)

        :return:
        The default result is a ChatCompletionResponse with the following format:
            {
                "choices": [
                    {
                    "finish_reason": "stop",
                    "index": 0,
                    "message": {
                        "content": "The 2020 World Series was played in Texas at Globe Life Field in Arlington.",
                        "role": "assistant"
                    },
                    "logprobs": null
                    }
                ],
                "id": "chatcmpl-7QyqpwdfhqwajicIEznoc6Q47XAyW",
                "model": "gpt-3.5-turbo-0613",
            }

        However, when stream is set to true, the response is an iterable of StreamingChatCompletionChunks. See examples below:
            {
                "choices": [
                    {
                    "finish_reason": null,
                    "index": 0,
                    "delta": {
                        "content": "The",
                        "role": ""
                    },
                    "logprobs": null
                    }
                ],
                "id": "chatcmpl-7QyqpwdfhqwajicIEznoc6Q47XAyW",
                "model": "gpt-3.5-turbo-0613",
            }

        Example:
        >>> from pinecone_plugins.assistant.models import Message
        >>> assistant = (...).assistant.Assistant("planets-km")
        >>> messages = [Message(role='user', content='How old is the earth')]
        >>> resp = assistant.chat_completions(messages=messages)
        >>> print(resp)
        {'choices': [{'finish_reason': 'stop',
              'index': 0,
              'message': {'content': 'The age of the Earth is estimated to be '
                                     'about 4.54 billion years, based on '
                                     'evidence from radiometric age dating of '
                                     'meteorite material and Earth rocks, as '
                                     'well as lunar samples. This estimate has '
                                     'a margin of error of about 1%.',
                          'role': 'assistant'}}],
        'id': 'chatcmpl-9VmkSD9s7rfP28uScLlheookaSwcB',
        'model': 'planets-km'}

        Streaming example:
        >>> resp = assistant.chat_completions(messages=messages, stream=True)
        >>> for chunk in resp:
                if chunk:
                    print(chunk)

        [{'choices': [{'finish_reason': 'stop',
              'index': 0,
              'delta': {'content': 'The age of the Earth is estimated to be '
                                     'about 4.54 billion years, based on '
                                     'evidence from radiometric age dating of '
                                     'meteorite material and Earth rocks, as '
                                     'well as lunar samples. This estimate has '
                                     'a margin of error of about 1%.',
                          'role': 'assistant'}}],
        'id': 'chatcmpl-9VmkSD9s7rfP28uScLlheookaSwcB',
        'model': 'gpt-4o'}, ... ]

        r%   !Invalid model. Valid options are , c              3   (   K   | ]
  }d | d   yw`N .0ms     r6   	<genexpr>z2AssistantModel.chat_completions.<locals>.<genexpr>       =W1!Ah=W   rJ   )ru   r}   rm   r~   )MODELS
ValueErrorjoinr|   _chat_completions_streaming_chat_completions_single)r4   ru   rm   rR   r}   r~   s         r6   chat_completionszAssistantModel.chat_completions[  s    ` =E& 3DII=WPV=W4W3XXYZ  ''133!v; 4   00!v; 1  r8   c                    |D cg c]#  }t        |j                  |j                        % }}||d}|r||d<   |||d<   t        di |}| j                  j                  | j                  |      }t        j                  |      S c c}w )Nrolecontent)ru   r}   rm   r~   )rX   search_completionsr   )	r   r   r   ChatCompletionsRequestr-   chat_completion_assistantr.   r   r_   )	r4   ru   r}   rm   r~   ctxkwargschat_requestresults	            r6   r   z'AssistantModel._chat_completions_single  s     IQ
ADLchh<
 
 '7%F8"$/F=!-77))CC99 D 
 &226::
s   (B	c              #   J  K   | j                   j                  }| j                   d| j                   d}|dd}|D cg c]  }t	        |       }}|d|d}	|r||	d<   |||	d<   	 t        j                  |||	d	d
      }
|
j                          |
j                         D ]Z  }|s|j                  d      }|j                  d      r|dd  }t        j                  |      }t        j                  |      }| \ y c c}w # t        $ r}t!        d|       d }~ww xY ww)N/chat/z/chat/completionsapplication/jsonzapi-keyzContent-TypeT)ru   rR   r}   rm   r~   <   headersr]   rF   rR   utf-8data:r[   %Error in chat completions streaming: )r+   api_keyr)   r.   varsrequestspostraise_for_status
iter_linesdecode
startswithr]   loadsr   ry   rN   r   )r4   ru   r}   rm   r~   r   base_urlr   r{   r   responselinedata	json_datareses                   r6   r   z*AssistantModel._chat_completions_streaming  s8     ++%%ii[tyyk1BC%7IJ19:gDM::'4%H &GH"%0GM"	J}}'DH %%' ++- 	;;w/Dw/#ABx $

4 0I6@@KCI	 ;.  	JDQCHII	Js;   <D#C?D#'?D 'AD >D#	D DD  D#json_responseinclude_highlightscontext_optionsc	           	      ^   |d}n1|t         vr)t        ddj                  d t         D               d      |r|rt        d      | j                  |      }t	        |t
              rt        j                  |      n|}|r| j                  ||||||      S | j                  |||||||      S )	aT   
        Performs a chat request to the following assistant.

        :param messages: The current context for the chat request. The final element in the list represents the user query to be made from this context.
        :type messages: List[Message] where Message requires the following:
            Message:
                - role: str, the role of the context ('user' or 'agent')
                - content: str, the content of the context

            Alternatively, you can pass a list of dictionaries with the following keys:
                - role: str, the role of the context ('user' or 'agent')
                - content: str, the content of the context

        :param model: The large language model to use for answer generation. If this flag is set to 'None', then the model used is OpenAI's GPT-4o.
        :type model: str | None (default 'gpt-4o' in case `None` is passed)

        :param temperature: Controls the randomness of the model's output: lower values make responses more deterministic, while higher values increase creativity and variability. If the model does not support a temperature parameter, the parameter will be ignored.
        :type temperature: float | None (default 0.0 in case `None` is passed)
        
        :param json_response: If true, the assistant will be instructed to return a JSON response. Cannot be used with streaming.
        :type json_response: bool (default False)

        :param include_highlights: If true, the assistant will be instructed to mark highlights for citations. Highlights are small snippets of text that are relevant to the citation.
        :type include_highlights: bool (default False)

        :param filter: Optional dictionary to filter which documents can be used in this query.
                       Use this to narrow down the context for the assistant's response.
        :type filter: Optional[dict[str, any]] (default None)

        Example filter:
            {
                "genre": {"$ne": "documentary"}
            }
        This filter would exclude documents with the genre "documentary" from being used in the query.

        :param stream: If this flag is turned on, then the return type is an Iterable[StreamChatResponseChunk] whether data is returned as a generator/stream
        :type stream: bool (default false)

        :param context_options: Option to control the context snippets sent to the LLM.
        :type context_options: Optional[ContextOptions] (default None)
            ContextOptions:
                - top_k: int, the number of context snippets to use. Default is 16. Maximum is 64.
                - snippet_size: int, the maximum context snippet size. Default is 2048 tokens. Minimum is 512 tokens. Maximum is 8192 tokens.
            
            Alternatively, you can pass a dictionary with the following keys:
                - top_k: int, the number of context snippets to use.
                - snippet_size: int, the maximum context snippet size.

        :return:
        The default result is a ChatModel with the following format:
            {
                "finish_reason": "stop",
                "index": 0,
                "message": {
                    "content": "The 2020 World Series was played in Texas at Globe Life Field in Arlington.",
                    "role": "assistant"
                },
                "id": "chatcmpl-7QyqpwdfhqwajicIEznoc6Q47XAyW",
                "model": "gpt-3.5-turbo-0613",
                "citations": [
                    {
                        "position": 3,
                        "references": [
                            {
                                "file": {
                                    'created_on': '2024-06-02T19:48:00Z',
                                    'id': '070513b3-022f-4966-b583-a9b12e0290ff',
                                    'metadata': None,
                                    'name': 'tiny_file.txt',
                                    'status': 'Available',
                                    'updated_on': '2024-06-02T19:48:00Z'
                                },
                                "pages": [1, 2, 3],
                                "highlight": Null,
                            }
                        ],
                    }
                ]
            }

        However, when stream is set to true, the response is an stream of StreamChatResponseChunks. This can be one of the following types:
        - StreamChatResponseMessageStart:
            {'type': 'message_start', 'id': '0000000000000000468323be9d266e55', 'model': 'gpt-4o-2024-11-20', 'role': 'assistant'}
        - StreamChatResponseContentDelta
            {'type': 'content_chunk', 'id': '0000000000000000468323be9d266e55', 'model': 'gpt-4o-2024-11-20', 'delta': {'content': 'The'}}
        - StreamChatResponseCitation
            {'type': 'citation', 'id': '0000000000000000116990b44044d21e', 'model': 'gpt-4o-2024-11-20', 'citation': {'position': 247, 'references': [{'id': 's0', 'file': {'status': 'Available', 'id': '985edb6c-f649-4334-8f14-9a16b7039ab6',
            'name': 'PEPSICO_2022_10K.pdf', 'size': 2993516, 'metadata': None, 'updated_on': '2024-08-08T15:41:58.839846634Z', 'created_on': '2024-08-08T15:41:07.427879083Z', 'percent_done': 0.0,
            'signed_url': 'example.com'}, 'pages': [32]}]}}
        - StreamChatResponseMessageEnd
            {'type': 'message_end', 'id': '0000000000000000116990b44044d21e', 'model': 'gpt-4o-2024-11-20', 'finish_reason': 'stop', 'usage': {'prompt_tokens': 1, 'completion_tokens': 1, 'total_tokens': 2}}


        Example:
        >>> from pinecone_plugins.assistant.models import Message
        >>> assistant = (...).assistant.Assistant("planets-km")
        >>> messages = [Message(role='user', content='How old is the earth')]
        >>> resp = assistant.chat(messages=messages, context_options=ContextOptions(top_k=10, snippet_size=4096))
        >>> print(resp)
        {
                "finish_reason": "stop",
                "index": 0,
                "message": {
                   'content': 'The age of the Earth is estimated to be '
                                     'about 4.54 billion years, based on '
                                     'evidence from radiometric age dating of '
                                     'meteorite material and Earth rocks, as '
                                     'well as lunar samples. This estimate has '
                                     'a margin of error of about 1%.',
                    'role': 'assistant'
                },
                'id': 'chatcmpl-7QyqpwdfhqwajicIEznoc6Q47XAyW',
                "model": "gpt-3.5-turbo-0613",
                "citations": [
                    {
                        "position": 3,
                        "references": [
                            {
                                "file": {
                                    'created_on': '2024-06-02T19:48:00Z',
                                    'id': '070513b3-022f-4966-b583-a9b12e0290ff',
                                    'metadata': None,
                                    'name': 'tiny_file.txt',
                                    'status': 'Available',
                                    'updated_on': '2024-06-02T19:48:00Z'
                                },
                                "pages": [1, 2, 3],
                                "highlight": Null,
                            }
                        ],
                    }
                ]
            }

        Streaming example:
        >>> resp = assistant.chat(messages=messages, stream=True, context_options={"top_k":10, "snippet_size":4096})
        >>> for chunk in resp:
                if chunk:
                    print(chunk)

        [{'type': 'message_start', 'id': '0000000000000000468323be9d266e55', 'model': 'gpt-4o-2024-11-20', 'role': 'assistant'},
         {'type': 'content_chunk', 'id': '0000000000000000468323be9d266e55', 'model': 'gpt-4o-2024-11-20', 'delta': {'content': 'The'}},
          ...
         {'type': 'message_end', 'id': '0000000000000000116990b44044d21e', 'model': 'gpt-4o-2024-11-20', 'finish_reason': 'stop', 'usage': {'prompt_tokens': 1, 'completion_tokens': 1, 'total_tokens': 2}}]

        r%   r   r   c              3   (   K   | ]
  }d | d   ywr   r   r   s     r6   r   z&AssistantModel.chat.<locals>.<genexpr>  r   r   rJ   z'Cannot use json_response with streaming)ru   r}   rm   r   r   r~   )ru   r}   rm   r   r   r   r~   )
r   r   r   r|   rw   rx   r   ry   _chat_streaming_chat_single)	r4   ru   rm   rR   r}   r~   r   r   r   s	            r6   chatzAssistantModel.chat  s    z =E& 3DII=WPV=W4W3XXYZ  VFGG''1GQRacgGh.22?Cn}''vj|  O^  lw'  x  x$$heFbo  EW  ix  FQ$  R  Rr8   c                    |D cg c]#  }t        |j                  |j                        % }}||||d}	|r||	d<   |||	d<   |Hi }
|j                  |j                  |
d<   |j                  |j                  |
d<   |
rt        d	i |
|	d<   t        d	i |	}| j                  j                  | j                  |      }t        j                  |      S c c}w )
Nr   )ru   r}   r   r   rm   r~   top_ksnippet_sizer   )rX   r   r   )r   r   r   r   r   r   ChatRequestr-   chat_assistantr.   r   r_   )r4   ru   r}   r~   rm   r   r   r   r   r   optionsr   chat_results                r6   r   zAssistantModel._chat_single  s    IQ
ADLchh<
 

 !*"4	
 %F8"$/F=!&G$$0#2#8#8 ++7*9*F*F',?,J',J()",V,..==99< > 
 ((557
s   (Cc              #     K   | j                   j                  }| j                   d| j                   }|dd}	|D 
cg c]  }
t	        |
       }}
|d||d}|r||d<   |||d<   |?i }|j
                  |j
                  |d<   |j                  |j                  |d	<   |r||d
<   	 t        j                  ||	|dd      }|j                          |j                         D ]  }|s|j                  d      }|j                  d      r|dd  }t        j                  |      }d }|j                  d      dk(  rt!        j"                  |      }n}|j                  d      dk(  rt%        j"                  |      }nS|j                  d      dk(  rt'        j"                  |      }n)|j                  d      dk(  rt)        j"                  |      }|  y c c}
w # t*        $ r}t-        d|       d }~ww xY ww)Nr   r   r   T)ru   rR   r}   r   rm   r~   r   r   r   r   r   r   r   r[   typemessage_startcontent_chunkcitationmessage_endr   )r+   r   r)   r.   r   r   r   r   r   r   r   r   r   r]   r   getr   ry   r   r   r   rN   r   )r4   ru   r}   r~   rm   r   r   r   r   r   r{   r   r   r   r   r   r   r   r   s                      r6   r   zAssistantModel._chat_streaming  s	     ++%%ii[tyyk2%7IJ19:gDM::'4%_qr &GH"%0GM"&G$$0#2#8#8 ++7*9*F*F'-4)*	J}}'DH %%' ++- ;;w/Dw/#ABx $

4 0IC }}V,?<FF%'"v./A<FF%'"v.*<8BB9M"v.-?:DDYOI)- ;V  	JDQCHII	Js<   ;G8GAG8(?G (C+G G8	G5"G00G55G8queryr   r   c                    |s|s|s|st        ||       t        d      S i }|rE| j                  |      }|D cg c]#  }t        |j                  |j
                        % }}||d<   n||d<   |r||d<   |||d<   |||d<   t        d	i |}| j                  j                  | j                  |      }	t        j                  |	      S c c}w )
a
  
        Performs a context request to the following assistant.

        :param query: The query to be used in the context request. Either
                      one of query or messages may be used to generate
                      the context response.
        :type query: Optional[str]

        :param messages: The messages to be used in the context request. Either
                         one of query or messages may be used to generate the
                         context response.
        :type messages: Optional[List[Message]]

        :param filter: Optional dictionary to filter which documents can be used in this query.
                       Use this to narrow down the context for the assistant's response.
        :type filter: Optional[dict[str, any]] (default None)

        Example filter:
            {
                "genre": {"$ne": "documentary"}
            }
        This filter would exclude documents with the genre "documentary" from being used in the query.

        :param top_k: Optional integer to specify the maximum number of context snippets to return.
        :type top_k: Optional[int] (default None)

        :param snippet_size: Optional integer to specify the maximum context snippet size. Default is 2048 tokens. Minimum is 512 tokens. Maximum is 8192 tokens.
        :type snippet_size: Optional[int] (default None)
        
        :return:
        The default result is a ContextResponse with the following format:

        {
          "snippets": [
            {
              "type": "text",
              "content": "The quick brown fox jumps over the lazy dog.",
              "score": 0.9946,
              "reference": {
                "type": "pdf",
                "file": {
                  "id": "96e6e2de-82b2-494d-8988-7dc88ce2ac01",
                  "metadata": null,
                  "name": "sample.pdf",
                  "percent_done": 1.0,
                  "status": "Available",
                  "created_on": "2024-11-13T14:59:53.369365582Z",
                  "updated_on": "2024-11-13T14:59:55.369365582Z",
                  "signed_url": "https://storage.googleapis.com/..."
                },
                "pages": [1]
              }
            }
          ],
          "usage": {
            "completion_tokens": 0,
            "prompt_tokens": 506,
            "total_tokens": 506
          }
        }

        Example:
        >>> assistant = (...).assistant.Assistant("planets-km")
        >>> resp = assistant.context(query="What is the age of the earth?")
        >>> print(resp)
        zBInvalid Inputs: Exactly one of query or messages must be inputted.r   ru   r   rm   r   r   )rX   context_requestr   )printr   r|   r   r   r   r!   r-   context_assistantr.   r   r_   )
r4   r   ru   rm   r   r   r   r   r   raw_responses
             r6   contextzAssistantModel.context'  s    T xe%"bcc++H5HT\]S#((CKKH]H]!)F:#F7O%F8#F7O#%1F>"( 

 //AA99+ B 
 ++L99' ^s   (C
)NN)Fr:   )NFNN)r%   NN)NFNNFFN)r%   NNFFN)r%   NNFN)NNNNN)+__name__
__module____qualname__OpenAIAssistantModelr7   r=   r@   rD   r;   r   rx   anyintr   rQ   r   rU   r   rL   boolrb   r   ro   rs   classmethodr   r   
RawMessager|   floatr   r   r   r   r   r   r   r   r"   r   r   r   r   r   r8   r6   r'   r'   ,   s7   "6 "#$- .2!%	-O-O 4S>*-O #	-O
 
-Of 26%)/C/C /C tCH~.	/C
 c]/C 
/Cj .2!%	*7*7 4S>**7 #	*7
 
*7X0,S 0,x~ 0,R[ 0,dK$sCx.!9 KT)_ K<13 1# 1f nuT']D<L-L'M nRVW^R_ n n ,0"&'+WtJ'778 c3h( 	
 S$Y e_ 
%x0L'MM	NH !%'+;w-; ; S#X	;
 e_; 
 ;6 +/'+"Jw-"J "J c3h(	"J
 e_"J 
.	/"JN ,0"&'+##(KOlRWtJ'778lR c3h(lR 	lR
 S$YlR e_lR lR !lR "%S#X(F"GHlR 
|Xa[(	)lRb '+!%##(48%6w-%6 %6 e_	%6
 S#X%6 %6 !%6 ".1%6 
%6T '++/#(488Jw-8J 8J e_	8J
 c3h(8J !8J ".18J 
!8Jx  $;?+/#&*d:}d: WtJ'778d: c3h(	d:
 }d: smd:r8   r'   )9r`   ior   urllib.parser   r   r]   typingr   r   r   r   r	   r
   r   Epinecone_plugins.assistant.data.core.client.api.manage_assistants_apir   r,   Dpinecone_plugins.assistant.data.core.client.model.search_completionsr   r   6pinecone_plugins.assistant.data.core.client.model.chatr   r   ?pinecone_plugins.assistant.data.core.client.model.message_modelr   Gpinecone_plugins.assistant.data.core.client.model.context_options_modelr   5pinecone_plugins.assistant.control.core.client.modelsr   r   +pinecone_plugins.assistant.data.core.clientr   ,pinecone_plugins.assistant.models.file_modelr   r   r   r   r   r   r   r   r   r   chat_completionr   r   context_responsesr   &data.core.client.model.context_requestr!   r   RawMessagesr"   r*   r   r'   r   r8   r6   <module>r      s          K K K W X g B B   R . C
DM4
#334C23	e_: _:r8   