@adonis-agora/agent 0.35.0 → 0.37.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/CHANGELOG.md +23 -0
- package/NOTICE +31 -0
- package/README.md +5 -5
- package/dist/configure.d.ts.map +1 -1
- package/dist/configure.js +1 -0
- package/dist/configure.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/rag/index.d.ts +3 -1
- package/dist/src/rag/index.d.ts.map +1 -1
- package/dist/src/rag/index.js +3 -1
- package/dist/src/rag/index.js.map +1 -1
- package/dist/src/rag/lexical-query.d.ts +28 -0
- package/dist/src/rag/lexical-query.d.ts.map +1 -0
- package/dist/src/rag/lexical-query.js +90 -0
- package/dist/src/rag/lexical-query.js.map +1 -0
- package/dist/src/rag/openai-embeddings.d.ts +20 -2
- package/dist/src/rag/openai-embeddings.d.ts.map +1 -1
- package/dist/src/rag/openai-embeddings.js +107 -42
- package/dist/src/rag/openai-embeddings.js.map +1 -1
- package/dist/src/rag/pg-vector-store.d.ts +56 -7
- package/dist/src/rag/pg-vector-store.d.ts.map +1 -1
- package/dist/src/rag/pg-vector-store.js +65 -17
- package/dist/src/rag/pg-vector-store.js.map +1 -1
- package/dist/src/rag/tree/build.d.ts +96 -0
- package/dist/src/rag/tree/build.d.ts.map +1 -0
- package/dist/src/rag/tree/build.js +659 -0
- package/dist/src/rag/tree/build.js.map +1 -0
- package/dist/src/rag/tree/headings.d.ts +29 -0
- package/dist/src/rag/tree/headings.d.ts.map +1 -0
- package/dist/src/rag/tree/headings.js +227 -0
- package/dist/src/rag/tree/headings.js.map +1 -0
- package/dist/src/rag/tree/index-document.d.ts +33 -0
- package/dist/src/rag/tree/index-document.d.ts.map +1 -0
- package/dist/src/rag/tree/index-document.js +36 -0
- package/dist/src/rag/tree/index-document.js.map +1 -0
- package/dist/src/rag/tree/index.d.ts +13 -0
- package/dist/src/rag/tree/index.d.ts.map +1 -0
- package/dist/src/rag/tree/index.js +12 -0
- package/dist/src/rag/tree/index.js.map +1 -0
- package/dist/src/rag/tree/keyword-tree-llm.d.ts +15 -0
- package/dist/src/rag/tree/keyword-tree-llm.d.ts.map +1 -0
- package/dist/src/rag/tree/keyword-tree-llm.js +105 -0
- package/dist/src/rag/tree/keyword-tree-llm.js.map +1 -0
- package/dist/src/rag/tree/llm.d.ts +179 -0
- package/dist/src/rag/tree/llm.d.ts.map +1 -0
- package/dist/src/rag/tree/llm.js +264 -0
- package/dist/src/rag/tree/llm.js.map +1 -0
- package/dist/src/rag/tree/navigate-tool.d.ts +58 -0
- package/dist/src/rag/tree/navigate-tool.d.ts.map +1 -0
- package/dist/src/rag/tree/navigate-tool.js +95 -0
- package/dist/src/rag/tree/navigate-tool.js.map +1 -0
- package/dist/src/rag/tree/navigate.d.ts +137 -0
- package/dist/src/rag/tree/navigate.d.ts.map +1 -0
- package/dist/src/rag/tree/navigate.js +404 -0
- package/dist/src/rag/tree/navigate.js.map +1 -0
- package/dist/src/rag/tree/pg-tree-store.d.ts +45 -0
- package/dist/src/rag/tree/pg-tree-store.d.ts.map +1 -0
- package/dist/src/rag/tree/pg-tree-store.js +205 -0
- package/dist/src/rag/tree/pg-tree-store.js.map +1 -0
- package/dist/src/rag/tree/store.d.ts +57 -0
- package/dist/src/rag/tree/store.d.ts.map +1 -0
- package/dist/src/rag/tree/store.js +66 -0
- package/dist/src/rag/tree/store.js.map +1 -0
- package/dist/src/rag/tree/two-stage.d.ts +54 -0
- package/dist/src/rag/tree/two-stage.d.ts.map +1 -0
- package/dist/src/rag/tree/two-stage.js +92 -0
- package/dist/src/rag/tree/two-stage.js.map +1 -0
- package/dist/src/rag/tree/types.d.ts +135 -0
- package/dist/src/rag/tree/types.d.ts.map +1 -0
- package/dist/src/rag/tree/types.js +21 -0
- package/dist/src/rag/tree/types.js.map +1 -0
- package/dist/stubs/database/migrations/create_agent_rag_trees.stub +40 -0
- package/package.json +3 -2
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import type { ModelProvider } from '../../spi/model-provider.js';
|
|
2
|
+
/**
|
|
3
|
+
* The structured side of every tree-LLM request: what is being asked, as data. The prompt says the
|
|
4
|
+
* same thing in prose; `task` exists so a deterministic fake (tests, offline dev — see
|
|
5
|
+
* {@link import('./keyword-tree-llm.js').keywordTreeLlm}) can answer without parsing prose, and so a
|
|
6
|
+
* host can log or route requests by kind.
|
|
7
|
+
*/
|
|
8
|
+
export type TreeLlmTask = {
|
|
9
|
+
kind: 'structure';
|
|
10
|
+
/** The window of pages the LLM is asked to find section starts in. */
|
|
11
|
+
units: {
|
|
12
|
+
unit: number;
|
|
13
|
+
page?: number;
|
|
14
|
+
text: string;
|
|
15
|
+
}[];
|
|
16
|
+
} | {
|
|
17
|
+
kind: 'summarize';
|
|
18
|
+
title: string;
|
|
19
|
+
text: string;
|
|
20
|
+
} | {
|
|
21
|
+
kind: 'describe';
|
|
22
|
+
title?: string;
|
|
23
|
+
outline: {
|
|
24
|
+
title: string;
|
|
25
|
+
summary?: string;
|
|
26
|
+
}[];
|
|
27
|
+
} | {
|
|
28
|
+
kind: 'navigate';
|
|
29
|
+
query: string;
|
|
30
|
+
/** `single-pass`: the whole tree is shown; `beam`: one level of candidates at a time. */
|
|
31
|
+
mode: 'single-pass' | 'beam';
|
|
32
|
+
candidates: TreeLlmCandidate[];
|
|
33
|
+
/** Max nodes the answer may name. */
|
|
34
|
+
maxNodes: number;
|
|
35
|
+
} | {
|
|
36
|
+
kind: 'select';
|
|
37
|
+
query: string;
|
|
38
|
+
documents: {
|
|
39
|
+
id: string;
|
|
40
|
+
title?: string;
|
|
41
|
+
description?: string;
|
|
42
|
+
}[];
|
|
43
|
+
maxDocuments: number;
|
|
44
|
+
};
|
|
45
|
+
/** A node as shown to the navigating LLM. */
|
|
46
|
+
export interface TreeLlmCandidate {
|
|
47
|
+
id: string;
|
|
48
|
+
title: string;
|
|
49
|
+
summary?: string;
|
|
50
|
+
pages?: string;
|
|
51
|
+
/** Present on beam candidates: whether the node can be expanded. */
|
|
52
|
+
hasChildren?: boolean;
|
|
53
|
+
/** Present in single-pass mode: depth (0 = top level). */
|
|
54
|
+
depth?: number;
|
|
55
|
+
}
|
|
56
|
+
export interface TreeLlmRequest {
|
|
57
|
+
task: TreeLlmTask;
|
|
58
|
+
system: string;
|
|
59
|
+
prompt: string;
|
|
60
|
+
/** A cap for the reply. Adapters pass it as `max_tokens` when they can. */
|
|
61
|
+
maxOutputTokens: number;
|
|
62
|
+
/** Aborted when the call's timeout or the build/navigation deadline passes. */
|
|
63
|
+
signal: AbortSignal;
|
|
64
|
+
}
|
|
65
|
+
export interface TreeLlmResponse {
|
|
66
|
+
text: string;
|
|
67
|
+
/** Provider-reported usage. When absent, the budget estimates ~4 characters per token. */
|
|
68
|
+
usage?: {
|
|
69
|
+
inputTokens?: number;
|
|
70
|
+
outputTokens?: number;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The only LLM surface tree building and navigation need: one prompt in, one text reply out. Replies
|
|
75
|
+
* are expected to be JSON (for structure / navigate / select) or plain text (summaries); parsing is
|
|
76
|
+
* lenient (code fences, prose around the object). Bring any model:
|
|
77
|
+
* {@link treeLlmFromModelProvider} (the agent's own `ModelProvider`), {@link openAiChatTreeLlm}
|
|
78
|
+
* (any OpenAI-compatible `/chat/completions`), or a function of your own. Use a deterministic
|
|
79
|
+
* setting (temperature 0) — trees are cached by content, so a flaky model makes rebuilds noisy.
|
|
80
|
+
*/
|
|
81
|
+
export type TreeLlm = (request: TreeLlmRequest) => Promise<TreeLlmResponse>;
|
|
82
|
+
/**
|
|
83
|
+
* Hard limits for one document build or one navigation. Every LLM call is checked against them
|
|
84
|
+
* **before** it is made (with the prompt's estimated size), so a budget is never overshot by more
|
|
85
|
+
* than one reply, and nothing retries past it: the failure mode this exists for is an indexer that
|
|
86
|
+
* burned ~1,240 calls on one PDF it could not structure.
|
|
87
|
+
*/
|
|
88
|
+
export interface TreeBudget {
|
|
89
|
+
/** Max LLM calls. */
|
|
90
|
+
maxCalls?: number;
|
|
91
|
+
/** Max input (prompt) tokens across all calls, estimated at ~4 chars/token before each call. */
|
|
92
|
+
maxInputTokens?: number;
|
|
93
|
+
/** Max output tokens across all calls. */
|
|
94
|
+
maxOutputTokens?: number;
|
|
95
|
+
/** Wall-clock deadline for the whole operation, ms. */
|
|
96
|
+
timeoutMs?: number;
|
|
97
|
+
/** Per-call timeout, ms. Default: whatever is left of `timeoutMs`. */
|
|
98
|
+
callTimeoutMs?: number;
|
|
99
|
+
}
|
|
100
|
+
/** Thrown internally when a budget or deadline would be exceeded; callers turn it into a fallback. */
|
|
101
|
+
export declare class TreeBudgetExceededError extends Error {
|
|
102
|
+
readonly limit: 'calls' | 'inputTokens' | 'outputTokens' | 'timeout';
|
|
103
|
+
constructor(limit: 'calls' | 'inputTokens' | 'outputTokens' | 'timeout');
|
|
104
|
+
}
|
|
105
|
+
/** ~4 characters per token: the budget's estimate when a provider reports no usage. */
|
|
106
|
+
export declare function estimateTokens(text: string): number;
|
|
107
|
+
/** Tracks spend against a {@link TreeBudget} and runs calls under it. Not exported from the package. */
|
|
108
|
+
export declare class BudgetedLlm {
|
|
109
|
+
private readonly llm;
|
|
110
|
+
private readonly budget;
|
|
111
|
+
private readonly outerSignal?;
|
|
112
|
+
calls: number;
|
|
113
|
+
inputTokens: number;
|
|
114
|
+
outputTokens: number;
|
|
115
|
+
exhausted: boolean;
|
|
116
|
+
private readonly deadline;
|
|
117
|
+
constructor(llm: TreeLlm, budget: Required<Pick<TreeBudget, 'maxCalls' | 'maxInputTokens' | 'maxOutputTokens'>> & TreeBudget, outerSignal?: AbortSignal | undefined);
|
|
118
|
+
/** Time left before the deadline, ms (`Infinity` without one). */
|
|
119
|
+
remainingMs(): number;
|
|
120
|
+
/** Would a call with this prompt fit? Does not reserve anything; a `false` marks the budget exhausted. */
|
|
121
|
+
fits(prompt: string, maxOutputTokens: number): boolean;
|
|
122
|
+
private limitHit;
|
|
123
|
+
/**
|
|
124
|
+
* Make one call, or throw {@link TreeBudgetExceededError} without calling. Provider errors
|
|
125
|
+
* propagate (after being counted). Never retries.
|
|
126
|
+
*/
|
|
127
|
+
call(task: TreeLlmTask, system: string, prompt: string, maxOutputTokens: number): Promise<string>;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Pull the JSON object out of a model reply: bare, fenced in ```json, or surrounded by prose.
|
|
131
|
+
* Returns `undefined` when there is none (never throws).
|
|
132
|
+
*/
|
|
133
|
+
export declare function parseJsonReply(text: string): Record<string, unknown> | undefined;
|
|
134
|
+
/** The strings in a JSON array value (numbers stringified); anything else yields `[]`. */
|
|
135
|
+
export declare function stringList(value: unknown): string[];
|
|
136
|
+
/**
|
|
137
|
+
* A {@link TreeLlm} over the agent's own {@link ModelProvider}: one `runTurn` with no tools and a
|
|
138
|
+
* discarding sink. Usage comes from the provider's report.
|
|
139
|
+
*/
|
|
140
|
+
export declare function treeLlmFromModelProvider(provider: ModelProvider): TreeLlm;
|
|
141
|
+
export interface OpenAiChatTreeLlmOptions {
|
|
142
|
+
model: string;
|
|
143
|
+
/** Base URL up to and including `/v1`. Default `https://api.openai.com/v1`. */
|
|
144
|
+
baseUrl?: string;
|
|
145
|
+
apiKey?: string;
|
|
146
|
+
headers?: Record<string, string>;
|
|
147
|
+
/** Default 0 — trees are cached by content, determinism keeps rebuilds quiet. */
|
|
148
|
+
temperature?: number;
|
|
149
|
+
/**
|
|
150
|
+
* Send `response_format: { type: 'json_object' }` on JSON tasks. Default `false`: not every
|
|
151
|
+
* OpenAI-compatible server accepts it, and replies are parsed leniently anyway.
|
|
152
|
+
*/
|
|
153
|
+
jsonMode?: boolean;
|
|
154
|
+
/** Extra body fields (a reasoning switch, provider routing). */
|
|
155
|
+
body?: Record<string, unknown>;
|
|
156
|
+
fetch?: typeof fetch;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* A {@link TreeLlm} over any OpenAI-compatible `POST /v1/chat/completions` — OpenAI, a gateway,
|
|
160
|
+
* vLLM, Ollama, DeepSeek, Qwen… — with no SDK dependency. Throws `HttpModelError` on a non-2xx.
|
|
161
|
+
*/
|
|
162
|
+
export declare function openAiChatTreeLlm(options: OpenAiChatTreeLlmOptions): TreeLlm;
|
|
163
|
+
/** A get/set cache — a `Map`, an LRU, a Redis wrapper. Values are whole replies. */
|
|
164
|
+
export interface TreeLlmCache {
|
|
165
|
+
get(key: string): TreeLlmResponse | undefined | Promise<TreeLlmResponse | undefined>;
|
|
166
|
+
set(key: string, value: TreeLlmResponse): unknown;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Memoize a {@link TreeLlm} by the exact request (task kind, system prompt, prompt, output cap).
|
|
170
|
+
* With a deterministic model that makes a rebuild of an unchanged section, or a repeated question,
|
|
171
|
+
* free. Cached replies report zero usage, so they cost nothing against a budget but a call slot.
|
|
172
|
+
*/
|
|
173
|
+
export declare function cachedTreeLlm(llm: TreeLlm, cache?: TreeLlmCache): TreeLlm;
|
|
174
|
+
/**
|
|
175
|
+
* A fast, deterministic, non-cryptographic 64-bit hash (two independent 32-bit FNV-1a/murmur-mixed
|
|
176
|
+
* lanes) as 16 hex chars — content fingerprints and cache keys, not security.
|
|
177
|
+
*/
|
|
178
|
+
export declare function stableHash(text: string): string;
|
|
179
|
+
//# sourceMappingURL=llm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm.d.ts","sourceRoot":"","sources":["../../../../src/rag/tree/llm.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { errorMessageOf, HttpModelError } from '../openai-embeddings.js';
|
|
2
|
+
/** Thrown internally when a budget or deadline would be exceeded; callers turn it into a fallback. */
|
|
3
|
+
export class TreeBudgetExceededError extends Error {
|
|
4
|
+
limit;
|
|
5
|
+
constructor(limit) {
|
|
6
|
+
super(`tree LLM budget exhausted (${limit})`);
|
|
7
|
+
this.limit = limit;
|
|
8
|
+
this.name = 'TreeBudgetExceededError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/** ~4 characters per token: the budget's estimate when a provider reports no usage. */
|
|
12
|
+
export function estimateTokens(text) {
|
|
13
|
+
return Math.ceil(text.length / 4);
|
|
14
|
+
}
|
|
15
|
+
/** Tracks spend against a {@link TreeBudget} and runs calls under it. Not exported from the package. */
|
|
16
|
+
export class BudgetedLlm {
|
|
17
|
+
llm;
|
|
18
|
+
budget;
|
|
19
|
+
outerSignal;
|
|
20
|
+
calls = 0;
|
|
21
|
+
inputTokens = 0;
|
|
22
|
+
outputTokens = 0;
|
|
23
|
+
exhausted = false;
|
|
24
|
+
deadline;
|
|
25
|
+
constructor(llm, budget, outerSignal) {
|
|
26
|
+
this.llm = llm;
|
|
27
|
+
this.budget = budget;
|
|
28
|
+
this.outerSignal = outerSignal;
|
|
29
|
+
this.deadline =
|
|
30
|
+
budget.timeoutMs !== undefined ? Date.now() + budget.timeoutMs : Number.POSITIVE_INFINITY;
|
|
31
|
+
}
|
|
32
|
+
/** Time left before the deadline, ms (`Infinity` without one). */
|
|
33
|
+
remainingMs() {
|
|
34
|
+
return this.deadline - Date.now();
|
|
35
|
+
}
|
|
36
|
+
/** Would a call with this prompt fit? Does not reserve anything; a `false` marks the budget exhausted. */
|
|
37
|
+
fits(prompt, maxOutputTokens) {
|
|
38
|
+
const fits = this.limitHit(prompt, maxOutputTokens) === undefined;
|
|
39
|
+
if (!fits) {
|
|
40
|
+
this.exhausted = true;
|
|
41
|
+
}
|
|
42
|
+
return fits;
|
|
43
|
+
}
|
|
44
|
+
limitHit(prompt, maxOutputTokens) {
|
|
45
|
+
if (this.calls >= this.budget.maxCalls) {
|
|
46
|
+
return 'calls';
|
|
47
|
+
}
|
|
48
|
+
if (this.inputTokens + estimateTokens(prompt) > this.budget.maxInputTokens) {
|
|
49
|
+
return 'inputTokens';
|
|
50
|
+
}
|
|
51
|
+
// A reply may be shorter than its cap; only refuse when nothing at all is left.
|
|
52
|
+
if (this.outputTokens + Math.min(maxOutputTokens, 16) > this.budget.maxOutputTokens) {
|
|
53
|
+
return 'outputTokens';
|
|
54
|
+
}
|
|
55
|
+
if (this.remainingMs() <= 0 || this.outerSignal?.aborted) {
|
|
56
|
+
return 'timeout';
|
|
57
|
+
}
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Make one call, or throw {@link TreeBudgetExceededError} without calling. Provider errors
|
|
62
|
+
* propagate (after being counted). Never retries.
|
|
63
|
+
*/
|
|
64
|
+
async call(task, system, prompt, maxOutputTokens) {
|
|
65
|
+
const limit = this.limitHit(system + prompt, maxOutputTokens);
|
|
66
|
+
if (limit !== undefined) {
|
|
67
|
+
this.exhausted = true;
|
|
68
|
+
throw new TreeBudgetExceededError(limit);
|
|
69
|
+
}
|
|
70
|
+
const outputCap = Math.max(16, Math.min(maxOutputTokens, this.budget.maxOutputTokens - this.outputTokens));
|
|
71
|
+
const timeoutMs = Math.min(this.budget.callTimeoutMs ?? Number.POSITIVE_INFINITY, this.remainingMs());
|
|
72
|
+
// Reserve the estimate now so concurrent calls cannot all pass the check on the same headroom;
|
|
73
|
+
// it is corrected to the reported usage when the reply arrives.
|
|
74
|
+
const reservedInput = estimateTokens(system + prompt);
|
|
75
|
+
this.inputTokens += reservedInput;
|
|
76
|
+
this.outputTokens += outputCap;
|
|
77
|
+
const controller = new AbortController();
|
|
78
|
+
const onOuterAbort = () => controller.abort(this.outerSignal?.reason);
|
|
79
|
+
this.outerSignal?.addEventListener('abort', onOuterAbort, { once: true });
|
|
80
|
+
let timer;
|
|
81
|
+
this.calls += 1;
|
|
82
|
+
try {
|
|
83
|
+
const response = await Promise.race([
|
|
84
|
+
this.llm({ task, system, prompt, maxOutputTokens: outputCap, signal: controller.signal }),
|
|
85
|
+
new Promise((_, reject) => {
|
|
86
|
+
if (Number.isFinite(timeoutMs)) {
|
|
87
|
+
timer = setTimeout(() => {
|
|
88
|
+
controller.abort(new TreeBudgetExceededError('timeout'));
|
|
89
|
+
reject(new TreeBudgetExceededError('timeout'));
|
|
90
|
+
}, Math.max(0, timeoutMs));
|
|
91
|
+
}
|
|
92
|
+
}),
|
|
93
|
+
]);
|
|
94
|
+
this.inputTokens += (response.usage?.inputTokens ?? reservedInput) - reservedInput;
|
|
95
|
+
this.outputTokens +=
|
|
96
|
+
(response.usage?.outputTokens ?? estimateTokens(response.text)) - outputCap;
|
|
97
|
+
return response.text;
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
// A failed call keeps its input estimate (the provider may have billed it) but no output.
|
|
101
|
+
this.outputTokens -= outputCap;
|
|
102
|
+
if (error instanceof TreeBudgetExceededError) {
|
|
103
|
+
this.exhausted = true;
|
|
104
|
+
}
|
|
105
|
+
throw error;
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
if (timer !== undefined) {
|
|
109
|
+
clearTimeout(timer);
|
|
110
|
+
}
|
|
111
|
+
this.outerSignal?.removeEventListener('abort', onOuterAbort);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Pull the JSON object out of a model reply: bare, fenced in ```json, or surrounded by prose.
|
|
117
|
+
* Returns `undefined` when there is none (never throws).
|
|
118
|
+
*/
|
|
119
|
+
export function parseJsonReply(text) {
|
|
120
|
+
const tryParse = (candidate) => {
|
|
121
|
+
try {
|
|
122
|
+
const value = JSON.parse(candidate);
|
|
123
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
124
|
+
? value
|
|
125
|
+
: undefined;
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
const trimmed = text.trim();
|
|
132
|
+
const direct = tryParse(trimmed);
|
|
133
|
+
if (direct !== undefined) {
|
|
134
|
+
return direct;
|
|
135
|
+
}
|
|
136
|
+
const fenced = /```(?:json)?\s*([\s\S]*?)```/i.exec(trimmed);
|
|
137
|
+
if (fenced?.[1] !== undefined) {
|
|
138
|
+
const inner = tryParse(fenced[1].trim());
|
|
139
|
+
if (inner !== undefined) {
|
|
140
|
+
return inner;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const start = trimmed.indexOf('{');
|
|
144
|
+
const end = trimmed.lastIndexOf('}');
|
|
145
|
+
if (start >= 0 && end > start) {
|
|
146
|
+
return tryParse(trimmed.slice(start, end + 1));
|
|
147
|
+
}
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
/** The strings in a JSON array value (numbers stringified); anything else yields `[]`. */
|
|
151
|
+
export function stringList(value) {
|
|
152
|
+
if (!Array.isArray(value)) {
|
|
153
|
+
return [];
|
|
154
|
+
}
|
|
155
|
+
return value
|
|
156
|
+
.map((item) => (typeof item === 'number' ? String(item) : item))
|
|
157
|
+
.filter((item) => typeof item === 'string');
|
|
158
|
+
}
|
|
159
|
+
const NOOP_SINK = {
|
|
160
|
+
write() { },
|
|
161
|
+
end() { },
|
|
162
|
+
};
|
|
163
|
+
/**
|
|
164
|
+
* A {@link TreeLlm} over the agent's own {@link ModelProvider}: one `runTurn` with no tools and a
|
|
165
|
+
* discarding sink. Usage comes from the provider's report.
|
|
166
|
+
*/
|
|
167
|
+
export function treeLlmFromModelProvider(provider) {
|
|
168
|
+
return async (request) => {
|
|
169
|
+
const result = await provider.runTurn({
|
|
170
|
+
system: request.system,
|
|
171
|
+
messages: [{ role: 'user', content: request.prompt }],
|
|
172
|
+
tools: [],
|
|
173
|
+
sink: NOOP_SINK,
|
|
174
|
+
abortSignal: request.signal,
|
|
175
|
+
});
|
|
176
|
+
return {
|
|
177
|
+
text: result.text,
|
|
178
|
+
usage: { inputTokens: result.usage.inputTokens, outputTokens: result.usage.outputTokens },
|
|
179
|
+
};
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* A {@link TreeLlm} over any OpenAI-compatible `POST /v1/chat/completions` — OpenAI, a gateway,
|
|
184
|
+
* vLLM, Ollama, DeepSeek, Qwen… — with no SDK dependency. Throws `HttpModelError` on a non-2xx.
|
|
185
|
+
*/
|
|
186
|
+
export function openAiChatTreeLlm(options) {
|
|
187
|
+
const url = `${(options.baseUrl ?? 'https://api.openai.com/v1').replace(/\/+$/, '')}/chat/completions`;
|
|
188
|
+
const doFetch = options.fetch ?? fetch;
|
|
189
|
+
return async (request) => {
|
|
190
|
+
const json = request.task.kind !== 'summarize';
|
|
191
|
+
const response = await doFetch(url, {
|
|
192
|
+
method: 'POST',
|
|
193
|
+
headers: {
|
|
194
|
+
'content-type': 'application/json',
|
|
195
|
+
...(options.apiKey ? { authorization: `Bearer ${options.apiKey}` } : {}),
|
|
196
|
+
...options.headers,
|
|
197
|
+
},
|
|
198
|
+
body: JSON.stringify({
|
|
199
|
+
model: options.model,
|
|
200
|
+
messages: [
|
|
201
|
+
{ role: 'system', content: request.system },
|
|
202
|
+
{ role: 'user', content: request.prompt },
|
|
203
|
+
],
|
|
204
|
+
temperature: options.temperature ?? 0,
|
|
205
|
+
max_tokens: request.maxOutputTokens,
|
|
206
|
+
...(options.jsonMode && json ? { response_format: { type: 'json_object' } } : {}),
|
|
207
|
+
...options.body,
|
|
208
|
+
}),
|
|
209
|
+
signal: request.signal,
|
|
210
|
+
});
|
|
211
|
+
const body = await response.text();
|
|
212
|
+
if (!response.ok) {
|
|
213
|
+
throw new HttpModelError(response.status, `Chat completion failed (${response.status}): ${errorMessageOf(body)}`);
|
|
214
|
+
}
|
|
215
|
+
const parsed = parseJsonReply(body);
|
|
216
|
+
const content = parsed?.choices?.[0]?.message?.content;
|
|
217
|
+
if (typeof content !== 'string') {
|
|
218
|
+
throw new HttpModelError(502, 'Chat completion returned no message content');
|
|
219
|
+
}
|
|
220
|
+
const usage = {};
|
|
221
|
+
if (typeof parsed?.usage?.prompt_tokens === 'number') {
|
|
222
|
+
usage.inputTokens = parsed.usage.prompt_tokens;
|
|
223
|
+
}
|
|
224
|
+
if (typeof parsed?.usage?.completion_tokens === 'number') {
|
|
225
|
+
usage.outputTokens = parsed.usage.completion_tokens;
|
|
226
|
+
}
|
|
227
|
+
return { text: content, usage };
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Memoize a {@link TreeLlm} by the exact request (task kind, system prompt, prompt, output cap).
|
|
232
|
+
* With a deterministic model that makes a rebuild of an unchanged section, or a repeated question,
|
|
233
|
+
* free. Cached replies report zero usage, so they cost nothing against a budget but a call slot.
|
|
234
|
+
*/
|
|
235
|
+
export function cachedTreeLlm(llm, cache = new Map()) {
|
|
236
|
+
return async (request) => {
|
|
237
|
+
const key = stableHash(`${request.task.kind}\u0000${request.maxOutputTokens}\u0000${request.system}\u0000${request.prompt}`);
|
|
238
|
+
const hit = await cache.get(key);
|
|
239
|
+
if (hit !== undefined) {
|
|
240
|
+
return { text: hit.text, usage: { inputTokens: 0, outputTokens: 0 } };
|
|
241
|
+
}
|
|
242
|
+
const response = await llm(request);
|
|
243
|
+
await cache.set(key, response);
|
|
244
|
+
return response;
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* A fast, deterministic, non-cryptographic 64-bit hash (two independent 32-bit FNV-1a/murmur-mixed
|
|
249
|
+
* lanes) as 16 hex chars — content fingerprints and cache keys, not security.
|
|
250
|
+
*/
|
|
251
|
+
export function stableHash(text) {
|
|
252
|
+
let h1 = 0x811c9dc5;
|
|
253
|
+
let h2 = 0x01000193 ^ text.length;
|
|
254
|
+
for (let i = 0; i < text.length; i++) {
|
|
255
|
+
const c = text.charCodeAt(i);
|
|
256
|
+
h1 = Math.imul(h1 ^ c, 0x01000193);
|
|
257
|
+
h2 = Math.imul(h2 ^ c, 0x5bd1e995);
|
|
258
|
+
h2 ^= h2 >>> 13;
|
|
259
|
+
}
|
|
260
|
+
h1 = Math.imul(h1 ^ (h1 >>> 16), 0x85ebca6b);
|
|
261
|
+
h2 = Math.imul(h2 ^ (h2 >>> 15), 0xc2b2ae35);
|
|
262
|
+
return (h1 >>> 0).toString(16).padStart(8, '0') + (h2 >>> 0).toString(16).padStart(8, '0');
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=llm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm.js","sourceRoot":"","sources":["../../../../src/rag/tree/llm.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { type BrandedFunctionalTool } from '../../ai-tool-ref.js';
|
|
2
|
+
import type { Passage } from '../../spi/retriever.js';
|
|
3
|
+
import type { AiToolCtx } from '../../spi/tool.js';
|
|
4
|
+
import type { TreeBudget } from './llm.js';
|
|
5
|
+
import type { NavigatedNode, NavigationStep, TreeNavigationRetriever } from './navigate.js';
|
|
6
|
+
export interface NavigateDocumentToolOptions {
|
|
7
|
+
/** Tool name the model sees. Default `navigate_document`. */
|
|
8
|
+
name?: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
/**
|
|
11
|
+
* The access filter for this call, from the tool context — e.g. `(ctx) => ({ tenant: ctx.actor.tenantRef })`.
|
|
12
|
+
* Applied to the tree read, with the vector stores' semantics. Omit only for single-tenant corpora.
|
|
13
|
+
*/
|
|
14
|
+
filter?: (ctx: AiToolCtx) => Record<string, unknown> | undefined;
|
|
15
|
+
/** Per-call navigation budget (overrides the navigator's). */
|
|
16
|
+
budget?: TreeBudget;
|
|
17
|
+
/** Roles allowed to invoke. Omit to inherit the config's `defaultRoles`. */
|
|
18
|
+
roles?: string[];
|
|
19
|
+
/** Authz ability for an ability-aware `RolesPolicy`. */
|
|
20
|
+
ability?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface NavigateDocumentInput {
|
|
23
|
+
documentId: string;
|
|
24
|
+
question: string;
|
|
25
|
+
}
|
|
26
|
+
export interface NavigateDocumentOutput {
|
|
27
|
+
documentId: string;
|
|
28
|
+
/** `false` when the document has no tree (short documents don't get one) or the caller may not read it. */
|
|
29
|
+
found: boolean;
|
|
30
|
+
passages: Passage[];
|
|
31
|
+
/** The sections chosen and the path to each. */
|
|
32
|
+
nodes: NavigatedNode[];
|
|
33
|
+
/** The walk, step by step, with the model's reasoning. */
|
|
34
|
+
steps: NavigationStep[];
|
|
35
|
+
stoppedBy?: string;
|
|
36
|
+
note?: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The agentic half of two-stage retrieval: `navigate_document(documentId, question)`, a `read`-kind
|
|
40
|
+
* tool the model calls **after** a search put a long document among its hits — it walks that
|
|
41
|
+
* document's table of contents to the sections that answer and returns their text, with the path and
|
|
42
|
+
* reasoning (the citation surface: section titles and page ranges).
|
|
43
|
+
*
|
|
44
|
+
* `documentId` may also be a chunk id from a search result (`doc#12`); the chunk suffix is dropped.
|
|
45
|
+
* A document with no tree answers `found: false` with a note, so the model falls back to the
|
|
46
|
+
* passages it already has instead of retrying.
|
|
47
|
+
*
|
|
48
|
+
* Returns a {@link defineTool} tool: export it from an `app/agent_tools` module, or pass it to
|
|
49
|
+
* `defineConfig({ tools })`.
|
|
50
|
+
*
|
|
51
|
+
* ```ts
|
|
52
|
+
* export const navigateDocument = createNavigateDocumentTool(navigator, {
|
|
53
|
+
* filter: (ctx) => ({ tenant: ctx.actor.tenantRef }),
|
|
54
|
+
* })
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare function createNavigateDocumentTool(navigator: TreeNavigationRetriever, options?: NavigateDocumentToolOptions): BrandedFunctionalTool;
|
|
58
|
+
//# sourceMappingURL=navigate-tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigate-tool.d.ts","sourceRoot":"","sources":["../../../../src/rag/tree/navigate-tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,qBAAqB,EAAc,MAAM,sBAAsB,CAAC;AAC9E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAE5F,MAAM,WAAW,2BAA2B;IAC1C,6DAA6D;IAC7D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACjE,8DAA8D;IAC9D,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,2GAA2G;IAC3G,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,gDAAgD;IAChD,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,0DAA0D;IAC1D,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AA2BD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,uBAAuB,EAClC,OAAO,GAAE,2BAAgC,GACxC,qBAAqB,CAuDvB"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { defineTool } from '../../ai-tool-ref.js';
|
|
2
|
+
import { documentIdOf } from '../vector-store.js';
|
|
3
|
+
function isInput(value) {
|
|
4
|
+
return (typeof value === 'object' &&
|
|
5
|
+
value !== null &&
|
|
6
|
+
typeof value.documentId === 'string' &&
|
|
7
|
+
typeof value.question === 'string');
|
|
8
|
+
}
|
|
9
|
+
const inputSchema = {
|
|
10
|
+
'~standard': {
|
|
11
|
+
version: 1,
|
|
12
|
+
vendor: 'adonis-agora-agent',
|
|
13
|
+
validate(value) {
|
|
14
|
+
return isInput(value)
|
|
15
|
+
? { value: { documentId: value.documentId, question: value.question } }
|
|
16
|
+
: {
|
|
17
|
+
issues: [
|
|
18
|
+
{ message: 'navigate_document expects { documentId: string, question: string }' },
|
|
19
|
+
],
|
|
20
|
+
};
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* The agentic half of two-stage retrieval: `navigate_document(documentId, question)`, a `read`-kind
|
|
26
|
+
* tool the model calls **after** a search put a long document among its hits — it walks that
|
|
27
|
+
* document's table of contents to the sections that answer and returns their text, with the path and
|
|
28
|
+
* reasoning (the citation surface: section titles and page ranges).
|
|
29
|
+
*
|
|
30
|
+
* `documentId` may also be a chunk id from a search result (`doc#12`); the chunk suffix is dropped.
|
|
31
|
+
* A document with no tree answers `found: false` with a note, so the model falls back to the
|
|
32
|
+
* passages it already has instead of retrying.
|
|
33
|
+
*
|
|
34
|
+
* Returns a {@link defineTool} tool: export it from an `app/agent_tools` module, or pass it to
|
|
35
|
+
* `defineConfig({ tools })`.
|
|
36
|
+
*
|
|
37
|
+
* ```ts
|
|
38
|
+
* export const navigateDocument = createNavigateDocumentTool(navigator, {
|
|
39
|
+
* filter: (ctx) => ({ tenant: ctx.actor.tenantRef }),
|
|
40
|
+
* })
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export function createNavigateDocumentTool(navigator, options = {}) {
|
|
44
|
+
return defineTool({
|
|
45
|
+
name: options.name ?? 'navigate_document',
|
|
46
|
+
kind: 'read',
|
|
47
|
+
description: options.description ??
|
|
48
|
+
'Read inside one long document (regulation, contract, filing, manual) by navigating its table of contents to the sections that answer a question. Use it after a search returned a long document: pass that document id and the question. Returns the matching sections with titles and page ranges for citation.',
|
|
49
|
+
input: inputSchema,
|
|
50
|
+
...(options.roles !== undefined ? { roles: options.roles } : {}),
|
|
51
|
+
...(options.ability !== undefined ? { ability: options.ability } : {}),
|
|
52
|
+
}, async (input, ctx) => {
|
|
53
|
+
if (!isInput(input)) {
|
|
54
|
+
throw new Error('navigate_document expects { documentId: string, question: string }');
|
|
55
|
+
}
|
|
56
|
+
const filter = options.filter?.(ctx);
|
|
57
|
+
const navigateOptions = {
|
|
58
|
+
...(filter !== undefined ? { filter } : {}),
|
|
59
|
+
...(options.budget !== undefined ? { budget: options.budget } : {}),
|
|
60
|
+
};
|
|
61
|
+
let documentId = input.documentId.trim();
|
|
62
|
+
let result = await navigator.navigate(input.question, [documentId], navigateOptions);
|
|
63
|
+
let navigation = result.documents[0];
|
|
64
|
+
if (navigation?.stoppedBy === 'not-found') {
|
|
65
|
+
const bare = documentIdOf(documentId.replace(/#node:\d+$/, ''));
|
|
66
|
+
if (bare !== documentId) {
|
|
67
|
+
documentId = bare;
|
|
68
|
+
result = await navigator.navigate(input.question, [documentId], navigateOptions);
|
|
69
|
+
navigation = result.documents[0];
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (navigation === undefined || navigation.stoppedBy === 'not-found') {
|
|
73
|
+
return {
|
|
74
|
+
documentId,
|
|
75
|
+
found: false,
|
|
76
|
+
passages: [],
|
|
77
|
+
nodes: [],
|
|
78
|
+
steps: [],
|
|
79
|
+
note: 'This document has no navigable table of contents (it is short, not indexed, or not accessible). Use the search passages instead.',
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
documentId,
|
|
84
|
+
found: true,
|
|
85
|
+
passages: result.passages,
|
|
86
|
+
nodes: navigation.nodes,
|
|
87
|
+
steps: navigation.steps,
|
|
88
|
+
...(navigation.stoppedBy !== undefined ? { stoppedBy: navigation.stoppedBy } : {}),
|
|
89
|
+
...(navigation.nodes.length === 0
|
|
90
|
+
? { note: 'No section of this document looked relevant to the question.' }
|
|
91
|
+
: {}),
|
|
92
|
+
};
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=navigate-tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigate-tool.js","sourceRoot":"","sources":["../../../../src/rag/tree/navigate-tool.ts"],"names":[],"mappings":"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"}
|