@hebo-ai/gateway 0.5.1 → 0.5.2
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/package.json
CHANGED
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
getChatRequestAttributes,
|
|
37
37
|
getChatResponseAttributes,
|
|
38
38
|
} from "./otel";
|
|
39
|
-
import { ChatCompletionsBodySchema } from "./schema";
|
|
39
|
+
import { ChatCompletionsBodySchema, type ChatCompletionsBody } from "./schema";
|
|
40
40
|
|
|
41
41
|
export const chatCompletions = (config: GatewayConfig): Endpoint => {
|
|
42
42
|
const hooks = config.hooks;
|
|
@@ -57,6 +57,7 @@ export const chatCompletions = (config: GatewayConfig): Endpoint => {
|
|
|
57
57
|
} catch {
|
|
58
58
|
throw new GatewayError("Invalid JSON", 400);
|
|
59
59
|
}
|
|
60
|
+
logger.trace({ requestId: ctx.requestId, body: ctx.body }, "[chat] ChatCompletionsBody");
|
|
60
61
|
addSpanEvent("hebo.request.deserialized");
|
|
61
62
|
|
|
62
63
|
const parsed = ChatCompletionsBodySchema.safeParse(ctx.body);
|
|
@@ -68,7 +69,8 @@ export const chatCompletions = (config: GatewayConfig): Endpoint => {
|
|
|
68
69
|
addSpanEvent("hebo.request.parsed");
|
|
69
70
|
|
|
70
71
|
if (hooks?.before) {
|
|
71
|
-
ctx.body =
|
|
72
|
+
ctx.body =
|
|
73
|
+
((await hooks.before(ctx as BeforeHookContext)) as ChatCompletionsBody) ?? ctx.body;
|
|
72
74
|
addSpanEvent("hebo.hooks.before.completed");
|
|
73
75
|
}
|
|
74
76
|
|
|
@@ -110,7 +112,7 @@ export const chatCompletions = (config: GatewayConfig): Endpoint => {
|
|
|
110
112
|
"[chat] AI SDK options",
|
|
111
113
|
);
|
|
112
114
|
addSpanEvent("hebo.options.prepared");
|
|
113
|
-
setSpanAttributes(getChatRequestAttributes(
|
|
115
|
+
setSpanAttributes(getChatRequestAttributes(ctx.body, genAiSignalLevel));
|
|
114
116
|
|
|
115
117
|
// Build middleware chain (model -> forward params -> provider).
|
|
116
118
|
const languageModelWithMiddleware = wrapLanguageModel({
|
|
@@ -138,6 +140,10 @@ export const chatCompletions = (config: GatewayConfig): Endpoint => {
|
|
|
138
140
|
res as unknown as GenerateTextResult<ToolSet, Output.Output>,
|
|
139
141
|
ctx.resolvedModelId!,
|
|
140
142
|
);
|
|
143
|
+
logger.trace(
|
|
144
|
+
{ requestId: ctx.requestId, result: streamResult },
|
|
145
|
+
"[chat] ChatCompletions",
|
|
146
|
+
);
|
|
141
147
|
addSpanEvent("hebo.result.transformed");
|
|
142
148
|
|
|
143
149
|
const genAiResponseAttrs = getChatResponseAttributes(streamResult, genAiSignalLevel);
|
|
@@ -180,6 +186,7 @@ export const chatCompletions = (config: GatewayConfig): Endpoint => {
|
|
|
180
186
|
|
|
181
187
|
// Transform result.
|
|
182
188
|
ctx.result = toChatCompletions(result, ctx.resolvedModelId);
|
|
189
|
+
logger.trace({ requestId: ctx.requestId, result: ctx.result }, "[chat] ChatCompletions");
|
|
183
190
|
addSpanEvent("hebo.result.transformed");
|
|
184
191
|
|
|
185
192
|
const genAiResponseAttrs = getChatResponseAttributes(ctx.result, genAiSignalLevel);
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
getEmbeddingsRequestAttributes,
|
|
30
30
|
getEmbeddingsResponseAttributes,
|
|
31
31
|
} from "./otel";
|
|
32
|
-
import { EmbeddingsBodySchema } from "./schema";
|
|
32
|
+
import { EmbeddingsBodySchema, type EmbeddingsBody } from "./schema";
|
|
33
33
|
|
|
34
34
|
export const embeddings = (config: GatewayConfig): Endpoint => {
|
|
35
35
|
const hooks = config.hooks;
|
|
@@ -50,6 +50,7 @@ export const embeddings = (config: GatewayConfig): Endpoint => {
|
|
|
50
50
|
} catch {
|
|
51
51
|
throw new GatewayError("Invalid JSON", 400);
|
|
52
52
|
}
|
|
53
|
+
logger.trace({ requestId: ctx.requestId, result: ctx.body }, "[chat] EmbeddingsBody");
|
|
53
54
|
addSpanEvent("hebo.request.deserialized");
|
|
54
55
|
|
|
55
56
|
const parsed = EmbeddingsBodySchema.safeParse(ctx.body);
|
|
@@ -61,7 +62,7 @@ export const embeddings = (config: GatewayConfig): Endpoint => {
|
|
|
61
62
|
addSpanEvent("hebo.request.parsed");
|
|
62
63
|
|
|
63
64
|
if (hooks?.before) {
|
|
64
|
-
ctx.body = (await hooks.before(ctx as BeforeHookContext)) ?? ctx.body;
|
|
65
|
+
ctx.body = ((await hooks.before(ctx as BeforeHookContext)) as EmbeddingsBody) ?? ctx.body;
|
|
65
66
|
addSpanEvent("hebo.hooks.before.completed");
|
|
66
67
|
}
|
|
67
68
|
|
|
@@ -100,7 +101,7 @@ export const embeddings = (config: GatewayConfig): Endpoint => {
|
|
|
100
101
|
"[embeddings] AI SDK options",
|
|
101
102
|
);
|
|
102
103
|
addSpanEvent("hebo.options.prepared");
|
|
103
|
-
setSpanAttributes(getEmbeddingsRequestAttributes(
|
|
104
|
+
setSpanAttributes(getEmbeddingsRequestAttributes(ctx.body, genAiSignalLevel));
|
|
104
105
|
|
|
105
106
|
// Build middleware chain (model -> forward params -> provider).
|
|
106
107
|
const embeddingModelWithMiddleware = wrapEmbeddingModel({
|
|
@@ -121,6 +122,7 @@ export const embeddings = (config: GatewayConfig): Endpoint => {
|
|
|
121
122
|
|
|
122
123
|
// Transform result.
|
|
123
124
|
ctx.result = toEmbeddings(result, ctx.modelId);
|
|
125
|
+
logger.trace({ requestId: ctx.requestId, result: ctx.result }, "[chat] Embeddings");
|
|
124
126
|
addSpanEvent("hebo.result.transformed");
|
|
125
127
|
const genAiResponseAttrs = getEmbeddingsResponseAttributes(ctx.result, genAiSignalLevel);
|
|
126
128
|
recordTokenUsage(genAiResponseAttrs, genAiGeneralAttrs, genAiSignalLevel);
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { EmbeddingModelMiddleware, LanguageModelMiddleware } from "ai";
|
|
2
|
+
|
|
3
|
+
import { logger } from "../logger";
|
|
4
|
+
|
|
5
|
+
export const debugLanguageFinalParamsMiddleware: LanguageModelMiddleware = {
|
|
6
|
+
specificationVersion: "v3",
|
|
7
|
+
// eslint-disable-next-line require-await
|
|
8
|
+
transformParams: async ({ params, model }) => {
|
|
9
|
+
logger.trace(
|
|
10
|
+
{
|
|
11
|
+
kind: "text",
|
|
12
|
+
modelId: model.modelId,
|
|
13
|
+
providerId: model.provider,
|
|
14
|
+
params,
|
|
15
|
+
},
|
|
16
|
+
"[middleware] final params",
|
|
17
|
+
);
|
|
18
|
+
return params;
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const debugEmbeddingFinalParamsMiddleware: EmbeddingModelMiddleware = {
|
|
23
|
+
specificationVersion: "v3",
|
|
24
|
+
// eslint-disable-next-line require-await
|
|
25
|
+
transformParams: async ({ params, model }) => {
|
|
26
|
+
logger.trace(
|
|
27
|
+
{
|
|
28
|
+
kind: "embedding",
|
|
29
|
+
modelId: model.modelId,
|
|
30
|
+
providerId: model.provider,
|
|
31
|
+
params,
|
|
32
|
+
},
|
|
33
|
+
"[middleware] final params",
|
|
34
|
+
);
|
|
35
|
+
return params;
|
|
36
|
+
},
|
|
37
|
+
};
|
|
@@ -6,6 +6,7 @@ import type { ProviderId } from "../providers/types";
|
|
|
6
6
|
import { logger } from "../logger";
|
|
7
7
|
import { addSpanEvent } from "../telemetry/span";
|
|
8
8
|
import { forwardParamsEmbeddingMiddleware, forwardParamsMiddleware } from "./common";
|
|
9
|
+
import { debugEmbeddingFinalParamsMiddleware, debugLanguageFinalParamsMiddleware } from "./debug";
|
|
9
10
|
|
|
10
11
|
type MiddlewareEntries = {
|
|
11
12
|
language?: LanguageModelMiddleware[];
|
|
@@ -110,6 +111,9 @@ class ModelMiddlewareMatcher {
|
|
|
110
111
|
if (providerId) {
|
|
111
112
|
out.push(...this.collect(this.provider.match(providerId), kind));
|
|
112
113
|
}
|
|
114
|
+
out.push(
|
|
115
|
+
kind === "text" ? debugLanguageFinalParamsMiddleware : debugEmbeddingFinalParamsMiddleware,
|
|
116
|
+
);
|
|
113
117
|
|
|
114
118
|
if (this.cache.size >= ModelMiddlewareMatcher.MAX_CACHE) {
|
|
115
119
|
let n = Math.ceil(ModelMiddlewareMatcher.MAX_CACHE * 0.2);
|