sourcegraph/internal/openapi/api/openapi.yaml
Ólafur Páll Geirsson 1b1229c867
feat/API: implement /models and /models/{modelId} using TypeSpec (#64421)
Fixes CODY-3085
Fixes CODY-3086

Previously, there was no way for OpenAI clients to list the available
models on Sourcegraph or query metadata about a given model ID ("model
ref" using our internal terminology). This PR fixes that problem AND
additionally adds infrastructure to auto-generate Go models from a
TypeSpec specification.

[TypeSpec](https://typespec.io/) is an IDL to document REST APIs,
created by Microsoft. Historically, the Go code in this repository has
been the single source of truth about what exact JSON structures are
expected in HTTP request/response pairs in our REST endpoints. This new
TypeSpec infrastructure allows us to document these shapes at a higher
abstraction level, which has several benefits including automatic
OpenAPI generation, which we can use to generate docs on
sourcegraph.com/docs or automatically generate client bindings in
TypeScript (among many other use-cases).

I am planning to write an RFC to propose we start using TypeSpec for new
REST endpoints going forward. If the RFC is not approved then we can
just delete the new `tools/typespec_codegen` directory and keep the
generated code in the repo. It won't be a big difference in the end
compared our current manual approach of writing Go structs for HTTP
APIs.

<!-- PR description tips:
https://www.notion.so/sourcegraph/Write-a-good-pull-request-description-610a7fd3e613496eb76f450db5a49b6e
-->

## Test plan
See test cases. I additionally wrote a basic python script with the
official OpenAI client to test that it works with this endpoint. First,
I ran `sg start minimal`. Then I wrote this script
```py
import os
from openai import OpenAI
from dotenv import load_dotenv
import httpx

load_dotenv()

openai = OpenAI(
    # base_url="https://api.openai.com/v1",
    # api_key=os.getenv("OPENAI_API_KEY"),
    base_url="https://sourcegraph.test:3443/api/v1",
    api_key=os.getenv("SRC_ACCESS_TOKEN"),
    http_client=httpx.Client(verify=False)
)

def main():
    response = openai.models.list()
    for model in response.data:
        print(model.id)
if __name__ == "__main__":
    main()

```
Finally, I ran 
```
❯ python3 models.py
anthropic::unknown::claude-3-haiku-20240307
anthropic::unknown::claude-3-sonnet-20240229
fireworks::unknown::starcoder
```
<!-- REQUIRED; info at
https://docs-legacy.sourcegraph.com/dev/background-information/testing_principles
-->

## Changelog

* New `GET /.api/llm/models` and `GET /.api/llm/models/{modelId}` REST
API endpoints to list available LLM models on the instance and to get
information about a given model. This endpoints is compatible with the
`/models` and `/models/{modelId}` endpoints from OpenAI.

<!-- OPTIONAL; info at
https://www.notion.so/sourcegraph/Writing-a-changelog-entry-dd997f411d524caabf0d8d38a24a878c
-->
2024-08-14 10:47:00 +00:00

124 lines
3.1 KiB
YAML

# Code generated by OpenAPI Generator - DO NOT EDIT
openapi: 3.0.0
info:
title: Cody Service
version: 0.0.0
servers:
- url: /
paths:
/models:
get:
operationId: Models_list
parameters: []
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/ListModelsResponse'
description: The request has succeeded.
default:
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: An unexpected error response.
summary: "Lists the currently available models, and provides basic information\
\ about each one such as the owner and availability."
/models/{modelId}:
get:
operationId: Models_retrieveModel
parameters:
- explode: false
in: path
name: modelId
required: true
schema:
type: string
style: simple
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/Model'
description: The request has succeeded.
default:
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: An unexpected error response.
summary: "Retrieves a model instance, providing basic information about the\
\ model such as the owner and permissioning."
components:
schemas:
Error:
example:
code: 6
message: message
properties:
code:
format: int32
type: integer
message:
type: string
required:
- code
- message
type: object
ListModelsResponse:
example:
data:
- created: 0
owned_by: owned_by
id: id
object: model
- created: 0
owned_by: owned_by
id: id
object: model
object: list
properties:
object:
enum:
- list
type: string
data:
items:
$ref: '#/components/schemas/Model'
type: array
required:
- data
- object
type: object
Model:
description: Describes an OpenAI model offering that can be used with the API.
example:
created: 0
owned_by: owned_by
id: id
object: model
properties:
id:
description: 'The model identifier, which can be referenced in the API endpoints.'
type: string
object:
description: 'The object type, which is always "model".'
enum:
- model
type: string
created:
description: The Unix timestamp (in seconds) when the model was created.
format: int64
type: integer
owned_by:
description: The organization that owns the model.
type: string
required:
- created
- id
- object
- owned_by
type: object