
    6iLk                    t   d 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	 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 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 er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- d
dl.m/Z/m0Z0m1Z1m2Z2 d
dl3m4Z4m5Z5m6Z6 d
dl7m8Z8m9Z9m:Z: d
dl;m<Z<m=Z=m>Z>m?Z? d
dl@mAZAmBZBmCZCmDZDmEZEmFZFmGZGmHZHmIZImJZJmKZKmLZLmMZM d
dlNmOZOmPZPmQZQmRZR d
dlSmTZTmUZUmVZVmWZWmXZXmYZYmZZZm[Z[m\Z\m]Z]m^Z^m_Z_m`Z` d
dlambZbmcZc d
dldmeZemfZfmgZgmhZh d
dlimjZjmkZkmlZlmmZm  ej                  d       Zo ed!e"      Zp ed#      Zq ed$      Zr ed%      Zsd&dde"j                  d'	 	 	 	 	 	 	 	 	 	 	 	 	 d.d(Zuddde"j                  d)	 	 	 	 	 	 	 	 	 	 	 d/d*Zvd0d+Zwe"j                  f	 	 	 	 	 	 	 d1d,Zx	 d2	 	 	 	 	 	 	 	 	 	 	 d3d-Zyy)4a  
This module serves as the central dispatcher for processing responses from various LLM providers
(OpenAI, Anthropic, Google, Cohere, etc.) and transforming them into structured Pydantic models.
It handles different response formats, streaming responses, validation, and error recovery.

The module supports 40+ different modes across providers, each with specific handling logic
for request formatting and response parsing. It also provides retry mechanisms (reask) for
handling validation errors gracefully.

Key Components:
    - Response processing functions for sync/async operations
    - Mode-based response model handlers for different providers
    - Error recovery and retry logic for validation failures
    - Support for streaming, partial, parallel, and iterable response models

Example:
    ```python
    from instructor.process_response import process_response
    from ..mode import Mode
    from pydantic import BaseModel

    class User(BaseModel):
        name: str
        age: int

    # Process an OpenAI response
    processed = process_response(
        response=openai_response,
        response_model=User,
        mode=Mode.TOOLS,
        stream=False
    )
    ```
    )annotationsN)AnyTypeVarTYPE_CHECKINGcast)AsyncGenerator)ChatCompletion)	BaseModel)	ParamSpec)InstructorErrorConfigurationError   )IterableBase)ParallelBase)PartialBase)ListResponse)AdapterBase   )OpenAISchema)Mode)convert_messages)prepare_response_model)handle_anthropic_jsonhandle_anthropic_parallel_tools handle_anthropic_reasoning_toolshandle_anthropic_toolsreask_anthropic_jsonreask_anthropic_tools)handle_bedrock_jsonhandle_bedrock_toolsreask_bedrock_jsonreask_bedrock_tools)handle_cerebras_jsonhandle_cerebras_toolsreask_cerebras_tools)handle_cohere_json_schemahandle_cohere_toolsreask_cohere_tools)handle_fireworks_jsonhandle_fireworks_toolsreask_fireworks_jsonreask_fireworks_tools)handle_gemini_jsonhandle_gemini_toolshandle_genai_structured_outputshandle_genai_toolshandle_vertexai_jsonhandle_vertexai_parallel_toolshandle_vertexai_toolsreask_gemini_jsonreask_gemini_toolsreask_genai_structured_outputsreask_genai_toolsreask_vertexai_jsonreask_vertexai_tools)!handle_mistral_structured_outputshandle_mistral_tools reask_mistral_structured_outputsreask_mistral_tools)handle_functionshandle_json_modeshandle_json_o1$handle_openrouter_structured_outputshandle_parallel_toolshandle_responses_tools)handle_responses_tools_with_inbuilt_toolshandle_toolshandle_tools_strictreask_defaultreask_md_jsonreask_responses_toolsreask_tools)handle_perplexity_jsonreask_perplexity_json)handle_writer_jsonhandle_writer_toolsreask_writer_jsonreask_writer_tools)handle_xai_jsonhandle_xai_toolsreask_xai_jsonreask_xai_tools
instructorT_Model)boundT_RetvalT_ParamSpecTF)streamvalidation_contextstrictmodec               2  K   t         j                  d|         || S t        j                  |      r<t	        |t
              r,|r*|j                  t        t        t        df   |       |      S t        j                  |      r<t	        |t              r,|r*|j                  t        t        t        df   |       |      S |j                  | |||      }t        |t
              rDt         j                  d       t        j                  |j                  D cg c]  }| c}|       S t        |t               rt         j                  d       | |_        |S t        |t$              r!t         j                  d       |j&                  S | |_        |S c c}w w)	a	  Asynchronously process and transform LLM responses into structured models.

    This function is the async entry point for converting raw LLM responses into validated
    Pydantic models. It handles various response formats from different providers and
    supports special response types like streaming, partial objects, and parallel tool calls.

    Args:
        response (ChatCompletion or Similar API Response): The raw response from the LLM API. Despite the type hint,
            this can be responses from any supported provider (OpenAI, Anthropic, Google, etc.)
        response_model (type[T_Model | BaseModel] | None): The target Pydantic
            model to parse the response into. If None, returns the raw response unchanged.
            Can also be special DSL types like ParallelBase for parallel tool calls, or IterableBase and PartialBase for streaming.
        stream (bool): Whether this is a streaming response. Required for proper handling
            of IterableBase and PartialBase models. Defaults to False.
        validation_context (dict[str, Any] | None): Additional context passed to Pydantic
            validators during model validation. Useful for dynamic validation logic. The context
            is also used to format templated responses. Defaults to None.
        strict (bool | None): Whether to enforce strict JSON parsing. When True, the response
            must exactly match the model schema. When False, allows minor deviations.
        mode (Mode): The provider/format mode that determines how to parse the response.
            Examples: Mode.TOOLS (OpenAI), Mode.ANTHROPIC_JSON, Mode.GEMINI_TOOLS.
            Defaults to Mode.TOOLS.

    Returns:
        T_Model | ChatCompletion: The processed response. Return type depends on inputs:
            - If response_model is None: returns raw response unchanged
            - If response_model is IterableBase with stream=True: returns list of models
            - If response_model is AdapterBase: returns the adapted content
            - Otherwise: returns instance of response_model with _raw_response attached

    Raises:
        ValidationError: If the response doesn't match the expected model schema
        IncompleteOutputException: If the response was truncated due to token limits
        ValueError: If an invalid mode is specified

    Note:
        The function automatically detects special response model types (Iterable, Partial,
        Parallel, Adapter) and applies appropriate processing logic for each.
    Instructor Raw Response: Nr^   r\   r]   r^   !Returning takes from IterableBaseraw_response!Returning model from ParallelBase Returning model from AdapterBase)loggerdebuginspectisclass
issubclassr   from_streaming_response_asyncr   r   r   r   from_response
isinstancer   	from_listtasksr   _raw_responser   contentresponseresponse_modelr[   r\   r]   r^   modeltasks           i/root/.openclaw/workspace/visionaryfx/venv/lib/python3.12/site-packages/instructor/processing/response.pyprocess_response_asyncrz      s    b LL
#H:.  	'~|4 ;;T	*H5 < 
 	
 	'~{3 ;;T	*H5 < 
 	

 ((-	 ) E %&8:%%#kk*dT*!
 	

 .,/8:&%%79}}"EL +s   DF	F!A6F)rv   r\   r]   r^   c               
   t         j                  d|         |t         j                  d       | S t        j                  |      r%t	        |t
              r|r|j                  | |      S t        j                  |      r.t	        |t              r|rt        |j                  | |            S |j                  | |||      }t        |t
              rDt         j                  d       t        j                  |j                  D cg c]  }| c}|       S t        |t              rt         j                  d       | |_        |S t        |t               r!t         j                  d       |j"                  S | |_        |S c c}w )	aS  Process and transform LLM responses into structured models (synchronous).

    This is the main entry point for converting raw LLM responses into validated Pydantic
    models. It acts as a dispatcher that handles various response formats from 40+ different
    provider modes and transforms them according to the specified response model type.

    Args:
        response (T_Model): The raw response from the LLM API. The actual type varies by
            provider (ChatCompletion for OpenAI, Message for Anthropic, etc.)
        response_model (type[OpenAISchema | BaseModel] | None): The target Pydantic model
            class to parse the response into. Special DSL types supported:
            - IterableBase: For streaming multiple objects from a single response
            - PartialBase: For incomplete/streaming partial objects
            - ParallelBase: For parallel tool/function calls
            - AdapterBase: For simple type adaptations (e.g., str, int)
            If None, returns the raw response unchanged.
        stream (bool): Whether this is a streaming response. Required to be True for
            proper handling of IterableBase and PartialBase models.
        validation_context (dict[str, Any] | None): Additional context passed to Pydantic
            validators. Useful for runtime validation logic based on external state.
        strict (bool | None): Controls JSON parsing strictness:
            - True: Enforce exact schema matching (no extra fields)
            - False/None: Allow minor deviations and extra fields
        mode (Mode): The provider/format mode that determines parsing strategy.
            Each mode corresponds to a specific provider and format combination:
            - Tool modes: TOOLS, ANTHROPIC_TOOLS, GEMINI_TOOLS, etc.
            - JSON modes: JSON, ANTHROPIC_JSON, VERTEXAI_JSON, etc.
            - Special modes: PARALLEL_TOOLS, MD_JSON, JSON_SCHEMA, etc.

    Returns:
        T_Model | list[T_Model] | None: The processed response:
            - If response_model is None: Original response unchanged
            - If IterableBase: List of extracted model instances
            - If ParallelBase: Special parallel response object
            - If AdapterBase: The adapted simple type (str, int, etc.)
            - Otherwise: Single instance of response_model with _raw_response attached

    Raises:
        ValidationError: Response doesn't match the expected model schema
        IncompleteOutputException: Response truncated due to token limits
        ValueError: Invalid mode specified or mode not supported
        JSONDecodeError: Malformed JSON in response (for JSON modes)

    Note:
        The function preserves the raw response by attaching it to the parsed model
        as `_raw_response`. This allows access to metadata like token usage, model
        info, and other provider-specific fields after parsing.
    r`   z+No response model, returning response as isra   rb   rc   rd   rf   rg   )rh   ri   rj   rk   rl   r   from_streaming_responser   listrn   ro   r   rp   rq   r   rr   r   rs   rt   s           ry   process_responser~     sp   r LL
#H:. BC 	'~|4 55 6 
 	
 	'~{3 22 3 
 	
 ((-	 ) E %&8:%%#kk*dT*!
 	

 .,/8:&%%79}}"EL +s   	F c                b    t        | t              xr t        | t              xr t	        | d      S )N__annotations__)ro   typerl   dicthasattr)clss    ry   is_typed_dictr     s0    3 	,sD!	,C*+    c           
        |j                         }|j                  dd      t        j                  t        t        j
                  t        t        j                  t        i}||v rn ||   | |      \  } }t        j                  d|j                  d| d||j                  | t        | d      r| j                  n
t        |       |d       | |fS | t        |       } i t        j                   t"        t        j$                  t&        t        j(                  t*        t        j,                  t.        t        j0                  t2        t        j4                  t6        t        j8                  d	 t        j:                  d
 t        j<                  d t        j>                  t@        t        jB                  tD        t        jF                  tH        t        jJ                  tL        t        jN                  tP        t        jR                  tT        t        jV                  tX        t        jZ                  fdi t        j\                  fdt        j^                  t`        t        jb                  td        t        jf                  th        t        jj                  tl        t        jn                  tp        t        jr                  tt        t        jv                  tx        t        jz                  t|        t        j~                  t        t        j                  t        t        j                  t        t        j                  t        t        j                  t        t        j                  t        t        j                  t        t        j                  t        }||v r ||   | |      \  } }n5t        d| ddj                  d |j                         D                     d|v rt        |d   |      |d<   t        j                  d|j                  d| d||j                  | t        | d      r| j                  n
t        |       |d       | |fS )a  
    Handles the response model based on the specified mode and prepares the kwargs for the API call.
    This really should be named 'prepare_create_kwargs' as its job is to map the openai create kwargs
    to the correct format for the API call based on the mode.

    Args:
        response_model (type[T] | None): The response model to be used for parsing the API response.
        mode (Mode): The mode to use for handling the response model. Defaults to Mode.TOOLS.
        **kwargs: Additional keyword arguments to be passed to the API call.

    Returns:
        tuple[type[T] | None, dict[str, Any]]: A tuple containing the processed response model and the updated kwargs.

    This function prepares the response model and modifies the kwargs based on the specified mode.
    It handles various modes like TOOLS, JSON, FUNCTIONS, etc., and applies the appropriate
    transformations to the response model and kwargs.
    autodetect_imagesFzInstructor Request: mode.value=z, response_model=z, new_kwargs=__name__)r^   rv   
new_kwargs)extrac                8    t        | |t        j                        S N)r?   r   JSONrmnks     ry   <lambda>z'handle_response_model.<locals>.<lambda>  s    "3BDII"F r   c                8    t        | |t        j                        S r   )r?   r   MD_JSONr   s     ry   r   z'handle_response_model.<locals>.<lambda>  s    %6r2t||%L r   c                8    t        | |t        j                        S r   )r?   r   JSON_SCHEMAr   s     ry   r   z'handle_response_model.<locals>.<lambda>  s    ):2r4CSCS)T r   c                    t        | |      S r   )r0   r   r   r   s     ry   r   z'handle_response_model.<locals>.<lambda>  s    );BDU)V r   c                    t        | |      S r   )r/   r   s     ry   r   z'handle_response_model.<locals>.<lambda>  s    6U%7
 r   zInvalid or unsupported mode: z5. This mode may not be implemented. Available modes: z, c              3  2   K   | ]  }t        |        y wr   )str).0ms     ry   	<genexpr>z(handle_response_model.<locals>.<genexpr>  s     )OQ#a&)Os   messages)r   )Scopypopr   PARALLEL_TOOLSrB   VERTEXAI_PARALLEL_TOOLSr2   ANTHROPIC_PARALLEL_TOOLSr   rh   ri   valuer   r   r   r   	FUNCTIONSr>   TOOLS_STRICTrF   TOOLSrE   MISTRAL_TOOLSr;   MISTRAL_STRUCTURED_OUTPUTSr:   JSON_O1r@   r   r   r   ANTHROPIC_TOOLSr   ANTHROPIC_REASONING_TOOLSr   ANTHROPIC_JSONr   COHERE_JSON_SCHEMAr&   COHERE_TOOLSr'   GEMINI_JSONr-   GEMINI_TOOLSr.   GENAI_TOOLSGENAI_STRUCTURED_OUTPUTSVERTEXAI_TOOLSr3   VERTEXAI_JSONr1   CEREBRAS_JSONr#   CEREBRAS_TOOLSr$   FIREWORKS_JSONr)   FIREWORKS_TOOLSr*   WRITER_TOOLSrN   WRITER_JSONrM   BEDROCK_JSONr   BEDROCK_TOOLSr    PERPLEXITY_JSONrK   OPENROUTER_STRUCTURED_OUTPUTSrA   RESPONSES_TOOLSrC   "RESPONSES_TOOLS_WITH_INBUILT_TOOLSrD   XAI_JSONrQ   	XAI_TOOLSrR   r   joinkeysr   )rv   r^   kwargsr   PARALLEL_MODESmode_handlersr   s         @ry   handle_response_modelr     sm   * J"':EB 	2$$&D%%'FN ~%9^D%9.*%U"
.4::-/A.1B.ZMR

 &1
; #++ ^,(	 	 	
 z)) !/?%(%.% 	

L% 	0	%
 	'')J% 	n% 			F% 	L% 	T% 	4% 	&&(H% 	2% 	!:% 	.% 	,%  	.!%" 	V#%$ 	%% (
%%* 	2+%, 	0-%. 	0/%0 	21%2 	23%4 	45%6 	.7%8 	,9%: 	.;%< 	0=%> 	4?%@ 	**,PA%B 	4C%D 	//1ZE%F 	G%H 	(I%MN }%8]4%8%T"
 +D6 2  $		)O-:L:L:N)O OPR
 	
 Z!1z"/"

: LL
*tzzm+=n->nNJJ "-'.*2U ''($
   :%%r   c                   | j                         }t        j                  ||      }i t        j                  t
        t        j                  t        t        j                  t        t        j                  t
        t        j                  t        t        j                  t        t        j                  t        t        j                  t        t        j                  t         t        j"                  t         t        j$                  t&        t        j(                  t*        t        j,                  t.        t        j0                  t.        t        j2                  t4        t        j6                  t.        t        j8                  t:        i t        j<                  t:        t        j>                  t@        t        jB                  tD        t        jF                  tH        t        jJ                  tL        t        jN                  tP        t        jR                  tT        t        jV                  tP        t        jX                  tZ        t        j\                  t
        t        j^                  t`        t        jb                  td        t        jf                  th        t        jj                  tl        t        jn                  tp        t        jr                  tt        t        jv                  tx        t        jz                  t
        t        j|                  t~        t        j                  t        i}||v r ||   |||      S t        |||      S )al  Handle validation errors by reformatting the request for retry (reask).

    This function serves as the central dispatcher for handling validation failures
    across all supported LLM providers. When a response fails validation, it prepares
    a new request that includes detailed error information and retry context, allowing
    the LLM to understand what went wrong and generate a corrected response.

    The reask process involves:
    1. Analyzing the validation error and failed response
    2. Selecting the appropriate provider-specific reask handler
    3. Enriching the exception with retry history (failed_attempts)
    4. Formatting error feedback in the provider's expected message format
    5. Preserving original request parameters while adding retry context

    Args:
        kwargs (dict[str, Any]): The original request parameters that resulted in
            a validation error. Contains all parameters passed to the LLM API:
            - messages: conversation history
            - tools/functions: available function definitions
            - temperature, max_tokens: generation parameters
            - model, provider-specific settings
        mode (Mode): The provider/format mode that determines which reask handler
            to use. Each mode implements a specific strategy for formatting error
            feedback and retry messages. Examples:
            - Mode.TOOLS: OpenAI function calling
            - Mode.ANTHROPIC_TOOLS: Anthropic tool use
            - Mode.JSON: JSON-only responses
        response (Any): The raw response from the LLM that failed validation.
            Type and structure varies by provider:
            - OpenAI: ChatCompletion with tool_calls or content
            - Anthropic: Message with tool_use blocks or text content
            - Google: GenerateContentResponse with function calls
            - Cohere: NonStreamedChatResponse with tool calls
        exception (Exception): The validation error that occurred, typically:
            - Pydantic ValidationError: field validation failures
            - JSONDecodeError: malformed JSON responses
            - Custom validation errors from response processors
            The exception will be enriched with failed_attempts data.
        failed_attempts (list[FailedAttempt] | None): Historical record of previous
            retry attempts for this request. Each FailedAttempt contains:
            - attempt_number: sequential attempt counter
            - exception: the validation error for that attempt
            - completion: the raw LLM response that failed
            Used to provide retry context and prevent repeated mistakes.

    Returns:
        dict[str, Any]: Modified kwargs for the retry request with:
            - Updated messages including error feedback
            - Original tool/function definitions preserved
            - Generation parameters maintained (temperature, etc.)
            - Provider-specific error formatting applied
            - Retry context embedded in appropriate message format

    Provider-Specific Reask Strategies:
        **OpenAI Modes:**
        - TOOLS/FUNCTIONS: Adds tool response messages with validation errors
        - JSON modes: Appends user message with correction instructions
        - Preserves function schemas and conversation context

        **Anthropic Modes:**
        - TOOLS: Creates tool_result blocks with error details
        - JSON: Adds user message with structured error feedback
        - Maintains conversation flow with proper message roles

        **Google/Gemini Modes:**
        - TOOLS: Formats as function response with error content
        - JSON: Appends user message with validation feedback

        **Other Providers (Cohere, Mistral, etc.):**
        - Provider-specific message formatting
        - Consistent error reporting patterns
        - Maintained conversation context

    Error Enrichment:
        The exception parameter is enriched with retry metadata:
        - exception.failed_attempts: list of previous failures
        - exception.retry_attempt_number: current attempt number
        This allows downstream handlers to access full retry context.

    Example:
        ```python
        # After a ValidationError occurs during retry attempt #2
        new_kwargs = handle_reask_kwargs(
            kwargs=original_request,
            mode=Mode.TOOLS,
            response=failed_completion,
            exception=validation_error,  # Will be enriched with failed_attempts
            failed_attempts=[attempt1, attempt2]  # Previous failures
        )
        # new_kwargs now contains retry messages with error context
        ```

    Note:
        This function is called internally by retry_sync() and retry_async()
        when max_retries > 1. It ensures each retry includes progressively
        more context about previous failures, helping the LLM learn from
        mistakes and avoid repeating the same errors.
    )failed_attempts)Br   r   from_exceptionr   r   rG   r   rJ   r   r   r   rH   r   r   r   r   rI   r   r   r=   r   r<   r   r   r   r   r   r   r   r(   r   r   r5   r   r4   r   r7   r   r6   r   r9   r   r8   r   r   r%   r   r   r,   r   r+   r   rP   r   rO   r   r"   r   r!   r   rL   r   r   rS   r   rT   )r   r^   ru   	exceptionr   kwargs_copyREASK_HANDLERSs          ry   handle_reask_kwargsr     s   T ++-K..?I
33 	;3 	

K	3
 	m3 			=3 	m3 	-3 	[3 	33 	//1F3 	/3 	'')I3  	3!3" 	&&(=#3$ 	1%3& 	%%'<'3* 	-+3, 	!3-30 	-132 	+334 	+536 	%%'E73: 	1;3< 	/=3> 	$$&:?3B 	1C3D 	ME3H 	3I3J 	1K3N 	-O3P 	+Q3T 	/U3V 	-W3Z 	3[3^ 	**M~e3Nj ~#~d#K9EE[(I>>r   )ru   r	   rv   z/type[T_Model | OpenAISchema | BaseModel] | Noner[   boolr\   dict[str, Any] | Noner]   zbool | Noner^   r   returnr   )ru   rV   rv   z%type[OpenAISchema | BaseModel] | Noner[   r   r\   r   r^   r   r   r   )r   r   )rv   ztype[T] | Noner^   r   r   r   r   z%tuple[type[T] | None, dict[str, Any]]r   )r   dict[str, Any]r^   r   ru   r   r   	Exceptionr   zlist[Any] | Noner   r   )z__doc__
__future__r   rj   loggingtypingr   r   r   r   collections.abcr   openai.types.chatr	   pydanticr
   typing_extensionsr   instructor.core.exceptionsr   r   dsl.iterabler   dsl.parallelr   dsl.partialr   dsl.response_listr   dsl.simple_typer   function_callsr   r^   r   
multimodalr   
utils.corer   providers.anthropic.utilsr   r   r   r   r   r   providers.bedrock.utilsr   r    r!   r"   providers.cerebras.utilsr#   r$   r%   providers.cohere.utilsr&   r'   r(   providers.fireworks.utilsr)   r*   r+   r,   providers.gemini.utilsr-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r8   r9   providers.mistral.utilsr:   r;   r<   r=   providers.openai.utilsr>   r?   r@   rA   rB   rC   rD   rE   rF   rG   rH   rI   rJ   providers.perplexity.utilsrK   rL   providers.writer.utilsrM   rN   rO   rP   providers.xai.utilsrQ   rR   rS   rT   	getLoggerrh   rV   rX   rY   rZ   r   rz   r~   r   r   r    r   ry   <module>r      sD  !F #   4 4 * ,  ' J ' ' % , ),  ( /        "    "   
		<	(
)9
-:&CL 04gg Dg 	g
 .g g g 	gZ =A04ss :s 	s
 .s s 	sl 26x&"x&*.x&GJx&*x&@ )-i?i?
i? i? 	i?
 &i? i?r   