Skip to content

Generate Content

Gunpal Jain edited this page Nov 15, 2026 · 4 revisions

This page shows how to generate content with GenerativeModel. You can call one of the convenience GenerateContentAsync overloads, or build a GenerateContentRequest yourself for full control. It also covers generation config, thinking, token counting, automatic continuation and error handling.

Package: Google_GenerativeAI. For setup, see Initialization.

using GenerativeAI;
using GenerativeAI.Types;

var model = new GoogleAi("YOUR_API_KEY").CreateGenerativeModel(GoogleAIModels.Gemini38Flash);

Method 1: Convenience Overloads

GenerateContentAsync(string prompt)

GenerateContentResponse response = await model.GenerateContentAsync("Write a short poem about nature.");
Console.WriteLine(response.Text());

GenerateContentAsync(string prompt, string fileUri, string mimeType)

Sends a prompt together with a remote file URI, such as a Files API URI, a gs:// URI on Vertex AI or a public URL the model can fetch. To send a local file, see Multimodal Features.

var response = await model.GenerateContentAsync(
    "Describe the image.",
    "https://generativelanguage.googleapis.com/v1beta/files/abc123",
    "image/jpeg");
Console.WriteLine(response.Text());

GenerateContentAsync(IEnumerable<Part> parts)

All parts are sent in a single user turn:

var parts = new List<Part>
{
    new Part { Text = "What are the benefits of using cloud computing?" },
    new Part { Text = "Answer in three bullet points." }
};

var response = await model.GenerateContentAsync(parts);
Console.WriteLine(response.Text());

All overloads accept an optional CancellationToken.

Method 2: Building a GenerateContentRequest

Use the extension methods on GenerateContentRequest to add text, parts, files, tools and JSON mode:

var request = new GenerateContentRequest();

// Text (appended to the last content, or a new user content if there is none)
request.AddText("Summarize the following article: ...");

// Parts
request.AddParts(new List<Part> { new Part { Text = "Keep it under 100 words." } });

// A whole Content with an explicit role
request.AddContent(new Content("Here is some more context.", Roles.User));

// Files
request.AddInlineFile("chart.png");                            // local file, sent inline (base64)
request.AddRemoteFile("https://example.com/report.pdf", "application/pdf");

// Tools (see Function Calling)
request.AddTool(new Tool { GoogleSearch = new GoogleSearchTool() });

// Generation settings
request.GenerationConfig = new GenerationConfig
{
    Temperature = 0.7,
    MaxOutputTokens = 1024
};

GenerateContentResponse response = await model.GenerateContentAsync(request);
Console.WriteLine(response.Text());

To get structured output, call request.UseJsonMode<MyResponseClass>() or use GenerateObjectAsync<T>. See JSON Mode.

Request fields

Property Description
Contents Conversation turns (List<Content>)
SystemInstruction A Content with system instructions
GenerationConfig Sampling, output and thinking settings
SafetySettings Per-request List<SafetySetting>
Tools, ToolConfig Function declarations, Google Search, code execution, ...
CachedContent Name of a context cache (see Context Caching)
ContinuationToken Resumes a response that ended with FinishReason.CONTINUATION (normally handled for you)
ServiceTier, Store, Labels, ModelArmorConfig, OutputConfig Optional API features

Request values take precedence. When a request doesn't set GenerationConfig, SafetySettings or SystemInstruction, the model's own Config, SafetySettings and SystemInstruction are used.

Model-Level Defaults

var model = new GoogleAi("YOUR_API_KEY").CreateGenerativeModel(
    GoogleAIModels.Gemini38Flash,
    config: new GenerationConfig { Temperature = 0.4 },
    systemInstruction: "You are a helpful technical writer.");

// Or set them later
model.SystemInstruction = "Answer in French.";
model.Config = new GenerationConfig { MaxOutputTokens = 512 };

Generation Config

Commonly used GenerationConfig properties:

Property Purpose
Temperature, TopP, TopK, Seed Sampling
MaxOutputTokens, StopSequences, CandidateCount Output length and stop conditions
PresencePenalty, FrequencyPenalty Repetition control
ResponseMimeType, ResponseSchema, ResponseJsonSchema Structured output (see JSON Mode)
ResponseModalities Ask for text, image or audio output
ThinkingConfig Thinking budget, level and thought summaries
MediaResolution Resolution used for image and video input
SpeechConfig, ImageConfig Speech and image generation options
ResponseLogprobs, Logprobs Return log probabilities

Thinking

Gemini 3.x models use a thinking level. Gemini 2.5 models use a thinking budget in tokens. Set IncludeThoughts to receive thought summaries.

var request = new GenerateContentRequest();
request.AddText("How many prime numbers are there between 1 and 100?");
request.GenerationConfig = new GenerationConfig
{
    ThinkingConfig = new ThinkingConfig
    {
        ThinkingLevel = ThinkingLevel.HIGH,   // MINIMAL, LOW, MEDIUM, HIGH, XHIGH (model dependent)
        IncludeThoughts = true
        // ThinkingBudget = 1024,             // Gemini 2.5: thinking budget in tokens
    }
};

var response = await model.GenerateContentAsync(request);

foreach (var part in response.Candidates![0].Content!.Parts)
{
    if (part.Thought == true)
        Console.WriteLine($"[thought] {part.Text}");
    else
        Console.WriteLine(part.Text);
}

Console.WriteLine($"Thinking tokens: {response.UsageMetadata?.ThoughtsTokenCount}");

response.Text() joins the text of all parts, including thought summaries when IncludeThoughts is on. To get only the answer, filter on Part.Thought as shown above.

Reading the Response

var response = await model.GenerateContentAsync("Hello");

string? text = response.Text();          // extension: text of all candidates' parts
string last  = response.Text;            // property: text of the last candidate's parts
var finish   = response.Candidates?[0].FinishReason;
var usage    = response.UsageMetadata;   // PromptTokenCount, CandidatesTokenCount, TotalTokenCount, ...
var calls    = response.GetFunctions();  // function calls requested by the model, if any
var code     = response.ExtractCodeBlocks();

If the prompt is blocked, or the response has no candidates and carries a block reason, the SDK throws GenerativeAIException with the block details.

Counting Tokens

CountTokensResponse count = await model.CountTokensAsync(new[] { new Content("How long is this prompt?", Roles.User) });
Console.WriteLine(count.TotalTokens);

// A full request (including system instruction and tools)
var countForRequest = await model.CountTokensAsync(request);

On Vertex AI, ModelClient.ComputeTokensAsync also returns the individual tokens. See Model Client.

Automatic Continuation

Some long responses end with FinishReason.CONTINUATION and a Candidate.ContinuationToken. By default, GenerativeModel resumes these responses automatically and merges the parts into one response. Streaming works the same way: a stream that fails after a checkpoint is resumed too.

model.EnableAutomaticContinuation = true; // default
model.MaxContinuations = 10;              // default

// To handle it yourself:
model.EnableAutomaticContinuation = false;
var first = await model.GenerateContentAsync(request);
if (first.Candidates?[0].FinishReason == FinishReason.CONTINUATION)
{
    request.ContinuationToken = first.Candidates[0].ContinuationToken;
    var next = await model.GenerateContentAsync(request);
}

Function Results Use the user Role

Gemini 3.x models reject the legacy function role. Before each request, the SDK rewrites any content with Roles.Function to Roles.User. This also fixes chat histories saved by older SDK versions. When you build function responses by hand, use Roles.User. See Function Calling.

Error Handling

When the API returns an error, the SDK throws GenerativeAI.Exceptions.ApiException:

using GenerativeAI.Exceptions;

try
{
    var response = await model.GenerateContentAsync("Hello");
}
catch (ApiException ex) when (ex.ErrorCode == 429)
{
    Console.WriteLine($"Rate limited ({ex.ErrorStatus}): {ex.ErrorMessage}");
}
catch (ApiException ex)
{
    Console.WriteLine($"{ex.ErrorCode} {ex.ErrorStatus}: {ex.ErrorMessage}");
}
catch (GenerativeAIException ex)
{
    Console.WriteLine($"Blocked: {ex.Details}");
}

If an error body can't be parsed, the SDK throws HttpRequestException with the status code and a short excerpt of the body.

Related Pages

API Reference

Clone this wiki locally