Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
Empty file added .doc_syle/DOC_STYLE.md
Empty file.
Empty file added .doc_syle/DOC_STYLE_UPDATES.md
Empty file.
Empty file.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ target/
# nodejs stuff
node_modules/
dist/
.*
191 changes: 170 additions & 21 deletions rig-core/src/client/completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,46 +11,160 @@ use serde::{Deserialize, Serialize};
use std::future::Future;
use std::sync::Arc;

/// A provider client with completion capabilities.
/// Clone is required for conversions between client types.
/// A provider client with text completion capabilities.
///
/// This trait extends [`ProviderClient`] to provide text generation functionality.
/// Providers that implement this trait can create completion models and agents.
///
/// # When to Implement
///
/// Implement this trait for provider clients that support:
/// - Text generation (chat completions, prompts)
/// - Multi-turn conversations
/// - Tool/function calling
/// - Streaming responses
///
/// # Examples
///
/// ```no_run
/// use rig::prelude::*;
/// use rig::providers::openai::{Client, self};
/// use rig::completion::Prompt;
///
/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
/// let client = Client::new("api-key");
///
/// // Create a completion model
/// let model = client.completion_model(openai::GPT_4O);
///
/// // Or create an agent with configuration
/// let agent = client.agent(openai::GPT_4O)
/// .preamble("You are a helpful assistant")
/// .temperature(0.7)
/// .max_tokens(1000)
/// .build();
///
/// let response = agent.prompt("Hello!").await?;
/// # Ok(())
/// # }
/// ```
///
/// # See Also
///
/// - [`crate::completion::CompletionModel`] - The model trait for making completion requests
/// - [`crate::agent::Agent`] - High-level agent abstraction built on completion models
/// - [`CompletionClientDyn`] - Dynamic dispatch version for runtime polymorphism
pub trait CompletionClient: ProviderClient + Clone {
/// The type of CompletionModel used by the client.
type CompletionModel: CompletionModel;

/// Create a completion model with the given name.
/// Creates a completion model with the specified model identifier.
///
/// # Example with OpenAI
/// ```
/// This method constructs a completion model that can be used to generate
/// text completions directly or as part of an agent.
///
/// # Arguments
///
/// * `model` - The model identifier (e.g., "gpt-4o", "claude-3-7-sonnet")
///
/// # Examples
///
/// ```no_run
/// use rig::prelude::*;
/// use rig::providers::openai::{Client, self};
/// use rig::completion::CompletionModel;
///
/// // Initialize the OpenAI client
/// let openai = Client::new("your-open-ai-api-key");
/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
/// let client = Client::new("your-api-key");
/// let model = client.completion_model(openai::GPT_4O);
///
/// let gpt4 = openai.completion_model(openai::GPT_4);
/// // Use the model to generate a completion
/// let response = model
/// .completion_request("What is Rust?")
/// .send()
/// .await?;
/// # Ok(())
/// # }
/// ```
fn completion_model(&self, model: &str) -> Self::CompletionModel;

/// Create an agent builder with the given completion model.
/// Creates an agent builder configured with the specified completion model.
///
/// # Example with OpenAI
/// ```
/// Agents provide a higher-level abstraction over completion models, adding
/// features like conversation management, tool integration, and persistent state.
///
/// # Arguments
///
/// * `model` - The model identifier (e.g., "gpt-4o", "claude-3-7-sonnet")
///
/// # Returns
///
/// An [`AgentBuilder`] that can be configured with preamble, tools, and other options.
///
/// # Examples
///
/// ```no_run
/// use rig::prelude::*;
/// use rig::providers::openai::{Client, self};
/// use rig::completion::Prompt;
///
/// // Initialize the OpenAI client
/// let openai = Client::new("your-open-ai-api-key");
/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
/// let client = Client::new("your-api-key");
///
/// let agent = openai.agent(openai::GPT_4)
/// .preamble("You are comedian AI with a mission to make people laugh.")
/// .temperature(0.0)
/// .build();
/// let agent = client.agent(openai::GPT_4O)
/// .preamble("You are a helpful assistant")
/// .temperature(0.7)
/// .build();
///
/// let response = agent.prompt("Hello!").await?;
/// # Ok(())
/// # }
/// ```
fn agent(&self, model: &str) -> AgentBuilder<Self::CompletionModel> {
AgentBuilder::new(self.completion_model(model))
}

/// Create an extractor builder with the given completion model.
/// Creates an extractor builder for structured data extraction.
///
/// Extractors use the completion model to extract structured data from text,
/// automatically generating the appropriate schema and parsing responses.
///
/// # Type Parameters
///
/// * `T` - The type to extract, must implement `JsonSchema`, `Deserialize`, and `Serialize`
///
/// # Arguments
///
/// * `model` - The model identifier (e.g., "gpt-4o", "claude-3-7-sonnet")
///
/// # Returns
///
/// An [`ExtractorBuilder`] that can be configured and used to extract structured data.
///
/// # Examples
///
/// ```no_run
/// use rig::prelude::*;
/// use rig::providers::openai::{Client, self};
/// use serde::{Deserialize, Serialize};
/// use schemars::JsonSchema;
///
/// #[derive(Debug, Deserialize, Serialize, JsonSchema)]
/// struct Person {
/// name: String,
/// age: u32,
/// }
///
/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
/// let client = Client::new("api-key");
///
/// let extractor = client.extractor::<Person>(openai::GPT_4O)
/// .build();
///
/// let person = extractor.extract("John Doe is 30 years old").await?;
/// # Ok(())
/// # }
/// ```
fn extractor<T>(&self, model: &str) -> ExtractorBuilder<Self::CompletionModel, T>
where
T: JsonSchema + for<'a> Deserialize<'a> + Serialize + Send + Sync,
Expand All @@ -59,9 +173,30 @@ pub trait CompletionClient: ProviderClient + Clone {
}
}

/// Wraps a CompletionModel in a dyn-compatible way for AgentBuilder.
/// A dynamic handle for completion models enabling trait object usage.
///
/// This struct wraps a [`CompletionModel`] in a way that allows it to be used
/// as a trait object with [`AgentBuilder`] and other generic contexts.
/// It uses `Arc` internally for efficient cloning.
///
/// # Examples
///
/// This type is primarily used internally by the dynamic client builder,
/// but can be useful when you need to store completion models of different types:
///
/// ```no_run
/// use rig::client::completion::CompletionModelHandle;
/// use rig::agent::AgentBuilder;
///
/// // CompletionModelHandle allows storing models from different providers
/// fn create_agent(model: CompletionModelHandle) -> AgentBuilder<CompletionModelHandle> {
/// AgentBuilder::new(model)
/// .preamble("You are a helpful assistant")
/// }
/// ```
#[derive(Clone)]
pub struct CompletionModelHandle<'a> {
/// The inner dynamic completion model.
pub inner: Arc<dyn CompletionModelDyn + 'a>,
}

Expand All @@ -87,11 +222,25 @@ impl CompletionModel for CompletionModelHandle<'_> {
}
}

/// Dynamic dispatch version of [`CompletionClient`].
///
/// This trait provides the same functionality as [`CompletionClient`] but returns
/// trait objects instead of associated types, enabling runtime polymorphism.
/// It is automatically implemented for all types that implement [`CompletionClient`].
///
/// # When to Use
///
/// Use this trait when you need to work with completion clients of different types
/// at runtime, such as in the [`DynClientBuilder`](crate::client::builder::DynClientBuilder).
pub trait CompletionClientDyn: ProviderClient {
/// Create a completion model with the given name.
/// Creates a boxed completion model with the specified model identifier.
///
/// Returns a trait object that can be used for dynamic dispatch.
fn completion_model<'a>(&self, model: &str) -> Box<dyn CompletionModelDyn + 'a>;

/// Create an agent builder with the given completion model.
/// Creates an agent builder with a dynamically-dispatched completion model.
///
/// Returns an agent builder using [`CompletionModelHandle`] for dynamic dispatch.
fn agent<'a>(&self, model: &str) -> AgentBuilder<CompletionModelHandle<'a>>;
}

Expand Down
Loading