Skip to content

feat: use an OpenAPI definition as a tool file #195

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

Merged
merged 16 commits into from
Mar 29, 2024

Conversation

g-linville
Copy link
Member

@g-linville g-linville commented Mar 28, 2024

This adds the ability to use an OpenAPI definition file as though it were a GPTScript tool file. gptscript will now attempt to parse any .json, .yaml, or .yml files as OpenAPI definitions, and if it gets an error while doing that, only then will it attempt to treat it as a standard gptscript file. (Files ending in any other extension are just treated as standard scripts and not checked for OpenAPI definitions.)

When parsing the file, gptscript creates an in-memory tool definition for each operation (path + HTTP method) defined in the file. It also creates one top-level tool that exports all the rest. Each tool's name matches the corresponding operation's operationId. Each tool's instructions (the bit after the preamble, where you would ordinarily prompt the model or run a command) starts with the unique sequence #!sys.openapi, followed by a JSON string with information about the operation. This tells gptscript's tool runner to handle this tool uniquely. The code that runs the tool will unmarshal the JSON and use the instructions to set up and do the HTTP request, print the body, and exit.

The typical use case for this would be to hand an OpenAPI definition to GPTScript and ask the model to just perform a series of tasks, and let it choose which operations it needs to use. It is still possible to restrict which tools you give it using the toolName from file.yaml syntax.

For more details on how to use this, see the doc that I added in this PR.

Comment on lines 6 to 14
Description string `json:"description,omitempty"`
Type string `json:"type,omitempty"`
Ref string `json:"$ref,omitempty"`
Items *JSONSchema `json:"items,omitempty"`
Enum []string `json:"enum,omitempty"`

ID string `json:"$id,omitempty"`
Title string `json:"title,omitempty"`
Properties map[string]Property `json:"properties"`
Properties map[string]JSONSchema `json:"properties"`
Copy link
Member Author

@g-linville g-linville Mar 28, 2024

Choose a reason for hiding this comment

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

These are some fixes that I made to the JSONSchema type. There was no need to have a separate Property struct.

@g-linville g-linville marked this pull request as ready for review March 28, 2024 18:54
// Check for a bearer token (only if using HTTPS)
if u.Scheme == "https" {
// For "https://example.com" the bearer token env name would be GPTSCRIPT_EXAMPLE_COM_BEARER_TOKEN
bearerEnv := "GPTSCRIPT_" + strings.ToUpper(strings.Replace(u.Host, ".", "_", -1)) + "_BEARER_TOKEN"
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you want u.Hostname() so that you don't get the port part if there is a port, like :8443

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for finding that!

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed

if err != nil {
return types.Tool{}, err
var tools []types.Tool
if strings.HasSuffix(base.Name, ".json") ||
Copy link
Contributor

Choose a reason for hiding this comment

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

We should detect if the data is openapi format by inspecting the data itself and not by file extension. That should be more flexible in the future. I also don't want something where the openai schema is hosted at path like "https://example.com/openapi" and it not working becaues it doesn't end with the extension.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed

// Check for a bearer token (only if using HTTPS)
if u.Scheme == "https" {
// For "https://example.com" the bearer token env name would be GPTSCRIPT_EXAMPLE_COM_BEARER_TOKEN
bearerEnv := "GPTSCRIPT_" + strings.ToUpper(strings.Replace(u.Hostname(), ".", "_", -1)) + "_BEARER_TOKEN"
Copy link
Contributor

Choose a reason for hiding this comment

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

There's a function somewhere ToEnvLike. Can you use that. It's handles - -> _ also which tends to break env vars also.

Copy link
Member Author

Choose a reason for hiding this comment

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

@ibuildthecloud that function doesn't replace . with _. Should I modify it to do that also?

Copy link
Member Author

Choose a reason for hiding this comment

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

Nvm, I hadn't updated my local branch on main yet. Fixed.

Signed-off-by: Grant Linville <[email protected]>
Signed-off-by: Grant Linville <[email protected]>
Signed-off-by: Grant Linville <[email protected]>
Signed-off-by: Grant Linville <[email protected]>
Signed-off-by: Grant Linville <[email protected]>
Signed-off-by: Grant Linville <[email protected]>
Signed-off-by: Grant Linville <[email protected]>
Signed-off-by: Grant Linville <[email protected]>
Signed-off-by: Grant Linville <[email protected]>
Signed-off-by: Grant Linville <[email protected]>
Signed-off-by: Grant Linville <[email protected]>
@g-linville g-linville merged commit 6c26410 into gptscript-ai:main Mar 29, 2024
@g-linville g-linville deleted the openapi-tools branch March 29, 2024 19:22
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.

2 participants