SDK Integration
Configuration Options
interface DataSource {
appId: number;
chartId?: number;
dataAppId?: number;
datasetId?: number;
subjectId?: number; // Business Indicator Subject Domain ID
}
interface CompletionConfig {
meta?: string;
openChartConfig?: boolean;
stylesheet?: string;
i18n?: {
[key: string]: {
[key: string]: string;
};
};
onCompletionDone?: (conversationId: number, uid: string) => void;
}
interface Config {
userConfig: {
sourceAppId?: number;
dataSources: DataSource[];
};
completionConfig?: CompletionConfig;
closable?: boolean;
draggable?: boolean | {
enable: boolean;
minWidth: number;
minHeight: number;
bounds: 'window' | 'parent';
position: {
x: number;
y: number;
};
size: {
width: number;
height: number;
};
};
locale?: string;
i18n?: {
[key: string]: {
[key: string]: string;
};
};
stylesheet?: string;
className?: string;
style?: React.CSSProperties;
bodyClassName?: string;
bodyStyle?: React.CSSProperties;
header?: string | React.ReactElement;
systemMsg?: string;
parser?: {
selectText: string;
onSelect: (chart: any) => void;
};
chartTheme?: string | Theme;
}
interface Theme {
base?: string | number;
background?: string;
color?: string;
fontSize?: number;
fontFamily?: any;
fontWeight?: string;
textAlign?: string;
borderColor?: string;
borderWidth?: number;
borderStyle?: string;
borderRadius?: number;
boxShadow?: string;
chartBackground?: string;
chartPadding?: number;
schema?: string[];
mapTheme?: string;
}
// Create Copilot configuration object
const config: Config = {
userConfig: {
// sourceAppId: 130870, // App ID from App Mart or App Creation
dataSources: [
// Method 1: Using Data Package and Dataset
{
appId: 130870,
dataAppId: 130870,
datasetId: 1,
},
// Or Method 2: Using Business Indicator Subject Domain
{
appId: 130871,
subjectId: 1,
}
],
},
completionConfig: {
meta: 'answer,chart,chartConfig', // Specify content combination to render
openChartConfig: false, // Whether to expand the chart logic panel, defaults to true
stylesheet: ':host > *, ::before, ::after { --brand: #4CAF50; }',
i18n: {
"en-US": {
'copilot.question-reasoning': 'Question Understanding',
'copilot.question-answer': 'Data Performance',
'copilot.question-reasoning-logic': 'Data Logic'
}
},
onCompletionDone: (conversationId, uid) => {
console.log('AI completion done:', conversationId, uid);
},
},
closable: true, // Optional, whether to display the close button, default is false
draggable: { // Optional, whether draggable, default is not draggable
enable: true,
minWidth: 440,
minHeight: 440,
bounds: 'window',
position: {
x: window.innerWidth - 480,
y: 20,
},
size: {
width: 440,
height: window.innerHeight * 0.8,
},
},
locale: 'en-US',
i18n: {
"en-US": {
'copilot.question-reasoning': 'Question Understanding',
'copilot.question-answer': 'Data Performance',
'copilot.question-reasoning-logic': 'Data Logic'
},
"zh-CN": {
'copilot.question-reasoning': '问题理解',
'copilot.question-answer': '数据表现',
'copilot.question-reasoning-logic': '取数逻辑'
}
},
stylesheet: '', // Optional, custom CSS styles
className: '', // Optional, custom class name
style: {}, // Optional, custom styles
bodyClassName: '', // Optional, class name for the dialog content container
bodyStyle: {}, // Optional, styles for the dialog content container
header: '', // Optional, additional content in the title
systemMsg: 'Welcome to the Intelligent Analysis Assistant', // Optional, welcome message
parser: {
selectText: 'Select Chart', // Button text
onSelect: (chart) => {
// Event triggered when button is clicked, chart parameter needs to be defined based on actual usage scenarios
console.log('Chart selection event', chart);
},
},
chartTheme: 'HAWAII_SEA', // Optional, chart theme, refer to dashboard themes
};
> [!NOTE]
> In the `dataSources` configuration, each data source can only use one of the following two modes:
> 1. Data Package and Dataset Mode: provide `dataAppId` and `datasetId`
> 2. Business Indicator Subject Domain Mode: provide `subjectId`
>
> You cannot mix both modes in the same data source configuration.
2. Calling HTTP API via JS
In the copilot example above, the api
object provides all the methods for calling HTTP APIs. You can interact with the backend by invoking these methods, such as:
// 1. Create a conversation
const { body: { data: conversation }} = await copilot.api.requestCreateConversation({
body: {
title: 'This is the title of the conversation',
},
}).value;
/**
conversation = {
"id": 135,
"title": "This is the title of the conversation",
"createdBy": 268,
"createdAt": "2024-09-14 15:47:23",
"updatedBy": 268,
"updatedAt": "2024-09-14 15:47:23"
}
*/
// 2. Create a Q&A
const { body: { data: chat }} = await copilot.api.requestCreateChat({
id: conversation.id,
body: {
prompt: 'Which director has the highest-grossing movies?', // This is the user's question
userConfig: { // Refer to the userConfig in copilotConfig above
dataAppId: 129150,
datasetId: 1,
}
},
qs: {
sync: true, // Whether to execute synchronously
timeout: 1000 * 60, // Timeout duration in milliseconds
},
}).value;
/**
chat = {
"conversationId": 135,
"prompt": "Which director has the highest-grossing movies?",
"answer": "Christopher Nolan has the highest-grossing movies.",
"model": "gpt-4o",
"uid": "08ff93ca-1972-4916-b884-35fab6f91c64",
"temperature": 0,
"createdBy": 268,
"createdAt": "2024-09-14 15:47:23",
"updatedBy": 268,
"updatedAt": "2024-09-14 15:47:23",
"responseAt": "2024-09-14 15:47:30",
"isDelete": false,
"isContextEnd": false,
"suggestQuestions": [],
"statusList": [
"PENDING",
"ANALYZE_REQUEST",
"HQL_SELECT_FIELDS",
"HQL_SELECT_FUNCTIONS",
"GENERATE_HQL_QUERY",
"DOING_HQL_QUERY",
"DOING_SUMMARY",
"DOING_QUESTION_SUGGESTING",
"DONE"
],
"userConfig": {
"datasetId": 1,
"dataAppId": 129150
},
"autoConfig": {
"agentType": "HQL_AGENT"
},
"isCurrent": true,
"usage": [
{
"completion_tokens": 24,
"prompt_tokens": 4063,
"total_tokens": 4087
},
{
"completion_tokens": 5,
"prompt_tokens": 1424,
"total_tokens": 1429
},
{
"completion_tokens": 49,
"prompt_tokens": 3906,
"total_tokens": 3955
},
{
"completion_tokens": 16,
"prompt_tokens": 299,
"total_tokens": 315
}
],
"chartCreatedAt": "2024-09-14 15:47:30",
"refineQuestion": "Which director has the highest-grossing movies?",
"favorite": false,
"charts": [
{
"appId": 129150,
"datasetId": 1,
"options": {
"axes": [
{
"op": "{{1}}.{director}",
"uid": "uid1",
"fieldName": "director",
"kind": "formula",
"datasetId": 1,
"labelOrigin": "director",
"label": "director",
"isAggregate": false,
"value": "{{coffe_product_table}}.{director}",
"dataset": 1,
"fieldType": "string"
},
{
"op": "max({{1}}.{votes})",
"uid": "uid2",
"fieldName": "votes",
"kind": "formula",
"datasetId": 1,
"labelOrigin": "votes",
"label": "votes",
"isAggregate": true,
"value": "max({{coffe_product_table}}.{votes})",
"dataset": 1,
"fieldType": "number"
}
],
"name": "Bar",
"limit": 1,
"sort": [
{
"op": "uid2",
"kind": "reference",
"direction": "desc"
},
{
"op": "uid1",
"kind": "reference",
"direction": "asc"
}
]
},
"dataAppId": 129150,
"datasetIds": [
1
]
}
]
}
*/
Login Authentication
When integrating the SDK, you may need to perform login authentication. We provide two methods:
- SSO Single Sign-On: If your system is already integrated with the HENGSHI SENSE system, no additional login is required.
- JWT Authentication: Use the following code to perform login authentication with JWT:
fetch('https://develop.hengshi.org/api/auth/login-info?activeAuth=jwt-param&jwtParam=Your JWT Parameter')
.then(response => {
// Login successful, proceed with using the SDK
})
.catch(error => {
// Login failed, handle the error
});
Tip
Ensure that you have configured JWT in 'Settings->Organization Management->Authentication Method->JWT Request Parameters'.
Replace 'Your JWT Parameter' with the actual JWT parameter.
Custom Styles
If you want to customize the AI assistant's style, you can achieve this through the following CSS code:
/* Example: Use CSS to batch customize skin styles */
*, ::before, ::after {
--brand: #4CAF50; // This is the system's overall brand color
}
/* Set the root element style for the AI assistant dialog box */
.hengshi-copilot-sdk .hst-copilot {
position: fixed;
// z-index: 1; // Set as needed
top: 10vh;
right: 50px;
width: 440px;
height: 80vh;
border-width: 1px;
}
/* Set the style for the AI assistant title element */
.hengshi-copilot-sdk .hst-copilot-header {
color: #fff;
background-color: darkslategray;
}
/* Set the style for the AI assistant conversation area element */
.hengshi-copilot-sdk .hst-copilot-conversations {
border-color: #aaa;
background-color: darkslategray;
height: calc(100% - 50px);
}
/* Set the style for the AI assistant message element */
.hengshi-copilot-sdk .hst-copilot-msg,
/* Set the style for the icon operations below the AI assistant message element */
.hengshi-copilot-sdk .hst-copilot-msg > .hs-relative > *,
/* Set the style for the AI assistant auxiliary information element */
.hengshi-copilot-sdk .hst-copilot-mark {
color: #fff;
}
.hengshi-copilot-sdk .hst-copilot-mark .hs-bg-\[color\:var\(--hs-bg-lighter\)\] {
background-color: transparent;
}
/* Set the background style for the icon operations below the AI assistant message element when hovered */
.hengshi-copilot-sdk .hover\:hs-bg-\[\#eee\]:hover {
--tw-bg-opacity: .2;
}
/* Set the style for the AI assistant bot message bubble element */
.hengshi-copilot-sdk .hst-copilot-msg-bot .hst-copilot-msg-inner,
/* Set the style for the AI assistant user message bubble element */
.hengshi-copilot-sdk .hst-copilot-msg-user .hst-copilot-msg-inner {
border-color: darkgray;
background-color: darkgray;
}
/* Set the background color for the AI assistant recommended question bubbles */
.hengshi-copilot-sdk .hst-copilot-msg-inner .hst-copilot-msg-inner {
background-color: slategray !important;
}
/* Set the style for the AI assistant input area element */
.hengshi-copilot-sdk .hst-copilot-prompt {
color: #fff;
background-color: darkslategray;
}
/* Set the style for the AI assistant input box element */
.hengshi-copilot-sdk .hst-copilot-prompt textarea {
color: #fff;
border-color: darkgray !important;
}
.hengshi-copilot-sdk .hst-copilot-prompt .hs-from-\[\#f1f1f1\],
.hengshi-copilot-sdk .hst-copilot-prompt .hs-to-\[\#f1f1f1\] {
--tw-gradient-to: darkslategray;
}
Pass the above CSS as a string in the Copilot configuration's stylesheet
:
// Create Copilot configuration object
const config: Config = {
...
stylesheet: css,
...
};
Integration via API can be done in two ways: frontend and backend. The frontend method directly calls the JavaScript API provided by the Copilot SDK, while the backend method uses HTTP interfaces.
Intercept API Requests and Customize API Requests
You can configure api
to intercept API requests and customize API requests in copilotConfig
.
The following APIs can be configured:
- requestFetchConversations: Fetch the conversation list
- requestCreateConversation: Create a conversation
- requestFetchConversation: Fetch conversation details
- requestDeleteConversation: Delete a conversation
- requestFetchChats: Fetch chat records within a conversation
- requestCreateChat: Create a chat record
- requestFetchChat: Fetch a single chat record
- requestUpdateChat: Update a single chat record
- requestDeleteChat: Delete a single chat record
- requestfetchChatLogs: Fetch logs of a single chat record
- requestRegenerateChat: Regenerate a response
Each API is a JavaScript function that accepts an object as a parameter, with the following rules:
- requestFetchConversations({ offset?: number, limit?: number })
- requestCreateConversation({ body: { title: string }})
- requestFetchConversation({ id: number })
- requestDeleteConversation({ id: number })
- requestFetchChats({ id: number, offset?: number, limit?: number })
- requestCreateChat({ id: number, body: { prompt: string, userConfig: object }})
- requestFetchChat({ id: number, chatUid: string })
- requestUpdateChat({ id: number, chatUid: string, body: object })
- requestDeleteChat({ id: number, chatUid: string })
- requestfetchChatLogs({ id: number, chatUid: string })
- requestRegenerateChat({ id: number, chatUid: string })
The function's return value is also an object, formatted as follows:
{
abort: function abort() {}, // Abort the API request
value: Promise, // The Promise of the API request
}
For example, if you want to intercept requests and add some custom parameters every time a conversation is created, you can configure it like this:
const copilotConfig = {
// ...
api: {
// Customize the API for creating conversations
requestCreateChat: params => {
// Add some custom parameters
if (!params.body.yourCustomProperty) {
params.body.yourCustomProperty = 'yourCustomValue';
}
return copilotInstance.context.endpoints.requestCreateChat(params);
},
// ... Other APIs can also be configured
},
};