diff --git a/docs/platform/3.core/7.apps.md b/docs/platform/3.core/7.apps.md index a68e5c220..d23ee7ff5 100644 --- a/docs/platform/3.core/7.apps.md +++ b/docs/platform/3.core/7.apps.md @@ -4,7 +4,8 @@ DIAL-native applications adhere to the [unified protocol](/docs/platform/3.core/0.about-core.md#unified-api) of DIAL, a single protocol for all applications and models deployed in a specific DIAL instance. DIAL-native apps can be enabled in DIAL and used directly (via API or UI) or as building blocks in other apps. -> Refer to [Agentic Platform](/docs/platform/0.architecture-and-concepts/4.agentic-platform.md) to learn more about agents in DIAL. +> * Refer to [Agentic Platform](/docs/platform/0.architecture-and-concepts/4.agentic-platform.md) to learn more about agents in DIAL. +> * Refer to [Custom Apps](/docs/tutorials/1.developers/4.apps-development/6.develop-custom-apps-overview.md) to learn about custom applications in DIAL. ## Schema-rich Applications @@ -14,21 +15,24 @@ Schema-rich applications are defined by a JSON schema that conforms to the main Users can create instances of schema-rich applications with different properties via [DIAL Core API](https://dialx.ai/dial_api#tag/Applications/operation/saveCustomApplication). There is a method in [DIAL SDK](https://github.com/epam/ai-dial-sdk) (`application_properties = await request.request_dial_application_properties()`) that returns application properties with a configuration request to DIAL Core. -Unlike [apps without schemas](#applications-without-schemas), where business logic properties are embedded in the application code or container environment and are difficult to change, schema-rich applications provide greater flexibility. +**Application Runners** are used to run schema-rich applications. An application runner can be seen as an application factory that allows end-users create individual logical instances each with its own configuration. An application runner definition includes a configuration schema that enforces data structure persisted for each instance. It is worth noting that Quick Apps, Code Apps and Mind Maps are application runners available in DIAL platform out of the box. DIAL admins can add and manage runners in the [DIAL Admin application](/docs/tutorials/3.admin/builders-application-runners.md). + +Unlike [apps without schemas](#standalone-applications), where business logic properties are embedded in the application code or container environment and are difficult to change, schema-rich applications provide greater flexibility. ### Application Types Schema-rich applications are usually associated with a specific **Application Type** - as schema-rich template for creating custom implementations of specific application types. -The [meta schema](https://github.com/epam/ai-dial-core/blob/development/config/src/main/resources/custom-application-schemas/schema) determines a possible structure of an application type schema, which is used to determine properties structure of specific applications of this type: +The [meta schema](https://github.com/epam/ai-dial-core/blob/development/config/src/main/resources/custom-application-schemas/schema.json) determines a possible structure of an application type schema, which is used to determine properties structure of specific applications of this type: ![](./img/schema-rich-apps.svg) -One of the main advantages of application types, is that they allow adding [application wizards](/docs/tutorials/0.user-guide.md#application-builder) on UI for end-users to create/edit apps in a low and no-code manner. +One of the main advantages of application types, is that they allow adding [application wizards](/docs/tutorials/0.user-guide.md#application-builder) on UI for end-users to create/edit apps in a low and no-code manner via a UI editor. + +Out of the box, DIAL includes application types such as Quick app, Code app and Mind Map. Users of DIAL Chat can use UI wizards to create custom instances of these application types. -:cloud: DIAL SaaS edition includes application types such as Quick app, Code app and Mind Map. Users of DIAL Chat can use UI wizards to create apps of these types. +:floppy_disk: In self-hosted deployments of DIAL, you can add new application types, featuring custom application UI (`applicationTypeViewerUrl`) and wizards (`applicationTypeEditorUrl`) and enabling end-users to create applications of that type. Refer to [Custom Apps](/docs/tutorials/1.developers/4.apps-development/6.develop-custom-apps-overview.md) to learn about custom applications in DIAL. -:floppy_disk: In self-hosted deployments of DIAL, you can add new application types, featuring custom application UI (`applicationTypeViewerUrl`) and wizards (`applicationTypeEditorUrl`) and enabling end-users to create applications of that type. #### Quick Apps @@ -78,9 +82,9 @@ Mind Map enables users to explore information through an interactive knowledge g > - Watch [Demo Video](/docs/video%20demos/2.Applications/mindmap-studio.md) to see [DIAL Mind Map Studio](/docs/tutorials/4.mind-map.md) in action. > - Refer to solutions to see implementations in specific industries: [Caspase-2 Article Visualization](https://dialx.ai/solutions/scientific-literature-knowledge-graph), [OMICS AI Assistant](https://dialx.ai/solutions/omics-data-assistant), [Visualization of Cinematic Universe](https://dialx.ai/solutions/lotr-universe-case) -## Applications without Schemas +## Standalone Applications -Applications without schemas are not tied to any specific application type. When enabling such an app, you must explicitly specify (in the [API PUT request](/docs/tutorials/1.developers/4.apps-development/3.enable-app.md#using-api-1) standard parameters of the application and available endpoints the application offers. Properties that define the logic and behavior of the application are part of the application code and the container it runs in, meaning they cannot be modified through the DIAL Core API, contrary to [schema-rich applications](#schema-rich-applications). For example, to enable two apps without schemas, you may need to launch two containers, whereas for schema-rich apps, you can make just two API calls. +Standalone applications are not tied to any specific application type nor their structure is defined by a JSON schema. When enabling such an app, you must explicitly specify (in the [API PUT request](/docs/tutorials/1.developers/4.apps-development/3.enable-app.md#using-api-1)) standard parameters of the application and available endpoints the application offers. Properties that define the logic and behavior of the application are part of the application code and the container it runs in, meaning they cannot be modified through the DIAL Core API, contrary to [schema-rich applications](#schema-rich-applications). For example, to enable two apps without schemas, you may need to launch two containers, whereas for schema-rich apps, you can make just two API calls. ## Create Applications @@ -111,7 +115,7 @@ Ready and deployed applications must be enabled to use them in DIAL. **Prerequisites for enablement of schema-rich applications:** - A schema of the application type must be included in the DIAL Core configuration. -- Having a running container for each application type. +- An application runner container must be running for each application type. - These containers must be accessible via the endpoints specified in the JSON schema for their respective application types. **Prerequisites for enablement of for applications without schemas:** diff --git a/docs/tutorials/1.developers/4.apps-development/6.develop-custom-apps-overview.md b/docs/tutorials/1.developers/4.apps-development/6.develop-custom-apps-overview.md new file mode 100644 index 000000000..f77ebf622 --- /dev/null +++ b/docs/tutorials/1.developers/4.apps-development/6.develop-custom-apps-overview.md @@ -0,0 +1,80 @@ +# Developing Custom DIAL Applications + +## Introduction + +Whenever the no-code and low-code DIAL extensibility features such as [Quick Apps](/docs/platform/3.core/7.apps.md#quick-apps), [Code Apps](/docs/platform/3.core/7.apps.md#code-apps) or [Mind Maps](/docs/platform/3.core/7.apps.md#mind-maps) are not sufficient to satisfy the needs of a particular use case, a custom application can be developed in any technology stack and exposed through the DIAL platform. From an end-user perspective, such applications will be accessible through the [DIAL Marketplace](/docs/platform/4.chat/1.marketplace.md) similarly to models and standard platform applications. + +There are two forms of custom applications in DIAL: + +- [Custom Standalone Application](/docs/tutorials/1.developers/4.apps-development/7.develop-single-app.md) – exists as a single logical instance in the platform. Settings and access permissions are managed centrally by an administrator. For example, it can be a standalone document summarization tool, where a platform administrator defines summarization options and quotas. +- [Custom Application Runner](/docs/tutorials/1.developers/4.apps-development/8.develop-app-runner.md) – an application factory that allows end-users create individual logical instances each with its own configuration. For example, a custom RAG application runner may allow an end user to configure a personalized RAG agent by connecting it to chosen data sources, such as internal knowledge bases, document repositories, or external APIs, and then share it with other users and groups. An application runner definition includes a configuration schema that enforces data structure persisted for each instance. It is worth noting that Quick Apps, Code Apps and Mind Maps are application runners available in DIAL platform out of the box. + +Regardless of the form, a custom DIAL application may consist of three separate components – Backend, Viewer UI and Editor UI. The purpose and necessity of each one is indicated in the table below. + +|Component|Custom Standalone Application|Custom Application Runner| +|---------|-----------------------------|-------------------------| +|Backend|Implements the business logic.
**Required**|Implements the business logic.
**Required**| +|Viewer UI|An alternative end-user UI (is needed when the default chat interface is not sufficient).
**Optional**|An alternative end-user UI (is needed when the default chat interface is not sufficient).
**Optional**| +|Editor UI|A UI screen for managing application settings from the [DIAL Admin](/docs/tutorials/3.admin/home.md) application.
**Optional**|A UI screen for configuring application settings when creating or updating a logical application instance.
**Required**| + +There are a few typical sets of components to be developed for a custom DIAL application depending on the use case: + +- Backend only – when end-users of a Custom Application are supposed to interact with the application through the default chat interface and there are no application settings to be managed by the DIAL administrator. +- Backend and Admin UI – when a Custom Application has some settings to be managed by the DIAL administrator or you are building a Custom Application Runner, while there is no need to have a custom end-user UI. +- Backend, Admin UI, and End-user UI – when a non-standard end-user UI is needed, and the Custom Application has some settings to be managed by the DIAL administrator, or you are building a Custom Application Runner. + +Here is an example of a custom Editor UI accessible through the DIAL Admin for a standalone application: + +![](../img/overview1.png) + +The screenshots below illustrate a typical user flow for an Application Runner, using Mind Maps as an example where both the Viewer and Editor UIs are customized: + +1. All Application Runners that the current user has access to, are available in the “Add App” dropdown in the [user’s Workspace](/docs/tutorials/0.user-guide.md#my-workspace). + + ![](../img/overview2.png) + +2. After populating the General Info tab and proceeding to the App Settings, a custom Editor UI will appear. + + ![](../img/overview3.png) + + ![](../img/overview4.png) + +3. A custom Viewer UI can be seen when a user opens a logical application instance created this way from his DIAL Workspace or Marketplace. + + ![](../img/overview5.png) + +The diagram below shows the most complete logical structure of a Custom Standalone Application: + +![](../img/overview6.png) + +And the following diagram – the most complete structure of a Custom Application Runner: + +![](../img/overview7.png) + +## Backend + +A backend service that implements the necessary business logic and exposes either a standard Open AI chat completion endpoint, or a set of custom API endpoints, or both. Can be implemented using any technology stack, but for simple cases, when only a chat completion endpoint needs to be exposed, it is recommended to use [DIAL SDK for Python](https://github.com/epam/ai-dial-sdk). + +For Application Runners, this SDK provides an easy way of getting configuration details about the calling instance (see `request_dial_application_properties` method). These properties are usually managed via a custom Editor UI and are validated by DIAL Core against the configuration schema provided for the application runner. + +The service doesn’t have to validate tokens, since authorization is handled by DIAL Core, which serves as an API gateway in this scenario. When forwarding a call to a backend endpoint, DIAL Core passes a [per-request key](/docs/platform/3.core/3.per-request-keys.md) in the `“api-key”` header instead of the original authorization header, which can later be used by the backend logic to call DIAL Core back for accessing models or other applications. + +## UI + +Both UI pieces are developed and hosted as standalone applications, but when registered in the platform, they get embedded as IFRAME into respective DIAL UI applications, providing integrated experience. + +There are no limitations on the technology stack, but it is recommended to use the [Next.js solution template](https://github.com/epam/ai-dial/tree/main/dial-samples/common-ui-app), since it already has all necessary boilerplate code including the authentication mechanism. + +As shown on the diagram above, each of the custom UI applications is supposed to be hosted on a separate subdomain. In order to issue a JWT token for accessing endpoints exposed by DIAL Core, each custom UI application must have its own client registration with the Identity Provider. Separate client registrations allow for more granular control over permissions and scopes, enabling each application to request only the access it requires, which aligns with the principle of least privilege. This separation also simplifies auditing and monitoring, as it becomes easier to trace and identify which application is responsible for specific API calls or security events. + +Communication with the corresponding backend service is always made through DIAL Core. When the backend exposes custom API endpoints, the corresponding [routes](https://github.com/epam/ai-dial-core/blob/development/docs/dynamic-settings/routes.md) must be configured in the DIAL Core configuration to make them reachable for the UI application. + +For Editor UI of an Application Runner it is recommended to save instance configuration in the application object – data stored in `application_properties` attribute of an application instance is validated against the schema provided for the corresponding Application Runner, persisted, and then can be read by the backend depending on the calling instance. + +## Deployment + +There are no limitations of how and where the custom components are deployed, the only requirement is that there must be network connectivity between DIAL Core and the backend service, as well as between UI applications and DIAL Core. Any communication between components is made only through API. +Here are the links to sample configuration guides for different types of applications: + +- [Standalone application](/docs/tutorials/1.developers/4.apps-development/7.develop-single-app.md) +- [Application runner](/docs/tutorials/1.developers/4.apps-development/8.develop-app-runner.md) diff --git a/docs/tutorials/1.developers/4.apps-development/7.develop-single-app.md b/docs/tutorials/1.developers/4.apps-development/7.develop-single-app.md new file mode 100644 index 000000000..73d1e410e --- /dev/null +++ b/docs/tutorials/1.developers/4.apps-development/7.develop-single-app.md @@ -0,0 +1,146 @@ +# Developing Chat-Based Standalone Custom Applications + +## Introduction + +The easiest way to develop a custom application for DIAL, is using the [sample project](https://github.com/epam/ai-dial/blob/main/dial-samples/standalone-app-chat-ui/backend/README.md) as a baseline. The instruction below shows how to set up a local DIAL environment as well as register and run the sample project. + +Refer to [Develop Custom Applications](/docs/tutorials/1.developers/4.apps-development/6.develop-custom-apps-overview.md) for a high-level information about application runners. + +> **Note**: This tutorial uses a Docker-deployed Keycloak instance as the Identity Provider for demonstration purposes. In your organization, you can apply the same configuration principles to your corporate Identity Provider, using the Keycloak setup here as a reference. + +## Running Sample Project + +1. Clone the project containing all templates and Docker Compose scripts from the [ai-dial GitHub repository](https://github.com/epam/ai-dial). +2. Run the base Docker Compose file. + + 1. Go to the `/dial-docker-compose-advanced` folder of the ai-dial GitHub project cloned in the previous step. + 2. Run the following command to launch a local DIAL environment with all components necessary for custom application development and testing: + + ```bash + docker compose -f docker-compose-base.yml up + ``` + + +3. Create a client in Keycloak for the custom Admin UI: + + 1. Open http://localhost:8900 and log in using “admin” as username and password. It is recommended to open this and all further “localhost” references in an incognito browser window. + 2. Click **Manage realms** in the left panel and select the **dial** realm in the realms list. + 3. Click **Clients** in the left panel and click **Create client**. + 4. Set **Client ID** and **Name** to “custom-app-admin” and click **Next**. + + ![](../img/custom-apps1.png) + + 5. Turn on the **Client authentication** toggle and click **Next**. + + ![](../img/custom-apps2.png) + + 6. Set **Root URL** and **Home URL** to `http://localhost:3301` and **Valid redirect URIs** to `http://localhost:3301/*`, then click **Save**. + + ![](../img/custom-apps3.png) + + 7. Go to **Client scopes** tab in the client properties page and click **Add client scope**. + + ![](../img/custom-apps4.png) + + 8. Select scopes “profile”, “basic” “email”, and “offline_access”, then click **Add** and select **Default**. + + ![](../img/custom-apps5.png) + +4. Update the custom applications Docker Compose file with client secrets + + 1. Go to the **Credentials** tab for the “custom-app-admin” client properties in Keycloak. + 2. Click the **Copy to clipboard** icon next to the Client Secret input field. + + ![](../img/custom-apps6.png) + + 3. Paste the copied value to `AUTH_KEYCLOAK_SECRET` variable in the Docker Compose file `/dial-samples/standalone-app-chat-ui/docker-compose.yml` from the cloned GitHub project. + +5. Create a new application in DIAL Admin: + 1. Open http://localhost:3102 and log in using “dial-admin” as username and “dial” as password. + 2. In the **Entities** section in the left panel, open **Applications** and click **Create** in the right upper corner. + 3. Set the **ID** to “custom-app” and the **Display Name** to “Custom Application”. + 4. Set **Completion endpoint** to `http://host.docker.internal:3302/openai/deployments/custom-app/chat/completions` and click **Create**. + + > **Note**: Please note that the “custom-app” section of this URL must be equal to the name passed to a call to “add_chat_completion” method in the underlying DIAL backend application. If you use a different name in your backend, the URL from above must be updated accordingly. + + ![](../img/custom-apps7.png) + +6. Configure new application: + + 1. Set **Editor URL** to `http://localhost:3301`. + 2. Go to the **Roles** tab and set the **Make available to specific roles** toggle **off**. + 3. Go to the **App Routes** tab and click **Add**. + 4. Set **Display Name** to “API” and click **Create**. + 5. Set **Path** to “/api/v1/.*”, toggle **Rewrite path** on, select GET, POST, and PUT in the Methods field. + 6. Set **Upstream Endpoint** to `http://host.docker.internal:3302`. + 7. Select both “Read” and “Write” in the **Permissions** field. + + ![](../img/custom-apps8.png) + + 8. Go to the **Roles** sub-tab within the **App Route** properties and toggle **Inherit Application Roles** on, then click **Save**. + +7. Make changes in the sample UI application code to make it compatible with the custom API exposed by the backend: + + 1. Open the folder `/dial-samples/common-ui-app` in an IDE. + 2. Go to file `/apps/dial-custom-ui-admin/src/app/[lang]/settings/actions.ts` + 3. Comment out the original return statements in both functions and uncomment the following lines of code: + + ```typescipt + return await configApi.getConfig(token); //In getCofing() + return await configApi.setConfig(config, token); //In saveConfig() + ``` + + > **Tip**: This change makes the custom admin application call the custom backend API that is intended for storing application settings for this custom standalone application. + +8. Run Docker Compose for the custom application runner with a chat end-user interface: + + 1. Go to the `/dial-samples/standalone-app-chat-ui` folder of the cloned GitHub project. + 2. Run Docker Compose: + + ```bash + docker compose -f docker-compose.yml up --build + ``` + +9. Configure the application setting in the DIAL Admin: + + 1. Get back to the DIAL Admin application at http://localhost:3102. + 2. Go to **Entities/Applications** and select **Custom Application** in the table. + 3. In the **Properties** page for the “Custom Application” switch to the **Parameters** tab. + 4. If you see just the “Login” link in the center of the tab – click it and log in with “dial-admin” as a user and “dial” as a password. + + > **Note**: Now you should see a sample custom configuration page with a single input field called “Number”. In this sample application, this property controls how many times your input will be repeated in the end-user chat in response. The configuration page is served by the URL specified in the “Editor URL” property of the application type. + + 5. Change the default value of 1 with any other integer number (e.g. 5), then click **Save**. +10. Access the newly-created application named “Custom Application” in the DIAL Marketplace: + 1. Open http://localhost:3100 + 2. Log in using “dial” as username and password. + 3. Click the **Marketplace** icon from the left panel. + + ![](../img/custom-apps9.png) + + 4. Click on the application named “Custom Application” and then – the **Use Application** button. Now you should see a chat interface, where each of your input messages will be repeated as many times in response, as was specified when configuring the application. + + ![](../img/custom-apps10.png) + +11. Check that the configuration can be changed at any time: + + 1. Get back to the DIAL Admin application at http://localhost:3102 + 2. Go to **Entities/Applications** and select “Custom Application” in the table. + 3. In the **Properties** page for the “Custom Application” switch to the **Parameters** tab. + 4. Change the number to any other value and check if it affects the behavior of the end-user custom application (see step 8). + +## Developing a Real-World Application + +A real-world standalone custom application can be developed using such sample applications as templates. + +* For a scenario with the standard chat interface for end-users (like demonstrated in this tutorial), the dial-custom-ui-client project of the common-ui-app sample can be ignored and removed. +* The Settings page from dial-custom-ui-admin can be changed however needed to satisfy the configurability requirements of your target use case. +* The backend for the scenario with the standard chat interface is using [DIAL SDK](https://github.com/epam/ai-dial-sdk) to implement the chat completion endpoint. There you can find more information and examples of how to build custom chat completion backends. +* The purpose of each environment variable used by the custom application is documented in the README.md of the corresponding project: + - [common-ui-app](https://github.com/epam/ai-dial/blob/main/dial-samples/common-ui-app/README.md) + - [standalone-app-chat-ui](https://github.com/epam/ai-dial/blob/main/dial-samples/standalone-app-chat-ui/backend/README.md) + - [app-runner-chat-ui](https://github.com/epam/ai-dial/blob/main/dial-samples/app-runner-chat-ui/backend/README.md) + + + + diff --git a/docs/tutorials/1.developers/4.apps-development/8.develop-app-runner.md b/docs/tutorials/1.developers/4.apps-development/8.develop-app-runner.md new file mode 100644 index 000000000..add80be67 --- /dev/null +++ b/docs/tutorials/1.developers/4.apps-development/8.develop-app-runner.md @@ -0,0 +1,121 @@ +# Developing Chat-Based Custom Application Runners + +## Introduction + +The easiest way to develop a custom application runner for DIAL, is using the [sample project](https://github.com/epam/ai-dial/blob/main/dial-samples/app-runner-chat-ui/backend/README.md) as a baseline. The instruction below shows how to set up a local DIAL environment as well as register and run the sample project. + +Refer to [Develop Custom Applications](/docs/tutorials/1.developers/4.apps-development/6.develop-custom-apps-overview.md) for a high-level information about application runners. + +> **Note**: This tutorial uses a Docker-deployed Keycloak instance as the Identity Provider for demonstration purposes. In your organization, you can apply the same configuration principles to your corporate Identity Provider, using the Keycloak setup here as a reference. + +## Running Sample Project + +1. Clone the project containing all templates and Docker Compose scripts from the [ai-dial GitHub repository](https://github.com/epam/ai-dial). +2. Add custom app URLs to the IFRAME allowed list for the DIAL Chat application + + Add the following two variables for the “chat” service in the `/dial-docker-compose-advanced/docker-compose-base.yml` + + ```yaml + ALLOWED_IFRAME_ORIGINS: http://localhost:3301 + ALLOWED_IFRAME_SOURCES: http://localhost:3301 + ``` + +3. Run the base Docker Compose file. + 1. Go to the `/dial-docker-compose-advanced` folder of the GitHub project cloned in step 1. + 2. Run the following command to launch a local DIAL environment with all components necessary for custom application development and testing: + + ```bash + docker compose -f docker-compose-base.yml up + ``` + +4. Create a client in Keycloak for the custom admin UI: + + 1. Open http://localhost:8900 and Log in using “admin” as username and password. It is recommended to open this and all further “localhost” references in an incognito browser window. + 2. Click **Manage Realms** in the left panel and click on the “dial” realm in the realms list. + 3. Click on **Clients** in the left panel and click **Create client**. + 4. Set **Client ID** and **Name** to “custom-app-admin” and click **Next**. + + ![](../img/custom-runner1.png) + 5. Turn on the **Client authentication** toggle and click **Next**. + + ![](../img/custom-runner2.png) + 6. Set **Root URL** and **Home URL** to `http://localhost:3301` and **Valid redirect URIs** to `http://localhost:3301/*`, then click **Save**. + + ![](../img/custom-runner3.png) + 7. Go to **Client scopes** tab in the client properties page and click **Add client scope**. + + ![](../img/custom-runner4.png) + 8. Select scopes “profile”, “basic” “email”, and “offline_access”, then click **Add** and select **Default**. + + ![](../img/custom-runner5.png) +5. Update the custom applications Docker Compose file with client secrets + 1. Go to the **Credentials** tab for the “custom-app-admin” client properties in Keycloak. + 2. Click the **Copy to clipboard** icon next to the Client Secret input field. + + ![](../img/custom-runner6.png) + 3. Paste the copied value to `AUTH_KEYCLOAK_SECRET` variable in the Docker Compose file `/dial-samples/app-runner-chat-ui/docker-compose.yml` from the cloned GitHub project. +6. Create a new application type in DIAL Admin: + 1. Open http://localhost:3102 and log in using “dial-admin” as username and “dial” as password. + 2. Expand the **Builders** section in the left panel and click on **Application Runners**. + 3. Click the **Create** button in the right upper corner. + 4. Set the **ID** to “https://dialx.ai/sample_application_schemas/custom_runner” (any valid URL is acceptable) and the **Display Name** to “Custom Runner”. When finished, click **Create**. + + ![](../img/custom-runner7.png) + 5. Make sure that the **Display Name** of the application type (“Custom Runner”) is equal to the value of the `DIAL_APPLICATION_NAME` variable from the Docker Compose file `/dial-samples/app-runner-chat-ui/docker-compose.yml`. Otherwise, the application won’t be loaded by the host DIAL Chat application. + 6. Set **Completion Endpoint** to “http://host.docker.internal:3302/openai/deployments/custom-app/chat/completions” and **Editor URL** to `http://localhost:3301`. When finished, click **Save**. + + > **Note**: Please note that the “custom-app” section of this URL must be equal to the name passed to a call to “add_chat_completion” method in the underlying DIAL backend application. If you use a different name in your backend, the URL from above must be updated accordingly. + + ![](../img/custom-runner8.png) + +7. Run Docker Compose for the custom application runner with a chat end-user interface: + + 1. Go to the `/dial-samples/app-runner-chat-ui` folder of the cloned GitHub repository + 2. Run Docker Compose: + + ```bash + docker compose up --build + ``` +8. Create a new application instance from the newly-registered application type + 1. Open http://localhost:3100 and log in using “dial” as username and password. + 2. Open **My Workspace** by clicking the Home icon on the left panel. + + ![](../img/custom-runner9.png) + + 3. In the **Add app** dropdown select **Custom Runner**. + 4. Set **Name** to “Custom Runner Instance 1” and click **Next**. + + > **Note**: Now you should see a sample custom configuration page with a single input field called “Number”. In this sample application, this property controls how many times your input will be repeated in the end-user chat in response. The configuration page is served by the URL specified in the “Editor URL” property of the application type. + +9. Change the default value of 1 with any other integer number (e.g. 5), then click **Save** and **Exit** in the right upper corner of the page. + + ![](../img/custom-runner10.png) + +10. Find the newly-created application instance named “Custom Runner Instance 1” in your workspace and open it. + + Now you should see a chat interface, where each of your input messages will be repeated as many times in response, as was specified when creating the application instance. + + ![](../img/custom-runner11.png) + +11. Check if the configuration can be changed at any time: + 1. Get back to your workspace in the DIAL Chat application. + 2. Click tree-dot icon on your newly-created application instance’s tile, and then click **Edit** in the pop-up menu. + + ![](../img/custom-runner12.png) + + 3. Change the number to any other value and check if it affects the behavior of this chat application instance. + +## Developing a Real-World Application + +A real-world custom application runner can be developed using such sample applications as templates. + +* For a scenario with the standard chat interface for end-users (like demonstrated in this tutorial), the **dial-custom-ui-client** project of **common-ui-app** sample can be ignored and removed. +* The **Settings** page from **dial-custom-ui-admin** can be changed however needed to satisfy the configurability requirements of your target use case. +* The backend for the scenario with the standard chat interface is based on [DIAL SDK](https://github.com/epam/ai-dial-sdk). There you can find more information and examples of how to build custom chat completion backends. +* The purpose of each environment variable used by the custom application is documented in the README.md of the corresponding project: + - [common-ui-app](https://github.com/epam/ai-dial/blob/main/dial-samples/common-ui-app/README.md) + - [standalone-app-chat-ui](https://github.com/epam/ai-dial/blob/main/dial-samples/standalone-app-chat-ui/backend/README.md) + - [app-runner-chat-ui](https://github.com/epam/ai-dial/blob/main/dial-samples/app-runner-chat-ui/backend/README.md) +* The main idea of handling instance-specific configuration with a custom Application Runner is: + - A custom configuration UI reads and saves instance-specific configuration directly accessing DIAL API (see [getCustomApplication](https://dialx.ai/dial_api#tag/Applications/operation/getCustomApplication) and [saveCustomApplication](https://dialx.ai/dial_api#tag/Applications/operation/saveCustomApplication) + - A custom chat completion backend reads the instance configuration associated with the current request by calling `request.request_dial_application_properties()` diff --git a/docs/tutorials/1.developers/img/custom-apps1.png b/docs/tutorials/1.developers/img/custom-apps1.png new file mode 100644 index 000000000..b9b2106fb Binary files /dev/null and b/docs/tutorials/1.developers/img/custom-apps1.png differ diff --git a/docs/tutorials/1.developers/img/custom-apps10.png b/docs/tutorials/1.developers/img/custom-apps10.png new file mode 100644 index 000000000..b15f3fedd Binary files /dev/null and b/docs/tutorials/1.developers/img/custom-apps10.png differ diff --git a/docs/tutorials/1.developers/img/custom-apps2.png b/docs/tutorials/1.developers/img/custom-apps2.png new file mode 100644 index 000000000..5a7b3d9d5 Binary files /dev/null and b/docs/tutorials/1.developers/img/custom-apps2.png differ diff --git a/docs/tutorials/1.developers/img/custom-apps3.png b/docs/tutorials/1.developers/img/custom-apps3.png new file mode 100644 index 000000000..f2a279304 Binary files /dev/null and b/docs/tutorials/1.developers/img/custom-apps3.png differ diff --git a/docs/tutorials/1.developers/img/custom-apps4.png b/docs/tutorials/1.developers/img/custom-apps4.png new file mode 100644 index 000000000..519b7da03 Binary files /dev/null and b/docs/tutorials/1.developers/img/custom-apps4.png differ diff --git a/docs/tutorials/1.developers/img/custom-apps5.png b/docs/tutorials/1.developers/img/custom-apps5.png new file mode 100644 index 000000000..f8ac3b6ec Binary files /dev/null and b/docs/tutorials/1.developers/img/custom-apps5.png differ diff --git a/docs/tutorials/1.developers/img/custom-apps6.png b/docs/tutorials/1.developers/img/custom-apps6.png new file mode 100644 index 000000000..c38a098e3 Binary files /dev/null and b/docs/tutorials/1.developers/img/custom-apps6.png differ diff --git a/docs/tutorials/1.developers/img/custom-apps7.png b/docs/tutorials/1.developers/img/custom-apps7.png new file mode 100644 index 000000000..171128ff9 Binary files /dev/null and b/docs/tutorials/1.developers/img/custom-apps7.png differ diff --git a/docs/tutorials/1.developers/img/custom-apps8.png b/docs/tutorials/1.developers/img/custom-apps8.png new file mode 100644 index 000000000..f6cac61a5 Binary files /dev/null and b/docs/tutorials/1.developers/img/custom-apps8.png differ diff --git a/docs/tutorials/1.developers/img/custom-apps9.png b/docs/tutorials/1.developers/img/custom-apps9.png new file mode 100644 index 000000000..7ae12cd22 Binary files /dev/null and b/docs/tutorials/1.developers/img/custom-apps9.png differ diff --git a/docs/tutorials/1.developers/img/custom-runner1.png b/docs/tutorials/1.developers/img/custom-runner1.png new file mode 100644 index 000000000..d3ca4d765 Binary files /dev/null and b/docs/tutorials/1.developers/img/custom-runner1.png differ diff --git a/docs/tutorials/1.developers/img/custom-runner10.png b/docs/tutorials/1.developers/img/custom-runner10.png new file mode 100644 index 000000000..98a24db17 Binary files /dev/null and b/docs/tutorials/1.developers/img/custom-runner10.png differ diff --git a/docs/tutorials/1.developers/img/custom-runner11.png b/docs/tutorials/1.developers/img/custom-runner11.png new file mode 100644 index 000000000..4804804ea Binary files /dev/null and b/docs/tutorials/1.developers/img/custom-runner11.png differ diff --git a/docs/tutorials/1.developers/img/custom-runner12.png b/docs/tutorials/1.developers/img/custom-runner12.png new file mode 100644 index 000000000..78cc07e14 Binary files /dev/null and b/docs/tutorials/1.developers/img/custom-runner12.png differ diff --git a/docs/tutorials/1.developers/img/custom-runner2.png b/docs/tutorials/1.developers/img/custom-runner2.png new file mode 100644 index 000000000..05dc87b8c Binary files /dev/null and b/docs/tutorials/1.developers/img/custom-runner2.png differ diff --git a/docs/tutorials/1.developers/img/custom-runner3.png b/docs/tutorials/1.developers/img/custom-runner3.png new file mode 100644 index 000000000..57dde1ac2 Binary files /dev/null and b/docs/tutorials/1.developers/img/custom-runner3.png differ diff --git a/docs/tutorials/1.developers/img/custom-runner4.png b/docs/tutorials/1.developers/img/custom-runner4.png new file mode 100644 index 000000000..8406358be Binary files /dev/null and b/docs/tutorials/1.developers/img/custom-runner4.png differ diff --git a/docs/tutorials/1.developers/img/custom-runner5.png b/docs/tutorials/1.developers/img/custom-runner5.png new file mode 100644 index 000000000..0c774b403 Binary files /dev/null and b/docs/tutorials/1.developers/img/custom-runner5.png differ diff --git a/docs/tutorials/1.developers/img/custom-runner6.png b/docs/tutorials/1.developers/img/custom-runner6.png new file mode 100644 index 000000000..6397e26c4 Binary files /dev/null and b/docs/tutorials/1.developers/img/custom-runner6.png differ diff --git a/docs/tutorials/1.developers/img/custom-runner7.png b/docs/tutorials/1.developers/img/custom-runner7.png new file mode 100644 index 000000000..564caed60 Binary files /dev/null and b/docs/tutorials/1.developers/img/custom-runner7.png differ diff --git a/docs/tutorials/1.developers/img/custom-runner8.png b/docs/tutorials/1.developers/img/custom-runner8.png new file mode 100644 index 000000000..8560b9ecc Binary files /dev/null and b/docs/tutorials/1.developers/img/custom-runner8.png differ diff --git a/docs/tutorials/1.developers/img/custom-runner9.png b/docs/tutorials/1.developers/img/custom-runner9.png new file mode 100644 index 000000000..1ceb7c9f9 Binary files /dev/null and b/docs/tutorials/1.developers/img/custom-runner9.png differ diff --git a/docs/tutorials/1.developers/img/overview1.png b/docs/tutorials/1.developers/img/overview1.png new file mode 100644 index 000000000..ca5dfa2c7 Binary files /dev/null and b/docs/tutorials/1.developers/img/overview1.png differ diff --git a/docs/tutorials/1.developers/img/overview2.png b/docs/tutorials/1.developers/img/overview2.png new file mode 100644 index 000000000..61e081249 Binary files /dev/null and b/docs/tutorials/1.developers/img/overview2.png differ diff --git a/docs/tutorials/1.developers/img/overview3.png b/docs/tutorials/1.developers/img/overview3.png new file mode 100644 index 000000000..49395cd26 Binary files /dev/null and b/docs/tutorials/1.developers/img/overview3.png differ diff --git a/docs/tutorials/1.developers/img/overview4.png b/docs/tutorials/1.developers/img/overview4.png new file mode 100644 index 000000000..c94b74870 Binary files /dev/null and b/docs/tutorials/1.developers/img/overview4.png differ diff --git a/docs/tutorials/1.developers/img/overview5.png b/docs/tutorials/1.developers/img/overview5.png new file mode 100644 index 000000000..c7e52881a Binary files /dev/null and b/docs/tutorials/1.developers/img/overview5.png differ diff --git a/docs/tutorials/1.developers/img/overview6.png b/docs/tutorials/1.developers/img/overview6.png new file mode 100644 index 000000000..09eb80db8 Binary files /dev/null and b/docs/tutorials/1.developers/img/overview6.png differ diff --git a/docs/tutorials/1.developers/img/overview7.png b/docs/tutorials/1.developers/img/overview7.png new file mode 100644 index 000000000..c17546c24 Binary files /dev/null and b/docs/tutorials/1.developers/img/overview7.png differ diff --git a/sidebars.js b/sidebars.js index 3663bb9a8..e15cd02b1 100644 --- a/sidebars.js +++ b/sidebars.js @@ -120,6 +120,11 @@ const sidebars = { id: 'platform/core/apps', label: 'DIAL-Native Apps', }, + { + type: 'doc', + id: 'tutorials/developers/apps-development/develop-custom-apps-overview', + label: 'Custom Apps', + }, ], }, { @@ -315,6 +320,22 @@ const sidebars = { 'tutorials/developers/apps-development/multimodality/dial-cookbook/examples/how_to_call_dalle_3_with_configuration', ], }, + { + type: 'category', + label: 'Develop Custom Apps', + items: [ + { + type: 'doc', + id: 'tutorials/developers/apps-development/develop-single-app', + label: 'Develop Single App', + }, + { + type: 'doc', + id: 'tutorials/developers/apps-development/develop-app-runner', + label: 'Develop App Runner', + }, + ], + } ], }, {