@littlebigbrain/client 0.4.3 → 0.5.0
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 +11 -0
- package/dist/client.d.ts +39 -1
- package/dist/client.js +92 -5
- package/dist/namespaces.d.ts +8 -0
- package/dist/namespaces.js +21 -4
- package/dist/schema.d.ts +986 -206
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -54,6 +54,17 @@ feedback, and model runs in little big brain:
|
|
|
54
54
|
5. Grade cited results, reconnect to durable trainer jobs, and require a
|
|
55
55
|
held-out quality plus latency gate before promotion.
|
|
56
56
|
|
|
57
|
+
`suggestionShown`, `suggestionAdopted`, `externalPlannerTrace`, and
|
|
58
|
+
`askFeedback` use generated versioned payload types and idempotency keys. Their
|
|
59
|
+
acknowledgements expose stable receipt/event identity, replay state, and why an
|
|
60
|
+
event is or is not trainable.
|
|
61
|
+
|
|
62
|
+
For an LLM query planner, call `lbb.context.suggest(...)` to fill grounded
|
|
63
|
+
schema/value prefixes, then `lbb.context.resolve(...)` to snap free-text guesses
|
|
64
|
+
onto real vocabulary. `resolve` uses managed embeddings when configured. Record
|
|
65
|
+
adopted suggestions and accepted/rejected/corrected plans so a smaller planner
|
|
66
|
+
and suggest ranker can be trained on the product's actual workload.
|
|
67
|
+
|
|
57
68
|
The [enterprise-search integration guide](https://docs.littlebigbrain.com/guides/enterprise-search/)
|
|
58
69
|
contains the graph model, migration sequence, and acceptance tests.
|
|
59
70
|
|
package/dist/client.d.ts
CHANGED
|
@@ -7,6 +7,15 @@ export { LbbError } from "./transport.js";
|
|
|
7
7
|
export type { CallOptions, Query, QueryValue, RequestOptions, } from "./transport.js";
|
|
8
8
|
export type { EntityListOptions, HybridSearchOptions } from "./namespaces.js";
|
|
9
9
|
export { ContextNamespace, EntityNamespace, FactsNamespace, GraphNamespace, IndexNamespace, OntologyNamespace, QueryNamespace, SchemaNamespace, SearchNamespace, } from "./namespaces.js";
|
|
10
|
+
export interface IndexLineageObservation {
|
|
11
|
+
metadata: Schemas["GraphMetadataResponse"];
|
|
12
|
+
lineage: Schemas["IndexLineage"];
|
|
13
|
+
buildCommit?: string;
|
|
14
|
+
replica?: string;
|
|
15
|
+
requestId?: string;
|
|
16
|
+
attempts: number;
|
|
17
|
+
elapsedMs: number;
|
|
18
|
+
}
|
|
10
19
|
/**
|
|
11
20
|
* A typed HTTP client for a little big brain graph server. One instance is scoped to a
|
|
12
21
|
* single graph/branch; construct another for a different scope. All methods
|
|
@@ -133,10 +142,21 @@ export declare class LbbClient {
|
|
|
133
142
|
}): Promise<unknown>;
|
|
134
143
|
embeddingConfig(): Promise<Schemas["ManagedEmbeddingConfigResponse"]>;
|
|
135
144
|
setEmbeddingConfig(body: Schemas["ManagedEmbeddingConfigRequest"]): Promise<Schemas["ManagedEmbeddingConfigResponse"]>;
|
|
145
|
+
submitEmbeddingBackfill(opts?: {
|
|
146
|
+
batchSize?: number;
|
|
147
|
+
limit?: number;
|
|
148
|
+
full?: boolean;
|
|
149
|
+
idempotencyKey?: string;
|
|
150
|
+
}): Promise<Schemas["ManagedEmbeddingBackfillJobStatusResponse"]>;
|
|
151
|
+
embeddingBackfillJob(jobId: string): Promise<Schemas["ManagedEmbeddingBackfillJobStatusResponse"]>;
|
|
152
|
+
cancelEmbeddingBackfill(jobId: string): Promise<Schemas["ManagedEmbeddingBackfillJobStatusResponse"]>;
|
|
136
153
|
backfillEmbeddings(opts?: {
|
|
137
154
|
batchSize?: number;
|
|
138
155
|
limit?: number;
|
|
139
156
|
full?: boolean;
|
|
157
|
+
idempotencyKey?: string;
|
|
158
|
+
timeoutMs?: number;
|
|
159
|
+
pollIntervalMs?: number;
|
|
140
160
|
}): Promise<Schemas["ManagedEmbeddingBackfillResponse"]>;
|
|
141
161
|
promoteEmbedding(opts: {
|
|
142
162
|
runId: string;
|
|
@@ -224,7 +244,21 @@ export declare class LbbClient {
|
|
|
224
244
|
* explicit feedback capture. `accepted: false` in the response means
|
|
225
245
|
* signal capture is off on this deployment (the contract is identical).
|
|
226
246
|
*/
|
|
227
|
-
askFeedback(body: Schemas["AskFeedbackRequest"]
|
|
247
|
+
askFeedback(body: Schemas["AskFeedbackRequest"], opts?: {
|
|
248
|
+
idempotencyKey?: string;
|
|
249
|
+
}): Promise<Schemas["AskFeedbackResponse"]>;
|
|
250
|
+
ingestSignals(body: Schemas["SignalIngestRequest"], opts?: {
|
|
251
|
+
idempotencyKey?: string;
|
|
252
|
+
}): Promise<Schemas["SignalIngestResponse"]>;
|
|
253
|
+
suggestionShown(payload: Schemas["SuggestionShownV1"], opts?: {
|
|
254
|
+
idempotencyKey?: string;
|
|
255
|
+
}): Promise<Schemas["SignalIngestResponse"]>;
|
|
256
|
+
suggestionAdopted(payload: Schemas["SuggestionAdoptedV1"], opts?: {
|
|
257
|
+
idempotencyKey?: string;
|
|
258
|
+
}): Promise<Schemas["SignalIngestResponse"]>;
|
|
259
|
+
externalPlannerTrace(payload: Schemas["ExternalPlannerTraceV1"], opts?: {
|
|
260
|
+
idempotencyKey?: string;
|
|
261
|
+
}): Promise<Schemas["SignalIngestResponse"]>;
|
|
228
262
|
/**
|
|
229
263
|
* The planner fine-tune's training feed: accepted/corrected feedback
|
|
230
264
|
* joined to its traces (signals ≤ the split pin), topped up with
|
|
@@ -521,6 +555,10 @@ export declare class LbbClient {
|
|
|
521
555
|
status(): Promise<unknown>;
|
|
522
556
|
/** Graph footprint, WAL tail, and index coverage. */
|
|
523
557
|
metadata(): Promise<Schemas["GraphMetadataResponse"]>;
|
|
558
|
+
waitForIndexLineage(targetSeq: number, opts?: {
|
|
559
|
+
timeoutMs?: number;
|
|
560
|
+
pollIntervalMs?: number;
|
|
561
|
+
}): Promise<IndexLineageObservation>;
|
|
524
562
|
/** Graph counts and type/relation buckets. */
|
|
525
563
|
summary(): Promise<Schemas["GraphSummaryResponse"]>;
|
|
526
564
|
/** List the graphs (and branches) under the scoped tenant. */
|
package/dist/client.js
CHANGED
|
@@ -395,11 +395,40 @@ export class LbbClient {
|
|
|
395
395
|
setEmbeddingConfig(body) {
|
|
396
396
|
return this.request("POST", "/v1/graph/embedding", { body });
|
|
397
397
|
}
|
|
398
|
-
|
|
399
|
-
return this.request("POST", "/v1/graph/embedding/backfill", {
|
|
400
|
-
|
|
398
|
+
submitEmbeddingBackfill(opts = {}) {
|
|
399
|
+
return this.request("POST", "/v1/graph/embedding/backfill-jobs", {
|
|
400
|
+
body: {
|
|
401
|
+
batch_size: opts.batchSize,
|
|
402
|
+
limit: opts.limit,
|
|
403
|
+
full: opts.full ?? false,
|
|
404
|
+
},
|
|
405
|
+
idempotencyKey: opts.idempotencyKey ?? this.idempotencyKey("embedding-backfill"),
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
embeddingBackfillJob(jobId) {
|
|
409
|
+
return this.request("GET", "/v1/graph/embedding/backfill-jobs", {
|
|
410
|
+
query: { job_id: jobId },
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
cancelEmbeddingBackfill(jobId) {
|
|
414
|
+
return this.request("DELETE", "/v1/graph/embedding/backfill-jobs", {
|
|
415
|
+
query: { job_id: jobId },
|
|
401
416
|
});
|
|
402
417
|
}
|
|
418
|
+
async backfillEmbeddings(opts = {}) {
|
|
419
|
+
let status = await this.submitEmbeddingBackfill(opts);
|
|
420
|
+
const deadline = Date.now() + (opts.timeoutMs ?? 30 * 60_000);
|
|
421
|
+
while (status.status === "pending" || status.status === "running") {
|
|
422
|
+
if (Date.now() >= deadline)
|
|
423
|
+
throw new Error(`embedding backfill ${status.job_id} did not finish before timeout`);
|
|
424
|
+
await sleep(opts.pollIntervalMs ?? 2_000);
|
|
425
|
+
status = await this.embeddingBackfillJob(status.job_id);
|
|
426
|
+
}
|
|
427
|
+
if (status.status !== "succeeded" || status.result == null)
|
|
428
|
+
throw new Error(status.terminal_error ??
|
|
429
|
+
`embedding backfill ${status.job_id} ended ${status.status}`);
|
|
430
|
+
return status.result;
|
|
431
|
+
}
|
|
403
432
|
promoteEmbedding(opts) {
|
|
404
433
|
return this.request("POST", "/v1/graph/embedding/promote", {
|
|
405
434
|
query: { run_id: opts.runId, allow_regression: opts.allowRegression },
|
|
@@ -506,8 +535,35 @@ export class LbbClient {
|
|
|
506
535
|
* explicit feedback capture. `accepted: false` in the response means
|
|
507
536
|
* signal capture is off on this deployment (the contract is identical).
|
|
508
537
|
*/
|
|
509
|
-
askFeedback(body) {
|
|
510
|
-
return this.request("POST", "/v1/ask/feedback", {
|
|
538
|
+
askFeedback(body, opts = {}) {
|
|
539
|
+
return this.request("POST", "/v1/ask/feedback", {
|
|
540
|
+
body,
|
|
541
|
+
idempotencyKey: opts.idempotencyKey ?? this.idempotencyKey("ask-feedback"),
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
ingestSignals(body, opts = {}) {
|
|
545
|
+
return this.request("POST", "/v1/signals", {
|
|
546
|
+
body,
|
|
547
|
+
idempotencyKey: opts.idempotencyKey ?? this.idempotencyKey("signals"),
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
suggestionShown(payload, opts = {}) {
|
|
551
|
+
return this.ingestSignals({ signals: [{ kind: "suggestion_shown", payload }] }, opts);
|
|
552
|
+
}
|
|
553
|
+
suggestionAdopted(payload, opts = {}) {
|
|
554
|
+
return this.ingestSignals({ signals: [{ kind: "suggestion_adopted", payload }] }, opts);
|
|
555
|
+
}
|
|
556
|
+
externalPlannerTrace(payload, opts = {}) {
|
|
557
|
+
return this.ingestSignals({
|
|
558
|
+
signals: [
|
|
559
|
+
{
|
|
560
|
+
kind: "external_planner_trace",
|
|
561
|
+
request_id: payload.ask_id,
|
|
562
|
+
snapshot_token: payload.snapshot_token,
|
|
563
|
+
payload,
|
|
564
|
+
},
|
|
565
|
+
],
|
|
566
|
+
}, opts);
|
|
511
567
|
}
|
|
512
568
|
/**
|
|
513
569
|
* The planner fine-tune's training feed: accepted/corrected feedback
|
|
@@ -923,6 +979,37 @@ export class LbbClient {
|
|
|
923
979
|
metadata() {
|
|
924
980
|
return this.request("GET", "/v1/graph/metadata");
|
|
925
981
|
}
|
|
982
|
+
async waitForIndexLineage(targetSeq, opts = {}) {
|
|
983
|
+
const deadline = Date.now() + (opts.timeoutMs ?? 30_000);
|
|
984
|
+
let last;
|
|
985
|
+
while (true) {
|
|
986
|
+
last = await this.rawRequest("GET", "/v1/graph/metadata");
|
|
987
|
+
const lineage = last.data.index_lineage;
|
|
988
|
+
if (lineage != null &&
|
|
989
|
+
lineage.bm25_indexed_commit_seq != null &&
|
|
990
|
+
lineage.bm25_indexed_commit_seq >= targetSeq &&
|
|
991
|
+
lineage.ann_indexed_commit_seq != null &&
|
|
992
|
+
lineage.ann_indexed_commit_seq >= targetSeq &&
|
|
993
|
+
lineage.adjacency_indexed_commit_seq != null &&
|
|
994
|
+
lineage.adjacency_indexed_commit_seq >= targetSeq) {
|
|
995
|
+
return {
|
|
996
|
+
metadata: last.data,
|
|
997
|
+
lineage,
|
|
998
|
+
buildCommit: last.headers?.get("lbb-build-commit") ?? undefined,
|
|
999
|
+
replica: last.headers?.get("lbb-replica") ?? undefined,
|
|
1000
|
+
requestId: last.requestId,
|
|
1001
|
+
attempts: last.attempts,
|
|
1002
|
+
elapsedMs: last.elapsedMs,
|
|
1003
|
+
};
|
|
1004
|
+
}
|
|
1005
|
+
if (Date.now() >= deadline) {
|
|
1006
|
+
const build = last.headers?.get("lbb-build-commit") ?? "unknown";
|
|
1007
|
+
const replica = last.headers?.get("lbb-replica") ?? "unknown";
|
|
1008
|
+
throw new Error(`index lineage did not reach ${targetSeq} before timeout (build=${build}, replica=${replica}, last=${JSON.stringify(last.data.index_lineage)})`);
|
|
1009
|
+
}
|
|
1010
|
+
await sleep(opts.pollIntervalMs ?? 250);
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
926
1013
|
/** Graph counts and type/relation buckets. */
|
|
927
1014
|
summary() {
|
|
928
1015
|
return this.request("GET", "/v1/graph/summary");
|
package/dist/namespaces.d.ts
CHANGED
|
@@ -39,7 +39,15 @@ export declare class GraphNamespace {
|
|
|
39
39
|
batchSize?: number;
|
|
40
40
|
limit?: number;
|
|
41
41
|
full?: boolean;
|
|
42
|
+
pollIntervalMs?: number;
|
|
42
43
|
}): Promise<Schemas["ManagedEmbeddingBackfillResponse"]>;
|
|
44
|
+
submitEmbeddingBackfill(options?: CallOptions & {
|
|
45
|
+
batchSize?: number;
|
|
46
|
+
limit?: number;
|
|
47
|
+
full?: boolean;
|
|
48
|
+
}): Promise<Schemas["ManagedEmbeddingBackfillJobStatusResponse"]>;
|
|
49
|
+
embeddingBackfillJob(jobId: string): Promise<Schemas["ManagedEmbeddingBackfillJobStatusResponse"]>;
|
|
50
|
+
cancelEmbeddingBackfill(jobId: string): Promise<Schemas["ManagedEmbeddingBackfillJobStatusResponse"]>;
|
|
43
51
|
promoteEmbedding(options: CallOptions & {
|
|
44
52
|
runId: string;
|
|
45
53
|
allowRegression?: boolean;
|
package/dist/namespaces.js
CHANGED
|
@@ -53,12 +53,29 @@ export class GraphNamespace {
|
|
|
53
53
|
});
|
|
54
54
|
}
|
|
55
55
|
backfillEmbeddings(options = {}) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
return this.client.backfillEmbeddings({
|
|
57
|
+
batchSize: options.batchSize,
|
|
58
|
+
limit: options.limit,
|
|
59
|
+
full: options.full,
|
|
60
|
+
idempotencyKey: options.idempotencyKey,
|
|
61
|
+
timeoutMs: options.timeoutMs,
|
|
62
|
+
pollIntervalMs: options.pollIntervalMs,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
submitEmbeddingBackfill(options = {}) {
|
|
66
|
+
return this.client.submitEmbeddingBackfill({
|
|
67
|
+
batchSize: options.batchSize,
|
|
68
|
+
limit: options.limit,
|
|
69
|
+
full: options.full,
|
|
70
|
+
idempotencyKey: options.idempotencyKey,
|
|
60
71
|
});
|
|
61
72
|
}
|
|
73
|
+
embeddingBackfillJob(jobId) {
|
|
74
|
+
return this.client.embeddingBackfillJob(jobId);
|
|
75
|
+
}
|
|
76
|
+
cancelEmbeddingBackfill(jobId) {
|
|
77
|
+
return this.client.cancelEmbeddingBackfill(jobId);
|
|
78
|
+
}
|
|
62
79
|
promoteEmbedding(options) {
|
|
63
80
|
const { runId, allowRegression, ...request } = options;
|
|
64
81
|
return this.client.request("POST", "/v1/graph/embedding/promote", {
|