Skip to content

Commit

Permalink
Merge branch '21744-trainee-interface' of github.com:howsoai/howso-en…
Browse files Browse the repository at this point in the history
…gine-ts into 21744-trainee-interface
  • Loading branch information
fulpm committed Oct 10, 2024
2 parents bb57c3f + 32e4cc7 commit 946ad3c
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 51 deletions.
21 changes: 19 additions & 2 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

This major change refactors the client and types for all Howso Engine operations.

### Typing Changes
### Typing changes

- Most of all the types are now autogenerated from the Engine API, and will have a different naming schema across
the board. However, most of the type's properties should remain the same.
Expand All @@ -13,7 +13,7 @@ This major change refactors the client and types for all Howso Engine operations
- The existing `Trainee` type has been renamed to `BaseTrainee` and no longer has a `features` property. Request
features via the method `getFeatureAttributes` instead.

### Client Changes
### Client changes

- `BaseClient` has been renamed to `AbstractBaseClient`.
- `WasmClient` has been renamed to `HowsoWorkerClient`.
Expand All @@ -33,6 +33,23 @@ This major change refactors the client and types for all Howso Engine operations
- The `react` method now uses `context_values` instead of `context` and `action_values` instead of `actions`.
- `local_*` react features have been removed. Use their unqualified versions instead.

### Utilities changes

- The options of `inferFeatureAttributes`'s `service.infer`'s `InferFeatureAttributesOptions` have been updated to
a subset of standard [engine options](https://docs.howso.com/en/release-latest/api_reference/_autosummary/howso.utilities.html#howso.utilities.infer_feature_attributes). Please remap to the following:

```ts
type InferFeatureAttributesOptions = {
dependent_features?: Record<string, string[]>;
features?: FeatureAttributesIndex;
include_sample?: boolean;
infer_bounds?: boolean;
mode_bound_features?: string[];
ordinal_feature_values?: Record<string, string[]>;
tight_bounds?: boolean;
};
```

## 5.x

The `inferFeatureAttributes` function now requires a `sourceFormat` argument, and is strongly typed through a union.
Expand Down
32 changes: 14 additions & 18 deletions src/features/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,20 @@ import type { FeatureAttributesIndex } from "../types";

export type FeatureSourceFormat = "unknown" | "array" | "parsed_array";

export interface InferFeatureBoundsOptions {
tightBounds?: boolean | string[];
modeBounds?: boolean | string[];
}

export interface InferFeatureTimeSeriesOptions {
timeFeature: string;
idFeatureName?: string;
}

export interface InferFeatureAttributesOptions {
defaults?: FeatureAttributesIndex;
inferBounds?: boolean | InferFeatureBoundsOptions;
timeSeries?: InferFeatureTimeSeriesOptions;
ordinalFeatureValues?: Record<string, string[]>;
dependentFeatures?: Record<string, string[]>;
includeSample?: boolean;
}
/**
* A subset of supported options.
* Full options are available only when using the Python direct client or Platform installation.
* @see https://docs.howso.com/en/release-latest/api_reference/_autosummary/howso.utilities.html#howso.utilities.infer_feature_attributes
**/
export type InferFeatureAttributesOptions = {
dependent_features?: Record<string, string[]>;
features?: FeatureAttributesIndex;
include_sample?: boolean;
infer_bounds?: boolean;
mode_bound_features?: string[];
ordinal_feature_values?: Record<string, string[]>;
tight_bounds?: boolean;
};

export interface ArrayData<T = any, C extends string = string> {
readonly columns: C[];
Expand Down
2 changes: 1 addition & 1 deletion src/features/sources/Array.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ describe("features/sources/Array", () => {
number: { type: "continuous", data_type: "number" },
date: { type: "continuous", data_type: "formatted_date_time", date_time_format: "%Y-%m-%dT%h-%m-%s" },
};
const features = await service.infer({ defaults, includeSample: true });
const features = await service.infer({ features: defaults, include_sample: true });
expectFeatureAttributesIndex(features);

// Id
Expand Down
22 changes: 6 additions & 16 deletions src/features/sources/Array.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
import type { FeatureAttributes } from "../../types";
import {
AbstractDataType,
ArrayData,
FeatureSourceFormat,
InferFeatureBoundsOptions,
InferFeatureTimeSeriesOptions,
isArrayData,
} from "../base";
import { AbstractDataType, ArrayData, FeatureSourceFormat, InferFeatureAttributesOptions, isArrayData } from "../base";
import * as utils from "../utils";
import { FeatureSerializerBase, InferFeatureAttributeFeatureStatistics, InferFeatureAttributesBase } from "./Base";

Expand Down Expand Up @@ -124,7 +117,7 @@ export class InferFeatureAttributesFromArray extends InferFeatureAttributesBase
public async inferBounds(
attributes: Readonly<FeatureAttributes>,
featureName: string,
options: InferFeatureBoundsOptions,
options: InferFeatureAttributesOptions,
): Promise<FeatureAttributes["bounds"]> {
const { minimum, maximum, hasNulls, samples, uniqueValues, totalValues } = await this.getStatistics(featureName);

Expand Down Expand Up @@ -167,15 +160,12 @@ export class InferFeatureAttributesFromArray extends InferFeatureAttributesBase
const actualMax = maxValue;

if (minValue !== undefined && maxValue !== undefined) {
if (
!options.tightBounds ||
(Array.isArray(options.tightBounds) && options.tightBounds.indexOf(featureName) === -1)
) {
if (!options.tight_bounds) {
// Use loose bounds
[minValue, maxValue] = utils.guessLooseBounds(minValue, maxValue);

const { modeBounds = true } = options;
if (modeBounds || (Array.isArray(modeBounds) && modeBounds.indexOf(featureName) >= 0)) {
const { mode_bound_features = [] } = options;
if (mode_bound_features.includes(featureName)) {
// Check for mode bounds
if (uniqueValues !== totalValues) {
const [modes, modeCount] = utils.allModes(column);
Expand Down Expand Up @@ -234,7 +224,7 @@ export class InferFeatureAttributesFromArray extends InferFeatureAttributesBase
/* eslint-disable-next-line @typescript-eslint/no-unused-vars*/
featureName: string,
/* eslint-disable-next-line @typescript-eslint/no-unused-vars*/
options: InferFeatureTimeSeriesOptions,
options: InferFeatureAttributesOptions,
): Promise<Partial<FeatureAttributes>> {
// TODO - infer time series
throw new Error("Method not implemented.");
Expand Down
20 changes: 7 additions & 13 deletions src/features/sources/Base.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
import { FeatureAttributes, FeatureAttributesIndex, FeatureOriginalType } from "../../types";
import {
AbstractDataType,
FeatureSourceFormat,
InferFeatureAttributesOptions,
InferFeatureBoundsOptions,
InferFeatureTimeSeriesOptions,
} from "../base";
import { AbstractDataType, FeatureSourceFormat, InferFeatureAttributesOptions } from "../base";
import { coerceDate } from "../utils";

export type InferFeatureAttributeFeatureStatistics = {
Expand Down Expand Up @@ -37,10 +31,10 @@ export abstract class InferFeatureAttributesBase {
// Loop the columns into attributes immediately to get order assigned. Probably should be a Map...
const columns = await this.getFeatureNames();
const attributes: FeatureAttributesIndex = columns.reduce((attributes, column) => {
attributes[column] = (options.defaults?.[column] || {}) as FeatureAttributes;
attributes[column] = (options.features?.[column] || {}) as FeatureAttributes;
return attributes;
}, {} as FeatureAttributesIndex);
const { ordinalFeatureValues = {}, dependentFeatures = {} } = options;
const { ordinal_feature_values: ordinalFeatureValues = {}, dependent_features: dependentFeatures = {} } = options;

const getFeatureAttributes = async (featureName: string): Promise<FeatureAttributes | undefined> => {
const originalFeatureType = await this.getOriginalFeatureType(featureName);
Expand Down Expand Up @@ -100,7 +94,7 @@ export abstract class InferFeatureAttributesBase {
}

// Infer bounds
const { inferBounds = true } = options;
const { infer_bounds: inferBounds = true } = options;
if (inferBounds && !attributes[featureName].bounds) {
const bounds = await this.inferBounds(
attributes[featureName],
Expand All @@ -117,7 +111,7 @@ export abstract class InferFeatureAttributesBase {
// TODO - infer time series
// }

if (options.includeSample) {
if (options.include_sample) {
additions.sample = await this.getSample(featureName);
}

Expand Down Expand Up @@ -248,12 +242,12 @@ export abstract class InferFeatureAttributesBase {
public abstract inferBounds(
attributes: Readonly<FeatureAttributes>,
featureName: string,
options: InferFeatureBoundsOptions,
options: InferFeatureAttributesOptions,
): Promise<FeatureAttributes["bounds"]>;
public abstract inferTimeSeries(
attributes: Readonly<FeatureAttributes>,
featureName: string,
options: InferFeatureTimeSeriesOptions,
options: InferFeatureAttributesOptions,
): Promise<Partial<FeatureAttributes>>;

protected async getSample(featureName: string): Promise<any | undefined> {
Expand Down
2 changes: 1 addition & 1 deletion src/features/sources/examples/CSV.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ describe("features/sources/CSV", () => {
const service = new InferFeatureAttributesFromCSV(data, serviceOptions);
expect(service.samples?.length).toBe(serviceOptions.samplesLimit);

const features = await service.infer({ includeSample: true });
const features = await service.infer({ include_sample: true });
expect(Object.keys(features)).toStrictEqual(columns);
expectFeatureAttributesIndex(features);
expectAsteroids(features);
Expand Down

0 comments on commit 946ad3c

Please sign in to comment.