openrouter_rs/api/
completion.rs

1use crate::{
2    error::OpenRouterError,
3    setter,
4    types::{ProviderPreferences, ReasoningConfig},
5    utils::handle_error,
6};
7use reqwest::Client;
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10
11#[derive(Serialize, Deserialize, Debug)]
12pub struct CompletionRequest {
13    model: String,
14    prompt: String,
15    stream: Option<bool>,
16    max_tokens: Option<u32>,
17    temperature: Option<f64>,
18    seed: Option<u32>,
19    top_p: Option<f64>,
20    top_k: Option<u32>,
21    frequency_penalty: Option<f64>,
22    presence_penalty: Option<f64>,
23    repetition_penalty: Option<f64>,
24    logit_bias: Option<HashMap<String, f64>>,
25    top_logprobs: Option<u32>,
26    min_p: Option<f64>,
27    top_a: Option<f64>,
28    transforms: Option<Vec<String>>,
29    models: Option<Vec<String>>,
30    route: Option<String>,
31    provider: Option<ProviderPreferences>,
32    reasoning: Option<ReasoningConfig>,
33}
34
35impl CompletionRequest {
36    pub fn new(model: &str, prompt: &str) -> Self {
37        Self {
38            model: model.to_string(),
39            prompt: prompt.to_string(),
40            stream: None,
41            max_tokens: None,
42            temperature: None,
43            seed: None,
44            top_p: None,
45            top_k: None,
46            frequency_penalty: None,
47            presence_penalty: None,
48            repetition_penalty: None,
49            logit_bias: None,
50            top_logprobs: None,
51            min_p: None,
52            top_a: None,
53            transforms: None,
54            models: None,
55            route: None,
56            provider: None,
57            reasoning: None,
58        }
59    }
60
61    setter!(stream, bool);
62    setter!(max_tokens, u32);
63    setter!(temperature, f64);
64    setter!(seed, u32);
65    setter!(top_p, f64);
66    setter!(top_k, u32);
67    setter!(frequency_penalty, f64);
68    setter!(presence_penalty, f64);
69    setter!(repetition_penalty, f64);
70    setter!(logit_bias, HashMap<String, f64>);
71    setter!(top_logprobs, u32);
72    setter!(min_p, f64);
73    setter!(top_a, f64);
74    setter!(transforms, Vec<String>);
75    setter!(models, Vec<String>);
76    setter!(route, String);
77    setter!(provider, ProviderPreferences);
78    setter!(reasoning, ReasoningConfig);
79}
80
81#[derive(Serialize, Deserialize, Debug)]
82pub struct CompletionResponse {
83    id: Option<String>,
84    choices: Option<Vec<Choice>>,
85}
86
87#[derive(Serialize, Deserialize, Debug)]
88pub struct Choice {
89    text: Option<String>,
90    index: Option<u32>,
91    finish_reason: Option<String>,
92}
93
94/// Send a completion request to a selected model (text-only format)
95///
96/// # Arguments
97///
98/// * `client` - The HTTP client to use for the request.
99/// * `api_key` - The API key for authentication.
100/// * `request` - The completion request containing the model, prompt, and other optional parameters.
101///
102/// # Returns
103///
104/// * `Result<CompletionResponse, OpenRouterError>` - The response from the completion request, containing the generated text and other details.
105pub async fn send_completion_request(
106    client: &Client,
107    api_key: &str,
108    request: &CompletionRequest,
109) -> Result<CompletionResponse, OpenRouterError> {
110    let url = "https://openrouter.ai/api/v1/completions";
111
112    let response = client
113        .post(url)
114        .bearer_auth(api_key)
115        .json(request)
116        .send()
117        .await?;
118
119    if response.status().is_success() {
120        let completion_response = response.json::<CompletionResponse>().await?;
121        Ok(completion_response)
122    } else {
123        handle_error(response).await?;
124        unreachable!()
125    }
126}