ys memos

Blog

RustでOpenAIのChatCompletionsをストリームで受けるmod 〜1.カスタムエラー〜


rust

2023/08/31


本コードの動作確認は2023/05時点までしか行っていません。
当時動作していたコードをそのまま公開いたします。

現在のAPIでの動作確認はしていないこと、ご了承ください。

以前、OpenAIのChat Completionsを叩くアプリを作っていた。 しかし、いつしか熱が冷めて開発が止まっていたので、眠らせておくくらいならと思い、コードを公開する。

また、一つの記事にまとめたかったが、ボリュームが大きくなりすぎてしまったので、記事をいくつかに分割した。



ここでは、モジュールのために利用するエラーを定義しておく。モジュールそのもので吐き出すエラー以外に、外部クレートによるエラーの変換も統合しておく。

src/
└── chatter
    ├── error.rs           # <-
    ├── headers.rs
    ├── json.rs
    ├── message.rs
    ├── mod.rs
    ├── request_builder.rs
    ├── role.rs
    └── stream_data.rs


use reqwest::header::InvalidHeaderValue;
use std::{fmt, io};
use thiserror::Error;

pub type ChatterResult<T> = Result<T, ChatterError>;

#[derive(Debug)]
pub(super) struct UnitError;

impl fmt::Display for UnitError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "UnitError")
    }
}

impl std::error::Error for UnitError {}

#[derive(Debug, Error)]
pub enum ChatterError {
    #[error("I/O error occurred: {0}")]
    IoError(#[from] io::Error),

    #[error("error occurred: {0}")]
    InvalidHeaderValue(#[from] InvalidHeaderValue),

    #[error("error occurred: {0}")]
    ReqwestError(#[from] reqwest::Error),

    #[error("Error occurred on from_str::<StreamData>()")]
    StreamParsingError,

    #[error("Error occurred on to_stream_data()")]
    StreamDataConvertingError,

    #[error("Error occurred on send()")]
    DuplicatedSendingError,

    #[error("undefined error")]
    UnknownError,
}

impl From<ChatterError> for io::Error {
    fn from(value: ChatterError) -> Self {
        match value {
            ChatterError::IoError(e) => e,
            _ => io::Error::new(io::ErrorKind::Other, format!("{value}")),
        }
    }
}


受け取れるようにするクレートのエラー型などをuse

use reqwest::header::InvalidHeaderValue;
use std::{fmt, io};
use thiserror::Error;

カスタムエラー返すResultを簡潔に利用できるように型エイリアスを定義

pub type ChatterResult<T> = Result<T, ChatterError>;

当時のコードに含まれていたが、おそらくここは不要。意図としては、「空のエラー(=とりあえず投げるエラー)」を目的とする型で開発段階で利用していた。

#[derive(Debug)]
pub(super) struct UnitError;

impl fmt::Display for UnitError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "UnitError")
    }
}

impl std::error::Error for UnitError {}

本題であるカスタムエラーの定義。

io::Error, InvalidHeaderValue, reqwest::Error空の変換を定義しつつ、モジュール内コードで発生するエラーを定義しておく。

UnknownErrorは、今回公開するコード内では使っていないが、開発段階で利用していた。

#[derive(Debug, Error)]
pub enum ChatterError {
    #[error("I/O error occurred: {0}")]
    IoError(#[from] io::Error),

    #[error("error occurred: {0}")]
    InvalidHeaderValue(#[from] InvalidHeaderValue),

    #[error("error occurred: {0}")]
    ReqwestError(#[from] reqwest::Error),

    #[error("Error occurred on from_str::<StreamData>()")]
    StreamParsingError,

    #[error("Error occurred on to_stream_data()")]
    StreamDataConvertingError,

    #[error("Error occurred on send()")]
    DuplicatedSendingError,

    #[error("undefined error")]
    UnknownError,
}

io::Errorへの変換を実装しておくことで、io::Result?を使えるようにする。

impl From<ChatterError> for io::Error {
    fn from(value: ChatterError) -> Self {
        match value {
            ChatterError::IoError(e) => e,
            _ => io::Error::new(io::ErrorKind::Other, format!("{value}")),
        }
    }
}


関連タグを探す