[docs]classOutputFunctionsParser(BaseGenerationOutputParser[Any]):"""Parse an output that is one of sets of values."""args_only:bool=True"""Whether to only return the arguments to the function call."""
[docs]defparse_result(self,result:List[Generation],*,partial:bool=False)->Any:"""Parse the result of an LLM call to a JSON object. Args: result: The result of the LLM call. partial: Whether to parse partial JSON objects. Default is False. Returns: The parsed JSON object. Raises: OutputParserException: If the output is not valid JSON. """generation=result[0]ifnotisinstance(generation,ChatGeneration):raiseOutputParserException("This output parser can only be used with a chat generation.")message=generation.messagetry:func_call=copy.deepcopy(message.additional_kwargs["function_call"])exceptKeyErrorasexc:raiseOutputParserException(f"Could not parse function call: {exc}")fromexcifself.args_only:returnfunc_call["arguments"]returnfunc_call
[docs]classJsonOutputFunctionsParser(BaseCumulativeTransformOutputParser[Any]):"""Parse an output as the Json object."""strict:bool=False"""Whether to allow non-JSON-compliant strings. See: https://docs.python.org/3/library/json.html#encoders-and-decoders Useful when the parsed output may include unicode characters or new lines. """args_only:bool=True"""Whether to only return the arguments to the function call."""@propertydef_type(self)->str:return"json_functions"def_diff(self,prev:Optional[Any],next:Any)->Any:returnjsonpatch.make_patch(prev,next).patch
[docs]defparse_result(self,result:List[Generation],*,partial:bool=False)->Any:"""Parse the result of an LLM call to a JSON object. Args: result: The result of the LLM call. partial: Whether to parse partial JSON objects. Default is False. Returns: The parsed JSON object. Raises: OutputParserException: If the output is not valid JSON. """iflen(result)!=1:raiseOutputParserException(f"Expected exactly one result, but got {len(result)}")generation=result[0]ifnotisinstance(generation,ChatGeneration):raiseOutputParserException("This output parser can only be used with a chat generation.")message=generation.messagetry:function_call=message.additional_kwargs["function_call"]exceptKeyErrorasexc:ifpartial:returnNoneelse:raiseOutputParserException(f"Could not parse function call: {exc}")fromexctry:ifpartial:try:ifself.args_only:returnparse_partial_json(function_call["arguments"],strict=self.strict)else:return{**function_call,"arguments":parse_partial_json(function_call["arguments"],strict=self.strict),}exceptjson.JSONDecodeError:returnNoneelse:ifself.args_only:try:returnjson.loads(function_call["arguments"],strict=self.strict)except(json.JSONDecodeError,TypeError)asexc:raiseOutputParserException(f"Could not parse function call data: {exc}")fromexcelse:try:return{**function_call,"arguments":json.loads(function_call["arguments"],strict=self.strict),}except(json.JSONDecodeError,TypeError)asexc:raiseOutputParserException(f"Could not parse function call data: {exc}")fromexcexceptKeyError:returnNone
# This method would be called by the default implementation of `parse_result`# but we're overriding that method so it's not needed.
[docs]defparse(self,text:str)->Any:"""Parse the output of an LLM call to a JSON object. Args: text: The output of the LLM call. Returns: The parsed JSON object. """raiseNotImplementedError()
[docs]classJsonKeyOutputFunctionsParser(JsonOutputFunctionsParser):"""Parse an output as the element of the Json object."""key_name:str"""The name of the key to return."""
[docs]defparse_result(self,result:List[Generation],*,partial:bool=False)->Any:"""Parse the result of an LLM call to a JSON object. Args: result: The result of the LLM call. partial: Whether to parse partial JSON objects. Default is False. Returns: The parsed JSON object. """res=super().parse_result(result,partial=partial)ifpartialandresisNone:returnNonereturnres.get(self.key_name)ifpartialelseres[self.key_name]
[docs]classPydanticOutputFunctionsParser(OutputFunctionsParser):"""Parse an output as a pydantic object. This parser is used to parse the output of a ChatModel that uses OpenAI function format to invoke functions. The parser extracts the function call invocation and matches them to the pydantic schema provided. An exception will be raised if the function call does not match the provided schema. Example: ... code-block:: python message = AIMessage( content="This is a test message", additional_kwargs={ "function_call": { "name": "cookie", "arguments": json.dumps({"name": "value", "age": 10}), } }, ) chat_generation = ChatGeneration(message=message) class Cookie(BaseModel): name: str age: int class Dog(BaseModel): species: str # Full output parser = PydanticOutputFunctionsParser( pydantic_schema={"cookie": Cookie, "dog": Dog} ) result = parser.parse_result([chat_generation]) """pydantic_schema:Union[Type[BaseModel],Dict[str,Type[BaseModel]]]"""The pydantic schema to parse the output with. If multiple schemas are provided, then the function name will be used to determine which schema to use. """@root_validator(pre=True)defvalidate_schema(cls,values:Dict)->Dict:"""Validate the pydantic schema. Args: values: The values to validate. Returns: The validated values. Raises: ValueError: If the schema is not a pydantic schema. """schema=values["pydantic_schema"]if"args_only"notinvalues:values["args_only"]=isinstance(schema,type)andissubclass(schema,BaseModel)elifvalues["args_only"]andisinstance(schema,Dict):raiseValueError("If multiple pydantic schemas are provided then args_only should be"" False.")returnvalues
[docs]defparse_result(self,result:List[Generation],*,partial:bool=False)->Any:"""Parse the result of an LLM call to a JSON object. Args: result: The result of the LLM call. partial: Whether to parse partial JSON objects. Default is False. Returns: The parsed JSON object. """_result=super().parse_result(result)ifself.args_only:pydantic_args=self.pydantic_schema.parse_raw(_result)# type: ignoreelse:fn_name=_result["name"]_args=_result["arguments"]pydantic_args=self.pydantic_schema[fn_name].parse_raw(_args)# type: ignorereturnpydantic_args
[docs]classPydanticAttrOutputFunctionsParser(PydanticOutputFunctionsParser):"""Parse an output as an attribute of a pydantic object."""attr_name:str"""The name of the attribute to return."""
[docs]defparse_result(self,result:List[Generation],*,partial:bool=False)->Any:"""Parse the result of an LLM call to a JSON object. Args: result: The result of the LLM call. partial: Whether to parse partial JSON objects. Default is False. Returns: The parsed JSON object. """result=super().parse_result(result)returngetattr(result,self.attr_name)