llm_worker/llm_client/
client.rs

1//! LLMクライアント共通trait定義
2
3use std::pin::Pin;
4
5use crate::llm_client::{ClientError, Request, RequestConfig, event::Event};
6use async_trait::async_trait;
7use futures::Stream;
8
9/// 設定に関する警告
10///
11/// プロバイダがサポートしていない設定を使用した場合に返される。
12#[derive(Debug, Clone)]
13pub struct ConfigWarning {
14    /// 設定オプション名
15    pub option_name: &'static str,
16    /// 警告メッセージ
17    pub message: String,
18}
19
20impl ConfigWarning {
21    /// 新しい警告を作成
22    pub fn unsupported(option_name: &'static str, provider_name: &str) -> Self {
23        Self {
24            option_name,
25            message: format!(
26                "'{}' is not supported by {} and will be ignored",
27                option_name, provider_name
28            ),
29        }
30    }
31}
32
33impl std::fmt::Display for ConfigWarning {
34    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35        write!(f, "{}: {}", self.option_name, self.message)
36    }
37}
38
39/// LLMクライアントのtrait
40///
41/// 各プロバイダはこのtraitを実装し、統一されたインターフェースを提供する。
42#[async_trait]
43pub trait LlmClient: Send + Sync {
44    /// ストリーミングリクエストを送信し、Eventストリームを返す
45    ///
46    /// # Arguments
47    /// * `request` - リクエスト情報
48    ///
49    /// # Returns
50    /// * `Ok(Stream)` - イベントストリーム
51    /// * `Err(ClientError)` - エラー
52    async fn stream(
53        &self,
54        request: Request,
55    ) -> Result<Pin<Box<dyn Stream<Item = Result<Event, ClientError>> + Send>>, ClientError>;
56
57    /// 設定をバリデーションし、未サポートの設定があれば警告を返す
58    ///
59    /// # Arguments
60    /// * `config` - バリデーション対象の設定
61    ///
62    /// # Returns
63    /// サポートされていない設定に対する警告のリスト
64    fn validate_config(&self, config: &RequestConfig) -> Vec<ConfigWarning> {
65        // デフォルト実装: 全ての設定をサポート
66        let _ = config;
67        Vec::new()
68    }
69}
70
71/// `Box<dyn LlmClient>` に対する `LlmClient` の実装
72///
73/// これにより、動的ディスパッチを使用するクライアントも `Worker` で利用可能になる。
74#[async_trait]
75impl LlmClient for Box<dyn LlmClient> {
76    async fn stream(
77        &self,
78        request: Request,
79    ) -> Result<Pin<Box<dyn Stream<Item = Result<Event, ClientError>> + Send>>, ClientError> {
80        (**self).stream(request).await
81    }
82
83    fn validate_config(&self, config: &RequestConfig) -> Vec<ConfigWarning> {
84        (**self).validate_config(config)
85    }
86}