@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,137 @@
|
|
|
1
|
+
import type { Passage, RetrieveOptions, Retriever } from '../../spi/retriever.js';
|
|
2
|
+
import { type TreeBudget, type TreeLlm } from './llm.js';
|
|
3
|
+
import type { DocumentTreeStore } from './store.js';
|
|
4
|
+
export interface TreeNavigationRetrieverOptions {
|
|
5
|
+
store: DocumentTreeStore;
|
|
6
|
+
llm: TreeLlm;
|
|
7
|
+
/**
|
|
8
|
+
* A tree whose outline (titles, pages, summaries) fits in this many characters is navigated in
|
|
9
|
+
* **one** call that sees the whole outline — PageIndex's tree search, the variant measured in the
|
|
10
|
+
* benchmark. Bigger trees are walked level by level (a beam). Default 40 000 (~10k tokens).
|
|
11
|
+
*/
|
|
12
|
+
singlePassMaxChars?: number;
|
|
13
|
+
/** Nodes the navigator may expand or read per beam step. Default 4. */
|
|
14
|
+
beamWidth?: number;
|
|
15
|
+
/** Beam levels, at most. Nodes still marked "expand" at the last level are read whole. Default 4. */
|
|
16
|
+
maxSteps?: number;
|
|
17
|
+
/** Nodes returned per document, at most. Default 5. */
|
|
18
|
+
maxNodes?: number;
|
|
19
|
+
/**
|
|
20
|
+
* Hard per-document limits for one navigation. Defaults: 6 calls, 60k input tokens, 4k output
|
|
21
|
+
* tokens, 60 s. Running out mid-walk returns what was chosen so far (the nodes last marked for
|
|
22
|
+
* expansion are read whole) and records `stoppedBy: 'budget'`.
|
|
23
|
+
*/
|
|
24
|
+
budget?: TreeBudget;
|
|
25
|
+
/** Characters of text per returned node. Default 12 000. */
|
|
26
|
+
maxPassageChars?: number;
|
|
27
|
+
/** Units (pages/sections) read per returned node, at most. Default 25. */
|
|
28
|
+
maxUnitsPerNode?: number;
|
|
29
|
+
/** Characters across all passages of one navigation (every document). Default 48 000 (~12k tokens). */
|
|
30
|
+
maxContextChars?: number;
|
|
31
|
+
/**
|
|
32
|
+
* {@link TreeNavigationRetriever.retrieve} with no first stage: documents navigated per query. When
|
|
33
|
+
* more trees pass the filter, the LLM picks this many from their titles and descriptions
|
|
34
|
+
* (PageIndex's document selection). Default 3.
|
|
35
|
+
*/
|
|
36
|
+
maxDocuments?: number;
|
|
37
|
+
/** Trees shown to document selection, at most. Default 200. */
|
|
38
|
+
maxSelectionCandidates?: number;
|
|
39
|
+
/** Documents navigated in parallel. Default 3. */
|
|
40
|
+
concurrency?: number;
|
|
41
|
+
}
|
|
42
|
+
/** One step of a navigation, for the audit trail. */
|
|
43
|
+
export interface NavigationStep {
|
|
44
|
+
step: number;
|
|
45
|
+
/** Node ids shown to the LLM this step. */
|
|
46
|
+
shown: string[];
|
|
47
|
+
/** Node ids it chose to open further. */
|
|
48
|
+
expanded: string[];
|
|
49
|
+
/** Node ids it chose to read. */
|
|
50
|
+
read: string[];
|
|
51
|
+
/** The LLM's stated reasoning, verbatim (capped). */
|
|
52
|
+
reasoning?: string;
|
|
53
|
+
}
|
|
54
|
+
/** A node navigation chose, with the path that led to it. */
|
|
55
|
+
export interface NavigatedNode {
|
|
56
|
+
nodeId: string;
|
|
57
|
+
title: string;
|
|
58
|
+
/** Ancestors from the top level down, then the node itself. */
|
|
59
|
+
path: {
|
|
60
|
+
id: string;
|
|
61
|
+
title: string;
|
|
62
|
+
}[];
|
|
63
|
+
pageStart?: number;
|
|
64
|
+
pageEnd?: number;
|
|
65
|
+
unitStart: number;
|
|
66
|
+
unitEnd: number;
|
|
67
|
+
}
|
|
68
|
+
/** The auditable record of navigating one document. */
|
|
69
|
+
export interface DocumentNavigation {
|
|
70
|
+
documentId: string;
|
|
71
|
+
title?: string;
|
|
72
|
+
mode: 'single-pass' | 'beam';
|
|
73
|
+
steps: NavigationStep[];
|
|
74
|
+
nodes: NavigatedNode[];
|
|
75
|
+
llmCalls: number;
|
|
76
|
+
inputTokens: number;
|
|
77
|
+
outputTokens: number;
|
|
78
|
+
/** Why the walk stopped early, when it did. */
|
|
79
|
+
stoppedBy?: 'budget' | 'timeout' | 'maxSteps' | 'error' | 'not-found';
|
|
80
|
+
error?: string;
|
|
81
|
+
}
|
|
82
|
+
export interface NavigationResult {
|
|
83
|
+
passages: Passage[];
|
|
84
|
+
documents: DocumentNavigation[];
|
|
85
|
+
/** Set when {@link TreeNavigationRetriever.retrieve} had the LLM pick the documents. */
|
|
86
|
+
selection?: {
|
|
87
|
+
candidates: number;
|
|
88
|
+
selected: string[];
|
|
89
|
+
reasoning?: string;
|
|
90
|
+
error?: string;
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
export interface NavigateOptions {
|
|
94
|
+
/** Access filter applied to every tree read (vector-store semantics). */
|
|
95
|
+
filter?: Record<string, unknown>;
|
|
96
|
+
/** Overrides the retriever's per-document budget. */
|
|
97
|
+
budget?: TreeBudget;
|
|
98
|
+
signal?: AbortSignal;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Tree navigation retrieval ("vectorless", reasoning-based — PageIndex's method): an LLM reads a
|
|
102
|
+
* document's table of contents (titles, page ranges, summaries — no body text) and picks the
|
|
103
|
+
* sections that answer the question; their text comes back as passages, with the path taken and the
|
|
104
|
+
* model's reasoning recorded so the choice is auditable.
|
|
105
|
+
*
|
|
106
|
+
* A small tree is navigated in one call over the whole outline. A large one is walked level by
|
|
107
|
+
* level: the model sees one level of candidates, opens (`expand`) the promising ones and takes
|
|
108
|
+
* (`read`) the ones that already answer, until it reaches leaves, runs out of `maxSteps`, or runs
|
|
109
|
+
* out of its hard per-document {@link TreeBudget} — in which case it returns what it had.
|
|
110
|
+
*
|
|
111
|
+
* It pays off on **long structured documents** (regulations, contracts, filings, manuals) where
|
|
112
|
+
* chunk ranking struggles among hundreds of look-alike passages; on short notes it costs seconds and
|
|
113
|
+
* LLM spend for nothing. Compose it behind a first stage with {@link TwoStageRetriever}, or give it
|
|
114
|
+
* to the agent as a tool with {@link createNavigateDocumentTool}.
|
|
115
|
+
*
|
|
116
|
+
* As a plain `Retriever`, `retrieve(query, { filter })` navigates the trees that pass `filter`:
|
|
117
|
+
* all of them when there are at most `maxDocuments`, otherwise the ones the LLM picks from their
|
|
118
|
+
* descriptions.
|
|
119
|
+
*/
|
|
120
|
+
export declare class TreeNavigationRetriever implements Retriever {
|
|
121
|
+
private readonly options;
|
|
122
|
+
readonly store: DocumentTreeStore;
|
|
123
|
+
private readonly llm;
|
|
124
|
+
constructor(options: TreeNavigationRetrieverOptions);
|
|
125
|
+
retrieve(query: string, options?: RetrieveOptions): Promise<Passage[]>;
|
|
126
|
+
/** {@link retrieve} with the audit trail: which documents, which nodes, why. */
|
|
127
|
+
search(query: string, options?: NavigateOptions): Promise<NavigationResult>;
|
|
128
|
+
/**
|
|
129
|
+
* Navigate the given documents (in parallel, up to `concurrency`) and return their passages in
|
|
130
|
+
* the order given, within `maxContextChars`. Documents without a tree, or whose tree fails
|
|
131
|
+
* `filter`, yield no passages and `stoppedBy: 'not-found'`.
|
|
132
|
+
*/
|
|
133
|
+
navigate(query: string, documentIds: readonly string[], options?: NavigateOptions): Promise<NavigationResult>;
|
|
134
|
+
private walk;
|
|
135
|
+
private passagesOf;
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=navigate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigate.d.ts","sourceRoot":"","sources":["../../../../src/rag/tree/navigate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
import { mapLimit } from './build.js';
|
|
2
|
+
import { BudgetedLlm, parseJsonReply, stringList, TreeBudgetExceededError, } from './llm.js';
|
|
3
|
+
import { indexTree, walkTree } from './types.js';
|
|
4
|
+
const NAVIGATE_SYSTEM = 'You navigate the table of contents of a document to find where a question is answered. You answer with JSON only.';
|
|
5
|
+
const DEFAULT_BUDGET = {
|
|
6
|
+
maxCalls: 6,
|
|
7
|
+
maxInputTokens: 60_000,
|
|
8
|
+
maxOutputTokens: 4_000,
|
|
9
|
+
timeoutMs: 60_000,
|
|
10
|
+
};
|
|
11
|
+
function pages(node) {
|
|
12
|
+
if (node.pageStart === undefined) {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
return node.pageEnd === undefined || node.pageEnd === node.pageStart
|
|
16
|
+
? `p. ${node.pageStart}`
|
|
17
|
+
: `pp. ${node.pageStart}-${node.pageEnd}`;
|
|
18
|
+
}
|
|
19
|
+
function candidate(node, summaryChars, depth) {
|
|
20
|
+
const shownPages = pages(node);
|
|
21
|
+
let summary = node.summary;
|
|
22
|
+
if (summary !== undefined && summary.length > summaryChars) {
|
|
23
|
+
summary = `${summary.slice(0, Math.max(0, summaryChars - 1))}…`;
|
|
24
|
+
}
|
|
25
|
+
if (node.keyItems !== undefined && node.keyItems.length > 0 && summaryChars > 0) {
|
|
26
|
+
summary = `${summary ?? ''}${summary ? ' ' : ''}Includes: ${node.keyItems.slice(0, 12).join('; ')}`;
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
id: node.id,
|
|
30
|
+
title: node.title,
|
|
31
|
+
...(summary && summaryChars > 0 ? { summary } : {}),
|
|
32
|
+
...(shownPages !== undefined ? { pages: shownPages } : {}),
|
|
33
|
+
...(depth !== undefined ? { depth } : { hasChildren: node.children.length > 0 }),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function render(candidates) {
|
|
37
|
+
return candidates
|
|
38
|
+
.map((entry) => {
|
|
39
|
+
const indent = ' '.repeat(entry.depth ?? 0);
|
|
40
|
+
const meta = [entry.pages, entry.hasChildren ? 'has subsections' : undefined]
|
|
41
|
+
.filter(Boolean)
|
|
42
|
+
.join(', ');
|
|
43
|
+
return `${indent}[${entry.id}] ${entry.title}${meta ? ` (${meta})` : ''}${entry.summary ? ` — ${entry.summary}` : ''}`;
|
|
44
|
+
})
|
|
45
|
+
.join('\n');
|
|
46
|
+
}
|
|
47
|
+
/** Candidates rendered within `maxChars`: full summaries, then shorter, then titles only. */
|
|
48
|
+
function fitCandidates(nodes, maxChars) {
|
|
49
|
+
let last;
|
|
50
|
+
for (const summaryChars of [400, 160, 0]) {
|
|
51
|
+
const candidates = nodes.map(({ node, depth }) => candidate(node, summaryChars, depth));
|
|
52
|
+
const text = render(candidates);
|
|
53
|
+
last = { candidates, text };
|
|
54
|
+
if (text.length <= maxChars) {
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return last;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Tree navigation retrieval ("vectorless", reasoning-based — PageIndex's method): an LLM reads a
|
|
62
|
+
* document's table of contents (titles, page ranges, summaries — no body text) and picks the
|
|
63
|
+
* sections that answer the question; their text comes back as passages, with the path taken and the
|
|
64
|
+
* model's reasoning recorded so the choice is auditable.
|
|
65
|
+
*
|
|
66
|
+
* A small tree is navigated in one call over the whole outline. A large one is walked level by
|
|
67
|
+
* level: the model sees one level of candidates, opens (`expand`) the promising ones and takes
|
|
68
|
+
* (`read`) the ones that already answer, until it reaches leaves, runs out of `maxSteps`, or runs
|
|
69
|
+
* out of its hard per-document {@link TreeBudget} — in which case it returns what it had.
|
|
70
|
+
*
|
|
71
|
+
* It pays off on **long structured documents** (regulations, contracts, filings, manuals) where
|
|
72
|
+
* chunk ranking struggles among hundreds of look-alike passages; on short notes it costs seconds and
|
|
73
|
+
* LLM spend for nothing. Compose it behind a first stage with {@link TwoStageRetriever}, or give it
|
|
74
|
+
* to the agent as a tool with {@link createNavigateDocumentTool}.
|
|
75
|
+
*
|
|
76
|
+
* As a plain `Retriever`, `retrieve(query, { filter })` navigates the trees that pass `filter`:
|
|
77
|
+
* all of them when there are at most `maxDocuments`, otherwise the ones the LLM picks from their
|
|
78
|
+
* descriptions.
|
|
79
|
+
*/
|
|
80
|
+
export class TreeNavigationRetriever {
|
|
81
|
+
options;
|
|
82
|
+
store;
|
|
83
|
+
llm;
|
|
84
|
+
constructor(options) {
|
|
85
|
+
this.options = options;
|
|
86
|
+
this.store = options.store;
|
|
87
|
+
this.llm = options.llm;
|
|
88
|
+
}
|
|
89
|
+
async retrieve(query, options = {}) {
|
|
90
|
+
const result = await this.search(query, options.filter !== undefined ? { filter: options.filter } : {});
|
|
91
|
+
return result.passages.slice(0, options.topK ?? result.passages.length);
|
|
92
|
+
}
|
|
93
|
+
/** {@link retrieve} with the audit trail: which documents, which nodes, why. */
|
|
94
|
+
async search(query, options = {}) {
|
|
95
|
+
const maxDocuments = Math.max(1, this.options.maxDocuments ?? 3);
|
|
96
|
+
const maxCandidates = Math.max(maxDocuments, this.options.maxSelectionCandidates ?? 200);
|
|
97
|
+
const headers = await this.store.list({
|
|
98
|
+
...(options.filter !== undefined ? { filter: options.filter } : {}),
|
|
99
|
+
limit: maxCandidates,
|
|
100
|
+
});
|
|
101
|
+
if (headers.length <= maxDocuments) {
|
|
102
|
+
return this.navigate(query, headers.map((header) => header.documentId), options);
|
|
103
|
+
}
|
|
104
|
+
const budget = new BudgetedLlm(this.llm, { ...DEFAULT_BUDGET, ...this.options.budget, ...options.budget }, options.signal);
|
|
105
|
+
const documents = headers.map((header) => ({
|
|
106
|
+
id: header.documentId,
|
|
107
|
+
...(header.title !== undefined ? { title: header.title } : {}),
|
|
108
|
+
...(header.description !== undefined
|
|
109
|
+
? { description: header.description.slice(0, 600) }
|
|
110
|
+
: {}),
|
|
111
|
+
}));
|
|
112
|
+
const prompt = `Select the documents that may contain the answer to the question, most relevant first, at most ${maxDocuments}.
|
|
113
|
+
|
|
114
|
+
Question: ${query}
|
|
115
|
+
|
|
116
|
+
Documents:
|
|
117
|
+
${documents.map((document) => `[${document.id}] ${document.title ?? ''}${document.description ? ` — ${document.description}` : ''}`).join('\n')}
|
|
118
|
+
|
|
119
|
+
Reply with JSON only: {"thinking": "<why>", "documents": ["<document id>", ...]} — an empty list if none is relevant.`;
|
|
120
|
+
const known = new Set(documents.map((document) => document.id));
|
|
121
|
+
try {
|
|
122
|
+
const reply = parseJsonReply(await budget.call({ kind: 'select', query, documents, maxDocuments }, NAVIGATE_SYSTEM, prompt, 800));
|
|
123
|
+
const selected = [
|
|
124
|
+
...new Set(stringList(reply?.documents ?? reply?.answer).filter((id) => known.has(id))),
|
|
125
|
+
].slice(0, maxDocuments);
|
|
126
|
+
const result = await this.navigate(query, selected, options);
|
|
127
|
+
const reasoning = typeof reply?.thinking === 'string' ? reply.thinking.slice(0, 2_000) : undefined;
|
|
128
|
+
return {
|
|
129
|
+
...result,
|
|
130
|
+
selection: {
|
|
131
|
+
candidates: documents.length,
|
|
132
|
+
selected,
|
|
133
|
+
...(reasoning !== undefined ? { reasoning } : {}),
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
return {
|
|
139
|
+
passages: [],
|
|
140
|
+
documents: [],
|
|
141
|
+
selection: { candidates: documents.length, selected: [], error: error.message },
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Navigate the given documents (in parallel, up to `concurrency`) and return their passages in
|
|
147
|
+
* the order given, within `maxContextChars`. Documents without a tree, or whose tree fails
|
|
148
|
+
* `filter`, yield no passages and `stoppedBy: 'not-found'`.
|
|
149
|
+
*/
|
|
150
|
+
async navigate(query, documentIds, options = {}) {
|
|
151
|
+
const ids = [...new Set(documentIds)];
|
|
152
|
+
const trees = new Map((await this.store.getMany(ids, options.filter)).map((tree) => [tree.documentId, tree]));
|
|
153
|
+
const navigations = await mapLimit(ids, Math.max(1, this.options.concurrency ?? 3), async (id) => {
|
|
154
|
+
const tree = trees.get(id);
|
|
155
|
+
if (tree === undefined) {
|
|
156
|
+
return {
|
|
157
|
+
navigation: {
|
|
158
|
+
documentId: id,
|
|
159
|
+
mode: 'single-pass',
|
|
160
|
+
steps: [],
|
|
161
|
+
nodes: [],
|
|
162
|
+
llmCalls: 0,
|
|
163
|
+
inputTokens: 0,
|
|
164
|
+
outputTokens: 0,
|
|
165
|
+
stoppedBy: 'not-found',
|
|
166
|
+
},
|
|
167
|
+
passages: [],
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
const navigation = await this.walk(query, tree, options);
|
|
171
|
+
return { navigation, passages: await this.passagesOf(tree, navigation) };
|
|
172
|
+
});
|
|
173
|
+
// Share the context budget across documents in the order given.
|
|
174
|
+
const maxContextChars = this.options.maxContextChars ?? 48_000;
|
|
175
|
+
let used = 0;
|
|
176
|
+
const passages = [];
|
|
177
|
+
for (const entry of navigations) {
|
|
178
|
+
for (const passage of entry.passages) {
|
|
179
|
+
if (used >= maxContextChars) {
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
const text = passage.text.slice(0, maxContextChars - used);
|
|
183
|
+
used += text.length;
|
|
184
|
+
passages.push({ ...passage, text });
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return { passages, documents: navigations.map((entry) => entry.navigation) };
|
|
188
|
+
}
|
|
189
|
+
async walk(query, tree, options) {
|
|
190
|
+
const budget = new BudgetedLlm(this.llm, { ...DEFAULT_BUDGET, ...this.options.budget, ...options.budget }, options.signal);
|
|
191
|
+
const maxNodes = Math.max(1, this.options.maxNodes ?? 5);
|
|
192
|
+
const singlePassMaxChars = this.options.singlePassMaxChars ?? 40_000;
|
|
193
|
+
const index = indexTree(tree);
|
|
194
|
+
const whole = [...walkTree(tree.nodes)].map(({ node, path }) => ({ node, depth: path.length }));
|
|
195
|
+
const outline = fitCandidates(whole, Number.POSITIVE_INFINITY);
|
|
196
|
+
const title = tree.title ?? tree.source ?? tree.documentId;
|
|
197
|
+
const steps = [];
|
|
198
|
+
const chosen = [];
|
|
199
|
+
let stoppedBy;
|
|
200
|
+
let error;
|
|
201
|
+
const mode = outline.text.length <= singlePassMaxChars ? 'single-pass' : 'beam';
|
|
202
|
+
const stop = (caught) => {
|
|
203
|
+
if (caught instanceof TreeBudgetExceededError) {
|
|
204
|
+
stoppedBy = caught.limit === 'timeout' ? 'timeout' : 'budget';
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
stoppedBy = 'error';
|
|
208
|
+
}
|
|
209
|
+
error = caught.message;
|
|
210
|
+
};
|
|
211
|
+
if (mode === 'single-pass') {
|
|
212
|
+
const prompt = `Find the sections of the document that are likely to contain the answer to the question. Prefer the most specific (deepest) sections; list at most ${maxNodes}, most relevant first.
|
|
213
|
+
|
|
214
|
+
Question: ${query}
|
|
215
|
+
|
|
216
|
+
Document: ${title}${tree.description ? `\nAbout: ${tree.description}` : ''}
|
|
217
|
+
Table of contents ([id] title (pages) — summary):
|
|
218
|
+
${outline.text}
|
|
219
|
+
|
|
220
|
+
Reply with JSON only: {"thinking": "<which sections answer and why>", "read": ["<id>", ...]} — an empty list if none does.`;
|
|
221
|
+
try {
|
|
222
|
+
const reply = requireJson(await budget.call({ kind: 'navigate', query, mode, candidates: outline.candidates, maxNodes }, NAVIGATE_SYSTEM, prompt, 1_500));
|
|
223
|
+
const read = [...new Set(stringList(reply?.read ?? reply?.node_list ?? reply?.nodes))]
|
|
224
|
+
.map((id) => resolveId(index, id))
|
|
225
|
+
.filter((id) => id !== undefined)
|
|
226
|
+
.slice(0, maxNodes);
|
|
227
|
+
chosen.push(...read);
|
|
228
|
+
steps.push({
|
|
229
|
+
step: 1,
|
|
230
|
+
shown: outline.candidates.map((entry) => entry.id),
|
|
231
|
+
expanded: [],
|
|
232
|
+
read,
|
|
233
|
+
...reasoningOf(reply),
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
catch (caught) {
|
|
237
|
+
stop(caught);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
const beamWidth = Math.max(1, this.options.beamWidth ?? 4);
|
|
242
|
+
const maxSteps = Math.max(1, this.options.maxSteps ?? 4);
|
|
243
|
+
let frontier = tree.nodes;
|
|
244
|
+
let pendingExpand = [];
|
|
245
|
+
for (let step = 1; frontier.length > 0 && chosen.length < maxNodes; step++) {
|
|
246
|
+
if (step > maxSteps) {
|
|
247
|
+
stoppedBy = 'maxSteps';
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
const shown = fitCandidates(frontier.map((node) => ({ node })), singlePassMaxChars);
|
|
251
|
+
const path = index.get(frontier[0]?.id ?? '')?.path ?? [];
|
|
252
|
+
const where = path.length > 0 ? `\nYou are inside: ${path.map((node) => node.title).join(' > ')}` : '';
|
|
253
|
+
const prompt = `Find where the question is answered in the document by walking its table of contents.
|
|
254
|
+
For each relevant section below, either "expand" it (open its subsections, only for sections that have subsections) or "read" it (its text answers the question). Choose at most ${beamWidth} in total, most relevant first; choose none if nothing here is relevant.
|
|
255
|
+
|
|
256
|
+
Question: ${query}
|
|
257
|
+
|
|
258
|
+
Document: ${title}${tree.description ? `\nAbout: ${tree.description}` : ''}${where}
|
|
259
|
+
Sections ([id] title (pages) — summary):
|
|
260
|
+
${shown.text}
|
|
261
|
+
|
|
262
|
+
Reply with JSON only: {"thinking": "<why>", "expand": ["<id>", ...], "read": ["<id>", ...]}`;
|
|
263
|
+
let reply;
|
|
264
|
+
try {
|
|
265
|
+
reply = requireJson(await budget.call({ kind: 'navigate', query, mode, candidates: shown.candidates, maxNodes: beamWidth }, NAVIGATE_SYSTEM, prompt, 1_200));
|
|
266
|
+
}
|
|
267
|
+
catch (caught) {
|
|
268
|
+
stop(caught);
|
|
269
|
+
break;
|
|
270
|
+
}
|
|
271
|
+
const onFrontier = new Set(frontier.map((node) => node.id));
|
|
272
|
+
const pick = (value) => [...new Set(stringList(value))]
|
|
273
|
+
.map((id) => resolveId(index, id))
|
|
274
|
+
.filter((id) => id !== undefined && onFrontier.has(id));
|
|
275
|
+
let expand = pick(reply?.expand);
|
|
276
|
+
let read = pick(reply?.read);
|
|
277
|
+
// A leaf cannot be expanded: reading it is what was meant.
|
|
278
|
+
read = [
|
|
279
|
+
...read,
|
|
280
|
+
...expand.filter((id) => (index.get(id)?.node.children.length ?? 0) === 0),
|
|
281
|
+
];
|
|
282
|
+
expand = expand.filter((id) => (index.get(id)?.node.children.length ?? 0) > 0);
|
|
283
|
+
const limited = [...expand, ...read].slice(0, beamWidth);
|
|
284
|
+
expand = expand.filter((id) => limited.includes(id));
|
|
285
|
+
read = [...new Set(read.filter((id) => limited.includes(id)))];
|
|
286
|
+
steps.push({
|
|
287
|
+
step,
|
|
288
|
+
shown: shown.candidates.map((entry) => entry.id),
|
|
289
|
+
expanded: expand,
|
|
290
|
+
read,
|
|
291
|
+
...reasoningOf(reply),
|
|
292
|
+
});
|
|
293
|
+
chosen.push(...read);
|
|
294
|
+
pendingExpand = expand;
|
|
295
|
+
frontier = expand.flatMap((id) => index.get(id)?.node.children ?? []);
|
|
296
|
+
if (frontier.length === 0) {
|
|
297
|
+
pendingExpand = [];
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
// Anything still marked for expansion when the walk stopped is read whole.
|
|
301
|
+
if (stoppedBy !== undefined) {
|
|
302
|
+
chosen.push(...pendingExpand);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
// A section chosen together with one of its own subsections adds nothing but length: the
|
|
306
|
+
// more specific choice wins.
|
|
307
|
+
const unique = [...new Set(chosen)];
|
|
308
|
+
const specific = unique.filter((id) => !unique.some((other) => other !== id && index.get(other)?.path.some((node) => node.id === id)));
|
|
309
|
+
const nodes = specific.slice(0, maxNodes).flatMap((id) => {
|
|
310
|
+
const entry = index.get(id);
|
|
311
|
+
if (entry === undefined) {
|
|
312
|
+
return [];
|
|
313
|
+
}
|
|
314
|
+
const { node, path } = entry;
|
|
315
|
+
return [
|
|
316
|
+
{
|
|
317
|
+
nodeId: node.id,
|
|
318
|
+
title: node.title,
|
|
319
|
+
path: [...path, node].map((step) => ({ id: step.id, title: step.title })),
|
|
320
|
+
...(node.pageStart !== undefined ? { pageStart: node.pageStart } : {}),
|
|
321
|
+
...(node.pageEnd !== undefined ? { pageEnd: node.pageEnd } : {}),
|
|
322
|
+
unitStart: node.unitStart,
|
|
323
|
+
unitEnd: node.unitEnd,
|
|
324
|
+
},
|
|
325
|
+
];
|
|
326
|
+
});
|
|
327
|
+
return {
|
|
328
|
+
documentId: tree.documentId,
|
|
329
|
+
...(tree.title !== undefined ? { title: tree.title } : {}),
|
|
330
|
+
mode,
|
|
331
|
+
steps,
|
|
332
|
+
nodes,
|
|
333
|
+
llmCalls: budget.calls,
|
|
334
|
+
inputTokens: budget.inputTokens,
|
|
335
|
+
outputTokens: budget.outputTokens,
|
|
336
|
+
...(stoppedBy !== undefined ? { stoppedBy } : {}),
|
|
337
|
+
...(error !== undefined ? { error } : {}),
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
async passagesOf(tree, navigation) {
|
|
341
|
+
const maxPassageChars = this.options.maxPassageChars ?? 12_000;
|
|
342
|
+
const maxUnits = Math.max(1, this.options.maxUnitsPerNode ?? 25);
|
|
343
|
+
const reasoning = navigation.steps
|
|
344
|
+
.map((step) => step.reasoning)
|
|
345
|
+
.filter((text) => text !== undefined)
|
|
346
|
+
.join('\n');
|
|
347
|
+
const passages = [];
|
|
348
|
+
for (const [rank, node] of navigation.nodes.entries()) {
|
|
349
|
+
const units = await this.store.readUnits(tree.documentId, node.unitStart, Math.min(node.unitEnd, node.unitStart + maxUnits - 1));
|
|
350
|
+
let text = units.map((unit) => unit.text).join('\n\n');
|
|
351
|
+
if (text.length > maxPassageChars) {
|
|
352
|
+
text = `${text.slice(0, maxPassageChars - 1)}…`;
|
|
353
|
+
}
|
|
354
|
+
passages.push({
|
|
355
|
+
id: `${tree.documentId}#node:${node.nodeId}`,
|
|
356
|
+
text,
|
|
357
|
+
// Rank within the document's choice; not a similarity.
|
|
358
|
+
score: 1 / (rank + 1),
|
|
359
|
+
source: tree.source ?? tree.title ?? tree.documentId,
|
|
360
|
+
metadata: {
|
|
361
|
+
...tree.metadata,
|
|
362
|
+
documentId: tree.documentId,
|
|
363
|
+
nodeId: node.nodeId,
|
|
364
|
+
title: node.title,
|
|
365
|
+
...(node.pageStart !== undefined ? { pageStart: node.pageStart } : {}),
|
|
366
|
+
...(node.pageEnd !== undefined ? { pageEnd: node.pageEnd } : {}),
|
|
367
|
+
path: node.path,
|
|
368
|
+
retrieval: 'tree-navigation',
|
|
369
|
+
...(reasoning ? { reasoning: reasoning.slice(0, 2_000) } : {}),
|
|
370
|
+
},
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
return passages;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
/** Accept `0003`, `3`, `"[0003]"` for node `0003`. */
|
|
377
|
+
function resolveId(index, raw) {
|
|
378
|
+
const id = raw.trim().replace(/^\[|\]$/g, '');
|
|
379
|
+
if (index.has(id)) {
|
|
380
|
+
return id;
|
|
381
|
+
}
|
|
382
|
+
if (/^\d+$/.test(id)) {
|
|
383
|
+
const padded = id.padStart(4, '0');
|
|
384
|
+
if (index.has(padded)) {
|
|
385
|
+
return padded;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return undefined;
|
|
389
|
+
}
|
|
390
|
+
/** The reply's JSON object, or an error naming what came back (a truncated or chatty reply). */
|
|
391
|
+
function requireJson(reply) {
|
|
392
|
+
const json = parseJsonReply(reply);
|
|
393
|
+
if (json === undefined) {
|
|
394
|
+
throw new Error(`navigation reply was not JSON: ${JSON.stringify(reply.slice(0, 120))}`);
|
|
395
|
+
}
|
|
396
|
+
return json;
|
|
397
|
+
}
|
|
398
|
+
function reasoningOf(reply) {
|
|
399
|
+
const thinking = reply?.thinking ?? reply?.reasoning;
|
|
400
|
+
return typeof thinking === 'string' && thinking.trim()
|
|
401
|
+
? { reasoning: thinking.slice(0, 2_000) }
|
|
402
|
+
: {};
|
|
403
|
+
}
|
|
404
|
+
//# sourceMappingURL=navigate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigate.js","sourceRoot":"","sources":["../../../../src/rag/tree/navigate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { LucidRawRunner } from '../../stores/lucid.js';
|
|
2
|
+
import { type DocumentTreeHeader, type DocumentTreeStore } from './store.js';
|
|
3
|
+
import type { DocumentTree, TreeUnit } from './types.js';
|
|
4
|
+
export interface PgDocumentTreeStoreOptions {
|
|
5
|
+
/** Trees table. Default `agent_rag_trees`. Validated against the identifier regex. */
|
|
6
|
+
table?: string;
|
|
7
|
+
/** Units (page/section text) table. Default `${table}_units`, i.e. `agent_rag_trees_units`. */
|
|
8
|
+
unitsTable?: string;
|
|
9
|
+
/** Unit rows per multi-row `INSERT`. Default 200. */
|
|
10
|
+
insertBatchSize?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* A Postgres {@link DocumentTreeStore} over Lucid's raw runner (`db` or `db.connection(name)` — the
|
|
14
|
+
* same structural {@link LucidRawRunner} `PgVectorStore` takes, so `@adonisjs/lucid` stays an
|
|
15
|
+
* optional peer): one row per tree (header columns, `metadata` as `jsonb` for filtering, the nodes as
|
|
16
|
+
* `jsonb`) and one row per unit of text. Filters compile through the same builder as `PgVectorStore`'s
|
|
17
|
+
* — scalar `@>` containment, array match-any, empty array denies — so the filter you pass the vector
|
|
18
|
+
* store works here unchanged.
|
|
19
|
+
*
|
|
20
|
+
* Provision it with the published `create_agent_rag_trees` migration, or {@link ensureSchema} /
|
|
21
|
+
* {@link schemaStatements}. Needs no extension. Writes run in one transaction when the runner has one.
|
|
22
|
+
*/
|
|
23
|
+
export declare class PgDocumentTreeStore implements DocumentTreeStore {
|
|
24
|
+
protected readonly db: LucidRawRunner;
|
|
25
|
+
protected readonly table: string;
|
|
26
|
+
protected readonly unitsTable: string;
|
|
27
|
+
private readonly insertBatchSize;
|
|
28
|
+
constructor(db: LucidRawRunner, options?: PgDocumentTreeStoreOptions);
|
|
29
|
+
/** The idempotent DDL {@link ensureSchema} runs, in order. */
|
|
30
|
+
schemaStatements(): string[];
|
|
31
|
+
ensureSchema(): Promise<void>;
|
|
32
|
+
private write;
|
|
33
|
+
/** Replace the tree and its units (one transaction when the runner has one). */
|
|
34
|
+
put(tree: DocumentTree, units: TreeUnit[]): Promise<void>;
|
|
35
|
+
get(documentId: string, filter?: Record<string, unknown>): Promise<DocumentTree | undefined>;
|
|
36
|
+
getMany(documentIds: readonly string[], filter?: Record<string, unknown>): Promise<DocumentTree[]>;
|
|
37
|
+
list(options?: {
|
|
38
|
+
filter?: Record<string, unknown>;
|
|
39
|
+
documentIds?: readonly string[];
|
|
40
|
+
limit?: number;
|
|
41
|
+
}): Promise<DocumentTreeHeader[]>;
|
|
42
|
+
readUnits(documentId: string, start: number, end: number): Promise<TreeUnit[]>;
|
|
43
|
+
remove(documentId: string): Promise<void>;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=pg-tree-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pg-tree-store.d.ts","sourceRoot":"","sources":["../../../../src/rag/tree/pg-tree-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAY,MAAM,YAAY,CAAC;AACvF,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEzD,MAAM,WAAW,0BAA0B;IACzC,sFAAsF;IACtF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+FAA+F;IAC/F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAoCD;;;;;;;;;;GAUG;AACH,qBAAa,mBAAoB,YAAW,iBAAiB;IAMzD,SAAS,CAAC,QAAQ,CAAC,EAAE,EAAE,cAAc;IALvC,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACjC,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IACtC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IAEzC,YACqB,EAAE,EAAE,cAAc,EACrC,OAAO,GAAE,0BAA+B,EAKzC;IAED,8DAA8D;IAC9D,gBAAgB,IAAI,MAAM,EAAE,CAuB3B;IAEK,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAIlC;YAEa,KAAK;IAYnB,gFAAgF;IAC1E,GAAG,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA0C9D;IAEK,GAAG,CACP,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAEnC;IAEK,OAAO,CACX,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,YAAY,EAAE,CAAC,CAiBzB;IAEK,IAAI,CACR,OAAO,GAAE;QACP,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACjC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QAChC,KAAK,CAAC,EAAE,MAAM,CAAC;KACX,GACL,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAoD/B;IAEK,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAanF;IAEK,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK9C;CACF"}
|