From 70441d740bb81fdc5be3fba9e95a27af3d134172 Mon Sep 17 00:00:00 2001 From: gioelecerati Date: Tue, 1 Oct 2024 13:03:40 +0200 Subject: [PATCH 1/4] ai: generate: remove endpoint from experiment & remove beta from path --- packages/api/src/controllers/generate.test.ts | 50 ++-- packages/api/src/controllers/generate.ts | 8 +- packages/api/src/controllers/index.ts | 2 + packages/api/src/schema/ai-api-schema.yaml | 278 +++++++++++++++--- packages/api/src/schema/pull-ai-schema.js | 14 +- 5 files changed, 291 insertions(+), 61 deletions(-) diff --git a/packages/api/src/controllers/generate.test.ts b/packages/api/src/controllers/generate.test.ts index 4b2c0f078..c58ca4f00 100644 --- a/packages/api/src/controllers/generate.test.ts +++ b/packages/api/src/controllers/generate.test.ts @@ -71,6 +71,16 @@ afterEach(async () => { await clearDatabase(server); }); +const testBothRoutes = (testFn) => { + describe("generate route", () => { + testFn("/generate"); + }); + + describe("beta generate route", () => { + testFn("/beta/generate"); + }); +}; + describe("controllers/generate", () => { let client: TestClient; let adminUser: User; @@ -145,9 +155,9 @@ describe("controllers/generate", () => { return form; }; - describe("API proxies", () => { - it("should call the AI Gateway for generate API /audio-to-text", async () => { - const res = await client.fetch("/beta/generate/audio-to-text", { + testBothRoutes((basePath) => { + it(`should call the AI Gateway for ${basePath}/audio-to-text`, async () => { + const res = await client.fetch(`${basePath}/audio-to-text`, { method: "POST", body: buildMultipartBody( {}, @@ -162,8 +172,8 @@ describe("controllers/generate", () => { expect(aiGatewayCalls).toEqual({ "audio-to-text": 1 }); }); - it("should call the AI Gateway for generate API /text-to-image", async () => { - const res = await client.post("/beta/generate/text-to-image", { + it(`should call the AI Gateway for ${basePath}/text-to-image`, async () => { + const res = await client.post(`${basePath}/text-to-image`, { prompt: "a man in a suit and tie", }); expect(res.status).toBe(200); @@ -174,8 +184,8 @@ describe("controllers/generate", () => { expect(aiGatewayCalls).toEqual({ "text-to-image": 1 }); }); - it("should call the AI Gateway for generate API /image-to-image", async () => { - const res = await client.fetch("/beta/generate/image-to-image", { + it(`should call the AI Gateway for ${basePath}/image-to-image`, async () => { + const res = await client.fetch(`${basePath}/image-to-image`, { method: "POST", body: buildMultipartBody({ prompt: "replace the suit with a bathing suit", @@ -189,8 +199,8 @@ describe("controllers/generate", () => { expect(aiGatewayCalls).toEqual({ "image-to-image": 1 }); }); - it("should call the AI Gateway for generate API /image-to-video", async () => { - const res = await client.fetch("/beta/generate/image-to-video", { + it(`should call the AI Gateway for ${basePath}/image-to-video`, async () => { + const res = await client.fetch(`${basePath}/image-to-video`, { method: "POST", body: buildMultipartBody({}), }); @@ -202,8 +212,8 @@ describe("controllers/generate", () => { expect(aiGatewayCalls).toEqual({ "image-to-video": 1 }); }); - it("should call the AI Gateway for generate API /upscale", async () => { - const res = await client.fetch("/beta/generate/upscale", { + it(`should call the AI Gateway for ${basePath}/upscale`, async () => { + const res = await client.fetch(`${basePath}/upscale`, { method: "POST", body: buildMultipartBody({ prompt: "enhance" }), }); @@ -215,8 +225,8 @@ describe("controllers/generate", () => { expect(aiGatewayCalls).toEqual({ upscale: 1 }); }); - it("should call the AI Gateway for generate API /segment-anything-2", async () => { - const res = await client.fetch("/beta/generate/segment-anything-2", { + it(`should call the AI Gateway for ${basePath}/segment-anything-2`, async () => { + const res = await client.fetch(`${basePath}/segment-anything-2`, { method: "POST", body: buildMultipartBody({}), }); @@ -260,7 +270,7 @@ describe("controllers/generate", () => { for (const [title, input, error] of testCases) { it(title, async () => { - const res = await client.fetch("/beta/generate/image-to-image", { + const res = await client.fetch("/generate/image-to-image", { method: "POST", body: input, }); @@ -287,7 +297,7 @@ describe("controllers/generate", () => { } it("should log all requests to db", async () => { - const res = await client.post("/beta/generate/text-to-image", { + const res = await client.post("/generate/text-to-image", { prompt: "a man in a suit and tie", }); expect(res.status).toBe(200); @@ -325,7 +335,7 @@ describe("controllers/generate", () => { `{"details":{"msg":"sudden error"}}`, ); - const res = await client.post("/beta/generate/text-to-image", { + const res = await client.post("/generate/text-to-image", { prompt: "a man in a suit and tie", }); expect(res.status).toBe(500); @@ -345,7 +355,7 @@ describe("controllers/generate", () => { it("should log non JSON outputs as strings to db", async () => { mockFetchHttpError(418, "text/plain", `I'm not Jason`); - const res = await client.post("/beta/generate/text-to-image", { + const res = await client.post("/generate/text-to-image", { prompt: "a man in a suit and tie", }); expect(res.status).toBe(418); @@ -364,7 +374,7 @@ describe("controllers/generate", () => { mockedFetchWithTimeout.mockImplementation(() => { throw new Error("on your face"); }); - const res = await client.post("/beta/generate/text-to-image", { + const res = await client.post("/generate/text-to-image", { prompt: "a man in a suit and tie", }); expect(res.status).toBe(500); @@ -394,10 +404,10 @@ describe("controllers/generate", () => { const makeAiGenReq = (pipeline: (typeof pipelines)[number]) => pipeline === "text-to-image" - ? client.post(`/beta/generate/${pipeline}`, { + ? client.post(`/generate/${pipeline}`, { prompt: "whatever you feel like", }) - : client.fetch(`/beta/generate/${pipeline}`, { + : client.fetch(`/generate/${pipeline}`, { method: "POST", body: buildMultipartBody( pipeline === "image-to-video" ? {} : { prompt: "make magic" }, diff --git a/packages/api/src/controllers/generate.ts b/packages/api/src/controllers/generate.ts index f9a02c85e..7d7a29da7 100644 --- a/packages/api/src/controllers/generate.ts +++ b/packages/api/src/controllers/generate.ts @@ -35,7 +35,13 @@ const aiGenerateDurationMetric = new promclient.Histogram({ const app = Router(); -app.use(experimentSubjectsOnly("ai-generate")); +// TODO: Remove beta paths middleware +app.use((req, res, next) => { + if (req.path.startsWith("/beta/generate")) { + req.url = req.url.replace("/beta/generate", "/generate"); + } + next(); +}); const rateLimiter: RequestHandler = async (req, res, next) => { const now = Date.now(); diff --git a/packages/api/src/controllers/index.ts b/packages/api/src/controllers/index.ts index f9863cd7f..bb0332a6a 100644 --- a/packages/api/src/controllers/index.ts +++ b/packages/api/src/controllers/index.ts @@ -34,6 +34,8 @@ export default { "api-token": apiToken, asset, auth, + generate, + // TODO: Remove beta paths "beta/generate": generate, broadcaster, clip, diff --git a/packages/api/src/schema/ai-api-schema.yaml b/packages/api/src/schema/ai-api-schema.yaml index 7dbd0284d..51118934e 100644 --- a/packages/api/src/schema/ai-api-schema.yaml +++ b/packages/api/src/schema/ai-api-schema.yaml @@ -1,6 +1,6 @@ openapi: 3.1.0 paths: - /api/beta/generate/text-to-image: + /api/generate/api/generate/text-to-image: &ref_0 post: tags: - generate @@ -27,7 +27,9 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPError' + - oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' '401': description: Unauthorized @@ -35,7 +37,9 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPError' + - oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' '422': description: Validation Error @@ -43,7 +47,9 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPValidationError' + - oneOf: + - $ref: '#/components/schemas/HTTPValidationError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' '500': description: Internal Server Error @@ -51,16 +57,21 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPError' + - oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' default: description: Error content: application/json: schema: - $ref: '#/components/schemas/studio-api-error' + oneOf: + - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/studio-api-error' x-speakeasy-name-override: textToImage - /api/beta/generate/image-to-image: + /api/generate/api/beta/generate/text-to-image: *ref_0 + /api/generate/api/generate/image-to-image: &ref_1 post: tags: - generate @@ -87,7 +98,9 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPError' + - oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' '401': description: Unauthorized @@ -95,7 +108,9 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPError' + - oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' '422': description: Validation Error @@ -103,7 +118,9 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPValidationError' + - oneOf: + - $ref: '#/components/schemas/HTTPValidationError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' '500': description: Internal Server Error @@ -111,16 +128,21 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPError' + - oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' default: description: Error content: application/json: schema: - $ref: '#/components/schemas/studio-api-error' + oneOf: + - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/studio-api-error' x-speakeasy-name-override: imageToImage - /api/beta/generate/image-to-video: + /api/generate/api/beta/generate/image-to-image: *ref_1 + /api/generate/api/generate/image-to-video: &ref_2 post: tags: - generate @@ -147,7 +169,9 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPError' + - oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' '401': description: Unauthorized @@ -155,7 +179,9 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPError' + - oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' '422': description: Validation Error @@ -163,7 +189,9 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPValidationError' + - oneOf: + - $ref: '#/components/schemas/HTTPValidationError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' '500': description: Internal Server Error @@ -171,16 +199,21 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPError' + - oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' default: description: Error content: application/json: schema: - $ref: '#/components/schemas/studio-api-error' + oneOf: + - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/studio-api-error' x-speakeasy-name-override: imageToVideo - /api/beta/generate/upscale: + /api/generate/api/beta/generate/image-to-video: *ref_2 + /api/generate/api/generate/upscale: &ref_3 post: tags: - generate @@ -207,7 +240,9 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPError' + - oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' '401': description: Unauthorized @@ -215,7 +250,9 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPError' + - oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' '422': description: Validation Error @@ -223,7 +260,9 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPValidationError' + - oneOf: + - $ref: '#/components/schemas/HTTPValidationError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' '500': description: Internal Server Error @@ -231,16 +270,21 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPError' + - oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' default: description: Error content: application/json: schema: - $ref: '#/components/schemas/studio-api-error' + oneOf: + - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/studio-api-error' x-speakeasy-name-override: upscale - /api/beta/generate/audio-to-text: + /api/generate/api/beta/generate/upscale: *ref_3 + /api/generate/api/generate/audio-to-text: &ref_4 post: tags: - generate @@ -267,7 +311,9 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPError' + - oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' '401': description: Unauthorized @@ -275,7 +321,9 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPError' + - oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' '413': description: Request Entity Too Large @@ -283,7 +331,9 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPError' + - oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' '422': description: Validation Error @@ -291,7 +341,9 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPValidationError' + - oneOf: + - $ref: '#/components/schemas/HTTPValidationError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' '500': description: Internal Server Error @@ -299,16 +351,21 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPError' + - oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' default: description: Error content: application/json: schema: - $ref: '#/components/schemas/studio-api-error' + oneOf: + - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/studio-api-error' x-speakeasy-name-override: audioToText - /api/beta/generate/segment-anything-2: + /api/generate/api/beta/generate/audio-to-text: *ref_4 + /api/generate/api/generate/segment-anything-2: &ref_5 post: tags: - generate @@ -335,7 +392,9 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPError' + - oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' '401': description: Unauthorized @@ -343,7 +402,9 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPError' + - oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' '422': description: Validation Error @@ -351,7 +412,9 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPValidationError' + - oneOf: + - $ref: '#/components/schemas/HTTPValidationError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' '500': description: Internal Server Error @@ -359,15 +422,90 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/HTTPError' + - oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' - $ref: '#/components/schemas/studio-api-error' default: description: Error content: application/json: schema: - $ref: '#/components/schemas/studio-api-error' + oneOf: + - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/studio-api-error' x-speakeasy-name-override: segmentAnything2 + /api/generate/api/beta/generate/segment-anything-2: *ref_5 + /api/generate/api/generate/llm: &ref_6 + post: + tags: + - generate + summary: LLM + description: Generate text using a language model. + operationId: genLLM + requestBody: + content: + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Body_genLLM' + required: true + responses: + '200': + description: Successful Response + content: + application/json: + schema: + $ref: '#/components/schemas/LLMResponse' + '400': + description: Bad Request + content: + application/json: + schema: + oneOf: + - oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/studio-api-error' + '401': + description: Unauthorized + content: + application/json: + schema: + oneOf: + - oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/studio-api-error' + '422': + description: Validation Error + content: + application/json: + schema: + oneOf: + - oneOf: + - $ref: '#/components/schemas/HTTPValidationError' + - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/studio-api-error' + '500': + description: Internal Server Error + content: + application/json: + schema: + oneOf: + - oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/studio-api-error' + default: + description: Error + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/studio-api-error' + x-speakeasy-name-override: llm + /api/generate/api/beta/generate/llm: *ref_6 components: schemas: APIError: @@ -414,6 +552,14 @@ components: title: Model Id description: Hugging Face model ID used for image generation. default: timbrooks/instruct-pix2pix + loras: + type: string + title: Loras + description: >- + A LoRA (Low-Rank Adaptation) model and its corresponding weight for + image generation. Example: { "latent-consistency/lcm-lora-sdxl": + 1.0, "nerijs/pixel-art-xl": 1.2}. + default: '' strength: type: number title: Strength @@ -533,6 +679,41 @@ components: - image title: Body_genImageToVideo additionalProperties: false + Body_genLLM: + properties: + prompt: + type: string + title: Prompt + model_id: + type: string + title: Model Id + default: '' + system_msg: + type: string + title: System Msg + default: '' + temperature: + type: number + title: Temperature + default: 0.7 + max_tokens: + type: integer + title: Max Tokens + default: 256 + history: + type: string + title: History + default: '[]' + stream: + type: boolean + title: Stream + default: false + type: object + required: + - prompt + - model_id + title: Body_genLLM + additionalProperties: false Body_genSegmentAnything2: properties: image: @@ -544,7 +725,7 @@ components: type: string title: Model Id description: Hugging Face model ID used for image generation. - default: 'facebook/sam2-hiera-large' + default: facebook/sam2-hiera-large point_coords: type: string title: Point Coords @@ -667,6 +848,19 @@ components: - images title: ImageResponse description: Response model for image generation. + LLMResponse: + properties: + response: + type: string + title: Response + tokens_used: + type: integer + title: Tokens Used + type: object + required: + - response + - tokens_used + title: LLMResponse MasksResponse: properties: masks: @@ -734,6 +928,14 @@ components: title: Model Id description: Hugging Face model ID used for image generation. default: SG161222/RealVisXL_V4.0_Lightning + loras: + type: string + title: Loras + description: >- + A LoRA (Low-Rank Adaptation) model and its corresponding weight for + image generation. Example: { "latent-consistency/lcm-lora-sdxl": + 1.0, "nerijs/pixel-art-xl": 1.2}. + default: '' prompt: type: string title: Prompt diff --git a/packages/api/src/schema/pull-ai-schema.js b/packages/api/src/schema/pull-ai-schema.js index 02645051e..4104e658d 100644 --- a/packages/api/src/schema/pull-ai-schema.js +++ b/packages/api/src/schema/pull-ai-schema.js @@ -60,10 +60,20 @@ const downloadAiSchema = async () => { // add studio-api-error schema schema.components.schemas["studio-api-error"] = studioApiErrorSchema; + // TODO: Remove beta paths + const newPaths = {}; + Object.entries(schema.paths).forEach(([path, value]) => { + const generatePath = `/api/generate${path}`; + const betaGeneratePath = `/api/beta/generate${path}`; + newPaths[generatePath] = value; + newPaths[betaGeneratePath] = value; + }); + schema.paths = newPaths; + // patches to the paths section schema.paths = mapObject(schema.paths, (path, value) => { - // prefix paths with /api/beta/generate - path = `/api/beta/generate${path}`; + // prefix paths with /api/generate + path = `/api/generate${path}`; // remove security field delete value.post.security; // add Studio API error as oneOf to all of the error responses From c7f79852011f998c6f23c293e9bc3359402ede15 Mon Sep 17 00:00:00 2001 From: gioelecerati Date: Tue, 1 Oct 2024 13:09:02 +0200 Subject: [PATCH 2/4] revert broken schema --- packages/api/src/schema/ai-api-schema.yaml | 280 +++------------------ 1 file changed, 39 insertions(+), 241 deletions(-) diff --git a/packages/api/src/schema/ai-api-schema.yaml b/packages/api/src/schema/ai-api-schema.yaml index 51118934e..4acb0c038 100644 --- a/packages/api/src/schema/ai-api-schema.yaml +++ b/packages/api/src/schema/ai-api-schema.yaml @@ -1,6 +1,6 @@ openapi: 3.1.0 paths: - /api/generate/api/generate/text-to-image: &ref_0 + /api/beta/generate/text-to-image: post: tags: - generate @@ -27,9 +27,7 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPError' - $ref: '#/components/schemas/studio-api-error' '401': description: Unauthorized @@ -37,9 +35,7 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPError' - $ref: '#/components/schemas/studio-api-error' '422': description: Validation Error @@ -47,9 +43,7 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPValidationError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPValidationError' - $ref: '#/components/schemas/studio-api-error' '500': description: Internal Server Error @@ -57,21 +51,16 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPError' - $ref: '#/components/schemas/studio-api-error' default: description: Error content: application/json: schema: - oneOf: - - $ref: '#/components/schemas/studio-api-error' - - $ref: '#/components/schemas/studio-api-error' + $ref: '#/components/schemas/studio-api-error' x-speakeasy-name-override: textToImage - /api/generate/api/beta/generate/text-to-image: *ref_0 - /api/generate/api/generate/image-to-image: &ref_1 + /api/beta/generate/image-to-image: post: tags: - generate @@ -98,9 +87,7 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPError' - $ref: '#/components/schemas/studio-api-error' '401': description: Unauthorized @@ -108,9 +95,7 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPError' - $ref: '#/components/schemas/studio-api-error' '422': description: Validation Error @@ -118,9 +103,7 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPValidationError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPValidationError' - $ref: '#/components/schemas/studio-api-error' '500': description: Internal Server Error @@ -128,21 +111,16 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPError' - $ref: '#/components/schemas/studio-api-error' default: description: Error content: application/json: schema: - oneOf: - - $ref: '#/components/schemas/studio-api-error' - - $ref: '#/components/schemas/studio-api-error' + $ref: '#/components/schemas/studio-api-error' x-speakeasy-name-override: imageToImage - /api/generate/api/beta/generate/image-to-image: *ref_1 - /api/generate/api/generate/image-to-video: &ref_2 + /api/beta/generate/image-to-video: post: tags: - generate @@ -169,9 +147,7 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPError' - $ref: '#/components/schemas/studio-api-error' '401': description: Unauthorized @@ -179,9 +155,7 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPError' - $ref: '#/components/schemas/studio-api-error' '422': description: Validation Error @@ -189,9 +163,7 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPValidationError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPValidationError' - $ref: '#/components/schemas/studio-api-error' '500': description: Internal Server Error @@ -199,21 +171,16 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPError' - $ref: '#/components/schemas/studio-api-error' default: description: Error content: application/json: schema: - oneOf: - - $ref: '#/components/schemas/studio-api-error' - - $ref: '#/components/schemas/studio-api-error' + $ref: '#/components/schemas/studio-api-error' x-speakeasy-name-override: imageToVideo - /api/generate/api/beta/generate/image-to-video: *ref_2 - /api/generate/api/generate/upscale: &ref_3 + /api/beta/generate/upscale: post: tags: - generate @@ -240,9 +207,7 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPError' - $ref: '#/components/schemas/studio-api-error' '401': description: Unauthorized @@ -250,9 +215,7 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPError' - $ref: '#/components/schemas/studio-api-error' '422': description: Validation Error @@ -260,9 +223,7 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPValidationError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPValidationError' - $ref: '#/components/schemas/studio-api-error' '500': description: Internal Server Error @@ -270,21 +231,16 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPError' - $ref: '#/components/schemas/studio-api-error' default: description: Error content: application/json: schema: - oneOf: - - $ref: '#/components/schemas/studio-api-error' - - $ref: '#/components/schemas/studio-api-error' + $ref: '#/components/schemas/studio-api-error' x-speakeasy-name-override: upscale - /api/generate/api/beta/generate/upscale: *ref_3 - /api/generate/api/generate/audio-to-text: &ref_4 + /api/beta/generate/audio-to-text: post: tags: - generate @@ -311,9 +267,7 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPError' - $ref: '#/components/schemas/studio-api-error' '401': description: Unauthorized @@ -321,9 +275,7 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPError' - $ref: '#/components/schemas/studio-api-error' '413': description: Request Entity Too Large @@ -331,9 +283,7 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPError' - $ref: '#/components/schemas/studio-api-error' '422': description: Validation Error @@ -341,9 +291,7 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPValidationError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPValidationError' - $ref: '#/components/schemas/studio-api-error' '500': description: Internal Server Error @@ -351,21 +299,16 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPError' - $ref: '#/components/schemas/studio-api-error' default: description: Error content: application/json: schema: - oneOf: - - $ref: '#/components/schemas/studio-api-error' - - $ref: '#/components/schemas/studio-api-error' + $ref: '#/components/schemas/studio-api-error' x-speakeasy-name-override: audioToText - /api/generate/api/beta/generate/audio-to-text: *ref_4 - /api/generate/api/generate/segment-anything-2: &ref_5 + /api/beta/generate/segment-anything-2: post: tags: - generate @@ -392,9 +335,7 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPError' - $ref: '#/components/schemas/studio-api-error' '401': description: Unauthorized @@ -402,9 +343,7 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPError' - $ref: '#/components/schemas/studio-api-error' '422': description: Validation Error @@ -412,9 +351,7 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPValidationError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPValidationError' - $ref: '#/components/schemas/studio-api-error' '500': description: Internal Server Error @@ -422,90 +359,15 @@ paths: application/json: schema: oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPError' - - $ref: '#/components/schemas/studio-api-error' + - $ref: '#/components/schemas/HTTPError' - $ref: '#/components/schemas/studio-api-error' default: description: Error content: application/json: schema: - oneOf: - - $ref: '#/components/schemas/studio-api-error' - - $ref: '#/components/schemas/studio-api-error' + $ref: '#/components/schemas/studio-api-error' x-speakeasy-name-override: segmentAnything2 - /api/generate/api/beta/generate/segment-anything-2: *ref_5 - /api/generate/api/generate/llm: &ref_6 - post: - tags: - - generate - summary: LLM - description: Generate text using a language model. - operationId: genLLM - requestBody: - content: - application/x-www-form-urlencoded: - schema: - $ref: '#/components/schemas/Body_genLLM' - required: true - responses: - '200': - description: Successful Response - content: - application/json: - schema: - $ref: '#/components/schemas/LLMResponse' - '400': - description: Bad Request - content: - application/json: - schema: - oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPError' - - $ref: '#/components/schemas/studio-api-error' - - $ref: '#/components/schemas/studio-api-error' - '401': - description: Unauthorized - content: - application/json: - schema: - oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPError' - - $ref: '#/components/schemas/studio-api-error' - - $ref: '#/components/schemas/studio-api-error' - '422': - description: Validation Error - content: - application/json: - schema: - oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPValidationError' - - $ref: '#/components/schemas/studio-api-error' - - $ref: '#/components/schemas/studio-api-error' - '500': - description: Internal Server Error - content: - application/json: - schema: - oneOf: - - oneOf: - - $ref: '#/components/schemas/HTTPError' - - $ref: '#/components/schemas/studio-api-error' - - $ref: '#/components/schemas/studio-api-error' - default: - description: Error - content: - application/json: - schema: - oneOf: - - $ref: '#/components/schemas/studio-api-error' - - $ref: '#/components/schemas/studio-api-error' - x-speakeasy-name-override: llm - /api/generate/api/beta/generate/llm: *ref_6 components: schemas: APIError: @@ -552,14 +414,6 @@ components: title: Model Id description: Hugging Face model ID used for image generation. default: timbrooks/instruct-pix2pix - loras: - type: string - title: Loras - description: >- - A LoRA (Low-Rank Adaptation) model and its corresponding weight for - image generation. Example: { "latent-consistency/lcm-lora-sdxl": - 1.0, "nerijs/pixel-art-xl": 1.2}. - default: '' strength: type: number title: Strength @@ -679,41 +533,6 @@ components: - image title: Body_genImageToVideo additionalProperties: false - Body_genLLM: - properties: - prompt: - type: string - title: Prompt - model_id: - type: string - title: Model Id - default: '' - system_msg: - type: string - title: System Msg - default: '' - temperature: - type: number - title: Temperature - default: 0.7 - max_tokens: - type: integer - title: Max Tokens - default: 256 - history: - type: string - title: History - default: '[]' - stream: - type: boolean - title: Stream - default: false - type: object - required: - - prompt - - model_id - title: Body_genLLM - additionalProperties: false Body_genSegmentAnything2: properties: image: @@ -725,7 +544,7 @@ components: type: string title: Model Id description: Hugging Face model ID used for image generation. - default: facebook/sam2-hiera-large + default: 'facebook/sam2-hiera-large' point_coords: type: string title: Point Coords @@ -848,19 +667,6 @@ components: - images title: ImageResponse description: Response model for image generation. - LLMResponse: - properties: - response: - type: string - title: Response - tokens_used: - type: integer - title: Tokens Used - type: object - required: - - response - - tokens_used - title: LLMResponse MasksResponse: properties: masks: @@ -928,14 +734,6 @@ components: title: Model Id description: Hugging Face model ID used for image generation. default: SG161222/RealVisXL_V4.0_Lightning - loras: - type: string - title: Loras - description: >- - A LoRA (Low-Rank Adaptation) model and its corresponding weight for - image generation. Example: { "latent-consistency/lcm-lora-sdxl": - 1.0, "nerijs/pixel-art-xl": 1.2}. - default: '' prompt: type: string title: Prompt @@ -1056,4 +854,4 @@ components: securitySchemes: HTTPBearer: type: http - scheme: bearer + scheme: bearer \ No newline at end of file From 58e4bc3304027594c570a78b7fc84cbf880b29bc Mon Sep 17 00:00:00 2001 From: gioelecerati Date: Tue, 1 Oct 2024 13:10:41 +0200 Subject: [PATCH 3/4] remove beta path from schema --- packages/api/src/schema/ai-api-schema.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/api/src/schema/ai-api-schema.yaml b/packages/api/src/schema/ai-api-schema.yaml index 4acb0c038..86dccac93 100644 --- a/packages/api/src/schema/ai-api-schema.yaml +++ b/packages/api/src/schema/ai-api-schema.yaml @@ -1,6 +1,6 @@ openapi: 3.1.0 paths: - /api/beta/generate/text-to-image: + /api/generate/text-to-image: post: tags: - generate @@ -60,7 +60,7 @@ paths: schema: $ref: '#/components/schemas/studio-api-error' x-speakeasy-name-override: textToImage - /api/beta/generate/image-to-image: + /api/generate/image-to-image: post: tags: - generate @@ -120,7 +120,7 @@ paths: schema: $ref: '#/components/schemas/studio-api-error' x-speakeasy-name-override: imageToImage - /api/beta/generate/image-to-video: + /api/generate/image-to-video: post: tags: - generate @@ -180,7 +180,7 @@ paths: schema: $ref: '#/components/schemas/studio-api-error' x-speakeasy-name-override: imageToVideo - /api/beta/generate/upscale: + /api/generate/upscale: post: tags: - generate @@ -240,7 +240,7 @@ paths: schema: $ref: '#/components/schemas/studio-api-error' x-speakeasy-name-override: upscale - /api/beta/generate/audio-to-text: + /api/generate/audio-to-text: post: tags: - generate @@ -308,7 +308,7 @@ paths: schema: $ref: '#/components/schemas/studio-api-error' x-speakeasy-name-override: audioToText - /api/beta/generate/segment-anything-2: + /api/generate/segment-anything-2: post: tags: - generate From 62fb683daee0c7d6a135718654768e671bb7c653 Mon Sep 17 00:00:00 2001 From: gioelecerati Date: Wed, 2 Oct 2024 16:04:14 +0200 Subject: [PATCH 4/4] generate schema & remove unused middleware --- packages/api/src/controllers/generate.ts | 8 -- packages/api/src/schema/ai-api-schema.yaml | 127 ++++++++++++++++++++- packages/api/src/schema/pull-ai-schema.js | 10 -- 3 files changed, 125 insertions(+), 20 deletions(-) diff --git a/packages/api/src/controllers/generate.ts b/packages/api/src/controllers/generate.ts index 7d7a29da7..3016e14b2 100644 --- a/packages/api/src/controllers/generate.ts +++ b/packages/api/src/controllers/generate.ts @@ -35,14 +35,6 @@ const aiGenerateDurationMetric = new promclient.Histogram({ const app = Router(); -// TODO: Remove beta paths middleware -app.use((req, res, next) => { - if (req.path.startsWith("/beta/generate")) { - req.url = req.url.replace("/beta/generate", "/generate"); - } - next(); -}); - const rateLimiter: RequestHandler = async (req, res, next) => { const now = Date.now(); const [[{ count, min }]] = await db.aiGenerateLog.find( diff --git a/packages/api/src/schema/ai-api-schema.yaml b/packages/api/src/schema/ai-api-schema.yaml index 86dccac93..fd3f90288 100644 --- a/packages/api/src/schema/ai-api-schema.yaml +++ b/packages/api/src/schema/ai-api-schema.yaml @@ -368,6 +368,65 @@ paths: schema: $ref: '#/components/schemas/studio-api-error' x-speakeasy-name-override: segmentAnything2 + /api/generate/llm: + post: + tags: + - generate + summary: LLM + description: Generate text using a language model. + operationId: genLLM + requestBody: + content: + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/Body_genLLM' + required: true + responses: + '200': + description: Successful Response + content: + application/json: + schema: + $ref: '#/components/schemas/LLMResponse' + '400': + description: Bad Request + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' + '401': + description: Unauthorized + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' + '422': + description: Validation Error + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/HTTPValidationError' + - $ref: '#/components/schemas/studio-api-error' + '500': + description: Internal Server Error + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/HTTPError' + - $ref: '#/components/schemas/studio-api-error' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/studio-api-error' + x-speakeasy-name-override: llm components: schemas: APIError: @@ -414,6 +473,14 @@ components: title: Model Id description: Hugging Face model ID used for image generation. default: timbrooks/instruct-pix2pix + loras: + type: string + title: Loras + description: >- + A LoRA (Low-Rank Adaptation) model and its corresponding weight for + image generation. Example: { "latent-consistency/lcm-lora-sdxl": + 1.0, "nerijs/pixel-art-xl": 1.2}. + default: '' strength: type: number title: Strength @@ -533,6 +600,41 @@ components: - image title: Body_genImageToVideo additionalProperties: false + Body_genLLM: + properties: + prompt: + type: string + title: Prompt + model_id: + type: string + title: Model Id + default: '' + system_msg: + type: string + title: System Msg + default: '' + temperature: + type: number + title: Temperature + default: 0.7 + max_tokens: + type: integer + title: Max Tokens + default: 256 + history: + type: string + title: History + default: '[]' + stream: + type: boolean + title: Stream + default: false + type: object + required: + - prompt + - model_id + title: Body_genLLM + additionalProperties: false Body_genSegmentAnything2: properties: image: @@ -544,7 +646,7 @@ components: type: string title: Model Id description: Hugging Face model ID used for image generation. - default: 'facebook/sam2-hiera-large' + default: facebook/sam2-hiera-large point_coords: type: string title: Point Coords @@ -667,6 +769,19 @@ components: - images title: ImageResponse description: Response model for image generation. + LLMResponse: + properties: + response: + type: string + title: Response + tokens_used: + type: integer + title: Tokens Used + type: object + required: + - response + - tokens_used + title: LLMResponse MasksResponse: properties: masks: @@ -734,6 +849,14 @@ components: title: Model Id description: Hugging Face model ID used for image generation. default: SG161222/RealVisXL_V4.0_Lightning + loras: + type: string + title: Loras + description: >- + A LoRA (Low-Rank Adaptation) model and its corresponding weight for + image generation. Example: { "latent-consistency/lcm-lora-sdxl": + 1.0, "nerijs/pixel-art-xl": 1.2}. + default: '' prompt: type: string title: Prompt @@ -854,4 +977,4 @@ components: securitySchemes: HTTPBearer: type: http - scheme: bearer \ No newline at end of file + scheme: bearer diff --git a/packages/api/src/schema/pull-ai-schema.js b/packages/api/src/schema/pull-ai-schema.js index 4104e658d..9b95937ef 100644 --- a/packages/api/src/schema/pull-ai-schema.js +++ b/packages/api/src/schema/pull-ai-schema.js @@ -60,16 +60,6 @@ const downloadAiSchema = async () => { // add studio-api-error schema schema.components.schemas["studio-api-error"] = studioApiErrorSchema; - // TODO: Remove beta paths - const newPaths = {}; - Object.entries(schema.paths).forEach(([path, value]) => { - const generatePath = `/api/generate${path}`; - const betaGeneratePath = `/api/beta/generate${path}`; - newPaths[generatePath] = value; - newPaths[betaGeneratePath] = value; - }); - schema.paths = newPaths; - // patches to the paths section schema.paths = mapObject(schema.paths, (path, value) => { // prefix paths with /api/generate