mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-05 08:09:22 +00:00
fix: refactor online evals (#12654)
move online evals to enterprise repo
This commit is contained in:
@@ -24,10 +24,14 @@ pub mod alerts;
|
||||
pub mod billings;
|
||||
pub mod dashboards;
|
||||
pub mod destinations;
|
||||
#[cfg(feature = "enterprise")]
|
||||
pub mod eval_jobs;
|
||||
pub mod folders;
|
||||
pub mod pipelines;
|
||||
#[cfg(feature = "enterprise")]
|
||||
pub mod providers;
|
||||
pub mod reports;
|
||||
#[cfg(feature = "enterprise")]
|
||||
pub mod score_configs;
|
||||
#[cfg(feature = "enterprise")]
|
||||
pub mod scorers;
|
||||
|
||||
@@ -34,9 +34,15 @@ use crate::{
|
||||
impl From<EvalJobError> for Response {
|
||||
fn from(value: EvalJobError) -> Self {
|
||||
match value {
|
||||
EvalJobError::InfraError(err) => MetaHttpResponse::internal_error(err),
|
||||
EvalJobError::InfraError(err) => {
|
||||
log::error!("[EvalJob] internal error: {err}");
|
||||
MetaHttpResponse::internal_error("Internal server error")
|
||||
}
|
||||
EvalJobError::NotFound => MetaHttpResponse::not_found(value),
|
||||
EvalJobError::ReconcilerError(_) => MetaHttpResponse::internal_error(value),
|
||||
EvalJobError::ReconcilerError(err) => {
|
||||
log::error!("[EvalJob] reconciler error: {err}");
|
||||
MetaHttpResponse::internal_error("Internal server error")
|
||||
}
|
||||
EvalJobError::InvalidStatus(_) | EvalJobError::InvalidStatusTransition { .. } => {
|
||||
MetaHttpResponse::bad_request(value)
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ pub mod dashboards;
|
||||
#[cfg(feature = "enterprise")]
|
||||
pub mod domain_management;
|
||||
pub mod enrichment_table;
|
||||
#[cfg(feature = "enterprise")]
|
||||
pub mod eval_jobs;
|
||||
#[allow(deprecated)]
|
||||
pub mod folders;
|
||||
@@ -51,12 +52,15 @@ pub mod pipelines;
|
||||
#[cfg(feature = "profiling")]
|
||||
pub mod profiling;
|
||||
pub mod promql;
|
||||
#[cfg(feature = "enterprise")]
|
||||
pub mod providers;
|
||||
pub mod ratelimit;
|
||||
#[cfg(feature = "enterprise")]
|
||||
pub mod re_pattern;
|
||||
pub mod rum;
|
||||
#[cfg(feature = "enterprise")]
|
||||
pub mod score_configs;
|
||||
#[cfg(feature = "enterprise")]
|
||||
pub mod scorers;
|
||||
pub mod search;
|
||||
pub mod service_accounts;
|
||||
|
||||
@@ -30,7 +30,10 @@ use crate::{
|
||||
impl From<ProviderError> for Response {
|
||||
fn from(value: ProviderError) -> Self {
|
||||
match value {
|
||||
ProviderError::InfraError(err) => MetaHttpResponse::internal_error(err),
|
||||
ProviderError::InfraError(err) => {
|
||||
log::error!("[Provider] internal error: {err}");
|
||||
MetaHttpResponse::internal_error("Internal server error")
|
||||
}
|
||||
ProviderError::MissingName => {
|
||||
MetaHttpResponse::bad_request("Provider name cannot be empty")
|
||||
}
|
||||
|
||||
@@ -20,7 +20,10 @@ use crate::common::utils::auth::UserEmail;
|
||||
#[cfg(feature = "enterprise")]
|
||||
use crate::handler::http::extractors::Headers;
|
||||
use crate::{
|
||||
common::meta::http::HttpResponse as MetaHttpResponse,
|
||||
common::{
|
||||
meta::{authz::Authz, http::HttpResponse as MetaHttpResponse},
|
||||
utils::auth::{is_ofga_object_visible, remove_ownership, set_ownership},
|
||||
},
|
||||
handler::http::models::score_configs::{
|
||||
ListScoreConfigVersionsResponseBody, ListScoreConfigsResponseBody, ScoreConfigRequestBody,
|
||||
ScoreConfigResponseBody, ScoreConfigUpdateRequestBody,
|
||||
@@ -28,19 +31,20 @@ use crate::{
|
||||
service::llm_evaluations::score_configs::{self, ScoreConfigError},
|
||||
};
|
||||
|
||||
impl From<ScoreConfigError> for Response {
|
||||
fn from(value: ScoreConfigError) -> Self {
|
||||
match value {
|
||||
ScoreConfigError::InfraError(err) => MetaHttpResponse::internal_error(err),
|
||||
ScoreConfigError::MissingName => {
|
||||
MetaHttpResponse::bad_request("Score config name cannot be empty")
|
||||
}
|
||||
ScoreConfigError::NotFound => MetaHttpResponse::not_found("Score config not found"),
|
||||
ScoreConfigError::DuplicateName => {
|
||||
MetaHttpResponse::conflict("Score config name already exists")
|
||||
}
|
||||
ScoreConfigError::InUseByScorer => MetaHttpResponse::conflict(value),
|
||||
fn score_config_error_response(value: ScoreConfigError) -> Response {
|
||||
match value {
|
||||
ScoreConfigError::InfraError(err) => {
|
||||
log::error!("[ScoreConfig] internal error: {err}");
|
||||
MetaHttpResponse::internal_error("Internal server error")
|
||||
}
|
||||
ScoreConfigError::MissingName => {
|
||||
MetaHttpResponse::bad_request("Score config name cannot be empty")
|
||||
}
|
||||
ScoreConfigError::NotFound => MetaHttpResponse::not_found("Score config not found"),
|
||||
ScoreConfigError::DuplicateName => {
|
||||
MetaHttpResponse::conflict("Score config name already exists")
|
||||
}
|
||||
ScoreConfigError::InUseByScorer => MetaHttpResponse::conflict(value),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,15 +84,23 @@ pub async fn list_score_configs(
|
||||
Err(e) => return MetaHttpResponse::forbidden(e.to_string()),
|
||||
}
|
||||
};
|
||||
#[cfg(not(feature = "enterprise"))]
|
||||
let permitted_objects = None;
|
||||
|
||||
match score_configs::list_score_configs(&org_id, permitted_objects).await {
|
||||
match score_configs::list_score_configs(&org_id).await {
|
||||
Ok(list) => {
|
||||
let list: Vec<infra::table::score_configs::ScoreConfig> = list
|
||||
.into_iter()
|
||||
.filter(|config| {
|
||||
is_ofga_object_visible(
|
||||
&org_id,
|
||||
"score_config",
|
||||
&config.entity_id,
|
||||
permitted_objects.as_deref(),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let body: ListScoreConfigsResponseBody = list.into();
|
||||
MetaHttpResponse::json(body)
|
||||
}
|
||||
Err(err) => err.into(),
|
||||
Err(err) => score_config_error_response(err),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,10 +132,11 @@ pub async fn create_score_config(
|
||||
let config: infra::table::score_configs::ScoreConfig = body.into();
|
||||
match score_configs::save_score_config(&org_id, config).await {
|
||||
Ok(c) => {
|
||||
set_ownership(&org_id, "score_configs", Authz::new(&c.entity_id)).await;
|
||||
let resp: ScoreConfigResponseBody = c.into();
|
||||
MetaHttpResponse::json(resp)
|
||||
}
|
||||
Err(err) => err.into(),
|
||||
Err(err) => score_config_error_response(err),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +168,7 @@ pub async fn get_score_config(Path((org_id, entity_id)): Path<(String, String)>)
|
||||
let resp: ScoreConfigResponseBody = c.into();
|
||||
MetaHttpResponse::json(resp)
|
||||
}
|
||||
Err(err) => err.into(),
|
||||
Err(err) => score_config_error_response(err),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,7 +201,7 @@ pub async fn list_score_config_versions(
|
||||
let body: ListScoreConfigVersionsResponseBody = versions.into();
|
||||
MetaHttpResponse::json(body)
|
||||
}
|
||||
Err(err) => err.into(),
|
||||
Err(err) => score_config_error_response(err),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,7 +238,7 @@ pub async fn update_score_config(
|
||||
let resp: ScoreConfigResponseBody = c.into();
|
||||
MetaHttpResponse::json(resp)
|
||||
}
|
||||
Err(err) => err.into(),
|
||||
Err(err) => score_config_error_response(err),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,8 +267,11 @@ pub async fn update_score_config(
|
||||
)]
|
||||
pub async fn delete_score_config(Path((org_id, entity_id)): Path<(String, String)>) -> Response {
|
||||
match score_configs::delete_score_config(&org_id, &entity_id).await {
|
||||
Ok(()) => MetaHttpResponse::ok("Score config deactivated"),
|
||||
Err(err) => err.into(),
|
||||
Ok(()) => {
|
||||
remove_ownership(&org_id, "score_configs", Authz::new(&entity_id)).await;
|
||||
MetaHttpResponse::ok("Score config deactivated")
|
||||
}
|
||||
Err(err) => score_config_error_response(err),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,7 +288,7 @@ mod tests {
|
||||
(ScoreConfigError::InUseByScorer, 409),
|
||||
];
|
||||
for (err, expected) in cases {
|
||||
let resp: Response = err.into();
|
||||
let resp = score_config_error_response(err);
|
||||
assert_eq!(resp.status().as_u16(), expected);
|
||||
}
|
||||
}
|
||||
@@ -280,7 +296,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_score_config_error_infra_is_500() {
|
||||
let err = ScoreConfigError::InfraError(infra::errors::Error::Message("db".to_string()));
|
||||
let resp: Response = err.into();
|
||||
let resp = score_config_error_response(err);
|
||||
assert_eq!(resp.status().as_u16(), 500);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,10 @@ use crate::common::utils::auth::UserEmail;
|
||||
#[cfg(feature = "enterprise")]
|
||||
use crate::handler::http::extractors::Headers;
|
||||
use crate::{
|
||||
common::meta::http::HttpResponse as MetaHttpResponse,
|
||||
common::{
|
||||
meta::{authz::Authz, http::HttpResponse as MetaHttpResponse},
|
||||
utils::auth::{is_ofga_object_visible, remove_ownership, set_ownership},
|
||||
},
|
||||
handler::http::models::scorers::{
|
||||
ListScorerVersionsResponseBody, ListScorersQuery, ListScorersResponseBody,
|
||||
LlmJudgeOutputSchemaRequestBody, LlmJudgeOutputSchemaResponseBody, ScorerRequestBody,
|
||||
@@ -36,22 +39,21 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
impl From<ScorerError> for Response {
|
||||
fn from(value: ScorerError) -> Self {
|
||||
match value {
|
||||
ScorerError::InfraError(err) => MetaHttpResponse::internal_error(err),
|
||||
ScorerError::MissingName => {
|
||||
MetaHttpResponse::bad_request("Scorer name cannot be empty")
|
||||
}
|
||||
ScorerError::NotFound => MetaHttpResponse::not_found("Scorer not found"),
|
||||
ScorerError::InvalidScorerType(_)
|
||||
| ScorerError::ScorerTypeImmutable
|
||||
| ScorerError::ProducesScoreConfigIdImmutable
|
||||
| ScorerError::ScoreConfigVersionNotFound
|
||||
| ScorerError::InvalidOutputSchema(_) => MetaHttpResponse::bad_request(value),
|
||||
ScorerError::DuplicateName => MetaHttpResponse::conflict(value),
|
||||
ScorerError::InUseByEvalJob => MetaHttpResponse::conflict(value),
|
||||
fn scorer_error_response(value: ScorerError) -> Response {
|
||||
match value {
|
||||
ScorerError::InfraError(err) => {
|
||||
log::error!("[Scorer] internal error: {err}");
|
||||
MetaHttpResponse::internal_error("Internal server error")
|
||||
}
|
||||
ScorerError::MissingName => MetaHttpResponse::bad_request("Scorer name cannot be empty"),
|
||||
ScorerError::NotFound => MetaHttpResponse::not_found("Scorer not found"),
|
||||
ScorerError::InvalidScorerType(_)
|
||||
| ScorerError::ScorerTypeImmutable
|
||||
| ScorerError::ProducesScoreConfigIdImmutable
|
||||
| ScorerError::ScoreConfigVersionNotFound
|
||||
| ScorerError::InvalidOutputSchema(_) => MetaHttpResponse::bad_request(value),
|
||||
ScorerError::DuplicateName => MetaHttpResponse::conflict(value),
|
||||
ScorerError::InUseByEvalJob => MetaHttpResponse::conflict(value),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,15 +97,23 @@ pub async fn list_scorers(
|
||||
Err(e) => return MetaHttpResponse::forbidden(e.to_string()),
|
||||
}
|
||||
};
|
||||
#[cfg(not(feature = "enterprise"))]
|
||||
let permitted_objects = None;
|
||||
|
||||
match scorers::list_scorers(&org_id, query.scorer_type.as_ref(), permitted_objects).await {
|
||||
match scorers::list_scorers(&org_id, query.scorer_type.as_ref()).await {
|
||||
Ok(list) => {
|
||||
let list: Vec<infra::table::scorers::Scorer> = list
|
||||
.into_iter()
|
||||
.filter(|scorer| {
|
||||
is_ofga_object_visible(
|
||||
&org_id,
|
||||
"scorer",
|
||||
&scorer.entity_id,
|
||||
permitted_objects.as_deref(),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let body: ListScorersResponseBody = list.into();
|
||||
MetaHttpResponse::json(body)
|
||||
}
|
||||
Err(err) => err.into(),
|
||||
Err(err) => scorer_error_response(err),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,10 +145,11 @@ pub async fn create_scorer(
|
||||
let scorer: infra::table::scorers::Scorer = body.into();
|
||||
match scorers::save_scorer(&org_id, scorer).await {
|
||||
Ok(s) => {
|
||||
set_ownership(&org_id, "scorers", Authz::new(&s.entity_id)).await;
|
||||
let resp: ScorerResponseBody = s.into();
|
||||
MetaHttpResponse::json(resp)
|
||||
}
|
||||
Err(err) => err.into(),
|
||||
Err(err) => scorer_error_response(err),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +181,7 @@ pub async fn get_scorer(Path((org_id, entity_id)): Path<(String, String)>) -> Re
|
||||
let resp: ScorerResponseBody = s.into();
|
||||
MetaHttpResponse::json(resp)
|
||||
}
|
||||
Err(err) => err.into(),
|
||||
Err(err) => scorer_error_response(err),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,7 +212,7 @@ pub async fn list_scorer_versions(Path((org_id, entity_id)): Path<(String, Strin
|
||||
let body: ListScorerVersionsResponseBody = versions.into();
|
||||
MetaHttpResponse::json(body)
|
||||
}
|
||||
Err(err) => err.into(),
|
||||
Err(err) => scorer_error_response(err),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,7 +249,7 @@ pub async fn update_scorer(
|
||||
let resp: ScorerResponseBody = s.into();
|
||||
MetaHttpResponse::json(resp)
|
||||
}
|
||||
Err(err) => err.into(),
|
||||
Err(err) => scorer_error_response(err),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,8 +278,11 @@ pub async fn update_scorer(
|
||||
)]
|
||||
pub async fn delete_scorer(Path((org_id, entity_id)): Path<(String, String)>) -> Response {
|
||||
match scorers::delete_scorer(&org_id, &entity_id).await {
|
||||
Ok(()) => MetaHttpResponse::ok("Scorer deactivated"),
|
||||
Err(err) => err.into(),
|
||||
Ok(()) => {
|
||||
remove_ownership(&org_id, "scorers", Authz::new(&entity_id)).await;
|
||||
MetaHttpResponse::ok("Scorer deactivated")
|
||||
}
|
||||
Err(err) => scorer_error_response(err),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,7 +313,7 @@ pub async fn test_scorer(
|
||||
) -> Response {
|
||||
match run_scorer_test(&org_id, &body).await {
|
||||
Ok(resp) => MetaHttpResponse::json(resp),
|
||||
Err(err) => err.into(),
|
||||
Err(err) => scorer_error_response(err),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,7 +345,7 @@ pub async fn preview_llm_judge_output_schema(
|
||||
Ok(output_schema) => {
|
||||
MetaHttpResponse::json(LlmJudgeOutputSchemaResponseBody { output_schema })
|
||||
}
|
||||
Err(err) => err.into(),
|
||||
Err(err) => scorer_error_response(err),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -548,7 +562,7 @@ mod tests {
|
||||
(ScorerError::InUseByEvalJob, 409),
|
||||
];
|
||||
for (err, expected) in cases {
|
||||
let resp: Response = err.into();
|
||||
let resp = scorer_error_response(err);
|
||||
assert_eq!(resp.status().as_u16(), expected);
|
||||
}
|
||||
}
|
||||
@@ -556,7 +570,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_scorer_error_infra_is_500() {
|
||||
let err = ScorerError::InfraError(infra::errors::Error::Message("db".to_string()));
|
||||
let resp: Response = err.into();
|
||||
let resp = scorer_error_response(err);
|
||||
assert_eq!(resp.status().as_u16(), 500);
|
||||
}
|
||||
|
||||
|
||||
@@ -366,6 +366,7 @@ pub async fn zo_config() -> impl IntoResponse {
|
||||
let service_streams_enabled = enterprise_value!(false, o2cfg.service_streams.enabled);
|
||||
// Anomaly detection is always on when the enterprise feature is compiled in — no runtime flag.
|
||||
let anomaly_detection_enabled = enterprise_value!(false, true);
|
||||
let online_evals_enabled = enterprise_value!(false, o2cfg.common.online_evals_enabled);
|
||||
|
||||
#[cfg(all(feature = "cloud", not(feature = "enterprise")))]
|
||||
let build_type = "cloud";
|
||||
@@ -473,7 +474,7 @@ pub async fn zo_config() -> impl IntoResponse {
|
||||
incidents_enabled,
|
||||
service_streams_enabled,
|
||||
model_pricing_enabled: cfg.common.model_pricing_enabled,
|
||||
online_evals_enabled: cfg.common.online_evals_enabled,
|
||||
online_evals_enabled,
|
||||
anomaly_detection_enabled,
|
||||
enable_cross_linking: cfg.common.enable_cross_linking,
|
||||
show_fts_field_values: cfg.common.show_fts_field_values,
|
||||
|
||||
@@ -850,35 +850,41 @@ pub fn service_routes() -> Router {
|
||||
// sourcemaps
|
||||
.route("/{org_id}/sourcemaps",get(sourcemaps::list).post(sourcemaps::upload_maps).delete(sourcemaps::delete))
|
||||
.route("/{org_id}/sourcemaps/values",get(sourcemaps::list_values))
|
||||
.route("/{org_id}/sourcemaps/stacktrace",post(sourcemaps::translate_stacktrace))
|
||||
.route("/{org_id}/sourcemaps/stacktrace",post(sourcemaps::translate_stacktrace));
|
||||
|
||||
// LLM Providers (Online Eval Phase 2)
|
||||
.route("/{org_id}/providers", get(providers::list_providers).post(providers::create_provider))
|
||||
.route("/{org_id}/providers/{provider_id}", get(providers::get_provider).put(providers::update_provider).delete(providers::delete_provider))
|
||||
.route("/{org_id}/providers/{provider_id}/test", post(providers::test_provider))
|
||||
#[cfg(feature = "enterprise")]
|
||||
{
|
||||
if get_o2_config().common.online_evals_enabled {
|
||||
router = router
|
||||
// LLM Providers (Online Eval Phase 2)
|
||||
.route("/{org_id}/providers", get(providers::list_providers).post(providers::create_provider))
|
||||
.route("/{org_id}/providers/{provider_id}", get(providers::get_provider).put(providers::update_provider).delete(providers::delete_provider))
|
||||
.route("/{org_id}/providers/{provider_id}/test", post(providers::test_provider))
|
||||
|
||||
// Score Configs (Online Eval Phase 2)
|
||||
// NOTE: /{entity_id}/versions must precede /{entity_id} for routing correctness
|
||||
.route("/{org_id}/score_configs", get(score_configs::list_score_configs).post(score_configs::create_score_config))
|
||||
.route("/{org_id}/score_configs/{entity_id}/versions", get(score_configs::list_score_config_versions))
|
||||
.route("/{org_id}/score_configs/{entity_id}", get(score_configs::get_score_config).put(score_configs::update_score_config).delete(score_configs::delete_score_config))
|
||||
// Score Configs (Online Eval Phase 2)
|
||||
// NOTE: /{entity_id}/versions must precede /{entity_id} for routing correctness
|
||||
.route("/{org_id}/score_configs", get(score_configs::list_score_configs).post(score_configs::create_score_config))
|
||||
.route("/{org_id}/score_configs/{entity_id}/versions", get(score_configs::list_score_config_versions))
|
||||
.route("/{org_id}/score_configs/{entity_id}", get(score_configs::get_score_config).put(score_configs::update_score_config).delete(score_configs::delete_score_config))
|
||||
|
||||
// Scorers (Online Eval Phase 2)
|
||||
// NOTE: static and nested routes must precede /{entity_id}
|
||||
.route("/{org_id}/scorers", get(scorers::list_scorers).post(scorers::create_scorer))
|
||||
.route("/{org_id}/scorers/test", post(scorers::test_scorer))
|
||||
.route("/{org_id}/scorers/llm_judge/output_schema", post(scorers::preview_llm_judge_output_schema))
|
||||
.route("/{org_id}/scorers/{entity_id}/versions", get(scorers::list_scorer_versions))
|
||||
.route("/{org_id}/scorers/{entity_id}", get(scorers::get_scorer).put(scorers::update_scorer).delete(scorers::delete_scorer))
|
||||
// Scorers (Online Eval Phase 2)
|
||||
// NOTE: static and nested routes must precede /{entity_id}
|
||||
.route("/{org_id}/scorers", get(scorers::list_scorers).post(scorers::create_scorer))
|
||||
.route("/{org_id}/scorers/test", post(scorers::test_scorer))
|
||||
.route("/{org_id}/scorers/llm_judge/output_schema", post(scorers::preview_llm_judge_output_schema))
|
||||
.route("/{org_id}/scorers/{entity_id}/versions", get(scorers::list_scorer_versions))
|
||||
.route("/{org_id}/scorers/{entity_id}", get(scorers::get_scorer).put(scorers::update_scorer).delete(scorers::delete_scorer))
|
||||
|
||||
// Online Eval Jobs (Online Eval Phase 2)
|
||||
// NOTE: /activate, /pause, /resume, /archive must precede /{job_id}
|
||||
.route("/{org_id}/eval_jobs", get(eval_jobs::list_eval_jobs).post(eval_jobs::create_eval_job))
|
||||
.route("/{org_id}/eval_jobs/{job_id}/activate", post(eval_jobs::activate_eval_job))
|
||||
.route("/{org_id}/eval_jobs/{job_id}/pause", post(eval_jobs::pause_eval_job))
|
||||
.route("/{org_id}/eval_jobs/{job_id}/resume", post(eval_jobs::resume_eval_job))
|
||||
.route("/{org_id}/eval_jobs/{job_id}/archive", post(eval_jobs::archive_eval_job))
|
||||
.route("/{org_id}/eval_jobs/{job_id}", get(eval_jobs::get_eval_job).put(eval_jobs::update_eval_job).delete(eval_jobs::delete_eval_job));
|
||||
// Online Eval Jobs (Online Eval Phase 2)
|
||||
// NOTE: /activate, /pause, /resume, /archive must precede /{job_id}
|
||||
.route("/{org_id}/eval_jobs", get(eval_jobs::list_eval_jobs).post(eval_jobs::create_eval_job))
|
||||
.route("/{org_id}/eval_jobs/{job_id}/activate", post(eval_jobs::activate_eval_job))
|
||||
.route("/{org_id}/eval_jobs/{job_id}/pause", post(eval_jobs::pause_eval_job))
|
||||
.route("/{org_id}/eval_jobs/{job_id}/resume", post(eval_jobs::resume_eval_job))
|
||||
.route("/{org_id}/eval_jobs/{job_id}/archive", post(eval_jobs::archive_eval_job))
|
||||
.route("/{org_id}/eval_jobs/{job_id}", get(eval_jobs::get_eval_job).put(eval_jobs::update_eval_job).delete(eval_jobs::delete_eval_job));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user