
    j$                         d dl Z d dlmZmZ d dlZd dlmZ d dlmZ ddl	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  e j(                  e      Z G d d      Zy)    N)ListOptional)TraceThread)BatchFeedbackScoreDict   )helpersrest_stream_parser	constants   )config)messages)sequence_splitter)trace_thread_filterc                       e Zd ZdZddZ	 	 	 	 ddee   dee   dedede	e
   f
d	Z	 dd
e	e   dee   ddfdZdededdfdZedd       Zy)ThreadsClienta  
    Client for managing and interacting with conversational threads.

    This class provides methods for searching threads and logging feedback scores
    related to threads using an underlying client instance. It is intended to be
    used in scenarios where thread management and feedback tracking are required.

    Args:
        client: Instance of the underlying OPIK client.
    c                     || _         y N_opik_client)selfclients     /Users/manta/Documents/Projects/TheRoad-I1/backend/.venv/lib/python3.12/site-packages/opik/api_objects/threads/threads_client.py__init__zThreadsClient.__init__   s
    "    Nproject_namefilter_stringmax_resultstruncatereturnc                      t        j                  |t        j                  d      xs  j                  j
                  t        j                   fd|t              }|S )a  Search for threads in a given project based on specific criteria.

        This method retrieves a list of TraceThread objects that match the specified
        filter criteria. It takes an optional project name, a filter string to narrow
        down the results, and a maximum number of threads to return.

        The filter string should be a string that represents a filter condition in the
        form of a string expression. For example, to search for threads with a specific
        status, you could use the following filter string: `filter_string = 'status = "active"'`.
        The filter string can include logical operators (AND) to combine
        multiple conditions, for example, `filter_string = 'status = "active" and id = "{thread_id}"'`.

        Args:
            project_name:
                The name of the project to search the threads for. If None, the search
                will include threads from all projects.
            filter_string:
                A filter string to narrow down the search using Opik Query Language (OQL).
                The format is: "<COLUMN> <OPERATOR> <VALUE> [AND <COLUMN> <OPERATOR> <VALUE>]*"

                Supported columns include:
                - `id`, `name`, `created_by`, `thread_id`, `type`, `model`, `provider`: String fields with full operator support
                - `status`: String field (=, contains, not_contains only)
                - `start_time`, `end_time`: DateTime fields (use ISO 8601 format, e.g., "2024-01-01T00:00:00Z")
                - `input`, `output`: String fields for content (=, contains, not_contains only)
                - `metadata`: Dictionary field (use dot notation, e.g., "metadata.model")
                - `feedback_scores`: Numeric field (use dot notation, e.g., "feedback_scores.accuracy")
                - `tags`: List field (use "contains" operator only)
                - `usage.total_tokens`, `usage.prompt_tokens`, `usage.completion_tokens`: Numeric usage fields
                - `duration`, `number_of_messages`, `total_estimated_cost`: Numeric fields

                Supported operators by column:
                - `id`, `name`, `created_by`, `thread_id`, `type`, `model`, `provider`: =, !=, contains, not_contains, starts_with, ends_with, >, <
                - `status`: =, contains, not_contains
                - `start_time`, `end_time`: =, >, <, >=, <=
                - `input`, `output`: =, contains, not_contains
                - `metadata`: =, contains, >, <
                - `feedback_scores`: =, >, <, >=, <=, is_empty, is_not_empty
                - `tags`: contains (only)
                - `usage.total_tokens`, `usage.prompt_tokens`, `usage.completion_tokens`, `duration`, `number_of_messages`, `total_estimated_cost`: =, !=, >, <, >=, <=

                Examples:
                - `status = "inactive"` - Filter by thread status
                - `id = "thread_123"` - Filter by specific thread ID
                - `duration > 300` - Filter by thread duration (seconds)
                - `number_of_messages >= 5` - Filter by message count
                - `feedback_scores.user_frustration > 0.5` - Filter by feedback score
                - `feedback_scores.my_metric is_empty` - Filter threads with empty feedback score
                - `feedback_scores.my_metric is_not_empty` - Filter threads with non-empty feedback score
                - `tags contains "important"` - Filter by tag

                If not provided, all threads in the project will be returned up to the limit.
            max_results:
                The maximum number of threads to retrieve. The default value is 1000
                if not specified.
            truncate:
                Whether to truncate image data stored in input, output, or metadata

        Returns:
            List[TraceThread]: A list of TraceThread objects that match the search
            criteria.

        Example:
            >>> from opik import Opik
            >>> client = Opik(api_key="YOUR_API_KEY", workspace_name="YOUR_WORKSPACE_NAME")
            >>> thread_id = "your_thread_id"
            >>> threads = client.get_threads_client().search_threads(
            >>>     project_name="Demo Project",
            >>>     filter_string=f'id = "{thread_id}"',
            >>>     max_results=10)
        threads)parsed_item_classentity_typec                 l    j                   j                  j                  j                  | |      S )N)r   filterslimitr   last_retrieved_thread_model_id)r   rest_clienttracessearch_trace_threads)current_batch_sizelast_retrieved_idr%   r   r   r   s     r   <lambda>z.ThreadsClient.search_threads.<locals>.<lambda>x   s8    #00<<CCXX)(!/@  Y  r   )read_sourcer   r"   )	r   parse_filter_expressionsr   TraceThreadFilterr   r   r	   read_and_parse_full_streamr   )r   r   r   r   r   r!   r%   s   ``  ` @r   search_threadszThreadsClient.search_threads!   sa    \ 221CC!
 $Et'8'8'E'E$?? $)
 r   scoresc                    |xs | j                   j                  }t        j                  ||t        j
                  t              }|t        j                  d|        yt        j                  |t        j                  t        j                        D ]=  }t	        j                  |      }| j                   j                  j!                  |       ? y)a  
        Logs feedback scores for threads in a specific project. This method processes the given
        feedback scores and associates them with the specified project if a project name is
        provided. It is designed to handle multiple scores in a structured manner.

        Args:
            scores: A list of dictionaries containing feedback scores
                for threads to be logged. Specifying a thread id via `id` key for each score is mandatory.
            project_name: The name of the project to associate with the logged
                scores. If not provided, the project name configured in the Opik client will be used.
                This parameter is used as a fallback if `project_name` is not specified in the score dictionary.
        )r3   r   r"   loggerNz<No valid threads feedback scores to log from provided ones: )max_payload_size_MB
max_length)batch)r   r   r   parse_feedback_score_messagesr   ThreadsFeedbackScoreMessageLOGGERerrorr   split_into_batchesr   MAX_BATCH_SIZE_MBr
   FEEDBACK_SCORES_MAX_BATCH_SIZE$AddThreadsFeedbackScoresBatchMessage	_streamerput)r   r3   r   score_messagesr8   )add_threads_feedback_scores_batch_messages         r   log_threads_feedback_scoresz)ThreadsClient.log_threads_feedback_scores   s     $Et'8'8'E'E >>%&BB	
 !LLNvhW &99 & 8 8 ??
E ==EJ 6 ''++,UV
r   	thread_idc                     ddl }|j                  dt        d       | j                  j                  j
                  j                  ||       y)a  
        Closes a thread in a specific project.

        .. deprecated::
            This method is deprecated. Thread status (active/inactive) is no longer
            required for adding feedback scores. Feedback scores can now be added
            to threads at any time. This method is kept for backwards compatibility
            but will be removed in a future version.

        Args:
            thread_id: The identifier of the thread to close.
            project_name: The name of the project to close the thread in.
        r   Nzclose_thread() is deprecated. Thread status is no longer required for adding feedback scores. Feedback scores can now be added to threads at any time. This method will be removed in a future version.r   )
stacklevel)rF   r   )warningswarnDeprecationWarningr   r(   r)   close_trace_thread)r   rF   r   rI   s       r   close_threadzThreadsClient.close_thread   sS     	I  	 	
 	%%,,??l 	@ 	
r   c                     | j                   S r   r   )r   s    r   opik_clientzThreadsClient.opik_client   s       r   )r   	opik.Opik)NNi  Tr   )r   rP   )__name__
__module____qualname____doc__r   r   strintboolr   r   r2   r   rE   rM   propertyrO    r   r   r   r      s    	#
 '+'+bsmb  }b 	b
 b 
k	bJ SW&W12&WBJ3-&W	&WP
c 
 
 
6 ! !r   r   )loggingtypingr   r   opikopik.rest_apir   
opik.typesr    r   r	   r
   r   message_processingr   message_processing.batchingr   rest_api.typesr   	getLoggerrQ   r;   r   rY   r   r   <module>rd      sF     !  % - 5 5  * < 1 
		8	$x! x!r   