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

Add JSON program generation, validation, and evaluation in core module #20

Merged
merged 7 commits into from
Jul 17, 2023

Conversation

ahejlsberg
Copy link
Member

@ahejlsberg ahejlsberg commented Jul 16, 2023

This PR adds support for generation, validation, and evaluation of simple programs targeting a specified API. Programs consist of a sequence of calls to functions of the specified API with arguments that are a combination of JSON values and results from preceding program steps. Programs are are represented as JSON using the following schema:

// A program consists of a sequence of expressions that are evaluated in order.
export type Program = {
    "@steps": Expression[];
}

// An expression is a JSON value, a function call, or a reference to the result of a preceding expression.
export type Expression = JsonValue | FunctionCall | ResultReference;

// A JSON value is a string, a number, a boolean, null, an object, or an array. Function calls and result
// references can be nested in objects and arrays.
export type JsonValue = string | number | boolean | null | { [x: string]: Expression } | Expression[];

// A function call specifices a function name and a list of argument expressions. Arguments may contain
// nested function calls and result references.
export type FunctionCall = {
    // Name of the function
    "@func": string;
    // Arguments for the function
    "@args": Expression[];
};

// A result reference represents the value of an expression from a preceding step.
export type ResultReference = {
    // Index of the previous expression in the "@steps" array
    "@ref": number;
};

For example, given a music service API with functions getRecentlyPlayed, filterTracks, and createPlaylist, the user request "get my favorite 50 tracks from last year and make the non-classical ones into a playlist" might be represented as the following Program instance:

{
    "@steps": [
        {
            "@func": "getRecentlyPlayed",
            "@args": [{ "favoritesTerm": "long_term", "count": 50 }]
        },
        {
            "@func": "filterTracks",
            "@args": [{ "@ref": 0 }, { "filter": "genre:classical", "negate": true }]
        },
        {
            "@func": "createPlaylist",
            "@args": [{ "@ref": 1 }, "Non-Classical Favorites" ]
        }
    ]
}

The createProgramTranslator function introduced in this PR creates an object that can translate natural language requests into such programs. The translate method of the object combines the Program schema, a specified API schema, and a user request into a prompt that directs the LLM to generate a JSON program. The resulting program can be safely evaluated using the evaluateJsonProgram function, which implements a simple interpreter. Calls to API functions in the program are passed to an onCall callback function for validation and dispatch. Thus, unlike JavaScript's eval, access to external functionality and resources is entirely controlled by the host application.

@steveluc
Copy link
Contributor

Great to see. Looks good. Shall we remove the programs example since it matches the music one at this point?

@ahejlsberg
Copy link
Member Author

Yes, I'll put up a separate PR to remove examples/programs.

@ahejlsberg ahejlsberg merged commit ae6a984 into main Jul 17, 2023
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants