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

Generate chart yaml using AI #4323

Merged
merged 22 commits into from
Mar 25, 2024
Merged

Conversation

AdityaHegde
Copy link
Collaborator

@AdityaHegde AdityaHegde commented Mar 12, 2024

  • Endpoint to send prompt to chatgpt.
  • Parse chatgpt response and generate the yaml (happens in the UI right now).
  • Hook up a menu item to chart to generate the vega lite chart spec.
  • Support generating a chart directly from a table/model.
  • Support generating a chart directly from a metrics view.

These will have a follow up PR

  • Prompt tuning.

@AdityaHegde AdityaHegde force-pushed the adityahegde/custom-chart-using-ai branch from 74af5f5 to e32e9a3 Compare March 13, 2024 07:56
@AdityaHegde AdityaHegde marked this pull request as ready for review March 13, 2024 15:31
runtime/resolver.go Outdated Show resolved Hide resolved
runtime/server/generate_chart.go Show resolved Hide resolved
proto/rill/runtime/v1/api.proto Outdated Show resolved Hide resolved
Comment on lines +154 to +155
Replace the data field in vega lite json with,
{ "name": "table" }
Copy link
Contributor

Choose a reason for hiding this comment

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

With metrics view generation, it seemed that less fixed rule were better. So maybe consider saying "don't add a 'data' field". And then just add this programmatically afterwards.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

One thing I am seeing is chatgpt does a good job of giving proper indentation. Parsing, updating and reformatting will lose this. So probably it might be good to keep it as is.

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay, you can keep if you want. But note that Go's JSON encoder is able to output indented JSON.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

While true, I dont think any library can do partial indentation like,

 {
    "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
    "data": { "name": "table" },
    "mark": "arc",
    "encoding": {
      "theta": {"field": "total_records", "type": "quantitative"},
      "color": {"field": "publisher", "type": "nominal"}
    },
    "width": 300,
    "height": 300
  }

Copy link
Contributor

Choose a reason for hiding this comment

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

That's probably true :) Makes sense

runtime/server/generate_chart.go Outdated Show resolved Hide resolved
runtime/server/generate_chart.go Outdated Show resolved Hide resolved
@AdityaHegde AdityaHegde force-pushed the adityahegde/custom-chart-using-ai branch from b2bb265 to a4d5fdc Compare March 14, 2024 12:51
@AdityaHegde AdityaHegde force-pushed the adityahegde/custom-chart-using-ai branch from d0e92c6 to 024e3a0 Compare March 15, 2024 05:47
@AdityaHegde AdityaHegde force-pushed the adityahegde/custom-chart-using-ai branch from d3fdec9 to 8a0f5a8 Compare March 15, 2024 10:36
Comment on lines 123 to 135
rpc GenerateResolver(GenerateResolverRequest) returns (GenerateResolverResponse) {
option (google.api.http) = {
post: "/v1/instances/{instance_id}/files/generate-resolver",
body: "*"
};
}

rpc GenerateChartSpec(GenerateChartSpecRequest) returns (GenerateChartSpecResponse) {
option (google.api.http) = {
post: "/v1/instances/{instance_id}/files/generate-chart",
body: "*"
};
}
Copy link
Contributor

Choose a reason for hiding this comment

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

  1. Add a docstring for each API (can be short, like for the other APIs) :)
  2. Since these endpoints don't generate files, they shouldn't use the /files/ path. For consistency between all the generator APIs, you might also consider refactoring GenerateMetricsViewFile to GenerateMetricsView and have the frontend write the file.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

for 2 will raise a separate PR to refactor GenerateMetricsViewFile. This PR is already getting large.

Comment on lines 518 to 519
string table = 3;
string connector = 4;
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: define connector before table – that's the order in all other protos with these two props

string prompt = 2;
string table = 3;
string connector = 4;
string metrics_view = 5;
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe add a comment that if this is set, both connector and table should be empty

@@ -86,7 +95,7 @@ type ResolveOptions struct {
}

// Resolve resolves a query using the given options.
func (r *Runtime) Resolve(ctx context.Context, opts *ResolveOptions) ([]byte, error) {
func (r *Runtime) Resolve(ctx context.Context, opts *ResolveOptions) (*CachedResolverResult, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Would suggest not using a pointer, this is a very light struct

Comment on lines 50 to 51
// CachedResolverResult is subset of ResolverResult that is cached
type CachedResolverResult struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

Would suggest calling this ResolveResult because it is a result returned from Resolve (note: not "resolve", not "resolver"). And then move the definition to after the ResolveOptions` struct.

"Cached" is an implementation detail, and it will actually not always have been served from cache :)

Comment on lines +154 to +155
Replace the data field in vega lite json with,
{ "name": "table" }
Copy link
Contributor

Choose a reason for hiding this comment

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

Okay, you can keep if you want. But note that Go's JSON encoder is able to output indented JSON.

Comment on lines 120 to 134
func marshalResolverProperties(resolverProperties map[string]interface{}) string {
if sql, ok := resolverProperties["sql"]; ok {
if sqlStr, ok := sql.(string); ok {
return sqlStr
}
}

if api, ok := resolverProperties["api"]; ok {
if apiStr, ok := api.(string); ok {
return apiStr
}
}

return ""
}
Copy link
Contributor

Choose a reason for hiding this comment

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

The goal of the resolver abstraction is to avoid resolver-specific switches littered across the codebase. So can we change this to a normal JSON serialization?

attribute.String("args.connector", req.Connector),
attribute.String("args.table", req.Table),
attribute.String("args.metrics_view", req.MetricsView),
// attribute.String("args.prompt", req.Prompt), // Adding this might be a privacy issue
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment as in the other API


start := time.Now()

sql, err := s.generateResolverForTable(ctx, req.InstanceId, req.Prompt, tbl.Name, dialect, tbl.Schema)
Copy link
Contributor

Choose a reason for hiding this comment

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

Would suggest returning resolver, resolverProps, err here instead of sql (otherwise the function should be generateSQLResolverForTable)

Comment on lines 119 to 122
sql, err := s.generateResolverForMetricsView(ctx, req.InstanceId, req.Prompt, req.MetricsView, dialect, q.Result.Schema)
if err != nil {
return nil, err
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment – mismatch between func name and return value

@AdityaHegde AdityaHegde force-pushed the adityahegde/custom-chart-using-ai branch from 07263f8 to ca7fd31 Compare March 18, 2024 06:30
@AdityaHegde AdityaHegde force-pushed the adityahegde/custom-chart-using-ai branch from 46a9209 to 61c03ea Compare March 21, 2024 06:02
@AdityaHegde AdityaHegde merged commit 8315aec into main Mar 25, 2024
7 checks passed
@AdityaHegde AdityaHegde deleted the adityahegde/custom-chart-using-ai branch March 25, 2024 11:00
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.

3 participants