SDKガイド
Rust
async-openai クレートで api14 を使う手順です。OpenAIConfig::with_api_base の設定から、チャット、ストリーミング、ツール呼び出し、構造化出力、画像入力、埋め込み、タイムアウトと再試行までを Rust で示します。
async-openai を api14 で使います。OpenAIConfig::with_api_base で API のベースを設定し、openai/gpt-5-mini などのモデル ID を渡します。
インストール
cargo add async-openai futures serde_json
cargo add tokio --features full
export API14_API_KEY="sk-api14-..."
設定
use async_openai::{config::OpenAIConfig, Client};
let config = OpenAIConfig::new()
.with_api_base("https://api14.com/api/v1")
.with_api_key(std::env::var("API14_API_KEY")?);
let client = Client::with_config(config);
キーはハードコードせず、上記のように環境から読み取ってください。ステージングと本番を切り替えるには、ベース URL も同じ方法で読み取ります。たとえば std::env::var("API14_BASE_URL").unwrap_or("https://api14.com/api/v1".into()) です。
チャット
use async_openai::{
config::OpenAIConfig,
types::{ChatCompletionRequestUserMessageArgs, CreateChatCompletionRequestArgs},
Client,
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = OpenAIConfig::new()
.with_api_base("https://api14.com/api/v1")
.with_api_key(std::env::var("API14_API_KEY")?);
let client = Client::with_config(config);
let request = CreateChatCompletionRequestArgs::default()
.model("openai/gpt-5-mini")
.messages([ChatCompletionRequestUserMessageArgs::default()
.content("Explain vector databases in two sentences.")
.build()?
.into()])
.build()?;
let response = client.chat().create(request).await?;
if let Some(content) = &response.choices[0].message.content {
println!("{content}");
}
Ok(())
}
ストリーミング
use futures::StreamExt;
let request = CreateChatCompletionRequestArgs::default()
.model("anthropic/claude-sonnet-4.5")
.messages([ChatCompletionRequestUserMessageArgs::default()
.content("Write a haiku about APIs.")
.build()?
.into()])
.build()?;
let mut stream = client.chat().create_stream(request).await?;
while let Some(result) = stream.next().await {
match result {
Ok(chunk) => {
for choice in chunk.choices {
if let Some(text) = choice.delta.content {
print!("{text}");
}
}
}
Err(err) => eprintln!("stream error: {err}"),
}
}
ストリーミングを参照してください。
ツール呼び出し
use async_openai::types::{
ChatCompletionRequestAssistantMessageArgs, ChatCompletionRequestMessage,
ChatCompletionRequestToolMessageArgs, ChatCompletionToolArgs, ChatCompletionToolType,
FunctionObjectArgs,
};
use serde_json::{json, Value};
let tools = vec![ChatCompletionToolArgs::default()
.r#type(ChatCompletionToolType::Function)
.function(FunctionObjectArgs::default()
.name("get_weather")
.description("Current weather for a city")
.parameters(json!({
"type": "object",
"properties": { "city": { "type": "string" } },
"required": ["city"]
}))
.build()?)
.build()?];
let mut messages: Vec<ChatCompletionRequestMessage> = vec![ChatCompletionRequestUserMessageArgs::default()
.content("What's the weather in Istanbul?")
.build()?
.into()];
loop {
let request = CreateChatCompletionRequestArgs::default()
.model("openai/gpt-5-mini")
.messages(messages.clone())
.tools(tools.clone())
.build()?;
let message = client.chat().create(request).await?.choices.remove(0).message;
let Some(calls) = message.tool_calls else {
println!("{}", message.content.unwrap_or_default());
break;
};
messages.push(ChatCompletionRequestAssistantMessageArgs::default()
.tool_calls(calls.clone())
.build()?
.into());
for call in calls {
let args: Value = serde_json::from_str(&call.function.arguments)?;
let result = get_weather(args["city"].as_str().unwrap_or_default()); // 自分の関数
messages.push(ChatCompletionRequestToolMessageArgs::default()
.tool_call_id(call.id)
.content(result)
.build()?
.into());
}
}
ツール呼び出しを参照してください。
構造化出力
use async_openai::types::{ResponseFormat, ResponseFormatJsonSchema};
let request = CreateChatCompletionRequestArgs::default()
.model("openai/gpt-5-mini")
.messages([ChatCompletionRequestUserMessageArgs::default()
.content("Extract: Ada Lovelace, born 1815.")
.build()?
.into()])
.response_format(ResponseFormat::JsonSchema {
json_schema: ResponseFormatJsonSchema {
name: "person".into(),
description: None,
strict: Some(true),
schema: Some(json!({
"type": "object",
"properties": { "name": { "type": "string" }, "born": { "type": "integer" } },
"required": ["name", "born"],
"additionalProperties": false
})),
},
})
.build()?;
let response = client.chat().create(request).await?;
let person: Value = serde_json::from_str(response.choices[0].message.content.as_deref().unwrap_or("{}"))?;
構造化出力を参照してください。
画像入力
use async_openai::types::{
ChatCompletionRequestMessageContentPartImageArgs, ChatCompletionRequestMessageContentPartTextArgs,
ImageUrlArgs,
};
let message = ChatCompletionRequestUserMessageArgs::default()
.content(vec![
ChatCompletionRequestMessageContentPartTextArgs::default()
.text("What is in this picture?")
.build()?
.into(),
ChatCompletionRequestMessageContentPartImageArgs::default()
.image_url(ImageUrlArgs::default().url("https://example.com/photo.jpg").build()?)
.build()?
.into(),
])
.build()?;
google/gemini-2.5-flash など、image 入力に対応する別のモデルで送信してください。画像とファイル入力を参照してください。
埋め込み
use async_openai::types::CreateEmbeddingRequestArgs;
let request = CreateEmbeddingRequestArgs::default()
.model("openai/text-embedding-3-small")
.input(["The quick brown fox", "Lorem ipsum"])
.build()?;
let response = client.embeddings().create(request).await?;
println!("{}", response.data[0].embedding.len());
クレートに型がないエンドポイント(動画ジョブ、リランク)は reqwest で呼び出せます。下のコードブロックにある HTTP の例を参照してください。
エラー
ゲートウェイのエラーは OpenAIError::ApiError に解析されます。マシン用の code で分岐します。
use async_openai::error::OpenAIError;
match client.chat().create(request).await {
Ok(response) => println!("{:?}", response.choices[0].message.content),
Err(OpenAIError::ApiError(err)) => match err.code.as_deref() {
Some("insufficient_balance") => eprintln!("Balance too low, add funds"),
Some("rate_limited") | Some("daily_limit_reached") => eprintln!("Slow down: {}", err.message),
_ => eprintln!("API error: {}", err.message),
},
Err(other) => eprintln!("{other}"),
}
エラーを参照してください。
タイムアウトと再試行
async-openai は、429 rate_limited のレスポンスをすでにバックオフして再試行します。デフォルトのバックオフは最大 15 分間試行を続けますが、これはほとんどのアプリでは長すぎ、daily_limit_reached では意味がありません。上限を設け、HTTP クライアントにもタイムアウトを設定してください(cargo add backoff reqwest。バージョンは async-openai が使うものに合わせます)。
use std::time::Duration;
let http = reqwest::Client::builder()
.timeout(Duration::from_secs(120))
.build()?;
let client = Client::with_config(config)
.with_http_client(http)
.with_backoff(backoff::ExponentialBackoffBuilder::new()
.with_max_elapsed_time(Some(Duration::from_secs(90)))
.build());
レート制限を参照してください。
すべての機能
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);