winglang / wing

A programming language for the cloud ☁️ A unified programming model, combining infrastructure and runtime code into one language ⚡
https://winglang.io
Other
4.8k stars 189 forks source link

`bring openapi` #2024

Open eladb opened 1 year ago

eladb commented 1 year ago

Feature Spec

The bring api statement can be used to obtain a strongly-typed client for making requests to OpenAPI endpoints without needing a dedicated library.

As a cloud-oriented language, Wing has built-in support for OpenAPI. For example, when creating a cloud.Api resource, it will automatically generate an OpenAPI specification for your endpoints.

Similarly, Wing can seamlessly interact with any service that has an OpenAPI specification by automatically generating a strongly-typed client for it.

Let's look at an example. Say we want to interact with OpenAI.

First, we need to download the OpenAPI spec from the OpenAI repository:

curl -o openai.yaml https://raw.githubusercontent.com/openai/openai-openapi/master/openapi.yaml

Now, we can simply bring it into our Wing code:

bring api "./openai.yaml" as openai;

new cloud.Function(inflight () => {
  let client = new openai.Client(headers: {
    authorization: "Bearer ${env.OPENAI_API_KEY}"
  });

  let response = client.completions.post(
    model: "text-davinci-003",
    prompt: "Correct this to standard English:\n\nShe no went to the market.",
    temperature: 0,
    max_tokens: 60,
    top_p: 1.0,
    frequency_penalty: 0.0,
    presence_penalty: 0.0
  );

  let first = response.choices.at(0);
  print(first.text);
});

Under the hood, the Wing compiler will generate the following types:

struct CreateCompletionRequest {
  /** 
   * ID of the model to use. You can use the [List models](/docs/api-reference/models/list) 
   * API to see all of your available models, or see our [Model overview]
   * (/docs/models/overview) for descriptions of them.
   */
  model: str;

  /**
   * The prompt(s) to generate completions for, encoded as a string, array of strings, 
   * array of tokens, or array of token arrays.
   * 
   * Note that <|endoftext|> is the document separator that the model sees during training, so 
   * if a prompt is not specified the model will generate as if from the beginning of a new 
   * document.
   *
   * @example "This is a test."
   * @default "<|endoftext|>"
   */
  prompt: str?; // see https://github.com/winglang/wing/issues/2023

  /**
   * The suffix that comes after a completion of inserted text.
   * 
   * @example "test."
   */  
  suffix: str?;

  /**
   * The maximum number of [tokens](/tokenizer) to generate in the completion.
   * 
   * The token count of your prompt plus `max_tokens` cannot exceed the model's context
   * length. Most models have a context length of 2048 tokens (except for the newest models,
   * which support 4096).
   * 
   * @minimum 0
   * @default 16
   * @example 16
   */
  max_tokens: num?;

  // ...
}

struct CreateCompletionResponseChoicesItem {
  text: str;
  index: num;
  finish_reason: str;

  // ...
}

struct CreateCompletionResponse {
  id: str;
  object: str;
  created: num;
  model: str;
  choices: Array<CreateCompletionResponseChoicesItem>;

  // ...
}

inflight post(req: CreateCompletionRequest): CreateCompletionResponse;

Use Cases

The cloud is an API-driven machine. OpenAPI is becoming the de-facto standard for describing these APIs. Being able to natively use any OpenAPI-based service in Wing is a natural capability of a cloud-oriented language.

Implementation Notes

This is a current limitation of structs that can cause trouble with certain APIs: https://github.com/winglang/wing/issues/2023

For example, the prompt field in the OpenAI API is modeled like this:

oneOf:
  - type: string
    default: ''
    example: "This is a test."
  - type: array
    items:
      type: string
      default: ''
      example: "This is a test."
  - type: array
    minItems: 1
    items:
      type: integer
    example: "[1212, 318, 257, 1332, 13]"
  - type: array
    minItems: 1
    items:
      type: array
      minItems: 1
      items:
        type: integer
    example: "[[1212, 318, 257, 1332, 13]]"

In the above example, we've just selected the first schema (string), but ideally I'd want a way to use any of these formats.

Component

Language Design, Compiler, SDK

Community Note

Please vote by adding a 👍 reaction to the issue to help us prioritize. If you are interested to work on this issue, please leave a comment.

staycoolcall911 commented 1 year ago

Very cool idea! P2 for now

github-actions[bot] commented 1 year ago

Hi,

This issue hasn't seen activity in 60 days. Therefore, we are marking this issue as stale for now. It will be closed after 7 days. Feel free to re-open this issue when there's an update or relevant information to be added. Thanks!

github-actions[bot] commented 3 months ago

Hi,

This issue hasn't seen activity in 90 days. Therefore, we are marking this issue as stale for now. It will be closed after 7 days. Feel free to re-open this issue when there's an update or relevant information to be added. Thanks!