@equinor/fusion-framework-cli-plugin-ai-search 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +65 -0
- package/LICENSE +21 -0
- package/README.md +92 -0
- package/dist/esm/index.js +11 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/options/ai.js +152 -0
- package/dist/esm/options/ai.js.map +1 -0
- package/dist/esm/search.js +227 -0
- package/dist/esm/search.js.map +1 -0
- package/dist/esm/utils/setup-framework.js +53 -0
- package/dist/esm/utils/setup-framework.js.map +1 -0
- package/dist/esm/version.js +3 -0
- package/dist/esm/version.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/options/ai.d.ts +105 -0
- package/dist/types/search.d.ts +50 -0
- package/dist/types/utils/setup-framework.d.ts +10 -0
- package/dist/types/version.d.ts +1 -0
- package/package.json +58 -0
- package/src/index.ts +13 -0
- package/src/options/ai.ts +254 -0
- package/src/search.ts +284 -0
- package/src/utils/setup-framework.ts +75 -0
- package/src/version.ts +2 -0
- package/tsconfig.json +24 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# @equinor/fusion-framework-cli-plugin-ai-search
|
|
2
|
+
|
|
3
|
+
## 1.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- [`e2d2a76`](https://github.com/equinor/fusion-framework/commit/e2d2a76d08b86c3a9d8783fed1606551df9d5633) Thanks [@odinr](https://github.com/odinr)! - Add new AI search plugin package for vector store search capabilities.
|
|
8
|
+
|
|
9
|
+
This plugin extends the Fusion Framework CLI with semantic search functionality for querying vector store embeddings, enabling validation of indexed documents and retrieval of relevant content.
|
|
10
|
+
|
|
11
|
+
**Features:**
|
|
12
|
+
|
|
13
|
+
- Semantic search using vector embeddings
|
|
14
|
+
- Configurable result limits
|
|
15
|
+
- OData filter expressions for metadata-based filtering
|
|
16
|
+
- Multiple search types (similarity and MMR - Maximum Marginal Relevance)
|
|
17
|
+
- JSON output option for programmatic use
|
|
18
|
+
- Raw metadata output option
|
|
19
|
+
- Verbose output mode
|
|
20
|
+
|
|
21
|
+
**Quick Usage:**
|
|
22
|
+
|
|
23
|
+
1. Install the plugin:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
pnpm add -D @equinor/fusion-framework-cli-plugin-ai-search
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
2. Configure in `fusion-cli.config.ts`:
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import { defineFusionCli } from "@equinor/fusion-framework-cli";
|
|
33
|
+
|
|
34
|
+
export default defineFusionCli(() => ({
|
|
35
|
+
plugins: ["@equinor/fusion-framework-cli-plugin-ai-search"],
|
|
36
|
+
}));
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
3. Use the search command:
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
# Basic semantic search
|
|
43
|
+
ffc ai search "how to use the framework"
|
|
44
|
+
|
|
45
|
+
# Limit results and use MMR search
|
|
46
|
+
ffc ai search "authentication" --limit 5 --search-type mmr
|
|
47
|
+
|
|
48
|
+
# Filter by metadata
|
|
49
|
+
ffc ai search "typescript" --filter "metadata/source eq 'src/index.ts'"
|
|
50
|
+
|
|
51
|
+
# JSON output for programmatic use
|
|
52
|
+
ffc ai search "documentation" --json
|
|
53
|
+
|
|
54
|
+
# Raw metadata output
|
|
55
|
+
ffc ai search "API reference" --json --raw --verbose
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The plugin supports Azure OpenAI and Azure Cognitive Search configuration via command-line options or environment variables.
|
|
59
|
+
|
|
60
|
+
### Patch Changes
|
|
61
|
+
|
|
62
|
+
- Updated dependencies [[`e2d2a76`](https://github.com/equinor/fusion-framework/commit/e2d2a76d08b86c3a9d8783fed1606551df9d5633), [`e2d2a76`](https://github.com/equinor/fusion-framework/commit/e2d2a76d08b86c3a9d8783fed1606551df9d5633), [`e2d2a76`](https://github.com/equinor/fusion-framework/commit/e2d2a76d08b86c3a9d8783fed1606551df9d5633)]:
|
|
63
|
+
- @equinor/fusion-framework-cli-plugin-ai-base@1.0.0
|
|
64
|
+
- @equinor/fusion-framework-cli@13.0.0
|
|
65
|
+
- @equinor/fusion-framework-module-ai@2.0.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Equinor
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# @equinor/fusion-framework-cli-plugin-ai-search
|
|
2
|
+
|
|
3
|
+
AI search plugin for Fusion Framework CLI providing vector store search capabilities.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
pnpm add -D @equinor/fusion-framework-cli-plugin-ai-search
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Configuration
|
|
12
|
+
|
|
13
|
+
After installing the plugin, create a `fusion-cli.config.ts` file in your project root:
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { defineFusionCli } from '@equinor/fusion-framework-cli';
|
|
17
|
+
|
|
18
|
+
export default defineFusionCli(() => ({
|
|
19
|
+
plugins: [
|
|
20
|
+
'@equinor/fusion-framework-cli-plugin-ai-search',
|
|
21
|
+
],
|
|
22
|
+
}));
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The CLI will automatically discover and load plugins listed in this configuration file. The config file can be `.ts`, `.js`, or `.json`. The `defineFusionCli` helper provides type safety and IntelliSense support.
|
|
26
|
+
|
|
27
|
+
## Features
|
|
28
|
+
|
|
29
|
+
This plugin extends the Fusion Framework CLI with AI search capabilities:
|
|
30
|
+
|
|
31
|
+
- **Vector store search** for validating embeddings
|
|
32
|
+
- Semantic search using vector embeddings
|
|
33
|
+
- Configurable result limits
|
|
34
|
+
- Filter support for metadata-based filtering
|
|
35
|
+
- JSON output option for programmatic use
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
Once installed, the search command is automatically available:
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
# Search the vector store
|
|
43
|
+
ffc ai search "your query"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Commands
|
|
47
|
+
|
|
48
|
+
### `ai search`
|
|
49
|
+
|
|
50
|
+
Search the vector store to validate embeddings and retrieve relevant documents.
|
|
51
|
+
|
|
52
|
+
**Features:**
|
|
53
|
+
- Semantic search using vector embeddings
|
|
54
|
+
- Configurable result limits
|
|
55
|
+
- Filter support for metadata-based filtering
|
|
56
|
+
- JSON output option for programmatic use
|
|
57
|
+
- Detailed result display with scores and metadata
|
|
58
|
+
|
|
59
|
+
**Options:**
|
|
60
|
+
- `--limit <number>` - Maximum number of results to return (default: 10)
|
|
61
|
+
- `--search-type <type>` - Search type: 'mmr' or 'similarity' (default: similarity)
|
|
62
|
+
- `--filter <expression>` - OData filter expression for metadata filtering
|
|
63
|
+
- `--json` - Output results as JSON
|
|
64
|
+
- `--raw` - Output raw metadata without normalization
|
|
65
|
+
- `--verbose` - Enable verbose output
|
|
66
|
+
- `--openai-api-key <key>` - API key for Azure OpenAI
|
|
67
|
+
- `--openai-api-version <version>` - API version (default: 2024-02-15-preview)
|
|
68
|
+
- `--openai-instance <name>` - Azure OpenAI instance name
|
|
69
|
+
- `--openai-embedding-deployment <name>` - Azure OpenAI embedding deployment name
|
|
70
|
+
- `--azure-search-endpoint <url>` - Azure Search endpoint URL
|
|
71
|
+
- `--azure-search-api-key <key>` - Azure Search API key
|
|
72
|
+
- `--azure-search-index-name <name>` - Azure Search index name
|
|
73
|
+
|
|
74
|
+
**Examples:**
|
|
75
|
+
```sh
|
|
76
|
+
$ ffc ai search "how to use the framework"
|
|
77
|
+
$ ffc ai search "authentication" --limit 5
|
|
78
|
+
$ ffc ai search "typescript" --filter "metadata/source eq 'src/index.ts'"
|
|
79
|
+
$ ffc ai search "documentation" --search-type mmr
|
|
80
|
+
$ ffc ai search "documentation" --json
|
|
81
|
+
$ ffc ai search "documentation" --json --raw
|
|
82
|
+
$ ffc ai search "API reference" --verbose
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Configuration
|
|
86
|
+
|
|
87
|
+
The plugin requires Azure OpenAI and Azure Cognitive Search configuration. See the main CLI documentation for details on setting up API keys and endpoints.
|
|
88
|
+
|
|
89
|
+
## License
|
|
90
|
+
|
|
91
|
+
ISC
|
|
92
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { registerAiPlugin as registerAiPluginBase } from '@equinor/fusion-framework-cli-plugin-ai-base';
|
|
2
|
+
import { command as searchCommand } from './search.js';
|
|
3
|
+
/**
|
|
4
|
+
* Registers the AI search plugin command with the CLI program
|
|
5
|
+
* @param program - The Commander program instance to register commands with
|
|
6
|
+
*/
|
|
7
|
+
export function registerAiPlugin(program) {
|
|
8
|
+
registerAiPluginBase(program, searchCommand);
|
|
9
|
+
}
|
|
10
|
+
export default registerAiPlugin;
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,IAAI,oBAAoB,EAAE,MAAM,8CAA8C,CAAC;AACxG,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,aAAa,CAAC;AAEvD;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAC/C,oBAAoB,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;AAC/C,CAAC;AAED,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { createOption, InvalidOptionArgumentError } from 'commander';
|
|
2
|
+
/**
|
|
3
|
+
* Option for specifying the Azure OpenAI API key.
|
|
4
|
+
* Required for authentication with Azure OpenAI services.
|
|
5
|
+
*/
|
|
6
|
+
export const apiKeyOption = createOption('--openai-api-key <key>', 'API key for Azure OpenAI services').env('AZURE_OPENAI_API_KEY');
|
|
7
|
+
/**
|
|
8
|
+
* Option for specifying the Azure OpenAI API version.
|
|
9
|
+
* Defaults to the latest stable version if not provided.
|
|
10
|
+
*/
|
|
11
|
+
export const apiVersionOption = createOption('--openai-api-version <version>', 'Azure OpenAI API version')
|
|
12
|
+
.env('AZURE_OPENAI_API_VERSION')
|
|
13
|
+
.default('2024-02-15-preview');
|
|
14
|
+
/**
|
|
15
|
+
* Option for specifying the Azure OpenAI instance name.
|
|
16
|
+
* Required for Azure OpenAI service endpoint construction.
|
|
17
|
+
*/
|
|
18
|
+
export const apiInstanceOption = createOption('--openai-instance <name>', 'Azure OpenAI instance name').env('AZURE_OPENAI_INSTANCE_NAME');
|
|
19
|
+
/**
|
|
20
|
+
* Option for specifying the Azure OpenAI deployment name for chat models.
|
|
21
|
+
* Required for chat completions API calls.
|
|
22
|
+
*/
|
|
23
|
+
export const chatDeploymentOption = createOption('--openai-chat-deployment <name>', 'Azure OpenAI chat deployment name').env('AZURE_OPENAI_CHAT_DEPLOYMENT_NAME');
|
|
24
|
+
/**
|
|
25
|
+
* Option for specifying the Azure OpenAI deployment name for embedding models.
|
|
26
|
+
* Required for embeddings API calls.
|
|
27
|
+
*/
|
|
28
|
+
export const embeddingDeploymentOption = createOption('--openai-embedding-deployment <name>', 'Azure OpenAI embedding deployment name').env('AZURE_OPENAI_EMBEDDING_DEPLOYMENT_NAME');
|
|
29
|
+
/**
|
|
30
|
+
* Option for specifying the Azure Search endpoint URL.
|
|
31
|
+
* Required for Azure Cognitive Search operations.
|
|
32
|
+
*/
|
|
33
|
+
export const azureSearchEndpointOption = createOption('--azure-search-endpoint <url>', 'Azure Search endpoint URL').env('AZURE_SEARCH_ENDPOINT');
|
|
34
|
+
/**
|
|
35
|
+
* Option for specifying the Azure Search API key.
|
|
36
|
+
* Required for authentication with Azure Cognitive Search.
|
|
37
|
+
*/
|
|
38
|
+
export const azureSearchApiKeyOption = createOption('--azure-search-api-key <key>', 'Azure Search API key').env('AZURE_SEARCH_API_KEY');
|
|
39
|
+
/**
|
|
40
|
+
* Option for specifying the Azure Search index name.
|
|
41
|
+
* Required for search operations on a specific index.
|
|
42
|
+
*/
|
|
43
|
+
export const azureSearchIndexNameOption = createOption('--azure-search-index-name <name>', 'Azure Search index name').env('AZURE_SEARCH_INDEX_NAME');
|
|
44
|
+
/**
|
|
45
|
+
* Enhances a given command with AI-related options.
|
|
46
|
+
*
|
|
47
|
+
* This function adds the following options to the provided command:
|
|
48
|
+
* - `openaiApiKey`: Azure OpenAI API key
|
|
49
|
+
* - `openaiApiVersion`: Azure OpenAI API version
|
|
50
|
+
* - `openaiInstance`: Azure OpenAI instance name
|
|
51
|
+
* - `openaiChatDeployment`: Chat model deployment name
|
|
52
|
+
* - `openaiEmbeddingDeployment`: Embedding model deployment name (if includeEmbedding is true)
|
|
53
|
+
* - `azureSearchEndpoint`: Azure Search endpoint URL (if includeSearch is true)
|
|
54
|
+
* - `azureSearchApiKey`: Azure Search API key (if includeSearch is true)
|
|
55
|
+
* - `azureSearchIndexName`: Azure Search index name (if includeSearch is true)
|
|
56
|
+
*
|
|
57
|
+
* @param command - The command to which AI options will be added
|
|
58
|
+
* @param args - Optional configuration for which options to include
|
|
59
|
+
* @param args.includeEmbedding - Whether to include embedding deployment option
|
|
60
|
+
* @param args.includeChat - Whether to include chat deployment option (defaults to true)
|
|
61
|
+
* @param args.includeSearch - Whether to include Azure Search options (defaults to false)
|
|
62
|
+
* @returns The enhanced command with AI options
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* import { createCommand } from 'commander';
|
|
67
|
+
* import { withAiOptions } from './path/to/this/file';
|
|
68
|
+
*
|
|
69
|
+
* const command = withAiOptions(
|
|
70
|
+
* createCommand('ai-chat')
|
|
71
|
+
* .description('Chat with AI models')
|
|
72
|
+
* .action((options) => {
|
|
73
|
+
* console.log('API Key:', options.openaiApiKey);
|
|
74
|
+
* console.log('Instance:', options.openaiInstance);
|
|
75
|
+
* console.log('Chat Deployment:', options.openaiChatDeployment);
|
|
76
|
+
* })
|
|
77
|
+
* );
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export const withAiOptions = (command, args) => {
|
|
81
|
+
// Core authentication options
|
|
82
|
+
command.addOption(apiKeyOption);
|
|
83
|
+
command.addOption(apiVersionOption);
|
|
84
|
+
command.addOption(apiInstanceOption);
|
|
85
|
+
// Deployment options
|
|
86
|
+
if (args?.includeChat === true) {
|
|
87
|
+
command.addOption(chatDeploymentOption);
|
|
88
|
+
}
|
|
89
|
+
if (args?.includeEmbedding === true) {
|
|
90
|
+
command.addOption(embeddingDeploymentOption);
|
|
91
|
+
}
|
|
92
|
+
// Azure Search options
|
|
93
|
+
if (args?.includeSearch === true) {
|
|
94
|
+
command.addOption(azureSearchEndpointOption);
|
|
95
|
+
command.addOption(azureSearchApiKeyOption);
|
|
96
|
+
command.addOption(azureSearchIndexNameOption);
|
|
97
|
+
}
|
|
98
|
+
// Validation hook
|
|
99
|
+
command.hook('preAction', (thisCommand) => {
|
|
100
|
+
const options = thisCommand.opts();
|
|
101
|
+
// Validate API key
|
|
102
|
+
if (!options.openaiApiKey ||
|
|
103
|
+
typeof options.openaiApiKey !== 'string' ||
|
|
104
|
+
options.openaiApiKey.trim() === '') {
|
|
105
|
+
throw new InvalidOptionArgumentError('API key is required and must be a non-empty string.');
|
|
106
|
+
}
|
|
107
|
+
// Validate API version
|
|
108
|
+
if (!options.openaiApiVersion || typeof options.openaiApiVersion !== 'string') {
|
|
109
|
+
throw new InvalidOptionArgumentError('API version must be a non-empty string.');
|
|
110
|
+
}
|
|
111
|
+
// Validate instance name
|
|
112
|
+
if (!options.openaiInstance ||
|
|
113
|
+
typeof options.openaiInstance !== 'string' ||
|
|
114
|
+
options.openaiInstance.trim() === '') {
|
|
115
|
+
throw new InvalidOptionArgumentError('API instance name is required and must be a non-empty string.');
|
|
116
|
+
}
|
|
117
|
+
if (args?.includeChat === true) {
|
|
118
|
+
if (!options.openaiChatDeployment ||
|
|
119
|
+
typeof options.openaiChatDeployment !== 'string' ||
|
|
120
|
+
options.openaiChatDeployment.trim() === '') {
|
|
121
|
+
throw new InvalidOptionArgumentError('Chat deployment name is required and must be a non-empty string.');
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (args?.includeEmbedding === true) {
|
|
125
|
+
if (!options.openaiEmbeddingDeployment ||
|
|
126
|
+
typeof options.openaiEmbeddingDeployment !== 'string' ||
|
|
127
|
+
options.openaiEmbeddingDeployment.trim() === '') {
|
|
128
|
+
throw new InvalidOptionArgumentError('Embedding deployment name is required and must be a non-empty string.');
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (args?.includeSearch === true) {
|
|
132
|
+
if (!options.azureSearchEndpoint ||
|
|
133
|
+
typeof options.azureSearchEndpoint !== 'string' ||
|
|
134
|
+
options.azureSearchEndpoint.trim() === '') {
|
|
135
|
+
throw new InvalidOptionArgumentError('Azure Search endpoint is required and must be a non-empty string.');
|
|
136
|
+
}
|
|
137
|
+
if (!options.azureSearchApiKey ||
|
|
138
|
+
typeof options.azureSearchApiKey !== 'string' ||
|
|
139
|
+
options.azureSearchApiKey.trim() === '') {
|
|
140
|
+
throw new InvalidOptionArgumentError('Azure Search API key is required and must be a non-empty string.');
|
|
141
|
+
}
|
|
142
|
+
if (!options.azureSearchIndexName ||
|
|
143
|
+
typeof options.azureSearchIndexName !== 'string' ||
|
|
144
|
+
options.azureSearchIndexName.trim() === '') {
|
|
145
|
+
throw new InvalidOptionArgumentError('Azure Search index name is required and must be a non-empty string.');
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
return command;
|
|
150
|
+
};
|
|
151
|
+
export default withAiOptions;
|
|
152
|
+
//# sourceMappingURL=ai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai.js","sourceRoot":"","sources":["../../../src/options/ai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,YAAY,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAC;AAyBnF;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,YAAY,CACtC,wBAAwB,EACxB,mCAAmC,CACpC,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;AAE9B;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,YAAY,CAC1C,gCAAgC,EAChC,0BAA0B,CAC3B;KACE,GAAG,CAAC,0BAA0B,CAAC;KAC/B,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAEjC;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,YAAY,CAC3C,0BAA0B,EAC1B,4BAA4B,CAC7B,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;AAEpC;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,YAAY,CAC9C,iCAAiC,EACjC,mCAAmC,CACpC,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;AAE3C;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,YAAY,CACnD,sCAAsC,EACtC,wCAAwC,CACzC,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;AAEhD;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,YAAY,CACnD,+BAA+B,EAC/B,2BAA2B,CAC5B,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;AAE/B;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,YAAY,CACjD,8BAA8B,EAC9B,sBAAsB,CACvB,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;AAE9B;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,YAAY,CACpD,kCAAkC,EAClC,yBAAyB,CAC1B,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;AAEjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,OAAgB,EAChB,IAIE,EACO,EAAE;IACX,8BAA8B;IAC9B,OAAO,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;IAChC,OAAO,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IACpC,OAAO,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;IAErC,qBAAqB;IACrB,IAAI,IAAI,EAAE,WAAW,KAAK,IAAI,EAAE,CAAC;QAC/B,OAAO,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;IAC1C,CAAC;IAED,IAAI,IAAI,EAAE,gBAAgB,KAAK,IAAI,EAAE,CAAC;QACpC,OAAO,CAAC,SAAS,CAAC,yBAAyB,CAAC,CAAC;IAC/C,CAAC;IAED,uBAAuB;IACvB,IAAI,IAAI,EAAE,aAAa,KAAK,IAAI,EAAE,CAAC;QACjC,OAAO,CAAC,SAAS,CAAC,yBAAyB,CAAC,CAAC;QAC7C,OAAO,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;QAC3C,OAAO,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAC;IAChD,CAAC;IAED,kBAAkB;IAClB,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,WAAW,EAAE,EAAE;QACxC,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC;QAEnC,mBAAmB;QACnB,IACE,CAAC,OAAO,CAAC,YAAY;YACrB,OAAO,OAAO,CAAC,YAAY,KAAK,QAAQ;YACxC,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,EAClC,CAAC;YACD,MAAM,IAAI,0BAA0B,CAAC,qDAAqD,CAAC,CAAC;QAC9F,CAAC;QAED,uBAAuB;QACvB,IAAI,CAAC,OAAO,CAAC,gBAAgB,IAAI,OAAO,OAAO,CAAC,gBAAgB,KAAK,QAAQ,EAAE,CAAC;YAC9E,MAAM,IAAI,0BAA0B,CAAC,yCAAyC,CAAC,CAAC;QAClF,CAAC;QAED,yBAAyB;QACzB,IACE,CAAC,OAAO,CAAC,cAAc;YACvB,OAAO,OAAO,CAAC,cAAc,KAAK,QAAQ;YAC1C,OAAO,CAAC,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE,EACpC,CAAC;YACD,MAAM,IAAI,0BAA0B,CAClC,+DAA+D,CAChE,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,EAAE,WAAW,KAAK,IAAI,EAAE,CAAC;YAC/B,IACE,CAAC,OAAO,CAAC,oBAAoB;gBAC7B,OAAO,OAAO,CAAC,oBAAoB,KAAK,QAAQ;gBAChD,OAAO,CAAC,oBAAoB,CAAC,IAAI,EAAE,KAAK,EAAE,EAC1C,CAAC;gBACD,MAAM,IAAI,0BAA0B,CAClC,kEAAkE,CACnE,CAAC;YACJ,CAAC;QACH,CAAC;QAED,IAAI,IAAI,EAAE,gBAAgB,KAAK,IAAI,EAAE,CAAC;YACpC,IACE,CAAC,OAAO,CAAC,yBAAyB;gBAClC,OAAO,OAAO,CAAC,yBAAyB,KAAK,QAAQ;gBACrD,OAAO,CAAC,yBAAyB,CAAC,IAAI,EAAE,KAAK,EAAE,EAC/C,CAAC;gBACD,MAAM,IAAI,0BAA0B,CAClC,uEAAuE,CACxE,CAAC;YACJ,CAAC;QACH,CAAC;QAED,IAAI,IAAI,EAAE,aAAa,KAAK,IAAI,EAAE,CAAC;YACjC,IACE,CAAC,OAAO,CAAC,mBAAmB;gBAC5B,OAAO,OAAO,CAAC,mBAAmB,KAAK,QAAQ;gBAC/C,OAAO,CAAC,mBAAmB,CAAC,IAAI,EAAE,KAAK,EAAE,EACzC,CAAC;gBACD,MAAM,IAAI,0BAA0B,CAClC,mEAAmE,CACpE,CAAC;YACJ,CAAC;YAED,IACE,CAAC,OAAO,CAAC,iBAAiB;gBAC1B,OAAO,OAAO,CAAC,iBAAiB,KAAK,QAAQ;gBAC7C,OAAO,CAAC,iBAAiB,CAAC,IAAI,EAAE,KAAK,EAAE,EACvC,CAAC;gBACD,MAAM,IAAI,0BAA0B,CAClC,kEAAkE,CACnE,CAAC;YACJ,CAAC;YAED,IACE,CAAC,OAAO,CAAC,oBAAoB;gBAC7B,OAAO,OAAO,CAAC,oBAAoB,KAAK,QAAQ;gBAChD,OAAO,CAAC,oBAAoB,CAAC,IAAI,EAAE,KAAK,EAAE,EAC1C,CAAC;gBACD,MAAM,IAAI,0BAA0B,CAClC,qEAAqE,CACtE,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { createCommand, createOption } from 'commander';
|
|
2
|
+
import { withAiOptions } from './options/ai.js';
|
|
3
|
+
import { setupFramework } from './utils/setup-framework.js';
|
|
4
|
+
import { inspect } from 'node:util';
|
|
5
|
+
/**
|
|
6
|
+
* Normalizes metadata attributes from Azure Search format to a flat object
|
|
7
|
+
* Azure Search returns metadata attributes as an array of {key, value} pairs,
|
|
8
|
+
* which this function converts to a simple key-value object for easier access
|
|
9
|
+
* @param metadata - Raw metadata object that may contain attributes array
|
|
10
|
+
* @returns Normalized metadata with attributes flattened into the root object
|
|
11
|
+
*/
|
|
12
|
+
const normalizeMetadata = (metadata) => {
|
|
13
|
+
const normalized = { ...metadata };
|
|
14
|
+
// Azure Search returns attributes as an array of {key, value} pairs
|
|
15
|
+
// Convert this to a flat object structure for easier access
|
|
16
|
+
if (Array.isArray(normalized.attributes)) {
|
|
17
|
+
const attributesObj = {};
|
|
18
|
+
for (const attr of normalized.attributes) {
|
|
19
|
+
// Validate attribute structure before processing
|
|
20
|
+
if (typeof attr === 'object' &&
|
|
21
|
+
attr !== null &&
|
|
22
|
+
'key' in attr &&
|
|
23
|
+
'value' in attr &&
|
|
24
|
+
typeof attr.key === 'string') {
|
|
25
|
+
// Try to parse JSON values (Azure Search stores complex values as JSON strings)
|
|
26
|
+
// Fall back to raw value if parsing fails (for string values)
|
|
27
|
+
try {
|
|
28
|
+
attributesObj[attr.key] = JSON.parse(attr.value);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
attributesObj[attr.key] = attr.value;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// Merge flattened attributes into the root metadata object
|
|
36
|
+
Object.assign(normalized, attributesObj);
|
|
37
|
+
// Remove the original attributes array to avoid duplication
|
|
38
|
+
delete normalized.attributes;
|
|
39
|
+
}
|
|
40
|
+
return normalized;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* CLI command: `ai search`
|
|
44
|
+
*
|
|
45
|
+
* Search the vector store to validate embeddings and retrieve relevant documents.
|
|
46
|
+
*
|
|
47
|
+
* Features:
|
|
48
|
+
* - Semantic search using vector embeddings
|
|
49
|
+
* - Configurable result limits
|
|
50
|
+
* - Filter support for metadata-based filtering
|
|
51
|
+
* - JSON output option for programmatic use
|
|
52
|
+
* - Detailed result display with scores and metadata
|
|
53
|
+
*
|
|
54
|
+
* Usage:
|
|
55
|
+
* $ ffc ai search <query> [options]
|
|
56
|
+
*
|
|
57
|
+
* Options:
|
|
58
|
+
* --limit <number> Maximum number of results to return (default: 10)
|
|
59
|
+
* --search-type <type> Search type: 'mmr' or 'similarity' (default: similarity)
|
|
60
|
+
* --filter <expression> OData filter expression for metadata filtering
|
|
61
|
+
* --json Output results as JSON
|
|
62
|
+
* --raw Output raw metadata without normalization
|
|
63
|
+
* --verbose Enable verbose output
|
|
64
|
+
* --openai-api-key <key> API key for Azure OpenAI
|
|
65
|
+
* --openai-api-version <version> API version (default: 2024-02-15-preview)
|
|
66
|
+
* --openai-instance <name> Azure OpenAI instance name
|
|
67
|
+
* --openai-embedding-deployment <name> Azure OpenAI embedding deployment name
|
|
68
|
+
* --azure-search-endpoint <url> Azure Search endpoint URL
|
|
69
|
+
* --azure-search-api-key <key> Azure Search API key
|
|
70
|
+
* --azure-search-index-name <name> Azure Search index name
|
|
71
|
+
*
|
|
72
|
+
* Environment Variables:
|
|
73
|
+
* AZURE_OPENAI_API_KEY API key for Azure OpenAI
|
|
74
|
+
* AZURE_OPENAI_API_VERSION API version
|
|
75
|
+
* AZURE_OPENAI_INSTANCE_NAME Instance name
|
|
76
|
+
* AZURE_OPENAI_EMBEDDING_DEPLOYMENT_NAME Embedding deployment name
|
|
77
|
+
* AZURE_SEARCH_ENDPOINT Azure Search endpoint
|
|
78
|
+
* AZURE_SEARCH_API_KEY Azure Search API key
|
|
79
|
+
* AZURE_SEARCH_INDEX_NAME Azure Search index name
|
|
80
|
+
*
|
|
81
|
+
* Examples:
|
|
82
|
+
* $ ffc ai search "how to use the framework"
|
|
83
|
+
* $ ffc ai search "authentication" --limit 5
|
|
84
|
+
* $ ffc ai search "typescript" --filter "metadata/source eq 'src/index.ts'"
|
|
85
|
+
* $ ffc ai search "documentation" --search-type similarity
|
|
86
|
+
* $ ffc ai search "documentation" --json
|
|
87
|
+
* $ ffc ai search "documentation" --json --raw
|
|
88
|
+
* $ ffc ai search "API reference" --verbose
|
|
89
|
+
*/
|
|
90
|
+
export const command = withAiOptions(createCommand('search')
|
|
91
|
+
.description('Search the vector store to validate embeddings and retrieve relevant documents')
|
|
92
|
+
.addOption(createOption('--limit <number>', 'Maximum number of results to return')
|
|
93
|
+
.default(10)
|
|
94
|
+
.argParser(parseInt))
|
|
95
|
+
.addOption(createOption('--search-type <type>', 'Search type: mmr or similarity')
|
|
96
|
+
.choices(['mmr', 'similarity'])
|
|
97
|
+
.default('similarity'))
|
|
98
|
+
.addOption(createOption('--filter <expression>', 'OData filter expression for metadata filtering'))
|
|
99
|
+
.addOption(createOption('--json', 'Output results as JSON').default(false))
|
|
100
|
+
.addOption(createOption('--raw', 'Output raw metadata without normalization').default(false))
|
|
101
|
+
.addOption(createOption('--verbose', 'Enable verbose output').default(false))
|
|
102
|
+
.argument('<query>', 'Search query string')
|
|
103
|
+
.action(async (query, options) => {
|
|
104
|
+
if (options.verbose) {
|
|
105
|
+
console.log('🔍 Initializing framework...');
|
|
106
|
+
}
|
|
107
|
+
const framework = await setupFramework(options);
|
|
108
|
+
if (!options.azureSearchIndexName) {
|
|
109
|
+
throw new Error('Azure Search index name is required');
|
|
110
|
+
}
|
|
111
|
+
if (options.verbose) {
|
|
112
|
+
console.log('✅ Framework initialized successfully');
|
|
113
|
+
console.log(`🔎 Searching for: "${query}"`);
|
|
114
|
+
console.log(`📊 Limit: ${options.limit}`);
|
|
115
|
+
console.log(`🔍 Search type: ${options.searchType}`);
|
|
116
|
+
if (options.filter) {
|
|
117
|
+
console.log(`🔧 Filter: ${options.filter}`);
|
|
118
|
+
}
|
|
119
|
+
console.log('');
|
|
120
|
+
}
|
|
121
|
+
const vectorStoreService = framework.ai.getService('search', options.azureSearchIndexName);
|
|
122
|
+
try {
|
|
123
|
+
// Configure retriever options for semantic search
|
|
124
|
+
// The retriever provides more control over search parameters than direct vector store queries
|
|
125
|
+
// RetrieverOptions is a discriminated union, so we construct it based on search type
|
|
126
|
+
const filter = options.filter
|
|
127
|
+
? {
|
|
128
|
+
filterExpression: options.filter,
|
|
129
|
+
}
|
|
130
|
+
: undefined;
|
|
131
|
+
// Construct retriever options based on search type
|
|
132
|
+
// MMR search requires additional parameters for diversity optimization
|
|
133
|
+
// Similarity search doesn't need these parameters
|
|
134
|
+
const retrieverOptions = options.searchType === 'mmr'
|
|
135
|
+
? {
|
|
136
|
+
k: options.limit,
|
|
137
|
+
searchType: 'mmr',
|
|
138
|
+
...(filter && { filter: filter }),
|
|
139
|
+
}
|
|
140
|
+
: {
|
|
141
|
+
k: options.limit,
|
|
142
|
+
searchType: 'similarity',
|
|
143
|
+
...(filter && { filter: filter }),
|
|
144
|
+
};
|
|
145
|
+
// Create retriever and execute search query
|
|
146
|
+
const retriever = vectorStoreService.asRetriever(retrieverOptions);
|
|
147
|
+
const results = await retriever.invoke(query);
|
|
148
|
+
// Validate that results is an array
|
|
149
|
+
if (!results || !Array.isArray(results)) {
|
|
150
|
+
throw new Error(`Invalid search results: expected array but got ${results === null ? 'null' : typeof results}`);
|
|
151
|
+
}
|
|
152
|
+
if (options.json) {
|
|
153
|
+
// Output as JSON for programmatic use (e.g., piping to other tools)
|
|
154
|
+
for (const doc of results) {
|
|
155
|
+
if (options.raw) {
|
|
156
|
+
// Output raw document structure with full depth inspection
|
|
157
|
+
console.log(inspect(doc, { depth: null, colors: true }));
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
// Output normalized metadata for cleaner JSON structure
|
|
161
|
+
const metadata = normalizeMetadata(doc.metadata);
|
|
162
|
+
console.log({
|
|
163
|
+
content: doc.pageContent,
|
|
164
|
+
metadata,
|
|
165
|
+
score: metadata?.score,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
// Format results for human-readable output
|
|
172
|
+
if (results.length === 0) {
|
|
173
|
+
console.log('❌ No results found');
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
console.log(`✅ Found ${results.length} result${results.length !== 1 ? 's' : ''}:\n`);
|
|
177
|
+
results.forEach((doc, index) => {
|
|
178
|
+
// Normalize metadata to flatten attributes array unless --raw flag is set
|
|
179
|
+
// Raw mode preserves Azure Search's original metadata structure
|
|
180
|
+
const processedMetadata = options.raw
|
|
181
|
+
? doc.metadata
|
|
182
|
+
: normalizeMetadata(doc.metadata);
|
|
183
|
+
const metadata = processedMetadata;
|
|
184
|
+
const score = metadata.score;
|
|
185
|
+
const source = metadata.source || 'Unknown source';
|
|
186
|
+
// Display result header with score if available
|
|
187
|
+
console.log(`${'─'.repeat(80)}`);
|
|
188
|
+
console.log(`Result ${index + 1}${score !== undefined ? ` (Score: ${score.toFixed(4)})` : ''}`);
|
|
189
|
+
console.log(`Source: ${source}`);
|
|
190
|
+
// Display additional metadata fields if verbose mode is enabled
|
|
191
|
+
// Exclude source and score from additional metadata to avoid duplication
|
|
192
|
+
if (options.verbose) {
|
|
193
|
+
const { source: _, score: __, ...otherMetadata } = metadata;
|
|
194
|
+
if (Object.keys(otherMetadata).length > 0) {
|
|
195
|
+
console.log(`Metadata:`, JSON.stringify(otherMetadata, null, 2));
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
console.log('');
|
|
199
|
+
// Truncate content if too long to keep output readable
|
|
200
|
+
// Full content is still available in JSON mode
|
|
201
|
+
const content = doc.pageContent;
|
|
202
|
+
const maxLength = 500;
|
|
203
|
+
if (content.length > maxLength) {
|
|
204
|
+
console.log(`${content.substring(0, maxLength)}...`);
|
|
205
|
+
console.log(`\n[Content truncated - ${content.length} characters total]`);
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
console.log(content);
|
|
209
|
+
}
|
|
210
|
+
console.log('');
|
|
211
|
+
});
|
|
212
|
+
console.log(`${'─'.repeat(80)}`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
console.error(`❌ Search failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
217
|
+
if (options.verbose && error instanceof Error && error.stack) {
|
|
218
|
+
console.error(error.stack);
|
|
219
|
+
}
|
|
220
|
+
process.exit(1);
|
|
221
|
+
}
|
|
222
|
+
}), {
|
|
223
|
+
includeEmbedding: true,
|
|
224
|
+
includeSearch: true,
|
|
225
|
+
});
|
|
226
|
+
export default command;
|
|
227
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAExD,OAAO,EAAE,aAAa,EAAkB,MAAM,iBAAiB,CAAC;AAEhE,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqBpC;;;;;;GAMG;AACH,MAAM,iBAAiB,GAAG,CAAC,QAAiC,EAA2B,EAAE;IACvF,MAAM,UAAU,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;IAEnC,oEAAoE;IACpE,4DAA4D;IAC5D,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACzC,MAAM,aAAa,GAA4B,EAAE,CAAC;QAClD,KAAK,MAAM,IAAI,IAAI,UAAU,CAAC,UAAU,EAAE,CAAC;YACzC,iDAAiD;YACjD,IACE,OAAO,IAAI,KAAK,QAAQ;gBACxB,IAAI,KAAK,IAAI;gBACb,KAAK,IAAI,IAAI;gBACb,OAAO,IAAI,IAAI;gBACf,OAAO,IAAI,CAAC,GAAG,KAAK,QAAQ,EAC5B,CAAC;gBACD,gFAAgF;gBAChF,8DAA8D;gBAC9D,IAAI,CAAC;oBACH,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAe,CAAC,CAAC;gBAC7D,CAAC;gBAAC,MAAM,CAAC;oBACP,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;gBACvC,CAAC;YACH,CAAC;QACH,CAAC;QACD,2DAA2D;QAC3D,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;QACzC,4DAA4D;QAC5D,OAAO,UAAU,CAAC,UAAU,CAAC;IAC/B,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,aAAa,CAClC,aAAa,CAAC,QAAQ,CAAC;KACpB,WAAW,CAAC,gFAAgF,CAAC;KAC7F,SAAS,CACR,YAAY,CAAC,kBAAkB,EAAE,qCAAqC,CAAC;KACpE,OAAO,CAAC,EAAE,CAAC;KACX,SAAS,CAAC,QAAQ,CAAC,CACvB;KACA,SAAS,CACR,YAAY,CAAC,sBAAsB,EAAE,gCAAgC,CAAC;KACnE,OAAO,CAAC,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;KAC9B,OAAO,CAAC,YAAY,CAAC,CACzB;KACA,SAAS,CACR,YAAY,CAAC,uBAAuB,EAAE,gDAAgD,CAAC,CACxF;KACA,SAAS,CAAC,YAAY,CAAC,QAAQ,EAAE,wBAAwB,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;KAC1E,SAAS,CAAC,YAAY,CAAC,OAAO,EAAE,2CAA2C,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;KAC5F,SAAS,CAAC,YAAY,CAAC,WAAW,EAAE,uBAAuB,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;KAC5E,QAAQ,CAAC,SAAS,EAAE,qBAAqB,CAAC;KAC1C,MAAM,CAAC,KAAK,EAAE,KAAa,EAAE,OAAuB,EAAE,EAAE;IACvD,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,CAAC;IAEhD,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IAED,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,sBAAsB,KAAK,GAAG,CAAC,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,aAAa,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,mBAAmB,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;QACrD,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,cAAc,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAC9C,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,kBAAkB,GAAG,SAAS,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAE3F,IAAI,CAAC;QACH,kDAAkD;QAClD,8FAA8F;QAC9F,qFAAqF;QACrF,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM;YAC3B,CAAC,CAAC;gBACE,gBAAgB,EAAE,OAAO,CAAC,MAAM;aACjC;YACH,CAAC,CAAC,SAAS,CAAC;QAEd,mDAAmD;QACnD,uEAAuE;QACvE,kDAAkD;QAClD,MAAM,gBAAgB,GACpB,OAAO,CAAC,UAAU,KAAK,KAAK;YAC1B,CAAC,CAAC;gBACE,CAAC,EAAE,OAAO,CAAC,KAAK;gBAChB,UAAU,EAAE,KAAK;gBACjB,GAAG,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,MAAiC,EAAE,CAAC;aAC7D;YACH,CAAC,CAAC;gBACE,CAAC,EAAE,OAAO,CAAC,KAAK;gBAChB,UAAU,EAAE,YAAY;gBACxB,GAAG,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,MAAiC,EAAE,CAAC;aAC7D,CAAC;QAER,4CAA4C;QAC5C,MAAM,SAAS,GAAG,kBAAkB,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC;QACnE,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAE9C,oCAAoC;QACpC,IAAI,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CACb,kDAAkD,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,OAAO,EAAE,CAC/F,CAAC;QACJ,CAAC;QAED,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,oEAAoE;YACpE,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;gBAC1B,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;oBAChB,2DAA2D;oBAC3D,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;gBAC3D,CAAC;qBAAM,CAAC;oBACN,wDAAwD;oBACxD,MAAM,QAAQ,GAAG,iBAAiB,CAAC,GAAG,CAAC,QAAmC,CAAC,CAAC;oBAC5E,OAAO,CAAC,GAAG,CAAC;wBACV,OAAO,EAAE,GAAG,CAAC,WAAW;wBACxB,QAAQ;wBACR,KAAK,EAAG,QAA+B,EAAE,KAAK;qBAC/C,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,2CAA2C;YAC3C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;gBAClC,OAAO;YACT,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,WAAW,OAAO,CAAC,MAAM,UAAU,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;YAErF,OAAO,CAAC,OAAO,CAAC,CAAC,GAAa,EAAE,KAAa,EAAE,EAAE;gBAC/C,0EAA0E;gBAC1E,gEAAgE;gBAChE,MAAM,iBAAiB,GAAG,OAAO,CAAC,GAAG;oBACnC,CAAC,CAAE,GAAG,CAAC,QAAoC;oBAC3C,CAAC,CAAC,iBAAiB,CAAC,GAAG,CAAC,QAAmC,CAAC,CAAC;gBAC/D,MAAM,QAAQ,GAAG,iBAIhB,CAAC;gBACF,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;gBAC7B,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,IAAI,gBAAgB,CAAC;gBAEnD,gDAAgD;gBAChD,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gBACjC,OAAO,CAAC,GAAG,CACT,UAAU,KAAK,GAAG,CAAC,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,YAAY,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACnF,CAAC;gBACF,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,EAAE,CAAC,CAAC;gBAEjC,gEAAgE;gBAChE,yEAAyE;gBACzE,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;oBACpB,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,aAAa,EAAE,GAAG,QAAQ,CAAC;oBAC5D,IAAI,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBAC1C,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;oBACnE,CAAC;gBACH,CAAC;gBACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBAEhB,uDAAuD;gBACvD,+CAA+C;gBAC/C,MAAM,OAAO,GAAG,GAAG,CAAC,WAAW,CAAC;gBAChC,MAAM,SAAS,GAAG,GAAG,CAAC;gBACtB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;oBAC/B,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC;oBACrD,OAAO,CAAC,GAAG,CAAC,0BAA0B,OAAO,CAAC,MAAM,oBAAoB,CAAC,CAAC;gBAC5E,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBACvB,CAAC;gBACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAClB,CAAC,CAAC,CAAC;YAEH,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CACX,oBAAoB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAC/E,CAAC;QACF,IAAI,OAAO,CAAC,OAAO,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAC7D,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,EACJ;IACE,gBAAgB,EAAE,IAAI;IACtB,aAAa,EAAE,IAAI;CACpB,CACF,CAAC;AAEF,eAAe,OAAO,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { enableAI } from '@equinor/fusion-framework-module-ai';
|
|
2
|
+
import { AzureOpenAiEmbed, AzureOpenAIModel, AzureVectorStore, } from '@equinor/fusion-framework-module-ai/azure';
|
|
3
|
+
import { ModulesConfigurator } from '@equinor/fusion-framework-module';
|
|
4
|
+
/**
|
|
5
|
+
* Initializes and configures the Fusion Framework with AI module capabilities
|
|
6
|
+
* @param options - AI configuration options including API keys, deployments, and vector store settings
|
|
7
|
+
* @returns Promise resolving to an initialized framework instance with AI module
|
|
8
|
+
* @throws {Error} If embedding deployment is required but not provided when configuring vector store
|
|
9
|
+
*/
|
|
10
|
+
export const setupFramework = async (options) => {
|
|
11
|
+
// Create a new module configurator for the framework
|
|
12
|
+
const configurator = new ModulesConfigurator();
|
|
13
|
+
// Configure AI module with provided options
|
|
14
|
+
enableAI(configurator, (aiConfig) => {
|
|
15
|
+
// Configure chat model if deployment name is provided
|
|
16
|
+
if (options.openaiChatDeployment) {
|
|
17
|
+
aiConfig.setModel(options.openaiChatDeployment, new AzureOpenAIModel({
|
|
18
|
+
azureOpenAIApiKey: options.openaiApiKey,
|
|
19
|
+
azureOpenAIApiDeploymentName: options.openaiChatDeployment,
|
|
20
|
+
azureOpenAIApiInstanceName: options.openaiInstance,
|
|
21
|
+
azureOpenAIApiVersion: options.openaiApiVersion,
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
// Configure embedding model if deployment name is provided
|
|
25
|
+
if (options.openaiEmbeddingDeployment) {
|
|
26
|
+
aiConfig.setEmbedding(options.openaiEmbeddingDeployment, new AzureOpenAiEmbed({
|
|
27
|
+
azureOpenAIApiKey: options.openaiApiKey,
|
|
28
|
+
azureOpenAIApiDeploymentName: options.openaiEmbeddingDeployment,
|
|
29
|
+
azureOpenAIApiInstanceName: options.openaiInstance,
|
|
30
|
+
azureOpenAIApiVersion: options.openaiApiVersion,
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
33
|
+
// Configure vector store if Azure Search options are provided
|
|
34
|
+
// Vector store requires an embedding service to generate embeddings for documents
|
|
35
|
+
if (options.azureSearchEndpoint && options.azureSearchApiKey && options.azureSearchIndexName) {
|
|
36
|
+
if (!options.openaiEmbeddingDeployment) {
|
|
37
|
+
throw new Error('Embedding deployment is required to configure the vector store');
|
|
38
|
+
}
|
|
39
|
+
// Retrieve the embedding service to pass to the vector store
|
|
40
|
+
// The vector store uses embeddings to index and search documents
|
|
41
|
+
const embeddingService = aiConfig.getService('embeddings', options.openaiEmbeddingDeployment);
|
|
42
|
+
aiConfig.setVectorStore(options.azureSearchIndexName, new AzureVectorStore(embeddingService, {
|
|
43
|
+
endpoint: options.azureSearchEndpoint,
|
|
44
|
+
key: options.azureSearchApiKey,
|
|
45
|
+
indexName: options.azureSearchIndexName,
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
// Initialize the framework with all configured modules
|
|
50
|
+
const framework = await configurator.initialize();
|
|
51
|
+
return framework;
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=setup-framework.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-framework.js","sourceRoot":"","sources":["../../../src/utils/setup-framework.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAuC,MAAM,qCAAqC,CAAC;AAEpG,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,2CAA2C,CAAC;AAGnD,OAAO,EAAE,mBAAmB,EAAwB,MAAM,kCAAkC,CAAC;AAE7F;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EAAE,OAAkB,EAAwC,EAAE;IAC/F,qDAAqD;IACrD,MAAM,YAAY,GAAG,IAAI,mBAAmB,EAAc,CAAC;IAE3D,4CAA4C;IAC5C,QAAQ,CAAC,YAAY,EAAE,CAAC,QAAyB,EAAE,EAAE;QACnD,sDAAsD;QACtD,IAAI,OAAO,CAAC,oBAAoB,EAAE,CAAC;YACjC,QAAQ,CAAC,QAAQ,CACf,OAAO,CAAC,oBAAoB,EAC5B,IAAI,gBAAgB,CAAC;gBACnB,iBAAiB,EAAE,OAAO,CAAC,YAAY;gBACvC,4BAA4B,EAAE,OAAO,CAAC,oBAAoB;gBAC1D,0BAA0B,EAAE,OAAO,CAAC,cAAc;gBAClD,qBAAqB,EAAE,OAAO,CAAC,gBAAgB;aAChD,CAAC,CACH,CAAC;QACJ,CAAC;QAED,2DAA2D;QAC3D,IAAI,OAAO,CAAC,yBAAyB,EAAE,CAAC;YACtC,QAAQ,CAAC,YAAY,CACnB,OAAO,CAAC,yBAAyB,EACjC,IAAI,gBAAgB,CAAC;gBACnB,iBAAiB,EAAE,OAAO,CAAC,YAAY;gBACvC,4BAA4B,EAAE,OAAO,CAAC,yBAAyB;gBAC/D,0BAA0B,EAAE,OAAO,CAAC,cAAc;gBAClD,qBAAqB,EAAE,OAAO,CAAC,gBAAgB;aAChD,CAAC,CACH,CAAC;QACJ,CAAC;QAED,8DAA8D;QAC9D,kFAAkF;QAClF,IAAI,OAAO,CAAC,mBAAmB,IAAI,OAAO,CAAC,iBAAiB,IAAI,OAAO,CAAC,oBAAoB,EAAE,CAAC;YAC7F,IAAI,CAAC,OAAO,CAAC,yBAAyB,EAAE,CAAC;gBACvC,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;YACpF,CAAC;YAED,6DAA6D;YAC7D,iEAAiE;YACjE,MAAM,gBAAgB,GAAG,QAAQ,CAAC,UAAU,CAAC,YAAY,EAAE,OAAO,CAAC,yBAAyB,CAAC,CAAC;YAE9F,QAAQ,CAAC,cAAc,CACrB,OAAO,CAAC,oBAAoB,EAC5B,IAAI,gBAAgB,CAAC,gBAAgB,EAAE;gBACrC,QAAQ,EAAE,OAAO,CAAC,mBAAmB;gBACrC,GAAG,EAAE,OAAO,CAAC,iBAAiB;gBAC9B,SAAS,EAAE,OAAO,CAAC,oBAAoB;aACxC,CAAC,CACH,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,uDAAuD;IACvD,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,UAAU,EAAE,CAAC;IAClD,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC"}
|