@lmnr-ai/lmnr 0.4.10 → 0.4.11-alpha
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/dist/cli.d.mts +7 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.js +191 -0
- package/dist/cli.js.map +1 -0
- package/dist/cli.mjs +164 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/index.d.mts +33 -8
- package/dist/index.d.ts +33 -8
- package/dist/index.js +131 -38
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +130 -37
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -2
- package/src/cli.ts +86 -0
- package/src/evaluations.ts +111 -17
- package/src/index.ts +1 -1
- package/src/laminar.ts +32 -26
- package/src/types.ts +3 -0
- package/src/utils.ts +4 -0
package/dist/index.js
CHANGED
|
@@ -35,14 +35,17 @@ var require_package = __commonJS({
|
|
|
35
35
|
"package.json"(exports2, module2) {
|
|
36
36
|
module2.exports = {
|
|
37
37
|
name: "@lmnr-ai/lmnr",
|
|
38
|
-
version: "0.4.
|
|
38
|
+
version: "0.4.11-alpha",
|
|
39
39
|
description: "TypeScript SDK for Laminar AI",
|
|
40
40
|
main: "dist/index.js",
|
|
41
41
|
types: "dist/index.d.ts",
|
|
42
42
|
scripts: {
|
|
43
|
-
build: "tsup src/index.ts --format esm,cjs --dts",
|
|
43
|
+
build: "tsup src/index.ts src/cli.ts --format esm,cjs --dts",
|
|
44
44
|
test: 'echo "Error: no test specified" && exit 1'
|
|
45
45
|
},
|
|
46
|
+
bin: {
|
|
47
|
+
lmnr: "./dist/cli.js"
|
|
48
|
+
},
|
|
46
49
|
repository: {
|
|
47
50
|
type: "git",
|
|
48
51
|
url: "git+https://github.com/lmnr-ai/lmnr-ts.git"
|
|
@@ -68,6 +71,8 @@ var require_package = __commonJS({
|
|
|
68
71
|
"@langchain/core": ">=0.0.11",
|
|
69
72
|
"@pinecone-database/pinecone": ">=2.0.1",
|
|
70
73
|
"@qdrant/js-client-rest": ">=1.5.0",
|
|
74
|
+
"@types/argparse": "^2.0.16",
|
|
75
|
+
"@types/cli-progress": "^3.11.6",
|
|
71
76
|
"@types/node": ">=14.18.63",
|
|
72
77
|
"@types/semver": ">=7.5.3",
|
|
73
78
|
"@types/uuid": ">=9.0.6",
|
|
@@ -105,6 +110,9 @@ var require_package = __commonJS({
|
|
|
105
110
|
"@traceloop/instrumentation-pinecone": "^0.11.1",
|
|
106
111
|
"@traceloop/instrumentation-qdrant": "^0.11.1",
|
|
107
112
|
"@traceloop/instrumentation-vertexai": "^0.11.1",
|
|
113
|
+
argparse: "^2.0.1",
|
|
114
|
+
"cli-progress": "^3.12.0",
|
|
115
|
+
esbuild: "^0.23.1",
|
|
108
116
|
"posthog-node": ">=3.1.3",
|
|
109
117
|
uuid: ">=9.0.0"
|
|
110
118
|
}
|
|
@@ -116,8 +124,8 @@ var require_package = __commonJS({
|
|
|
116
124
|
var src_exports = {};
|
|
117
125
|
__export(src_exports, {
|
|
118
126
|
Dataset: () => Dataset,
|
|
119
|
-
Evaluation: () => Evaluation,
|
|
120
127
|
Laminar: () => Laminar,
|
|
128
|
+
evaluate: () => evaluate,
|
|
121
129
|
observe: () => observe
|
|
122
130
|
});
|
|
123
131
|
module.exports = __toCommonJS(src_exports);
|
|
@@ -661,6 +669,9 @@ var otelTraceIdToUUID = (traceId) => {
|
|
|
661
669
|
}
|
|
662
670
|
return id.replace(/^(.{8})(.{4})(.{4})(.{4})(.{12})$/, "$1-$2-$3-$4-$5");
|
|
663
671
|
};
|
|
672
|
+
function isNumber(value) {
|
|
673
|
+
return typeof value === "number";
|
|
674
|
+
}
|
|
664
675
|
|
|
665
676
|
// src/laminar.ts
|
|
666
677
|
var import_exporter_trace_otlp_grpc = require("@opentelemetry/exporter-trace-otlp-grpc");
|
|
@@ -675,9 +686,8 @@ var Laminar = class {
|
|
|
675
686
|
* If not specified, it will try to read from the LMNR_PROJECT_API_KEY environment variable.
|
|
676
687
|
* @param env - Default environment passed to `run` and `evaluateEvent` requests,
|
|
677
688
|
* unless overriden at request time. Usually, model provider keys are stored here.
|
|
678
|
-
* @param baseUrl -
|
|
679
|
-
* If not specified, defaults to https://api.lmnr.ai
|
|
680
|
-
* default setting must be http://localhost:8001.
|
|
689
|
+
* @param baseUrl - Laminar API url.
|
|
690
|
+
* If not specified, defaults to https://api.lmnr.ai.
|
|
681
691
|
* @param instrumentModules - List of modules to instrument.
|
|
682
692
|
* If not specified, all auto-instrumentable modules will be instrumented, which include
|
|
683
693
|
* LLM calls (OpenAI, Anthropic, etc), Langchain, VectorDB calls (Pinecone, Qdrant, etc).
|
|
@@ -722,7 +732,7 @@ var Laminar = class {
|
|
|
722
732
|
const metadata = new import_grpc_js.Metadata();
|
|
723
733
|
metadata.set("authorization", `Bearer ${this.projectApiKey}`);
|
|
724
734
|
const exporter = new import_exporter_trace_otlp_grpc.OTLPTraceExporter({
|
|
725
|
-
url: this.baseUrl
|
|
735
|
+
url: `${this.baseUrl}:8443`,
|
|
726
736
|
metadata
|
|
727
737
|
});
|
|
728
738
|
initialize({
|
|
@@ -926,11 +936,14 @@ var Laminar = class {
|
|
|
926
936
|
name
|
|
927
937
|
})
|
|
928
938
|
});
|
|
939
|
+
if (!response.ok) {
|
|
940
|
+
throw new Error(`Failed to create evaluation ${name}. Response: ${response.statusText}`);
|
|
941
|
+
}
|
|
929
942
|
return await response.json();
|
|
930
943
|
}
|
|
931
|
-
static async postEvaluationResults(
|
|
944
|
+
static async postEvaluationResults(evaluationId, data) {
|
|
932
945
|
const body = JSON.stringify({
|
|
933
|
-
|
|
946
|
+
evaluationId,
|
|
934
947
|
points: data
|
|
935
948
|
});
|
|
936
949
|
const headers = this.getHeaders();
|
|
@@ -950,26 +963,27 @@ var Laminar = class {
|
|
|
950
963
|
}
|
|
951
964
|
;
|
|
952
965
|
}
|
|
953
|
-
|
|
966
|
+
/**
|
|
967
|
+
* Updates the status of an evaluation. Returns the updated evaluation object.
|
|
968
|
+
*
|
|
969
|
+
* @param evaluationId - The ID of the evaluation to update.
|
|
970
|
+
* @param status - The status to set for the evaluation.
|
|
971
|
+
*/
|
|
972
|
+
static async updateEvaluationStatus(evaluationId, status) {
|
|
954
973
|
const body = JSON.stringify({
|
|
955
|
-
name: evaluationName,
|
|
956
974
|
status
|
|
957
975
|
});
|
|
958
976
|
const headers = this.getHeaders();
|
|
959
|
-
const url = `${this.baseUrl}/v1/evaluations`;
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
console.error("Failed to update evaluation status. Response: ");
|
|
968
|
-
response.text().then((text) => console.error(text));
|
|
969
|
-
}
|
|
970
|
-
} catch (error) {
|
|
971
|
-
console.error("Failed to update evaluation status. Error: ", error);
|
|
977
|
+
const url = `${this.baseUrl}/v1/evaluations/${evaluationId}`;
|
|
978
|
+
const response = await fetch(url, {
|
|
979
|
+
method: "POST",
|
|
980
|
+
headers,
|
|
981
|
+
body
|
|
982
|
+
});
|
|
983
|
+
if (!response.ok) {
|
|
984
|
+
throw new Error(`Failed to update evaluation status ${evaluationId}. Response: ${await response.text()}`);
|
|
972
985
|
}
|
|
986
|
+
return await response.json();
|
|
973
987
|
}
|
|
974
988
|
static getHeaders() {
|
|
975
989
|
return {
|
|
@@ -978,12 +992,16 @@ var Laminar = class {
|
|
|
978
992
|
};
|
|
979
993
|
}
|
|
980
994
|
};
|
|
981
|
-
Laminar.baseUrl = "https://api.lmnr.ai
|
|
995
|
+
Laminar.baseUrl = "https://api.lmnr.ai";
|
|
982
996
|
Laminar.env = {};
|
|
983
997
|
Laminar.isInitialized = false;
|
|
984
998
|
|
|
985
999
|
// src/evaluations.ts
|
|
1000
|
+
var import_cli_progress = __toESM(require("cli-progress"));
|
|
986
1001
|
var DEFAULT_BATCH_SIZE = 5;
|
|
1002
|
+
var getEvaluationUrl = (projectId, evaluationId) => {
|
|
1003
|
+
return `https://www.lmnr.ai/project/${projectId}/evaluations/${evaluationId}`;
|
|
1004
|
+
};
|
|
987
1005
|
var Dataset = class {
|
|
988
1006
|
slice(start, end) {
|
|
989
1007
|
const result = [];
|
|
@@ -993,6 +1011,41 @@ var Dataset = class {
|
|
|
993
1011
|
return result;
|
|
994
1012
|
}
|
|
995
1013
|
};
|
|
1014
|
+
var EvaluationReporter = class {
|
|
1015
|
+
constructor() {
|
|
1016
|
+
this.cliProgress = new import_cli_progress.default.SingleBar({}, import_cli_progress.default.Presets.shades_classic);
|
|
1017
|
+
}
|
|
1018
|
+
start({ name, projectId, id, length }) {
|
|
1019
|
+
process.stdout.write(`
|
|
1020
|
+
Running evaluation ${name}...
|
|
1021
|
+
|
|
1022
|
+
`);
|
|
1023
|
+
process.stdout.write(`Check progress and results at ${getEvaluationUrl(projectId, id)}
|
|
1024
|
+
|
|
1025
|
+
`);
|
|
1026
|
+
this.cliProgress.start(length, 0);
|
|
1027
|
+
}
|
|
1028
|
+
update(batchLength) {
|
|
1029
|
+
this.cliProgress.update(batchLength);
|
|
1030
|
+
}
|
|
1031
|
+
// Call either error or stop, not both
|
|
1032
|
+
stopWithError(error) {
|
|
1033
|
+
this.cliProgress.stop();
|
|
1034
|
+
process.stdout.write(`
|
|
1035
|
+
Error: ${error.message}
|
|
1036
|
+
`);
|
|
1037
|
+
}
|
|
1038
|
+
// Call either error or stop, not both
|
|
1039
|
+
stop(averageScores) {
|
|
1040
|
+
this.cliProgress.stop();
|
|
1041
|
+
process.stdout.write("\nAverage scores:\n");
|
|
1042
|
+
for (const key in averageScores) {
|
|
1043
|
+
process.stdout.write(`${key}: ${averageScores[key]}
|
|
1044
|
+
`);
|
|
1045
|
+
}
|
|
1046
|
+
process.stdout.write("\n");
|
|
1047
|
+
}
|
|
1048
|
+
};
|
|
996
1049
|
var Evaluation = class {
|
|
997
1050
|
/**
|
|
998
1051
|
* Create a new evaluation and prepare data.
|
|
@@ -1000,6 +1053,7 @@ var Evaluation = class {
|
|
|
1000
1053
|
* @param props.data List of data points to evaluate. `data` is the input to the executor function, `target` is the input to the evaluator function.
|
|
1001
1054
|
* @param props.executor The executor function. Takes the data point + any additional arguments and returns the output to evaluate.
|
|
1002
1055
|
* @param props.evaluators List of evaluator functions. Each evaluator function takes the output of the executor and the target data, and returns.
|
|
1056
|
+
* @param props.config Optional override configurations for the evaluator.
|
|
1003
1057
|
*/
|
|
1004
1058
|
constructor(name, {
|
|
1005
1059
|
data,
|
|
@@ -1007,9 +1061,11 @@ var Evaluation = class {
|
|
|
1007
1061
|
evaluators,
|
|
1008
1062
|
config
|
|
1009
1063
|
}) {
|
|
1064
|
+
this.isFinished = false;
|
|
1010
1065
|
this.batchSize = DEFAULT_BATCH_SIZE;
|
|
1011
1066
|
var _a;
|
|
1012
1067
|
this.name = name;
|
|
1068
|
+
this.progressReporter = new EvaluationReporter();
|
|
1013
1069
|
this.data = data;
|
|
1014
1070
|
this.executor = executor;
|
|
1015
1071
|
this.evaluators = Object.fromEntries(evaluators.map((e, i) => [e.name.length > 0 ? e.name : `evaluator_${i + 1}`, e]));
|
|
@@ -1022,26 +1078,42 @@ var Evaluation = class {
|
|
|
1022
1078
|
/**
|
|
1023
1079
|
* Runs the evaluation.
|
|
1024
1080
|
*
|
|
1025
|
-
* Creates a new evaluation
|
|
1081
|
+
* Creates a new evaluation.
|
|
1026
1082
|
* Evaluates data points in batches of `batchSize`. The executor function is called on each data point
|
|
1027
1083
|
* to get the output, and then evaluate it by each evaluator function.
|
|
1028
1084
|
*/
|
|
1029
1085
|
async run() {
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1086
|
+
if (this.isFinished) {
|
|
1087
|
+
throw new Error("Evaluation is already finished");
|
|
1088
|
+
}
|
|
1089
|
+
const evaluation = await Laminar.createEvaluation(this.name);
|
|
1090
|
+
this.progressReporter.start({ name: evaluation.name, projectId: evaluation.projectId, id: evaluation.id, length: this.getLength() });
|
|
1091
|
+
try {
|
|
1092
|
+
await this.evaluateInBatches(evaluation);
|
|
1093
|
+
} catch (e) {
|
|
1094
|
+
await Laminar.updateEvaluationStatus(evaluation.id, "Error");
|
|
1095
|
+
this.progressReporter.stopWithError(e);
|
|
1096
|
+
this.isFinished = true;
|
|
1097
|
+
}
|
|
1098
|
+
if (!this.isFinished) {
|
|
1099
|
+
const updatedEvaluation = await Laminar.updateEvaluationStatus(evaluation.id, "Finished");
|
|
1100
|
+
this.progressReporter.stop(updatedEvaluation.averageScores);
|
|
1101
|
+
this.isFinished = true;
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
// TODO: Calculate duration of the evaluation and add it to the summary
|
|
1105
|
+
async evaluateInBatches(evaluation) {
|
|
1106
|
+
for (let i = 0; i < this.getLength(); i += this.batchSize) {
|
|
1033
1107
|
const batch = this.data.slice(i, i + this.batchSize);
|
|
1034
1108
|
try {
|
|
1035
|
-
await this.evaluateBatch(batch);
|
|
1109
|
+
const results = await this.evaluateBatch(batch);
|
|
1110
|
+
await Laminar.postEvaluationResults(evaluation.id, results);
|
|
1036
1111
|
} catch (e) {
|
|
1037
1112
|
console.error(`Error evaluating batch: ${e}`);
|
|
1113
|
+
} finally {
|
|
1114
|
+
this.progressReporter.update(batch.length);
|
|
1038
1115
|
}
|
|
1039
1116
|
}
|
|
1040
|
-
try {
|
|
1041
|
-
await Laminar.updateEvaluationStatus(response.name, "Finished");
|
|
1042
|
-
} catch (e) {
|
|
1043
|
-
console.error(`Error updating evaluation status: ${e}`);
|
|
1044
|
-
}
|
|
1045
1117
|
}
|
|
1046
1118
|
async evaluateBatch(batch) {
|
|
1047
1119
|
const batchPromises = batch.map(async (datapoint) => {
|
|
@@ -1051,7 +1123,10 @@ var Evaluation = class {
|
|
|
1051
1123
|
for (const evaluatorName of this.evaluatorNames) {
|
|
1052
1124
|
const evaluator = this.evaluators[evaluatorName];
|
|
1053
1125
|
const value = await evaluator(output, target);
|
|
1054
|
-
if (
|
|
1126
|
+
if (isNumber(value)) {
|
|
1127
|
+
if (isNaN(value)) {
|
|
1128
|
+
throw new Error(`Evaluator ${evaluatorName} returned NaN`);
|
|
1129
|
+
}
|
|
1055
1130
|
scores[evaluatorName] = value;
|
|
1056
1131
|
} else {
|
|
1057
1132
|
scores = { ...scores, ...value };
|
|
@@ -1065,9 +1140,27 @@ var Evaluation = class {
|
|
|
1065
1140
|
};
|
|
1066
1141
|
});
|
|
1067
1142
|
const results = await Promise.all(batchPromises);
|
|
1068
|
-
return
|
|
1143
|
+
return results;
|
|
1144
|
+
}
|
|
1145
|
+
getLength() {
|
|
1146
|
+
return this.data instanceof Dataset ? this.data.size() : this.data.length;
|
|
1069
1147
|
}
|
|
1070
1148
|
};
|
|
1149
|
+
function evaluate(name, {
|
|
1150
|
+
data,
|
|
1151
|
+
executor,
|
|
1152
|
+
evaluators,
|
|
1153
|
+
config
|
|
1154
|
+
}) {
|
|
1155
|
+
(async () => {
|
|
1156
|
+
const evaluation = new Evaluation(name, { data, executor, evaluators, config });
|
|
1157
|
+
if (globalThis._set_global_evaluation) {
|
|
1158
|
+
globalThis._evaluation = evaluation;
|
|
1159
|
+
} else {
|
|
1160
|
+
await evaluation.run();
|
|
1161
|
+
}
|
|
1162
|
+
})();
|
|
1163
|
+
}
|
|
1071
1164
|
|
|
1072
1165
|
// src/decorators.ts
|
|
1073
1166
|
async function observe({
|
|
@@ -1087,8 +1180,8 @@ async function observe({
|
|
|
1087
1180
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1088
1181
|
0 && (module.exports = {
|
|
1089
1182
|
Dataset,
|
|
1090
|
-
Evaluation,
|
|
1091
1183
|
Laminar,
|
|
1184
|
+
evaluate,
|
|
1092
1185
|
observe
|
|
1093
1186
|
});
|
|
1094
1187
|
//# sourceMappingURL=index.js.map
|