The official Chalk client library.
- Go 1.19 or later
Make sure your project is using Go Modules (it will have a go.mod
file in its
root if it already is):
go mod init
Then, reference chalk-go
in a Go program with import
:
import (
"github.com/chalk-ai/chalk-go"
)
Run any of the normal go
commands (build
/install
/test
). The Go
toolchain will resolve and fetch the chalk-go
module automatically.
Alternatively, you can also explicitly go get
the package into a project:
go get -u github.com/chalk-ai/chalk-go
Chalk generates Go structs from your python feature definitions, which makes it easy to use your features from Go.
Run the code-gen command inside your chalk project to generate a file containing your generated structs, then copy that file into your go project.
chalk codegen go --out=<OUTPUT_FILEPATH>
Create a client using the NewClient
method. The returned client gets its configuration:
- From overrides configured by passing in a
*chalk.ClientConfig
- From environment variables if no arguments are passed
- From a ~/.chalk.yml file if neither 1 nor 2 are available
(2) and (3) are applicable only for these options.
import (
"github.com/chalk-ai/chalk-go"
)
client := chalk.NewClient()
client, err := chalk.NewClient(&chalk.ClientConfig{
ClientId: "id-89140a6614886982a6782106759e30",
ClientSecret: "sec-b1ba98e658d7ada4ff4c7464fb0fcee65fe2cbd86b3dd34141e16f6314267b7b",
ApiServer: "https://api.chalk.ai",
EnvironmentId: "qa",
Branch: "jorges-december",
})
To use gRPC as the underlying protocol for communication with Chalk, set the UseGrpc
field in ClientConfig
to
true
.
client, err := chalk.NewClient(&chalk.ClientConfig{
UseGrpc: true,
})
You can then make requests just like you would without UseGrpc
specified.
Query online features using the generated feature structs. Access the results in the returned object or by passing the address of a variable with the correct type.
user := User{}
_, err = client.OnlineQuery(
chalk.OnlineQueryParams{}.
WithInput(Features.User.Id, "u273489057").
WithInput(Features.User.Transactions, []Transaction{
{Id: utils.ToPtr("sd8f76"), Amount: utils.ToPtr(13.23)},
{Id: utils.ToPtr("jk546d"), SeriesId: utils.ToPtr(48.95)},
}).
WithOutputs(Features.User.Id, Features.User.LastName),
&user,
)
When executing an offline query, a dataset is returned and can be downloaded as parquet files using the DownloadData
method.
res, _ := client.OfflineQuery(
chalk.OfflineQueryParams{}.
WithInput(Features.User.Id, []any{...}).
WithOutputs(Features.User),
)
err = res.Revisions[0].DownloadData(<FILE_DIRECTORY>)
Chalk allows you to synchronously persist features directly to your online and offline stores.
res, err := client.UploadFeatures(
chalk.UploadFeaturesParams{
Inputs: map[any]any{
Features.User.Id: []string{"user-1", "user-2"},
"user.last_name": []string{"Borges", "Paris"},
},
},
)
Note: This method is available only when using the gRPC client. See gRPC Client for more information.
You can easily update your windowed aggregation feature values with UpdateAggregates
. For example, with this feature
definition:
@features
class User:
id: str
txns: "DataFrame[Transaction]"
txn_amount_total: Windowed[int] = windowed(
"30d",
"90d",
materialization={
"bucket_duration": "1d",
},
expression=_.txns[_.amount].sum(),
)
@features
class Transaction:
id: Primary[str]
amount: float
user_id: str
Then to update the txn_amount_total
feature, you would upload features corresponding to that aggregation:
res, err := client.UpdateAggregates(
chalk.UpdateAggregatesParams{
Inputs: map[any]any{
"transaction.id": []string{"txn-1", "txn-2"},
"transaction.user_id": []string{"user-1", "user-2"},
"transaction.amount": []float64{100.0, 200.0},
"transaction.__chalk_observed_at__": []time.Time{time.Now(), time.Now()},
},
},
)
Note that if you have an explicit FeatureTime
feature specified, you could provide that in place of the
__chalk_observed_at__
column.
To query against a branch, create a ChalkClient
with a Branch
specified, and then make queries using that client.
client, err := chalk.NewClient(&chalk.ClientConfig{
Branch: "jorges-december",
})
By default, Chalk logs error messages only (which are sent to stderr
).
Configure default logging using the global DefaultLeveledLogger
variable:
chalk.DefaultLeveledLogger = &chalk.StdOutLeveledLogger{
Level: chalk.LevelInfo,
}
It's possible to use non-Chalk leveled loggers as well. Chalk expects loggers to comply to the following interface:
type LeveledLogger interface {
Debugf(format string, v ...interface{})
Errorf(format string, v ...interface{})
Infof(format string, v ...interface{})
Warnf(format string, v ...interface{})
}
Some loggers like Logrus and Zap's SugaredLogger
support this interface natively, so it's possible to set
DefaultLeveledLogger
to a *logrus.Logger
or *zap.SugaredLogger
directly.
To use other loggers, you may need a shim layer.
We'd love to accept your patches! If you submit a pull request, please keep the following guidelines in mind:
- Fork the repo, develop and test your code changes.
- Ensure your code adheres to the existing style.
- Ensure that your code has an appropriate set of tests that pass.
- Submit a pull request.
Clone the git repo from github.com/chalk-ai/chalk-go.
- All patches must be
go fmt
compatible. - All types, structs, and functions should be documented.
To execute the tests: go test ./...
. Enure all tests pass
Apache 2.0 - See LICENSE for more information.