@retrivora-ai/rag-engine 1.2.0 → 1.2.2
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/dist/DocumentChunker-BXOUMKoP.d.ts +93 -0
- package/dist/DocumentChunker-D1dg5iCi.d.mts +93 -0
- package/dist/{chunk-OCDCJUNE.mjs → chunk-GCPPRD2G.mjs} +70 -1
- package/dist/handlers/index.d.mts +2 -2
- package/dist/handlers/index.d.ts +2 -2
- package/dist/handlers/index.js +70 -0
- package/dist/handlers/index.mjs +3 -1
- package/dist/{index-CYgr00ot.d.ts → index-B67KQ9NN.d.ts} +14 -2
- package/dist/{RagConfig-FyMB_UG6.d.mts → index-Cti1u0y1.d.mts} +87 -86
- package/dist/{RagConfig-FyMB_UG6.d.ts → index-Cti1u0y1.d.ts} +87 -86
- package/dist/{index-D-lfcqlL.d.mts → index-kUXnRvuI.d.mts} +14 -2
- package/dist/index.d.mts +53 -89
- package/dist/index.d.ts +53 -89
- package/dist/index.js +139 -27
- package/dist/index.mjs +143 -27
- package/dist/server.d.mts +9 -4
- package/dist/server.d.ts +9 -4
- package/dist/server.js +51 -0
- package/dist/server.mjs +1 -1
- package/package.json +1 -1
- package/src/app/api/suggestions/route.ts +4 -0
- package/src/components/ChatWidget.tsx +1 -7
- package/src/components/ChatWindow.tsx +180 -25
- package/src/components/ConfigProvider.tsx +7 -33
- package/src/components/DocumentUpload.tsx +1 -8
- package/src/components/MessageBubble.tsx +1 -12
- package/src/components/ProductCard.tsx +1 -15
- package/src/components/ProductCarousel.tsx +2 -7
- package/src/components/SourceCard.tsx +1 -6
- package/src/config/RagConfig.ts +2 -0
- package/src/config/uiConstants.ts +23 -0
- package/src/core/Pipeline.ts +57 -1
- package/src/core/VectorPlugin.ts +8 -1
- package/src/handlers/index.ts +31 -1
- package/src/hooks/useRagChat.ts +1 -45
- package/src/hooks/useStoredMessages.ts +1 -1
- package/src/index.ts +20 -5
- package/src/llm/ILLMProvider.ts +1 -13
- package/src/llm/providers/AnthropicProvider.ts +2 -1
- package/src/llm/providers/GeminiProvider.ts +2 -1
- package/src/llm/providers/OllamaProvider.ts +2 -1
- package/src/llm/providers/OpenAIProvider.ts +2 -1
- package/src/llm/providers/UniversalLLMAdapter.ts +2 -1
- package/src/server.ts +2 -2
- package/src/types/chat.ts +53 -0
- package/src/types/index.ts +17 -0
- package/src/types/props.ts +79 -0
- package/dist/DocumentChunker-Dh9TvmGG.d.mts +0 -45
- package/dist/DocumentChunker-Dh9TvmGG.d.ts +0 -45
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { C as ChatMessage, c as ChatOptions } from './index-Cti1u0y1.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Generic LLM Provider interface.
|
|
5
|
+
* Covers both chat completion and embedding generation so a single
|
|
6
|
+
* provider can handle both responsibilities when appropriate.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
interface EmbedOptions {
|
|
10
|
+
/** Override model for this specific embed call */
|
|
11
|
+
model?: string;
|
|
12
|
+
/** Specify the task type for models that require prefixes (e.g. nomic-embed-text) */
|
|
13
|
+
taskType?: 'query' | 'document';
|
|
14
|
+
}
|
|
15
|
+
interface ILLMProvider {
|
|
16
|
+
/**
|
|
17
|
+
* Send a chat completion request.
|
|
18
|
+
* @param messages – the full conversation history
|
|
19
|
+
* @param context – retrieved RAG context to inject
|
|
20
|
+
* @param options – optional per-call overrides
|
|
21
|
+
* @returns – the assistant's reply text
|
|
22
|
+
*/
|
|
23
|
+
chat(messages: ChatMessage[], context: string, options?: ChatOptions): Promise<string>;
|
|
24
|
+
/**
|
|
25
|
+
* Send a streaming chat completion request.
|
|
26
|
+
* @returns – an async iterable of text chunks
|
|
27
|
+
*/
|
|
28
|
+
chatStream?(messages: ChatMessage[], context: string, options?: ChatOptions): AsyncIterable<string>;
|
|
29
|
+
/**
|
|
30
|
+
* Generate an embedding vector for the given text.
|
|
31
|
+
* @param text – text to embed
|
|
32
|
+
* @param options – optional overrides
|
|
33
|
+
* @returns – float array (the embedding)
|
|
34
|
+
*/
|
|
35
|
+
embed(text: string, options?: EmbedOptions): Promise<number[]>;
|
|
36
|
+
/**
|
|
37
|
+
* Generate embedding vectors for multiple texts in a single batch.
|
|
38
|
+
* @param texts – array of texts to embed
|
|
39
|
+
* @param options – optional overrides
|
|
40
|
+
* @returns – array of float arrays
|
|
41
|
+
*/
|
|
42
|
+
batchEmbed(texts: string[], options?: EmbedOptions): Promise<number[][]>;
|
|
43
|
+
/**
|
|
44
|
+
* Check if the provider endpoint is reachable.
|
|
45
|
+
*/
|
|
46
|
+
ping(): Promise<boolean>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* DocumentChunker — splits long text into overlapping chunks
|
|
51
|
+
* suitable for vector embedding and retrieval.
|
|
52
|
+
*
|
|
53
|
+
* Strategy: sentence-aware sliding window
|
|
54
|
+
* 1. Split on sentence boundaries
|
|
55
|
+
* 2. Accumulate sentences into chunks up to `chunkSize` characters
|
|
56
|
+
* 3. Carry over `chunkOverlap` characters from the previous chunk
|
|
57
|
+
*/
|
|
58
|
+
interface Chunk {
|
|
59
|
+
id: string;
|
|
60
|
+
content: string;
|
|
61
|
+
metadata?: Record<string, unknown>;
|
|
62
|
+
}
|
|
63
|
+
interface ChunkOptions {
|
|
64
|
+
/** Target chunk size in characters (default 1000) */
|
|
65
|
+
chunkSize?: number;
|
|
66
|
+
/** Overlap between consecutive chunks in characters (default 200) */
|
|
67
|
+
chunkOverlap?: number;
|
|
68
|
+
/** Source document identifier used as ID prefix */
|
|
69
|
+
docId?: string | number;
|
|
70
|
+
/** Extra metadata to attach to every chunk */
|
|
71
|
+
metadata?: Record<string, unknown>;
|
|
72
|
+
/** Characters used to split text, in order of priority */
|
|
73
|
+
separators?: string[];
|
|
74
|
+
}
|
|
75
|
+
declare class DocumentChunker {
|
|
76
|
+
private readonly chunkSize;
|
|
77
|
+
private readonly chunkOverlap;
|
|
78
|
+
private readonly separators;
|
|
79
|
+
constructor(chunkSize?: number, chunkOverlap?: number, separators?: string[]);
|
|
80
|
+
/**
|
|
81
|
+
* Split a single text string into overlapping chunks using a recursive strategy.
|
|
82
|
+
* Preserves structural boundaries (Markdown headers) where possible.
|
|
83
|
+
*/
|
|
84
|
+
chunk(text: string, options?: ChunkOptions): Chunk[];
|
|
85
|
+
private recursiveSplit;
|
|
86
|
+
chunkMany(documents: Array<{
|
|
87
|
+
content: string;
|
|
88
|
+
docId?: string | number;
|
|
89
|
+
metadata?: Record<string, unknown>;
|
|
90
|
+
}>): Chunk[];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export { type Chunk as C, DocumentChunker as D, type EmbedOptions as E, type ILLMProvider as I, type ChunkOptions as a };
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { C as ChatMessage, c as ChatOptions } from './index-Cti1u0y1.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Generic LLM Provider interface.
|
|
5
|
+
* Covers both chat completion and embedding generation so a single
|
|
6
|
+
* provider can handle both responsibilities when appropriate.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
interface EmbedOptions {
|
|
10
|
+
/** Override model for this specific embed call */
|
|
11
|
+
model?: string;
|
|
12
|
+
/** Specify the task type for models that require prefixes (e.g. nomic-embed-text) */
|
|
13
|
+
taskType?: 'query' | 'document';
|
|
14
|
+
}
|
|
15
|
+
interface ILLMProvider {
|
|
16
|
+
/**
|
|
17
|
+
* Send a chat completion request.
|
|
18
|
+
* @param messages – the full conversation history
|
|
19
|
+
* @param context – retrieved RAG context to inject
|
|
20
|
+
* @param options – optional per-call overrides
|
|
21
|
+
* @returns – the assistant's reply text
|
|
22
|
+
*/
|
|
23
|
+
chat(messages: ChatMessage[], context: string, options?: ChatOptions): Promise<string>;
|
|
24
|
+
/**
|
|
25
|
+
* Send a streaming chat completion request.
|
|
26
|
+
* @returns – an async iterable of text chunks
|
|
27
|
+
*/
|
|
28
|
+
chatStream?(messages: ChatMessage[], context: string, options?: ChatOptions): AsyncIterable<string>;
|
|
29
|
+
/**
|
|
30
|
+
* Generate an embedding vector for the given text.
|
|
31
|
+
* @param text – text to embed
|
|
32
|
+
* @param options – optional overrides
|
|
33
|
+
* @returns – float array (the embedding)
|
|
34
|
+
*/
|
|
35
|
+
embed(text: string, options?: EmbedOptions): Promise<number[]>;
|
|
36
|
+
/**
|
|
37
|
+
* Generate embedding vectors for multiple texts in a single batch.
|
|
38
|
+
* @param texts – array of texts to embed
|
|
39
|
+
* @param options – optional overrides
|
|
40
|
+
* @returns – array of float arrays
|
|
41
|
+
*/
|
|
42
|
+
batchEmbed(texts: string[], options?: EmbedOptions): Promise<number[][]>;
|
|
43
|
+
/**
|
|
44
|
+
* Check if the provider endpoint is reachable.
|
|
45
|
+
*/
|
|
46
|
+
ping(): Promise<boolean>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* DocumentChunker — splits long text into overlapping chunks
|
|
51
|
+
* suitable for vector embedding and retrieval.
|
|
52
|
+
*
|
|
53
|
+
* Strategy: sentence-aware sliding window
|
|
54
|
+
* 1. Split on sentence boundaries
|
|
55
|
+
* 2. Accumulate sentences into chunks up to `chunkSize` characters
|
|
56
|
+
* 3. Carry over `chunkOverlap` characters from the previous chunk
|
|
57
|
+
*/
|
|
58
|
+
interface Chunk {
|
|
59
|
+
id: string;
|
|
60
|
+
content: string;
|
|
61
|
+
metadata?: Record<string, unknown>;
|
|
62
|
+
}
|
|
63
|
+
interface ChunkOptions {
|
|
64
|
+
/** Target chunk size in characters (default 1000) */
|
|
65
|
+
chunkSize?: number;
|
|
66
|
+
/** Overlap between consecutive chunks in characters (default 200) */
|
|
67
|
+
chunkOverlap?: number;
|
|
68
|
+
/** Source document identifier used as ID prefix */
|
|
69
|
+
docId?: string | number;
|
|
70
|
+
/** Extra metadata to attach to every chunk */
|
|
71
|
+
metadata?: Record<string, unknown>;
|
|
72
|
+
/** Characters used to split text, in order of priority */
|
|
73
|
+
separators?: string[];
|
|
74
|
+
}
|
|
75
|
+
declare class DocumentChunker {
|
|
76
|
+
private readonly chunkSize;
|
|
77
|
+
private readonly chunkOverlap;
|
|
78
|
+
private readonly separators;
|
|
79
|
+
constructor(chunkSize?: number, chunkOverlap?: number, separators?: string[]);
|
|
80
|
+
/**
|
|
81
|
+
* Split a single text string into overlapping chunks using a recursive strategy.
|
|
82
|
+
* Preserves structural boundaries (Markdown headers) where possible.
|
|
83
|
+
*/
|
|
84
|
+
chunk(text: string, options?: ChunkOptions): Chunk[];
|
|
85
|
+
private recursiveSplit;
|
|
86
|
+
chunkMany(documents: Array<{
|
|
87
|
+
content: string;
|
|
88
|
+
docId?: string | number;
|
|
89
|
+
metadata?: Record<string, unknown>;
|
|
90
|
+
}>): Chunk[];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export { type Chunk as C, DocumentChunker as D, type EmbedOptions as E, type ILLMProvider as I, type ChunkOptions as a };
|
|
@@ -2523,6 +2523,50 @@ Optimized Search Query:`;
|
|
|
2523
2523
|
);
|
|
2524
2524
|
return rewrite.trim() || question;
|
|
2525
2525
|
}
|
|
2526
|
+
/**
|
|
2527
|
+
* Generate 3-5 short, relevant questions based on the vector database content.
|
|
2528
|
+
*/
|
|
2529
|
+
async getSuggestions(query, namespace) {
|
|
2530
|
+
if (!query || query.trim().length < 3) {
|
|
2531
|
+
return [];
|
|
2532
|
+
}
|
|
2533
|
+
await this.initialize();
|
|
2534
|
+
const ns = namespace != null ? namespace : this.config.projectId;
|
|
2535
|
+
try {
|
|
2536
|
+
const { sources } = await this.retrieve(query, { namespace: ns, topK: 3 });
|
|
2537
|
+
if (sources.length === 0) {
|
|
2538
|
+
return [];
|
|
2539
|
+
}
|
|
2540
|
+
const context = sources.map((s) => s.content).join("\n\n---\n\n");
|
|
2541
|
+
const prompt = `
|
|
2542
|
+
Based on the following snippets from a document, what are 3 short, relevant questions a user might ask?
|
|
2543
|
+
Focus on questions that can be answered by the context.
|
|
2544
|
+
Keep each question under 10 words and make them very specific to the content.
|
|
2545
|
+
Return ONLY a JSON array of strings like ["Question 1", "Question 2", "Question 3"].
|
|
2546
|
+
|
|
2547
|
+
Context:
|
|
2548
|
+
${context}
|
|
2549
|
+
|
|
2550
|
+
Suggestions:`;
|
|
2551
|
+
const response = await this.llmProvider.chat(
|
|
2552
|
+
[
|
|
2553
|
+
{ role: "system", content: "You are a helpful assistant that generates search suggestions." },
|
|
2554
|
+
{ role: "user", content: prompt }
|
|
2555
|
+
],
|
|
2556
|
+
""
|
|
2557
|
+
);
|
|
2558
|
+
const match = response.match(/\[[\s\S]*\]/);
|
|
2559
|
+
if (match) {
|
|
2560
|
+
const suggestions = JSON.parse(match[0]);
|
|
2561
|
+
if (Array.isArray(suggestions)) {
|
|
2562
|
+
return suggestions.map((s) => String(s)).slice(0, 3);
|
|
2563
|
+
}
|
|
2564
|
+
}
|
|
2565
|
+
} catch (error) {
|
|
2566
|
+
console.error("[Pipeline] Failed to generate suggestions:", error);
|
|
2567
|
+
}
|
|
2568
|
+
return [];
|
|
2569
|
+
}
|
|
2526
2570
|
};
|
|
2527
2571
|
|
|
2528
2572
|
// src/core/ProviderHealthCheck.ts
|
|
@@ -2677,6 +2721,13 @@ var VectorPlugin = class {
|
|
|
2677
2721
|
await this.validationPromise;
|
|
2678
2722
|
return this.pipeline.ingest(documents, namespace);
|
|
2679
2723
|
}
|
|
2724
|
+
/**
|
|
2725
|
+
* Get auto-suggestions based on a query prefix.
|
|
2726
|
+
*/
|
|
2727
|
+
async getSuggestions(query, namespace) {
|
|
2728
|
+
await this.validationPromise;
|
|
2729
|
+
return this.pipeline.getSuggestions(query, namespace);
|
|
2730
|
+
}
|
|
2680
2731
|
};
|
|
2681
2732
|
|
|
2682
2733
|
// src/utils/DocumentParser.ts
|
|
@@ -2906,6 +2957,23 @@ function createUploadHandler(configOrPlugin) {
|
|
|
2906
2957
|
}
|
|
2907
2958
|
};
|
|
2908
2959
|
}
|
|
2960
|
+
function createSuggestionsHandler(configOrPlugin) {
|
|
2961
|
+
const plugin = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
|
|
2962
|
+
return async function POST(req) {
|
|
2963
|
+
try {
|
|
2964
|
+
const body = await req.json();
|
|
2965
|
+
const { query, namespace } = body;
|
|
2966
|
+
if (typeof query !== "string") {
|
|
2967
|
+
return NextResponse.json({ error: "query is required" }, { status: 400 });
|
|
2968
|
+
}
|
|
2969
|
+
const suggestions = await plugin.getSuggestions(query, namespace);
|
|
2970
|
+
return NextResponse.json({ suggestions });
|
|
2971
|
+
} catch (err) {
|
|
2972
|
+
const message = err instanceof Error ? err.message : "Internal server error";
|
|
2973
|
+
return NextResponse.json({ error: message }, { status: 500 });
|
|
2974
|
+
}
|
|
2975
|
+
};
|
|
2976
|
+
}
|
|
2909
2977
|
|
|
2910
2978
|
export {
|
|
2911
2979
|
getRagConfig,
|
|
@@ -2935,5 +3003,6 @@ export {
|
|
|
2935
3003
|
createStreamHandler,
|
|
2936
3004
|
createIngestHandler,
|
|
2937
3005
|
createHealthHandler,
|
|
2938
|
-
createUploadHandler
|
|
3006
|
+
createUploadHandler,
|
|
3007
|
+
createSuggestionsHandler
|
|
2939
3008
|
};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import '../
|
|
2
|
-
export { c as createChatHandler, d as createHealthHandler, e as createIngestHandler, f as createStreamHandler, g as createUploadHandler, s as sseErrorFrame, h as sseFrame, i as sseMetaFrame, j as sseTextFrame } from '../index-
|
|
1
|
+
import '../index-Cti1u0y1.mjs';
|
|
2
|
+
export { c as createChatHandler, d as createHealthHandler, e as createIngestHandler, f as createStreamHandler, k as createSuggestionsHandler, g as createUploadHandler, s as sseErrorFrame, h as sseFrame, i as sseMetaFrame, j as sseTextFrame } from '../index-kUXnRvuI.mjs';
|
|
3
3
|
import 'next/server';
|
package/dist/handlers/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import '../
|
|
2
|
-
export { c as createChatHandler, d as createHealthHandler, e as createIngestHandler, f as createStreamHandler, g as createUploadHandler, s as sseErrorFrame, h as sseFrame, i as sseMetaFrame, j as sseTextFrame } from '../index-
|
|
1
|
+
import '../index-Cti1u0y1.js';
|
|
2
|
+
export { c as createChatHandler, d as createHealthHandler, e as createIngestHandler, f as createStreamHandler, k as createSuggestionsHandler, g as createUploadHandler, s as sseErrorFrame, h as sseFrame, i as sseMetaFrame, j as sseTextFrame } from '../index-B67KQ9NN.js';
|
|
3
3
|
import 'next/server';
|
package/dist/handlers/index.js
CHANGED
|
@@ -1612,6 +1612,7 @@ __export(handlers_exports, {
|
|
|
1612
1612
|
createHealthHandler: () => createHealthHandler,
|
|
1613
1613
|
createIngestHandler: () => createIngestHandler,
|
|
1614
1614
|
createStreamHandler: () => createStreamHandler,
|
|
1615
|
+
createSuggestionsHandler: () => createSuggestionsHandler,
|
|
1615
1616
|
createUploadHandler: () => createUploadHandler,
|
|
1616
1617
|
sseErrorFrame: () => sseErrorFrame,
|
|
1617
1618
|
sseFrame: () => sseFrame,
|
|
@@ -4085,6 +4086,50 @@ Optimized Search Query:`;
|
|
|
4085
4086
|
);
|
|
4086
4087
|
return rewrite.trim() || question;
|
|
4087
4088
|
}
|
|
4089
|
+
/**
|
|
4090
|
+
* Generate 3-5 short, relevant questions based on the vector database content.
|
|
4091
|
+
*/
|
|
4092
|
+
async getSuggestions(query, namespace) {
|
|
4093
|
+
if (!query || query.trim().length < 3) {
|
|
4094
|
+
return [];
|
|
4095
|
+
}
|
|
4096
|
+
await this.initialize();
|
|
4097
|
+
const ns = namespace != null ? namespace : this.config.projectId;
|
|
4098
|
+
try {
|
|
4099
|
+
const { sources } = await this.retrieve(query, { namespace: ns, topK: 3 });
|
|
4100
|
+
if (sources.length === 0) {
|
|
4101
|
+
return [];
|
|
4102
|
+
}
|
|
4103
|
+
const context = sources.map((s) => s.content).join("\n\n---\n\n");
|
|
4104
|
+
const prompt = `
|
|
4105
|
+
Based on the following snippets from a document, what are 3 short, relevant questions a user might ask?
|
|
4106
|
+
Focus on questions that can be answered by the context.
|
|
4107
|
+
Keep each question under 10 words and make them very specific to the content.
|
|
4108
|
+
Return ONLY a JSON array of strings like ["Question 1", "Question 2", "Question 3"].
|
|
4109
|
+
|
|
4110
|
+
Context:
|
|
4111
|
+
${context}
|
|
4112
|
+
|
|
4113
|
+
Suggestions:`;
|
|
4114
|
+
const response = await this.llmProvider.chat(
|
|
4115
|
+
[
|
|
4116
|
+
{ role: "system", content: "You are a helpful assistant that generates search suggestions." },
|
|
4117
|
+
{ role: "user", content: prompt }
|
|
4118
|
+
],
|
|
4119
|
+
""
|
|
4120
|
+
);
|
|
4121
|
+
const match = response.match(/\[[\s\S]*\]/);
|
|
4122
|
+
if (match) {
|
|
4123
|
+
const suggestions = JSON.parse(match[0]);
|
|
4124
|
+
if (Array.isArray(suggestions)) {
|
|
4125
|
+
return suggestions.map((s) => String(s)).slice(0, 3);
|
|
4126
|
+
}
|
|
4127
|
+
}
|
|
4128
|
+
} catch (error) {
|
|
4129
|
+
console.error("[Pipeline] Failed to generate suggestions:", error);
|
|
4130
|
+
}
|
|
4131
|
+
return [];
|
|
4132
|
+
}
|
|
4088
4133
|
};
|
|
4089
4134
|
|
|
4090
4135
|
// src/core/ProviderHealthCheck.ts
|
|
@@ -4239,6 +4284,13 @@ var VectorPlugin = class {
|
|
|
4239
4284
|
await this.validationPromise;
|
|
4240
4285
|
return this.pipeline.ingest(documents, namespace);
|
|
4241
4286
|
}
|
|
4287
|
+
/**
|
|
4288
|
+
* Get auto-suggestions based on a query prefix.
|
|
4289
|
+
*/
|
|
4290
|
+
async getSuggestions(query, namespace) {
|
|
4291
|
+
await this.validationPromise;
|
|
4292
|
+
return this.pipeline.getSuggestions(query, namespace);
|
|
4293
|
+
}
|
|
4242
4294
|
};
|
|
4243
4295
|
|
|
4244
4296
|
// src/utils/DocumentParser.ts
|
|
@@ -4468,12 +4520,30 @@ function createUploadHandler(configOrPlugin) {
|
|
|
4468
4520
|
}
|
|
4469
4521
|
};
|
|
4470
4522
|
}
|
|
4523
|
+
function createSuggestionsHandler(configOrPlugin) {
|
|
4524
|
+
const plugin = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
|
|
4525
|
+
return async function POST(req) {
|
|
4526
|
+
try {
|
|
4527
|
+
const body = await req.json();
|
|
4528
|
+
const { query, namespace } = body;
|
|
4529
|
+
if (typeof query !== "string") {
|
|
4530
|
+
return import_server.NextResponse.json({ error: "query is required" }, { status: 400 });
|
|
4531
|
+
}
|
|
4532
|
+
const suggestions = await plugin.getSuggestions(query, namespace);
|
|
4533
|
+
return import_server.NextResponse.json({ suggestions });
|
|
4534
|
+
} catch (err) {
|
|
4535
|
+
const message = err instanceof Error ? err.message : "Internal server error";
|
|
4536
|
+
return import_server.NextResponse.json({ error: message }, { status: 500 });
|
|
4537
|
+
}
|
|
4538
|
+
};
|
|
4539
|
+
}
|
|
4471
4540
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4472
4541
|
0 && (module.exports = {
|
|
4473
4542
|
createChatHandler,
|
|
4474
4543
|
createHealthHandler,
|
|
4475
4544
|
createIngestHandler,
|
|
4476
4545
|
createStreamHandler,
|
|
4546
|
+
createSuggestionsHandler,
|
|
4477
4547
|
createUploadHandler,
|
|
4478
4548
|
sseErrorFrame,
|
|
4479
4549
|
sseFrame,
|
package/dist/handlers/index.mjs
CHANGED
|
@@ -3,12 +3,13 @@ import {
|
|
|
3
3
|
createHealthHandler,
|
|
4
4
|
createIngestHandler,
|
|
5
5
|
createStreamHandler,
|
|
6
|
+
createSuggestionsHandler,
|
|
6
7
|
createUploadHandler,
|
|
7
8
|
sseErrorFrame,
|
|
8
9
|
sseFrame,
|
|
9
10
|
sseMetaFrame,
|
|
10
11
|
sseTextFrame
|
|
11
|
-
} from "../chunk-
|
|
12
|
+
} from "../chunk-GCPPRD2G.mjs";
|
|
12
13
|
import "../chunk-YLTMFW4M.mjs";
|
|
13
14
|
import "../chunk-X4TOT24V.mjs";
|
|
14
15
|
export {
|
|
@@ -16,6 +17,7 @@ export {
|
|
|
16
17
|
createHealthHandler,
|
|
17
18
|
createIngestHandler,
|
|
18
19
|
createStreamHandler,
|
|
20
|
+
createSuggestionsHandler,
|
|
19
21
|
createUploadHandler,
|
|
20
22
|
sseErrorFrame,
|
|
21
23
|
sseFrame,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { h as RagConfig, C as ChatMessage, d as ChatResponse, I as IngestDocument } from './index-Cti1u0y1.js';
|
|
2
2
|
import { NextRequest, NextResponse } from 'next/server';
|
|
3
3
|
|
|
4
4
|
interface ValidationError {
|
|
@@ -112,6 +112,10 @@ declare class VectorPlugin {
|
|
|
112
112
|
docId: string | number;
|
|
113
113
|
chunksIngested: number;
|
|
114
114
|
}>>;
|
|
115
|
+
/**
|
|
116
|
+
* Get auto-suggestions based on a query prefix.
|
|
117
|
+
*/
|
|
118
|
+
getSuggestions(query: string, namespace?: string): Promise<string[]>;
|
|
115
119
|
}
|
|
116
120
|
|
|
117
121
|
/**
|
|
@@ -202,5 +206,13 @@ declare function createUploadHandler(configOrPlugin?: Partial<RagConfig> | Vecto
|
|
|
202
206
|
chunksIngested: number;
|
|
203
207
|
}[];
|
|
204
208
|
}>>;
|
|
209
|
+
/**
|
|
210
|
+
* createSuggestionsHandler — factory for the auto-suggestions endpoint.
|
|
211
|
+
*/
|
|
212
|
+
declare function createSuggestionsHandler(configOrPlugin?: Partial<RagConfig> | VectorPlugin): (req: NextRequest) => Promise<NextResponse<{
|
|
213
|
+
error: string;
|
|
214
|
+
}> | NextResponse<{
|
|
215
|
+
suggestions: string[];
|
|
216
|
+
}>>;
|
|
205
217
|
|
|
206
|
-
export { ConfigValidator as C, type HealthCheckResult as H, type IProviderValidator as I, type ValidationError as V, type IProviderHealthChecker as a, VectorPlugin as b, createChatHandler as c, createHealthHandler as d, createIngestHandler as e, createStreamHandler as f, createUploadHandler as g, sseFrame as h, sseMetaFrame as i, sseTextFrame as j, sseErrorFrame as s };
|
|
218
|
+
export { ConfigValidator as C, type HealthCheckResult as H, type IProviderValidator as I, type ValidationError as V, type IProviderHealthChecker as a, VectorPlugin as b, createChatHandler as c, createHealthHandler as d, createIngestHandler as e, createStreamHandler as f, createUploadHandler as g, sseFrame as h, sseMetaFrame as i, sseTextFrame as j, createSuggestionsHandler as k, sseErrorFrame as s };
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
* Generic LLM Provider interface.
|
|
3
|
-
* Covers both chat completion and embedding generation so a single
|
|
4
|
-
* provider can handle both responsibilities when appropriate.
|
|
5
|
-
*/
|
|
1
|
+
type MessageRole = 'user' | 'assistant' | 'system';
|
|
6
2
|
interface ChatMessage {
|
|
7
|
-
role:
|
|
3
|
+
role: MessageRole;
|
|
8
4
|
content: string;
|
|
9
5
|
}
|
|
6
|
+
interface RagMessage extends ChatMessage {
|
|
7
|
+
id: string;
|
|
8
|
+
sources?: VectorMatch[];
|
|
9
|
+
createdAt: string;
|
|
10
|
+
}
|
|
10
11
|
interface ChatOptions {
|
|
11
12
|
/** Override max tokens for this specific call */
|
|
12
13
|
maxTokens?: number;
|
|
@@ -15,86 +16,33 @@ interface ChatOptions {
|
|
|
15
16
|
/** Stop sequences */
|
|
16
17
|
stop?: string[];
|
|
17
18
|
}
|
|
18
|
-
interface
|
|
19
|
-
/** Override
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
* @param options – optional per-call overrides
|
|
30
|
-
* @returns – the assistant's reply text
|
|
31
|
-
*/
|
|
32
|
-
chat(messages: ChatMessage[], context: string, options?: ChatOptions): Promise<string>;
|
|
33
|
-
/**
|
|
34
|
-
* Send a streaming chat completion request.
|
|
35
|
-
* @returns – an async iterable of text chunks
|
|
36
|
-
*/
|
|
37
|
-
chatStream?(messages: ChatMessage[], context: string, options?: ChatOptions): AsyncIterable<string>;
|
|
38
|
-
/**
|
|
39
|
-
* Generate an embedding vector for the given text.
|
|
40
|
-
* @param text – text to embed
|
|
41
|
-
* @param options – optional overrides
|
|
42
|
-
* @returns – float array (the embedding)
|
|
43
|
-
*/
|
|
44
|
-
embed(text: string, options?: EmbedOptions): Promise<number[]>;
|
|
45
|
-
/**
|
|
46
|
-
* Generate embedding vectors for multiple texts in a single batch.
|
|
47
|
-
* @param texts – array of texts to embed
|
|
48
|
-
* @param options – optional overrides
|
|
49
|
-
* @returns – array of float arrays
|
|
50
|
-
*/
|
|
51
|
-
batchEmbed(texts: string[], options?: EmbedOptions): Promise<number[][]>;
|
|
52
|
-
/**
|
|
53
|
-
* Check if the provider endpoint is reachable.
|
|
54
|
-
*/
|
|
55
|
-
ping(): Promise<boolean>;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
interface VectorMatch {
|
|
59
|
-
id: string | number;
|
|
60
|
-
score: number;
|
|
61
|
-
content: string;
|
|
62
|
-
metadata?: Record<string, unknown>;
|
|
63
|
-
}
|
|
64
|
-
interface UpsertDocument {
|
|
65
|
-
id: string | number;
|
|
66
|
-
vector: number[];
|
|
67
|
-
content: string;
|
|
68
|
-
metadata?: Record<string, unknown>;
|
|
69
|
-
}
|
|
70
|
-
interface IngestDocument {
|
|
71
|
-
docId: string | number;
|
|
72
|
-
content: string;
|
|
73
|
-
metadata?: Record<string, unknown>;
|
|
74
|
-
}
|
|
75
|
-
interface ChatResponse {
|
|
76
|
-
reply: string;
|
|
77
|
-
sources: VectorMatch[];
|
|
78
|
-
graphData?: GraphSearchResult;
|
|
79
|
-
}
|
|
80
|
-
interface GraphNode {
|
|
81
|
-
id: string;
|
|
82
|
-
label: string;
|
|
83
|
-
properties?: Record<string, unknown>;
|
|
84
|
-
}
|
|
85
|
-
interface Edge {
|
|
86
|
-
source: string;
|
|
87
|
-
target: string;
|
|
88
|
-
type: string;
|
|
89
|
-
properties?: Record<string, unknown>;
|
|
90
|
-
}
|
|
91
|
-
interface GraphSearchResult {
|
|
92
|
-
nodes: GraphNode[];
|
|
93
|
-
edges: Edge[];
|
|
19
|
+
interface UseRagChatOptions {
|
|
20
|
+
/** Override the chat API endpoint (default: /api/chat) */
|
|
21
|
+
apiUrl?: string;
|
|
22
|
+
/** Override project namespace */
|
|
23
|
+
namespace?: string;
|
|
24
|
+
/** Persist chat history to localStorage (default: true) */
|
|
25
|
+
persist?: boolean;
|
|
26
|
+
/** Called after each successful assistant reply */
|
|
27
|
+
onReply?: (message: RagMessage) => void;
|
|
28
|
+
/** Called on error */
|
|
29
|
+
onError?: (error: string) => void;
|
|
94
30
|
}
|
|
95
|
-
interface
|
|
96
|
-
|
|
97
|
-
|
|
31
|
+
interface UseRagChatReturn {
|
|
32
|
+
/** All messages in the current conversation */
|
|
33
|
+
messages: RagMessage[];
|
|
34
|
+
/** Whether a response is in flight */
|
|
35
|
+
isLoading: boolean;
|
|
36
|
+
/** Current error message, or null */
|
|
37
|
+
error: string | null;
|
|
38
|
+
/** Send a user message */
|
|
39
|
+
send: (text: string) => Promise<void>;
|
|
40
|
+
/** Clear the conversation (and localStorage if persist=true) */
|
|
41
|
+
clear: () => void;
|
|
42
|
+
/** Retry the last failed send */
|
|
43
|
+
retry: () => Promise<void>;
|
|
44
|
+
/** Programmatically set the conversation (e.g. to restore from a DB) */
|
|
45
|
+
setMessages: React.Dispatch<React.SetStateAction<RagMessage[]>>;
|
|
98
46
|
}
|
|
99
47
|
|
|
100
48
|
/**
|
|
@@ -224,6 +172,8 @@ interface UIConfig {
|
|
|
224
172
|
allowUpload?: boolean;
|
|
225
173
|
/** Whether to allow manual resizing of the chat window. Defaults to true. */
|
|
226
174
|
allowResize?: boolean;
|
|
175
|
+
/** Whether to enable voice search input. Defaults to true. */
|
|
176
|
+
enableVoiceInput?: boolean;
|
|
227
177
|
}
|
|
228
178
|
interface RAGConfig {
|
|
229
179
|
/** Number of top-K chunks retrieved per query */
|
|
@@ -271,4 +221,55 @@ interface RagConfig {
|
|
|
271
221
|
graphDb?: GraphDBConfig;
|
|
272
222
|
}
|
|
273
223
|
|
|
274
|
-
|
|
224
|
+
interface VectorMatch {
|
|
225
|
+
id: string | number;
|
|
226
|
+
score: number;
|
|
227
|
+
content: string;
|
|
228
|
+
metadata?: Record<string, unknown>;
|
|
229
|
+
}
|
|
230
|
+
interface UpsertDocument {
|
|
231
|
+
id: string | number;
|
|
232
|
+
vector: number[];
|
|
233
|
+
content: string;
|
|
234
|
+
metadata?: Record<string, unknown>;
|
|
235
|
+
}
|
|
236
|
+
interface IngestDocument {
|
|
237
|
+
docId: string | number;
|
|
238
|
+
content: string;
|
|
239
|
+
metadata?: Record<string, unknown>;
|
|
240
|
+
}
|
|
241
|
+
interface ChatResponse {
|
|
242
|
+
reply: string;
|
|
243
|
+
sources: VectorMatch[];
|
|
244
|
+
graphData?: GraphSearchResult;
|
|
245
|
+
}
|
|
246
|
+
interface GraphNode {
|
|
247
|
+
id: string;
|
|
248
|
+
label: string;
|
|
249
|
+
properties?: Record<string, unknown>;
|
|
250
|
+
}
|
|
251
|
+
interface Edge {
|
|
252
|
+
source: string;
|
|
253
|
+
target: string;
|
|
254
|
+
type: string;
|
|
255
|
+
properties?: Record<string, unknown>;
|
|
256
|
+
}
|
|
257
|
+
interface GraphSearchResult {
|
|
258
|
+
nodes: GraphNode[];
|
|
259
|
+
edges: Edge[];
|
|
260
|
+
}
|
|
261
|
+
interface RetrievalResult {
|
|
262
|
+
sources: VectorMatch[];
|
|
263
|
+
graphData?: GraphSearchResult;
|
|
264
|
+
}
|
|
265
|
+
interface Product {
|
|
266
|
+
id: string | number;
|
|
267
|
+
name: string;
|
|
268
|
+
brand?: string;
|
|
269
|
+
price?: string | number;
|
|
270
|
+
image?: string;
|
|
271
|
+
link?: string;
|
|
272
|
+
description?: string;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
export type { ChatMessage as C, EmbeddingConfig as E, GraphDBConfig as G, IngestDocument as I, LLMConfig as L, Product as P, RagMessage as R, UIConfig as U, VectorMatch as V, UseRagChatOptions as a, UseRagChatReturn as b, ChatOptions as c, ChatResponse as d, EmbeddingProvider as e, LLMProvider as f, RAGConfig as g, RagConfig as h, UpsertDocument as i, VectorDBConfig as j, VectorDBProvider as k, RetrievalResult as l, GraphNode as m, Edge as n, GraphSearchResult as o };
|