@ixo/common 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +9 -0
- package/.prettierignore +3 -0
- package/.prettierrc.cjs +4 -0
- package/.turbo/turbo-build.log +4 -0
- package/CHANGELOG.md +76 -0
- package/README.md +245 -0
- package/dist/ai/checkpointer/index.d.ts +2 -0
- package/dist/ai/checkpointer/index.d.ts.map +1 -0
- package/dist/ai/checkpointer/index.js +2 -0
- package/dist/ai/checkpointer/index.js.map +1 -0
- package/dist/ai/index.d.ts +9 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +9 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/models/index.d.ts +2 -0
- package/dist/ai/models/index.d.ts.map +1 -0
- package/dist/ai/models/index.js +2 -0
- package/dist/ai/models/index.js.map +1 -0
- package/dist/ai/models/openai.d.ts +10 -0
- package/dist/ai/models/openai.d.ts.map +1 -0
- package/dist/ai/models/openai.js +38 -0
- package/dist/ai/models/openai.js.map +1 -0
- package/dist/ai/models/openai.test.d.ts +2 -0
- package/dist/ai/models/openai.test.d.ts.map +1 -0
- package/dist/ai/models/openai.test.js +58 -0
- package/dist/ai/models/openai.test.js.map +1 -0
- package/dist/ai/nodes/create-fake-node.d.ts +2 -0
- package/dist/ai/nodes/create-fake-node.d.ts.map +1 -0
- package/dist/ai/nodes/create-fake-node.js +2 -0
- package/dist/ai/nodes/create-fake-node.js.map +1 -0
- package/dist/ai/nodes/find-docs/find-docs.prompt.d.ts +3 -0
- package/dist/ai/nodes/find-docs/find-docs.prompt.d.ts.map +1 -0
- package/dist/ai/nodes/find-docs/find-docs.prompt.js +61 -0
- package/dist/ai/nodes/find-docs/find-docs.prompt.js.map +1 -0
- package/dist/ai/nodes/find-docs/index.d.ts +3 -0
- package/dist/ai/nodes/find-docs/index.d.ts.map +1 -0
- package/dist/ai/nodes/find-docs/index.js +3 -0
- package/dist/ai/nodes/find-docs/index.js.map +1 -0
- package/dist/ai/nodes/find-docs/node.d.ts +17 -0
- package/dist/ai/nodes/find-docs/node.d.ts.map +1 -0
- package/dist/ai/nodes/find-docs/node.js +46 -0
- package/dist/ai/nodes/find-docs/node.js.map +1 -0
- package/dist/ai/nodes/generic-chat/generic-chat.node.d.ts +12 -0
- package/dist/ai/nodes/generic-chat/generic-chat.node.d.ts.map +1 -0
- package/dist/ai/nodes/generic-chat/generic-chat.node.js +34 -0
- package/dist/ai/nodes/generic-chat/generic-chat.node.js.map +1 -0
- package/dist/ai/nodes/generic-chat/generic-chat.prompt.d.ts +10 -0
- package/dist/ai/nodes/generic-chat/generic-chat.prompt.d.ts.map +1 -0
- package/dist/ai/nodes/generic-chat/generic-chat.prompt.js +58 -0
- package/dist/ai/nodes/generic-chat/generic-chat.prompt.js.map +1 -0
- package/dist/ai/nodes/generic-chat/index.d.ts +2 -0
- package/dist/ai/nodes/generic-chat/index.d.ts.map +1 -0
- package/dist/ai/nodes/generic-chat/index.js +2 -0
- package/dist/ai/nodes/generic-chat/index.js.map +1 -0
- package/dist/ai/nodes/index.d.ts +4 -0
- package/dist/ai/nodes/index.d.ts.map +1 -0
- package/dist/ai/nodes/index.js +4 -0
- package/dist/ai/nodes/index.js.map +1 -0
- package/dist/ai/semantic-router-factory/create-semantic-router.d.ts +7 -0
- package/dist/ai/semantic-router-factory/create-semantic-router.d.ts.map +1 -0
- package/dist/ai/semantic-router-factory/create-semantic-router.js +71 -0
- package/dist/ai/semantic-router-factory/create-semantic-router.js.map +1 -0
- package/dist/ai/semantic-router-factory/create-semantic-router.test.d.ts +2 -0
- package/dist/ai/semantic-router-factory/create-semantic-router.test.d.ts.map +1 -0
- package/dist/ai/semantic-router-factory/create-semantic-router.test.js +68 -0
- package/dist/ai/semantic-router-factory/create-semantic-router.test.js.map +1 -0
- package/dist/ai/semantic-router-factory/index.d.ts +4 -0
- package/dist/ai/semantic-router-factory/index.d.ts.map +1 -0
- package/dist/ai/semantic-router-factory/index.js +4 -0
- package/dist/ai/semantic-router-factory/index.js.map +1 -0
- package/dist/ai/semantic-router-factory/semantic-router-prompt.d.ts +2 -0
- package/dist/ai/semantic-router-factory/semantic-router-prompt.d.ts.map +1 -0
- package/dist/ai/semantic-router-factory/semantic-router-prompt.js +169 -0
- package/dist/ai/semantic-router-factory/semantic-router-prompt.js.map +1 -0
- package/dist/ai/semantic-router-factory/validate-routes.d.ts +2 -0
- package/dist/ai/semantic-router-factory/validate-routes.d.ts.map +1 -0
- package/dist/ai/semantic-router-factory/validate-routes.js +16 -0
- package/dist/ai/semantic-router-factory/validate-routes.js.map +1 -0
- package/dist/ai/tools/action-caller.d.ts +14 -0
- package/dist/ai/tools/action-caller.d.ts.map +1 -0
- package/dist/ai/tools/action-caller.js +12 -0
- package/dist/ai/tools/action-caller.js.map +1 -0
- package/dist/ai/tools/ask-ixo-guru/ask-ixo-guru.d.ts +25 -0
- package/dist/ai/tools/ask-ixo-guru/ask-ixo-guru.d.ts.map +1 -0
- package/dist/ai/tools/ask-ixo-guru/ask-ixo-guru.js +46 -0
- package/dist/ai/tools/ask-ixo-guru/ask-ixo-guru.js.map +1 -0
- package/dist/ai/tools/ask-ixo-guru/index.d.ts +2 -0
- package/dist/ai/tools/ask-ixo-guru/index.d.ts.map +1 -0
- package/dist/ai/tools/ask-ixo-guru/index.js +2 -0
- package/dist/ai/tools/ask-ixo-guru/index.js.map +1 -0
- package/dist/ai/tools/browser-tool-caller.d.ts +14 -0
- package/dist/ai/tools/browser-tool-caller.d.ts.map +1 -0
- package/dist/ai/tools/browser-tool-caller.js +12 -0
- package/dist/ai/tools/browser-tool-caller.js.map +1 -0
- package/dist/ai/tools/frontend-tool-caller.d.ts +10 -0
- package/dist/ai/tools/frontend-tool-caller.d.ts.map +1 -0
- package/dist/ai/tools/frontend-tool-caller.js +50 -0
- package/dist/ai/tools/frontend-tool-caller.js.map +1 -0
- package/dist/ai/tools/index.d.ts +11 -0
- package/dist/ai/tools/index.d.ts.map +1 -0
- package/dist/ai/tools/index.js +11 -0
- package/dist/ai/tools/index.js.map +1 -0
- package/dist/ai/tools/log-action-to-matrix.d.ts +13 -0
- package/dist/ai/tools/log-action-to-matrix.d.ts.map +1 -0
- package/dist/ai/tools/log-action-to-matrix.js +14 -0
- package/dist/ai/tools/log-action-to-matrix.js.map +1 -0
- package/dist/ai/tools/parser-action-tool.d.ts +8 -0
- package/dist/ai/tools/parser-action-tool.d.ts.map +1 -0
- package/dist/ai/tools/parser-action-tool.js +40 -0
- package/dist/ai/tools/parser-action-tool.js.map +1 -0
- package/dist/ai/tools/parser-browser-tool.d.ts +8 -0
- package/dist/ai/tools/parser-browser-tool.d.ts.map +1 -0
- package/dist/ai/tools/parser-browser-tool.js +38 -0
- package/dist/ai/tools/parser-browser-tool.js.map +1 -0
- package/dist/ai/tools/retriever-tool/index.d.ts +2 -0
- package/dist/ai/tools/retriever-tool/index.d.ts.map +1 -0
- package/dist/ai/tools/retriever-tool/index.js +2 -0
- package/dist/ai/tools/retriever-tool/index.js.map +1 -0
- package/dist/ai/tools/retriever-tool/retriever-tool.d.ts +18 -0
- package/dist/ai/tools/retriever-tool/retriever-tool.d.ts.map +1 -0
- package/dist/ai/tools/retriever-tool/retriever-tool.js +62 -0
- package/dist/ai/tools/retriever-tool/retriever-tool.js.map +1 -0
- package/dist/ai/tools/retriever-tool/retriever-tool.test.d.ts +2 -0
- package/dist/ai/tools/retriever-tool/retriever-tool.test.d.ts.map +1 -0
- package/dist/ai/tools/retriever-tool/retriever-tool.test.js +119 -0
- package/dist/ai/tools/retriever-tool/retriever-tool.test.js.map +1 -0
- package/dist/ai/tools/scrape-web-page.d.ts +7 -0
- package/dist/ai/tools/scrape-web-page.d.ts.map +1 -0
- package/dist/ai/tools/scrape-web-page.js +65 -0
- package/dist/ai/tools/scrape-web-page.js.map +1 -0
- package/dist/ai/tools/web-search-tool.d.ts +10 -0
- package/dist/ai/tools/web-search-tool.d.ts.map +1 -0
- package/dist/ai/tools/web-search-tool.js +30 -0
- package/dist/ai/tools/web-search-tool.js.map +1 -0
- package/dist/ai/types.d.ts +4 -0
- package/dist/ai/types.d.ts.map +1 -0
- package/dist/ai/types.js +2 -0
- package/dist/ai/types.js.map +1 -0
- package/dist/ai/utils/__tests__/chunk-arr.test.d.ts +2 -0
- package/dist/ai/utils/__tests__/chunk-arr.test.d.ts.map +1 -0
- package/dist/ai/utils/__tests__/chunk-arr.test.js +37 -0
- package/dist/ai/utils/__tests__/chunk-arr.test.js.map +1 -0
- package/dist/ai/utils/__tests__/doc-relevance-checker.test.d.ts +2 -0
- package/dist/ai/utils/__tests__/doc-relevance-checker.test.d.ts.map +1 -0
- package/dist/ai/utils/__tests__/doc-relevance-checker.test.js +80 -0
- package/dist/ai/utils/__tests__/doc-relevance-checker.test.js.map +1 -0
- package/dist/ai/utils/__tests__/doc-splitter.test.d.ts +2 -0
- package/dist/ai/utils/__tests__/doc-splitter.test.d.ts.map +1 -0
- package/dist/ai/utils/__tests__/doc-splitter.test.js +35 -0
- package/dist/ai/utils/__tests__/doc-splitter.test.js.map +1 -0
- package/dist/ai/utils/__tests__/filter-similarity-search-results.test.d.ts +2 -0
- package/dist/ai/utils/__tests__/filter-similarity-search-results.test.d.ts.map +1 -0
- package/dist/ai/utils/__tests__/filter-similarity-search-results.test.js +47 -0
- package/dist/ai/utils/__tests__/filter-similarity-search-results.test.js.map +1 -0
- package/dist/ai/utils/__tests__/json-to-yaml.test.d.ts +2 -0
- package/dist/ai/utils/__tests__/json-to-yaml.test.d.ts.map +1 -0
- package/dist/ai/utils/__tests__/json-to-yaml.test.js +63 -0
- package/dist/ai/utils/__tests__/json-to-yaml.test.js.map +1 -0
- package/dist/ai/utils/__tests__/stringify-docs.test.d.ts +2 -0
- package/dist/ai/utils/__tests__/stringify-docs.test.d.ts.map +1 -0
- package/dist/ai/utils/__tests__/stringify-docs.test.js +54 -0
- package/dist/ai/utils/__tests__/stringify-docs.test.js.map +1 -0
- package/dist/ai/utils/chunk-arr.d.ts +3 -0
- package/dist/ai/utils/chunk-arr.d.ts.map +1 -0
- package/dist/ai/utils/chunk-arr.js +13 -0
- package/dist/ai/utils/chunk-arr.js.map +1 -0
- package/dist/ai/utils/doc-relevance-checker.d.ts +10 -0
- package/dist/ai/utils/doc-relevance-checker.d.ts.map +1 -0
- package/dist/ai/utils/doc-relevance-checker.js +37 -0
- package/dist/ai/utils/doc-relevance-checker.js.map +1 -0
- package/dist/ai/utils/doc-splitter.d.ts +3 -0
- package/dist/ai/utils/doc-splitter.d.ts.map +1 -0
- package/dist/ai/utils/doc-splitter.js +20 -0
- package/dist/ai/utils/doc-splitter.js.map +1 -0
- package/dist/ai/utils/filter-similarity-search-results.d.ts +4 -0
- package/dist/ai/utils/filter-similarity-search-results.d.ts.map +1 -0
- package/dist/ai/utils/filter-similarity-search-results.js +11 -0
- package/dist/ai/utils/filter-similarity-search-results.js.map +1 -0
- package/dist/ai/utils/generate-questions-from-chunks.d.ts +15 -0
- package/dist/ai/utils/generate-questions-from-chunks.d.ts.map +1 -0
- package/dist/ai/utils/generate-questions-from-chunks.js +101 -0
- package/dist/ai/utils/generate-questions-from-chunks.js.map +1 -0
- package/dist/ai/utils/index.d.ts +11 -0
- package/dist/ai/utils/index.d.ts.map +1 -0
- package/dist/ai/utils/index.js +11 -0
- package/dist/ai/utils/index.js.map +1 -0
- package/dist/ai/utils/json-to-yaml.d.ts +2 -0
- package/dist/ai/utils/json-to-yaml.d.ts.map +1 -0
- package/dist/ai/utils/json-to-yaml.js +25 -0
- package/dist/ai/utils/json-to-yaml.js.map +1 -0
- package/dist/ai/utils/load-file.d.ts +3 -0
- package/dist/ai/utils/load-file.d.ts.map +1 -0
- package/dist/ai/utils/load-file.js +133 -0
- package/dist/ai/utils/load-file.js.map +1 -0
- package/dist/ai/utils/stringify-docs.d.ts +3 -0
- package/dist/ai/utils/stringify-docs.d.ts.map +1 -0
- package/dist/ai/utils/stringify-docs.js +6 -0
- package/dist/ai/utils/stringify-docs.js.map +1 -0
- package/dist/ai/utils/transformGraphStateMessageToListMessageResponse.d.ts +35 -0
- package/dist/ai/utils/transformGraphStateMessageToListMessageResponse.d.ts.map +1 -0
- package/dist/ai/utils/transformGraphStateMessageToListMessageResponse.js +55 -0
- package/dist/ai/utils/transformGraphStateMessageToListMessageResponse.js.map +1 -0
- package/dist/ai/utils/verify-matrix-openId-token.d.ts +6 -0
- package/dist/ai/utils/verify-matrix-openId-token.d.ts.map +1 -0
- package/dist/ai/utils/verify-matrix-openId-token.js +36 -0
- package/dist/ai/utils/verify-matrix-openId-token.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/services/env/env-service.test.d.ts +2 -0
- package/dist/services/env/env-service.test.d.ts.map +1 -0
- package/dist/services/env/env-service.test.js +99 -0
- package/dist/services/env/env-service.test.js.map +1 -0
- package/dist/services/env/env.service.d.ts +11 -0
- package/dist/services/env/env.service.d.ts.map +1 -0
- package/dist/services/env/env.service.js +42 -0
- package/dist/services/env/env.service.js.map +1 -0
- package/dist/services/env/index.d.ts +2 -0
- package/dist/services/env/index.d.ts.map +1 -0
- package/dist/services/env/index.js +2 -0
- package/dist/services/env/index.js.map +1 -0
- package/dist/services/index.d.ts +5 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +5 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/memory-engine/memory-engine.service.d.ts +35 -0
- package/dist/services/memory-engine/memory-engine.service.d.ts.map +1 -0
- package/dist/services/memory-engine/memory-engine.service.js +295 -0
- package/dist/services/memory-engine/memory-engine.service.js.map +1 -0
- package/dist/services/memory-engine/types.d.ts +88 -0
- package/dist/services/memory-engine/types.d.ts.map +1 -0
- package/dist/services/memory-engine/types.js +2 -0
- package/dist/services/memory-engine/types.js.map +1 -0
- package/dist/services/session-manager/dto.d.ts +40 -0
- package/dist/services/session-manager/dto.d.ts.map +1 -0
- package/dist/services/session-manager/dto.js +170 -0
- package/dist/services/session-manager/dto.js.map +1 -0
- package/dist/services/session-manager/errors.d.ts +22 -0
- package/dist/services/session-manager/errors.d.ts.map +1 -0
- package/dist/services/session-manager/errors.js +41 -0
- package/dist/services/session-manager/errors.js.map +1 -0
- package/dist/services/session-manager/index.d.ts +4 -0
- package/dist/services/session-manager/index.d.ts.map +1 -0
- package/dist/services/session-manager/index.js +4 -0
- package/dist/services/session-manager/index.js.map +1 -0
- package/dist/services/session-manager/session-manager.service.d.ts +40 -0
- package/dist/services/session-manager/session-manager.service.d.ts.map +1 -0
- package/dist/services/session-manager/session-manager.service.js +251 -0
- package/dist/services/session-manager/session-manager.service.js.map +1 -0
- package/dist/utils/get-user-subscription.d.ts +21 -0
- package/dist/utils/get-user-subscription.d.ts.map +1 -0
- package/dist/utils/get-user-subscription.js +44 -0
- package/dist/utils/get-user-subscription.js.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -0
- package/docs/ai-module.md +84 -0
- package/docs/services.md +168 -0
- package/docs/tools.md +325 -0
- package/jest.config.js +6 -0
- package/package.json +81 -0
- package/src/ai/checkpointer/index.ts +1 -0
- package/src/ai/index.ts +8 -0
- package/src/ai/models/index.ts +1 -0
- package/src/ai/models/openai.test.ts +72 -0
- package/src/ai/models/openai.ts +54 -0
- package/src/ai/nodes/create-fake-node.ts +1 -0
- package/src/ai/nodes/find-docs/find-docs.prompt.ts +61 -0
- package/src/ai/nodes/find-docs/index.ts +2 -0
- package/src/ai/nodes/find-docs/node.ts +83 -0
- package/src/ai/nodes/generic-chat/generic-chat.node.ts +58 -0
- package/src/ai/nodes/generic-chat/generic-chat.prompt.ts +66 -0
- package/src/ai/nodes/generic-chat/index.ts +1 -0
- package/src/ai/nodes/index.ts +3 -0
- package/src/ai/semantic-router-factory/create-semantic-router.test.ts +98 -0
- package/src/ai/semantic-router-factory/create-semantic-router.ts +136 -0
- package/src/ai/semantic-router-factory/index.ts +3 -0
- package/src/ai/semantic-router-factory/semantic-router-prompt.ts +168 -0
- package/src/ai/semantic-router-factory/validate-routes.ts +26 -0
- package/src/ai/tools/action-caller.ts +37 -0
- package/src/ai/tools/ask-ixo-guru/ask-ixo-guru.ts +73 -0
- package/src/ai/tools/ask-ixo-guru/index.ts +1 -0
- package/src/ai/tools/browser-tool-caller.ts +37 -0
- package/src/ai/tools/frontend-tool-caller.ts +86 -0
- package/src/ai/tools/index.ts +10 -0
- package/src/ai/tools/log-action-to-matrix.ts +30 -0
- package/src/ai/tools/parser-action-tool.ts +61 -0
- package/src/ai/tools/parser-browser-tool.ts +55 -0
- package/src/ai/tools/retriever-tool/index.ts +1 -0
- package/src/ai/tools/retriever-tool/retriever-tool.test.ts +156 -0
- package/src/ai/tools/retriever-tool/retriever-tool.ts +107 -0
- package/src/ai/tools/scrape-web-page.ts +75 -0
- package/src/ai/tools/web-search-tool.ts +38 -0
- package/src/ai/types.ts +6 -0
- package/src/ai/utils/__tests__/chunk-arr.test.ts +46 -0
- package/src/ai/utils/__tests__/doc-relevance-checker.test.ts +90 -0
- package/src/ai/utils/__tests__/doc-splitter.test.ts +42 -0
- package/src/ai/utils/__tests__/filter-similarity-search-results.test.ts +57 -0
- package/src/ai/utils/__tests__/json-to-yaml.test.ts +70 -0
- package/src/ai/utils/__tests__/stringify-docs.test.ts +61 -0
- package/src/ai/utils/chunk-arr.ts +13 -0
- package/src/ai/utils/doc-relevance-checker.ts +58 -0
- package/src/ai/utils/doc-splitter.ts +28 -0
- package/src/ai/utils/filter-similarity-search-results.ts +15 -0
- package/src/ai/utils/generate-questions-from-chunks.ts +114 -0
- package/src/ai/utils/index.ts +10 -0
- package/src/ai/utils/json-to-yaml.ts +32 -0
- package/src/ai/utils/load-file.ts +170 -0
- package/src/ai/utils/stringify-docs.ts +14 -0
- package/src/ai/utils/transformGraphStateMessageToListMessageResponse.ts +108 -0
- package/src/ai/utils/verify-matrix-openId-token.ts +46 -0
- package/src/index.ts +3 -0
- package/src/services/env/env-service.test.ts +153 -0
- package/src/services/env/env.service.ts +65 -0
- package/src/services/env/index.ts +1 -0
- package/src/services/index.ts +4 -0
- package/src/services/memory-engine/memory-engine.service.ts +486 -0
- package/src/services/memory-engine/types.ts +208 -0
- package/src/services/session-manager/dto.ts +120 -0
- package/src/services/session-manager/errors.ts +56 -0
- package/src/services/session-manager/index.ts +3 -0
- package/src/services/session-manager/session-manager.service.ts +405 -0
- package/src/utils/get-user-subscription.ts +84 -0
- package/src/utils/index.ts +1 -0
- package/tsconfig.json +16 -0
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import 'dotenv/config';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
ChatOpenAI,
|
|
5
|
+
OpenAIEmbeddings,
|
|
6
|
+
type ChatOpenAIFields,
|
|
7
|
+
type ChatOpenAIResponseFormat,
|
|
8
|
+
} from '@langchain/openai';
|
|
9
|
+
import OpenAI, { type ClientOptions } from 'openai';
|
|
10
|
+
|
|
11
|
+
const getChatOpenAiModel = (params?: ChatOpenAIFields): ChatOpenAI =>
|
|
12
|
+
new ChatOpenAI({
|
|
13
|
+
temperature: 0.2,
|
|
14
|
+
model: 'gpt-4o-mini',
|
|
15
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
16
|
+
...params,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const getOpenAiClient = (params?: ClientOptions): OpenAI =>
|
|
20
|
+
new OpenAI({
|
|
21
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
22
|
+
...params,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const getOpenAiEmbeddings = (
|
|
26
|
+
params?: ConstructorParameters<typeof OpenAIEmbeddings>[0],
|
|
27
|
+
): OpenAIEmbeddings =>
|
|
28
|
+
new OpenAIEmbeddings({
|
|
29
|
+
model: 'text-embedding-3-small',
|
|
30
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
31
|
+
...params,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
export const getOpenRouterChatModel = (params?: ChatOpenAIFields) =>
|
|
35
|
+
getChatOpenAiModel({
|
|
36
|
+
temperature: 0.8,
|
|
37
|
+
apiKey: process.env.OPEN_ROUTER_API_KEY,
|
|
38
|
+
model: params?.model ?? 'qwen/qwen3-14b', //qwen3-30b-a3b
|
|
39
|
+
...params,
|
|
40
|
+
configuration: {
|
|
41
|
+
baseURL: 'https://openrouter.ai/api/v1',
|
|
42
|
+
...params?.configuration,
|
|
43
|
+
defaultHeaders: {
|
|
44
|
+
'HTTP-Referer': 'oracle-app.com',
|
|
45
|
+
'X-Title': process.env.ORACLE_NAME ?? 'Oracle App',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
modelKwargs: {
|
|
49
|
+
require_parameters: true,
|
|
50
|
+
...params?.modelKwargs,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
export { getChatOpenAiModel, getOpenAiClient, getOpenAiEmbeddings };
|
|
54
|
+
export type { ChatOpenAIResponseFormat };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const createFakeNode = <S extends object>(state: S): S => state;
|
|
@@ -0,0 +1,61 @@
|
|
|
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 };
|
|
@@ -0,0 +1,83 @@
|
|
|
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
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Logger } from '@ixo/logger';
|
|
2
|
+
import { BaseMessage } from '@langchain/core/messages';
|
|
3
|
+
import {
|
|
4
|
+
ChatPromptTemplate,
|
|
5
|
+
MessagesPlaceholder,
|
|
6
|
+
} from '@langchain/core/prompts';
|
|
7
|
+
import { RunnableConfig } from '@langchain/core/runnables';
|
|
8
|
+
import { StructuredTool, Tool } from '@langchain/core/tools';
|
|
9
|
+
import { getChatOpenAiModel } from 'src/ai/models/openai.js';
|
|
10
|
+
import { GENERIC_CHAT_PROMPT, InputVariables } from './generic-chat.prompt.js';
|
|
11
|
+
|
|
12
|
+
type StateWithMessages<S extends object> = {
|
|
13
|
+
messages: BaseMessage[];
|
|
14
|
+
} & S;
|
|
15
|
+
|
|
16
|
+
export const createGenericChatNode = (
|
|
17
|
+
inputVariables: InputVariables,
|
|
18
|
+
tools: (Tool | StructuredTool)[],
|
|
19
|
+
llm = getChatOpenAiModel(),
|
|
20
|
+
) => {
|
|
21
|
+
return async <S extends object>(
|
|
22
|
+
state: StateWithMessages<S>,
|
|
23
|
+
config?: RunnableConfig,
|
|
24
|
+
) => {
|
|
25
|
+
Logger.debug('Generic chat node called', {
|
|
26
|
+
state,
|
|
27
|
+
config,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
let systemPrompt = '';
|
|
31
|
+
try {
|
|
32
|
+
systemPrompt = await GENERIC_CHAT_PROMPT.format(inputVariables);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
Logger.error('Error formatting system prompt', error);
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const chain = ChatPromptTemplate.fromMessages([
|
|
39
|
+
['system', systemPrompt],
|
|
40
|
+
new MessagesPlaceholder('msgs'),
|
|
41
|
+
]).pipe(llm.bindTools(tools));
|
|
42
|
+
|
|
43
|
+
const result = await chain.invoke(
|
|
44
|
+
{
|
|
45
|
+
msgs: state.messages,
|
|
46
|
+
},
|
|
47
|
+
config,
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
Logger.debug('Generic chat node result', {
|
|
51
|
+
result,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
messages: [result],
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { PromptTemplate } from '@langchain/core/prompts';
|
|
2
|
+
|
|
3
|
+
export type InputVariables = {
|
|
4
|
+
APP_NAME: string;
|
|
5
|
+
APP_PURPOSE: string;
|
|
6
|
+
APP_MAIN_FEATURES: string;
|
|
7
|
+
APP_TARGET_USERS: string;
|
|
8
|
+
APP_UNIQUE_SELLING_POINTS: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const GENERIC_CHAT_PROMPT = new PromptTemplate<InputVariables, never>({
|
|
12
|
+
template: `# IXO AI Assistant: Expert Guide and Conversational Partner
|
|
13
|
+
|
|
14
|
+
## Your Identity
|
|
15
|
+
You are an AI assistant for the IXO Organization. Your primary role is to engage users in friendly, natural conversations, offering casual and informative chitchat. You can discuss various topics to keep conversations engaging and approachable.
|
|
16
|
+
|
|
17
|
+
Additionally, you have detailed knowledge about the app hosting you. Below is essential information about the hosting app that you can refer to when responding to user inquiries about it:
|
|
18
|
+
|
|
19
|
+
## App Information
|
|
20
|
+
### App Details
|
|
21
|
+
- **App Name**: {{APP_NAME}}
|
|
22
|
+
- **App Purpose**: {{APP_PURPOSE}}
|
|
23
|
+
- **Main Features**: {{APP_MAIN_FEATURES}}
|
|
24
|
+
- **Target Users**: {{APP_TARGET_USERS}}
|
|
25
|
+
- **Unique Selling Points**: {{APP_UNIQUE_SELLING_POINTS}}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
## Your Capabilities
|
|
29
|
+
- Provide detailed information about the IXO app and ecosystem
|
|
30
|
+
- Engage in natural, friendly conversation on various topics
|
|
31
|
+
- Explain complex concepts in accessible language
|
|
32
|
+
- Guide users through app features when they express interest
|
|
33
|
+
- Offer relevant suggestions based on user inquiries
|
|
34
|
+
|
|
35
|
+
## Communication Style
|
|
36
|
+
- **Tone**: Professional yet warm, conversational, and engaging
|
|
37
|
+
- **Language**: Clear, concise, and jargon-free unless requested
|
|
38
|
+
- **Personality**: Helpful, patient, and slightly enthusiastic
|
|
39
|
+
- **Responses**: Informative but concise, typically 2-4 sentences
|
|
40
|
+
|
|
41
|
+
## Interaction Guidelines
|
|
42
|
+
- Begin responses with direct answers to user questions
|
|
43
|
+
- When discussing app features, provide concrete examples of how they benefit users
|
|
44
|
+
- For complex topics, use analogies or step-by-step explanations
|
|
45
|
+
- If uncertain about a specific app detail, acknowledge this transparently
|
|
46
|
+
- Balance informative content with conversational elements
|
|
47
|
+
- Proactively suggest relevant app features when appropriate
|
|
48
|
+
- Personalize responses based on user's demonstrated knowledge level
|
|
49
|
+
|
|
50
|
+
## What to Avoid
|
|
51
|
+
- Making claims about app capabilities not listed in your knowledge base
|
|
52
|
+
- Using overly technical language with non-technical users
|
|
53
|
+
- Providing lengthy, overwhelming responses
|
|
54
|
+
- Making definitive statements about future IXO developments unless explicitly mentioned
|
|
55
|
+
- Sharing sensitive information about IXO's internal operations
|
|
56
|
+
|
|
57
|
+
Remember that your primary goal is to create a positive, informative experience that builds trust in the IXO platform while making users feel valued and understood.`,
|
|
58
|
+
inputVariables: [
|
|
59
|
+
'APP_NAME',
|
|
60
|
+
'APP_PURPOSE',
|
|
61
|
+
'APP_MAIN_FEATURES',
|
|
62
|
+
'APP_TARGET_USERS',
|
|
63
|
+
'APP_UNIQUE_SELLING_POINTS',
|
|
64
|
+
],
|
|
65
|
+
templateFormat: 'mustache',
|
|
66
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './generic-chat.node.js';
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { createSemanticRouter } from './create-semantic-router.js';
|
|
2
|
+
|
|
3
|
+
const parse = jest.fn();
|
|
4
|
+
const create = jest.fn();
|
|
5
|
+
jest.mock('openai', () => ({
|
|
6
|
+
OpenAI: jest.fn().mockImplementation(() => {
|
|
7
|
+
function fn(): unknown {
|
|
8
|
+
return {};
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
fn.beta = {
|
|
12
|
+
chat: {
|
|
13
|
+
completions: { parse },
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
fn.chat = {
|
|
18
|
+
completions: { create },
|
|
19
|
+
};
|
|
20
|
+
return fn;
|
|
21
|
+
}),
|
|
22
|
+
}));
|
|
23
|
+
|
|
24
|
+
describe('createSemanticRouter', () => {
|
|
25
|
+
it('should create a semantic router with valid routes', () => {
|
|
26
|
+
// const router = createSemanticRouter(
|
|
27
|
+
// {
|
|
28
|
+
// generateBlog: 'if the intent is blog',
|
|
29
|
+
// generateSocialMediaPost: 'if the intent is post',
|
|
30
|
+
// },
|
|
31
|
+
// ['intent'],
|
|
32
|
+
// );
|
|
33
|
+
expect(() =>
|
|
34
|
+
createSemanticRouter(
|
|
35
|
+
{
|
|
36
|
+
generateBlog: 'if the intent is blog',
|
|
37
|
+
generateSocialMediaPost: 'if the intent is post',
|
|
38
|
+
},
|
|
39
|
+
['intent'],
|
|
40
|
+
),
|
|
41
|
+
).not.toThrow();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should fail to create a semantic router with invalid routes', () => {
|
|
45
|
+
expect(() => createSemanticRouter({}, ['intent'])).toThrow();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should fail to get route with invalid state', async () => {
|
|
49
|
+
const router = createSemanticRouter(
|
|
50
|
+
{
|
|
51
|
+
generateBlog: 'if the intent is blog',
|
|
52
|
+
generateSocialMediaPost: 'if the intent is post',
|
|
53
|
+
},
|
|
54
|
+
['intent'],
|
|
55
|
+
);
|
|
56
|
+
await expect(
|
|
57
|
+
router({
|
|
58
|
+
foo: 'boo',
|
|
59
|
+
}),
|
|
60
|
+
).rejects.toThrow();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should get route with valid state', async () => {
|
|
64
|
+
const router = createSemanticRouter(
|
|
65
|
+
{
|
|
66
|
+
generateBlog: 'if the intent is blog',
|
|
67
|
+
generateSocialMediaPost: 'if the intent is post',
|
|
68
|
+
},
|
|
69
|
+
['intent'],
|
|
70
|
+
'gpt-4o-mini',
|
|
71
|
+
false,
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
parse.mockResolvedValue({
|
|
75
|
+
choices: [
|
|
76
|
+
{
|
|
77
|
+
message: {
|
|
78
|
+
parsed: {
|
|
79
|
+
nextRoute: 'generateBlog',
|
|
80
|
+
},
|
|
81
|
+
content: 'generateBlog',
|
|
82
|
+
role: 'assistant',
|
|
83
|
+
refusal: null,
|
|
84
|
+
tool_calls: [],
|
|
85
|
+
},
|
|
86
|
+
finish_reason: 'stop',
|
|
87
|
+
index: 0,
|
|
88
|
+
logprobs: null,
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
const route = await router({
|
|
94
|
+
intent: 'blog',
|
|
95
|
+
});
|
|
96
|
+
expect(route).toBe('generateBlog');
|
|
97
|
+
});
|
|
98
|
+
});
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { Logger } from '@ixo/logger';
|
|
2
|
+
import { PromptTemplate } from '@langchain/core/prompts';
|
|
3
|
+
import { LangfuseConfig, observeOpenAI } from 'langfuse';
|
|
4
|
+
import { OpenAI } from 'openai';
|
|
5
|
+
import { zodResponseFormat } from 'openai/helpers/zod';
|
|
6
|
+
import z from 'zod';
|
|
7
|
+
import { type EnsureKeys } from '../types.js';
|
|
8
|
+
import { jsonToYaml } from '../utils/index.js';
|
|
9
|
+
import { semanticRouterPrompt } from './semantic-router-prompt.js';
|
|
10
|
+
import { validateRoutes } from './validate-routes.js';
|
|
11
|
+
import { APIPromise } from 'openai/index.js';
|
|
12
|
+
import { ParsedChatCompletion } from 'openai/resources/chat/completions.mjs';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Creates a semantic router that resolves the path based on the given routes and basedOn value.
|
|
16
|
+
* routes The routes that will be used to resolve the path
|
|
17
|
+
* basedOn Array of keys from the state that will be used to resolve the path
|
|
18
|
+
* @returns A function that will be used to resolve the path
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* const routes = {
|
|
23
|
+
* generateBlog: 'if the intent is blog',
|
|
24
|
+
* generateSocialMediaPost: 'if the intent is post',
|
|
25
|
+
* }
|
|
26
|
+
*
|
|
27
|
+
* const intentRouter = createSemanticRouter(routes, ['intent']);
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export const createSemanticRouter = <
|
|
31
|
+
K extends string[],
|
|
32
|
+
R extends Record<string, string> = Record<string, string>,
|
|
33
|
+
>(
|
|
34
|
+
routes: R,
|
|
35
|
+
basedOn: K,
|
|
36
|
+
model:
|
|
37
|
+
| 'gpt-4o-mini'
|
|
38
|
+
| 'gpt-4o'
|
|
39
|
+
| 'gpt-4.1-nano'
|
|
40
|
+
| 'gpt-4.1-mini' = 'gpt-4.1-mini',
|
|
41
|
+
isComplex = false,
|
|
42
|
+
): ((
|
|
43
|
+
state: EnsureKeys<Record<string, unknown>, K>,
|
|
44
|
+
traceConfig?: LangfuseConfig,
|
|
45
|
+
) => Promise<keyof R>) => {
|
|
46
|
+
const keys = validateRoutes(routes, basedOn);
|
|
47
|
+
const schema = z.object({
|
|
48
|
+
nextRoute: z.enum(keys as [string, ...string[]], 'The routes that will be used to resolve the path'),
|
|
49
|
+
});
|
|
50
|
+
return async <T extends Record<string, unknown>>(
|
|
51
|
+
state: EnsureKeys<T, K>,
|
|
52
|
+
traceConfig?: LangfuseConfig,
|
|
53
|
+
): Promise<keyof R> => {
|
|
54
|
+
const selectedValues = {} as Record<string, string | object>;
|
|
55
|
+
for (const key of basedOn) {
|
|
56
|
+
const stateValue = state[key];
|
|
57
|
+
if (!stateValue) {
|
|
58
|
+
throw new Error(`The state must have a value for the key ${key}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
selectedValues[key] = stateValue;
|
|
62
|
+
}
|
|
63
|
+
if (Object.values(selectedValues).length === 0) {
|
|
64
|
+
throw new Error(
|
|
65
|
+
`The state must have a value for the key ${basedOn.toString()}`,
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// find the route that matches the state
|
|
70
|
+
const prompt = PromptTemplate.fromTemplate(semanticRouterPrompt);
|
|
71
|
+
|
|
72
|
+
const client = observeOpenAI(new OpenAI(), traceConfig);
|
|
73
|
+
const promptWithState = await prompt.format({
|
|
74
|
+
routes: jsonToYaml(routes),
|
|
75
|
+
state: jsonToYaml(selectedValues),
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const getRoute = async (
|
|
79
|
+
messages: (
|
|
80
|
+
| { role: 'system'; content: string }
|
|
81
|
+
| { role: 'user'; content: string }
|
|
82
|
+
)[],
|
|
83
|
+
): Promise<
|
|
84
|
+
APIPromise<
|
|
85
|
+
ParsedChatCompletion<{
|
|
86
|
+
nextRoute: string;
|
|
87
|
+
}>
|
|
88
|
+
>
|
|
89
|
+
> => {
|
|
90
|
+
if (model === 'gpt-4.1-nano' && isComplex) {
|
|
91
|
+
const { choices } = await client.chat.completions.create({
|
|
92
|
+
messages,
|
|
93
|
+
model,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const route = choices[0]?.message?.content?.toString();
|
|
97
|
+
Logger.debug('🚀 ~ route:', route);
|
|
98
|
+
return client.chat.completions.parse({
|
|
99
|
+
model,
|
|
100
|
+
messages,
|
|
101
|
+
response_format: zodResponseFormat(schema, 'routesResponse'),
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
return client.chat.completions.parse({
|
|
105
|
+
model,
|
|
106
|
+
messages,
|
|
107
|
+
response_format: zodResponseFormat(schema, 'routesResponse'),
|
|
108
|
+
});
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const completion = await getRoute([
|
|
112
|
+
{ role: 'system', content: promptWithState },
|
|
113
|
+
{
|
|
114
|
+
role: 'user',
|
|
115
|
+
content:
|
|
116
|
+
'Think and analyze the routes and messages then select the next route',
|
|
117
|
+
},
|
|
118
|
+
]);
|
|
119
|
+
const message = completion.choices[0]?.message;
|
|
120
|
+
|
|
121
|
+
if (message?.parsed) {
|
|
122
|
+
const nextRoute = message.parsed.nextRoute;
|
|
123
|
+
Logger.debug(
|
|
124
|
+
`🚀 ~ nextRoute: ${message.parsed.nextRoute.toString()}`,
|
|
125
|
+
message.parsed,
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
return nextRoute as keyof R;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
Logger.error('Error parsing the response from the semantic router');
|
|
132
|
+
throw new Error('Error parsing the response from the semantic router');
|
|
133
|
+
};
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
export { zodResponseFormat, type ParsedChatCompletion };
|