2023/08/31
はじめに
本コードの動作確認は2023/05時点までしか行っていません。
当時動作していたコードをそのまま公開いたします。
現在のAPIでの動作確認はしていないこと、ご了承ください。
以前、OpenAIのChat Completionsを叩くアプリを作っていた。 しかし、いつしか熱が冷めて開発が止まっていたので、眠らせておくくらいならと思い、コードを公開する。
また、一つの記事にまとめたかったが、ボリュームが大きくなりすぎてしまったので、記事をいくつかに分割した。
目次
実装対象
APIの宛先やリクエストヘッダ、リクエストボディーそのものを意識しないでチャットするための定義。
当時はファイル分割していたが、ここは同一ファイルに記述しても良さそうな内容&量と思った。
src/
└── chatter
├── error.rs
├── headers.rs # <-
├── json.rs
├── message.rs
├── mod.rs
├── request_builder.rs # <-
├── role.rs
└── stream_data.rs
コード
headers.rs
use std::env;
use dotenv::dotenv;
use reqwest::header::{HeaderMap, HeaderValue, AUTHORIZATION, CONTENT_TYPE};
use super::error::ChatterResult;
pub(super) fn create() -> ChatterResult<HeaderMap> {
dotenv().ok();
let openai_api_key = env::var("OPENAI_API_KEY").expect("Not Found API key");
let mut headers = HeaderMap::new();
headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json"));
headers.insert(
AUTHORIZATION,
HeaderValue::from_str(&format!("Bearer {}", openai_api_key))?,
);
Ok(headers)
}
request_builder.rs
use reqwest::RequestBuilder;
use super::error::ChatterResult;
pub(super) fn create() -> ChatterResult<RequestBuilder> {
let headers = super::headers::create()?;
let request_builder = reqwest::Client::new()
.post("https://api.openai.com/v1/chat/completions")
.headers(headers);
Ok(request_builder)
}
解説
headers.rs
use std::env;
use dotenv::dotenv;
use reqwest::header::{HeaderMap, HeaderValue, AUTHORIZATION, CONTENT_TYPE};
use super::error::ChatterResult;
リクエストヘッダーを作成する。このコードでは、ここで環境変数を取得しているのが、サーバなどで起動する場合はサーバ起動時に環境変数を取得し、存在しない場合にエラーを投げることが望ましいと思われる。
pub(super) fn create() -> ChatterResult<HeaderMap> {
dotenv().ok();
let openai_api_key = env::var("OPENAI_API_KEY").expect("Not Found API key");
let mut headers = HeaderMap::new();
headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json"));
headers.insert(
AUTHORIZATION,
HeaderValue::from_str(&format!("Bearer {}", openai_api_key))?,
);
Ok(headers)
}
request_builder.rs
use reqwest::RequestBuilder;
use super::error::ChatterResult;
柔軟性のためにRequestBuilder
を返すように設計してみた。
しかし、ここでの実装はChat Completions専用なので、もっと特化し、役割を増やしても良いかもしれない。
pub(super) fn create() -> ChatterResult<RequestBuilder> {
let headers = super::headers::create()?;
let request_builder = reqwest::Client::new()
.post("https://api.openai.com/v1/chat/completions")
.headers(headers);
Ok(request_builder)
}