1use derive_builder::Builder;
2use serde::{Deserialize, Serialize};
3
4use crate::error::OpenAIError;
5use crate::spec::Metadata;
6use crate::spec::chat::{ChatCompletionTool, ImageDetail, InputAudio, ResponseFormat};
7use crate::spec::graders::{
8 GraderLabelModel, GraderPython, GraderScoreModel, GraderStringCheck, GraderTextSimilarity,
9};
10pub use crate::spec::responses::{EasyInputMessage, InputTextContent, ReasoningEffort};
12use crate::spec::responses::{ResponseTextParam, Tool};
13
14#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
21pub struct Eval {
22 pub object: String,
24 pub id: String,
26 pub name: String,
28 pub data_source_config: EvalDataSourceConfig,
30 pub testing_criteria: Vec<EvalTestingCriterion>,
32 pub created_at: u64,
34 pub metadata: Metadata,
35}
36
37#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
39#[serde(tag = "type", rename_all = "snake_case")]
40pub enum EvalDataSourceConfig {
41 Custom(EvalCustomDataSourceConfig),
43 Logs(EvalLogsDataSourceConfig),
45 #[serde(rename = "stored_completions")]
47 StoredCompletions(EvalStoredCompletionsDataSourceConfig),
48}
49
50#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
52pub struct EvalCustomDataSourceConfig {
53 #[serde(rename = "type")]
55 pub kind: String,
56 pub schema: serde_json::Value,
58}
59
60#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
62pub struct EvalLogsDataSourceConfig {
63 #[serde(rename = "type")]
65 pub kind: String,
66 #[serde(skip_serializing_if = "Option::is_none")]
68 pub metadata: Option<Metadata>,
69 pub schema: serde_json::Value,
71}
72
73#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
75pub struct EvalStoredCompletionsDataSourceConfig {
76 #[serde(rename = "type")]
78 pub kind: String,
79 #[serde(skip_serializing_if = "Option::is_none")]
81 pub metadata: Option<Metadata>,
82 pub schema: serde_json::Value,
84}
85
86#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
88#[serde(tag = "type", rename_all = "snake_case")]
89pub enum EvalTestingCriterion {
90 LabelModel(EvalGraderLabelModel),
92 StringCheck(EvalGraderStringCheck),
94 TextSimilarity(EvalGraderTextSimilarity),
96 Python(EvalGraderPython),
98 ScoreModel(EvalGraderScoreModel),
100}
101
102#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
104#[serde(transparent)]
105pub struct EvalGraderLabelModel(pub GraderLabelModel);
106
107#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
109#[serde(transparent)]
110pub struct EvalGraderStringCheck(pub GraderStringCheck);
111
112#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
114pub struct EvalGraderTextSimilarity {
115 #[serde(flatten)]
116 pub grader: GraderTextSimilarity,
117 pub pass_threshold: f64,
118}
119
120#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq)]
122#[serde(rename_all = "snake_case")]
123pub enum TextSimilarityMetric {
124 Cosine,
126 FuzzyMatch,
128 Bleu,
130 Gleu,
132 Meteor,
134 Rouge1,
136 Rouge2,
138 Rouge3,
140 Rouge4,
142 Rouge5,
144 RougeL,
146}
147
148#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
151pub struct EvalGraderPython {
152 #[serde(flatten)]
153 pub grader: GraderPython,
154 pub pass_threshold: Option<f64>,
155}
156
157#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
158pub struct SamplingParams {
159 #[serde(skip_serializing_if = "Option::is_none")]
161 pub seed: Option<i32>,
162 #[serde(skip_serializing_if = "Option::is_none")]
164 pub top_p: Option<f64>,
165 #[serde(skip_serializing_if = "Option::is_none")]
167 pub temperature: Option<f64>,
168 #[serde(skip_serializing_if = "Option::is_none")]
170 pub max_completion_tokens: Option<i32>,
171 #[serde(skip_serializing_if = "Option::is_none")]
173 pub reasoning_effort: Option<ReasoningEffort>,
174}
175
176#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
179pub struct EvalGraderScoreModel {
180 #[serde(flatten)]
181 pub grader: GraderScoreModel,
182 pub pass_threshold: Option<f64>,
184}
185
186#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
187pub struct EvalItem {
188 pub role: EvalItemRole,
191 pub content: EvalItemContent,
194}
195
196#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq)]
198#[serde(rename_all = "lowercase")]
199pub enum EvalItemRole {
200 User,
202 Assistant,
204 System,
206 Developer,
208}
209
210#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
212pub struct EvalItemContentOutputText {
213 pub text: String,
215}
216
217#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
219pub struct EvalItemInputImage {
220 pub image_url: String,
222 #[serde(skip_serializing_if = "Option::is_none")]
225 pub detail: Option<ImageDetail>,
226}
227
228#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
232#[serde(untagged)]
233pub enum EvalItemContent {
234 Array(Vec<EvalItemContentItem>),
236 Single(EvalItemContentItem),
238}
239
240#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
242#[serde(tag = "type", rename_all = "snake_case")]
243pub enum EvalItemContentItem {
244 InputText(InputTextContent),
246 OutputText(EvalItemContentOutputText),
248 InputImage(EvalItemInputImage),
250 InputAudio(InputAudio),
252 #[serde(untagged)]
254 Text(String),
255}
256
257#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
259pub struct EvalList {
260 pub object: String,
262 pub data: Vec<Eval>,
264 pub first_id: Option<String>,
266 pub last_id: Option<String>,
268 pub has_more: bool,
270}
271
272#[derive(Debug, Serialize, Clone, Builder, PartialEq, Default)]
273#[builder(name = "CreateEvalRequestArgs")]
274#[builder(pattern = "mutable")]
275#[builder(setter(into, strip_option), default)]
276#[builder(derive(Debug))]
277#[builder(build_fn(error = "OpenAIError"))]
278pub struct CreateEvalRequest {
279 pub name: Option<String>,
281 pub data_source_config: CreateEvalDataSourceConfig,
284 pub testing_criteria: Vec<CreateEvalTestingCriterion>,
289 #[serde(skip_serializing_if = "Option::is_none")]
290 pub metadata: Option<Metadata>,
291}
292
293#[derive(Debug, Serialize, Clone, PartialEq)]
294#[serde(tag = "type", rename_all = "snake_case")]
295pub enum CreateEvalDataSourceConfig {
296 Custom(CreateEvalCustomDataSourceConfig),
301 Logs(CreateEvalLogsDataSourceConfig),
304}
305
306impl Default for CreateEvalDataSourceConfig {
307 fn default() -> Self {
308 Self::Custom(CreateEvalCustomDataSourceConfig::default())
309 }
310}
311
312#[derive(Debug, Serialize, Clone, PartialEq, Builder, Default)]
313#[builder(name = "CreateEvalCustomDataSourceConfigArgs")]
314#[builder(pattern = "mutable")]
315#[builder(setter(into, strip_option), default)]
316#[builder(derive(Debug))]
317#[builder(build_fn(error = "OpenAIError"))]
318pub struct CreateEvalCustomDataSourceConfig {
319 pub item_schema: serde_json::Value,
321 #[serde(skip_serializing_if = "Option::is_none")]
324 pub include_sample_schema: Option<bool>,
325}
326
327#[derive(Debug, Serialize, Clone, PartialEq, Builder, Default)]
329#[builder(name = "CreateEvalLogsDataSourceConfigArgs")]
330#[builder(pattern = "mutable")]
331#[builder(setter(into, strip_option), default)]
332#[builder(derive(Debug))]
333#[builder(build_fn(error = "OpenAIError"))]
334pub struct CreateEvalLogsDataSourceConfig {
335 #[serde(skip_serializing_if = "Option::is_none")]
337 pub metadata: Option<Metadata>,
338}
339
340#[derive(Debug, Serialize, Clone, PartialEq)]
341#[serde(tag = "type", rename_all = "snake_case")]
342pub enum CreateEvalTestingCriterion {
343 LabelModel(CreateEvalLabelModelGrader),
346 StringCheck(EvalGraderStringCheck),
349 TextSimilarity(EvalGraderTextSimilarity),
351 Python(EvalGraderPython),
353 ScoreModel(EvalGraderScoreModel),
355}
356
357#[derive(Debug, Serialize, Clone, PartialEq, Builder, Default)]
359#[builder(name = "CreateEvalLabelModelGraderArgs")]
360#[builder(pattern = "mutable")]
361#[builder(setter(into, strip_option), default)]
362#[builder(derive(Debug))]
363#[builder(build_fn(error = "OpenAIError"))]
364pub struct CreateEvalLabelModelGrader {
365 pub name: String,
367 pub model: String,
369 pub input: Vec<CreateEvalItem>,
372 pub labels: Vec<String>,
374 pub passing_labels: Vec<String>,
376}
377
378#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
379pub struct SimpleInputMessage {
380 pub role: String,
382 pub content: String,
384}
385
386#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
388#[serde(tag = "type", rename_all = "snake_case")]
389pub enum CreateEvalItem {
390 Message(EvalItem),
396
397 #[serde(untagged)]
399 Simple(SimpleInputMessage),
400}
401
402#[derive(Debug, Serialize, Clone, Builder, PartialEq, Default)]
404#[builder(name = "UpdateEvalRequestArgs")]
405#[builder(pattern = "mutable")]
406#[builder(setter(into, strip_option), default)]
407#[builder(derive(Debug))]
408#[builder(build_fn(error = "OpenAIError"))]
409pub struct UpdateEvalRequest {
410 #[serde(skip_serializing_if = "Option::is_none")]
412 pub name: Option<String>,
413 #[serde(skip_serializing_if = "Option::is_none")]
415 pub metadata: Option<Metadata>,
416}
417
418#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
420pub struct DeleteEvalResponse {
421 pub object: String,
423 pub deleted: bool,
425 pub eval_id: String,
427}
428
429#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
433pub struct EvalRun {
434 pub object: String,
436 pub id: String,
438 pub eval_id: String,
440 pub status: EvalRunStatus,
442 pub model: String,
444 pub name: String,
446 pub created_at: u64,
448 pub report_url: String,
450 pub result_counts: EvalRunResultCounts,
452 pub per_model_usage: Option<Vec<EvalRunModelUsage>>,
454 pub per_testing_criteria_results: Option<Vec<EvalRunTestingCriteriaResult>>,
456 pub data_source: EvalRunDataSource,
458 pub metadata: Metadata,
460 pub error: Option<EvalApiError>,
462}
463
464#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq)]
466#[serde(rename_all = "snake_case")]
467pub enum EvalRunStatus {
468 Queued,
470 InProgress,
472 Completed,
474 Failed,
476 Canceled,
478}
479
480#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
482pub struct EvalRunResultCounts {
483 pub total: u32,
485 pub errored: u32,
487 pub failed: u32,
489 pub passed: u32,
491}
492
493#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
495pub struct EvalRunModelUsage {
496 pub model_name: String,
498 pub invocation_count: u32,
500 pub prompt_tokens: u32,
502 pub completion_tokens: u32,
504 pub total_tokens: u32,
506 pub cached_tokens: u32,
508}
509
510#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
512pub struct EvalRunTestingCriteriaResult {
513 pub testing_criteria: String,
515 pub passed: u32,
517 pub failed: u32,
519}
520
521#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
523#[serde(tag = "type", rename_all = "snake_case")]
524pub enum EvalRunDataSource {
525 Jsonl(CreateEvalJsonlRunDataSource),
527 Completions(CreateEvalCompletionsRunDataSource),
529 Responses(CreateEvalResponsesRunDataSource),
531}
532
533#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
535pub struct CreateEvalJsonlRunDataSource {
536 pub source: EvalJsonlSource,
538}
539
540#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
542#[serde(tag = "type", rename_all = "snake_case")]
543pub enum EvalJsonlSource {
544 FileContent(EvalJsonlFileContentSource),
546 FileId(EvalJsonlFileIdSource),
548}
549
550#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
552pub struct EvalJsonlFileContentSource {
553 pub content: Vec<EvalJsonlContentItem>,
555}
556
557#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
559pub struct EvalJsonlFileIdSource {
560 pub id: String,
562}
563
564#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
566pub struct EvalJsonlContentItem {
567 pub item: serde_json::Value,
569 #[serde(skip_serializing_if = "Option::is_none")]
571 pub sample: Option<serde_json::Value>,
572}
573
574#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
576pub struct CreateEvalCompletionsRunDataSource {
577 pub input_messages: EvalInputMessages,
582 #[serde(skip_serializing_if = "Option::is_none")]
584 pub sampling_params: Option<EvalSamplingParams>,
585 pub model: String,
587 pub source: EvalCompletionsSource,
589}
590
591#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
592pub struct TemplateInputMessages {
593 pub template: Vec<CreateEvalItem>,
596}
597
598#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
599pub struct ItemReference {
600 pub item_reference: String,
602}
603
604#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
606#[serde(tag = "type", rename_all = "snake_case")]
607pub enum EvalInputMessages {
608 Template(TemplateInputMessages),
610 ItemReference(ItemReference),
612}
613
614#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Default)]
616pub struct EvalSamplingParams {
617 #[serde(skip_serializing_if = "Option::is_none")]
619 pub seed: Option<i32>,
620 #[serde(skip_serializing_if = "Option::is_none")]
622 pub top_p: Option<f64>,
623 #[serde(skip_serializing_if = "Option::is_none")]
625 pub temperature: Option<f64>,
626 #[serde(skip_serializing_if = "Option::is_none")]
628 pub max_completion_tokens: Option<i32>,
629 #[serde(skip_serializing_if = "Option::is_none")]
631 pub reasoning_effort: Option<ReasoningEffort>,
632 #[serde(skip_serializing_if = "Option::is_none")]
634 pub response_format: Option<ResponseFormat>,
635 #[serde(skip_serializing_if = "Option::is_none")]
637 pub tools: Option<Vec<ChatCompletionTool>>,
638}
639
640#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Default)]
641pub struct EvalResponsesSamplingParams {
642 #[serde(skip_serializing_if = "Option::is_none")]
644 pub seed: Option<i32>,
645 #[serde(skip_serializing_if = "Option::is_none")]
647 pub top_p: Option<f64>,
648 #[serde(skip_serializing_if = "Option::is_none")]
650 pub temperature: Option<f64>,
651 #[serde(skip_serializing_if = "Option::is_none")]
653 pub max_completion_tokens: Option<u32>,
654 #[serde(skip_serializing_if = "Option::is_none")]
656 pub reasoning_effort: Option<ReasoningEffort>,
657 #[serde(skip_serializing_if = "Option::is_none")]
659 pub response_format: Option<ResponseFormat>,
660 #[serde(skip_serializing_if = "Option::is_none")]
662 pub tools: Option<Vec<Tool>>,
663 #[serde(skip_serializing_if = "Option::is_none")]
668 pub text: Option<ResponseTextParam>,
669}
670
671#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
673#[serde(tag = "type", rename_all = "snake_case")]
674pub enum EvalCompletionsSource {
675 FileContent(EvalJsonlFileContentSource),
677 FileId(EvalJsonlFileIdSource),
679 StoredCompletions(EvalStoredCompletionsSource),
681}
682
683#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
685pub struct EvalStoredCompletionsSource {
686 #[serde(skip_serializing_if = "Option::is_none")]
688 pub metadata: Option<Metadata>,
689 #[serde(skip_serializing_if = "Option::is_none")]
691 pub model: Option<String>,
692 #[serde(skip_serializing_if = "Option::is_none")]
694 pub created_after: Option<u64>,
695 #[serde(skip_serializing_if = "Option::is_none")]
697 pub created_before: Option<u64>,
698 #[serde(skip_serializing_if = "Option::is_none")]
700 pub limit: Option<i32>,
701}
702
703#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
705pub struct CreateEvalResponsesRunDataSource {
706 #[serde(skip_serializing_if = "Option::is_none")]
709 pub input_messages: Option<EvalInputMessages>,
710 #[serde(skip_serializing_if = "Option::is_none")]
712 pub sampling_params: Option<EvalResponsesSamplingParams>,
713 #[serde(skip_serializing_if = "Option::is_none")]
714 pub model: Option<String>,
715 pub source: EvalResponsesRunSource,
717}
718
719#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
721#[serde(tag = "type", rename_all = "snake_case")]
722pub enum EvalResponsesRunSource {
723 FileContent(EvalJsonlFileContentSource),
725 FileId(EvalJsonlFileIdSource),
727 Responses(EvalResponsesSource),
729}
730
731#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
733pub struct EvalResponsesSource {
734 #[serde(skip_serializing_if = "Option::is_none")]
736 pub metadata: Option<serde_json::Value>,
737 #[serde(skip_serializing_if = "Option::is_none")]
740 pub model: Option<String>,
741 #[serde(skip_serializing_if = "Option::is_none")]
744 pub instructions_search: Option<String>,
745 #[serde(skip_serializing_if = "Option::is_none")]
748 pub created_after: Option<u64>,
749 #[serde(skip_serializing_if = "Option::is_none")]
752 pub created_before: Option<u64>,
753 #[serde(skip_serializing_if = "Option::is_none")]
755 pub reasoning_effort: Option<ReasoningEffort>,
756 #[serde(skip_serializing_if = "Option::is_none")]
758 pub temperature: Option<f64>,
759 #[serde(skip_serializing_if = "Option::is_none")]
761 pub top_p: Option<f64>,
762 #[serde(skip_serializing_if = "Option::is_none")]
764 pub users: Option<Vec<String>>,
765 #[serde(skip_serializing_if = "Option::is_none")]
767 pub tools: Option<Vec<String>>,
768}
769
770#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
772pub struct EvalRunList {
773 pub object: String,
775 pub data: Vec<EvalRun>,
777 pub first_id: Option<String>,
779 pub last_id: Option<String>,
781 pub has_more: bool,
783}
784
785#[derive(Debug, Serialize, Clone, Builder, PartialEq, Default)]
787#[builder(name = "CreateEvalRunRequestArgs")]
788#[builder(pattern = "mutable")]
789#[builder(setter(into, strip_option), default)]
790#[builder(derive(Debug))]
791#[builder(build_fn(error = "OpenAIError"))]
792pub struct CreateEvalRunRequest {
793 #[serde(skip_serializing_if = "Option::is_none")]
795 pub name: Option<String>,
796 pub data_source: CreateEvalRunDataSource,
798 #[serde(skip_serializing_if = "Option::is_none")]
800 pub metadata: Option<Metadata>,
801}
802
803#[derive(Debug, Serialize, Clone, PartialEq)]
805#[serde(tag = "type", rename_all = "snake_case")]
806pub enum CreateEvalRunDataSource {
807 Jsonl(CreateEvalJsonlRunDataSource),
809 Completions(CreateEvalCompletionsRunDataSource),
811 Responses(CreateEvalResponsesRunDataSource),
813}
814
815impl Default for CreateEvalRunDataSource {
817 fn default() -> Self {
818 todo!()
819 }
820}
821
822#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
824pub struct DeleteEvalRunResponse {
825 pub object: String,
827 pub deleted: bool,
829 pub run_id: String,
831}
832
833#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
837pub struct EvalRunOutputItem {
838 pub object: String,
840 pub id: String,
842 pub run_id: String,
844 pub eval_id: String,
846 pub created_at: u64,
848 pub status: String,
850 pub datasource_item_id: u64,
852 pub datasource_item: serde_json::Value,
854 pub results: Vec<EvalRunOutputItemResult>,
856 pub sample: EvalRunOutputItemSample,
858}
859
860#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
862pub struct EvalRunOutputItemResult {
863 pub name: String,
865 pub score: f64,
867 pub passed: bool,
869 #[serde(skip_serializing_if = "Option::is_none")]
871 pub sample: Option<serde_json::Value>,
872}
873
874#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
875pub struct SimpleOutputMessage {
876 pub role: String,
877 pub content: String,
878}
879
880#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
882pub struct EvalRunOutputItemSample {
883 pub input: Vec<SimpleInputMessage>,
885 pub output: Vec<SimpleOutputMessage>,
887 pub finish_reason: String,
889 pub model: String,
891 pub usage: EvalRunOutputItemUsage,
893 pub error: Option<EvalApiError>,
895 pub temperature: f64,
897 pub max_completion_tokens: i32,
899 pub top_p: f64,
901 pub seed: i32,
903}
904
905#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
907pub struct EvalRunOutputItemUsage {
908 pub total_tokens: i32,
910 pub completion_tokens: i32,
912 pub prompt_tokens: i32,
914 pub cached_tokens: i32,
916}
917
918#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
920pub struct EvalRunOutputItemList {
921 pub object: String,
923 pub data: Vec<EvalRunOutputItem>,
925 pub first_id: Option<String>,
927 pub last_id: Option<String>,
929 pub has_more: bool,
931}
932
933#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
935pub struct EvalApiError {
936 pub code: String,
938 pub message: String,
940}