Skip to content
This repository was archived by the owner on Jan 15, 2025. It is now read-only.

Commit e97e6b0

Browse files
authored
Changes for R14 (#1249)
* orchestrator:remove orchestrator:remove - take 1 * remove data source * use @microsoft scoped package of orchestrator-core * Update labelresolver.ts * refactored add data source * add missing qna file * unit tests fixes * Update settings.test.ts * fix orchestrator tests * Update basemodel.ts update download progress * Update basemodel.ts * updated basemodel:get log * log model download status * create - incremental update if existing blu file already exists * added tests for remove * Update pnpm-lock.yaml * Update datasourcehelper.ts fixed linting * updated to release package of orchestrator-core updated to release package of orchestrator-core * Update package.json * addressed PR comments from Josh * Update create.ts PR comments from Josh G * Addressed PR comments per Josh G Removed "strictNullChecks": false, * Update build.ts more PR comment * Addressed PR comments from Emilio * Update settings.ts fixed validation build errors
1 parent 7b2fd2e commit e97e6b0

File tree

19 files changed

+681
-214
lines changed

19 files changed

+681
-214
lines changed

common/config/rush/pnpm-lock.yaml

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/orchestrator/src/commands/orchestrator/add.ts

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import * as path from 'path';
77
import {Command, CLIError, flags} from '@microsoft/bf-cli-command';
8-
import {DataSourceHelper, Orchestrator, OrchestratorDataSource, OrchestratorHelper, OrchestratorSettings, Utility} from '@microsoft/bf-orchestrator';
8+
import {Orchestrator, OrchestratorDataSource, OrchestratorHelper, OrchestratorSettings} from '@microsoft/bf-orchestrator';
99

1010
export default class OrchestratorAdd extends Command {
1111
static description: string = 'Add examples from .lu/.qna/.json/.blu files, LUIS app(s) and QnaMaker kb(s) to Orchestrator snapshot file.';
@@ -57,33 +57,32 @@ export default class OrchestratorAdd extends Command {
5757
fullEmbeddings = true;
5858
}
5959

60+
const settings: OrchestratorSettings = OrchestratorSettings.getCurrent();
6061
if (type.length > 0) {
61-
if (type === 'luis' && Utility.isEmptyString(endpoint)) {
62-
throw new CLIError('LUIS endpoint required, ie --endpoint https://westus.api.cognitive.microsoft.com');
63-
}
64-
OrchestratorSettings.init(cwd, baseModelPath, entityBaseModelPath, output, true, true);
65-
const dataSource: OrchestratorDataSource = new OrchestratorDataSource(id, key, version, endpoint, type, routingName, OrchestratorSettings.DataSources.path);
66-
await DataSourceHelper.ensureDataSourceAsync(dataSource, OrchestratorSettings.DataSources.path);
62+
settings.init(cwd, baseModelPath, entityBaseModelPath, output, true, true);
63+
const dataSource: OrchestratorDataSource =
64+
new OrchestratorDataSource(id, key, version, endpoint, type, routingName, inputPath);
65+
await Orchestrator.addDataSource(dataSource);
6766

6867
if (dataSource.Type === 'file') {
6968
this.log(`Added ${dataSource.Type} source ${dataSource.FilePath}`);
7069
} else {
7170
this.log(`Added ${dataSource.Type} source with id ${dataSource.Id}`);
7271
}
7372
} else {
74-
OrchestratorSettings.init(cwd, baseModelPath, entityBaseModelPath, output);
75-
const snapshot: Uint8Array = OrchestratorHelper.getSnapshotFromFile(path.resolve(OrchestratorSettings.SnapshotPath));
73+
settings.init(cwd, baseModelPath, entityBaseModelPath, output);
74+
const snapshot: Uint8Array = OrchestratorHelper.getSnapshotFromFile(path.resolve(settings.SnapshotPath));
7675
const inputs: any = OrchestratorHelper.getLuInputs(inputPath);
7776
await Orchestrator.addAsync(
78-
OrchestratorSettings.ModelPath,
77+
settings.ModelPath,
7978
snapshot,
8079
inputs,
8180
isDialog,
8281
entityBaseModelPath,
8382
fullEmbeddings);
8483
}
8584

86-
OrchestratorSettings.persist();
85+
settings.persist();
8786
} catch (error) {
8887
throw (new CLIError(error));
8988
}

packages/orchestrator/src/commands/orchestrator/basemodel/get.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ export default class OrchestratorBaseModelGet extends Command {
3030
if (!OrchestratorHelper.exists(output)) {
3131
OrchestratorHelper.mkDir(output);
3232
}
33-
OrchestratorSettings.init(cwd, output, '', '');
33+
34+
const settings: OrchestratorSettings = OrchestratorSettings.getCurrent();
35+
settings.init(cwd, output, '', '');
3436
const models: any[] = [];
3537

3638
let versions: any;
@@ -64,10 +66,13 @@ export default class OrchestratorBaseModelGet extends Command {
6466
await OrchestratorBaseModel.getAsync(
6567
modelInfo.modelFolder,
6668
modelInfo.versionId,
67-
(message: any) => {
68-
if (flags.verbose) {
69+
(message: any, pct: number) => {
70+
if (message) {
6971
this.log(message);
7072
}
73+
if (flags.verbose && pct) {
74+
this.log(`Downloaded ${pct}%...`);
75+
}
7176
},
7277
(message: any) => {
7378
this.log(`Model ${modelInfo.versionId} downloaded to ${modelInfo.modelFolder}`);
@@ -78,7 +83,7 @@ export default class OrchestratorBaseModelGet extends Command {
7883
})
7984
);
8085

81-
OrchestratorSettings.persist();
86+
settings.persist();
8287
} catch (error) {
8388
throw (new CLIError(error));
8489
}

packages/orchestrator/src/commands/orchestrator/build.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,21 @@ export default class OrchestratorBuild extends Command {
4545
output = path.dirname(output);
4646
}
4747

48+
const settings: OrchestratorSettings = OrchestratorSettings.getCurrent();
4849
const luInputs: any[] = OrchestratorHelper.getLuInputs(input);
4950
const snapshots: Map<string, Uint8Array> = OrchestratorHelper.getSnapshots(output);
50-
const labelResolvers: Map<string, LabelResolver> = await Orchestrator.getLabelResolversAsync(OrchestratorSettings.ModelPath, entityBaseModelPath, snapshots);
51+
const labelResolvers: Map<string, LabelResolver> = await Orchestrator.getLabelResolversAsync(settings.ModelPath, entityBaseModelPath, snapshots);
5152

5253
try {
5354
let fullEmbeddings: boolean = false;
5455
if (process.env.fullEmbeddings) {
5556
fullEmbeddings = true;
5657
}
5758
Utility.toPrintDebuggingLogToConsole = flags.debug;
58-
OrchestratorSettings.init(cwd, flags.model, output, cwd);
59+
60+
settings.init(cwd, flags.model, output, cwd);
5961
const retPayload: any = await Orchestrator.buildAsync(
60-
OrchestratorSettings.ModelPath,
62+
settings.ModelPath,
6163
luInputs,
6264
labelResolvers,
6365
isDialog,

packages/orchestrator/src/commands/orchestrator/create.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import * as path from 'path';
77
import {Command, CLIError, flags} from '@microsoft/bf-cli-command';
8-
import {DataSourceHelper, Orchestrator, OrchestratorHelper, OrchestratorDataSourceSettings, OrchestratorSettings, Utility} from '@microsoft/bf-orchestrator';
8+
import {DataSourceHelper, Orchestrator, OrchestratorHelper, OrchestratorSettings, OrchestratorDataSourceSettings, Utility} from '@microsoft/bf-orchestrator';
99

1010
export default class OrchestratorCreate extends Command {
1111
static description: string = 'Create orchestrator snapshot (.blu) file from .lu/.qna/.json/.tsv/.dispatch files, which represent bot modules';
@@ -44,7 +44,8 @@ export default class OrchestratorCreate extends Command {
4444
Utility.resetFlagToPrintDebuggingLogToConsole(flags.debug);
4545

4646
try {
47-
OrchestratorSettings.init(cwd, baseModelPath, entityBaseModelPath, output, flags.hierarchical);
47+
const settings: OrchestratorSettings = OrchestratorSettings.getCurrent();
48+
settings.init(cwd, baseModelPath, entityBaseModelPath, output, flags.hierarchical);
4849

4950
let fullEmbeddings: boolean = false;
5051
if (process.env.fullEmbeddings) {
@@ -55,30 +56,30 @@ export default class OrchestratorCreate extends Command {
5556

5657
if (DataSourceHelper.isDispatchInput(input)) {
5758
const dispatchJson: any = JSON.parse(OrchestratorHelper.readFile(input));
58-
DataSourceHelper.convertDispatchInputs(dispatchJson, OrchestratorSettings.DataSources);
59+
DataSourceHelper.convertDispatchInputs(dispatchJson, settings.DataSources);
5960
refresh = true;
6061
}
6162

62-
const hasDataSources: boolean = OrchestratorSettings.DataSources && OrchestratorSettings.DataSources.inputs.length > 0;
63+
const hasDataSources: boolean = settings.DataSources?.inputs?.length > 0 ?? false;
6364
if (hasDataSources) {
64-
input = OrchestratorSettings.DataSources.path;
65+
input = settings.DataSources.path;
6566
hierarchical = true;
6667
}
6768

6869
if (refresh) {
69-
await this.refreshLuisQnAInputs(OrchestratorSettings.DataSources);
70+
await this.refreshLuisQnAInputs(settings.DataSources);
7071
}
7172

7273
const snapshotFilePath: string = await Orchestrator.createAsync(
73-
OrchestratorSettings.ModelPath,
74+
settings.ModelPath,
7475
input,
75-
OrchestratorSettings.SnapshotPath,
76-
OrchestratorSettings.EntityModelPath,
76+
settings.SnapshotPath,
77+
settings.EntityModelPath,
7778
hierarchical,
7879
fullEmbeddings);
7980

80-
OrchestratorSettings.SnapshotPath = snapshotFilePath;
81-
OrchestratorSettings.persist();
81+
settings.SnapshotPath = snapshotFilePath;
82+
settings.persist();
8283
} catch (error) {
8384
throw (new CLIError(error));
8485
}
@@ -93,7 +94,7 @@ export default class OrchestratorCreate extends Command {
9394
this.log(`Refreshing ${dataSource.Type} data - id ${dataSource.Id}...`);
9495
}
9596
// eslint-disable-next-line no-await-in-loop
96-
await DataSourceHelper.ensureDataSourceAsync(dataSource, OrchestratorSettings.DataSources.path, false);
97+
await DataSourceHelper.ensureDataSourceAsync(dataSource, dataSources.path, false);
9798
}
9899
}
99100
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*!
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License.
4+
*/
5+
6+
import * as path from 'path';
7+
import {Command, CLIError, flags} from '@microsoft/bf-cli-command';
8+
import {Orchestrator, OrchestratorDataSource, OrchestratorSettings} from '@microsoft/bf-orchestrator';
9+
10+
export default class OrchestratorRemove extends Command {
11+
static description: string = 'Remove examples from LUIS app(s), QnaMaker kb(s) or .lu/.qna/.json files from Orchestrator snapshot file.';
12+
13+
static examples: Array<string> = [`
14+
$ bf orchestrator:remove
15+
$ bf orchestrator:remove -t luis --id LUIS_APP_ID
16+
$ bf orchestrator:remove -t qna --id QNA_KB
17+
$ bf orchestrator:remove -t file -i FILE_PATH
18+
`]
19+
20+
static flags: flags.Input<any> = {
21+
in: flags.string({char: 'i', description: 'Path to example file (.lu/.qna/.json/.blu).'}),
22+
id: flags.string({description: 'LUIS app id or QnAMaker kb id if type = luis/qna.'}),
23+
type: flags.string({char: 't', description: 'Type of input (luis/qna/file).'}),
24+
debug: flags.boolean({char: 'd'}),
25+
help: flags.help({char: 'h', description: 'Orchestrator remove command help'}),
26+
}
27+
28+
async run() {
29+
const {flags}: flags.Output = this.parse(OrchestratorRemove);
30+
const cwd: string = process.cwd();
31+
const filePath: string = path.resolve(flags.in || cwd);
32+
const type: string = (flags.type.toLowerCase() || '');
33+
const id: string = (flags.id || '');
34+
35+
if (!type) {
36+
throw new CLIError('Type parameter required');
37+
}
38+
39+
try {
40+
const settings: OrchestratorSettings = OrchestratorSettings.getCurrent();
41+
settings.init(cwd, '', '', '', true, true);
42+
const dataSource: OrchestratorDataSource = new OrchestratorDataSource(id, '', '', '', type, '', filePath);
43+
if (Orchestrator.removeDataSource(dataSource)) {
44+
if (dataSource.Type === 'file') {
45+
this.log(`Removed ${dataSource.Type} source ${dataSource.FilePath}`);
46+
} else {
47+
this.log(`Removed ${dataSource.Type} source with id ${dataSource.Id}`);
48+
}
49+
} else {
50+
this.log('Data source not found');
51+
}
52+
53+
settings.persist();
54+
} catch (error) {
55+
throw (new CLIError(error));
56+
}
57+
}
58+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*!
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License.
4+
*/
5+
6+
import {expect, test} from '@oclif/test';
7+
describe('orchestrator:remove tests', () => {
8+
test
9+
.stdout()
10+
.command(['orchestrator:remove', '--help'])
11+
.exit(1)
12+
.it('should print the help contents when --help is passed as an argument', (ctx: any) => {
13+
expect(ctx.stdout).to.contain('Remove examples from LUIS app(s), QnaMaker kb(s) or .lu/.qna/.json files');
14+
});
15+
});

packages/orchestratorlib/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
"axios":"~0.21.1",
4141
"https-proxy-agent": "^5.0.0",
4242
"tslib": "^2.0.3",
43-
"@microsoft/orchestrator-core": "4.14.0-preview",
43+
"@microsoft/orchestrator-core": "~4.14.0",
4444
"@types/fs-extra": "~8.1.0",
4545
"fs-extra": "~9.0.0",
4646
"read-text-file": "~1.1.0",

packages/orchestratorlib/src/basemodel.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export class OrchestratorBaseModel {
6262
const modelZipPath: string = path.join(baseModelPath, fileName);
6363
Utility.debuggingLog(`OrchestratorBaseModel.getModelAsync(): finished calling fileName=${fileName}`);
6464
Utility.debuggingLog(`OrchestratorBaseModel.getModelAsync(): finished calling modelZipPath=${modelZipPath}`);
65-
await this.downloadModel(modelUrl, modelZipPath);
65+
await this.downloadModel(modelUrl, modelZipPath, onProgress);
6666
if (onProgress) {
6767
onProgress('OrchestratorBaseModel.getModelAsync(): model downloaded...');
6868
}
@@ -100,13 +100,25 @@ export class OrchestratorBaseModel {
100100
return response.data;
101101
}
102102

103-
public static async downloadModel(modelUrl: string, modelZipPath: string): Promise<(resolve: any) => void> {
103+
public static async downloadModel(modelUrl: string, modelZipPath: string, onProgress: any = OrchestratorBaseModel.defaultHandler): Promise<(resolve: any) => void> {
104104
const response: AxiosResponse<Stream> = await axios({
105105
method: 'GET',
106106
url: modelUrl,
107107
responseType: 'stream',
108108
});
109+
const totalLength: number = response.headers['content-length'];
110+
onProgress(`Total to download: ${totalLength} bytes...`);
111+
let totalCompleted: number = 0;
112+
let totalCompletedPct: number = 0;
109113
Utility.debuggingLog('OrchestratorBaseModel.getModelAsync(): calling download zipped model files');
114+
response.data.on('data', (chunk: any) => {
115+
totalCompleted += chunk.length;
116+
const newPct: number = Math.round(totalCompleted / totalLength * 100);
117+
if (newPct > totalCompletedPct) {
118+
totalCompletedPct = newPct;
119+
onProgress('', totalCompletedPct);
120+
}
121+
});
110122
response.data.pipe(fs.createWriteStream(modelZipPath));
111123

112124
return new Promise((resolve: any) => {

0 commit comments

Comments
 (0)