diff --git a/.vitepress/theme/components/ConfigInspect.vue b/.vitepress/theme/components/ConfigInspect.vue index f497a2897..c54d21571 100644 --- a/.vitepress/theme/components/ConfigInspect.vue +++ b/.vitepress/theme/components/ConfigInspect.vue @@ -15,12 +15,12 @@
cds.features.runtime_views: true. +In CAP Java, runtime views are enabled by default. Node.js does not support it yet. [Learn more about runtime views in CAP Java.](../java/working-with-cql/query-execution#runtimeviews) {.learn-more} diff --git a/get-started/index.md b/get-started/index.md index ca771a3d6..3ddb17f1c 100644 --- a/get-started/index.md +++ b/get-started/index.md @@ -18,7 +18,7 @@ On macOS, Linux and WSL (Windows Subsystem for Linux), we recommend using [Homeb ```shell [macOS] bash -c "$( curl https://raw.githubusercontent.com/homebrew/install/HEAD/install.sh )" ``` -```shell [Linux / WSL] +```shell [Linux] # install curl (required to get Homebrew) and git (required to run Homebrew) sudo apt install curl git -y bash -c "$( curl https://raw.githubusercontent.com/homebrew/install/HEAD/install.sh )" @@ -34,7 +34,7 @@ bash -c "$( curl https://raw.githubusercontent.com/homebrew/install/HEAD/install ### Node.js and _cds-dk_ {.required} ::: code-group -```shell [macOS / Linux / WSL] +```shell [macOS/Linux] brew install node # Node.js LTS npm i -g @sap/cds-dk # install CAP's cds-dk globally ``` @@ -59,7 +59,7 @@ sqlite3 -version ### Java and Maven {.optional} ::: code-group -```shell [macOS / Linux / WSL] +```shell [macOS/Linux] brew install sapmachine-jdk brew install maven ``` @@ -92,7 +92,7 @@ brew install git # Git CLI brew install gh # GitHub CLI brew install github # GitHub Desktop App ``` -```shell [Linux / WSL] +```shell [Linux] brew install git # Git CLI brew install gh # GitHub CLI @@ -127,7 +127,7 @@ git -v # display Git cli version ```shell [macOS] brew install --cask visual-studio-code # VS Code itself ``` -```bash [Linux / WSL] +```bash [Linux] # VS Code on Homebrew is only supported for macOS sudo snap install --classic code code -v # display VS Code's version diff --git a/guides/databases/_menu.md b/guides/databases/_menu.md index ca989779d..cdbfd2514 100644 --- a/guides/databases/_menu.md +++ b/guides/databases/_menu.md @@ -10,3 +10,4 @@ ## [ PostgreSQL ](postgres.md) # [ Schema Evolution ](schema-evolution.md) # [ Performance Guide ](performance.md) +# [ Vector Embeddings ](vector-embeddings.md) diff --git a/guides/databases/hana.md b/guides/databases/hana.md index 4bda1e0c3..ac78a3650 100644 --- a/guides/databases/hana.md +++ b/guides/databases/hana.md @@ -261,86 +261,6 @@ See the [Deploying to Cloud](../deploy/index.md) guide for information about how The HANA Service provides dedicated support for native SAP HANA features as follows. -### Vector Embeddings - -Vector embeddings let you add semantic search, recommendations, and generative AI features to your CAP application. Embeddings are numeric arrays that represent the meaning of unstructured data (text, images, etc.), making it possible to compare and search for items that are semantically related to each other or a user query. - -#### Choose an Embedding Model - -Choose an embedding model that fits your use case and data (for example english or multilingual text). The model determines the number of dimensions of the resulting output vector. Check the documentation of the respective embedding model for details. - -Use the [SAP Generative AI Hub](https://community.sap.com/t5/technology-blogs-by-sap/how-sap-s-generative-ai-hub-facilitates-embedded-trustworthy-and-reliable/ba-p/13596153) for unified consumption of embedding models and LLMs across different vendors and open source models. Check for available models on the [SAP AI Launchpad](https://help.sap.com/docs/ai-launchpad/sap-ai-launchpad-user-guide/models-and-scenarios-in-generative-ai-hub-fef463b24bff4f44a33e98bb1e4f3148#models). - -#### Add Embeddings to Your CDS Model -Use the `cds.Vector` type in your CDS model to store embeddings on SAP HANA Cloud. Set the dimension to match your embedding model (for example, 1536 embedding dimensions for OpenAI *text-embedding-3-small*). - - ```cds - entity Books : cuid { - title : String(111); - description : LargeString; - embedding : Vector(1536); // adjust dimensions to embedding model - } - ``` - -#### Generate Embeddings -Use an embedding model to convert your data (for example, book descriptions) into vectors. The [SAP Cloud SDK for AI](https://sap.github.io/ai-sdk/) makes it easy to call SAP AI Core services to generate these embeddings. - -:::details Example using SAP Cloud SDK for AI -```Java -var aiClient = OpenAiClient.forModel(OpenAiModel.TEXT_EMBEDDING_3_SMALL); -var response = aiClient.embedding( - new OpenAiEmbeddingRequest(List.of(book.getDescription()))); -book.setEmbedding(CdsVector.of(response.getEmbeddingVectors().get(0))); -``` -::: - -#### Query for Similarity -At runtime, use SAP HANA's built-in vector functions to search for similar items. For example, find books with embeddings similar to a user question: - -::: code-group -```Java [Java] -// Compute embedding for user question -var request = new OpenAiEmbeddingRequest(List.of("How to use vector embeddings in CAP?")); -CdsVector userQuestion = CdsVector.of( - aiClient.embedding(request).getEmbeddingVectors().get(0)); - -// Compute similarity between user question and book embeddings -var similarity = CQL.cosineSimilarity( // computed on SAP HANA - CQL.get(Books.EMBEDDING), userQuestion); - -// Find Books related to user question ordered by similarity -hana.run(Select.from(BOOKS).limit(10) - .columns(b -> b.ID(), b -> b.title(), b -> similarity.as("similarity")) - .orderBy(b -> b.get("similarity").desc()) -); -``` - -```js [Node.js] -const response = await new AzureOpenAiEmbeddingClient( - 'text-embedding-3-small' -).run({ - input: 'How to use vector embeddings in CAP?' -}); - -const questionEmbedding = response.getEmbedding(); -let similarBooks = await SELECT.from('Books') - .where`cosine_similarity(embedding, to_real_vector(${questionEmbedding})) > 0.9`; -``` -::: - -:::tip Evolve embeddings with your model -Store embeddings when you create or update your data. Regenerate embeddings if you change your embedding model. -::: - -:::tip Use SAP Cloud SDK for AI -Use the [SAP Cloud SDK for AI](https://sap.github.io/ai-sdk/) for unified access to embedding models and large language models (LLMs) from [SAP AI Core](https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/what-is-sap-ai-core). -::: - -Learn more about the [SAP Cloud SDK for AI (Java)](https://sap.github.io/ai-sdk/docs/java/getting-started) or the [SAP Cloud SDK for AI (JavaScript)](https://sap.github.io/ai-sdk/docs/js/getting-started) {.learn-more} - -[Learn more about Vector Embeddings in CAP Java](../../java/cds-data#vector-embeddings) {.learn-more} - - ### Geospatial Functions CDS supports the special syntax for SAP HANA geospatial functions: diff --git a/guides/databases/vector-embeddings.md b/guides/databases/vector-embeddings.md new file mode 100644 index 000000000..cb4ebe69f --- /dev/null +++ b/guides/databases/vector-embeddings.md @@ -0,0 +1,109 @@ +--- +label: Vector Embeddings +--- +# Vector Embeddings + +Vector embeddings convert unstructured content (text, images, and so on) into numeric vectors that encode semantics (meaning). Comparing these vectors enables semantic search, recommendations, and enhanced generative AI features in your CAP application. For example retrieving related records, ranking results by relevance, or augmenting prompts for LLMs. + +## Choose an Embedding Model + +Choose an embedding model that fits your use case and data (for example English or multilingual text). The model determines the number of dimensions of the resulting output vector. Check the documentation of the respective embedding model for details. + +Use the [SAP Generative AI Hub](https://www.sap.com/products/artificial-intelligence/generative-ai-hub.html) for unified consumption of embedding models and LLMs across different vendors and open-source models. Check for available models on the [SAP AI Launchpad](https://help.sap.com/docs/ai-launchpad/sap-ai-launchpad-user-guide/models-and-scenarios-in-generative-ai-hub-fef463b24bff4f44a33e98bb1e4f3148#models). + +## Add Embeddings to Your CDS Model +Use the built-in CDL [Vector type](../../cds/types) in your CDS model to store embeddings. Set the vector dimensions to match the embedding model (for example, 768 for *SAP_GXY.20250407*). + +```cds +extend Incidents with { + embedding : Vector(768); +} +``` + +## Generate Embeddings +Use an embedding model to convert your data (for example, incident titles and summaries) into vectors. + +:::warning Evolve embeddings with your model +Store embeddings when you create or update your data. Regenerate embeddings if you change your embedding model. +::: + +### Generate Embeddings on the Database + +To generate vector embeddings on write in SAP HANA, you can use the [vector_embedding](https://help.sap.com/docs/hana-cloud-database/sap-hana-cloud-sap-hana-database-sql-reference-guide/vector-embedding-function-vector) function as calculated element [on-write](../../cds/cdl#on-write) with embedding models from [SAP HANA NLP](https://help.sap.com/docs/hana-cloud-database/sap-hana-cloud-sap-hana-database-vector-engine-guide/creating-text-embeddings-with-nlp-51eb170d038d4099a9bbb85c08fda888) or a configured remote source from SAP AI Core: + +```cds +extend Incidents with { + @cds.api.ignore + embedding : Vector(768) = vector_embedding( + 'Title: ' || title || ', Summary: ' || summary, + 'DOCUMENT', 'SAP_GXY.20250407' + ) stored; +} +``` + +:::tip Prefer calculated elements for vector embeddings +If the database calculates vector embeddings on write it automatically regenerates the embedding if the input data changes. +::: + +::: info Local Testing with H2 and SQLite +On H2 and SQLite the `CQL.vectorEmbedding` function is emulated to support local testing. +::: + +> [!warning] Java only and +> The `vector_embedding` function is currently in beta and only supported by the CAP Java runtime. + +[Learn more about Vector Embeddings in CAP Java](../../java/cds-data#vector-embeddings) {.learn-more} + +### Generate Embeddings Programmatically + +Alternatively, you can compute vector embeddings in your application layer using the [SAP Cloud SDK for AI](https://sap.github.io/ai-sdk/) to call SAP AI Core services for generating embeddings. + +:::details Example using SAP Cloud SDK for AI +```Java +var aiClient = OpenAiClient.forModel(OpenAiModel.TEXT_EMBEDDING_3_SMALL); +var response = aiClient.embedding( + new OpenAiEmbeddingRequest(List.of(book.getDescription()))); +book.setEmbedding(CdsVector.of(response.getEmbeddingVectors().get(0))); +``` +::: + +:::tip Use SAP Cloud SDK for AI +Use the [SAP Cloud SDK for AI](https://sap.github.io/ai-sdk/) for unified access to embedding models and large language models (LLMs) from [SAP AI Core](https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/what-is-sap-ai-core). +::: + +Learn more about the [SAP Cloud SDK for AI (Java)](https://sap.github.io/ai-sdk/docs/java/getting-started) or the [SAP Cloud SDK for AI (JavaScript)](https://sap.github.io/ai-sdk/docs/js/getting-started) {.learn-more} + +## Query for Similarity +At runtime, use vector functions to search for similar items. In an example Retrieval-Augmented Generation (RAG) scenario, use `CQL.cosineSimilarity` to enhance the context of a user query for the LLM. First, compute the vector embedding of the user query and use it to find related incidents. + +::: code-group +```Java [Java] +// Compute embedding for user question +var query = CQL.val( + "Any incidents with solar inverters this month? How were they resolved?"); +var embedding = CQL.vectorEmbedding(query, TextType.QUERY, "SAP_GXY.20250407"); + +// Compute similarity between user question and incident embeddings +var similarity = CQL.cosineSimilarity(CQL.get(Incidents.EMBEDDING), embedding); + +// Find Incidents related to user question ordered by relevance +Select.from(INCIDENTS) + .columns(i -> similarity.times(100).as("relevance"), + i -> i.ID(), i -> i.title(), i -> i.summary(), i -> i.date()) + .where(i -> similarity.gt(0.75)) + .orderBy(i -> i.get("relevance").desc()); +``` + +```js [Node.js] +const response = await new AzureOpenAiEmbeddingClient( + 'text-embedding-3-small' +).run({ + input: 'Any incidents with solar inverters this month? How were they resolved?' +}); + +const questionEmbedding = response.getEmbedding(); +let similarIncidents = await SELECT.from('Incidents') + .where`cosine_similarity(embedding, to_real_vector(${questionEmbedding})) > 0.75`; +``` +::: + diff --git a/guides/extensibility/customization.md b/guides/extensibility/customization.md index c370614dd..5eb2f8951 100644 --- a/guides/extensibility/customization.md +++ b/guides/extensibility/customization.md @@ -1039,7 +1039,7 @@ In case something unexpected happens, set the variable `DEBUG=cli` in your shell ::: code-group -```sh [Mac/Linux] +```sh [macOS/Linux] export DEBUG="cli" ``` diff --git a/guides/multitenancy/index.md b/guides/multitenancy/index.md index bd59752d5..5d0bbb6c1 100644 --- a/guides/multitenancy/index.md +++ b/guides/multitenancy/index.md @@ -817,7 +817,7 @@ The SAP HANA Tenant Management Service (TMS) v2 service provides direct support > - **Not suitable for existing applications** as there is **no migration from Service Manager** available yet. This will be provided as HANA tool later.
> There **won't be support for both Service Manager and TMS v2** together in one application. -[For more information, see the SAP HANA documentation](https://help.sap.com/docs/hana-cloud/sap-hana-cloud-multitenancy-guide-internal/introducing-sap-hana-cloud-multitenancy){.learn-more} +[For more information, see the SAP HANA documentation](https://help.sap.com/docs/hana-cloud/sap-hana-cloud-multitenancy/introducing-sap-hana-cloud-multitenancy){.learn-more} [Find the TMS v2 API on the SAP Business Accelerator Hub](https://api.sap.com/api/TenantAPI/overview){.learn-more} #### Configure MTXS for Tenant Management Service @@ -965,7 +965,7 @@ so clustering the upgrade by database does not work properly. ## SaaS Dependencies {#saas-dependencies} Some of the xsuaa-based services your application consumes need to be registered as _reuse services_ to work in multitenant environments. This holds true for the usage of both the SaaS Registry service and the Subscription Manager Service (SMS). -CAP Java as well as `@sap/cds-mtxs`, each offer an easy way to integrate these dependencies. They support some services out of the box and also provide a simple API for applications. Most notably, you need such dependencies for the following SAP BTP services: [Audit Log](https://discovery-center.cloud.sap/serviceCatalog/audit-log-service), [Event Mesh](https://discovery-center.cloud.sap/serviceCatalog/event-mesh), [Destination](https://discovery-center.cloud.sap/serviceCatalog/destination), [HTML5 Application Repository](https://discovery-center.cloud.sap/serviceCatalog/html5-application-repository-service), and [Cloud Portal](https://discovery-center.cloud.sap/serviceCatalog/cloud-portal-service). +CAP Java as well as `@sap/cds-mtxs`, each offer an easy way to integrate these dependencies. They support some services out of the box and also provide a simple API for applications. Most notably, you need such dependencies for the following SAP BTP services: [Audit Log](https://discovery-center.cloud.sap/serviceCatalog/audit-log-service), [Event Mesh](https://discovery-center.cloud.sap/serviceCatalog/event-mesh), [Destination](https://discovery-center.cloud.sap/serviceCatalog/destination-service), [HTML5 Application Repository](https://discovery-center.cloud.sap/serviceCatalog/html5-application-repository-service), and [Cloud Portal](https://discovery-center.cloud.sap/serviceCatalog/cloud-portal-service). For CAP Java, all these services are supported natively and SaaS dependencies are automatically created if such a service instance is bound to the CAP Java application, that is, the `srv` module. diff --git a/guides/services/consuming-services.md b/guides/services/consuming-services.md index 654bd2a74..39872356b 100644 --- a/guides/services/consuming-services.md +++ b/guides/services/consuming-services.md @@ -103,7 +103,7 @@ The export-import cycle is the way to go for now. It is under investigation to i ::: code-group -```sh [Mac/Linux] +```sh [macOS/Linux] cds compile srv -s OrdersService -2 edmx > OrdersService.edmx ``` @@ -750,7 +750,7 @@ service RiskService { } ``` -#### Extend a Remote by a Local Service +#### Extend a Remote by a Local Service You can augment a projection with a new association, if the required fields for the on condition are present in the remote service. The use of managed associations isn't possible, because this requires to create new fields in the remote service. @@ -864,7 +864,7 @@ Otherwise, you need to select the source item using that `where` block and take [See an example how to handle navigations in Java.](https://github.com/SAP-samples/cloud-cap-risk-management/blob/ext-service-s4hc-suppliers-ui-java/srv/src/main/java/com/sap/cap/riskmanagement/handler/RiskServiceHandler.java){.learn-more .java} ### Limitations and Feature Matrix -#### Required Implementations for Mashups +#### Required Implementations for Mashups You need additional logic, if remote entities are in the game. The following table shows what is required. "Local" is a database entity or a projection on a database entity. @@ -1027,7 +1027,7 @@ cds: ::: [Learn more about configuring destinations for Java.](../../java/cqn-services/remote-services){.learn-more} -#### Use Application Defined Destinations +#### Use Application Defined Destinations If you don't want to use SAP BTP destinations, you can also define destinations, which means the URL, authentication type, and additional configuration properties, in your application configuration or code. @@ -1064,9 +1064,9 @@ This is an example of a destination using basic authentication: } ``` -[Learn more about providing project configuration values.](./../../node.js/cds-env#project-specific-configurations){.learn-more} +[Learn more about providing project configuration values.](./../../node.js/cds-env#project-specific-configurations){.learn-more} -[See all the supported destination properties.](#destination-properties){.learn-more} +[See all the supported destination properties.](#destination-properties){.learn-more} ::: warning Warning: You should not put any sensitive information here! @@ -1133,7 +1133,7 @@ For the _configuration path_, you **must** use the underscore ("`_`") character There is no API to create a destination in Node.js programmatically. However, you can change the properties of a remote service before connecting to it, as shown in the previous example. -##### Configure Application Defined Destinations in Java +##### Configure Application Defined Destinations in Java Destinations are configured in Spring Boot's _application.yaml_ file. @@ -1239,7 +1239,7 @@ cds watch --profile hybrid If you are developing in the Business Application Studio and want to connect to an on-premise system, you will need to do so via Business Application Studio's built-in proxy, for which you need to add configuration in an `.env` file. See [Connecting to External Systems From the Business Application Studio](https://sap.github.io/cloud-sdk/docs/js/guides/bas) for more details. ::: -#### Run a Java Application with a Destination +#### Run a Java Application with a Destination Add a new profile `hybrid` to your _application.yaml_ file that configures the destination for the remote service. ::: code-group @@ -1406,13 +1406,13 @@ cds add xsuaa,destination,connectivity service: xsuaa service-plan: application path: ./xs-security.json - + - name: cpapp-destination type: org.cloudfoundry.managed-service parameters: service: destination service-plan: lite - + # Required for on-premise connectivity only - name: cpapp-connectivity type: org.cloudfoundry.managed-service @@ -1652,7 +1652,7 @@ The Node.js runtime supports `odata` as an alias for `odata-v4` as well. The following properties and authentication types are supported for *[application defined destinations](#use-application-defined-destinations)*: -#### Destination Properties +#### Destination Properties These destination properties are fully supported by both, the Java and the Node.js runtime. ::: tip diff --git a/java/cds-data.md b/java/cds-data.md index 4ff869296..3798486b1 100644 --- a/java/cds-data.md +++ b/java/cds-data.md @@ -328,58 +328,27 @@ On the database, this data is serialized to [JSON](https://www.json.org/)(1 Map data can be nested and may contain nested maps and lists, which are serialized to JSON objects and arrays, respectively. -## Vector Embeddings { #vector-embeddings } +## Vector Embeddings { #vector-embeddings } -In CDS [vector embeddings](../guides/databases/hana#vector-embeddings) are stored in elements of type `cds.Vector`: +In CDS [vector embeddings](../guides/databases/vector-embeddings) are stored in elements of type `cds.Vector`: -```cds -entity Books : cuid { // [!code focus] - title : String(111); - description : LargeString; // [!code focus] - embedding : Vector(1536); // vector space w/ 1536 dimensions // [!code focus] -} // [!code focus] -``` +CAP Java support the vector type on SAP HANA, as well as H2 and SQLite for local testing. On Postgres (beta) support for vectors requires the [pgvector](https://github.com/pgvector/pgvector) extension. -In CAP Java, vector embeddings are represented by the `CdsVector` type, which allows a unified handling of different vector representations such as `float[]` and `String`: +In CAP Java, vectors are represented by the `CdsVector` type, which allows a unified handling of different vector representations such as `float[]` and `String`: ```Java -// Vector embedding of text, for example, from SAP GenAI Hub or via LangChain4j -float[] embedding = embeddingModel.embed(bookDescription).content().vector(); +// Vector embedding of text via SAP Cloud SDK for AI +float[] embedding = embeddingModel.embedding( + new OpenAiEmbeddingRequest(List.of(text))).getEmbeddingVectors().get(0); CdsVector v1 = CdsVector.of(embedding); // float[] format -CdsVector v2 = CdsVector.of("[0.42, 0.73, 0.28, ...]"); // String format -``` - -You can use the functions, `CQL.cosineSimilarity` or `CQL.l2Distance` (Euclidean distance) in queries to compute the similarity or distance of embeddings in the vector space. To use vector embeddings in functions, wrap them using `CQL.vector`: - -```Java -CqnVector v = CQL.vector(embedding); - -CdsResult similarBooks = service.run(Select.from(BOOKS).where(b -> - CQL.cosineSimilarity(b.embedding(), v).gt(0.9)) -); ``` -You can also use parameters for vectors in queries: - -```Java -var similarity = CQL.cosineSimilarity(CQL.get(Books.EMBEDDING), CQL.param(0).type(VECTOR)); - -CqnSelect query = Select.from(BOOKS) - .columns(b -> b.title(), b -> similarity.as("similarity")) - .where(b -> b.ID().ne(bookId).and(similarity.gt(0.9))) - .orderBy(b -> b.get("similarity").desc()); - -Result similarBooks = db.run(query, CdsVector.of(embedding)); -``` - -In CDS QL queries, elements of type `cds.Vector` are not included in select _all_ queries. They must be explicitly added to the select list: - -```Java -CdsVector embedding = service.run(Select.from(BOOKS).byId(101) - .columns(b -> b.embedding())).single(Books.class).getEmbedding(); -``` +::: info +In CDS QL queries, elements of type `Vector` are excluded from the select list by default. +::: +CAP Java supports multiple [vector functions](./working-with-cql/query-api.md#vector-functions) that allow you to compute vector embeddings, similarity, and distance directly in the database. ## Data in CDS Query Language (CQL) diff --git a/java/developing-applications/building.md b/java/developing-applications/building.md index 05f5de196..5916fb860 100644 --- a/java/developing-applications/building.md +++ b/java/developing-applications/building.md @@ -309,7 +309,7 @@ An example of a CAP application with OData V4 on Cloud Foundry environment: Use the following command line to create a project from scratch with the CDS Maven archetype: ::: code-group -```sh [Mac/Linux] +```sh [macOS/Linux] mvn archetype:generate -DarchetypeArtifactId=cds-services-archetype -DarchetypeGroupId=com.sap.cds -DarchetypeVersion=RELEASE ``` diff --git a/java/working-with-cql/query-api.md b/java/working-with-cql/query-api.md index 9765123f2..926f2303c 100644 --- a/java/working-with-cql/query-api.md +++ b/java/working-with-cql/query-api.md @@ -1640,6 +1640,72 @@ Scalar functions are values that are calculated from other values. This calculat See [`Concat`](#string-expressions) String Expression + +#### Vector Functions + +Vector functions allow you to compute similarity and distance of [vectors](../cds-data.md#vector-embeddings), as well as [vector embeddings](../../guides/databases/vector-embeddings) of text data directly in the database. + +##### Computing Vector Embeddings in SAP HANA + +CAP Java supports the [VECTOR_EMBEDDING](https://help.sap.com/docs/hana-cloud-database/sap-hana-cloud-sap-hana-database-sql-reference-guide/vector-embedding-function-vector) function via `CQL.vectorEmbedding` to generate vector embeddings from text data directly in SAP HANA. + +To automatically generate vector embeddings on write in the database, you can define a calculated element [on-write](../../cds/cdl#on-write) using the `vector_embedding` function: + +```cds +extend Incidents with { + @cds.api.ignore + embedding : cds.Vector(768) = vector_embedding( + 'title: ' || title || ', summary: ' || summary, + 'DOCUMENT', 'SAP_GXY.20250407') stored; +} +``` + +In Java queries, use the `CQL.vectorEmbedding` function to compute vector embeddings: + +```java +var userQuery = CQL.val(""" + Have we seen incidents with solar inverters this month, + and how were they resolved? + """); +var v = CQL.vectorEmbedding(userQuery, TextType.QUERY, "SAP_GXY.20250407"); +``` + +On H2 and SQLite, the `vectorEmbedding` function is emulated. You can also use local [ONNX](https://onnx.ai) embedding models, which can be added for local testing via [LangChain4j embeddings](https://github.com/langchain4j/langchain4j/tree/main/embeddings): + +```xml + + dev.langchain4j + langchain4j-embeddings-all-minilm-l6-v2-q + runtime + +``` + +##### Computing Vector Similarity and Distance + +You can use the functions, `CQL.cosineSimilarity`, and `CQL.l2Distance` (Euclidean distance) in queries to compute the similarity and distance of vectors. Distance functions are used in use cases such as finding similar items based on [vector embeddings](../../guides/databases/vector-embeddings), for example to improve the response of an LLM to a user query. To use vector embeddings in functions, wrap them using `CQL.vector`: + +```Java +CqnVector vec = CQL.vector(embedding); + +var similarIncidents = db.run(Select.from(INCIDENTS).where(i -> + CQL.cosineSimilarity(i.embedding(), vec).gt(0.75)) +); +``` + +You can also use parameters for vectors in queries: + +```Java +var similarity = CQL.cosineSimilarity( + CQL.get(Incidents.EMBEDDING), CQL.param(0).type(VECTOR)); + +var query = Select.from(INCIDENTS) + .columns(i -> i.title(), i -> similarity.times(100).as("similarity")) + .where(i -> similarity.gt(0.75)) + .orderBy(i -> i.get("similarity").desc()); + +Result similarIncidents = db.run(query, CdsVector.of(embedding)); +``` + #### Case-When-Then Expressions Use a case expression to compute a value based on the evaluation of conditions. The following query converts the stock of Books into a textual representation as 'stockLevel': diff --git a/node.js/authentication.md b/node.js/authentication.md index 0ac7f4146..4b8cc3db0 100644 --- a/node.js/authentication.md +++ b/node.js/authentication.md @@ -361,7 +361,7 @@ Please see [`@sap/xssec` documentation](https://www.npmjs.com/package/@sap/xssec #### XSUAA Fallback -To ease your migration from XSUAA-based to IAS-based authentication, the `ias` strategy automatically supports tokens issued by XSUAA when you provide the necessary credentials at `cds.env.requires.xsuaa.credentials`. +To ease your migration from XSUAA-based to IAS-based authentication, the `ias` strategy automatically supports tokens issued by XSUAA when you provide the necessary credentials at `cds.env.requires.xsuaa.credentials`. For standard bindings, add `xsuaa` to the list of required services as follows: @@ -477,11 +477,11 @@ The following steps assume you've set up the [**Cloud Foundry Command Line Inter If you don't know the API endpoint, refer to [Regions and API Endpoints Available for the Cloud Foundry Environment](https://help.sap.com/products/BTP/65de2977205c403bbc107264b8eccf4b/350356d1dc314d3199dca15bd2ab9b0e.html#loiof344a57233d34199b2123b9620d0bb41). 2. Go to the project you have created in [Getting started in a Nutshell](../get-started/bookshop). - + #### Configure the Application 1. Configure your app for XSUAA-based authentication if not done yet: - + ```sh cds add xsuaa --for hybrid ``` @@ -602,7 +602,7 @@ The resulting JWT token is sent to the application where it's used to enforce au 3. In your project folder run: ::: code-group - ```sh [Mac/Linux] + ```sh [macOS/Linux] cds bind --exec -- npm start --prefix app/router ``` ```cmd [Windows] @@ -691,7 +691,7 @@ The login fails pointing to the correct OAuth configuration URL that is expected cds add ams npm install ``` - + This command installs `ams` and `ias` plugins, adds the required dependencies to `package.json` and updates `mta.yaml`. Learn more about [**Adding AMS Support**](../guides/security/cap-users#adding-ams-support) and [**Adding IAS**](../guides/security/authentication#adding-ias).{.learn-more} @@ -741,13 +741,13 @@ The login fails pointing to the correct OAuth configuration URL that is expected ``` #### Deploy the Application - + 1. Log in to Cloud Foundry: ```sh cf l -a ``` If you don't know the API endpoint, refer to [Regions and API Endpoints Available for the Cloud Foundry Environment](https://help.sap.com/products/BTP/65de2977205c403bbc107264b8eccf4b/350356d1dc314d3199dca15bd2ab9b0e.html#loiof344a57233d34199b2123b9620d0bb41). - + 2. Pack and deploy the application: ```sh @@ -757,13 +757,13 @@ The login fails pointing to the correct OAuth configuration URL that is expected #### Assign Policies in the Administrative Console 1. Log in to your Administrative Console for IAS and go to `Applications & Resources`. - + [Learn more about the Administrative Console for IAS.](/@external/guides/security/authentication#ias-admin){.learn-more} 2. Assign policies to IAS users or create custom policies, see [Cloud Deployment](../guides/security/cap-users#ams-deployment). #### Start Hybrid Testing - + 1. Bind your local application to the Identity Service Instance: ```sh @@ -798,7 +798,7 @@ The login fails pointing to the correct OAuth configuration URL that is expected 2. In your project folder run: ::: code-group - ```sh [Mac/Linux] + ```sh [macOS/Linux] cds bind --exec -- npm start --prefix app/router ``` ```cmd [Windows] diff --git a/node.js/cds-env.md b/node.js/cds-env.md index 959590076..1e1bb3301 100644 --- a/node.js/cds-env.md +++ b/node.js/cds-env.md @@ -406,7 +406,7 @@ cds run --profile my-custom-profile or ::: code-group -```sh [Mac/Linux] +```sh [macOS/Linux] CDS_ENV=my-custom-profile cds run ``` ```cmd [Windows] diff --git a/node.js/core-services.md b/node.js/core-services.md index 686de8e51..e0df43343 100644 --- a/node.js/core-services.md +++ b/node.js/core-services.md @@ -399,6 +399,7 @@ var srv.options : { //> from cds.requires config ### . entities {.property alt="The following documentation on actions also applies to entities. "} ### . events {.property alt="The following documentation on actions also applies to events. "} ### . actions {.property} +###### srv-entities ```tsx var srv.entities/events/actions : Iterable <{ @@ -406,7 +407,7 @@ var srv.entities/events/actions : Iterable <{ }> ``` -These properties provide convenient access to the CSN definitions of the *entities*, *events* and *actions* (incl. *functions*) exposed by this service. They return instances of [`LinkedDefinitions`](cds-reflect#iterable) which are iterable dictionaries of CSN definitions, which you can use in all of these ways: +These properties provide convenient access to the CSN definitions of the *entities*, *events* and *actions* (incl. *functions*) exposed by this service. They return instances of [`LinkedDefinitions`](cds-reflect#iterable) which you can use in all of these ways: ```js // Assumed `this` is an instance of cds.Service @@ -418,21 +419,21 @@ for (let d of this.entities) //... d is a CSN definition #### Similarity _and_ difference to `cds.entities` -These properties are very similar in nature and behavior to [`cds.entities`](cds-facade#cds-entities), which is a shortcut to `cds.model.entities()` to `cds.model.entities`, which in turn is implemented in [`cds.linked.entities`](cds-reflect#entities). However, note this difference: +These properties are very similar in nature and behavior to [`cds.entities`](cds-facade#cds-entities), which is a sortcut to [`cds.model.entities`](cds-reflect#entities). However, note this difference: -Both of these work with `cds.entities`: +While both of these work with [`cds.entities`](cds-facade#cds-entities): ```js const { 'some.namespace.Books':Books, ... } = cds.entities //> works const { Books, Authors } = cds.entities ('some.namespace') //> works ``` -Only the first one works with `srv.entities`: +Only the first one works with [`srv.entities`](#srv-entities): ```js const { Books, Authors } = srv.entities //> works const { Books, Authors } = srv.entities ('some.namespace') //> FAILS! [!code --] ``` - While [`cds.entities`](cds-facade#cds-entities) is sort of a chimera, which can be used both **as a getter** returning all definitions, and **as a function** which accepts a namespace to fetch definitions for, the latter doesn't make sense in the context of a service, as the namespace is already implied by the service's name. + Reason is that `cds.entities` is sort of a chimera, which can be used both **as a getter** returning _all_ definitions, and **as a function** which accepts a namespace to fetch definitions for. The latter doesn't make sense in the context of a service, as the namespace is already implied by the service's name. ### srv. init() {.method} @@ -518,30 +519,29 @@ class BooksService extends cds.ApplicationService { **Methods `.on`, `.before`, `.after`** refer to corresponding *phases* during request processing: -- **`.on`** handlers actually fulfill requests, for example, by reading/writing data from/to databases -- **`.before`** handlers run before the `.on` handlers, frequently for validating inbound data -- **`.after`** handlers run after the `.on` handlers, frequently to enrich outbound data +- **`.on`** handlers _fulfill_ requests, for example, by reading/writing data from/to databases +- **`.before`** handlers run before the `.on` handlers, e.g., for validating inbound data +- **`.after`** handlers run after the `.on` handlers, e.g., to enrich outbound data **Argument `event`** can be one of: -- `'CREATE'`, `'READ'`, `'UPDATE'`, `'UPSERT'`,`'DELETE'` -- `'INSERT'`,`'SELECT'` → as aliases for: `'CREATE'`,`'READ'` -- `'POST'`,`'GET'`,`'PUT'`,`'PATCH'` → as aliases for: `'CREATE'`,`'READ'`,`'UPDATE'` -- `'each'` → convenience feature to register `.after` `'READ'` handler that runs for each individual result entry -- Any other string name of a custom action or function – for example,, `'submitOrder'` -- An `array` of the above to register the given handler for multiple events -- The string `'*'` to register the given handler for *all* potential events -- The string `'error'` to register an error handler for *all* potential events +- String `CREATE`, `READ`, `UPDATE`, `UPSERT`, `DELETE` +- String `SELECT`, `INSERT` → aliases for: `READ` and `CREATE` +- String `GET`, `PUT`, `POST`, `PATCH` → aliases for: `READ`, `CREATE`, `UPDATE` +- String `each` → shorthand for `.after` `READ` handler ran for _each_ result entry +- String `error` to register an error handler for *all* potential events +- A name of a custom action or function – for example, `submitOrder` **Argument `entity`** can be one of: -- A `CSN definition` of an entity served by this service → as obtained from [`this.entities`](#entities) -- A `string` matching the name of an entity served by this service → see [draft support](./fiori#draft-support) -- A `path` navigating from a served entity to associated ones → for example, `'Books/author'` -- An `array` of the above to register the given handler for multiple entities / paths -- The string `'*'` to register the given handler for *all* potential entities / paths +- A `CSN definition` of an entity served by this service → i.e., from [`this.entities`](#entities) +- A `string` corresponding to the _name_ of an entity served by this service +- A `path` navigating from a served entity to associated ones → e.g., `Books/author` +**Multiple `events` or `entities`** – for both parameters, you can also specify: +- An `array` of the above to register a handler for _multiple_ events or entities +- String `*` to register a handler for _all_ potential events or entities. ::: tip Best Practices diff --git a/package-lock.json b/package-lock.json index a662cc322..eb75496e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@capire/docs", - "version": "2026.4.0", + "version": "2026.4.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@capire/docs", - "version": "2026.4.0", + "version": "2026.4.1", "license": "SEE LICENSE IN LICENSE", "devDependencies": { "@cap-js/cds-typer": "^0", diff --git a/package.json b/package.json index bbbd64152..a4a5f075f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@capire/docs", - "version": "2026.4.0", + "version": "2026.4.1", "description": "Capire on VitePress", "type": "module", "scripts": { diff --git a/tools/cds-bind.md b/tools/cds-bind.md index 3809694a7..a1086df92 100644 --- a/tools/cds-bind.md +++ b/tools/cds-bind.md @@ -289,7 +289,7 @@ With `cds bind` you avoid storing credentials on your hard disk. If you need to For example, you can run the App Router from an `approuter` child directory: ::: code-group -```sh [Mac/Linux] +```sh [macOS/Linux] cds bind --exec -- npm start --prefix approuter ``` ```cmd [Windows] @@ -303,7 +303,7 @@ cds bind --exec '--' npm start --prefix approuter This works by constructing a `VCAP_SERVICES` environment variable. You can output the content of this variable as follows: ::: code-group -```sh [Mac/Linux] +```sh [macOS/Linux] cds bind --exec -- node -e 'console.log(process.env.VCAP_SERVICES)' ``` ```cmd [Windows]