SDK 가이드
Rust
Rust에서 async-openai 크레이트의 with_api_base로 api14에 연결하는 방법입니다. 채팅, 스트리밍, 도구 호출, 구조화된 출력, 이미지 입력, 임베딩, 타임아웃과 재시도를 설명합니다. 이미지 입력 예제도 포함합니다.
api14에서 async-openai를 사용하세요. OpenAIConfig::with_api_base로 API 기본 URL을 설정하고 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);