Skip to main content

langfuse_client_base/apis/
experiments_api.rs

1/*
2 * server
3 *
4 * ## Real-time data  The only real-time path to get tracing data is to ingest via OpenTelemetry (`POST /api/public/otel/v1/traces`) and retrieve via Observations API v2 (`GET /api/public/v2/observations`) and Metrics API v2 (`GET /api/public/v2/metrics`). Other public API write and read endpoints can delay data by about 10 minutes. Direct OpenTelemetry exporters must send the `x-langfuse-ingestion-version: 4` header; current Python and JS SDKs already do. See the [Public API docs](https://langfuse.com/docs/api-and-data-platform/features/public-api) and [real-time ingestion](https://langfuse.com/integrations/native/opentelemetry.md#real-time-ingestion).  ## Authentication  Authenticate with the API using [Basic Auth](https://en.wikipedia.org/wiki/Basic_access_authentication), get API keys in the project settings:  - username: Langfuse Public Key - password: Langfuse Secret Key  ## Exports  - OpenAPI spec: https://cloud.langfuse.com/generated/api/openapi.yml - Self-hosted deployments: interactive API reference at `/api/docs` and OpenAPI spec at `/api/openapi.yaml`
5 *
6 * The version of the OpenAPI document:
7 *
8 * Generated by: https://openapi-generator.tech
9 */
10
11use super::{configuration, ContentType, Error};
12use crate::{apis::ResponseContent, models};
13use reqwest;
14use serde::{de::Error as _, Deserialize, Serialize};
15
16/// struct for typed errors of method [`experiments_list`]
17#[derive(Debug, Clone, Serialize, Deserialize)]
18#[serde(untagged)]
19pub enum ExperimentsListError {
20    Status400(serde_json::Value),
21    Status401(serde_json::Value),
22    Status403(serde_json::Value),
23    Status404(serde_json::Value),
24    Status405(serde_json::Value),
25    UnknownValue(serde_json::Value),
26}
27
28/// struct for typed errors of method [`experiments_list_items`]
29#[derive(Debug, Clone, Serialize, Deserialize)]
30#[serde(untagged)]
31pub enum ExperimentsListItemsError {
32    Status400(serde_json::Value),
33    Status401(serde_json::Value),
34    Status403(serde_json::Value),
35    Status404(serde_json::Value),
36    Status405(serde_json::Value),
37    UnknownValue(serde_json::Value),
38}
39
40/// List experiments with cursor-based pagination. Results are ordered by latest experiment activity descending.
41#[bon::builder]
42pub async fn experiments_list(
43    configuration: &configuration::Configuration,
44    from_start_time: chrono::DateTime<chrono::FixedOffset>,
45    fields: Option<&str>,
46    limit: Option<i32>,
47    score_limit: Option<i32>,
48    cursor: Option<&str>,
49    to_start_time: Option<chrono::DateTime<chrono::FixedOffset>>,
50    id: Option<&str>,
51    name: Option<&str>,
52    dataset_id: Option<&str>,
53    filter: Option<&str>,
54) -> Result<models::ExperimentsResponse, Error<ExperimentsListError>> {
55    // add a prefix to parameters to efficiently prevent name collisions
56    let p_query_from_start_time = from_start_time;
57    let p_query_fields = fields;
58    let p_query_limit = limit;
59    let p_query_score_limit = score_limit;
60    let p_query_cursor = cursor;
61    let p_query_to_start_time = to_start_time;
62    let p_query_id = id;
63    let p_query_name = name;
64    let p_query_dataset_id = dataset_id;
65    let p_query_filter = filter;
66
67    let uri_str = format!("{}/api/public/experiments", configuration.base_path);
68    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
69
70    if let Some(ref param_value) = p_query_fields {
71        req_builder = req_builder.query(&[("fields", &param_value.to_string())]);
72    }
73    if let Some(ref param_value) = p_query_limit {
74        req_builder = req_builder.query(&[("limit", &param_value.to_string())]);
75    }
76    if let Some(ref param_value) = p_query_score_limit {
77        req_builder = req_builder.query(&[("scoreLimit", &param_value.to_string())]);
78    }
79    if let Some(ref param_value) = p_query_cursor {
80        req_builder = req_builder.query(&[("cursor", &param_value.to_string())]);
81    }
82    req_builder = req_builder.query(&[("fromStartTime", &p_query_from_start_time.to_string())]);
83    if let Some(ref param_value) = p_query_to_start_time {
84        req_builder = req_builder.query(&[("toStartTime", &param_value.to_string())]);
85    }
86    if let Some(ref param_value) = p_query_id {
87        req_builder = req_builder.query(&[("id", &param_value.to_string())]);
88    }
89    if let Some(ref param_value) = p_query_name {
90        req_builder = req_builder.query(&[("name", &param_value.to_string())]);
91    }
92    if let Some(ref param_value) = p_query_dataset_id {
93        req_builder = req_builder.query(&[("datasetId", &param_value.to_string())]);
94    }
95    if let Some(ref param_value) = p_query_filter {
96        req_builder = req_builder.query(&[("filter", &param_value.to_string())]);
97    }
98    if let Some(ref user_agent) = configuration.user_agent {
99        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
100    }
101    if let Some(ref auth_conf) = configuration.basic_auth {
102        req_builder = req_builder.basic_auth(auth_conf.0.to_owned(), auth_conf.1.to_owned());
103    };
104
105    let req = req_builder.build()?;
106    let resp = configuration.client.execute(req).await?;
107
108    let status = resp.status();
109    let content_type = resp
110        .headers()
111        .get("content-type")
112        .and_then(|v| v.to_str().ok())
113        .unwrap_or("application/octet-stream");
114    let content_type = super::ContentType::from(content_type);
115
116    if !status.is_client_error() && !status.is_server_error() {
117        let content = resp.text().await?;
118        match content_type {
119            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
120            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::ExperimentsResponse`"))),
121            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::ExperimentsResponse`")))),
122        }
123    } else {
124        let content = resp.text().await?;
125        let entity: Option<ExperimentsListError> = serde_json::from_str(&content).ok();
126        Err(Error::ResponseError(ResponseContent {
127            status,
128            content,
129            entity,
130        }))
131    }
132}
133
134/// List experiment items with cursor-based pagination. Use this endpoint to export experiment item inputs, outputs, expected outputs, metadata, and optionally item/trace scores. Results are ordered by time descending.
135#[bon::builder]
136pub async fn experiments_list_items(
137    configuration: &configuration::Configuration,
138    from_start_time: chrono::DateTime<chrono::FixedOffset>,
139    fields: Option<&str>,
140    limit: Option<i32>,
141    score_limit: Option<i32>,
142    cursor: Option<&str>,
143    to_start_time: Option<chrono::DateTime<chrono::FixedOffset>>,
144    experiment_id: Option<&str>,
145    experiment_name: Option<&str>,
146    experiment_item_id: Option<&str>,
147    dataset_id: Option<&str>,
148    filter: Option<&str>,
149) -> Result<models::ExperimentItemsResponse, Error<ExperimentsListItemsError>> {
150    // add a prefix to parameters to efficiently prevent name collisions
151    let p_query_from_start_time = from_start_time;
152    let p_query_fields = fields;
153    let p_query_limit = limit;
154    let p_query_score_limit = score_limit;
155    let p_query_cursor = cursor;
156    let p_query_to_start_time = to_start_time;
157    let p_query_experiment_id = experiment_id;
158    let p_query_experiment_name = experiment_name;
159    let p_query_experiment_item_id = experiment_item_id;
160    let p_query_dataset_id = dataset_id;
161    let p_query_filter = filter;
162
163    let uri_str = format!("{}/api/public/experiment-items", configuration.base_path);
164    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
165
166    if let Some(ref param_value) = p_query_fields {
167        req_builder = req_builder.query(&[("fields", &param_value.to_string())]);
168    }
169    if let Some(ref param_value) = p_query_limit {
170        req_builder = req_builder.query(&[("limit", &param_value.to_string())]);
171    }
172    if let Some(ref param_value) = p_query_score_limit {
173        req_builder = req_builder.query(&[("scoreLimit", &param_value.to_string())]);
174    }
175    if let Some(ref param_value) = p_query_cursor {
176        req_builder = req_builder.query(&[("cursor", &param_value.to_string())]);
177    }
178    req_builder = req_builder.query(&[("fromStartTime", &p_query_from_start_time.to_string())]);
179    if let Some(ref param_value) = p_query_to_start_time {
180        req_builder = req_builder.query(&[("toStartTime", &param_value.to_string())]);
181    }
182    if let Some(ref param_value) = p_query_experiment_id {
183        req_builder = req_builder.query(&[("experimentId", &param_value.to_string())]);
184    }
185    if let Some(ref param_value) = p_query_experiment_name {
186        req_builder = req_builder.query(&[("experimentName", &param_value.to_string())]);
187    }
188    if let Some(ref param_value) = p_query_experiment_item_id {
189        req_builder = req_builder.query(&[("experimentItemId", &param_value.to_string())]);
190    }
191    if let Some(ref param_value) = p_query_dataset_id {
192        req_builder = req_builder.query(&[("datasetId", &param_value.to_string())]);
193    }
194    if let Some(ref param_value) = p_query_filter {
195        req_builder = req_builder.query(&[("filter", &param_value.to_string())]);
196    }
197    if let Some(ref user_agent) = configuration.user_agent {
198        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
199    }
200    if let Some(ref auth_conf) = configuration.basic_auth {
201        req_builder = req_builder.basic_auth(auth_conf.0.to_owned(), auth_conf.1.to_owned());
202    };
203
204    let req = req_builder.build()?;
205    let resp = configuration.client.execute(req).await?;
206
207    let status = resp.status();
208    let content_type = resp
209        .headers()
210        .get("content-type")
211        .and_then(|v| v.to_str().ok())
212        .unwrap_or("application/octet-stream");
213    let content_type = super::ContentType::from(content_type);
214
215    if !status.is_client_error() && !status.is_server_error() {
216        let content = resp.text().await?;
217        match content_type {
218            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
219            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::ExperimentItemsResponse`"))),
220            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::ExperimentItemsResponse`")))),
221        }
222    } else {
223        let content = resp.text().await?;
224        let entity: Option<ExperimentsListItemsError> = serde_json::from_str(&content).ok();
225        Err(Error::ResponseError(ResponseContent {
226            status,
227            content,
228            entity,
229        }))
230    }
231}