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