forked from google/adk-python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathllm_response.py
More file actions
188 lines (151 loc) · 6.55 KB
/
Copy pathllm_response.py
File metadata and controls
188 lines (151 loc) · 6.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import annotations
from typing import Any
from typing import Optional
from typing import Union
from google.genai import types
from pydantic import alias_generators
from pydantic import BaseModel
from pydantic import ConfigDict
from .cache_metadata import CacheMetadata
class LlmResponse(BaseModel):
"""LLM response class that provides the first candidate response from the
model if available. Otherwise, returns error code and message.
Attributes:
content: The content of the response.
grounding_metadata: The grounding metadata of the response.
partial: Indicates whether the text content is part of a unfinished text
stream. Only used for streaming mode and when the content is plain text.
turn_complete: Indicates whether the response from the model is complete.
Only used for streaming mode.
error_code: Error code if the response is an error. Code varies by model.
error_message: Error message if the response is an error.
interrupted: Flag indicating that LLM was interrupted when generating the
content. Usually it's due to user interruption during a bidi streaming.
custom_metadata: The custom metadata of the LlmResponse.
input_transcription: Audio transcription of user input.
output_transcription: Audio transcription of model output.
avg_logprobs: Average log probability of the generated tokens.
logprobs_result: Detailed log probabilities for chosen and top candidate tokens.
"""
model_config = ConfigDict(
extra='forbid',
alias_generator=alias_generators.to_camel,
populate_by_name=True,
)
"""The pydantic model config."""
content: Optional[types.Content] = None
"""The generative content of the response.
This should only contain content from the user or the model, and not any
framework or system-generated data.
"""
grounding_metadata: Optional[types.GroundingMetadata] = None
"""The grounding metadata of the response."""
partial: Optional[bool] = None
"""Indicates whether the text content is part of a unfinished text stream.
Only used for streaming mode and when the content is plain text.
"""
turn_complete: Optional[bool] = None
"""Indicates whether the response from the model is complete.
Only used for streaming mode.
"""
finish_reason: Optional[Union[types.FinishReason, str]] = None
"""The finish reason of the response.
Can be either a types.FinishReason enum (from Gemini) or a string (from LiteLLM).
"""
error_code: Optional[str] = None
"""Error code if the response is an error. Code varies by model."""
error_message: Optional[str] = None
"""Error message if the response is an error."""
interrupted: Optional[bool] = None
"""Flag indicating that LLM was interrupted when generating the content.
Usually it's due to user interruption during a bidi streaming.
"""
custom_metadata: Optional[dict[str, Any]] = None
"""The custom metadata of the LlmResponse.
An optional key-value pair to label an LlmResponse.
NOTE: the entire dict must be JSON serializable.
"""
usage_metadata: Optional[types.GenerateContentResponseUsageMetadata] = None
"""The usage metadata of the LlmResponse"""
live_session_resumption_update: Optional[
types.LiveServerSessionResumptionUpdate
] = None
"""The session resumption update of the LlmResponse"""
input_transcription: Optional[types.Transcription] = None
"""Audio transcription of user input."""
output_transcription: Optional[types.Transcription] = None
"""Audio transcription of model output."""
avg_logprobs: Optional[float] = None
"""Average log probability of the generated tokens."""
logprobs_result: Optional[types.LogprobsResult] = None
"""Detailed log probabilities for chosen and top candidate tokens."""
cache_metadata: Optional[CacheMetadata] = None
"""Context cache metadata if caching was used for this response.
Contains cache identification, usage tracking, and lifecycle information.
This field is automatically populated when context caching is enabled.
"""
citation_metadata: Optional[types.CitationMetadata] = None
"""Citation metadata for the response.
This field is automatically populated when citation is enabled.
"""
@staticmethod
def create(
generate_content_response: types.GenerateContentResponse,
) -> LlmResponse:
"""Creates an LlmResponse from a GenerateContentResponse.
Args:
generate_content_response: The GenerateContentResponse to create the
LlmResponse from.
Returns:
The LlmResponse.
"""
usage_metadata = generate_content_response.usage_metadata
if generate_content_response.candidates:
candidate = generate_content_response.candidates[0]
if candidate.content and candidate.content.parts:
return LlmResponse(
content=candidate.content,
grounding_metadata=candidate.grounding_metadata,
usage_metadata=usage_metadata,
finish_reason=candidate.finish_reason,
citation_metadata=candidate.citation_metadata,
avg_logprobs=candidate.avg_logprobs,
logprobs_result=candidate.logprobs_result,
)
else:
return LlmResponse(
error_code=candidate.finish_reason,
error_message=candidate.finish_message,
citation_metadata=candidate.citation_metadata,
usage_metadata=usage_metadata,
finish_reason=candidate.finish_reason,
avg_logprobs=candidate.avg_logprobs,
logprobs_result=candidate.logprobs_result,
)
else:
if generate_content_response.prompt_feedback:
prompt_feedback = generate_content_response.prompt_feedback
return LlmResponse(
error_code=prompt_feedback.block_reason,
error_message=prompt_feedback.block_reason_message,
usage_metadata=usage_metadata,
)
else:
return LlmResponse(
error_code='UNKNOWN_ERROR',
error_message='Unknown error.',
usage_metadata=usage_metadata,
)