@@ -2914,12 +2914,14 @@ class GenerateContentResponse(_common.BaseModel):
2914
2914
automatic_function_calling_history : Optional [list [Content ]] = None
2915
2915
parsed : Optional [Union [pydantic .BaseModel , dict , Enum ]] = Field (
2916
2916
default = None ,
2917
- description = """Parsed response if response_schema is provided. Not available for streaming.""" ,
2917
+ description = """First candidate from the parsed response if response_schema is provided. Not available for streaming.""" ,
2918
2918
)
2919
2919
2920
- @property
2921
- def text (self ) -> Optional [str ]:
2922
- """Returns the concatenation of all text parts in the response."""
2920
+ def _get_text (self , warn_property : str = 'text' ) -> Optional [str ]:
2921
+ """Returns the concatenation of all text parts in the response.
2922
+
2923
+ This is an internal method that allows customizing the warning message.
2924
+ """
2923
2925
if (
2924
2926
not self .candidates
2925
2927
or not self .candidates [0 ].content
@@ -2928,9 +2930,10 @@ def text(self) -> Optional[str]:
2928
2930
return None
2929
2931
if len (self .candidates ) > 1 :
2930
2932
logger .warning (
2931
- f'there are { len (self .candidates )} candidates, returning text from'
2932
- ' the first candidate.Access response.candidates directly to get'
2933
- ' text from other candidates.'
2933
+ f'there are { len (self .candidates )} candidates, returning'
2934
+ f' { warn_property } result from the first candidate. Access'
2935
+ ' response.candidates directly to get the result from other'
2936
+ ' candidates.'
2934
2937
)
2935
2938
text = ''
2936
2939
any_text_part_text = False
@@ -2949,12 +2952,18 @@ def text(self) -> Optional[str]:
2949
2952
if non_text_parts :
2950
2953
logger .warning (
2951
2954
'Warning: there are non-text parts in the response:'
2952
- f' { non_text_parts } ,returning concatenated text from text parts,check'
2953
- ' out the non text parts for full response from model.'
2955
+ f' { non_text_parts } ,returning concatenated { warn_property } result'
2956
+ ' from text parts,check out the non text parts for full response'
2957
+ ' from model.'
2954
2958
)
2955
2959
# part.text == '' is different from part.text is None
2956
2960
return text if any_text_part_text else None
2957
2961
2962
+ @property
2963
+ def text (self ) -> Optional [str ]:
2964
+ """Returns the concatenation of all text parts in the response."""
2965
+ return self ._get_text (warn_property = 'text' )
2966
+
2958
2967
@property
2959
2968
def function_calls (self ) -> Optional [list [FunctionCall ]]:
2960
2969
"""Returns the list of function calls in the response."""
@@ -3037,16 +3046,23 @@ def _from_response(
3037
3046
):
3038
3047
# Pydantic schema.
3039
3048
try :
3040
- if result .text is not None :
3041
- result .parsed = response_schema .model_validate_json (result .text )
3049
+ result_text = result ._get_text (warn_property = 'parsed' )
3050
+ if result_text is not None :
3051
+ result .parsed = response_schema .model_validate_json (result_text )
3042
3052
# may not be a valid json per stream response
3043
3053
except pydantic .ValidationError :
3044
3054
pass
3045
3055
except json .decoder .JSONDecodeError :
3046
3056
pass
3047
- elif isinstance (response_schema , EnumMeta ) and result .text is not None :
3057
+ elif (
3058
+ isinstance (response_schema , EnumMeta )
3059
+ and result ._get_text (warn_property = 'parsed' ) is not None
3060
+ ):
3048
3061
# Enum with "application/json" returns response in double quotes.
3049
- enum_value = result .text .replace ('"' , '' )
3062
+ result_text = result ._get_text (warn_property = 'parsed' )
3063
+ if result_text is None :
3064
+ raise ValueError ('Response is empty.' )
3065
+ enum_value = result_text .replace ('"' , '' )
3050
3066
try :
3051
3067
result .parsed = response_schema (enum_value )
3052
3068
if (
@@ -3064,8 +3080,9 @@ class Placeholder(pydantic.BaseModel):
3064
3080
placeholder : response_schema # type: ignore[valid-type]
3065
3081
3066
3082
try :
3067
- if result .text is not None :
3068
- parsed = {'placeholder' : json .loads (result .text )}
3083
+ result_text = result ._get_text (warn_property = 'parsed' )
3084
+ if result_text is not None :
3085
+ parsed = {'placeholder' : json .loads (result_text )}
3069
3086
placeholder = Placeholder .model_validate (parsed )
3070
3087
result .parsed = placeholder .placeholder
3071
3088
except json .decoder .JSONDecodeError :
@@ -3080,8 +3097,9 @@ class Placeholder(pydantic.BaseModel):
3080
3097
# want the result converted to. So just return json.
3081
3098
# JSON schema.
3082
3099
try :
3083
- if result .text is not None :
3084
- result .parsed = json .loads (result .text )
3100
+ result_text = result ._get_text (warn_property = 'parsed' )
3101
+ if result_text is not None :
3102
+ result .parsed = json .loads (result_text )
3085
3103
# may not be a valid json per stream response
3086
3104
except json .decoder .JSONDecodeError :
3087
3105
pass
@@ -3091,12 +3109,13 @@ class Placeholder(pydantic.BaseModel):
3091
3109
for union_type in union_types :
3092
3110
if issubclass (union_type , pydantic .BaseModel ):
3093
3111
try :
3094
- if result .text is not None :
3112
+ result_text = result ._get_text (warn_property = 'parsed' )
3113
+ if result_text is not None :
3095
3114
3096
3115
class Placeholder (pydantic .BaseModel ): # type: ignore[no-redef]
3097
3116
placeholder : response_schema # type: ignore[valid-type]
3098
3117
3099
- parsed = {'placeholder' : json .loads (result . text )}
3118
+ parsed = {'placeholder' : json .loads (result_text )}
3100
3119
placeholder = Placeholder .model_validate (parsed )
3101
3120
result .parsed = placeholder .placeholder
3102
3121
except json .decoder .JSONDecodeError :
@@ -3105,8 +3124,9 @@ class Placeholder(pydantic.BaseModel): # type: ignore[no-redef]
3105
3124
pass
3106
3125
else :
3107
3126
try :
3108
- if result .text is not None :
3109
- result .parsed = json .loads (result .text )
3127
+ result_text = result ._get_text (warn_property = 'parsed' )
3128
+ if result_text is not None :
3129
+ result .parsed = json .loads (result_text )
3110
3130
# may not be a valid json per stream response
3111
3131
except json .decoder .JSONDecodeError :
3112
3132
pass
0 commit comments