Panduan SDK
C# / .NET
Pakai paket OpenAI .NET resmi dengan api14 lewat OpenAIClientOptions.Endpoint, termasuk streaming, tool calling, structured output, dan retry.
Gunakan library OpenAI .NET resmi dengan api14. Atur OpenAIClientOptions.Endpoint ke api14 dan kirim ID model seperti openai/gpt-5-mini saat membuat klien.
Instalasi
dotnet add package OpenAI
export API14_API_KEY="sk-api14-..."
Konfigurasi
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);
Setiap ChatClient terikat pada satu model; buat satu untuk setiap ID model yang Anda pakai.
Baca key dari environment, user secrets, atau secret store Anda, jangan pernah dari appsettings.json yang di-commit ke source control. Di ASP.NET Core, daftarkan satu klien sebagai singleton; klien ini thread-safe.
Chat
ChatCompletion completion = await client.CompleteChatAsync("Explain vector databases in two sentences.");
Console.WriteLine(completion.Content[0].Text);
Dengan system prompt:
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);
}
Lihat Streaming.
Tool calling
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))); // your function
}
completion = await client.CompleteChatAsync(messages, toolOptions);
}
Console.WriteLine(completion.Content[0].Text);
Lihat Tool calling.
Structured output
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());
Lihat Structured outputs.
Input gambar
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"))),
]);
Untuk file lokal, gunakan ChatMessageContentPart.CreateImagePart(BinaryData.FromBytes(File.ReadAllBytes("photo.png")), "image/png"). Lihat Vision dan file.
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);
Error
Panggilan yang gagal melempar ClientResultException; respons mentah membawa status dan header:
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.");
}
Lihat Error.
Timeout dan retry
Library mengulang 429 dan 5xx secara otomatis dengan exponential backoff. Atur jumlah retry dan timeout jaringan pada opsi yang Anda kirim ke setiap klien:
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),
};
Kirim CancellationToken ke panggilan ...Async mana pun untuk membatasi total waktu di seluruh retry. Mengulang tidak membantu untuk daily_limit_reached atau insufficient_balance. Lihat Batas laju.
Semua kemampuan
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);