Usamos cookies. Las cookies y el almacenamiento del navegador mantienen tu sesión iniciada y recuerdan tus preferencias. Con tu permiso, también medimos cómo se usa el sitio. Puedes en cualquier momento. Consulta nuestra política de cookies.

C# y .NET

Guías de SDK

C# y .NET

Usa la biblioteca oficial OpenAI para .NET con api14: configura el endpoint, chat, streaming, herramientas, salida estructurada, embeddings y errores.

Usa la biblioteca oficial OpenAI para .NET con api14. Establece OpenAIClientOptions.Endpoint con la URL de api14 y pasa un id de modelo como openai/gpt-5-mini al crear un cliente.

Instalación

dotnet add package OpenAI
export API14_API_KEY="sk-api14-..."

Configuración

using System.ClientModel;
using OpenAI;
using OpenAI.Chat;

var credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("API14_API_KEY")!);
var options = new OpenAIClientOptions { Endpoint = new Uri("https://api14.com/api/v1") };

var client = new ChatClient(model: "openai/gpt-5-mini", credential: credential, options: options);

Cada ChatClient está ligado a un único modelo; crea uno por cada id de modelo que uses.

Lee la clave del entorno, de los secretos de usuario o de tu almacén de secretos, nunca de un appsettings.json subido al control de versiones. En ASP.NET Core, registra un solo cliente como singleton; es seguro para hilos.

Chat

ChatCompletion completion = await client.CompleteChatAsync("Explain vector databases in two sentences.");
Console.WriteLine(completion.Content[0].Text);

Con un prompt de sistema:

ChatCompletion completion = await client.CompleteChatAsync(
[
    new SystemChatMessage("You are terse."),
    new UserChatMessage("What is RAG?"),
]);

Streaming

var claude = new ChatClient("anthropic/claude-sonnet-4.5", credential, options);

await foreach (StreamingChatCompletionUpdate update in claude.CompleteChatStreamingAsync("Write a haiku about APIs."))
{
    foreach (ChatMessageContentPart part in update.ContentUpdate)
        Console.Write(part.Text);
}

Consulta Streaming.

Llamadas a herramientas

using System.Text.Json;

ChatTool getWeather = ChatTool.CreateFunctionTool(
    functionName: "get_weather",
    functionDescription: "Current weather for a city",
    functionParameters: BinaryData.FromString("""
        { "type": "object", "properties": { "city": { "type": "string" } }, "required": ["city"] }
        """));

var toolOptions = new ChatCompletionOptions { Tools = { getWeather } };
List<ChatMessage> messages = [new UserChatMessage("What's the weather in Istanbul?")];

ChatCompletion completion = await client.CompleteChatAsync(messages, toolOptions);
while (completion.FinishReason == ChatFinishReason.ToolCalls)
{
    messages.Add(new AssistantChatMessage(completion));
    foreach (ChatToolCall call in completion.ToolCalls)
    {
        using JsonDocument args = JsonDocument.Parse(call.FunctionArguments);
        string city = args.RootElement.GetProperty("city").GetString()!;
        messages.Add(new ToolChatMessage(call.Id, GetWeather(city))); // tu función
    }
    completion = await client.CompleteChatAsync(messages, toolOptions);
}
Console.WriteLine(completion.Content[0].Text);

Consulta Llamadas a herramientas.

Salida estructurada

var jsonOptions = new ChatCompletionOptions
{
    ResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat(
        jsonSchemaFormatName: "person",
        jsonSchema: BinaryData.FromString("""
            {
              "type": "object",
              "properties": { "name": { "type": "string" }, "born": { "type": "integer" } },
              "required": ["name", "born"],
              "additionalProperties": false
            }
            """),
        jsonSchemaIsStrict: true),
};

ChatCompletion result = await client.CompleteChatAsync(
    [new UserChatMessage("Extract: Ada Lovelace, born 1815.")], jsonOptions);

using JsonDocument person = JsonDocument.Parse(result.Content[0].Text);
Console.WriteLine(person.RootElement.GetProperty("born").GetInt32());

Consulta Salidas estructuradas.

Entrada de imagen

var vision = new ChatClient("google/gemini-2.5-flash", credential, options);

ChatCompletion described = await vision.CompleteChatAsync(
[
    new UserChatMessage(
        ChatMessageContentPart.CreateTextPart("What is in this picture?"),
        ChatMessageContentPart.CreateImagePart(new Uri("https://example.com/photo.jpg"))),
]);

Para un archivo local, usa ChatMessageContentPart.CreateImagePart(BinaryData.FromBytes(File.ReadAllBytes("photo.png")), "image/png"). Consulta Visión y archivos.

Embeddings

using OpenAI.Embeddings;

var embeddings = new EmbeddingClient("openai/text-embedding-3-small", credential, options);
OpenAIEmbedding embedding = await embeddings.GenerateEmbeddingAsync("The quick brown fox");
Console.WriteLine(embedding.ToFloats().Length);

Errores

Las llamadas fallidas lanzan ClientResultException; la respuesta sin procesar incluye el estado y las cabeceras:

try
{
    await client.CompleteChatAsync("Hi");
}
catch (ClientResultException ex) when (ex.Status == 402)
{
    Console.Error.WriteLine("Balance too low, add funds (insufficient_balance).");
}
catch (ClientResultException ex) when (ex.Status == 429)
{
    string? retryAfter = null;
    ex.GetRawResponse()?.Headers.TryGetValue("Retry-After", out retryAfter);
    Console.Error.WriteLine($"Rate limited, retry after {retryAfter ?? "60"}s.");
}

Consulta Errores.

Tiempos de espera y reintentos

La biblioteca reintenta automáticamente los errores 429 y 5xx con retroceso exponencial. Ajusta el número de reintentos y el tiempo de espera de red en las opciones que pasas a cada cliente:

using System.ClientModel.Primitives;

var options = new OpenAIClientOptions
{
    Endpoint = new Uri("https://api14.com/api/v1"),
    NetworkTimeout = TimeSpan.FromMinutes(2),
    RetryPolicy = new ClientRetryPolicy(maxRetries: 4),
};

Pasa un CancellationToken a cualquier llamada ...Async para limitar el tiempo total entre reintentos. Reintentar no ayuda con daily_limit_reached ni con insufficient_balance. Consulta Límites de tasa.

Todas las capacidades

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api14.com/api/v1",
  apiKey: process.env.API14_API_KEY,
});

const result = await client.chat.completions.create({
  "model": "openai/gpt-5-mini",
  "messages": [
    {
      "role": "user",
      "content": "Explain vector databases in two sentences."
    }
  ]
});
console.log(result.choices[0].message.content);