@lunora/ai 1.0.0-alpha.20 → 1.0.0-alpha.21
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.
|
@@ -113,6 +113,20 @@ const modelIdOf = (model) => {
|
|
|
113
113
|
const id = model.modelId;
|
|
114
114
|
return typeof id === "string" && id.length > 0 ? id : void 0;
|
|
115
115
|
};
|
|
116
|
+
const embedCostOf = (providerMetadata) => {
|
|
117
|
+
if (typeof providerMetadata !== "object" || providerMetadata === null) {
|
|
118
|
+
return void 0;
|
|
119
|
+
}
|
|
120
|
+
for (const bag of Object.values(providerMetadata)) {
|
|
121
|
+
if (typeof bag === "object" && bag !== null) {
|
|
122
|
+
const { cost } = bag;
|
|
123
|
+
if (typeof cost === "number" && Number.isFinite(cost)) {
|
|
124
|
+
return cost;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return void 0;
|
|
129
|
+
};
|
|
116
130
|
const defineRag = (config) => {
|
|
117
131
|
if (typeof config.index !== "string" || config.index.length === 0) {
|
|
118
132
|
throw new LunoraError("BAD_REQUEST", "@lunora/ai/rag: `index` must be a non-empty Vectorize index name");
|
|
@@ -151,15 +165,25 @@ const defineRag = (config) => {
|
|
|
151
165
|
const embedText = async (text) => {
|
|
152
166
|
model ??= resolveEmbeddingModel(config.embeddingModel, context.ai);
|
|
153
167
|
const resolvedModel = model;
|
|
154
|
-
const run = async () => {
|
|
155
|
-
const { embedding } = await embed({ model: resolvedModel, value: text });
|
|
168
|
+
const run = async (span) => {
|
|
169
|
+
const { embedding, providerMetadata, usage } = await embed({ model: resolvedModel, value: text });
|
|
170
|
+
if (span !== void 0) {
|
|
171
|
+
const inputTokens = usage.tokens;
|
|
172
|
+
if (typeof inputTokens === "number" && Number.isFinite(inputTokens)) {
|
|
173
|
+
span.setAttribute("gen_ai.usage.input_tokens", inputTokens);
|
|
174
|
+
}
|
|
175
|
+
const cost = embedCostOf(providerMetadata);
|
|
176
|
+
if (cost !== void 0) {
|
|
177
|
+
span.setAttribute("gen_ai.usage.cost", cost);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
156
180
|
return embedding;
|
|
157
181
|
};
|
|
158
182
|
if (tracer === void 0) {
|
|
159
183
|
return run();
|
|
160
184
|
}
|
|
161
185
|
const modelId = modelIdOf(resolvedModel);
|
|
162
|
-
return tracer("ai.embed", run, {
|
|
186
|
+
return tracer("ai.embed", (_trace, span) => run(span), {
|
|
163
187
|
"gen_ai.operation.name": "embeddings",
|
|
164
188
|
...modelId === void 0 ? {} : { "gen_ai.request.model": modelId }
|
|
165
189
|
});
|
package/dist/rag/index.d.mts
CHANGED
|
@@ -112,11 +112,15 @@ interface RagContext {
|
|
|
112
112
|
/**
|
|
113
113
|
* Optional `ctx.trace` span factory — an `ActionCtx`'s `ctx.trace` satisfies
|
|
114
114
|
* it structurally. When present, `defineRag` wraps each embedding-model
|
|
115
|
-
* call in a `generation` span
|
|
116
|
-
* `gen_ai.request.model`
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
115
|
+
* call in a `generation` span carrying `gen_ai.operation.name: "embeddings"`
|
|
116
|
+
* and `gen_ai.request.model` up front, plus — attached post-hoc through the
|
|
117
|
+
* span handle the tracer hands the body — `gen_ai.usage.input_tokens` (from
|
|
118
|
+
* the embed result's token usage) and `gen_ai.usage.cost` (probed from the
|
|
119
|
+
* embed result's provider metadata, e.g. AI Gateway) when those are present.
|
|
120
|
+
* So the embed shows up on the trace waterfall with its usage like any other
|
|
121
|
+
* instrumented model call. `unknown` on purpose — the same decoupling
|
|
122
|
+
* rationale as `auth`: `defineRag` narrows it to a callable and runs embeds
|
|
123
|
+
* untraced when it is absent (a hand-built context / test).
|
|
120
124
|
*/
|
|
121
125
|
trace?: unknown;
|
|
122
126
|
vectors: RagVectors;
|
package/dist/rag/index.d.ts
CHANGED
|
@@ -112,11 +112,15 @@ interface RagContext {
|
|
|
112
112
|
/**
|
|
113
113
|
* Optional `ctx.trace` span factory — an `ActionCtx`'s `ctx.trace` satisfies
|
|
114
114
|
* it structurally. When present, `defineRag` wraps each embedding-model
|
|
115
|
-
* call in a `generation` span
|
|
116
|
-
* `gen_ai.request.model`
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
115
|
+
* call in a `generation` span carrying `gen_ai.operation.name: "embeddings"`
|
|
116
|
+
* and `gen_ai.request.model` up front, plus — attached post-hoc through the
|
|
117
|
+
* span handle the tracer hands the body — `gen_ai.usage.input_tokens` (from
|
|
118
|
+
* the embed result's token usage) and `gen_ai.usage.cost` (probed from the
|
|
119
|
+
* embed result's provider metadata, e.g. AI Gateway) when those are present.
|
|
120
|
+
* So the embed shows up on the trace waterfall with its usage like any other
|
|
121
|
+
* instrumented model call. `unknown` on purpose — the same decoupling
|
|
122
|
+
* rationale as `auth`: `defineRag` narrows it to a callable and runs embeds
|
|
123
|
+
* untraced when it is absent (a hand-built context / test).
|
|
120
124
|
*/
|
|
121
125
|
trace?: unknown;
|
|
122
126
|
vectors: RagVectors;
|
package/dist/rag/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { default as fixedWindowChunks } from '../packem_shared/fixedWindowChunks-J-WfQDw9.mjs';
|
|
2
|
-
export { default as defineRag } from '../packem_shared/defineRag-
|
|
2
|
+
export { default as defineRag } from '../packem_shared/defineRag-CQ3pnKUh.mjs';
|
|
3
3
|
export { contentHash, guessMimeTypeFromExtension } from '../packem_shared/contentHash-Cgz5KRGD.mjs';
|
|
4
4
|
export { default as hybridRank } from '../packem_shared/hybridRank-DPC9c2ON.mjs';
|
|
5
5
|
export { default as bm25LexicalStore } from '../packem_shared/bm25LexicalStore-BQzWLMqX.mjs';
|