SAP Conversational AI SDK for iOS
The SAPCAI
Swift Package is a module to connect to a bot on the end-to-end chatbot platform SAP Conversational AI (CAI). It provides a pluggable SwiftUI AssistantView
to initiate a conversation and render the various message types of a bot.
This Swift Package is an open-source addition to the frameworks of the SAP BTP SDK for iOS.
- iOS 13 or higher
- Xcode 12 (Swift 5.3) or higher
- You have existing bot(s) on the SAP Conversational AI platform
- You created an OAuth client for Designtime API for your bot (Settings > Tokens)
- Your bot(s) are connected to a mobile channel
In the Enterprise Edition this can be done via the UI.
However, the option is currently hidden by default and needs to be enabled by filing a ticket.
In the Community Edition you create a mobile channel via the /channel API.
# create a mobile channel
curl -X POST "<BaseUrl>/connect/v1/channels" \
-H "X-Token: Token <DeveloperToken>" \
-H "Content-Type: application/json" \
-d '{"type":"mobile","slug":"<desiredChannelSlug>","connectionTarget": "SAP_Product","targetSystem": "MobileBot","isActivated":true}'
- SAPCommon for Logging
- SAPFoundation for Network Connectivity and Authentication
- URLImage for asynchronous image loading in SwiftUI
- Down for Markdown / CommonMark rendering in Swift
The package is intended for consumption via Swift Package Manager. To add SAPCAI
to your application target, navigate to the File > Swift Packages > Add Package Dependency... , then add the repository URL /~https://github.com/SAP/cloud-sdk-ios-cai.
You can choose one of the following package products to be added to your application / framework target
Package Product | When to Use |
---|---|
SAPCAI | You did not already embed binary frameworks from SAP BTP SDK for iOS |
SAPCAI-requiresToEmbedXCFrameworks | You already embedded SAPCommon and SAPFoundation binary frameworks to your target |
The code snippet below illustrates how to set up the CAIConversation
Combine publisher in order to initialize the MessagingViewModel
for the AssistantView
.
See Enterprise Configuration guide for required configuration steps to use SAPCAI
Swift package and connect indirectly with SAP Conversational AI Enterprise Edition through SAP Mobile Services.
The code snippet below contains example values specific for connecting iOS client directly with SAP Conversational AI Community Edition for prototyping. You have to replace variable values in angle brackets (e.g. <channelId>
) with your bot-specific values
import SAPCAI
import SAPFoundation
import SwiftUI
/*
Create the `CAIChannel` object by providing the channel id, channel token and channel slug which were created in CAI Platform.
If you do not want to hardcode chanel information on the client then you can retrieve a list of channels for a given Application ID with `CAIChannelService`.
*/
let caiChannel = CAIChannel(id: "<channelId>", token: "<channelToken>", slug: "<channelSlug>").
/*
Create and attach OAuthObserver to `SAPURLSession`
Example-specific extension for `CAIServiceConfig` to build OAuth observer (see next code snippet for implementation details)
Use CAI OAuth credentials for prototyping & direct communication between iOS client and SAP Conversational AI *Community Edition*
Use Mobile Service OAuth credentials to connect indirectly with SAP Conversational AI *Enterprise Edition* through SAP Mobile Services. In this case you have to reuse the `SAPURLSession` instance used for authentication against Mobile Services.
*/
let session = SAPURLSession()
if let observer = CAIServiceConfig.buildOAuthObserver(systemBaseURL: URL(string: "<Example: https://sapcai-community.sap.eu10.hana.ondemand.com>")!,
authenticationBaseURL: URL(string: "<Example: https://sapcai-community.authentication.eu10.hana.ondemand.com>")!,
clientId: "<OAuth client id>",
clientSecret: "<OAuth client secret>") {
session.register(observer)
}
// Create CAI service config for the provided SAPURLSession and URL pointing to CAI API endpoint
let serviceConfig = CAIServiceConfig(urlSession: session, host: URL(string:"<Example: https://api.cai.tools.sap>")!)
// Provide the message delivery object for polling
let polling: MessageDelivering = PollMessageDelivery(channelId: "<channelId>", serviceConfig: serviceConfig)
// Create CAIConversation object and use it as publisher
let dataPublisher = CAIConversation(config: serviceConfig, channel: caiChannel, messageDelivery: polling)
// Create view model for `AssistantView`
let viewModel = MessagingViewModel(publisher: dataPublisher)
Example-specific extension for CAIServiceConfig
to build OAuth observer
extension CAIServiceConfig {
public static func buildOAuthObserver(systemBaseURL: URL, authenticationBaseURL: URL, clientId: String, clientSecret: String) -> OAuth2Observer? {
let compositeStore = CompositeStorage()
do {
let secureKeyValueStore = SecureKeyValueStore()
try secureKeyValueStore.open(with: "cai_secure_store")
try compositeStore.setPersistentStore(secureKeyValueStore)
let params = OAuth2AuthenticationParameters(authorizationEndpointURL: authenticationBaseURL.appendingPathComponent("/oauth/authorize"),
clientID: clientId,
redirectURL: systemBaseURL.appendingPathComponent("login/callback"),
tokenEndpointURL: authenticationBaseURL.appendingPathComponent("/oauth/token"),
clientSecret: clientSecret)
let authenticator = OAuth2Authenticator(authenticationParameters: params, webViewPresenter: WKWebViewPresenter())
let oauthObserver = OAuth2Observer(authenticator: authenticator, tokenStore: OAuth2TokenStorage(store: compositeStore))
return oauthObserver
}
catch {
// error handling
return nil
}
}
}
Note: If you are developing your iOS application with SAP BTP SDK for iOS and Mobile Servcies then you can ignore the previous code snippet as you (probably) already have attached an OAuth2Observer
pointing to Mobile Services.
Using the SwiftUI implementation is the preferred approach
AssistantView()
.navigationBarTitle(Text("Chat"), displayMode: .inline) // if you are in navigation controller
.environmentObject(viewModel)
.environmentObject(ThemeManager.shared)
.onDisappear {
viewModel.cancelSubscriptions()
dataPublisher.resetConversation()
})
but SAPCAI
also provides a UIKit wrapper
let vc = MessagingViewController(MessagingViewModel(publisher: dataPublisher))
self.navigationController?.pushViewController(vc, animated: true)
SAPCAI
will provide two standard themes
- a Fiori theme and
- a Casual theme
Each theme will come with its color palette, that supports both light and dark mode.
ThemeManager.shared.setCurrentTheme( .fiori(FioriColorPalette()) )
ThemeManager.shared.setCurrentTheme( .casual(CasualColorPalette()) )
You can also provide an alternative color palette or provide a custom theme.
- No support for GitHub Flavored Markdown (e.g.
strikethrough). Bot responses containing Markdown will be rendered by theAssistantView
according to the Commonmark specification only and unknown syntax will be treated as text.
Trigger Skill
buttons are still enabled after execution / next interaction. This behavior differs from SAP CAI WebClient as once you click the button or type an utterance, the corresponding skill can't be triggered anymore at a later point in time, since the context in which it was created might not be valid anymore.
- Not being able to save, copy, or share an image as part of a bot reponse. Currently there is no gesture handler attached to an image view which could allow to open a contextual menu offering such features (similar to iMessage or WhatsApp).
- Animated images (GIF), as part of a bot response, will be viewed as static image (dependency to dmytro-anokhin/url-image#43)
Please raise an issue on GitHub. SAP customers can continue to report issues through OSS for SLA tracking.
Questions around CAI can be raised in the SAP CAI Answers forum.
If you want to contribute, please check the Contribution Guidelines.
The CAITestApp
in this repository allows you to
- choose a theme
- view static mock data or
- connect against a live system by either
- letting the user choose the mobile channel from the list of available mobile channels for given Application ID (a.k.a targetSystem); note: this illustrates the use of
CAIChannelService
and how to build a simple SwiftUI view on top of it - loading the
AssistantView
for a specific mobile channel
- letting the user choose the mobile channel from the list of available mobile channels for given Application ID (a.k.a targetSystem); note: this illustrates the use of
See here on how to maintain connection settings for the test application.