@dbx-tools/model 0.9.60 → 0.9.64

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.
@@ -103,7 +103,7 @@ interface DatabricksModelClient {
103
103
  host(): string;
104
104
  principal(): string;
105
105
  workspaceId(): string | undefined;
106
- request(path: string): Promise<unknown>;
106
+ request(path: string, init?: RequestInit): Promise<unknown>;
107
107
  }
108
108
 
109
109
  class AuthenticatedModelClient implements DatabricksModelClient {
@@ -124,13 +124,21 @@ class AuthenticatedModelClient implements DatabricksModelClient {
124
124
  return this.auth.workspaceId;
125
125
  }
126
126
 
127
- async request(path: string): Promise<unknown> {
127
+ async request(path: string, init: RequestInit = {}): Promise<unknown> {
128
128
  const url = new URL(path, `${this.host().replace(/\/$/, "")}/`).toString();
129
- let headers = await this.auth.headers();
130
- let response = await this.fetcher(url, { headers });
129
+ const headers = new Headers(init.headers);
130
+ for (const [name, value] of Object.entries(await this.auth.headers())) {
131
+ headers.set(name, value);
132
+ }
133
+ if (init.body !== undefined && !headers.has("content-type")) {
134
+ headers.set("content-type", "application/json");
135
+ }
136
+ let response = await this.fetcher(url, { ...init, headers });
131
137
  if (response.status === 401) {
132
- headers = await this.auth.headers({ refresh: true });
133
- response = await this.fetcher(url, { headers });
138
+ for (const [name, value] of Object.entries(await this.auth.headers({ refresh: true }))) {
139
+ headers.set(name, value);
140
+ }
141
+ response = await this.fetcher(url, { ...init, headers });
134
142
  }
135
143
  const text = await response.text();
136
144
  if (!response.ok) {
@@ -236,7 +244,7 @@ class DefaultModelClient implements ModelClient {
236
244
  if (!object.isRecord(response) || !Array.isArray(response.endpoints)) {
237
245
  throw new Error("Databricks serving-endpoints response is missing an endpoints array");
238
246
  }
239
- const endpoints = normalizeEndpoints(response.endpoints);
247
+ const endpoints = await this.measureEmbeddingDimensions(normalizeEndpoints(response.endpoints));
240
248
  logger.debug("listed", {
241
249
  count: endpoints.length,
242
250
  host: this.client.host(),
@@ -244,6 +252,42 @@ class DefaultModelClient implements ModelClient {
244
252
  });
245
253
  return endpoints;
246
254
  }
255
+
256
+ private async measureEmbeddingDimensions(
257
+ endpoints: readonly ServingEndpointSummary[],
258
+ ): Promise<ServingEndpointSummary[]> {
259
+ return Promise.all(
260
+ endpoints.map(async (endpoint) => {
261
+ if (endpoint.class !== ModelClass.Embedding || endpoint.dimension !== undefined) {
262
+ return endpoint;
263
+ }
264
+ try {
265
+ const response = await this.client.request(
266
+ `/serving-endpoints/${encodeURIComponent(endpoint.name)}/invocations`,
267
+ {
268
+ method: "POST",
269
+ body: JSON.stringify({ input: ["ping"] }),
270
+ },
271
+ );
272
+ const dimension = embeddingDimension(response);
273
+ return dimension === undefined ? endpoint : { ...endpoint, dimension };
274
+ } catch (error) {
275
+ logger.warn("embedding dimension probe failed", {
276
+ model: endpoint.name,
277
+ error,
278
+ });
279
+ return endpoint;
280
+ }
281
+ }),
282
+ );
283
+ }
284
+ }
285
+
286
+ function embeddingDimension(value: unknown): number | undefined {
287
+ if (!object.isRecord(value) || !Array.isArray(value.data)) return undefined;
288
+ const first = value.data[0];
289
+ if (!object.isRecord(first) || !Array.isArray(first.embedding)) return undefined;
290
+ return first.embedding.length > 0 ? first.embedding.length : undefined;
247
291
  }
248
292
 
249
293
  /** Create an authentication-aware Databricks model client. */
package/src/policy.ts CHANGED
@@ -90,7 +90,8 @@ export function isFoundationModelIdentity(name: string): boolean {
90
90
  return /^(?:databricks-|system\.ai\.)/i.test(name.trim());
91
91
  }
92
92
 
93
- function isOpenWeightsGpt(name: string): boolean {
93
+ /** Return whether an identity is hosted GPT-OSS rather than a GPT generation. */
94
+ export function isOpenWeightsGpt(name: string): boolean {
94
95
  return modelFamily(name) === "gpt" && /(?:^|[-_.])oss(?:[-_.]|$)/i.test(name);
95
96
  }
96
97