portkey_sdk/service/
prompts.rs

1use std::future::Future;
2
3#[cfg(feature = "tracing")]
4use crate::TRACING_TARGET_SERVICE;
5use crate::client::PortkeyClient;
6use crate::error::Result;
7use crate::model::{
8    PromptCompletionRequest, PromptCompletionResponse, PromptRenderRequest, PromptRenderResponse,
9};
10
11/// Service trait for executing prompt templates.
12///
13/// This trait provides methods for executing saved prompt templates on Portkey,
14/// allowing you to substitute variables and override hyperparameters.
15///
16/// # Example
17///
18/// ```rust,no_run
19/// use portkey_sdk::{PortkeyConfig, Result};
20/// use portkey_sdk::service::PromptsService;
21/// use portkey_sdk::builder::AuthMethod;
22/// use portkey_sdk::model::PromptCompletionRequest;
23/// use std::collections::HashMap;
24///
25/// #[tokio::main]
26/// async fn main() -> Result<()> {
27///     let client = PortkeyConfig::builder()
28///         .with_api_key("your-portkey-api-key")
29///         .with_auth_method(AuthMethod::virtual_key("your-virtual-key"))
30///         .build_client()?;
31///
32///     let mut variables = HashMap::new();
33///     variables.insert("user_input".to_string(), serde_json::json!("Hello world"));
34///
35///     let request = PromptCompletionRequest {
36///         variables,
37///         stream: Some(false),
38///         max_tokens: Some(250),
39///         presence_penalty: Some(0.2),
40///         temperature: None,
41///         frequency_penalty: None,
42///         top_p: None,
43///         stop: None,
44///         n: None,
45///         logprobs: None,
46///         echo: None,
47///         best_of: None,
48///         logit_bias: None,
49///         user: None,
50///     };
51///
52///     let response = client.execute_prompt("your-prompt-id", request).await?;
53///     println!("Completion: {:?}", response.body);
54///
55///     Ok(())
56/// }
57/// ```
58pub trait PromptsService {
59    /// Executes a saved prompt template with the given variables and parameters.
60    ///
61    /// # Arguments
62    ///
63    /// * `prompt_id` - The unique identifier of the prompt template
64    /// * `request` - The completion request with variables and hyperparameters
65    ///
66    /// # Returns
67    ///
68    /// Returns a `PromptCompletionResponse` containing the completion result.
69    ///
70    /// # Errors
71    ///
72    /// Returns an error if the API request fails or the response cannot be parsed.
73    fn execute_prompt(
74        &self,
75        prompt_id: &str,
76        request: PromptCompletionRequest,
77    ) -> impl Future<Output = Result<PromptCompletionResponse>>;
78
79    /// Renders a prompt template with variables and hyperparameters without executing it.
80    ///
81    /// This method substitutes variables in the prompt template and applies hyperparameters,
82    /// returning the fully rendered configuration that would be sent to the LLM provider.
83    ///
84    /// # Arguments
85    ///
86    /// * `prompt_id` - The unique identifier of the prompt template
87    /// * `request` - The render request with variables and optional hyperparameters
88    ///
89    /// # Returns
90    ///
91    /// Returns a `PromptRenderResponse` containing the rendered prompt configuration.
92    ///
93    /// # Errors
94    ///
95    /// Returns an error if the API request fails or the response cannot be parsed.
96    fn render_prompt(
97        &self,
98        prompt_id: &str,
99        request: PromptRenderRequest,
100    ) -> impl Future<Output = Result<PromptRenderResponse>>;
101}
102
103impl PromptsService for PortkeyClient {
104    async fn execute_prompt(
105        &self,
106        prompt_id: &str,
107        request: PromptCompletionRequest,
108    ) -> Result<PromptCompletionResponse> {
109        #[cfg(feature = "tracing")]
110        tracing::debug!(
111            target: TRACING_TARGET_SERVICE,
112            prompt_id = %prompt_id,
113            stream = ?request.stream,
114            max_tokens = ?request.max_tokens,
115            "Executing prompt template"
116        );
117
118        let path = format!("/prompts/{}/completions", prompt_id);
119        let response = self
120            .send_json(reqwest::Method::POST, &path, &request)
121            .await?;
122        let response = response.error_for_status()?;
123        let completion_response: PromptCompletionResponse = response.json().await?;
124
125        Ok(completion_response)
126    }
127
128    async fn render_prompt(
129        &self,
130        prompt_id: &str,
131        request: PromptRenderRequest,
132    ) -> Result<PromptRenderResponse> {
133        #[cfg(feature = "tracing")]
134        tracing::debug!(
135            target: TRACING_TARGET_SERVICE,
136            prompt_id = %prompt_id,
137            max_tokens = ?request.max_tokens,
138            "Rendering prompt template"
139        );
140
141        let path = format!("/prompts/{}/render", prompt_id);
142        let response = self
143            .send_json(reqwest::Method::POST, &path, &request)
144            .await?;
145        let response = response.error_for_status()?;
146        let render_response: PromptRenderResponse = response.json().await?;
147
148        Ok(render_response)
149    }
150}