@langinsight/ai-sdk 0.0.1 → 0.0.3
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 +43 -9
- package/dist/index.cjs +76 -42
- package/dist/index.d.cts +138 -6
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @langinsight/ai-sdk
|
|
2
2
|
|
|
3
|
-
LangInsight callback handler for Vercel AI SDK.
|
|
3
|
+
LangInsight callback handler for Vercel AI SDK. Sends input/output traces to LangInsight in parallel and supports feedback (thumbs up/down) via `score()`.
|
|
4
4
|
|
|
5
5
|
## Usage
|
|
6
6
|
|
|
@@ -17,6 +17,10 @@ const handler = new LangInsight.CallbackHandler({
|
|
|
17
17
|
apiKey: LANGINSIGHT_API_KEY,
|
|
18
18
|
endpoint: LANGINSIGHT_ENDPOINT,
|
|
19
19
|
metadata: { userId: "admin", sessionId: "admin" },
|
|
20
|
+
onSuccess: (trace) => {
|
|
21
|
+
// traceId の取得・DB永続化はここで
|
|
22
|
+
console.log("Trace sent:", trace.id);
|
|
23
|
+
},
|
|
20
24
|
});
|
|
21
25
|
|
|
22
26
|
const prompt = "Hello!";
|
|
@@ -26,7 +30,6 @@ const result = await generateText({
|
|
|
26
30
|
prompt,
|
|
27
31
|
});
|
|
28
32
|
|
|
29
|
-
// Report the result to LangInsight
|
|
30
33
|
await handler.report(result, { input: prompt });
|
|
31
34
|
```
|
|
32
35
|
|
|
@@ -43,6 +46,8 @@ const handler = new LangInsight.CallbackHandler({
|
|
|
43
46
|
apiKey: LANGINSIGHT_API_KEY,
|
|
44
47
|
endpoint: LANGINSIGHT_ENDPOINT,
|
|
45
48
|
metadata: { userId: "admin", sessionId: "admin" },
|
|
49
|
+
onSuccess: (trace) => console.log("Trace sent:", trace.id),
|
|
50
|
+
onFailure: (err) => console.error("Trace failed:", err),
|
|
46
51
|
});
|
|
47
52
|
|
|
48
53
|
const prompt = "Hello!";
|
|
@@ -50,7 +55,6 @@ const prompt = "Hello!";
|
|
|
50
55
|
const result = streamText({
|
|
51
56
|
model: openai("gpt-4o"),
|
|
52
57
|
prompt,
|
|
53
|
-
// Specify callback handler as onFinish
|
|
54
58
|
onFinish: handler.onFinish({ input: prompt }),
|
|
55
59
|
});
|
|
56
60
|
|
|
@@ -59,11 +63,41 @@ for await (const chunk of result.textStream) {
|
|
|
59
63
|
}
|
|
60
64
|
```
|
|
61
65
|
|
|
66
|
+
### Feedback (score)
|
|
67
|
+
|
|
68
|
+
Trace ID の取得や DB 永続化は `onSuccess` コールバックで受け取った `trace` を使って行い、その `trace.id` を `score()` に渡してフィードバックを送信する。
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
let lastOutputTraceId: string | undefined;
|
|
72
|
+
|
|
73
|
+
const handler = new LangInsight.CallbackHandler({
|
|
74
|
+
...options,
|
|
75
|
+
onSuccess: (trace) => {
|
|
76
|
+
lastOutputTraceId = trace.id; // DB 永続化などもここで
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// report() または onFinish の後
|
|
81
|
+
await handler.score({ traceId: lastOutputTraceId!, value: 1 }); // 👍
|
|
82
|
+
await handler.score({ traceId: lastOutputTraceId!, value: -1 }); // 👎
|
|
83
|
+
```
|
|
84
|
+
|
|
62
85
|
## Options
|
|
63
86
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
87
|
+
| Option | Type | Required | Description |
|
|
88
|
+
| ----------- | --------------------------------- | -------- | --------------------------------------------------------------------------- |
|
|
89
|
+
| `apiKey` | `string` | Yes | LangInsight API key |
|
|
90
|
+
| `endpoint` | `string` | Yes | LangInsight API endpoint (e.g. `https://api.langinsight.example.com`) |
|
|
91
|
+
| `metadata` | `object` | Yes | Metadata attached to traces |
|
|
92
|
+
| `metadata.userId` | `string` | Yes | User ID |
|
|
93
|
+
| `metadata.sessionId`| `string` | Yes | Session ID (e.g. conversation id) |
|
|
94
|
+
| `metadata.modelName` | `string` | No | Model name (defaults to result response when not set) |
|
|
95
|
+
| `metadata.*` | `any` | No | Additional key-value pairs |
|
|
96
|
+
| `onSuccess` | `(trace: Trace) => void` | No | Callback invoked with the output trace when trace submission succeeds. Use this to get `trace.id` and persist to DB. |
|
|
97
|
+
| `onFailure` | `(error: Error) => void` | No | Callback invoked with the error when trace submission fails |
|
|
98
|
+
|
|
99
|
+
## API
|
|
100
|
+
|
|
101
|
+
- **`report(result, { input })`** — Sends traces for a `generateText` result. Trace is passed to `onSuccess` on success.
|
|
102
|
+
- **`onFinish({ input })`** — Returns a function suitable for `streamText`’s `onFinish`. Sends traces when the stream finishes; trace is passed to `onSuccess`.
|
|
103
|
+
- **`score({ traceId, value })`** — Submits feedback (1 = thumbs up, -1 = thumbs down) for the given trace. Use the `trace.id` received in `onSuccess` as `traceId`.
|
package/dist/index.cjs
CHANGED
|
@@ -347,16 +347,17 @@ var LangInsight;
|
|
|
347
347
|
}
|
|
348
348
|
/**
|
|
349
349
|
* generateText の結果を送信
|
|
350
|
+
* traceId の取得・DB永続化は onSuccess コールバックで trace を受け取り行う。
|
|
350
351
|
*
|
|
351
352
|
* @example
|
|
352
353
|
* ```ts
|
|
353
|
-
* const handler = new LangInsight.CallbackHandler(
|
|
354
|
-
*
|
|
355
|
-
*
|
|
356
|
-
*
|
|
357
|
-
*
|
|
354
|
+
* const handler = new LangInsight.CallbackHandler({
|
|
355
|
+
* ...options,
|
|
356
|
+
* onSuccess: (trace) => {
|
|
357
|
+
* saveTraceToDb(trace); // traceId = trace.id
|
|
358
|
+
* },
|
|
358
359
|
* });
|
|
359
|
-
*
|
|
360
|
+
* const result = await generateText({ model: openai("gpt-4o"), prompt: "Hello!" });
|
|
360
361
|
* await handler.report(result, { input: "Hello!" });
|
|
361
362
|
* ```
|
|
362
363
|
*/
|
|
@@ -367,51 +368,84 @@ var LangInsight;
|
|
|
367
368
|
result
|
|
368
369
|
});
|
|
369
370
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
371
|
+
/**
|
|
372
|
+
* フィードバック(👍/👎)を送信
|
|
373
|
+
* traceId は onSuccess コールバックで受け取った trace.id を使用する。
|
|
374
|
+
*
|
|
375
|
+
* @example
|
|
376
|
+
* ```ts
|
|
377
|
+
* onSuccess: (trace) => { lastOutputTraceId = trace.id; },
|
|
378
|
+
* // ...
|
|
379
|
+
* await handler.score({ traceId: lastOutputTraceId, value: 1 }); // 👍
|
|
380
|
+
* ```
|
|
381
|
+
*/
|
|
382
|
+
async score(params) {
|
|
383
|
+
const { userId, sessionId } = this.options.metadata;
|
|
384
|
+
const res = await this.client.feedbacks.external.$post({
|
|
377
385
|
header: {
|
|
378
386
|
"x-api-key": this.options.apiKey
|
|
379
387
|
},
|
|
380
388
|
json: {
|
|
381
|
-
|
|
389
|
+
traceId: params.traceId,
|
|
382
390
|
sessionId,
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
content: input,
|
|
386
|
-
type: "input",
|
|
387
|
-
meta: { ...rest },
|
|
388
|
-
startedAt: startedAt.toISOString(),
|
|
389
|
-
endedAt: endedAt.toISOString()
|
|
391
|
+
userId,
|
|
392
|
+
value: params.value
|
|
390
393
|
}
|
|
391
394
|
});
|
|
392
|
-
if (!
|
|
393
|
-
console.error(await
|
|
394
|
-
return;
|
|
395
|
+
if (!res.ok) {
|
|
396
|
+
console.error(await res.text());
|
|
395
397
|
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
398
|
+
}
|
|
399
|
+
async sendTraces(params) {
|
|
400
|
+
const { input, result } = params;
|
|
401
|
+
const { userId, sessionId, ...rest } = this.options.metadata;
|
|
402
|
+
const model = result.response.modelId ?? "unknown";
|
|
403
|
+
const startedAt = result.response.timestamp;
|
|
404
|
+
const endedAt = /* @__PURE__ */ new Date();
|
|
405
|
+
try {
|
|
406
|
+
const res = await Promise.all([
|
|
407
|
+
this.client.traces.external.$post({
|
|
408
|
+
header: {
|
|
409
|
+
"x-api-key": this.options.apiKey
|
|
410
|
+
},
|
|
411
|
+
json: {
|
|
412
|
+
userId,
|
|
413
|
+
sessionId,
|
|
414
|
+
model,
|
|
415
|
+
token: result.usage.inputTokens ?? 0,
|
|
416
|
+
content: input,
|
|
417
|
+
type: "input",
|
|
418
|
+
meta: { ...rest },
|
|
419
|
+
startedAt: startedAt.toISOString(),
|
|
420
|
+
endedAt: endedAt.toISOString()
|
|
421
|
+
}
|
|
422
|
+
}),
|
|
423
|
+
this.client.traces.external.$post({
|
|
424
|
+
header: {
|
|
425
|
+
"x-api-key": this.options.apiKey
|
|
426
|
+
},
|
|
427
|
+
json: {
|
|
428
|
+
userId,
|
|
429
|
+
sessionId,
|
|
430
|
+
model,
|
|
431
|
+
token: result.usage.outputTokens ?? 0,
|
|
432
|
+
content: result.text,
|
|
433
|
+
type: "output",
|
|
434
|
+
meta: { ...rest },
|
|
435
|
+
startedAt: startedAt.toISOString(),
|
|
436
|
+
endedAt: endedAt.toISOString()
|
|
437
|
+
}
|
|
438
|
+
})
|
|
439
|
+
]);
|
|
440
|
+
if (!res.every((r) => r.ok)) {
|
|
441
|
+
console.error(await Promise.all(res.map((r) => r.text())));
|
|
442
|
+
throw new Error("Failed to send traces");
|
|
410
443
|
}
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
444
|
+
const outputTrace = await res[1].json();
|
|
445
|
+
this.options.onSuccess?.(outputTrace);
|
|
446
|
+
} catch (error) {
|
|
447
|
+
console.error(error);
|
|
448
|
+
this.options.onFailure?.(error instanceof Error ? error : new Error(String(error)));
|
|
415
449
|
}
|
|
416
450
|
}
|
|
417
451
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,118 @@
|
|
|
1
1
|
import { StepResult, ToolSet, LanguageModelUsage, GenerateTextResult } from 'ai';
|
|
2
|
+
import { InferOutput, ObjectSchema, SchemaWithPipe, StringSchema, UuidAction, NumberSchema, PicklistSchema, RecordSchema, AnySchema, CustomSchema, StandardProps, UnknownDataset, Config, BaseIssue, OutputDataset, ObjectIssue, NumberIssue, StringIssue, PicklistIssue, RecordIssue, CustomIssue } from 'valibot';
|
|
3
|
+
|
|
4
|
+
declare const vTraceEntity: ObjectSchema<{
|
|
5
|
+
readonly id: SchemaWithPipe<readonly [StringSchema<undefined>, UuidAction<string, undefined>]>;
|
|
6
|
+
readonly userId: StringSchema<undefined>;
|
|
7
|
+
readonly sessionId: StringSchema<undefined>;
|
|
8
|
+
readonly model: StringSchema<undefined>;
|
|
9
|
+
readonly token: NumberSchema<undefined>;
|
|
10
|
+
readonly content: StringSchema<undefined>;
|
|
11
|
+
readonly type: PicklistSchema<["input", "output", "error"], undefined>;
|
|
12
|
+
readonly meta: RecordSchema<StringSchema<undefined>, AnySchema, undefined>;
|
|
13
|
+
readonly createdAt: SchemaWithPipe<readonly [CustomSchema<unknown, undefined>, StringSchema<undefined>]>;
|
|
14
|
+
readonly startedAt: SchemaWithPipe<readonly [CustomSchema<unknown, undefined>, StringSchema<undefined>]>;
|
|
15
|
+
readonly endedAt: SchemaWithPipe<readonly [CustomSchema<unknown, undefined>, StringSchema<undefined>]>;
|
|
16
|
+
}, undefined> & {
|
|
17
|
+
create: Omit<ObjectSchema<{
|
|
18
|
+
readonly id: SchemaWithPipe<readonly [StringSchema<undefined>, UuidAction<string, undefined>]>;
|
|
19
|
+
readonly userId: StringSchema<undefined>;
|
|
20
|
+
readonly sessionId: StringSchema<undefined>;
|
|
21
|
+
readonly model: StringSchema<undefined>;
|
|
22
|
+
readonly token: NumberSchema<undefined>;
|
|
23
|
+
readonly content: StringSchema<undefined>;
|
|
24
|
+
readonly type: PicklistSchema<["input", "output", "error"], undefined>;
|
|
25
|
+
readonly meta: RecordSchema<StringSchema<undefined>, AnySchema, undefined>;
|
|
26
|
+
readonly createdAt: SchemaWithPipe<readonly [CustomSchema<unknown, undefined>, StringSchema<undefined>]>;
|
|
27
|
+
readonly startedAt: SchemaWithPipe<readonly [CustomSchema<unknown, undefined>, StringSchema<undefined>]>;
|
|
28
|
+
readonly endedAt: SchemaWithPipe<readonly [CustomSchema<unknown, undefined>, StringSchema<undefined>]>;
|
|
29
|
+
}, undefined>, "~types" | "~run" | "~standard" | "entries"> & {
|
|
30
|
+
readonly entries: Omit<{
|
|
31
|
+
readonly id: SchemaWithPipe<readonly [StringSchema<undefined>, UuidAction<string, undefined>]>;
|
|
32
|
+
readonly userId: StringSchema<undefined>;
|
|
33
|
+
readonly sessionId: StringSchema<undefined>;
|
|
34
|
+
readonly model: StringSchema<undefined>;
|
|
35
|
+
readonly token: NumberSchema<undefined>;
|
|
36
|
+
readonly content: StringSchema<undefined>;
|
|
37
|
+
readonly type: PicklistSchema<["input", "output", "error"], undefined>;
|
|
38
|
+
readonly meta: RecordSchema<StringSchema<undefined>, AnySchema, undefined>;
|
|
39
|
+
readonly createdAt: SchemaWithPipe<readonly [CustomSchema<unknown, undefined>, StringSchema<undefined>]>;
|
|
40
|
+
readonly startedAt: SchemaWithPipe<readonly [CustomSchema<unknown, undefined>, StringSchema<undefined>]>;
|
|
41
|
+
readonly endedAt: SchemaWithPipe<readonly [CustomSchema<unknown, undefined>, StringSchema<undefined>]>;
|
|
42
|
+
}, "id" | "createdAt">;
|
|
43
|
+
readonly "~standard": StandardProps<{
|
|
44
|
+
type: "output" | "input" | "error";
|
|
45
|
+
token: number;
|
|
46
|
+
content: string;
|
|
47
|
+
userId: string;
|
|
48
|
+
model: string;
|
|
49
|
+
meta: {
|
|
50
|
+
[x: string]: any;
|
|
51
|
+
};
|
|
52
|
+
sessionId: string;
|
|
53
|
+
startedAt: unknown;
|
|
54
|
+
endedAt: unknown;
|
|
55
|
+
}, {
|
|
56
|
+
type: "output" | "input" | "error";
|
|
57
|
+
token: number;
|
|
58
|
+
content: string;
|
|
59
|
+
userId: string;
|
|
60
|
+
model: string;
|
|
61
|
+
meta: {
|
|
62
|
+
[x: string]: any;
|
|
63
|
+
};
|
|
64
|
+
sessionId: string;
|
|
65
|
+
startedAt: string;
|
|
66
|
+
endedAt: string;
|
|
67
|
+
}>;
|
|
68
|
+
readonly "~run": (dataset: UnknownDataset, config: Config<BaseIssue<unknown>>) => OutputDataset<{
|
|
69
|
+
type: "output" | "input" | "error";
|
|
70
|
+
token: number;
|
|
71
|
+
content: string;
|
|
72
|
+
userId: string;
|
|
73
|
+
model: string;
|
|
74
|
+
meta: {
|
|
75
|
+
[x: string]: any;
|
|
76
|
+
};
|
|
77
|
+
sessionId: string;
|
|
78
|
+
startedAt: string;
|
|
79
|
+
endedAt: string;
|
|
80
|
+
}, ObjectIssue | NumberIssue | StringIssue | PicklistIssue | RecordIssue | CustomIssue>;
|
|
81
|
+
readonly "~types"?: {
|
|
82
|
+
readonly input: {
|
|
83
|
+
type: "output" | "input" | "error";
|
|
84
|
+
token: number;
|
|
85
|
+
content: string;
|
|
86
|
+
userId: string;
|
|
87
|
+
model: string;
|
|
88
|
+
meta: {
|
|
89
|
+
[x: string]: any;
|
|
90
|
+
};
|
|
91
|
+
sessionId: string;
|
|
92
|
+
startedAt: unknown;
|
|
93
|
+
endedAt: unknown;
|
|
94
|
+
};
|
|
95
|
+
readonly output: {
|
|
96
|
+
type: "output" | "input" | "error";
|
|
97
|
+
token: number;
|
|
98
|
+
content: string;
|
|
99
|
+
userId: string;
|
|
100
|
+
model: string;
|
|
101
|
+
meta: {
|
|
102
|
+
[x: string]: any;
|
|
103
|
+
};
|
|
104
|
+
sessionId: string;
|
|
105
|
+
startedAt: string;
|
|
106
|
+
endedAt: string;
|
|
107
|
+
};
|
|
108
|
+
readonly issue: ObjectIssue | NumberIssue | StringIssue | PicklistIssue | RecordIssue | CustomIssue;
|
|
109
|
+
} | undefined;
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
type TraceEntity = InferOutput<typeof vTraceEntity>;
|
|
113
|
+
declare namespace TraceEntity {
|
|
114
|
+
type Create = InferOutput<typeof vTraceEntity.create>;
|
|
115
|
+
}
|
|
2
116
|
|
|
3
117
|
declare namespace LangInsight {
|
|
4
118
|
interface Options {
|
|
@@ -9,6 +123,8 @@ declare namespace LangInsight {
|
|
|
9
123
|
sessionId: string;
|
|
10
124
|
[key: string]: any;
|
|
11
125
|
};
|
|
126
|
+
onSuccess?: (trace: TraceEntity) => void;
|
|
127
|
+
onFailure?: (error: Error) => void;
|
|
12
128
|
}
|
|
13
129
|
class CallbackHandler {
|
|
14
130
|
private readonly options;
|
|
@@ -36,22 +152,38 @@ declare namespace LangInsight {
|
|
|
36
152
|
}) => Promise<void>;
|
|
37
153
|
/**
|
|
38
154
|
* generateText の結果を送信
|
|
155
|
+
* traceId の取得・DB永続化は onSuccess コールバックで trace を受け取り行う。
|
|
39
156
|
*
|
|
40
157
|
* @example
|
|
41
158
|
* ```ts
|
|
42
|
-
* const handler = new LangInsight.CallbackHandler(
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
159
|
+
* const handler = new LangInsight.CallbackHandler({
|
|
160
|
+
* ...options,
|
|
161
|
+
* onSuccess: (trace) => {
|
|
162
|
+
* saveTraceToDb(trace); // traceId = trace.id
|
|
163
|
+
* },
|
|
47
164
|
* });
|
|
48
|
-
*
|
|
165
|
+
* const result = await generateText({ model: openai("gpt-4o"), prompt: "Hello!" });
|
|
49
166
|
* await handler.report(result, { input: "Hello!" });
|
|
50
167
|
* ```
|
|
51
168
|
*/
|
|
52
169
|
report(result: GenerateTextResult<ToolSet, any>, params: {
|
|
53
170
|
input: string;
|
|
54
171
|
}): Promise<void>;
|
|
172
|
+
/**
|
|
173
|
+
* フィードバック(👍/👎)を送信
|
|
174
|
+
* traceId は onSuccess コールバックで受け取った trace.id を使用する。
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* ```ts
|
|
178
|
+
* onSuccess: (trace) => { lastOutputTraceId = trace.id; },
|
|
179
|
+
* // ...
|
|
180
|
+
* await handler.score({ traceId: lastOutputTraceId, value: 1 }); // 👍
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
score(params: {
|
|
184
|
+
traceId: string;
|
|
185
|
+
value: 1 | -1;
|
|
186
|
+
}): Promise<void>;
|
|
55
187
|
private sendTraces;
|
|
56
188
|
}
|
|
57
189
|
}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@langinsight/ai-sdk",
|
|
3
3
|
"module": "dist/index.js",
|
|
4
4
|
"types": "dist/index.d.ts",
|
|
5
|
-
"version": "0.0.
|
|
5
|
+
"version": "0.0.3",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
8
8
|
},
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@types/bun": "1.3.8",
|
|
26
|
-
"ai": "^6.0.
|
|
26
|
+
"ai": "^6.0.77",
|
|
27
27
|
"tsup": "^8.5.1",
|
|
28
28
|
"typescript": "^5.9.3"
|
|
29
29
|
}
|