mistralrs_server_core/
openapi_doc.rs

1//! ## OpenAPI doc functionality.
2
3use utoipa::OpenApi;
4
5use crate::{
6    chat_completion::__path_chatcompletions,
7    completions::__path_completions,
8    embeddings::__path_embeddings,
9    handlers::{ReIsqRequest, __path_health, __path_models, __path_re_isq},
10    image_generation::__path_image_generation,
11    openai::{
12        AudioResponseFormat, ChatCompletionRequest, CompletionRequest, EmbeddingData,
13        EmbeddingEncodingFormat, EmbeddingInput, EmbeddingRequest, EmbeddingResponse,
14        EmbeddingUsage, EmbeddingVector, FunctionCalled, Grammar, ImageGenerationRequest,
15        JsonSchemaResponseFormat, Message, MessageContent, MessageInnerContent, ModelObject,
16        ModelObjects, ResponseFormat, ResponsesAnnotation, ResponsesChunk, ResponsesContent,
17        ResponsesCreateRequest, ResponsesDelta, ResponsesDeltaContent, ResponsesDeltaOutput,
18        ResponsesError, ResponsesIncompleteDetails, ResponsesInputTokensDetails, ResponsesMessages,
19        ResponsesObject, ResponsesOutput, ResponsesOutputTokensDetails, ResponsesUsage,
20        SpeechGenerationRequest, StopTokens, ToolCall,
21    },
22    responses::{__path_create_response, __path_delete_response, __path_get_response},
23    speech_generation::__path_speech_generation,
24};
25use mistralrs_core::{
26    ApproximateUserLocation, Function, ImageGenerationResponseFormat, SearchContextSize, Tool,
27    ToolChoice, ToolType, WebSearchOptions, WebSearchUserLocation,
28};
29
30/// This is used to generate the OpenAPI docs.
31/// The mistral.rs server router will include these by default, but if you're
32/// including the mistral.rs server core into another project, you can generate the
33/// OpenAPI docs separately to merge with the other project OpenAPI docs.
34///
35/// ### Arguments
36/// * `base_path` - the base path of the mistral.rs server instance (in case the mistral.rs server is being included in another axum project)
37///
38/// ### Example
39/// ```ignore
40/// // MyApp
41/// use axum::{Router, routing::{get, post}};
42/// use utoipa::OpenApi;
43/// use utoipa_swagger_ui::SwaggerUi;
44/// use mistralrs_server_core::openapi_doc::get_openapi_doc;
45///
46/// #[derive(OpenApi)]
47/// #[openapi(
48///     paths(root, controllers::custom_chat),
49///     tags(
50///         (name = "hello", description = "Hello world endpoints")
51///     ),
52///     info(
53///         title = "Hello World API",
54///         version = "1.0.0",
55///         description = "A simple API that responds with a greeting"
56///     )
57/// )]
58/// struct ApiDoc;
59///
60/// let mistral_base_path = "/api/mistral";
61/// let mistral_doc = get_openapi_doc(Some(mistral_base_path));
62/// let mut api_docs = ApiDoc::openapi();
63/// api_docs.merge(mistral_doc);
64///
65/// let app = Router::new()
66///   .route("/", get(root))
67///   .merge(SwaggerUi::new("/api-docs").url("/api-docs/openapi.json", api_docs));
68/// ```
69pub fn get_openapi_doc(base_path: Option<&str>) -> utoipa::openapi::OpenApi {
70    #[derive(OpenApi)]
71    #[openapi(
72        paths(models, health, chatcompletions, completions, embeddings, re_isq, image_generation, speech_generation, create_response, get_response, delete_response),
73        components(schemas(
74            ApproximateUserLocation,
75            AudioResponseFormat,
76            ChatCompletionRequest,
77            CompletionRequest,
78            EmbeddingData,
79            EmbeddingEncodingFormat,
80            EmbeddingInput,
81            EmbeddingRequest,
82            EmbeddingResponse,
83            EmbeddingUsage,
84            EmbeddingVector,
85            Function,
86            FunctionCalled,
87            Grammar,
88            ImageGenerationRequest,
89            ImageGenerationResponseFormat,
90            JsonSchemaResponseFormat,
91            Message,
92            MessageContent,
93            MessageInnerContent,
94            ModelObject,
95            ModelObjects,
96            ReIsqRequest,
97            ResponseFormat,
98            ResponsesAnnotation,
99            ResponsesChunk,
100            ResponsesContent,
101            ResponsesCreateRequest,
102            ResponsesDelta,
103            ResponsesDeltaContent,
104            ResponsesDeltaOutput,
105            ResponsesError,
106            ResponsesIncompleteDetails,
107            ResponsesInputTokensDetails,
108            ResponsesMessages,
109            ResponsesObject,
110            ResponsesOutput,
111            ResponsesOutputTokensDetails,
112            ResponsesUsage,
113            SearchContextSize,
114            SpeechGenerationRequest,
115            StopTokens,
116            Tool,
117            ToolCall,
118            ToolChoice,
119            ToolType,
120            WebSearchOptions,
121            WebSearchUserLocation
122        )),
123        tags(
124            (name = "Mistral.rs", description = "Mistral.rs API")
125        ),
126        info(
127            title = "Mistral.rs",
128            license(
129            name = "MIT",
130        )
131        )
132    )]
133    struct ApiDoc;
134
135    let mut doc = ApiDoc::openapi();
136
137    if let Some(prefix) = base_path {
138        if !prefix.is_empty() {
139            let mut prefixed_paths = utoipa::openapi::Paths::default();
140
141            let original_paths = std::mem::take(&mut doc.paths.paths);
142
143            for (path, item) in original_paths {
144                let prefixed_path = format!("{prefix}{path}");
145                prefixed_paths.paths.insert(prefixed_path, item);
146            }
147
148            prefixed_paths.extensions = doc.paths.extensions.clone();
149
150            doc.paths = prefixed_paths;
151        }
152    }
153
154    doc
155}