Skip to main content

langfuse_client_base/apis/
evaluation_rules_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 [`evaluation_rules_create`]
17#[derive(Debug, Clone, Serialize, Deserialize)]
18#[serde(untagged)]
19pub enum EvaluationRulesCreateError {
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    Status409(models::PublicApiError),
26    Status429(models::PublicApiError),
27    Status500(models::PublicApiError),
28    UnknownValue(serde_json::Value),
29}
30
31/// struct for typed errors of method [`evaluation_rules_delete`]
32#[derive(Debug, Clone, Serialize, Deserialize)]
33#[serde(untagged)]
34pub enum EvaluationRulesDeleteError {
35    Status400(serde_json::Value),
36    Status401(serde_json::Value),
37    Status403(serde_json::Value),
38    Status404(serde_json::Value),
39    Status405(serde_json::Value),
40    Status429(models::PublicApiError),
41    Status500(models::PublicApiError),
42    UnknownValue(serde_json::Value),
43}
44
45/// struct for typed errors of method [`evaluation_rules_get`]
46#[derive(Debug, Clone, Serialize, Deserialize)]
47#[serde(untagged)]
48pub enum EvaluationRulesGetError {
49    Status400(serde_json::Value),
50    Status401(serde_json::Value),
51    Status403(serde_json::Value),
52    Status404(serde_json::Value),
53    Status405(serde_json::Value),
54    Status429(models::PublicApiError),
55    Status500(models::PublicApiError),
56    UnknownValue(serde_json::Value),
57}
58
59/// struct for typed errors of method [`evaluation_rules_list`]
60#[derive(Debug, Clone, Serialize, Deserialize)]
61#[serde(untagged)]
62pub enum EvaluationRulesListError {
63    Status400(serde_json::Value),
64    Status401(serde_json::Value),
65    Status403(serde_json::Value),
66    Status404(serde_json::Value),
67    Status405(serde_json::Value),
68    Status429(models::PublicApiError),
69    Status500(models::PublicApiError),
70    UnknownValue(serde_json::Value),
71}
72
73/// struct for typed errors of method [`evaluation_rules_update`]
74#[derive(Debug, Clone, Serialize, Deserialize)]
75#[serde(untagged)]
76pub enum EvaluationRulesUpdateError {
77    Status400(serde_json::Value),
78    Status401(serde_json::Value),
79    Status403(serde_json::Value),
80    Status404(serde_json::Value),
81    Status405(serde_json::Value),
82    Status409(models::PublicApiError),
83    Status429(models::PublicApiError),
84    Status500(models::PublicApiError),
85    UnknownValue(serde_json::Value),
86}
87
88/// Create an evaluation rule using stable evaluator identifiers.  An evaluation rule defines **which** incoming observations should be evaluated and how prompt variables should be populated.  Key behavior: - rule names are not identifiers and do not need to be unique - rules always use the latest version of each associated evaluator - an enabled rule requires at least one evaluator assignment - omit `sampling` to evaluate every matching observation - omit `filter` to match every incoming observation - `datasetId` is the public filter name for selecting experiment datasets
89#[bon::builder]
90pub async fn evaluation_rules_create(
91    configuration: &configuration::Configuration,
92    create_evaluation_rule_request: models::CreateEvaluationRuleRequest,
93) -> Result<models::EvaluationRule, Error<EvaluationRulesCreateError>> {
94    // add a prefix to parameters to efficiently prevent name collisions
95    let p_body_create_evaluation_rule_request = create_evaluation_rule_request;
96
97    let uri_str = format!("{}/api/public/v2/evaluation-rules", configuration.base_path);
98    let mut req_builder = configuration
99        .client
100        .request(reqwest::Method::POST, &uri_str);
101
102    if let Some(ref user_agent) = configuration.user_agent {
103        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
104    }
105    if let Some(ref auth_conf) = configuration.basic_auth {
106        req_builder = req_builder.basic_auth(auth_conf.0.to_owned(), auth_conf.1.to_owned());
107    };
108    req_builder = req_builder.json(&p_body_create_evaluation_rule_request);
109
110    let req = req_builder.build()?;
111    let resp = configuration.client.execute(req).await?;
112
113    let status = resp.status();
114    let content_type = resp
115        .headers()
116        .get("content-type")
117        .and_then(|v| v.to_str().ok())
118        .unwrap_or("application/octet-stream");
119    let content_type = super::ContentType::from(content_type);
120
121    if !status.is_client_error() && !status.is_server_error() {
122        let content = resp.text().await?;
123        match content_type {
124            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
125            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::EvaluationRule`"))),
126            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::EvaluationRule`")))),
127        }
128    } else {
129        let content = resp.text().await?;
130        let entity: Option<EvaluationRulesCreateError> = serde_json::from_str(&content).ok();
131        Err(Error::ResponseError(ResponseContent {
132            status,
133            content,
134            entity,
135        }))
136    }
137}
138
139/// Delete an evaluation rule.  This removes the live-ingestion rule only. It does not delete associated evaluators or scores already produced by them.  Legacy trace and dataset rules can also be deleted. Their evaluators and previously produced scores are preserved.
140#[bon::builder]
141pub async fn evaluation_rules_delete(
142    configuration: &configuration::Configuration,
143    evaluation_rule_id: &str,
144) -> Result<models::DeletedEvaluationRule, Error<EvaluationRulesDeleteError>> {
145    // add a prefix to parameters to efficiently prevent name collisions
146    let p_path_evaluation_rule_id = evaluation_rule_id;
147
148    let uri_str = format!(
149        "{}/api/public/v2/evaluation-rules/{evaluationRuleId}",
150        configuration.base_path,
151        evaluationRuleId = crate::apis::urlencode(p_path_evaluation_rule_id)
152    );
153    let mut req_builder = configuration
154        .client
155        .request(reqwest::Method::DELETE, &uri_str);
156
157    if let Some(ref user_agent) = configuration.user_agent {
158        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
159    }
160    if let Some(ref auth_conf) = configuration.basic_auth {
161        req_builder = req_builder.basic_auth(auth_conf.0.to_owned(), auth_conf.1.to_owned());
162    };
163
164    let req = req_builder.build()?;
165    let resp = configuration.client.execute(req).await?;
166
167    let status = resp.status();
168    let content_type = resp
169        .headers()
170        .get("content-type")
171        .and_then(|v| v.to_str().ok())
172        .unwrap_or("application/octet-stream");
173    let content_type = super::ContentType::from(content_type);
174
175    if !status.is_client_error() && !status.is_server_error() {
176        let content = resp.text().await?;
177        match content_type {
178            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
179            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::DeletedEvaluationRule`"))),
180            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::DeletedEvaluationRule`")))),
181        }
182    } else {
183        let content = resp.text().await?;
184        let entity: Option<EvaluationRulesDeleteError> = serde_json::from_str(&content).ok();
185        Err(Error::ResponseError(ResponseContent {
186            status,
187            content,
188            entity,
189        }))
190    }
191}
192
193/// Get one evaluation rule, including a legacy trace or dataset rule, by its stable identifier.
194#[bon::builder]
195pub async fn evaluation_rules_get(
196    configuration: &configuration::Configuration,
197    evaluation_rule_id: &str,
198) -> Result<models::EvaluationRule, Error<EvaluationRulesGetError>> {
199    // add a prefix to parameters to efficiently prevent name collisions
200    let p_path_evaluation_rule_id = evaluation_rule_id;
201
202    let uri_str = format!(
203        "{}/api/public/v2/evaluation-rules/{evaluationRuleId}",
204        configuration.base_path,
205        evaluationRuleId = crate::apis::urlencode(p_path_evaluation_rule_id)
206    );
207    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
208
209    if let Some(ref user_agent) = configuration.user_agent {
210        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
211    }
212    if let Some(ref auth_conf) = configuration.basic_auth {
213        req_builder = req_builder.basic_auth(auth_conf.0.to_owned(), auth_conf.1.to_owned());
214    };
215
216    let req = req_builder.build()?;
217    let resp = configuration.client.execute(req).await?;
218
219    let status = resp.status();
220    let content_type = resp
221        .headers()
222        .get("content-type")
223        .and_then(|v| v.to_str().ok())
224        .unwrap_or("application/octet-stream");
225    let content_type = super::ContentType::from(content_type);
226
227    if !status.is_client_error() && !status.is_server_error() {
228        let content = resp.text().await?;
229        match content_type {
230            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
231            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::EvaluationRule`"))),
232            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::EvaluationRule`")))),
233        }
234    } else {
235        let content = resp.text().await?;
236        let entity: Option<EvaluationRulesGetError> = serde_json::from_str(&content).ok();
237        Err(Error::ResponseError(ResponseContent {
238            status,
239            content,
240            entity,
241        }))
242    }
243}
244
245/// List evaluation rules in newest-first creation order.  This includes legacy trace and dataset rules so they can be inspected and migrated. Treat the cursor as opaque and return it unchanged.
246#[bon::builder]
247pub async fn evaluation_rules_list(
248    configuration: &configuration::Configuration,
249    limit: Option<i32>,
250    cursor: Option<&str>,
251) -> Result<models::EvaluationRulesPage, Error<EvaluationRulesListError>> {
252    // add a prefix to parameters to efficiently prevent name collisions
253    let p_query_limit = limit;
254    let p_query_cursor = cursor;
255
256    let uri_str = format!("{}/api/public/v2/evaluation-rules", configuration.base_path);
257    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
258
259    if let Some(ref param_value) = p_query_limit {
260        req_builder = req_builder.query(&[("limit", &param_value.to_string())]);
261    }
262    if let Some(ref param_value) = p_query_cursor {
263        req_builder = req_builder.query(&[("cursor", &param_value.to_string())]);
264    }
265    if let Some(ref user_agent) = configuration.user_agent {
266        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
267    }
268    if let Some(ref auth_conf) = configuration.basic_auth {
269        req_builder = req_builder.basic_auth(auth_conf.0.to_owned(), auth_conf.1.to_owned());
270    };
271
272    let req = req_builder.build()?;
273    let resp = configuration.client.execute(req).await?;
274
275    let status = resp.status();
276    let content_type = resp
277        .headers()
278        .get("content-type")
279        .and_then(|v| v.to_str().ok())
280        .unwrap_or("application/octet-stream");
281    let content_type = super::ContentType::from(content_type);
282
283    if !status.is_client_error() && !status.is_server_error() {
284        let content = resp.text().await?;
285        match content_type {
286            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
287            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::EvaluationRulesPage`"))),
288            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::EvaluationRulesPage`")))),
289        }
290    } else {
291        let content = resp.text().await?;
292        let entity: Option<EvaluationRulesListError> = serde_json::from_str(&content).ok();
293        Err(Error::ResponseError(ResponseContent {
294            status,
295            content,
296            entity,
297        }))
298    }
299}
300
301/// Update an evaluation rule by its stable identifier.  Provide only the fields to change. Providing `evaluatorAssignments` replaces the complete assignment list. Replacing the list with an empty array disables the rule. Setting `enabled=true` is rejected when the resulting assignment list is empty, including when both fields are sent in the same request.  Legacy trace and dataset rules follow the existing lifecycle restrictions: they can be deactivated with `enabled=false`, but their name, filters, sampling, and evaluator assignments cannot be changed.
302#[bon::builder]
303pub async fn evaluation_rules_update(
304    configuration: &configuration::Configuration,
305    evaluation_rule_id: &str,
306    update_evaluation_rule_request: models::UpdateEvaluationRuleRequest,
307) -> Result<models::EvaluationRule, Error<EvaluationRulesUpdateError>> {
308    // add a prefix to parameters to efficiently prevent name collisions
309    let p_path_evaluation_rule_id = evaluation_rule_id;
310    let p_body_update_evaluation_rule_request = update_evaluation_rule_request;
311
312    let uri_str = format!(
313        "{}/api/public/v2/evaluation-rules/{evaluationRuleId}",
314        configuration.base_path,
315        evaluationRuleId = crate::apis::urlencode(p_path_evaluation_rule_id)
316    );
317    let mut req_builder = configuration
318        .client
319        .request(reqwest::Method::PATCH, &uri_str);
320
321    if let Some(ref user_agent) = configuration.user_agent {
322        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
323    }
324    if let Some(ref auth_conf) = configuration.basic_auth {
325        req_builder = req_builder.basic_auth(auth_conf.0.to_owned(), auth_conf.1.to_owned());
326    };
327    req_builder = req_builder.json(&p_body_update_evaluation_rule_request);
328
329    let req = req_builder.build()?;
330    let resp = configuration.client.execute(req).await?;
331
332    let status = resp.status();
333    let content_type = resp
334        .headers()
335        .get("content-type")
336        .and_then(|v| v.to_str().ok())
337        .unwrap_or("application/octet-stream");
338    let content_type = super::ContentType::from(content_type);
339
340    if !status.is_client_error() && !status.is_server_error() {
341        let content = resp.text().await?;
342        match content_type {
343            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
344            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::EvaluationRule`"))),
345            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::EvaluationRule`")))),
346        }
347    } else {
348        let content = resp.text().await?;
349        let entity: Option<EvaluationRulesUpdateError> = serde_json::from_str(&content).ok();
350        Err(Error::ResponseError(ResponseContent {
351            status,
352            content,
353            entity,
354        }))
355    }
356}