From a27eecdff747a36b5a181df31b89a4746b7ccadc Mon Sep 17 00:00:00 2001 From: william Date: Sun, 25 Feb 2024 00:58:12 +0800 Subject: [PATCH] Add openapi docs --- octet-chat-app/pom.xml | 10 +- .../chat/octet/api/ChatCompletionService.java | 101 ++++++++++++++++++ .../src/main/resources/application.yml | 5 +- 3 files changed, 109 insertions(+), 7 deletions(-) diff --git a/octet-chat-app/pom.xml b/octet-chat-app/pom.xml index 74cbd91..2bce0dc 100644 --- a/octet-chat-app/pom.xml +++ b/octet-chat-app/pom.xml @@ -74,11 +74,6 @@ reactor-test test - - io.springfox - springfox-boot-starter - 3.0.0 - commons-cli commons-cli @@ -134,6 +129,11 @@ joda-time 2.12.5 + + org.springdoc + springdoc-openapi-webflux-ui + 1.7.0 + diff --git a/octet-chat-app/src/main/java/chat/octet/api/ChatCompletionService.java b/octet-chat-app/src/main/java/chat/octet/api/ChatCompletionService.java index 92f2486..cbd32c3 100644 --- a/octet-chat-app/src/main/java/chat/octet/api/ChatCompletionService.java +++ b/octet-chat-app/src/main/java/chat/octet/api/ChatCompletionService.java @@ -16,8 +16,19 @@ import chat.octet.utils.JsonUtils; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import io.swagger.v3.oas.annotations.ExternalDocumentation; +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.info.Info; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.springdoc.core.annotations.RouterOperation; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; @@ -26,6 +37,7 @@ import org.springframework.core.io.buffer.DefaultDataBufferFactory; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.server.*; import reactor.core.publisher.Flux; @@ -39,8 +51,13 @@ import static org.springframework.web.reactive.function.server.RequestPredicates.POST; +@OpenAPIDefinition( + info = @Info(title = "Octet.Chat", description = "Build your own private auto agent."), + externalDocs = @ExternalDocumentation(description = "Github", url = "https://github.com/eoctet/Octet.Chat") +) @Slf4j @Configuration +@Tag(name = "ChatCompletionService", description = "Chat completion service") public class ChatCompletionService { private final Semaphore semaphore = new Semaphore(1); @@ -64,6 +81,18 @@ private Mono response(HttpStatus status, String body) { @Bean + @RouterOperation( + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.TEXT_EVENT_STREAM_VALUE}, + operation = @Operation( + requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = RequestParameter.class))), + description = "Chat with local agent.", + operationId = "chat", + tags = "Chat & Completions", + responses = @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = ChatCompletionChunk.class))) + ) + ) public RouterFunction chatCompletionsFunction() { return handler( POST("/v1/chat/completions"), @@ -82,6 +111,18 @@ public RouterFunction chatCompletionsFunction() { } @Bean + @RouterOperation( + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.TEXT_EVENT_STREAM_VALUE}, + operation = @Operation( + requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = RequestParameter.class))), + description = "Completions with local agent.", + operationId = "completions", + tags = "Chat & Completions", + responses = @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = ChatCompletionChunk.class))) + ) + ) public RouterFunction completionsFunction() { return handler( POST("/v1/completions"), @@ -96,6 +137,18 @@ public RouterFunction completionsFunction() { } @Bean + @RouterOperation( + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE, + operation = @Operation( + requestBody = @RequestBody(content = @Content(examples = @ExampleObject(value = "{\"content\":\"Your text\"}"), schema = @Schema(implementation = Object.class))), + description = "Tokenize text to tokens.", + operationId = "tokenize", + tags = "Tokenize", + responses = @ApiResponse(responseCode = "200", content = @Content(examples = @ExampleObject(value = "{\"tokens\":[]}"))) + ) + ) public RouterFunction tokenizeFunction() { return handler( POST("/v1/tokenize"), @@ -114,6 +167,18 @@ public RouterFunction tokenizeFunction() { } @Bean + @RouterOperation( + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE, + operation = @Operation( + requestBody = @RequestBody(content = @Content(examples = @ExampleObject(value = "{\"tokens\":[]}"), schema = @Schema(implementation = Object.class))), + description = "Detokenize tokens to text.", + operationId = "detokenize", + tags = "Tokenize", + responses = @ApiResponse(responseCode = "200", content = @Content(examples = @ExampleObject(value = "{\"content\":\"string\"}"))) + ) + ) public RouterFunction detokenizeFunction() { return handler( POST("/v1/detokenize"), @@ -133,6 +198,18 @@ public RouterFunction detokenizeFunction() { @Bean + @RouterOperation( + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.ALL_VALUE, + operation = @Operation( + requestBody = @RequestBody(content = @Content(examples = @ExampleObject(value = "{\"user\":\"string\",\"session\":\"string\"}"), schema = @Schema(implementation = Object.class))), + description = "Reset chat session.", + operationId = "reset", + tags = "Characters", + responses = @ApiResponse(responseCode = "200", content = @Content(examples = @ExampleObject(value = "success"))) + ) + ) public RouterFunction resetSessionFunction() { return handler( POST("/v1/session/reset"), @@ -159,6 +236,18 @@ public RouterFunction resetSessionFunction() { } @Bean + @RouterOperation( + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE, + operation = @Operation( + requestBody = @RequestBody(content = @Content(examples = @ExampleObject(value = "{}"), schema = @Schema(implementation = Object.class))), + description = "Show all AI characters list.", + operationId = "characters", + tags = "Characters", + responses = @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = CharacterModel.class))) + ) + ) public RouterFunction getCharactersFunction() { return RouterFunctions.route( RequestPredicates.POST("/v1/characters").and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), @@ -179,6 +268,18 @@ public RouterFunction getCharactersFunction() { } @Bean + @RouterOperation( + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.ALL_VALUE, + operation = @Operation( + requestBody = @RequestBody(content = @Content(examples = @ExampleObject(value = "{\"character\": \"string\"}"), schema = @Schema(implementation = Object.class))), + description = "Reload AI characters.", + operationId = "reload", + tags = "Characters", + responses = @ApiResponse(responseCode = "200", content = @Content(examples = @ExampleObject(value = "success"))) + ) + ) public RouterFunction reloadCharactersFunction() { return handler( POST("/v1/characters/reload"), diff --git a/octet-chat-app/src/main/resources/application.yml b/octet-chat-app/src/main/resources/application.yml index cba9827..d5881ca 100644 --- a/octet-chat-app/src/main/resources/application.yml +++ b/octet-chat-app/src/main/resources/application.yml @@ -2,8 +2,9 @@ server: port: 8152 shutdown: graceful -swagger: - enabled: true +springdoc: + api-docs: + enabled: true spring: lifecycle: timeout-per-shutdown-phase: 30s