diff --git a/cds-feature-ai-core/README.md b/cds-feature-ai-core/README.md index 1b1125f..61ffcf6 100644 --- a/cds-feature-ai-core/README.md +++ b/cds-feature-ai-core/README.md @@ -29,7 +29,7 @@ The plugin auto-registers via Java's `ServiceLoader` mechanism - no code changes In production, bind an SAP AI Core service instance to your application. Supported methods: -- **Service binding** (Cloud Foundry / Kubernetes) - detected automatically via `ServiceBindingUtils` +- **Service binding** (Cloud Foundry / Kubernetes) - **Environment variable** `AICORE_SERVICE_KEY` - for local hybrid testing (via `cds bind --exec`) Without a binding the plugin registers a mock implementation. diff --git a/cds-feature-recommendations/README.md b/cds-feature-recommendations/README.md index 27be8f2..088b165 100644 --- a/cds-feature-recommendations/README.md +++ b/cds-feature-recommendations/README.md @@ -7,7 +7,7 @@ AI-powered field recommendations for SAP Fiori UIs in CAP Java applications, lev The plugin generically hooks into any draft-enabled entity that has properties with a value help. When a user edits a draft record, the plugin: 1. Fetches historical records as training context -2. Sends context + current row to the RPT-1 model +2. Sends context + current row to the provided model (default: RPT-1 model) 3. Returns predictions as `SAP_Recommendations` in the OData response 4. Fiori Elements renders the recommendations as suggestions in form fields @@ -35,14 +35,9 @@ Or use the starter that bundles this with `cds-feature-ai-core`: ``` -### Prerequisites +Requires an [SAP AI Core](https://help.sap.com/docs/sap-ai-core) service binding — see [`cds-feature-ai-core`](../cds-feature-ai-core/README.md) for setup. -- An [SAP AI Core](https://help.sap.com/docs/sap-ai-core) service binding (see [`cds-feature-ai-core`](../cds-feature-ai-core/README.md)) -- Entity must be **draft-enabled** (`@odata.draft.enabled`) -- At least one field annotated with a **value list** -- The `@cap-js/ai` CDS plugin must be installed (provides the model enhancement that adds `SAP_Recommendations` as a navigation property) - -### CDS Plugin +#### CDS Plugin Add `@cap-js/ai` to your project's `package.json`: @@ -55,7 +50,7 @@ Add `@cap-js/ai` to your project's `package.json`: } ``` -Then run `npm install`. The plugin hooks into the CDS compiler and automatically adds the `SAP_Recommendations` navigation property to draft-enabled entities that have value-list fields. Without this plugin, predictions will be computed but not serialized in OData responses. +Then run `npm install`. The plugin hooks into the CDS compiler and automatically adds the `SAP_Recommendations` navigation property to draft-enabled entities that have value-list fields. Since the Java module `cds-feature-ai-core` already provides the `AICore` service CDS model, disable the duplicate model from `@cap-js/ai` in your `.cdsrc.json`: @@ -71,9 +66,16 @@ Since the Java module `cds-feature-ai-core` already provides the `AICore` servic ## Enabling Recommendations +For recommendations to fire on an entity: + +- The entity must be **draft-enabled** (`@odata.draft.enabled`) +- At least one field must be annotated with a **value list** +- The `SAP_Recommendations` navigation property must be present — either via the CDS plugin (see above) or added manually (see below). Without it, predictions are computed but not serialized in OData responses. + Recommendations are triggered for fields annotated with `@Common.ValueList`, `@Common.ValueListWithFixedValues`, or whose association target has `@cds.odata.valuelist`: ```cds +@odata.draft.enabled entity Books { key ID : Integer; title : String(111); @@ -98,6 +100,42 @@ annotate Books with { } ``` +#### Adding the SAP_Recommendations navigation property manually + +If you cannot use the CDS plugin, add the `SAP_Recommendations` navigation property directly in your CDS model. You need to: + +1. **Define a `RecommendationItem_*` type** for each CDS primitive type used by your value-list fields. Each type must contain the four fixed fields shown below — only `RecommendedFieldValue` varies by type. +2. **Extend each target entity** with a `SAP_Recommendations` composition that has one entry per value-list field, using the field name as the property name and the matching `RecommendationItem_*` type. + +The property names inside `SAP_Recommendations` must exactly match the field names on the entity (e.g. `genre_ID`, `author_ID`). + +```cds +// Define one type per CDS primitive used by your value-list fields +type RecommendationItem_Integer { + RecommendedFieldValue : Integer; + RecommendedFieldDescription : String; + RecommendedFieldScoreValue : Decimal; + RecommendedFieldIsSuggestion: Boolean; +} + +type RecommendationItem_UUID { + RecommendedFieldValue : UUID; + RecommendedFieldDescription : String; + RecommendedFieldScoreValue : Decimal; + RecommendedFieldIsSuggestion: Boolean; +} + +// Extend your entity — one entry per value-list field +extend my.Books with { + SAP_Recommendations: Composition of one { + genre_ID : many RecommendationItem_Integer; + author_ID: many RecommendationItem_UUID; + } +} +``` + +See also the [SAP Fiori Elements – Recommendations documentation](https://help.sap.com/docs/SAPUI5/b2f662dd9d7a4ec680056733050b4d34/1a6324d5ad7f4034a93f911b4e53e080.html). + ### Adding Text Descriptions Use `@Common.Text` to show human-readable descriptions alongside recommended values: @@ -132,11 +170,13 @@ A value of `1` (or omitting the annotation) means the field is eligible for reco ## Configuration +The following configuration applies to the RPT-1 model implementation. + ```yaml cds: requires: recommendations: - contextRowLimit: 2000 # Max historical rows used as training context + contextRowLimit: 2000 # Max historical rows used as training context (RPT-1) ``` See [`cds-feature-ai-core`](../cds-feature-ai-core/README.md) for AI Core connection and multi-tenancy configuration. @@ -164,12 +204,14 @@ SAP Fiori Elements automatically renders these as suggestions in form fields whe ## Supported Field Types -| Category | Types | -| -------- | --------------------------------------------------------- | -| String | `String`, `LargeString`, `UUID` | -| Numeric | `Integer`, `Int16`, `Int32`, `Int64`, `Decimal`, `Double` | -| Temporal | `Date`, `Time`, `DateTime`, `Timestamp` | -| Other | `Boolean` | +The following field types are supported by the RPT-1 model implementation: + +| Category | Types | +| -------- | ---------------------------------------------------------------------- | +| String | `String`, `LargeString`, `UUID` (treated as string) | +| Numeric | `Integer`, `Int16`, `Int32`, `Int64`, `Integer64`, `Decimal`, `Double` | +| Temporal | `Date`, `Time`, `DateTime`, `Timestamp` | +| Other | `Boolean` | Binary, vector, and draft system fields are excluded automatically. diff --git a/cds-feature-recommendations/src/test/resources/model/recommendations-test.cds b/cds-feature-recommendations/src/test/resources/model/recommendations-test.cds index 3e5f45d..0491697 100644 --- a/cds-feature-recommendations/src/test/resources/model/recommendations-test.cds +++ b/cds-feature-recommendations/src/test/resources/model/recommendations-test.cds @@ -6,13 +6,13 @@ namespace test; entity Books { key ID : UUID; title : String; - @Common.ValueListWithFixedValues genre_ID : Integer; @Common.Text : genre.name - genre : Association to Genres; @Common.ValueListWithFixedValues + genre : Association to Genres; currency_code : String(3); @(Common.Text: { $value: ![currency.name] }) + @Common.ValueListWithFixedValues currency : Association to Currencies; image : LargeBinary; embedding : Vector(8);