Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gateway OpenAPI schema live documentation #614

Merged
merged 1 commit into from
Dec 20, 2024

Conversation

neoxelox
Copy link
Contributor

@neoxelox neoxelox commented Nov 14, 2024

What?

Implement OpenAPI + Swagger UI for Latitude gateway API endpoints

image

Issue

#499

TODO

  • Do prove of concept with /run api v2 βœ…
  • Move evaluate tests to new folder πŸ‘ˆ I'm here
  • Consider if some schemas in core should go in gateway
  • Migrate all api routes to use OpenAPI interface
  • πŸ”₯ @hono/zod-validator

@neoxelox neoxelox added the 🚧 wip Work in progress label Nov 14, 2024
@andresgutgon andresgutgon force-pushed the feature/499-automatic-gateway-api-docs branch 2 times, most recently from e2833ce to 3712dd3 Compare December 19, 2024 16:04
@andresgutgon andresgutgon removed the 🚧 wip Work in progress label Dec 20, 2024
@andresgutgon andresgutgon force-pushed the feature/499-automatic-gateway-api-docs branch from d355868 to ea138b3 Compare December 20, 2024 09:46
import { chainEventPresenter } from '$/common/documents/getData'

// @ts-expect-error: streamSSE has type issues
export const chatHandler: AppRouteHandler<ChatRoute> = async (c) => {
Copy link
Contributor

@andresgutgon andresgutgon Dec 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason types are not working at this level. cc @neoxelox . Not only in SSE endpoints, in any of then. No big deal tho

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mmm that's probably why I did what I did, handlers + route def altogether... this types are magical... but if c.req.valid does complain when getting unknown parameters from the request schema... I guess I am okay with that

export const getRouteV2 = getRouteFactory({
path: ROUTES.v2.documents.get,
tags: ['Documents'],
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this abstraction in place reusing routes is as easy as changing the path if the implementation didn't change

@andresgutgon andresgutgon force-pushed the feature/499-automatic-gateway-api-docs branch from ea138b3 to acffc2c Compare December 20, 2024 10:00
@andresgutgon andresgutgon force-pushed the feature/499-automatic-gateway-api-docs branch from acffc2c to c9ce2f8 Compare December 20, 2024 10:05
@andresgutgon andresgutgon changed the title Gateway OpenAPI schema Gateway OpenAPI schema live documentation Dec 20, 2024

import { swaggerUI } from '@hono/swagger-ui'

import packageJson from '../../package.json'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol

import { OpenAPIHono } from '@hono/zod-openapi'

export function createRouter() {
return new OpenAPIHono({ strict: false })
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does strict mean in there?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

})

export const configSchema = z.object({}).passthrough()
export const providerLogSchema = z.object({}).passthrough()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no schema for provider log?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has not really been used in the API afaik

@@ -122,3 +74,45 @@ async function validatedEvalConnectedToDocument({
throw new BadRequestError('The evaluation is not connected to this prompt')
}
}

// @ts-expect-error: streamSSE has type issues
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the type issue really because of streamSSE? I think it is because we are separating the handler from the magical createRoute, I would put that in the comment instead of streamSSE? (Also this handler does nothing about SSEs)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah there's no sse herem, why are we escaping the type checking?

@@ -18,7 +18,7 @@ describe('GET documents', () => {
describe('unauthorized', () => {
it('fails', async () => {
const res = await app.request(
'/api/v1/projects/1/versions/asldkfjhsadl/documents/path/to/document',
'/api/v2/projects/1/versions/asldkfjhsadl/documents/path/to/document',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why the change from v1 to v2?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before the implementation was in v1. So the test. Now I moved the implementation to v2, so the test

Copy link
Contributor Author

@neoxelox neoxelox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Buena currada refactorizando todo! The only thing I would say it to check out the comments saying "Types not working because of SSEs", I don't think its that. I think it is because we are separating the handler from the magical createRoute, I would put that in the comment instead?

app.route('/', v1Routes)
app.route('/', documents)
app.route('/', conversations)
app.route('/', telemetry)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm this is very painful for the reader no? now there's no easy way to know what routes we are exposing you'd have to check every router

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I would have like is something similar to rails where routes.rb declares all the routes and routers are just the controllers with the handlers for each endpoint in that route

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can see all the routes in one place in routes.ts. Here are the paths

image

@@ -118,7 +118,12 @@ describe('POST /chat', () => {
messages: [
{
role: MessageRole.user,
content: 'fake-user-content',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm this should be valid content

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not according to this schema
https://github.com/latitude-dev/latitude-llm/blob/main/packages/core/src/constants.ts#L226-L243

This started failing now because before we did this "truquito"

import { messageSchema } from '@latitude-data/core/browser'
const messagesSchema = z.array(z.any(messageSchema))

☝️ This is using any

What I did was remove the any

const messagesSchema = z.array(messageSchema)

And now types works!

image

import { CreateLogRoute } from '$/routes/v2/documents/logs/create.route'
import { getData } from '$/common/documents/getData'

// @ts-expect-error: broken types
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i mean could we fix types πŸ˜… it looks like this PR is breaking all types

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before we were not using openapi so no old types broken. Just this

AppRouteHandler<CreateLogRoute>

And is because it does a complex generic black magic. But types inside the handlers all work nicely

@andresgutgon andresgutgon merged commit 3d0b277 into main Dec 20, 2024
3 checks passed
@andresgutgon andresgutgon deleted the feature/499-automatic-gateway-api-docs branch December 20, 2024 14:42
@github-actions github-actions bot locked and limited conversation to collaborators Dec 20, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

3 participants