1818using System . Collections . ObjectModel ;
1919using System . Linq ;
2020using Google . MiniJSON ;
21+ using Firebase . VertexAI . Internal ;
2122
2223namespace Firebase . VertexAI {
2324
@@ -65,8 +66,8 @@ public IEnumerable<ModelContent.FunctionCallPart> FunctionCalls {
6566 }
6667 }
6768
68- // Hidden constructor, users don't need to make this, though they still technically can .
69- internal GenerateContentResponse ( List < Candidate > candidates , PromptFeedback ? promptFeedback ,
69+ // Hidden constructor, users don't need to make this.
70+ private GenerateContentResponse ( List < Candidate > candidates , PromptFeedback ? promptFeedback ,
7071 UsageMetadata ? usageMetadata ) {
7172 _candidates = new ReadOnlyCollection < Candidate > ( candidates ?? new List < Candidate > ( ) ) ;
7273 PromptFeedback = promptFeedback ;
@@ -78,48 +79,119 @@ internal static GenerateContentResponse FromJson(string jsonString) {
7879 }
7980
8081 internal static GenerateContentResponse FromJson ( Dictionary < string , object > jsonDict ) {
81- // Parse the Candidates
82- List < Candidate > candidates = new ( ) ;
83- if ( jsonDict . TryGetValue ( "candidates" , out object candidatesObject ) ) {
84- if ( candidatesObject is not List < object > listOfCandidateObjects ) {
85- throw new VertexAISerializationException ( "Invalid JSON format: 'candidates' is not a list." ) ;
86- }
87-
88- candidates = listOfCandidateObjects
89- . Select ( o => o as Dictionary < string , object > )
90- . Where ( dict => dict != null )
91- . Select ( Candidate . FromJson )
92- . ToList ( ) ;
93- }
94-
95- // TODO: Parse PromptFeedback and UsageMetadata
96-
97- return new GenerateContentResponse ( candidates , null , null ) ;
82+ return new GenerateContentResponse (
83+ jsonDict . ParseObjectList ( "candidates" , Candidate . FromJson ) ,
84+ jsonDict . ParseNullableObject ( "promptFeedback" ,
85+ Firebase . VertexAI . PromptFeedback . FromJson ) ,
86+ jsonDict . ParseNullableObject ( "usageMetadata" ,
87+ Firebase . VertexAI . UsageMetadata . FromJson ) ) ;
9888 }
9989}
10090
91+ /// <summary>
92+ /// A type describing possible reasons to block a prompt.
93+ /// </summary>
10194public enum BlockReason {
102- Unknown ,
95+ /// <summary>
96+ /// A new and not yet supported value.
97+ /// </summary>
98+ Unknown = 0 ,
99+ /// <summary>
100+ /// The prompt was blocked because it was deemed unsafe.
101+ /// </summary>
103102 Safety ,
103+ /// <summary>
104+ /// All other block reasons.
105+ /// </summary>
104106 Other ,
107+ /// <summary>
108+ /// The prompt was blocked because it contained terms from the terminology blocklist.
109+ /// </summary>
105110 Blocklist ,
111+ /// <summary>
112+ /// The prompt was blocked due to prohibited content.
113+ /// </summary>
106114 ProhibitedContent ,
107115}
108116
117+ /// <summary>
118+ /// A metadata struct containing any feedback the model had on the prompt it was provided.
119+ /// </summary>
109120public readonly struct PromptFeedback {
121+ private readonly ReadOnlyCollection < SafetyRating > _safetyRatings ;
122+
123+ /// <summary>
124+ /// The reason a prompt was blocked, if it was blocked.
125+ /// </summary>
110126 public BlockReason ? BlockReason { get ; }
127+ /// <summary>
128+ /// A human-readable description of the `BlockReason`.
129+ /// </summary>
111130 public string BlockReasonMessage { get ; }
112- public IEnumerable < SafetyRating > SafetyRatings { get ; }
131+ /// <summary>
132+ /// The safety ratings of the prompt.
133+ /// </summary>
134+ public IEnumerable < SafetyRating > SafetyRatings =>
135+ _safetyRatings ?? new ReadOnlyCollection < SafetyRating > ( new List < SafetyRating > ( ) ) ;
136+
137+ // Hidden constructor, users don't need to make this.
138+ private PromptFeedback ( BlockReason ? blockReason , string blockReasonMessage ,
139+ List < SafetyRating > safetyRatings ) {
140+ BlockReason = blockReason ;
141+ BlockReasonMessage = blockReasonMessage ;
142+ _safetyRatings = new ReadOnlyCollection < SafetyRating > ( safetyRatings ?? new List < SafetyRating > ( ) ) ;
143+ }
113144
114- // Hidden constructor, users don't need to make this
145+ private static BlockReason ParseBlockReason ( string str ) {
146+ return str switch {
147+ "SAFETY" => Firebase . VertexAI . BlockReason . Safety ,
148+ "OTHER" => Firebase . VertexAI . BlockReason . Other ,
149+ "BLOCKLIST" => Firebase . VertexAI . BlockReason . Blocklist ,
150+ "PROHIBITED_CONTENT" => Firebase . VertexAI . BlockReason . ProhibitedContent ,
151+ _ => Firebase . VertexAI . BlockReason . Unknown ,
152+ } ;
153+ }
154+
155+ internal static PromptFeedback FromJson ( Dictionary < string , object > jsonDict ) {
156+ return new PromptFeedback (
157+ jsonDict . ParseNullableEnum ( "blockReason" , ParseBlockReason ) ,
158+ jsonDict . ParseValue < string > ( "blockReasonMessage" ) ,
159+ jsonDict . ParseObjectList ( "safetyRatings" , SafetyRating . FromJson ) ) ;
160+ }
115161}
116162
163+ /// <summary>
164+ /// Token usage metadata for processing the generate content request.
165+ /// </summary>
117166public readonly struct UsageMetadata {
167+ /// <summary>
168+ /// The number of tokens in the request prompt.
169+ /// </summary>
118170 public int PromptTokenCount { get ; }
171+ /// <summary>
172+ /// The total number of tokens across the generated response candidates.
173+ /// </summary>
119174 public int CandidatesTokenCount { get ; }
175+ /// <summary>
176+ /// The total number of tokens in both the request and response.
177+ /// </summary>
120178 public int TotalTokenCount { get ; }
121179
122- // Hidden constructor, users don't need to make this
180+ // TODO: New fields about ModalityTokenCount
181+
182+ // Hidden constructor, users don't need to make this.
183+ private UsageMetadata ( int promptTC , int candidatesTC , int totalTC ) {
184+ PromptTokenCount = promptTC ;
185+ CandidatesTokenCount = candidatesTC ;
186+ TotalTokenCount = totalTC ;
187+ }
188+
189+ internal static UsageMetadata FromJson ( Dictionary < string , object > jsonDict ) {
190+ return new UsageMetadata (
191+ jsonDict . ParseValue < int > ( "promptTokenCount" ) ,
192+ jsonDict . ParseValue < int > ( "candidatesTokenCount" ) ,
193+ jsonDict . ParseValue < int > ( "totalTokenCount" ) ) ;
194+ }
123195}
124196
125197}
0 commit comments