@kognitivedev/cloud-knowledge-base 0.2.29
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/.turbo/turbo-build.log +2 -0
- package/.turbo/turbo-test.log +11 -0
- package/CHANGELOG.md +14 -0
- package/README.md +88 -0
- package/dist/context-adapter.d.ts +2 -0
- package/dist/context-adapter.js +35 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +16 -0
- package/dist/search.d.ts +2 -0
- package/dist/search.js +38 -0
- package/dist/shared.d.ts +23 -0
- package/dist/shared.js +167 -0
- package/dist/tool.d.ts +18 -0
- package/dist/tool.js +56 -0
- package/dist/types.d.ts +118 -0
- package/dist/types.js +2 -0
- package/dist/workflow.d.ts +4 -0
- package/dist/workflow.js +59 -0
- package/package.json +47 -0
- package/src/__tests__/cloud-knowledge-base.test.ts +493 -0
- package/src/context-adapter.ts +65 -0
- package/src/index.ts +29 -0
- package/src/search.ts +40 -0
- package/src/shared.ts +224 -0
- package/src/tool.ts +70 -0
- package/src/types.ts +131 -0
- package/src/workflow.ts +102 -0
- package/tsconfig.json +13 -0
- package/vitest.config.ts +8 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export { searchCloudKnowledgeBase } from "./search";
|
|
2
|
+
export { createCloudKnowledgeBaseSearchTool } from "./tool";
|
|
3
|
+
export { createCloudKnowledgeBaseContextAdapter } from "./context-adapter";
|
|
4
|
+
export {
|
|
5
|
+
createCloudKnowledgeBaseSearchStep,
|
|
6
|
+
createCloudKnowledgeBaseAnswerStep,
|
|
7
|
+
} from "./workflow";
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
createKnowledgeBaseSearchStep,
|
|
11
|
+
createKnowledgeBaseAnswerStep,
|
|
12
|
+
DEFAULT_KNOWLEDGE_BASE_ANSWER_SCHEMA,
|
|
13
|
+
} from "@kognitivedev/workflows";
|
|
14
|
+
|
|
15
|
+
export type {
|
|
16
|
+
CloudKnowledgeBaseCitation,
|
|
17
|
+
CloudKnowledgeBaseHit,
|
|
18
|
+
CloudKnowledgeBaseSearchResponse,
|
|
19
|
+
CloudKnowledgeBaseAnswer,
|
|
20
|
+
CloudKnowledgeBaseResolverInput,
|
|
21
|
+
CloudKnowledgeBaseClientOptions,
|
|
22
|
+
CloudKnowledgeBasePipelineOptions,
|
|
23
|
+
CloudKnowledgeBaseSearchOptions,
|
|
24
|
+
CloudKnowledgeBaseSearchToolOptions,
|
|
25
|
+
CloudKnowledgeBaseContextAdapterOptions,
|
|
26
|
+
CloudKnowledgeBaseContextAdapter,
|
|
27
|
+
CloudKnowledgeBaseSearchStepOptions,
|
|
28
|
+
CloudKnowledgeBaseAnswerStepOptions,
|
|
29
|
+
} from "./types";
|
package/src/search.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { CloudKnowledgeBaseSearchOptions, CloudKnowledgeBaseSearchResponse } from "./types";
|
|
2
|
+
import { normalizeSearchResult, resolveSearchConfig } from "./shared";
|
|
3
|
+
|
|
4
|
+
export async function searchCloudKnowledgeBase(
|
|
5
|
+
options: CloudKnowledgeBaseSearchOptions,
|
|
6
|
+
): Promise<CloudKnowledgeBaseSearchResponse> {
|
|
7
|
+
const query = options.query.trim();
|
|
8
|
+
if (!query) {
|
|
9
|
+
throw new Error("Cloud knowledge base search requires a non-empty query.");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { client, pipelineId } = await resolveSearchConfig(options, {
|
|
13
|
+
resourceId: options.resourceId,
|
|
14
|
+
messages: options.messages,
|
|
15
|
+
metadata: options.metadata,
|
|
16
|
+
abortSignal: options.abortSignal,
|
|
17
|
+
apiKey: options.apiKey,
|
|
18
|
+
baseUrl: options.baseUrl,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
const results = await client.pipelines.search(pipelineId, {
|
|
23
|
+
query,
|
|
24
|
+
topK: options.topK,
|
|
25
|
+
retrievalMode: options.retrievalMode,
|
|
26
|
+
});
|
|
27
|
+
const hits = results.map((result) => normalizeSearchResult(result, options.snippetMaxLength));
|
|
28
|
+
return {
|
|
29
|
+
pipelineId,
|
|
30
|
+
query,
|
|
31
|
+
hits,
|
|
32
|
+
citations: hits.map((hit) => hit.citation),
|
|
33
|
+
};
|
|
34
|
+
} catch (error) {
|
|
35
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
36
|
+
const wrapped = new Error(`Cloud knowledge base search failed for pipeline "${pipelineId}": ${reason}`);
|
|
37
|
+
(wrapped as Error & { cause?: unknown }).cause = error;
|
|
38
|
+
throw wrapped;
|
|
39
|
+
}
|
|
40
|
+
}
|
package/src/shared.ts
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { KognitiveDocumentsClient, type PipelineSearchResult } from "@kognitivedev/documents";
|
|
2
|
+
import type {
|
|
3
|
+
CloudKnowledgeBaseCitation,
|
|
4
|
+
CloudKnowledgeBaseClientOptions,
|
|
5
|
+
CloudKnowledgeBasePipelineOptions,
|
|
6
|
+
CloudKnowledgeBaseResolverInput,
|
|
7
|
+
CloudKnowledgeBaseSearchResponse,
|
|
8
|
+
ResolvedCloudKnowledgeBaseSearchConfig,
|
|
9
|
+
} from "./types";
|
|
10
|
+
|
|
11
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
12
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function normalizeText(value: unknown): string | undefined {
|
|
16
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function normalizeNumber(value: unknown): number | undefined {
|
|
20
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
21
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
22
|
+
const parsed = Number(value);
|
|
23
|
+
if (Number.isFinite(parsed)) return parsed;
|
|
24
|
+
}
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function createSnippet(content: string, maxLength = 240): string {
|
|
29
|
+
const normalized = content.replace(/\s+/g, " ").trim();
|
|
30
|
+
if (normalized.length <= maxLength) {
|
|
31
|
+
return normalized;
|
|
32
|
+
}
|
|
33
|
+
return `${normalized.slice(0, Math.max(0, maxLength - 1)).trimEnd()}…`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function createModelSummary(
|
|
37
|
+
response: CloudKnowledgeBaseSearchResponse,
|
|
38
|
+
options: { maxHits?: number; maxCharacters?: number } = {},
|
|
39
|
+
): string {
|
|
40
|
+
const maxHits = options.maxHits ?? 4;
|
|
41
|
+
const maxCharacters = options.maxCharacters ?? 320;
|
|
42
|
+
const lines = [
|
|
43
|
+
`Knowledge base search results for "${response.query}" in pipeline ${response.pipelineId}:`,
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
for (const [index, hit] of response.hits.slice(0, maxHits).entries()) {
|
|
47
|
+
const citation = hit.citation;
|
|
48
|
+
const source = [
|
|
49
|
+
citation.filename ?? hit.sourceId,
|
|
50
|
+
typeof citation.pageNumber === "number" ? `page ${citation.pageNumber}` : null,
|
|
51
|
+
citation.sectionTitle ? `section ${citation.sectionTitle}` : null,
|
|
52
|
+
citation.sheetName ? `sheet ${citation.sheetName}` : null,
|
|
53
|
+
typeof citation.rowNumber === "number" ? `row ${citation.rowNumber}` : null,
|
|
54
|
+
citation.cellRange ? `range ${citation.cellRange}` : null,
|
|
55
|
+
citation.artifactType ?? null,
|
|
56
|
+
].filter(Boolean).join(" | ");
|
|
57
|
+
lines.push(
|
|
58
|
+
`[${index + 1}] score=${hit.score.toFixed(3)} source=${source}`,
|
|
59
|
+
createSnippet(hit.content || citation.snippet, maxCharacters),
|
|
60
|
+
`citation=${JSON.stringify(citation)}`,
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (response.hits.length > maxHits) {
|
|
65
|
+
lines.push(`Additional hits omitted: ${response.hits.length - maxHits}`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return lines.join("\n");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function buildSystemBlock(
|
|
72
|
+
response: CloudKnowledgeBaseSearchResponse,
|
|
73
|
+
options: { maxHits?: number; maxCharacters?: number; emptyStateMessage?: string } = {},
|
|
74
|
+
): string {
|
|
75
|
+
if (response.hits.length === 0) {
|
|
76
|
+
return [
|
|
77
|
+
"<CloudKnowledgeBaseContext>",
|
|
78
|
+
options.emptyStateMessage ?? `No relevant cloud knowledge base hits were found for query "${response.query}".`,
|
|
79
|
+
"</CloudKnowledgeBaseContext>",
|
|
80
|
+
].join("\n");
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return [
|
|
84
|
+
"<CloudKnowledgeBaseContext>",
|
|
85
|
+
`Pipeline: ${response.pipelineId}`,
|
|
86
|
+
`Query: ${response.query}`,
|
|
87
|
+
createModelSummary(response, {
|
|
88
|
+
maxHits: options.maxHits,
|
|
89
|
+
maxCharacters: options.maxCharacters,
|
|
90
|
+
}),
|
|
91
|
+
"Use these results as authoritative managed knowledge base context and cite matching sources when answering.",
|
|
92
|
+
"</CloudKnowledgeBaseContext>",
|
|
93
|
+
].join("\n");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function createDocumentsClient(options: CloudKnowledgeBaseClientOptions) {
|
|
97
|
+
if (options.client) {
|
|
98
|
+
return options.client;
|
|
99
|
+
}
|
|
100
|
+
if (!options.baseUrl) {
|
|
101
|
+
throw new Error(
|
|
102
|
+
"Cloud knowledge base backend configuration is missing. Provide a documents client or a baseUrl.",
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
return new KognitiveDocumentsClient({
|
|
106
|
+
baseUrl: options.baseUrl,
|
|
107
|
+
apiKey: options.apiKey,
|
|
108
|
+
fetch: options.fetch,
|
|
109
|
+
timeout: options.timeout,
|
|
110
|
+
logLevel: options.logLevel,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function resolveClientOptions(
|
|
115
|
+
options: CloudKnowledgeBaseClientOptions,
|
|
116
|
+
inherited?: Pick<CloudKnowledgeBaseResolverInput, "apiKey" | "baseUrl">,
|
|
117
|
+
): CloudKnowledgeBaseClientOptions {
|
|
118
|
+
if (options.client) {
|
|
119
|
+
return options;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const baseUrl = options.baseUrl ?? inherited?.baseUrl;
|
|
123
|
+
if (!baseUrl) {
|
|
124
|
+
throw new Error(
|
|
125
|
+
"Cloud knowledge base backend configuration is missing. Provide a documents client or a baseUrl, or inherit them from the host agent/workflow.",
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
...options,
|
|
131
|
+
baseUrl,
|
|
132
|
+
apiKey: options.apiKey ?? inherited?.apiKey,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export async function resolveSearchConfig(
|
|
137
|
+
options: CloudKnowledgeBaseClientOptions & CloudKnowledgeBasePipelineOptions,
|
|
138
|
+
input: CloudKnowledgeBaseResolverInput,
|
|
139
|
+
): Promise<ResolvedCloudKnowledgeBaseSearchConfig> {
|
|
140
|
+
const hasPipelineId = typeof options.pipelineId === "string" && options.pipelineId.trim().length > 0;
|
|
141
|
+
const hasResolver = typeof options.resolvePipelineId === "function";
|
|
142
|
+
|
|
143
|
+
if (hasPipelineId === hasResolver) {
|
|
144
|
+
throw new Error("Configure exactly one of pipelineId or resolvePipelineId for the cloud knowledge base.");
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const pipelineId = hasPipelineId
|
|
148
|
+
? options.pipelineId!.trim()
|
|
149
|
+
: await options.resolvePipelineId!({
|
|
150
|
+
resourceId: input.resourceId,
|
|
151
|
+
messages: input.messages,
|
|
152
|
+
metadata: input.metadata,
|
|
153
|
+
abortSignal: input.abortSignal,
|
|
154
|
+
apiKey: input.apiKey,
|
|
155
|
+
baseUrl: input.baseUrl,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
if (typeof pipelineId !== "string" || pipelineId.trim().length === 0) {
|
|
159
|
+
throw new Error("Cloud knowledge base pipeline resolution returned an empty pipeline id.");
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return {
|
|
163
|
+
client: createDocumentsClient(resolveClientOptions(options, input)),
|
|
164
|
+
pipelineId: pipelineId.trim(),
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export function normalizeSearchResult(result: PipelineSearchResult, snippetMaxLength = 240) {
|
|
169
|
+
const metadata = isRecord(result.metadata) ? result.metadata : undefined;
|
|
170
|
+
const content = normalizeText(result.content) ?? "";
|
|
171
|
+
const citation: CloudKnowledgeBaseCitation = {
|
|
172
|
+
sourceId: result.id,
|
|
173
|
+
snippet: normalizeText(metadata?.snippet) ?? createSnippet(content, snippetMaxLength),
|
|
174
|
+
...(normalizeText(metadata?.filename) ? { filename: normalizeText(metadata?.filename) } : {}),
|
|
175
|
+
...(normalizeText(metadata?.mimeType) ? { mimeType: normalizeText(metadata?.mimeType) } : {}),
|
|
176
|
+
...(normalizeNumber(metadata?.pageNumber) !== undefined ? { pageNumber: normalizeNumber(metadata?.pageNumber) } : {}),
|
|
177
|
+
...(normalizeText(metadata?.artifactType) || normalizeText(metadata?.blockType) || normalizeText(metadata?.kind)
|
|
178
|
+
? { artifactType: normalizeText(metadata?.artifactType) ?? normalizeText(metadata?.blockType) ?? normalizeText(metadata?.kind) }
|
|
179
|
+
: {}),
|
|
180
|
+
...(normalizeText(metadata?.parseDocumentId) ? { parseDocumentId: normalizeText(metadata?.parseDocumentId) } : {}),
|
|
181
|
+
...(normalizeText(metadata?.sectionTitle) ? { sectionTitle: normalizeText(metadata?.sectionTitle) } : {}),
|
|
182
|
+
...(normalizeText(metadata?.sheetName) ? { sheetName: normalizeText(metadata?.sheetName) } : {}),
|
|
183
|
+
...(normalizeNumber(metadata?.rowNumber) !== undefined ? { rowNumber: normalizeNumber(metadata?.rowNumber) } : {}),
|
|
184
|
+
...(normalizeText(metadata?.cellRange) ? { cellRange: normalizeText(metadata?.cellRange) } : {}),
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
return {
|
|
188
|
+
sourceId: result.id,
|
|
189
|
+
content,
|
|
190
|
+
score: typeof result.score === "number" ? result.score : 0,
|
|
191
|
+
citation,
|
|
192
|
+
...(metadata ? { metadata } : {}),
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export function extractLastUserText(messages: unknown[] | undefined): string {
|
|
197
|
+
if (!Array.isArray(messages)) return "";
|
|
198
|
+
|
|
199
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
200
|
+
const message = messages[index];
|
|
201
|
+
if (!isRecord(message) || message.role !== "user") continue;
|
|
202
|
+
|
|
203
|
+
const parts = Array.isArray(message.parts)
|
|
204
|
+
? message.parts
|
|
205
|
+
: Array.isArray(message.content)
|
|
206
|
+
? message.content
|
|
207
|
+
: [message.content];
|
|
208
|
+
|
|
209
|
+
const text = parts
|
|
210
|
+
.map((part) => {
|
|
211
|
+
if (typeof part === "string") return part;
|
|
212
|
+
if (isRecord(part) && typeof part.text === "string") return part.text;
|
|
213
|
+
return "";
|
|
214
|
+
})
|
|
215
|
+
.join("\n")
|
|
216
|
+
.trim();
|
|
217
|
+
|
|
218
|
+
if (text) {
|
|
219
|
+
return text;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return "";
|
|
224
|
+
}
|
package/src/tool.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { createTool } from "@kognitivedev/tools";
|
|
3
|
+
import type { Tool } from "@kognitivedev/tools";
|
|
4
|
+
import { searchCloudKnowledgeBase } from "./search";
|
|
5
|
+
import { createModelSummary } from "./shared";
|
|
6
|
+
import type { CloudKnowledgeBaseSearchResponse, CloudKnowledgeBaseSearchToolOptions } from "./types";
|
|
7
|
+
|
|
8
|
+
const SearchInputSchema = z.object({
|
|
9
|
+
query: z.string().min(1).describe("Natural-language query to run against the managed cloud knowledge base."),
|
|
10
|
+
topK: z.number().int().min(1).max(50).optional().describe("Maximum number of results to return."),
|
|
11
|
+
retrievalMode: z.enum(["chunks", "files_via_metadata", "files_via_content", "auto_routed"]).optional()
|
|
12
|
+
.describe("Pipeline retrieval mode override."),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const CitationSchema = z.object({
|
|
16
|
+
sourceId: z.string(),
|
|
17
|
+
snippet: z.string(),
|
|
18
|
+
filename: z.string().optional(),
|
|
19
|
+
mimeType: z.string().optional(),
|
|
20
|
+
pageNumber: z.number().optional(),
|
|
21
|
+
artifactType: z.string().optional(),
|
|
22
|
+
parseDocumentId: z.string().optional(),
|
|
23
|
+
sectionTitle: z.string().optional(),
|
|
24
|
+
sheetName: z.string().optional(),
|
|
25
|
+
rowNumber: z.number().optional(),
|
|
26
|
+
cellRange: z.string().optional(),
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const HitSchema = z.object({
|
|
30
|
+
sourceId: z.string(),
|
|
31
|
+
content: z.string(),
|
|
32
|
+
score: z.number(),
|
|
33
|
+
citation: CitationSchema,
|
|
34
|
+
metadata: z.record(z.string(), z.unknown()).optional(),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const SearchOutputSchema = z.object({
|
|
38
|
+
pipelineId: z.string(),
|
|
39
|
+
query: z.string(),
|
|
40
|
+
hits: z.array(HitSchema),
|
|
41
|
+
citations: z.array(CitationSchema),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
export function createCloudKnowledgeBaseSearchTool(
|
|
45
|
+
options: CloudKnowledgeBaseSearchToolOptions,
|
|
46
|
+
): Tool<
|
|
47
|
+
z.infer<typeof SearchInputSchema>,
|
|
48
|
+
CloudKnowledgeBaseSearchResponse
|
|
49
|
+
> {
|
|
50
|
+
return createTool<z.infer<typeof SearchInputSchema>, CloudKnowledgeBaseSearchResponse>({
|
|
51
|
+
id: options.id ?? "search-cloud-knowledge-base",
|
|
52
|
+
description: options.description
|
|
53
|
+
?? "Search a managed cloud knowledge base pipeline and return normalized hits with enterprise-grade citations.",
|
|
54
|
+
inputSchema: SearchInputSchema,
|
|
55
|
+
outputSchema: SearchOutputSchema as z.ZodType<CloudKnowledgeBaseSearchResponse>,
|
|
56
|
+
execute: async (input, context) => searchCloudKnowledgeBase({
|
|
57
|
+
...options,
|
|
58
|
+
query: input.query,
|
|
59
|
+
topK: input.topK ?? options.topK,
|
|
60
|
+
retrievalMode: input.retrievalMode ?? options.retrievalMode,
|
|
61
|
+
resourceId: context.resourceId,
|
|
62
|
+
metadata: context.metadata,
|
|
63
|
+
abortSignal: context.abortSignal,
|
|
64
|
+
}),
|
|
65
|
+
toModelOutput: (output) => createModelSummary(output, {
|
|
66
|
+
maxHits: options.modelSummaryMaxHits,
|
|
67
|
+
maxCharacters: options.modelSummaryMaxCharacters,
|
|
68
|
+
}),
|
|
69
|
+
});
|
|
70
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import type { AgentContextAdapter } from "@kognitivedev/agents";
|
|
2
|
+
import type {
|
|
3
|
+
DocumentsClientConfig,
|
|
4
|
+
KognitiveDocumentsClient,
|
|
5
|
+
LogLevel,
|
|
6
|
+
PipelineRetrievalMode,
|
|
7
|
+
} from "@kognitivedev/documents";
|
|
8
|
+
import type { KognitiveMessage, Metadata, ResourceId } from "@kognitivedev/shared";
|
|
9
|
+
import type {
|
|
10
|
+
KnowledgeBaseAnswer,
|
|
11
|
+
KnowledgeBaseCitation,
|
|
12
|
+
KnowledgeBaseHit,
|
|
13
|
+
KnowledgeBaseSearchResponse,
|
|
14
|
+
} from "@kognitivedev/workflows";
|
|
15
|
+
|
|
16
|
+
export type CloudKnowledgeBaseCitation = KnowledgeBaseCitation;
|
|
17
|
+
export type CloudKnowledgeBaseHit = KnowledgeBaseHit;
|
|
18
|
+
export type CloudKnowledgeBaseSearchResponse = KnowledgeBaseSearchResponse;
|
|
19
|
+
export type CloudKnowledgeBaseAnswer = KnowledgeBaseAnswer;
|
|
20
|
+
|
|
21
|
+
export interface CloudKnowledgeBaseResolverInput {
|
|
22
|
+
resourceId: ResourceId;
|
|
23
|
+
messages?: KognitiveMessage[];
|
|
24
|
+
metadata?: Metadata;
|
|
25
|
+
abortSignal?: AbortSignal;
|
|
26
|
+
apiKey?: string;
|
|
27
|
+
baseUrl?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface CloudKnowledgeBaseClientOptions {
|
|
31
|
+
client?: KognitiveDocumentsClient;
|
|
32
|
+
baseUrl?: string;
|
|
33
|
+
apiKey?: string;
|
|
34
|
+
fetch?: DocumentsClientConfig["fetch"];
|
|
35
|
+
timeout?: number;
|
|
36
|
+
logLevel?: LogLevel;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface CloudKnowledgeBasePipelineOptions {
|
|
40
|
+
pipelineId?: string;
|
|
41
|
+
resolvePipelineId?: (input: CloudKnowledgeBaseResolverInput) => Promise<string> | string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface CloudKnowledgeBaseSearchOptions
|
|
45
|
+
extends CloudKnowledgeBaseClientOptions, CloudKnowledgeBasePipelineOptions {
|
|
46
|
+
query: string;
|
|
47
|
+
topK?: number;
|
|
48
|
+
retrievalMode?: PipelineRetrievalMode;
|
|
49
|
+
resourceId: ResourceId;
|
|
50
|
+
messages?: KognitiveMessage[];
|
|
51
|
+
metadata?: Metadata;
|
|
52
|
+
abortSignal?: AbortSignal;
|
|
53
|
+
snippetMaxLength?: number;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface CloudKnowledgeBaseSearchToolOptions
|
|
57
|
+
extends CloudKnowledgeBaseClientOptions, CloudKnowledgeBasePipelineOptions {
|
|
58
|
+
id?: string;
|
|
59
|
+
description?: string;
|
|
60
|
+
topK?: number;
|
|
61
|
+
retrievalMode?: PipelineRetrievalMode;
|
|
62
|
+
snippetMaxLength?: number;
|
|
63
|
+
modelSummaryMaxHits?: number;
|
|
64
|
+
modelSummaryMaxCharacters?: number;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface CloudKnowledgeBaseContextAdapterOptions
|
|
68
|
+
extends CloudKnowledgeBaseClientOptions, CloudKnowledgeBasePipelineOptions {
|
|
69
|
+
topK?: number;
|
|
70
|
+
retrievalMode?: PipelineRetrievalMode;
|
|
71
|
+
snippetMaxLength?: number;
|
|
72
|
+
maxContextHits?: number;
|
|
73
|
+
maxContextCharacters?: number;
|
|
74
|
+
autoRegisterSearchTool?: boolean;
|
|
75
|
+
searchTool?: CloudKnowledgeBaseSearchToolOptions;
|
|
76
|
+
buildQuery?: (input: CloudKnowledgeBaseResolverInput) => Promise<string> | string;
|
|
77
|
+
emptyStateMessage?: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface CloudKnowledgeBaseSearchStepOptions<TInput, TOutput = CloudKnowledgeBaseSearchResponse>
|
|
81
|
+
extends CloudKnowledgeBaseClientOptions, CloudKnowledgeBasePipelineOptions {
|
|
82
|
+
id: string;
|
|
83
|
+
description?: string;
|
|
84
|
+
getQuery: (input: TInput, context: { resourceId: ResourceId; abortSignal: AbortSignal }) => Promise<string> | string;
|
|
85
|
+
topK?: number | ((input: TInput, context: { resourceId: ResourceId; abortSignal: AbortSignal }) => Promise<number | undefined> | number | undefined);
|
|
86
|
+
retrievalMode?: PipelineRetrievalMode | ((
|
|
87
|
+
input: TInput,
|
|
88
|
+
context: { resourceId: ResourceId; abortSignal: AbortSignal },
|
|
89
|
+
) => Promise<PipelineRetrievalMode | undefined> | PipelineRetrievalMode | undefined);
|
|
90
|
+
snippetMaxLength?: number;
|
|
91
|
+
extractOutput?: (result: CloudKnowledgeBaseSearchResponse) => TOutput;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface CloudKnowledgeBaseAnswerStepOptions<TInput, TOutput = CloudKnowledgeBaseAnswer>
|
|
95
|
+
extends CloudKnowledgeBaseClientOptions, CloudKnowledgeBasePipelineOptions {
|
|
96
|
+
id: string;
|
|
97
|
+
description?: string;
|
|
98
|
+
agent: {
|
|
99
|
+
generateObject(options: {
|
|
100
|
+
messages: any[];
|
|
101
|
+
resourceId: ResourceId;
|
|
102
|
+
abortSignal?: AbortSignal;
|
|
103
|
+
structuredOutput: any;
|
|
104
|
+
temperature?: number;
|
|
105
|
+
maxOutputTokens?: number;
|
|
106
|
+
}): Promise<any>;
|
|
107
|
+
};
|
|
108
|
+
getQuery: (input: TInput, context: { resourceId: ResourceId; abortSignal: AbortSignal }) => Promise<string> | string;
|
|
109
|
+
topK?: number | ((input: TInput, context: { resourceId: ResourceId; abortSignal: AbortSignal }) => Promise<number | undefined> | number | undefined);
|
|
110
|
+
retrievalMode?: PipelineRetrievalMode | ((
|
|
111
|
+
input: TInput,
|
|
112
|
+
context: { resourceId: ResourceId; abortSignal: AbortSignal },
|
|
113
|
+
) => Promise<PipelineRetrievalMode | undefined> | PipelineRetrievalMode | undefined);
|
|
114
|
+
snippetMaxLength?: number;
|
|
115
|
+
buildMessages?: (input: TInput, search: CloudKnowledgeBaseSearchResponse) => any[];
|
|
116
|
+
temperature?: number;
|
|
117
|
+
maxOutputTokens?: number;
|
|
118
|
+
emptyResultAnswer?: string;
|
|
119
|
+
extractOutput?: (result: {
|
|
120
|
+
answer: CloudKnowledgeBaseAnswer;
|
|
121
|
+
search: CloudKnowledgeBaseSearchResponse;
|
|
122
|
+
agentResult?: any;
|
|
123
|
+
}) => TOutput;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export interface ResolvedCloudKnowledgeBaseSearchConfig {
|
|
127
|
+
client: KognitiveDocumentsClient;
|
|
128
|
+
pipelineId: string;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export interface CloudKnowledgeBaseContextAdapter extends AgentContextAdapter {}
|
package/src/workflow.ts
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { PipelineRetrievalMode } from "@kognitivedev/documents";
|
|
2
|
+
import {
|
|
3
|
+
createKnowledgeBaseAnswerStep,
|
|
4
|
+
createKnowledgeBaseSearchStep,
|
|
5
|
+
type StepContext,
|
|
6
|
+
type StepDefinition,
|
|
7
|
+
} from "@kognitivedev/workflows";
|
|
8
|
+
import { searchCloudKnowledgeBase } from "./search";
|
|
9
|
+
import type {
|
|
10
|
+
CloudKnowledgeBaseAnswer,
|
|
11
|
+
CloudKnowledgeBaseAnswerStepOptions,
|
|
12
|
+
CloudKnowledgeBaseSearchResponse,
|
|
13
|
+
CloudKnowledgeBaseSearchStepOptions,
|
|
14
|
+
} from "./types";
|
|
15
|
+
|
|
16
|
+
async function resolveStepValue<TInput, TValue>(
|
|
17
|
+
value: TValue | ((input: TInput, context: { resourceId: StepContext["resourceId"]; abortSignal: AbortSignal }) => Promise<TValue> | TValue),
|
|
18
|
+
input: TInput,
|
|
19
|
+
context: StepContext,
|
|
20
|
+
): Promise<TValue> {
|
|
21
|
+
if (typeof value === "function") {
|
|
22
|
+
return (value as (input: TInput, context: { resourceId: StepContext["resourceId"]; abortSignal: AbortSignal }) => Promise<TValue> | TValue)(
|
|
23
|
+
input,
|
|
24
|
+
{ resourceId: context.resourceId, abortSignal: context.abortSignal },
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function searchForWorkflow<TInput>(
|
|
31
|
+
options: {
|
|
32
|
+
getQuery: (input: TInput, context: { resourceId: StepContext["resourceId"]; abortSignal: AbortSignal }) => Promise<string> | string;
|
|
33
|
+
topK?: number | ((input: TInput, context: { resourceId: StepContext["resourceId"]; abortSignal: AbortSignal }) => Promise<number | undefined> | number | undefined);
|
|
34
|
+
retrievalMode?: PipelineRetrievalMode | ((
|
|
35
|
+
input: TInput,
|
|
36
|
+
context: { resourceId: StepContext["resourceId"]; abortSignal: AbortSignal },
|
|
37
|
+
) => Promise<PipelineRetrievalMode | undefined> | PipelineRetrievalMode | undefined);
|
|
38
|
+
snippetMaxLength?: number;
|
|
39
|
+
client?: CloudKnowledgeBaseSearchStepOptions<TInput>["client"];
|
|
40
|
+
baseUrl?: CloudKnowledgeBaseSearchStepOptions<TInput>["baseUrl"];
|
|
41
|
+
apiKey?: CloudKnowledgeBaseSearchStepOptions<TInput>["apiKey"];
|
|
42
|
+
fetch?: CloudKnowledgeBaseSearchStepOptions<TInput>["fetch"];
|
|
43
|
+
timeout?: CloudKnowledgeBaseSearchStepOptions<TInput>["timeout"];
|
|
44
|
+
logLevel?: CloudKnowledgeBaseSearchStepOptions<TInput>["logLevel"];
|
|
45
|
+
pipelineId?: CloudKnowledgeBaseSearchStepOptions<TInput>["pipelineId"];
|
|
46
|
+
resolvePipelineId?: CloudKnowledgeBaseSearchStepOptions<TInput>["resolvePipelineId"];
|
|
47
|
+
},
|
|
48
|
+
input: TInput,
|
|
49
|
+
context: StepContext,
|
|
50
|
+
): Promise<CloudKnowledgeBaseSearchResponse> {
|
|
51
|
+
const inheritedContext = context as StepContext & { apiKey?: string; baseUrl?: string };
|
|
52
|
+
const query = await options.getQuery(input, {
|
|
53
|
+
resourceId: inheritedContext.resourceId,
|
|
54
|
+
abortSignal: inheritedContext.abortSignal,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return searchCloudKnowledgeBase({
|
|
58
|
+
client: options.client,
|
|
59
|
+
baseUrl: options.baseUrl ?? inheritedContext.baseUrl,
|
|
60
|
+
apiKey: options.apiKey ?? inheritedContext.apiKey,
|
|
61
|
+
fetch: options.fetch,
|
|
62
|
+
timeout: options.timeout,
|
|
63
|
+
logLevel: options.logLevel,
|
|
64
|
+
pipelineId: options.pipelineId,
|
|
65
|
+
resolvePipelineId: options.resolvePipelineId,
|
|
66
|
+
query,
|
|
67
|
+
topK: options.topK === undefined ? undefined : await resolveStepValue(options.topK, input, context),
|
|
68
|
+
retrievalMode: options.retrievalMode === undefined
|
|
69
|
+
? undefined
|
|
70
|
+
: await resolveStepValue(options.retrievalMode, input, context),
|
|
71
|
+
snippetMaxLength: options.snippetMaxLength,
|
|
72
|
+
resourceId: inheritedContext.resourceId,
|
|
73
|
+
abortSignal: inheritedContext.abortSignal,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function createCloudKnowledgeBaseSearchStep<TInput, TOutput = CloudKnowledgeBaseSearchResponse>(
|
|
78
|
+
options: CloudKnowledgeBaseSearchStepOptions<TInput, TOutput>,
|
|
79
|
+
): StepDefinition<TInput, TOutput> {
|
|
80
|
+
return createKnowledgeBaseSearchStep<TInput, CloudKnowledgeBaseSearchResponse, TOutput>({
|
|
81
|
+
id: options.id,
|
|
82
|
+
description: options.description,
|
|
83
|
+
search: async (input, context) => searchForWorkflow(options, input, context),
|
|
84
|
+
extractOutput: options.extractOutput,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function createCloudKnowledgeBaseAnswerStep<TInput, TOutput = CloudKnowledgeBaseAnswer>(
|
|
89
|
+
options: CloudKnowledgeBaseAnswerStepOptions<TInput, TOutput>,
|
|
90
|
+
): StepDefinition<TInput, TOutput> {
|
|
91
|
+
return createKnowledgeBaseAnswerStep<TInput, CloudKnowledgeBaseSearchResponse, TOutput>({
|
|
92
|
+
id: options.id,
|
|
93
|
+
description: options.description,
|
|
94
|
+
agent: options.agent,
|
|
95
|
+
search: async (input, context) => searchForWorkflow(options, input, context),
|
|
96
|
+
buildMessages: options.buildMessages,
|
|
97
|
+
temperature: options.temperature,
|
|
98
|
+
maxOutputTokens: options.maxOutputTokens,
|
|
99
|
+
emptyResultAnswer: options.emptyResultAnswer,
|
|
100
|
+
extractOutput: options.extractOutput,
|
|
101
|
+
});
|
|
102
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"rootDir": "src",
|
|
6
|
+
"outDir": "dist",
|
|
7
|
+
"declaration": true,
|
|
8
|
+
"noEmit": false,
|
|
9
|
+
"incremental": false
|
|
10
|
+
},
|
|
11
|
+
"include": ["src"],
|
|
12
|
+
"exclude": ["src/__tests__"]
|
|
13
|
+
}
|