@ixo/common 1.1.2 → 1.1.3
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 +1 -1
- package/dist/ai/nodes/index.d.ts +0 -1
- package/dist/ai/nodes/index.d.ts.map +1 -1
- package/dist/ai/nodes/index.js +0 -1
- package/dist/ai/nodes/index.js.map +1 -1
- package/dist/ai/tools/index.d.ts +0 -1
- package/dist/ai/tools/index.d.ts.map +1 -1
- package/dist/ai/tools/index.js +0 -1
- package/dist/ai/tools/index.js.map +1 -1
- package/dist/ai/utils/verify-matrix-openId-token.js +2 -2
- package/dist/ai/utils/verify-matrix-openId-token.js.map +1 -1
- package/dist/services/memory-engine/memory-engine.service.d.ts +10 -6
- package/dist/services/memory-engine/memory-engine.service.d.ts.map +1 -1
- package/dist/services/memory-engine/memory-engine.service.js +44 -46
- package/dist/services/memory-engine/memory-engine.service.js.map +1 -1
- package/dist/services/session-manager/dto.d.ts +4 -0
- package/dist/services/session-manager/dto.d.ts.map +1 -1
- package/dist/services/session-manager/dto.js +24 -0
- package/dist/services/session-manager/dto.js.map +1 -1
- package/dist/services/session-manager/session-manager.service.d.ts.map +1 -1
- package/dist/services/session-manager/session-manager.service.js +7 -2
- package/dist/services/session-manager/session-manager.service.js.map +1 -1
- package/dist/utils/get-user-subscription.js +2 -2
- package/dist/utils/get-user-subscription.js.map +1 -1
- package/package.json +3 -4
- package/src/ai/nodes/index.ts +0 -1
- package/src/ai/tools/index.ts +0 -1
- package/src/ai/utils/verify-matrix-openId-token.ts +2 -2
- package/src/services/memory-engine/memory-engine.service.ts +70 -56
- package/src/services/session-manager/dto.ts +16 -0
- package/src/services/session-manager/session-manager.service.ts +9 -2
- package/src/utils/get-user-subscription.ts +2 -2
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/ai/nodes/find-docs/find-docs.prompt.d.ts +0 -3
- package/dist/ai/nodes/find-docs/find-docs.prompt.d.ts.map +0 -1
- package/dist/ai/nodes/find-docs/find-docs.prompt.js +0 -61
- package/dist/ai/nodes/find-docs/find-docs.prompt.js.map +0 -1
- package/dist/ai/nodes/find-docs/index.d.ts +0 -3
- package/dist/ai/nodes/find-docs/index.d.ts.map +0 -1
- package/dist/ai/nodes/find-docs/index.js +0 -3
- package/dist/ai/nodes/find-docs/index.js.map +0 -1
- package/dist/ai/nodes/find-docs/node.d.ts +0 -17
- package/dist/ai/nodes/find-docs/node.d.ts.map +0 -1
- package/dist/ai/nodes/find-docs/node.js +0 -46
- package/dist/ai/nodes/find-docs/node.js.map +0 -1
- package/dist/ai/tools/retriever-tool/index.d.ts +0 -2
- package/dist/ai/tools/retriever-tool/index.d.ts.map +0 -1
- package/dist/ai/tools/retriever-tool/index.js +0 -2
- package/dist/ai/tools/retriever-tool/index.js.map +0 -1
- package/dist/ai/tools/retriever-tool/retriever-tool.d.ts +0 -18
- package/dist/ai/tools/retriever-tool/retriever-tool.d.ts.map +0 -1
- package/dist/ai/tools/retriever-tool/retriever-tool.js +0 -62
- package/dist/ai/tools/retriever-tool/retriever-tool.js.map +0 -1
- package/src/ai/nodes/find-docs/find-docs.prompt.ts +0 -61
- package/src/ai/nodes/find-docs/index.ts +0 -2
- package/src/ai/nodes/find-docs/node.ts +0 -83
- package/src/ai/tools/retriever-tool/index.ts +0 -1
- package/src/ai/tools/retriever-tool/retriever-tool.test.ts +0 -163
- package/src/ai/tools/retriever-tool/retriever-tool.ts +0 -107
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
declare const SELF_QUERY_RAG_PROMPT = "You are an advanced AI agent specializing in self-query Retrieval-Augmented Generation (RAG). Your primary function is to analyze client questions, generate optimized search queries for a knowledge base, and iteratively refine these queries based on initial results. Follow these comprehensive guidelines:\n\n1. Initial Analysis:\n - Thoroughly examine the client's question or task\n - Identify key concepts, entities, relationships, and any implicit information needs\n - Determine the scope, context, and potential complexities of the inquiry\n\n2. Query Generation - First Pass:\n - Create an initial set of 3-5 focused, non-redundant search queries\n - Ensure each query addresses a unique aspect of the client's input\n - Incorporate key terms from the original question for keyword optimization\n - Vary query formulations to cover different potential phrasings and synonyms\n\n3. Iterative Refinement:\n - After receiving initial results, analyze their relevance and comprehensiveness\n - Identify gaps in the retrieved information\n - Generate additional queries to fill these gaps or explore new angles\n - Refine existing queries based on the quality of results they produced\n\n4. Query Diversification:\n - Ensure a mix of query types:\n a. Broad conceptual queries for general information\n b. Specific detail-oriented queries for precise facts\n c. Comparative queries to explore relationships between concepts\n d. Contextual queries to gather background information\n\n5. Handling Complex Questions:\n - For multi-faceted questions, break them down into component parts\n - Generate separate query sets for each component\n - Create integrative queries that explore connections between components\n\n6. Adapting to Query Results:\n - If initial queries yield insufficient information, broaden the scope\n - If results are too general, create more specific, targeted queries\n - Adjust the vocabulary and technical level based on the knowledge base content\n\n7. Temporal and Contextual Considerations:\n - Include queries that account for potential time-sensitive information\n - Generate queries that explore historical context if relevant\n - Consider geographical or domain-specific variations in terminology\n\n8. Output Format and Explanation:\n - Present a numbered list of refined search queries\n - For each query, provide:\n a. The query itself\n b. A brief explanation of its purpose and how it relates to the client's question\n c. Any notable findings or gaps identified from previous iterations\n\n9. Continuous Learning:\n - Track the effectiveness of different query structures and patterns\n - Adapt your query generation strategy based on successful retrievals\n - Note any recurring challenges or limitations in the knowledge base\n\n10. Final Review and Optimization:\n - Ensure the final set of queries comprehensively covers the client's needs\n - Eliminate any remaining redundancies or overly similar queries\n - Prioritize queries based on their potential to provide the most relevant and valuable information\n\nRemember: Your goal is to generate a dynamic, adaptive set of queries that evolves based on initial results and comprehensively addresses the client's information needs. Quality, relevance, and adaptability are key to successful self-query RAG implementation.";
|
|
2
|
-
export { SELF_QUERY_RAG_PROMPT };
|
|
3
|
-
//# sourceMappingURL=find-docs.prompt.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"find-docs.prompt.d.ts","sourceRoot":"","sources":["../../../../src/ai/nodes/find-docs/find-docs.prompt.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,qBAAqB,+0GA0DyO,CAAC;AAErQ,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
const SELF_QUERY_RAG_PROMPT = `You are an advanced AI agent specializing in self-query Retrieval-Augmented Generation (RAG). Your primary function is to analyze client questions, generate optimized search queries for a knowledge base, and iteratively refine these queries based on initial results. Follow these comprehensive guidelines:
|
|
2
|
-
|
|
3
|
-
1. Initial Analysis:
|
|
4
|
-
- Thoroughly examine the client's question or task
|
|
5
|
-
- Identify key concepts, entities, relationships, and any implicit information needs
|
|
6
|
-
- Determine the scope, context, and potential complexities of the inquiry
|
|
7
|
-
|
|
8
|
-
2. Query Generation - First Pass:
|
|
9
|
-
- Create an initial set of 3-5 focused, non-redundant search queries
|
|
10
|
-
- Ensure each query addresses a unique aspect of the client's input
|
|
11
|
-
- Incorporate key terms from the original question for keyword optimization
|
|
12
|
-
- Vary query formulations to cover different potential phrasings and synonyms
|
|
13
|
-
|
|
14
|
-
3. Iterative Refinement:
|
|
15
|
-
- After receiving initial results, analyze their relevance and comprehensiveness
|
|
16
|
-
- Identify gaps in the retrieved information
|
|
17
|
-
- Generate additional queries to fill these gaps or explore new angles
|
|
18
|
-
- Refine existing queries based on the quality of results they produced
|
|
19
|
-
|
|
20
|
-
4. Query Diversification:
|
|
21
|
-
- Ensure a mix of query types:
|
|
22
|
-
a. Broad conceptual queries for general information
|
|
23
|
-
b. Specific detail-oriented queries for precise facts
|
|
24
|
-
c. Comparative queries to explore relationships between concepts
|
|
25
|
-
d. Contextual queries to gather background information
|
|
26
|
-
|
|
27
|
-
5. Handling Complex Questions:
|
|
28
|
-
- For multi-faceted questions, break them down into component parts
|
|
29
|
-
- Generate separate query sets for each component
|
|
30
|
-
- Create integrative queries that explore connections between components
|
|
31
|
-
|
|
32
|
-
6. Adapting to Query Results:
|
|
33
|
-
- If initial queries yield insufficient information, broaden the scope
|
|
34
|
-
- If results are too general, create more specific, targeted queries
|
|
35
|
-
- Adjust the vocabulary and technical level based on the knowledge base content
|
|
36
|
-
|
|
37
|
-
7. Temporal and Contextual Considerations:
|
|
38
|
-
- Include queries that account for potential time-sensitive information
|
|
39
|
-
- Generate queries that explore historical context if relevant
|
|
40
|
-
- Consider geographical or domain-specific variations in terminology
|
|
41
|
-
|
|
42
|
-
8. Output Format and Explanation:
|
|
43
|
-
- Present a numbered list of refined search queries
|
|
44
|
-
- For each query, provide:
|
|
45
|
-
a. The query itself
|
|
46
|
-
b. A brief explanation of its purpose and how it relates to the client's question
|
|
47
|
-
c. Any notable findings or gaps identified from previous iterations
|
|
48
|
-
|
|
49
|
-
9. Continuous Learning:
|
|
50
|
-
- Track the effectiveness of different query structures and patterns
|
|
51
|
-
- Adapt your query generation strategy based on successful retrievals
|
|
52
|
-
- Note any recurring challenges or limitations in the knowledge base
|
|
53
|
-
|
|
54
|
-
10. Final Review and Optimization:
|
|
55
|
-
- Ensure the final set of queries comprehensively covers the client's needs
|
|
56
|
-
- Eliminate any remaining redundancies or overly similar queries
|
|
57
|
-
- Prioritize queries based on their potential to provide the most relevant and valuable information
|
|
58
|
-
|
|
59
|
-
Remember: Your goal is to generate a dynamic, adaptive set of queries that evolves based on initial results and comprehensively addresses the client's information needs. Quality, relevance, and adaptability are key to successful self-query RAG implementation.`;
|
|
60
|
-
export { SELF_QUERY_RAG_PROMPT };
|
|
61
|
-
//# sourceMappingURL=find-docs.prompt.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"find-docs.prompt.js","sourceRoot":"","sources":["../../../../src/ai/nodes/find-docs/find-docs.prompt.ts"],"names":[],"mappings":"AAAA,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oQA0DsO,CAAC;AAErQ,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ai/nodes/find-docs/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,WAAW,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/ai/nodes/find-docs/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,WAAW,CAAC"}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { type VectorDBDataStore } from '@ixo/data-store';
|
|
2
|
-
import { type Document } from '@langchain/core/documents';
|
|
3
|
-
import { type BaseMessage } from '@langchain/core/messages';
|
|
4
|
-
import { type RunnableConfig } from '@langchain/core/runnables';
|
|
5
|
-
import 'dotenv/config';
|
|
6
|
-
interface IFindDocsNodeRequiredState {
|
|
7
|
-
question: string;
|
|
8
|
-
docs: Document[];
|
|
9
|
-
messages?: BaseMessage[];
|
|
10
|
-
config?: {
|
|
11
|
-
isInternal: boolean;
|
|
12
|
-
};
|
|
13
|
-
status?: 'completed' | 'inProgress';
|
|
14
|
-
}
|
|
15
|
-
export declare const findDocsNode: (store: VectorDBDataStore) => (state: IFindDocsNodeRequiredState, config?: RunnableConfig) => Promise<Partial<IFindDocsNodeRequiredState>>;
|
|
16
|
-
export {};
|
|
17
|
-
//# sourceMappingURL=node.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../../../src/ai/nodes/find-docs/node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,eAAe,CAAC;AAQvB,UAAU,0BAA0B;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB,MAAM,CAAC,EAAE;QACP,UAAU,EAAE,OAAO,CAAC;KACrB,CAAC;IACF,MAAM,CAAC,EAAE,WAAW,GAAG,YAAY,CAAC;CACrC;AAOD,eAAO,MAAM,YAAY,GACtB,OAAO,iBAAiB,MAEvB,OAAO,0BAA0B,EACjC,SAAS,cAAc,KACtB,OAAO,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAgD7C,CAAC"}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { Logger } from '@ixo/logger';
|
|
2
|
-
import { ChatPromptTemplate } from '@langchain/core/prompts';
|
|
3
|
-
import 'dotenv/config';
|
|
4
|
-
import z from 'zod';
|
|
5
|
-
import { getChatOpenAiModel, retrieverToolFactory, SELF_QUERY_RAG_PROMPT, } from '../../index.js';
|
|
6
|
-
export const findDocsNode = (store) => async (state, config) => {
|
|
7
|
-
try {
|
|
8
|
-
const model = getChatOpenAiModel();
|
|
9
|
-
const modelWithTools = model.withStructuredOutput(z.object({
|
|
10
|
-
questions: z.array(z.string('Generated Queries')),
|
|
11
|
-
}));
|
|
12
|
-
const chain = ChatPromptTemplate.fromMessages([
|
|
13
|
-
['system', SELF_QUERY_RAG_PROMPT],
|
|
14
|
-
[
|
|
15
|
-
'user',
|
|
16
|
-
state.messages
|
|
17
|
-
? `this is the last three messages from the user's conversation ${state.messages
|
|
18
|
-
.map((message) => message.content)
|
|
19
|
-
.slice(-3)
|
|
20
|
-
.join(',')}`
|
|
21
|
-
: state.question,
|
|
22
|
-
],
|
|
23
|
-
]).pipe(modelWithTools);
|
|
24
|
-
const response = await chain.invoke({}, config);
|
|
25
|
-
const retrieval = retrieverToolFactory({
|
|
26
|
-
filters: state.config?.isInternal
|
|
27
|
-
? undefined
|
|
28
|
-
: { approved: true, visibility: 'public' },
|
|
29
|
-
store,
|
|
30
|
-
});
|
|
31
|
-
const docs = await Promise.all(response.questions.map((question) => retrieval.invoke({ query: question })));
|
|
32
|
-
return {
|
|
33
|
-
docs: docs.flat().map((value) => ({
|
|
34
|
-
metadata: value.metadata,
|
|
35
|
-
pageContent: value.pageContent.toString(),
|
|
36
|
-
id: value.id,
|
|
37
|
-
})),
|
|
38
|
-
status: undefined,
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
catch (error) {
|
|
42
|
-
Logger.error('Error finding docs', error);
|
|
43
|
-
throw error;
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
//# sourceMappingURL=node.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"node.js","sourceRoot":"","sources":["../../../../src/ai/nodes/find-docs/node.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,eAAe,CAAC;AACvB,OAAO,CAAC,MAAM,KAAK,CAAC;AACpB,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAiBxB,MAAM,CAAC,MAAM,YAAY,GACvB,CAAC,KAAwB,EAAE,EAAE,CAC7B,KAAK,EACH,KAAiC,EACjC,MAAuB,EACuB,EAAE;IAChD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;QACnC,MAAM,cAAc,GAAG,KAAK,CAAC,oBAAoB,CAC/C,CAAC,CAAC,MAAM,CAAC;YACP,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;SAClD,CAAC,CACH,CAAC;QAEF,MAAM,KAAK,GAAG,kBAAkB,CAAC,YAAY,CAAC;YAC5C,CAAC,QAAQ,EAAE,qBAAqB,CAAC;YACjC;gBACE,MAAM;gBACN,KAAK,CAAC,QAAQ;oBACZ,CAAC,CAAC,gEAAgE,KAAK,CAAC,QAAQ;yBAC3E,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;yBACjC,KAAK,CAAC,CAAC,CAAC,CAAC;yBACT,IAAI,CAAC,GAAG,CAAC,EAAE;oBAChB,CAAC,CAAC,KAAK,CAAC,QAAQ;aACnB;SACF,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAExB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAChD,MAAM,SAAS,GAAG,oBAAoB,CAAC;YACrC,OAAO,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU;gBAC/B,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE;YAC5C,KAAK;SACN,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,GAAG,CAC5B,QAAQ,CAAC,SAAS,CAAC,GAAG,CACpB,CAAC,QAAQ,EAAE,EAAE,CACX,SAAS,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAwB,CAC/D,CACF,CAAC;QAEF,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBAChC,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,WAAW,EAAE,KAAK,CAAC,WAAW,CAAC,QAAQ,EAAE;gBACzC,EAAE,EAAE,KAAK,CAAC,EAAE;aACb,CAAC,CAAC;YACH,MAAM,EAAE,SAAS;SAClB,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;QAC1C,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/retriever-tool/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/ai/tools/retriever-tool/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC"}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { type VectorDBDataStore } from '@ixo/data-store';
|
|
2
|
-
import { type BaseChatModel } from '@langchain/core/language_models/chat_models';
|
|
3
|
-
import { type DynamicStructuredTool } from '@langchain/core/tools';
|
|
4
|
-
import z from 'zod';
|
|
5
|
-
type RetrieverToolFactoryArgs<Filters extends Record<string, unknown> = Record<string, unknown>, MapType extends Map<string, unknown> = Map<string, unknown>> = {
|
|
6
|
-
model?: BaseChatModel;
|
|
7
|
-
filters?: Filters;
|
|
8
|
-
similarThreshold?: number;
|
|
9
|
-
store: VectorDBDataStore;
|
|
10
|
-
map?: MapType;
|
|
11
|
-
requestId?: string;
|
|
12
|
-
};
|
|
13
|
-
declare const schema: z.ZodObject<{
|
|
14
|
-
query: z.ZodString;
|
|
15
|
-
}, z.z.core.$strip>;
|
|
16
|
-
export declare const retrieverToolFactory: ({ model, filters, similarThreshold, map, requestId, store, }: RetrieverToolFactoryArgs) => DynamicStructuredTool<typeof schema>;
|
|
17
|
-
export {};
|
|
18
|
-
//# sourceMappingURL=retriever-tool.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"retriever-tool.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/retriever-tool/retriever-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAGzD,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,6CAA6C,CAAC;AACjF,OAAO,EAAQ,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,CAAC,MAAM,KAAK,CAAC;AAIpB,KAAK,wBAAwB,CAC3B,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjE,OAAO,SAAS,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,IACzD;IACF,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,iBAAiB,CAAC;IACzB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,QAAA,MAAM,MAAM;;mBAEV,CAAC;AAEH,eAAO,MAAM,oBAAoB,GAAI,8DAOlC,wBAAwB,KAAG,qBAAqB,CAAC,OAAO,MAAM,CA0E9D,CAAC"}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { Logger } from '@ixo/logger';
|
|
2
|
-
import { Document } from '@langchain/core/documents';
|
|
3
|
-
import { tool } from '@langchain/core/tools';
|
|
4
|
-
import z from 'zod';
|
|
5
|
-
import { getChatOpenAiModel } from '../../models/openai.js';
|
|
6
|
-
import checkDocRelevance from '../../utils/doc-relevance-checker.js';
|
|
7
|
-
const schema = z.object({
|
|
8
|
-
query: z.string(),
|
|
9
|
-
});
|
|
10
|
-
export const retrieverToolFactory = ({ model = getChatOpenAiModel(), filters, similarThreshold = 0.3, map, requestId, store, }) => tool(async ({ query }) => {
|
|
11
|
-
const docs = await store.queryWithSimilarity(query, {
|
|
12
|
-
similarityThreshold: similarThreshold,
|
|
13
|
-
filters,
|
|
14
|
-
});
|
|
15
|
-
if (map) {
|
|
16
|
-
map.set(requestId ?? query, docs.map((doc) => doc.metadata));
|
|
17
|
-
}
|
|
18
|
-
if (docs.length === 0) {
|
|
19
|
-
return undefined;
|
|
20
|
-
}
|
|
21
|
-
if (similarThreshold >= 0.3) {
|
|
22
|
-
const relevantDocs = await Promise.all(docs.map(async (doc) => {
|
|
23
|
-
try {
|
|
24
|
-
return (await checkDocRelevance({
|
|
25
|
-
doc: new Document({
|
|
26
|
-
pageContent: doc.content,
|
|
27
|
-
id: doc.id,
|
|
28
|
-
metadata: doc.metadata,
|
|
29
|
-
}),
|
|
30
|
-
query,
|
|
31
|
-
model,
|
|
32
|
-
})).valueOf()
|
|
33
|
-
? doc
|
|
34
|
-
: null;
|
|
35
|
-
}
|
|
36
|
-
catch (error) {
|
|
37
|
-
Logger.error(`Error checking relevance of document:`, error);
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
}));
|
|
41
|
-
return relevantDocs.reduce((acc, doc) => {
|
|
42
|
-
if (doc) {
|
|
43
|
-
acc.push(new Document({
|
|
44
|
-
pageContent: doc.content,
|
|
45
|
-
id: doc.id,
|
|
46
|
-
metadata: doc.metadata,
|
|
47
|
-
}));
|
|
48
|
-
}
|
|
49
|
-
return acc;
|
|
50
|
-
}, []);
|
|
51
|
-
}
|
|
52
|
-
return docs.map((doc) => new Document({
|
|
53
|
-
pageContent: doc.content,
|
|
54
|
-
id: doc.id,
|
|
55
|
-
metadata: doc.metadata,
|
|
56
|
-
}));
|
|
57
|
-
}, {
|
|
58
|
-
name: 'retrieverTool',
|
|
59
|
-
description: 'Retrieves documents from the knowledge base based on the query',
|
|
60
|
-
schema,
|
|
61
|
-
});
|
|
62
|
-
//# sourceMappingURL=retriever-tool.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"retriever-tool.js","sourceRoot":"","sources":["../../../../src/ai/tools/retriever-tool/retriever-tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
const SELF_QUERY_RAG_PROMPT = `You are an advanced AI agent specializing in self-query Retrieval-Augmented Generation (RAG). Your primary function is to analyze client questions, generate optimized search queries for a knowledge base, and iteratively refine these queries based on initial results. Follow these comprehensive guidelines:
|
|
2
|
-
|
|
3
|
-
1. Initial Analysis:
|
|
4
|
-
- Thoroughly examine the client's question or task
|
|
5
|
-
- Identify key concepts, entities, relationships, and any implicit information needs
|
|
6
|
-
- Determine the scope, context, and potential complexities of the inquiry
|
|
7
|
-
|
|
8
|
-
2. Query Generation - First Pass:
|
|
9
|
-
- Create an initial set of 3-5 focused, non-redundant search queries
|
|
10
|
-
- Ensure each query addresses a unique aspect of the client's input
|
|
11
|
-
- Incorporate key terms from the original question for keyword optimization
|
|
12
|
-
- Vary query formulations to cover different potential phrasings and synonyms
|
|
13
|
-
|
|
14
|
-
3. Iterative Refinement:
|
|
15
|
-
- After receiving initial results, analyze their relevance and comprehensiveness
|
|
16
|
-
- Identify gaps in the retrieved information
|
|
17
|
-
- Generate additional queries to fill these gaps or explore new angles
|
|
18
|
-
- Refine existing queries based on the quality of results they produced
|
|
19
|
-
|
|
20
|
-
4. Query Diversification:
|
|
21
|
-
- Ensure a mix of query types:
|
|
22
|
-
a. Broad conceptual queries for general information
|
|
23
|
-
b. Specific detail-oriented queries for precise facts
|
|
24
|
-
c. Comparative queries to explore relationships between concepts
|
|
25
|
-
d. Contextual queries to gather background information
|
|
26
|
-
|
|
27
|
-
5. Handling Complex Questions:
|
|
28
|
-
- For multi-faceted questions, break them down into component parts
|
|
29
|
-
- Generate separate query sets for each component
|
|
30
|
-
- Create integrative queries that explore connections between components
|
|
31
|
-
|
|
32
|
-
6. Adapting to Query Results:
|
|
33
|
-
- If initial queries yield insufficient information, broaden the scope
|
|
34
|
-
- If results are too general, create more specific, targeted queries
|
|
35
|
-
- Adjust the vocabulary and technical level based on the knowledge base content
|
|
36
|
-
|
|
37
|
-
7. Temporal and Contextual Considerations:
|
|
38
|
-
- Include queries that account for potential time-sensitive information
|
|
39
|
-
- Generate queries that explore historical context if relevant
|
|
40
|
-
- Consider geographical or domain-specific variations in terminology
|
|
41
|
-
|
|
42
|
-
8. Output Format and Explanation:
|
|
43
|
-
- Present a numbered list of refined search queries
|
|
44
|
-
- For each query, provide:
|
|
45
|
-
a. The query itself
|
|
46
|
-
b. A brief explanation of its purpose and how it relates to the client's question
|
|
47
|
-
c. Any notable findings or gaps identified from previous iterations
|
|
48
|
-
|
|
49
|
-
9. Continuous Learning:
|
|
50
|
-
- Track the effectiveness of different query structures and patterns
|
|
51
|
-
- Adapt your query generation strategy based on successful retrievals
|
|
52
|
-
- Note any recurring challenges or limitations in the knowledge base
|
|
53
|
-
|
|
54
|
-
10. Final Review and Optimization:
|
|
55
|
-
- Ensure the final set of queries comprehensively covers the client's needs
|
|
56
|
-
- Eliminate any remaining redundancies or overly similar queries
|
|
57
|
-
- Prioritize queries based on their potential to provide the most relevant and valuable information
|
|
58
|
-
|
|
59
|
-
Remember: Your goal is to generate a dynamic, adaptive set of queries that evolves based on initial results and comprehensively addresses the client's information needs. Quality, relevance, and adaptability are key to successful self-query RAG implementation.`;
|
|
60
|
-
|
|
61
|
-
export { SELF_QUERY_RAG_PROMPT };
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { type VectorDBDataStore } from '@ixo/data-store';
|
|
2
|
-
import { Logger } from '@ixo/logger';
|
|
3
|
-
import { type Document } from '@langchain/core/documents';
|
|
4
|
-
import { type BaseMessage } from '@langchain/core/messages';
|
|
5
|
-
import { ChatPromptTemplate } from '@langchain/core/prompts';
|
|
6
|
-
import { type RunnableConfig } from '@langchain/core/runnables';
|
|
7
|
-
import 'dotenv/config';
|
|
8
|
-
import z from 'zod';
|
|
9
|
-
import {
|
|
10
|
-
getChatOpenAiModel,
|
|
11
|
-
retrieverToolFactory,
|
|
12
|
-
SELF_QUERY_RAG_PROMPT,
|
|
13
|
-
} from '../../index.js';
|
|
14
|
-
|
|
15
|
-
interface IFindDocsNodeRequiredState {
|
|
16
|
-
question: string;
|
|
17
|
-
docs: Document[];
|
|
18
|
-
messages?: BaseMessage[];
|
|
19
|
-
config?: {
|
|
20
|
-
isInternal: boolean;
|
|
21
|
-
};
|
|
22
|
-
status?: 'completed' | 'inProgress';
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* factory function that returns a Node that takes a state and config and returns a promise that resolves to a partial state.
|
|
27
|
-
* @param store - The vector database data store.
|
|
28
|
-
* @returns The Node that takes a state and config and returns a promise that resolves to a partial state.
|
|
29
|
-
*/
|
|
30
|
-
export const findDocsNode =
|
|
31
|
-
(store: VectorDBDataStore) =>
|
|
32
|
-
async (
|
|
33
|
-
state: IFindDocsNodeRequiredState,
|
|
34
|
-
config?: RunnableConfig,
|
|
35
|
-
): Promise<Partial<IFindDocsNodeRequiredState>> => {
|
|
36
|
-
try {
|
|
37
|
-
const model = getChatOpenAiModel();
|
|
38
|
-
const modelWithTools = model.withStructuredOutput(
|
|
39
|
-
z.object({
|
|
40
|
-
questions: z.array(z.string('Generated Queries')),
|
|
41
|
-
}),
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
const chain = ChatPromptTemplate.fromMessages([
|
|
45
|
-
['system', SELF_QUERY_RAG_PROMPT],
|
|
46
|
-
[
|
|
47
|
-
'user',
|
|
48
|
-
state.messages
|
|
49
|
-
? `this is the last three messages from the user's conversation ${state.messages
|
|
50
|
-
.map((message) => message.content)
|
|
51
|
-
.slice(-3)
|
|
52
|
-
.join(',')}`
|
|
53
|
-
: state.question,
|
|
54
|
-
],
|
|
55
|
-
]).pipe(modelWithTools);
|
|
56
|
-
|
|
57
|
-
const response = await chain.invoke({}, config);
|
|
58
|
-
const retrieval = retrieverToolFactory({
|
|
59
|
-
filters: state.config?.isInternal
|
|
60
|
-
? undefined
|
|
61
|
-
: { approved: true, visibility: 'public' },
|
|
62
|
-
store,
|
|
63
|
-
});
|
|
64
|
-
const docs = await Promise.all(
|
|
65
|
-
response.questions.map(
|
|
66
|
-
(question) =>
|
|
67
|
-
retrieval.invoke({ query: question }) as Promise<Document[]>,
|
|
68
|
-
),
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
return {
|
|
72
|
-
docs: docs.flat().map((value) => ({
|
|
73
|
-
metadata: value.metadata,
|
|
74
|
-
pageContent: value.pageContent.toString(),
|
|
75
|
-
id: value.id,
|
|
76
|
-
})),
|
|
77
|
-
status: undefined,
|
|
78
|
-
};
|
|
79
|
-
} catch (error) {
|
|
80
|
-
Logger.error('Error finding docs', error);
|
|
81
|
-
throw error;
|
|
82
|
-
}
|
|
83
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './retriever-tool.js';
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import { type VectorDBDataStore } from '@ixo/data-store';
|
|
2
|
-
import { Document } from '@langchain/core/documents';
|
|
3
|
-
import { FakeChatModel } from '@langchain/core/utils/testing';
|
|
4
|
-
import { retrieverToolFactory } from './retriever-tool.js';
|
|
5
|
-
|
|
6
|
-
const fakeModel = new FakeChatModel({});
|
|
7
|
-
|
|
8
|
-
// Mock the logger to prevent console output during tests
|
|
9
|
-
vi.mock('@ixo/logger', () => ({
|
|
10
|
-
Logger: {
|
|
11
|
-
error: vi.fn(),
|
|
12
|
-
},
|
|
13
|
-
}));
|
|
14
|
-
|
|
15
|
-
// Mock the OpenAI model
|
|
16
|
-
vi.mock('../../models/openai', () => ({
|
|
17
|
-
getChatOpenAiModel: () => fakeModel,
|
|
18
|
-
}));
|
|
19
|
-
|
|
20
|
-
// Mock the doc relevance checker
|
|
21
|
-
vi.mock('../../utils/doc-relevance-checker', () => ({
|
|
22
|
-
default: vi.fn().mockResolvedValue(true),
|
|
23
|
-
}));
|
|
24
|
-
const fakeDocRelevanceChecker = vi.fn().mockResolvedValue(true);
|
|
25
|
-
|
|
26
|
-
vi.spyOn(
|
|
27
|
-
await import('../../utils/doc-relevance-checker'),
|
|
28
|
-
'default',
|
|
29
|
-
).mockImplementation(fakeDocRelevanceChecker);
|
|
30
|
-
|
|
31
|
-
describe('RetrieverTool', () => {
|
|
32
|
-
let mockStore: { queryWithSimilarity: ReturnType<typeof vi.fn> };
|
|
33
|
-
const mockModel: FakeChatModel = new FakeChatModel({});
|
|
34
|
-
|
|
35
|
-
beforeEach(() => {
|
|
36
|
-
mockStore = {
|
|
37
|
-
queryWithSimilarity: vi.fn(),
|
|
38
|
-
};
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('should retrieve documents with default settings', async () => {
|
|
42
|
-
const mockDocs = [
|
|
43
|
-
{ id: '1', content: 'test content 1', metadata: { source: 'test1' } },
|
|
44
|
-
{ id: '2', content: 'test content 2', metadata: { source: 'test2' } },
|
|
45
|
-
];
|
|
46
|
-
|
|
47
|
-
mockStore.queryWithSimilarity.mockResolvedValue(mockDocs);
|
|
48
|
-
|
|
49
|
-
const tool = retrieverToolFactory({
|
|
50
|
-
store: mockStore as unknown as VectorDBDataStore,
|
|
51
|
-
});
|
|
52
|
-
const result = (await tool.invoke({ query: 'test query' })) as Document[];
|
|
53
|
-
|
|
54
|
-
expect(mockStore.queryWithSimilarity).toHaveBeenCalledWith('test query', {
|
|
55
|
-
similarityThreshold: 0.3,
|
|
56
|
-
filters: undefined,
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
expect(result).toHaveLength(2);
|
|
60
|
-
expect(result[0]).toBeInstanceOf(Document);
|
|
61
|
-
expect(result[0]?.pageContent).toBe('test content 1');
|
|
62
|
-
expect(result[0]?.metadata).toEqual({ source: 'test1' });
|
|
63
|
-
|
|
64
|
-
expect(fakeDocRelevanceChecker).toHaveBeenCalledWith({
|
|
65
|
-
doc: result[0],
|
|
66
|
-
query: 'test query',
|
|
67
|
-
model: fakeModel,
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('should store results in provided map', async () => {
|
|
72
|
-
const mockDocs = [
|
|
73
|
-
{ id: '1', content: 'test content', metadata: { source: 'test' } },
|
|
74
|
-
];
|
|
75
|
-
mockStore.queryWithSimilarity.mockResolvedValue(mockDocs);
|
|
76
|
-
|
|
77
|
-
const resultsMap = new Map();
|
|
78
|
-
const requestId = 'test-request-id';
|
|
79
|
-
|
|
80
|
-
const tool = retrieverToolFactory({
|
|
81
|
-
store: mockStore as unknown as VectorDBDataStore,
|
|
82
|
-
map: resultsMap,
|
|
83
|
-
requestId,
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
await tool.invoke({ query: 'test query' });
|
|
87
|
-
|
|
88
|
-
expect(resultsMap.get(requestId)).toEqual([{ source: 'test' }]);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it('should return undefined when no documents found', async () => {
|
|
92
|
-
mockStore.queryWithSimilarity.mockResolvedValue([]);
|
|
93
|
-
|
|
94
|
-
const tool = retrieverToolFactory({
|
|
95
|
-
store: mockStore as unknown as VectorDBDataStore,
|
|
96
|
-
});
|
|
97
|
-
const result = await tool.invoke({ query: 'test query' });
|
|
98
|
-
|
|
99
|
-
expect(result).toBeUndefined();
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it('should check document relevance when similarity threshold is higher', async () => {
|
|
103
|
-
const mockDocs = [
|
|
104
|
-
{ id: '1', content: 'test content', metadata: { source: 'test' } },
|
|
105
|
-
];
|
|
106
|
-
mockStore.queryWithSimilarity.mockResolvedValue(mockDocs);
|
|
107
|
-
|
|
108
|
-
const tool = retrieverToolFactory({
|
|
109
|
-
store: mockStore as unknown as VectorDBDataStore,
|
|
110
|
-
similarThreshold: 0.5,
|
|
111
|
-
model: mockModel,
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
const result = await tool.invoke({ query: 'test query' });
|
|
115
|
-
|
|
116
|
-
expect(result).toHaveLength(1);
|
|
117
|
-
expect(result[0]).toBeInstanceOf(Document);
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
it('should handle errors during relevance checking', async () => {
|
|
121
|
-
const mockDocs = [
|
|
122
|
-
{ id: '1', content: 'test content', metadata: { source: 'test' } },
|
|
123
|
-
];
|
|
124
|
-
mockStore.queryWithSimilarity.mockResolvedValue(mockDocs);
|
|
125
|
-
|
|
126
|
-
// Mock the relevance checker to throw an error
|
|
127
|
-
const docRelevanceModule = await import(
|
|
128
|
-
'../../utils/doc-relevance-checker'
|
|
129
|
-
);
|
|
130
|
-
(
|
|
131
|
-
docRelevanceModule.default as ReturnType<typeof vi.fn>
|
|
132
|
-
).mockRejectedValueOnce(new Error('Test error'));
|
|
133
|
-
|
|
134
|
-
const tool = retrieverToolFactory({
|
|
135
|
-
store: mockStore as unknown as VectorDBDataStore,
|
|
136
|
-
similarThreshold: 0.5,
|
|
137
|
-
model: mockModel,
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
const result = await tool.invoke({ query: 'test query' });
|
|
141
|
-
|
|
142
|
-
expect(result).toHaveLength(0);
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
it('should apply filters when provided', async () => {
|
|
146
|
-
const mockDocs = [
|
|
147
|
-
{ id: '1', content: 'test content', metadata: { source: 'test' } },
|
|
148
|
-
];
|
|
149
|
-
mockStore.queryWithSimilarity.mockResolvedValue(mockDocs);
|
|
150
|
-
const filters = { category: 'test' };
|
|
151
|
-
const tool = retrieverToolFactory({
|
|
152
|
-
store: mockStore as unknown as VectorDBDataStore,
|
|
153
|
-
filters,
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
await tool.invoke({ query: 'test query' });
|
|
157
|
-
|
|
158
|
-
expect(mockStore.queryWithSimilarity).toHaveBeenCalledWith('test query', {
|
|
159
|
-
similarityThreshold: 0.3,
|
|
160
|
-
filters,
|
|
161
|
-
});
|
|
162
|
-
});
|
|
163
|
-
});
|