braintrust 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,30 @@
1
+ A Node.js library for logging data to BrainTrust.
2
+
3
+ ### Quickstart
4
+
5
+ Install the library with npm (or yarn).
6
+
7
+ ```bash
8
+ npm install braintrust
9
+ ```
10
+
11
+ Then, run a simple experiment with the following code (replace `YOUR_API_KEY` with
12
+ your BrainTrust API key):
13
+
14
+ ```javascript
15
+ const braintrust = require("braintrust");
16
+
17
+ const experiment = await braintrust.init("NodeTest", {api_key: "YOUR_API_KEY"});
18
+ experiment.log({
19
+ inputs: {test: 1},
20
+ output: "foo",
21
+ expected: "bar",
22
+ scores: {
23
+ n: 0.5,
24
+ },
25
+ metadata: {
26
+ id: 1,
27
+ },
28
+ });
29
+ console.log(await experiment.summarize());
30
+ ```
package/dist/api.d.ts ADDED
File without changes
package/dist/api.js ADDED
@@ -0,0 +1 @@
1
+ "use strict";
package/dist/dep.d.ts ADDED
@@ -0,0 +1,52 @@
1
+ export declare class Experiment {
2
+ private _project;
3
+ constructor(project: string);
4
+ get project(): string;
5
+ /**
6
+ * Log a single event to the experiment. The event will be batched and uploaded behind the scenes.
7
+ *
8
+ * @param values
9
+ * @param values.inputs The arguments that uniquely define a test case (an arbitrary, JSON serializable object). Later on,
10
+ * BrainTrust will use the `inputs` to know whether two test casess are the same between experiments, so they should
11
+ * not contain experiment-specific state. A simple rule of thumb is that if you run the same experiment twice, the
12
+ * `inputs` should be identical.
13
+ * @param values.output The output of your application, including post-processing (an arbitrary, JSON serializable object),
14
+ * that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries,
15
+ * the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may
16
+ * be multiple valid queries that answer a single question.
17
+ * @param values.expected The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to
18
+ * determine if your `output` value is correct or not. BrainTrust currently does not compare `output` to `expected` for
19
+ * you, since there are so many different ways to do that correctly. Instead, these values are just used to help you
20
+ * navigate your experiments while digging into analyses. However, we may later use these values to re-score outputs or
21
+ * fine-tune your models.
22
+ * @param values.scores A dictionary of numeric values (between 0 and 1) to log. The scores should give you a variety of signals
23
+ * that help you determine how accurate the outputs are compared to what you expect and diagnose failures. For example, a
24
+ * summarization app might have one score that tells you how accurate the summary is, and another that measures the word similarity
25
+ * between the generated and grouth truth summary. The word similarity score could help you determine whether the summarization was
26
+ * covering similar concepts or not. You can use these scores to help you sort, filter, and compare experiments.
27
+ * @param values.metadata (Optional) a dictionary with additional data about the test example, model outputs, or just
28
+ * about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the
29
+ * `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any
30
+ * JSON-serializable type, but its keys must be strings.
31
+ * @returns The `id` of the logged event.
32
+ */
33
+ log({ inputs, output, expected, scores, metadata, }: {
34
+ readonly inputs: unknown;
35
+ readonly output: unknown;
36
+ readonly expected: unknown;
37
+ readonly scores: Record<string, number>;
38
+ readonly metadata?: Record<string, unknown>;
39
+ }): string;
40
+ /**
41
+ * Summarize the experiment, including the scores (compared to the closest reference experiment) and metadata.
42
+ *
43
+ * @param options
44
+ * @param summarize_scores Whether to summarize the scores. If False, only the metadata will be returned.
45
+ * @param comparison_experiment_id The experiment to compare against. If None, the most recent experiment on the origin's main branch will be used.
46
+ * @returns `ExperimentSummary`
47
+ */
48
+ summarize(options?: {
49
+ readonly summarizeScores?: boolean;
50
+ readonly comparisonExperimentId?: string;
51
+ } | undefined): string;
52
+ }
package/dist/dep.js ADDED
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Experiment = void 0;
4
+ class Experiment {
5
+ constructor(project) {
6
+ this._project = project;
7
+ }
8
+ get project() {
9
+ return this._project;
10
+ }
11
+ /**
12
+ * Log a single event to the experiment. The event will be batched and uploaded behind the scenes.
13
+ *
14
+ * @param values
15
+ * @param values.inputs The arguments that uniquely define a test case (an arbitrary, JSON serializable object). Later on,
16
+ * BrainTrust will use the `inputs` to know whether two test casess are the same between experiments, so they should
17
+ * not contain experiment-specific state. A simple rule of thumb is that if you run the same experiment twice, the
18
+ * `inputs` should be identical.
19
+ * @param values.output The output of your application, including post-processing (an arbitrary, JSON serializable object),
20
+ * that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries,
21
+ * the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may
22
+ * be multiple valid queries that answer a single question.
23
+ * @param values.expected The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to
24
+ * determine if your `output` value is correct or not. BrainTrust currently does not compare `output` to `expected` for
25
+ * you, since there are so many different ways to do that correctly. Instead, these values are just used to help you
26
+ * navigate your experiments while digging into analyses. However, we may later use these values to re-score outputs or
27
+ * fine-tune your models.
28
+ * @param values.scores A dictionary of numeric values (between 0 and 1) to log. The scores should give you a variety of signals
29
+ * that help you determine how accurate the outputs are compared to what you expect and diagnose failures. For example, a
30
+ * summarization app might have one score that tells you how accurate the summary is, and another that measures the word similarity
31
+ * between the generated and grouth truth summary. The word similarity score could help you determine whether the summarization was
32
+ * covering similar concepts or not. You can use these scores to help you sort, filter, and compare experiments.
33
+ * @param values.metadata (Optional) a dictionary with additional data about the test example, model outputs, or just
34
+ * about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the
35
+ * `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any
36
+ * JSON-serializable type, but its keys must be strings.
37
+ * @returns The `id` of the logged event.
38
+ */
39
+ log({ inputs, output, expected, scores, metadata, }) {
40
+ // TODO
41
+ (() => ({ inputs, output, expected, scores, metadata }))();
42
+ return "foo";
43
+ }
44
+ /**
45
+ * Summarize the experiment, including the scores (compared to the closest reference experiment) and metadata.
46
+ *
47
+ * @param options
48
+ * @param summarize_scores Whether to summarize the scores. If False, only the metadata will be returned.
49
+ * @param comparison_experiment_id The experiment to compare against. If None, the most recent experiment on the origin's main branch will be used.
50
+ * @returns `ExperimentSummary`
51
+ */
52
+ summarize(options = undefined) {
53
+ return "Summary!";
54
+ }
55
+ }
56
+ exports.Experiment = Experiment;
package/dist/index.d.ts CHANGED
@@ -1,8 +1,48 @@
1
+ /**
2
+ * A Node.js library for logging data to BrainTrust.
3
+ *
4
+ * ### Quickstart
5
+ *
6
+ * Install the library with npm (or yarn).
7
+ *
8
+ * ```bash
9
+ * npm install braintrust
10
+ * ```
11
+ *
12
+ * Then, run a simple experiment with the following code (replace `YOUR_API_KEY` with
13
+ * your BrainTrust API key):
14
+ *
15
+ * ```javascript
16
+ * const braintrust = require("braintrust");
17
+ *
18
+ * const experiment = await braintrust.init("NodeTest", {api_key: "YOUR_API_KEY"});
19
+ * experiment.log({
20
+ * inputs: {test: 1},
21
+ * output: "foo",
22
+ * expected: "bar",
23
+ * scores: {
24
+ * n: 0.5,
25
+ * },
26
+ * metadata: {
27
+ * id: 1,
28
+ * },
29
+ * });
30
+ * console.log(await experiment.summarize());
31
+ * ```
32
+ *
33
+ * @module braintrust
34
+ */
35
+ export declare class Project {
36
+ name: string;
37
+ id: string;
38
+ org_id: string;
39
+ constructor(name: string, id: string, org_id: string);
40
+ }
1
41
  /**
2
42
  * Log in, and then initialize a new experiment in a specified project. If the project does not exist, it will be created.
3
43
  *
4
44
  * @param project The name of the project to create the experiment in.
5
- * @param options
45
+ * @param options Additional options for configuring init().
6
46
  * @param options.experiment The name of the experiment to create. If not specified, a name will be generated automatically.
7
47
  * @param options.description An optional description of the experiment.
8
48
  * @param options.base_experiment An optional experiment name to use as a base. If specified, the new experiment will be summarized and compared to this
@@ -14,7 +54,7 @@
14
54
  * @param options.disable_cache Do not use cached login information.
15
55
  * @returns The experiment object.
16
56
  */
17
- export declare function init(project: string, { experiment, }: {
57
+ export declare function init(project: string, options?: {
18
58
  readonly experiment?: string;
19
59
  readonly description?: string;
20
60
  readonly base_experiment?: string;
@@ -22,11 +62,98 @@ export declare function init(project: string, { experiment, }: {
22
62
  readonly api_key?: string;
23
63
  readonly org_name?: string;
24
64
  readonly disable_cache?: boolean;
25
- }): Experiment;
65
+ }): Promise<Experiment>;
66
+ /**
67
+ * Log into BrainTrust. This will prompt you for your API token, which you can find at
68
+ * https://www.braintrustdata.com/app/token. This method is called automatically by `init()`.
69
+ *
70
+ * @param options
71
+ * @param options.api_url The URL of the BrainTrust API. Defaults to https://www.braintrustdata.com.
72
+ * @param options.api_key The API key to use. If the parameter is not specified, will try to use the `BRAINTRUST_API_KEY` environment variable. If no API
73
+ * key is specified, will prompt the user to login.
74
+ * @param options.org_name (Optional) The name of a specific organization to connect to. This is useful if you belong to multiple.
75
+ * @param options.disable_cache Do not use cached login information.
76
+ * @param options.force_login Login again, even if you have already logged in (by default, this function will exit quickly if you have already logged in)
77
+ * @returns
78
+ */
79
+ export declare function login(options?: {
80
+ api_url?: string;
81
+ api_key?: string;
82
+ org_name?: string;
83
+ disable_cache?: boolean;
84
+ force_login?: boolean;
85
+ } | undefined): Promise<void>;
86
+ /**
87
+ * Log a single event to the current experiment. The event will be batched and uploaded behind the scenes.
88
+ *
89
+ * @param values
90
+ * @param values.inputs The arguments that uniquely define a test case (an arbitrary, JSON serializable object). Later on,
91
+ * BrainTrust will use the `inputs` to know whether two test casess are the same between experiments, so they should
92
+ * not contain experiment-specific state. A simple rule of thumb is that if you run the same experiment twice, the
93
+ * `inputs` should be identical.
94
+ * @param values.output The output of your application, including post-processing (an arbitrary, JSON serializable object),
95
+ * that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries,
96
+ * the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may
97
+ * be multiple valid queries that answer a single question.
98
+ * @param values.expected The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to
99
+ * determine if your `output` value is correct or not. BrainTrust currently does not compare `output` to `expected` for
100
+ * you, since there are so many different ways to do that correctly. Instead, these values are just used to help you
101
+ * navigate your experiments while digging into analyses. However, we may later use these values to re-score outputs or
102
+ * fine-tune your models.
103
+ * @param values.scores A dictionary of numeric values (between 0 and 1) to log. The scores should give you a variety of signals
104
+ * that help you determine how accurate the outputs are compared to what you expect and diagnose failures. For example, a
105
+ * summarization app might have one score that tells you how accurate the summary is, and another that measures the word similarity
106
+ * between the generated and grouth truth summary. The word similarity score could help you determine whether the summarization was
107
+ * covering similar concepts or not. You can use these scores to help you sort, filter, and compare experiments.
108
+ * @param values.metadata (Optional) a dictionary with additional data about the test example, model outputs, or just
109
+ * about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the
110
+ * `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any
111
+ * JSON-serializable type, but its keys must be strings.
112
+ * @returns The `id` of the logged event.
113
+ */
114
+ export declare function log(options: {
115
+ readonly inputs: unknown;
116
+ readonly output: unknown;
117
+ readonly expected: unknown;
118
+ readonly scores: Record<string, number>;
119
+ readonly metadata?: Record<string, unknown>;
120
+ }): string;
121
+ /**
122
+ * Summarize the current experiment, including the scores (compared to the closest reference experiment) and metadata.
123
+ *
124
+ * @param options
125
+ * @param summarize_scores Whether to summarize the scores. If False, only the metadata will be returned.
126
+ * @param comparison_experiment_id The experiment to compare against. If None, the most recent experiment on the origin's main branch will be used.
127
+ * @returns `ExperimentSummary`
128
+ */
129
+ export declare function summarize(options?: {
130
+ readonly summarizeScores?: boolean;
131
+ readonly comparisonExperimentId?: string;
132
+ } | undefined): Promise<ExperimentSummary>;
133
+ /**
134
+ * An experiment is a collection of logged events, such as model inputs and outputs, which represent
135
+ * a snapshot of your application at a particular point in time. An experiment is meant to capture more
136
+ * than just the model you use, and includes the data you use to test, pre- and post- processing code,
137
+ * comparison metrics (scores), and any other metadata you want to include.
138
+ *
139
+ * Experiments are associated with a project, and two experiments are meant to be easily comparable via
140
+ * their `inputs`. You can change the attributes of the experiments in a project (e.g. scoring functions)
141
+ * over time, simply by changing what you log.
142
+ *
143
+ * You should not create `Experiment` objects directly. Instead, use the `braintrust.init()` method.
144
+ */
26
145
  export declare class Experiment {
27
- private _project;
28
- constructor(project: string);
29
- get project(): string;
146
+ readonly project: Project;
147
+ readonly id: string;
148
+ readonly name: string;
149
+ readonly user_id: string;
150
+ private logger;
151
+ constructor(project: Project, id: string, name: string, user_id: string);
152
+ static init(project: Project, { name, description, base_experiment, }?: {
153
+ name?: string;
154
+ description?: string;
155
+ base_experiment?: string;
156
+ }): Promise<Experiment>;
30
157
  /**
31
158
  * Log a single event to the experiment. The event will be batched and uploaded behind the scenes.
32
159
  *
@@ -73,5 +200,38 @@ export declare class Experiment {
73
200
  summarize(options?: {
74
201
  readonly summarizeScores?: boolean;
75
202
  readonly comparisonExperimentId?: string;
76
- } | undefined): string;
203
+ } | undefined): Promise<ExperimentSummary>;
204
+ }
205
+ /**
206
+ * Summary of a score's performance.
207
+ * @property name Name of the score.
208
+ * @property score Average score across all examples.
209
+ * @property diff Difference in score between the current and reference experiment.
210
+ * @property improvements Number of improvements in the score.
211
+ * @property regressions Number of regressions in the score.
212
+ */
213
+ interface ScoreSummary {
214
+ name: string;
215
+ score: number;
216
+ diff: number;
217
+ improvements: number;
218
+ regressions: number;
219
+ }
220
+ /**
221
+ * Summary of an experiment's scores and metadata.
222
+ * @property projectName Name of the project that the experiment belongs to.
223
+ * @property experimentName Name of the experiment.
224
+ * @property projectUrl URL to the project's page in the BrainTrust app.
225
+ * @property experimentUrl URL to the experiment's page in the BrainTrust app.
226
+ * @property comparisonExperimentName The experiment scores are baselined against.
227
+ * @property scores Summary of the experiment's scores.
228
+ */
229
+ interface ExperimentSummary {
230
+ projectName: string;
231
+ experimentName: string;
232
+ projectUrl: string;
233
+ experimentUrl: string;
234
+ comparisonExperimentName: string | undefined;
235
+ scores: Record<string, ScoreSummary> | undefined;
77
236
  }
237
+ export {};
package/dist/index.js CHANGED
@@ -1,9 +1,312 @@
1
1
  "use strict";
2
+ /**
3
+ * A Node.js library for logging data to BrainTrust.
4
+ *
5
+ * ### Quickstart
6
+ *
7
+ * Install the library with npm (or yarn).
8
+ *
9
+ * ```bash
10
+ * npm install braintrust
11
+ * ```
12
+ *
13
+ * Then, run a simple experiment with the following code (replace `YOUR_API_KEY` with
14
+ * your BrainTrust API key):
15
+ *
16
+ * ```javascript
17
+ * const braintrust = require("braintrust");
18
+ *
19
+ * const experiment = await braintrust.init("NodeTest", {api_key: "YOUR_API_KEY"});
20
+ * experiment.log({
21
+ * inputs: {test: 1},
22
+ * output: "foo",
23
+ * expected: "bar",
24
+ * scores: {
25
+ * n: 0.5,
26
+ * },
27
+ * metadata: {
28
+ * id: 1,
29
+ * },
30
+ * });
31
+ * console.log(await experiment.summarize());
32
+ * ```
33
+ *
34
+ * @module braintrust
35
+ */
36
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
37
+ if (k2 === undefined) k2 = k;
38
+ var desc = Object.getOwnPropertyDescriptor(m, k);
39
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
40
+ desc = { enumerable: true, get: function() { return m[k]; } };
41
+ }
42
+ Object.defineProperty(o, k2, desc);
43
+ }) : (function(o, m, k, k2) {
44
+ if (k2 === undefined) k2 = k;
45
+ o[k2] = m[k];
46
+ }));
47
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
48
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
49
+ }) : function(o, v) {
50
+ o["default"] = v;
51
+ });
52
+ var __importStar = (this && this.__importStar) || function (mod) {
53
+ if (mod && mod.__esModule) return mod;
54
+ var result = {};
55
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
56
+ __setModuleDefault(result, mod);
57
+ return result;
58
+ };
59
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
60
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
61
+ return new (P || (P = Promise))(function (resolve, reject) {
62
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
63
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
64
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
65
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
66
+ });
67
+ };
68
+ var __importDefault = (this && this.__importDefault) || function (mod) {
69
+ return (mod && mod.__esModule) ? mod : { "default": mod };
70
+ };
71
+ Object.defineProperty(exports, "__esModule", { value: true });
72
+ exports.Experiment = exports.summarize = exports.log = exports.login = exports.init = exports.Project = void 0;
73
+ const http = __importStar(require("http"));
74
+ const https = __importStar(require("https"));
75
+ const axios_1 = __importDefault(require("axios"));
76
+ const uuid_1 = require("uuid");
77
+ let _state = {
78
+ current_project: null,
79
+ current_experiment: null,
80
+ };
81
+ let API_URL = null;
82
+ let ORG_ID = null;
83
+ let ORG_NAME = null;
84
+ let LOG_URL = null;
85
+ let LOGGED_IN = false;
86
+ class HTTPConnection {
87
+ constructor(base_url) {
88
+ this.base_url = base_url;
89
+ this.token = null;
90
+ this.session = null;
91
+ this._reset();
92
+ }
93
+ ping() {
94
+ return __awaiter(this, void 0, void 0, function* () {
95
+ try {
96
+ const resp = yield this.get("ping");
97
+ if (_var_user_info === null) {
98
+ _var_user_info = resp.data;
99
+ }
100
+ return resp.status === 200;
101
+ }
102
+ catch (e) {
103
+ return false;
104
+ }
105
+ });
106
+ }
107
+ make_long_lived() {
108
+ // Following a suggestion in https://stackoverflow.com/questions/23013220/max-retries-exceeded-with-url-in-requests
109
+ this._reset();
110
+ }
111
+ set_token(token) {
112
+ token = token.trim();
113
+ this.token = token;
114
+ this._reset();
115
+ }
116
+ // As far as I can tell, you cannot set the retry/backoff factor here
117
+ _reset() {
118
+ // From https://github.com/axios/axios/issues/1846
119
+ const httpAgent = new http.Agent({ keepAlive: true });
120
+ const httpsAgent = new https.Agent({ keepAlive: true });
121
+ let headers = {};
122
+ if (this.token) {
123
+ headers["Authorization"] = `Bearer ${this.token}`;
124
+ }
125
+ this.session = axios_1.default.create({
126
+ httpAgent,
127
+ httpsAgent,
128
+ headers,
129
+ });
130
+ }
131
+ get(path, params = undefined) {
132
+ return __awaiter(this, void 0, void 0, function* () {
133
+ return yield this.session.get(_urljoin(this.base_url, path), { params });
134
+ });
135
+ }
136
+ post(path, params = undefined) {
137
+ return __awaiter(this, void 0, void 0, function* () {
138
+ return yield this.session.post(_urljoin(this.base_url, path), params);
139
+ });
140
+ }
141
+ }
142
+ let _api_conn = null;
143
+ function api_conn() {
144
+ if (!_api_conn) {
145
+ _api_conn = new HTTPConnection(LOG_URL);
146
+ }
147
+ return _api_conn;
148
+ }
149
+ function api_get(object_type, args = undefined) {
150
+ return __awaiter(this, void 0, void 0, function* () {
151
+ const resp = yield api_conn().get(`${object_type}`, args);
152
+ return resp.data;
153
+ });
154
+ }
155
+ function api_insert(object_type, args = undefined) {
156
+ return __awaiter(this, void 0, void 0, function* () {
157
+ const resp = yield api_conn().post(`${object_type}`, args);
158
+ return resp.data;
159
+ });
160
+ }
161
+ let _var_user_info = null;
162
+ function _user_info() {
163
+ return __awaiter(this, void 0, void 0, function* () {
164
+ if (_var_user_info === null) {
165
+ _var_user_info = yield api_get("ping");
166
+ }
167
+ return _var_user_info;
168
+ });
169
+ }
170
+ class Project {
171
+ constructor(name, id, org_id) {
172
+ this.name = name;
173
+ this.id = id;
174
+ this.org_id = org_id;
175
+ }
176
+ }
177
+ exports.Project = Project;
178
+ // NOTE: This is because we do not have async constructors
179
+ const _PROJECTS_ENDPOINT = "projects";
180
+ function initProject(name) {
181
+ return __awaiter(this, void 0, void 0, function* () {
182
+ const unique_key = { name, org_id: ORG_ID };
183
+ // Can we have an upsert (or insert if not exists) method instead?
184
+ let existing = [];
185
+ if (unique_key) {
186
+ existing = yield api_get(_PROJECTS_ENDPOINT, unique_key);
187
+ }
188
+ if (existing.length === 0) {
189
+ existing = yield api_insert(_PROJECTS_ENDPOINT, unique_key);
190
+ }
191
+ if (existing) {
192
+ return existing[0];
193
+ }
194
+ else {
195
+ throw new Error(`Unable to find record in ${_PROJECTS_ENDPOINT}`);
196
+ }
197
+ });
198
+ }
199
+ /*
200
+ def guess_git_experiment_name():
201
+ try:
202
+ repo = git.Repo(search_parent_directories=True)
203
+ except git.InvalidGitRepositoryError:
204
+ return None
205
+
206
+ branch = repo.active_branch.name
207
+ diff = repo.git.diff(repo.head.commit.tree)
208
+ if not diff and len(repo.head.commit.parents) > 0:
209
+ diff = repo.head.commit.message + "\n" + repo.git.diff(repo.head.commit.tree, repo.head.commit.parents[0].tree)
210
+
211
+ return [
212
+ {
213
+ "role": "system",
214
+ "content": """\
215
+ You can generate two word summaries for machine learning experiment names, based
216
+ on the branch name and an optional "diff" of the experiment's code on top of the branch.
217
+ The experiment name should be exactly two words, concatenated with a hyphen, all lowercase.
218
+ The input format is the output of "git diff". For example, "foo-bar" is valid but
219
+ "foo-bar-baz" is not.""",
220
+ },
221
+ {
222
+ "role": "user",
223
+ "content": f"Branch: {branch}" + (f"\n\nDiff:\n{diff[:4096]}" if diff else ""),
224
+ },
225
+ ]
226
+
227
+
228
+ def guess_experiment_name():
229
+ # OpenAI is very slow to import, so we only do it when we need it
230
+ import openai
231
+
232
+ if openai.api_key is None:
233
+ return None
234
+
235
+ messages = guess_notebook_block_name()
236
+ if not messages:
237
+ messages = guess_git_experiment_name()
238
+
239
+ if not messages:
240
+ return None
241
+
242
+ resp = run_cached_request(
243
+ Completion=openai.ChatCompletion,
244
+ model="gpt-3.5-turbo",
245
+ messages=messages,
246
+ max_tokens=128,
247
+ temperature=0.7,
248
+ )
249
+
250
+ name = None
251
+ if len(resp["choices"]) > 0:
252
+ name = "-".join(resp["choices"][0]["message"]["content"].split("-")[:2])
253
+ # Strip punctuation and whitespace from the prefix and suffix
254
+ name = name.strip(" .,;:!?-")
255
+ return name
256
+ */
257
+ function guess_experiment_name() {
258
+ // TODO: Implement experiment name guessing from git
259
+ return null;
260
+ }
261
+ class LogThread {
262
+ constructor() {
263
+ this.items = [];
264
+ this.active_flush = Promise.resolve([]);
265
+ this.active_flush_resolved = true;
266
+ }
267
+ log(items) {
268
+ this.items.push(...items);
269
+ if (this.active_flush_resolved) {
270
+ this.active_flush_resolved = false;
271
+ this.active_flush = this.flush_once();
272
+ }
273
+ }
274
+ flush_once() {
275
+ return __awaiter(this, void 0, void 0, function* () {
276
+ this.active_flush_resolved = false;
277
+ const items = this.items;
278
+ this.items = [];
279
+ let ret = [];
280
+ if (items.length > 0) {
281
+ const resp = yield api_insert("logs", items);
282
+ ret = resp.data;
283
+ }
284
+ // If more items were added while we were flushing, flush again
285
+ if (this.items.length > 0) {
286
+ this.active_flush = this.flush_once();
287
+ }
288
+ else {
289
+ this.active_flush_resolved = true;
290
+ }
291
+ return ret;
292
+ });
293
+ }
294
+ flush() {
295
+ return __awaiter(this, void 0, void 0, function* () {
296
+ while (true) {
297
+ yield this.active_flush;
298
+ if (this.active_flush_resolved) {
299
+ break;
300
+ }
301
+ }
302
+ });
303
+ }
304
+ }
2
305
  /**
3
306
  * Log in, and then initialize a new experiment in a specified project. If the project does not exist, it will be created.
4
307
  *
5
308
  * @param project The name of the project to create the experiment in.
6
- * @param options
309
+ * @param options Additional options for configuring init().
7
310
  * @param options.experiment The name of the experiment to create. If not specified, a name will be generated automatically.
8
311
  * @param options.description An optional description of the experiment.
9
312
  * @param options.base_experiment An optional experiment name to use as a base. If specified, the new experiment will be summarized and compared to this
@@ -15,19 +318,226 @@
15
318
  * @param options.disable_cache Do not use cached login information.
16
319
  * @returns The experiment object.
17
320
  */
18
- Object.defineProperty(exports, "__esModule", { value: true });
19
- exports.Experiment = exports.init = void 0;
20
- function init(project, { experiment, }) {
21
- // TODO
22
- return new Experiment(project);
321
+ function init(project, options = {}) {
322
+ return __awaiter(this, void 0, void 0, function* () {
323
+ const { experiment, description, base_experiment, api_url, api_key, org_name, disable_cache, } = options || {};
324
+ yield login({
325
+ org_name,
326
+ disable_cache,
327
+ api_key,
328
+ api_url,
329
+ });
330
+ _state.current_project = yield initProject(project);
331
+ _state.current_experiment = yield Experiment.init(_state.current_project, {
332
+ name: experiment,
333
+ description,
334
+ base_experiment,
335
+ });
336
+ return _state.current_experiment;
337
+ });
23
338
  }
24
339
  exports.init = init;
340
+ /**
341
+ * Log into BrainTrust. This will prompt you for your API token, which you can find at
342
+ * https://www.braintrustdata.com/app/token. This method is called automatically by `init()`.
343
+ *
344
+ * @param options
345
+ * @param options.api_url The URL of the BrainTrust API. Defaults to https://www.braintrustdata.com.
346
+ * @param options.api_key The API key to use. If the parameter is not specified, will try to use the `BRAINTRUST_API_KEY` environment variable. If no API
347
+ * key is specified, will prompt the user to login.
348
+ * @param options.org_name (Optional) The name of a specific organization to connect to. This is useful if you belong to multiple.
349
+ * @param options.disable_cache Do not use cached login information.
350
+ * @param options.force_login Login again, even if you have already logged in (by default, this function will exit quickly if you have already logged in)
351
+ * @returns
352
+ */
353
+ function login(options = undefined) {
354
+ return __awaiter(this, void 0, void 0, function* () {
355
+ const { api_url = process.env.BRAINTRUST_API_URL ||
356
+ "https://www.braintrustdata.com", api_key = process.env.BRAINTRUST_API_KEY, org_name = undefined, disable_cache = false, force_login = false, } = options || {};
357
+ if (LOGGED_IN && !force_login) {
358
+ return;
359
+ }
360
+ API_URL = api_url;
361
+ let login_key_info = null;
362
+ let ping_ok = false;
363
+ let conn = null;
364
+ if (api_key !== undefined) {
365
+ const resp = yield axios_1.default.post(_urljoin(API_URL, `/api/apikey/login`), {
366
+ token: api_key,
367
+ });
368
+ const info = resp.data;
369
+ _check_org_info(info.org_info, org_name);
370
+ conn = api_conn();
371
+ conn.set_token(api_key);
372
+ ping_ok = yield conn.ping();
373
+ }
374
+ else {
375
+ // TODO: Implement token based login in the JS client
376
+ throw new Error("Please specify an api key. Token based login is not yet implemented in the JS client.");
377
+ }
378
+ if (!conn) {
379
+ throw new Error("Conn should be set at this point (a bug)");
380
+ }
381
+ if (!ping_ok) {
382
+ yield conn.get("ping");
383
+ }
384
+ conn.make_long_lived();
385
+ LOGGED_IN = true;
386
+ });
387
+ }
388
+ exports.login = login;
389
+ /**
390
+ * Log a single event to the current experiment. The event will be batched and uploaded behind the scenes.
391
+ *
392
+ * @param values
393
+ * @param values.inputs The arguments that uniquely define a test case (an arbitrary, JSON serializable object). Later on,
394
+ * BrainTrust will use the `inputs` to know whether two test casess are the same between experiments, so they should
395
+ * not contain experiment-specific state. A simple rule of thumb is that if you run the same experiment twice, the
396
+ * `inputs` should be identical.
397
+ * @param values.output The output of your application, including post-processing (an arbitrary, JSON serializable object),
398
+ * that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries,
399
+ * the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may
400
+ * be multiple valid queries that answer a single question.
401
+ * @param values.expected The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to
402
+ * determine if your `output` value is correct or not. BrainTrust currently does not compare `output` to `expected` for
403
+ * you, since there are so many different ways to do that correctly. Instead, these values are just used to help you
404
+ * navigate your experiments while digging into analyses. However, we may later use these values to re-score outputs or
405
+ * fine-tune your models.
406
+ * @param values.scores A dictionary of numeric values (between 0 and 1) to log. The scores should give you a variety of signals
407
+ * that help you determine how accurate the outputs are compared to what you expect and diagnose failures. For example, a
408
+ * summarization app might have one score that tells you how accurate the summary is, and another that measures the word similarity
409
+ * between the generated and grouth truth summary. The word similarity score could help you determine whether the summarization was
410
+ * covering similar concepts or not. You can use these scores to help you sort, filter, and compare experiments.
411
+ * @param values.metadata (Optional) a dictionary with additional data about the test example, model outputs, or just
412
+ * about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the
413
+ * `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any
414
+ * JSON-serializable type, but its keys must be strings.
415
+ * @returns The `id` of the logged event.
416
+ */
417
+ function log(options) {
418
+ if (!_state.current_experiment) {
419
+ throw new Error("Not initialized. Please call init() first");
420
+ }
421
+ return _state.current_experiment.log(options);
422
+ }
423
+ exports.log = log;
424
+ /**
425
+ * Summarize the current experiment, including the scores (compared to the closest reference experiment) and metadata.
426
+ *
427
+ * @param options
428
+ * @param summarize_scores Whether to summarize the scores. If False, only the metadata will be returned.
429
+ * @param comparison_experiment_id The experiment to compare against. If None, the most recent experiment on the origin's main branch will be used.
430
+ * @returns `ExperimentSummary`
431
+ */
432
+ function summarize(options = undefined) {
433
+ return __awaiter(this, void 0, void 0, function* () {
434
+ if (!_state.current_experiment) {
435
+ throw new Error("Not initialized. Please call init() first");
436
+ }
437
+ return yield _state.current_experiment.summarize(options);
438
+ });
439
+ }
440
+ exports.summarize = summarize;
441
+ function _check_org_info(org_info, org_name) {
442
+ if (org_info.length === 0) {
443
+ throw new Error("This user is not part of any organizations.");
444
+ }
445
+ for (const org of org_info) {
446
+ if (org_name === undefined || org.name === org_name) {
447
+ ORG_ID = org.id;
448
+ ORG_NAME = org.name;
449
+ LOG_URL = org.api_url;
450
+ break;
451
+ }
452
+ }
453
+ if (ORG_ID === undefined) {
454
+ throw new Error(`Organization ${org_name} not found. Must be one of ${org_info
455
+ .map((x) => x.name)
456
+ .join(", ")}`);
457
+ }
458
+ }
459
+ function _urljoin(...parts) {
460
+ return parts.map((x) => x.replace(/^\//, "")).join("/");
461
+ }
462
+ /**
463
+ * An experiment is a collection of logged events, such as model inputs and outputs, which represent
464
+ * a snapshot of your application at a particular point in time. An experiment is meant to capture more
465
+ * than just the model you use, and includes the data you use to test, pre- and post- processing code,
466
+ * comparison metrics (scores), and any other metadata you want to include.
467
+ *
468
+ * Experiments are associated with a project, and two experiments are meant to be easily comparable via
469
+ * their `inputs`. You can change the attributes of the experiments in a project (e.g. scoring functions)
470
+ * over time, simply by changing what you log.
471
+ *
472
+ * You should not create `Experiment` objects directly. Instead, use the `braintrust.init()` method.
473
+ */
25
474
  class Experiment {
26
- constructor(project) {
27
- this._project = project;
475
+ constructor(project, id, name, user_id) {
476
+ this.project = project;
477
+ this.id = id;
478
+ this.name = name;
479
+ this.user_id = user_id;
480
+ this.logger = new LogThread();
28
481
  }
29
- get project() {
30
- return this._project;
482
+ static init(project, { name, description, base_experiment, } = {
483
+ name: undefined,
484
+ description: undefined,
485
+ base_experiment: undefined,
486
+ }) {
487
+ return __awaiter(this, void 0, void 0, function* () {
488
+ const args = { project_id: project.id };
489
+ // TODO
490
+ /*
491
+ if (!name) {
492
+ name = guessExperimentName();
493
+ }
494
+ */
495
+ if (name) {
496
+ args["name"] = name;
497
+ }
498
+ if (description) {
499
+ args["description"] = description;
500
+ }
501
+ // TODO
502
+ /*
503
+ const repoStatus = await get_repo_status();
504
+ if (repoStatus) {
505
+ args["repo_info"] = repoStatus;
506
+ }
507
+ */
508
+ const conn = api_conn();
509
+ let base_exp_id = undefined;
510
+ if (base_experiment !== undefined) {
511
+ const resp = yield conn.get("experiments", {
512
+ project_id: project.id,
513
+ name: base_experiment,
514
+ });
515
+ const experiments = resp.data;
516
+ if (experiments.length > 0) {
517
+ base_exp_id = experiments[0]["id"];
518
+ }
519
+ else {
520
+ throw new Error(`Base experiment ${base_experiment} not found`);
521
+ }
522
+ }
523
+ if (base_exp_id === undefined) {
524
+ const resp = yield conn.post("experiments-by-commits", {
525
+ project_id: project.id,
526
+ // TODO
527
+ commits: [] /* await get_past_n_ancestors() */,
528
+ });
529
+ base_exp_id = resp.data["experiment_id"];
530
+ }
531
+ if (base_exp_id !== undefined) {
532
+ args["base_exp_id"] = base_exp_id;
533
+ }
534
+ const data = (yield api_insert("register-experiment", args))[0];
535
+ // NOTE: This is a deviation from the Python lib and allows the log() method
536
+ // to not be async.
537
+ //
538
+ const user_id = (yield _user_info())["id"];
539
+ return new Experiment(project, data.id, data.name, user_id);
540
+ });
31
541
  }
32
542
  /**
33
543
  * Log a single event to the experiment. The event will be batched and uploaded behind the scenes.
@@ -58,9 +568,38 @@ class Experiment {
58
568
  * @returns The `id` of the logged event.
59
569
  */
60
570
  log({ inputs, output, expected, scores, metadata, }) {
61
- // TODO
62
- (() => ({ inputs, output, expected, scores, metadata }))();
63
- return "foo";
571
+ for (const [name, score] of Object.entries(scores)) {
572
+ if (typeof name !== "string") {
573
+ throw new Error("score names must be strings");
574
+ }
575
+ if (typeof score !== "number") {
576
+ throw new Error("score values must be numbers");
577
+ }
578
+ if (score < 0 || score > 1) {
579
+ throw new Error("score values must be between 0 and 1");
580
+ }
581
+ }
582
+ if (metadata !== undefined) {
583
+ for (const key of Object.keys(metadata)) {
584
+ if (typeof key !== "string") {
585
+ throw new Error("metadata keys must be strings");
586
+ }
587
+ }
588
+ }
589
+ const args = {
590
+ id: (0, uuid_1.v4)(),
591
+ inputs,
592
+ output,
593
+ expected,
594
+ scores,
595
+ project_id: this.project.id,
596
+ experiment_id: this.id,
597
+ user_id: this.user_id,
598
+ created: new Date().toISOString(),
599
+ metadata,
600
+ };
601
+ this.logger.log([args]);
602
+ return args.id;
64
603
  }
65
604
  /**
66
605
  * Summarize the experiment, including the scores (compared to the closest reference experiment) and metadata.
@@ -71,7 +610,41 @@ class Experiment {
71
610
  * @returns `ExperimentSummary`
72
611
  */
73
612
  summarize(options = undefined) {
74
- return "Summary!";
613
+ return __awaiter(this, void 0, void 0, function* () {
614
+ let { summarizeScores = true, comparisonExperimentId = undefined } = options || {};
615
+ yield this.logger.flush();
616
+ const projectUrl = `${API_URL}/app/${encodeURIComponent(ORG_NAME)}/p/${encodeURIComponent(this.project.name)}`;
617
+ const experimentUrl = `${projectUrl}/${encodeURIComponent(this.name)}`;
618
+ let scores = undefined;
619
+ let comparisonExperimentName = undefined;
620
+ if (summarizeScores) {
621
+ if (comparisonExperimentId === undefined) {
622
+ const conn = api_conn();
623
+ const resp = yield conn.get("/crud/base_experiments", {
624
+ id: this.id,
625
+ });
626
+ const base_experiments = resp.data;
627
+ if (base_experiments.length > 0) {
628
+ comparisonExperimentId = base_experiments[0]["base_exp_id"];
629
+ comparisonExperimentName = base_experiments[0]["base_exp_name"];
630
+ }
631
+ }
632
+ if (comparisonExperimentId !== undefined) {
633
+ scores = (yield api_conn().get("/experiment-comparison", {
634
+ experiment_id: this.id,
635
+ base_experiment_id: comparisonExperimentId,
636
+ })).data;
637
+ }
638
+ }
639
+ return {
640
+ projectName: this.project.name,
641
+ experimentName: this.name,
642
+ projectUrl: projectUrl,
643
+ experimentUrl: experimentUrl,
644
+ comparisonExperimentName: comparisonExperimentName,
645
+ scores,
646
+ };
647
+ });
75
648
  }
76
649
  }
77
650
  exports.Experiment = Experiment;
@@ -1 +1 @@
1
- {"program":{"fileNames":["../node_modules/typescript/lib/lib.es5.d.ts","../node_modules/typescript/lib/lib.es2015.d.ts","../node_modules/typescript/lib/lib.es2015.core.d.ts","../node_modules/typescript/lib/lib.es2015.collection.d.ts","../node_modules/typescript/lib/lib.es2015.generator.d.ts","../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../node_modules/typescript/lib/lib.es2015.promise.d.ts","../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../node_modules/typescript/lib/lib.decorators.d.ts","../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../src/index.ts"],"fileInfos":[{"version":"f59215c5f1d886b05395ee7aca73e0ac69ddfad2843aa88530e797879d511bad","affectsGlobalScope":true},"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4",{"version":"9d9885c728913c1d16e0d2831b40341d6ad9a0ceecaabc55209b306ad9c736a5","affectsGlobalScope":true},{"version":"17bea081b9c0541f39dd1ae9bc8c78bdd561879a682e60e2f25f688c0ecab248","affectsGlobalScope":true},{"version":"4443e68b35f3332f753eacc66a04ac1d2053b8b035a0e0ac1d455392b5e243b3","affectsGlobalScope":true},{"version":"ab22100fdd0d24cfc2cc59d0a00fc8cf449830d9c4030dc54390a46bd562e929","affectsGlobalScope":true},{"version":"f7bd636ae3a4623c503359ada74510c4005df5b36de7f23e1db8a5c543fd176b","affectsGlobalScope":true},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true},{"version":"0c20f4d2358eb679e4ae8a4432bdd96c857a2960fd6800b21ec4008ec59d60ea","affectsGlobalScope":true},{"version":"36ae84ccc0633f7c0787bc6108386c8b773e95d3b052d9464a99cd9b8795fbec","affectsGlobalScope":true},{"version":"189c0703923150aa30673fa3de411346d727cc44a11c75d05d7cf9ef095daa22","affectsGlobalScope":true},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true},{"version":"0b0efe6cf1c03e6fcdb6e0d4650267739d78670d17e77310d8e4930d91671622","signature":"b4370986352e9c14688509ded0252bf8daa86bdcff5f2c2f7c8b2f7514fec525"}],"root":[14],"options":{"declaration":true,"esModuleInterop":true,"module":1,"outDir":"./","strict":true,"target":2},"referencedMap":[],"exportedModulesMap":[],"semanticDiagnosticsPerFile":[12,13,4,3,2,5,6,7,8,9,10,11,1,14]},"version":"5.1.6"}
1
+ {"program":{"fileNames":["../node_modules/typescript/lib/lib.es5.d.ts","../node_modules/typescript/lib/lib.es2015.d.ts","../node_modules/typescript/lib/lib.es2016.d.ts","../node_modules/typescript/lib/lib.es2017.d.ts","../node_modules/typescript/lib/lib.es2018.d.ts","../node_modules/typescript/lib/lib.es2019.d.ts","../node_modules/typescript/lib/lib.es2020.d.ts","../node_modules/typescript/lib/lib.es2015.core.d.ts","../node_modules/typescript/lib/lib.es2015.collection.d.ts","../node_modules/typescript/lib/lib.es2015.generator.d.ts","../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../node_modules/typescript/lib/lib.es2015.promise.d.ts","../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../node_modules/typescript/lib/lib.es2017.object.d.ts","../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../node_modules/typescript/lib/lib.es2017.string.d.ts","../node_modules/typescript/lib/lib.es2017.intl.d.ts","../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../node_modules/typescript/lib/lib.es2018.intl.d.ts","../node_modules/typescript/lib/lib.es2018.promise.d.ts","../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../node_modules/typescript/lib/lib.es2019.array.d.ts","../node_modules/typescript/lib/lib.es2019.object.d.ts","../node_modules/typescript/lib/lib.es2019.string.d.ts","../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../node_modules/typescript/lib/lib.es2019.intl.d.ts","../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../node_modules/typescript/lib/lib.es2020.date.d.ts","../node_modules/typescript/lib/lib.es2020.promise.d.ts","../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../node_modules/typescript/lib/lib.es2020.string.d.ts","../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../node_modules/typescript/lib/lib.es2020.intl.d.ts","../node_modules/typescript/lib/lib.es2020.number.d.ts","../node_modules/typescript/lib/lib.esnext.intl.d.ts","../node_modules/typescript/lib/lib.decorators.d.ts","../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../node_modules/axios/index.d.ts","../node_modules/@types/uuid/index.d.ts","../src/index.ts","../node_modules/@types/node/assert.d.ts","../node_modules/@types/node/assert/strict.d.ts","../node_modules/@types/node/globals.d.ts","../node_modules/@types/node/async_hooks.d.ts","../node_modules/@types/node/buffer.d.ts","../node_modules/@types/node/child_process.d.ts","../node_modules/@types/node/cluster.d.ts","../node_modules/@types/node/console.d.ts","../node_modules/@types/node/constants.d.ts","../node_modules/@types/node/crypto.d.ts","../node_modules/@types/node/dgram.d.ts","../node_modules/@types/node/diagnostics_channel.d.ts","../node_modules/@types/node/dns.d.ts","../node_modules/@types/node/dns/promises.d.ts","../node_modules/@types/node/domain.d.ts","../node_modules/@types/node/dom-events.d.ts","../node_modules/@types/node/events.d.ts","../node_modules/@types/node/fs.d.ts","../node_modules/@types/node/fs/promises.d.ts","../node_modules/@types/node/http.d.ts","../node_modules/@types/node/http2.d.ts","../node_modules/@types/node/https.d.ts","../node_modules/@types/node/inspector.d.ts","../node_modules/@types/node/module.d.ts","../node_modules/@types/node/net.d.ts","../node_modules/@types/node/os.d.ts","../node_modules/@types/node/path.d.ts","../node_modules/@types/node/perf_hooks.d.ts","../node_modules/@types/node/process.d.ts","../node_modules/@types/node/punycode.d.ts","../node_modules/@types/node/querystring.d.ts","../node_modules/@types/node/readline.d.ts","../node_modules/@types/node/readline/promises.d.ts","../node_modules/@types/node/repl.d.ts","../node_modules/@types/node/stream.d.ts","../node_modules/@types/node/stream/promises.d.ts","../node_modules/@types/node/stream/consumers.d.ts","../node_modules/@types/node/stream/web.d.ts","../node_modules/@types/node/string_decoder.d.ts","../node_modules/@types/node/test.d.ts","../node_modules/@types/node/timers.d.ts","../node_modules/@types/node/timers/promises.d.ts","../node_modules/@types/node/tls.d.ts","../node_modules/@types/node/trace_events.d.ts","../node_modules/@types/node/tty.d.ts","../node_modules/@types/node/url.d.ts","../node_modules/@types/node/util.d.ts","../node_modules/@types/node/v8.d.ts","../node_modules/@types/node/vm.d.ts","../node_modules/@types/node/wasi.d.ts","../node_modules/@types/node/worker_threads.d.ts","../node_modules/@types/node/zlib.d.ts","../node_modules/@types/node/globals.global.d.ts","../node_modules/@types/node/index.d.ts"],"fileInfos":[{"version":"f59215c5f1d886b05395ee7aca73e0ac69ddfad2843aa88530e797879d511bad","affectsGlobalScope":true},"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","dc48272d7c333ccf58034c0026162576b7d50ea0e69c3b9292f803fc20720fd5","27147504487dc1159369da4f4da8a26406364624fa9bc3db632f7d94a5bae2c3","5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4",{"version":"9d9885c728913c1d16e0d2831b40341d6ad9a0ceecaabc55209b306ad9c736a5","affectsGlobalScope":true},{"version":"17bea081b9c0541f39dd1ae9bc8c78bdd561879a682e60e2f25f688c0ecab248","affectsGlobalScope":true},{"version":"4443e68b35f3332f753eacc66a04ac1d2053b8b035a0e0ac1d455392b5e243b3","affectsGlobalScope":true},{"version":"ab22100fdd0d24cfc2cc59d0a00fc8cf449830d9c4030dc54390a46bd562e929","affectsGlobalScope":true},{"version":"f7bd636ae3a4623c503359ada74510c4005df5b36de7f23e1db8a5c543fd176b","affectsGlobalScope":true},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true},{"version":"0c20f4d2358eb679e4ae8a4432bdd96c857a2960fd6800b21ec4008ec59d60ea","affectsGlobalScope":true},{"version":"36ae84ccc0633f7c0787bc6108386c8b773e95d3b052d9464a99cd9b8795fbec","affectsGlobalScope":true},{"version":"82d0d8e269b9eeac02c3bd1c9e884e85d483fcb2cd168bccd6bc54df663da031","affectsGlobalScope":true},{"version":"b8deab98702588840be73d67f02412a2d45a417a3c097b2e96f7f3a42ac483d1","affectsGlobalScope":true},{"version":"4738f2420687fd85629c9efb470793bb753709c2379e5f85bc1815d875ceadcd","affectsGlobalScope":true},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true},{"version":"376d554d042fb409cb55b5cbaf0b2b4b7e669619493c5d18d5fa8bd67273f82a","affectsGlobalScope":true},{"version":"9fc46429fbe091ac5ad2608c657201eb68b6f1b8341bd6d670047d32ed0a88fa","affectsGlobalScope":true},{"version":"61c37c1de663cf4171e1192466e52c7a382afa58da01b1dc75058f032ddf0839","affectsGlobalScope":true},{"version":"c4138a3dd7cd6cf1f363ca0f905554e8d81b45844feea17786cdf1626cb8ea06","affectsGlobalScope":true},{"version":"6ff3e2452b055d8f0ec026511c6582b55d935675af67cdb67dd1dc671e8065df","affectsGlobalScope":true},{"version":"03de17b810f426a2f47396b0b99b53a82c1b60e9cba7a7edda47f9bb077882f4","affectsGlobalScope":true},{"version":"8184c6ddf48f0c98429326b428478ecc6143c27f79b79e85740f17e6feb090f1","affectsGlobalScope":true},{"version":"261c4d2cf86ac5a89ad3fb3fafed74cbb6f2f7c1d139b0540933df567d64a6ca","affectsGlobalScope":true},{"version":"6af1425e9973f4924fca986636ac19a0cf9909a7e0d9d3009c349e6244e957b6","affectsGlobalScope":true},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true},{"version":"15a630d6817718a2ddd7088c4f83e4673fde19fa992d2eae2cf51132a302a5d3","affectsGlobalScope":true},{"version":"f06948deb2a51aae25184561c9640fb66afeddb34531a9212d011792b1d19e0a","affectsGlobalScope":true},{"version":"01e0ee7e1f661acedb08b51f8a9b7d7f959e9cdb6441360f06522cc3aea1bf2e","affectsGlobalScope":true},{"version":"ac17a97f816d53d9dd79b0d235e1c0ed54a8cc6a0677e9a3d61efb480b2a3e4e","affectsGlobalScope":true},{"version":"bf14a426dbbf1022d11bd08d6b8e709a2e9d246f0c6c1032f3b2edb9a902adbe","affectsGlobalScope":true},{"version":"ec0104fee478075cb5171e5f4e3f23add8e02d845ae0165bfa3f1099241fa2aa","affectsGlobalScope":true},{"version":"2b72d528b2e2fe3c57889ca7baef5e13a56c957b946906d03767c642f386bbc3","affectsGlobalScope":true},{"version":"9cc66b0513ad41cb5f5372cca86ef83a0d37d1c1017580b7dace3ea5661836df","affectsGlobalScope":true},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true},{"version":"307c8b7ebbd7f23a92b73a4c6c0a697beca05b06b036c23a34553e5fe65e4fdc","affectsGlobalScope":true},{"version":"189c0703923150aa30673fa3de411346d727cc44a11c75d05d7cf9ef095daa22","affectsGlobalScope":true},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true},"1d729ea435a93e1a70519d06a6f13fa418c4c39a52b69e6db86750ebfcdf5554","95c617b16c4765ff6de307629b6918181908bee82a59fca0b2c95f170a4be7ea",{"version":"953cc0f7f15219f652f865083404e93e79314a8dedbedfd017320871eac2619c","signature":"503e6fc7e1a057c9c51962e32bac1f31827fae2100f413341595c165936ac140"},"587f13f1e8157bd8cec0adda0de4ef558bb8573daa9d518d1e2af38e87ecc91f","a69c09dbea52352f479d3e7ac949fde3d17b195abe90b045d619f747b38d6d1a",{"version":"bce910d9164785c9f0d4dcea4be359f5f92130c7c7833dea6138ab1db310a1f9","affectsGlobalScope":true},"7a435e0c814f58f23e9a0979045ec0ef5909aac95a70986e8bcce30c27dff228",{"version":"c81c51f43e343b6d89114b17341fb9d381c4ccbb25e0ee77532376052c801ba7","affectsGlobalScope":true},"db71be322f07f769200108aa19b79a75dd19a187c9dca2a30c4537b233aa2863","57135ce61976a8b1dadd01bb412406d1805b90db6e8ecb726d0d78e0b5f76050",{"version":"49479e21a040c0177d1b1bc05a124c0383df7a08a0726ad4d9457619642e875a","affectsGlobalScope":true},"82408ed3e959ddc60d3e9904481b5a8dc16469928257af22a3f7d1a3bc7fd8c4","f302f3a47d7758f67f2afc753b9375d6504dde05d2e6ecdb1df50abbb131fc89","3690133deae19c8127c5505fcb67b04bdc9eb053796008538a9b9abbb70d85aa","5b1c0a23f464f894e7c2b2b6c56df7b9afa60ed48c5345f8618d389a636b2108","be2b092f2765222757c6441b86c53a5ea8dfed47bbc43eab4c5fe37942c866b3","8e6b05abc98adba15e1ac78e137c64576c74002e301d682e66feb77a23907ab8","1ca735bb3d407b2af4fbee7665f3a0a83be52168c728cc209755060ba7ed67bd",{"version":"6b526a5ec4a401ca7c26cfe6a48e641d8f30af76673bad3b06a1b4504594a960","affectsGlobalScope":true},{"version":"b85c02e14ecb2a873dad5a1de72319b265160ba48f1b83661aeb3bba1366c1bc","affectsGlobalScope":true},"7a2ba0c9af860ac3e77b35ed01fd96d15986f17aa22fe40f188ae556fb1070df","fc3764040518a1008dd04bdc80964591b566b896283e00df85c95851c1f46237","55709608060f77965c270ac10ac646286589f1bd1cb174fff1778a2dd9a7ef31","790623a47c5eda62910098884ecb154dc0e5f3a23fc36c1bfb3b5b9ed44e2c2d","42b40e40f2a358cda332456214fad311e1806a6abf3cebaaac72496e07556642","354612fe1d49ecc9551ea3a27d94eef2887b64ef4a71f72ca444efe0f2f0ba80",{"version":"ac0c77cd7db52b3c278bdd1452ce754014835493d05b84535f46854fdc2063b2","affectsGlobalScope":true},"f5490f53d40291cc8607f5463434d1ac6c5564bc4fbb03abceb03a8f6b014457","5e2b91328a540a0933ab5c2203f4358918e6f0fe7505d22840a891a6117735f1","3abc3512fa04aa0230f59ea1019311fd8667bd935d28306311dccc8b17e79d5d",{"version":"14a50dafe3f45713f7f27cb6320dff07c6ac31678f07959c2134260061bf91ff","affectsGlobalScope":true},{"version":"19da7150ca062323b1db6311a6ef058c9b0a39cc64d836b5e9b75d301869653b","affectsGlobalScope":true},"1349077576abb41f0e9c78ec30762ff75b710208aff77f5fdcc6a8c8ce6289dd","e2ce82603102b5c0563f59fb40314cc1ff95a4d521a66ad14146e130ea80d89c","a3e0395220255a350aa9c6d56f882bfcb5b85c19fddf5419ec822cf22246a26d","c27b01e8ddff5cd280711af5e13aecd9a3228d1c256ea797dd64f8fdec5f7df5","898840e876dfd21843db9f2aa6ae38ba2eab550eb780ff62b894b9fbfebfae6b","0cab4d7d4edc40cd3af9eea7c3ed6d1016910c0954c49c4297e479bf3822a625","1b952304137851e45bc009785de89ada562d9376177c97e37702e39e60c2f1ff","785e5be57d4f20f290a20e7b0c6263f6c57fd6e51283050756cef07d6d651c68","44b8b584a338b190a59f4f6929d072431950c7bd92ec2694821c11bce180c8a5","164deb2409ac5f4da3cd139dbcee7f7d66753d90363a4d7e2db8d8874f272270",{"version":"ffc62d73b4fa10ca8c59f8802df88efefe447025730a24ee977b60adedc5bf37","affectsGlobalScope":true},{"version":"ab294c4b7279318ee2a8fdf681305457ecc05970c94108d304933f18823eeac1","affectsGlobalScope":true},"ad08154d9602429522cac965a715fde27d421d69b24756c5d291877dda75353e","5bc85813bfcb6907cc3a960fec8734a29d7884e0e372515147720c5991b8bc22","812b25f798033c202baedf386a1ccc41f9191b122f089bffd10fdccce99fba11","993325544790073f77e945bee046d53988c0bc3ac5695c9cf8098166feb82661",{"version":"75dd741ca6a6c8d2437a6ca8349b64b816421dbf9fe82dd026afaba965576962","affectsGlobalScope":true},{"version":"0e08c360c9b5961ecb0537b703e253842b3ded53151ee07024148219b61a8baf","affectsGlobalScope":true},"2ce2210032ccaff7710e2abf6a722e62c54960458e73e356b6a365c93ab6ca66","92db194ef7d208d5e4b6242a3434573fd142a621ff996d84cc9dbba3553277d0","16a3080e885ed52d4017c902227a8d0d8daf723d062bec9e45627c6fdcd6699b",{"version":"0bd9543cd8fc0959c76fb8f4f5a26626c2ed62ef4be98fd857bce268066db0a2","affectsGlobalScope":true},"1ca6858a0cbcd74d7db72d7b14c5360a928d1d16748a55ecfa6bfaff8b83071b",{"version":"ab9b9a36e5284fd8d3bf2f7d5fcbc60052f25f27e4d20954782099282c60d23e","affectsGlobalScope":true},"ebf3434b09c527078aa74139ff367fffa64fea32a01d6c06fb0a69b0ecadf43e"],"root":[46],"options":{"declaration":true,"esModuleInterop":true,"module":1,"outDir":"./","strict":true,"target":2},"fileIdsList":[[47,93],[50,93],[51,56,84,93],[52,63,64,71,81,92,93],[52,53,63,71,93],[54,93],[55,56,64,72,93],[56,81,89,93],[57,59,63,71,93],[58,93],[59,60,93],[63,93],[61,63,93],[63,64,65,81,92,93],[63,64,65,78,81,84,93],[93,97],[93],[59,63,66,71,81,92,93],[63,64,66,67,71,81,89,92,93],[66,68,81,89,92,93],[47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99],[63,69,93],[70,92,93],[59,63,71,81,93],[72,93],[73,93],[50,74,93],[75,91,93,97],[76,93],[77,93],[63,78,79,93],[78,80,93,95],[51,63,81,82,83,84,93],[51,81,83,93],[81,82,93],[84,93],[85,93],[81,93],[63,87,88,93],[87,88,93],[56,71,81,89,93],[90,93],[71,91,93],[51,66,77,92,93],[56,93],[81,93,94],[93,95],[93,96],[51,56,63,65,74,81,92,93,95,97],[81,93,98],[44,45,66,68,93]],"referencedMap":[[47,1],[48,1],[50,2],[51,3],[52,4],[53,5],[54,6],[55,7],[56,8],[57,9],[58,10],[59,11],[60,11],[62,12],[61,13],[63,12],[64,14],[65,15],[49,16],[99,17],[66,18],[67,19],[68,20],[100,21],[69,22],[70,23],[71,24],[72,25],[73,26],[74,27],[75,28],[76,29],[77,30],[78,31],[79,31],[80,32],[81,33],[83,34],[82,35],[84,36],[85,37],[86,38],[87,39],[88,40],[89,41],[90,42],[91,43],[92,44],[93,45],[94,46],[95,47],[96,48],[97,49],[98,50],[45,17],[44,17],[42,17],[43,17],[9,17],[8,17],[2,17],[10,17],[11,17],[12,17],[13,17],[14,17],[15,17],[16,17],[17,17],[3,17],[4,17],[21,17],[18,17],[19,17],[20,17],[22,17],[23,17],[24,17],[5,17],[25,17],[26,17],[27,17],[28,17],[6,17],[32,17],[29,17],[30,17],[31,17],[33,17],[7,17],[34,17],[39,17],[40,17],[35,17],[36,17],[37,17],[38,17],[1,17],[41,17],[46,51]],"exportedModulesMap":[[47,1],[48,1],[50,2],[51,3],[52,4],[53,5],[54,6],[55,7],[56,8],[57,9],[58,10],[59,11],[60,11],[62,12],[61,13],[63,12],[64,14],[65,15],[49,16],[99,17],[66,18],[67,19],[68,20],[100,21],[69,22],[70,23],[71,24],[72,25],[73,26],[74,27],[75,28],[76,29],[77,30],[78,31],[79,31],[80,32],[81,33],[83,34],[82,35],[84,36],[85,37],[86,38],[87,39],[88,40],[89,41],[90,42],[91,43],[92,44],[93,45],[94,46],[95,47],[96,48],[97,49],[98,50],[45,17],[44,17],[17,17],[3,17],[4,17],[21,17],[18,17],[19,17],[20,17],[22,17],[23,17],[24,17],[5,17],[25,17],[26,17],[27,17],[28,17],[6,17],[32,17],[29,17],[30,17],[31,17],[33,17],[7,17],[34,17],[39,17],[40,17],[35,17],[36,17],[37,17],[38,17],[41,17]],"semanticDiagnosticsPerFile":[47,48,50,51,52,53,54,55,56,57,58,59,60,62,61,63,64,65,49,99,66,67,68,100,69,70,71,72,73,74,75,76,77,78,79,80,81,83,82,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,45,44,42,43,9,8,2,10,11,12,13,14,15,16,17,3,4,21,18,19,20,22,23,24,5,25,26,27,28,6,32,29,30,31,33,7,34,39,40,35,36,37,38,1,41,46]},"version":"5.1.6"}
package/package.json CHANGED
@@ -1,15 +1,26 @@
1
1
  {
2
2
  "name": "braintrust",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "SDK for integrating BrainTrust",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
7
7
  "build": "tsc",
8
+ "watch": "tsc --watch",
9
+ "docs": "npx typedoc --plugin typedoc-plugin-markdown --out ../app/pages/docs/libs/js src/index.ts --publicPath /docs/libs/js/ --githubPages false --disableSources true --hideInPageTOC true",
8
10
  "test": "jest"
9
11
  },
10
12
  "author": "",
11
13
  "license": "MIT",
12
14
  "devDependencies": {
15
+ "@types/uuid": "^9.0.2",
16
+ "typedoc": "^0.24.8",
17
+ "typedoc-plugin-markdown": "^3.15.3",
13
18
  "typescript": "^5.1.6"
19
+ },
20
+ "dependencies": {
21
+ "@types/axios": "^0.14.0",
22
+ "@types/node": "^20.4.1",
23
+ "axios": "^1.4.0",
24
+ "uuid": "^9.0.0"
14
25
  }
15
26
  }