Skip to content

Commit 65a04a8

Browse files
committed
feat: lark chatbi
1 parent 722110a commit 65a04a8

File tree

5 files changed

+152
-66
lines changed

5 files changed

+152
-66
lines changed

apps/cloud/src/app/features/chat/chat-input/chat-input.component.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
<div class="flex items-end rounded-[2rem] p-2 bg-black/5 dark:bg-white/10">
1+
<div class="flex items-end rounded-[2rem] p-2 active:scale-[.99] active:translate-y-0.5 transition-all
2+
bg-black/5 dark:bg-white/10 active:bg-black/10 active:dark:bg-white/5">
23
<textarea #userInput matInput class="ngm-colpilot__input flex-1 w-full px-1.5 m-2 z-10 resize-none overflow-visible"
34
id="userInput" onInput="this.parentNode.dataset.replicatedValue = this.value"
45
[placeholder]="'PAC.Chat.MessageDigitalExpert' | translate: {Default: 'Message digital expert'}"

packages/analytics/src/chatbi/commands/handlers/chatbi.handler.ts

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
} from '@metad/server-ai'
1212
import { Inject, Logger } from '@nestjs/common'
1313
import { CommandBus, CommandHandler, ICommandHandler } from '@nestjs/cqrs'
14-
import { EMPTY, from, Observable } from 'rxjs'
1514
import { IsNull } from 'typeorm'
1615
import { ChatBIModelService } from '../../../chatbi-model'
1716
import { SemanticModelMemberService } from '../../../model-member'
@@ -43,17 +42,15 @@ export class ChatBIHandler implements ICommandHandler<ChatBICommand> {
4342
private readonly commandBus: CommandBus
4443
) {}
4544

46-
public async execute(command: ChatBICommand): Promise<Observable<any>> {
45+
public async execute(command: ChatBICommand): Promise<any> {
4746
const { input } = command
4847
const { tenant, organizationId, user, larkService } = input
4948

5049
const conversation = await this.getUserConversation(input)
5150
if (!conversation) {
52-
return from(
53-
larkService.errorMessage(
54-
input,
55-
new Error(`Failed to create chat conversation for user: ${input.userId}`)
56-
)
51+
return await larkService.errorMessage(
52+
input,
53+
new Error(`Failed to create chat conversation for user: ${input.userId}`)
5754
)
5855
}
5956

@@ -65,18 +62,17 @@ export class ChatBIHandler implements ICommandHandler<ChatBICommand> {
6562
userId: user.id,
6663
copilot: conversation.copilot
6764
}))
68-
return EMPTY
6965
} catch(err) {
70-
//
66+
return await larkService.errorMessage(
67+
input,
68+
err
69+
)
7170
}
7271

73-
return new Observable((subscriber) => {
74-
conversation.ask(input.text).then()
75-
return () => {
76-
// when cancel
77-
conversation.destroy()
78-
}
79-
})
72+
// Ask
73+
conversation.ask(input.text).then()
74+
75+
return
8076
}
8177

8278
async getUserConversation(input: ChatBILarkContext): Promise<ChatBIConversation> {
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import { createSlicersTitle } from './answer'
2+
3+
describe('Answer', () => {
4+
beforeEach(async () => {
5+
//
6+
})
7+
8+
describe('createSlicersTitle', () => {
9+
it('should return an array', async () => {
10+
const result = createSlicersTitle([
11+
{
12+
dimension: {
13+
dimension: '[0RTYPE]',
14+
hierarchy: '[0RTYPE]',
15+
parameter: '[!V000003]'
16+
},
17+
members: [
18+
{
19+
key: '[M]',
20+
caption: '在平均比率下的标准兑换'
21+
}
22+
]
23+
},
24+
{
25+
dimension: {
26+
dimension: '[0CURRENCY]',
27+
hierarchy: '[0CURRENCY]',
28+
parameter: '[!V000004]'
29+
},
30+
members: [
31+
{
32+
key: '[USD]',
33+
caption: 'USD'
34+
}
35+
]
36+
},
37+
{
38+
dimension: {
39+
dimension: '[2CP3MJ5KTNH8ZFZHFAZCH2WTDYK]',
40+
hierarchy: '[2CP3MJ5KTNH8ZFZHFAZCH2WTDYK]'
41+
},
42+
members: [
43+
{
44+
key: '2024',
45+
value: '2024'
46+
}
47+
]
48+
}
49+
])
50+
51+
console.log(result)
52+
53+
expect(result).toStrictEqual([])
54+
})
55+
56+
it('should return an array', async () => {
57+
const result = createSlicersTitle([
58+
{
59+
dimension: {
60+
dimension: '[0RTYPE]',
61+
hierarchy: '[0RTYPE]',
62+
parameter: '[!V000003]'
63+
},
64+
members: [
65+
{
66+
key: '[M]',
67+
caption: '在平均比率下的标准兑换'
68+
}
69+
]
70+
},
71+
{
72+
dimension: {
73+
dimension: '[0CURRENCY]',
74+
hierarchy: '[0CURRENCY]',
75+
parameter: '[!V000004]'
76+
},
77+
members: [
78+
{
79+
key: '[USD]',
80+
caption: 'USD'
81+
}
82+
]
83+
},
84+
{
85+
dimension: {
86+
parameter: '',
87+
dimension: '[2CISDDISTRCHANNEL]',
88+
hierarchy: '[2CISDDISTRCHANNEL]',
89+
level: '[2CISDDISTRCHANNEL].[LEVEL01]',
90+
zeroSuppression: true
91+
},
92+
exclude: false,
93+
members: [
94+
{
95+
key: '[00]',
96+
caption: '通用'
97+
}
98+
]
99+
},
100+
{
101+
dimension: {
102+
dimension: '[2CP3MJ5KTNH8ZFZHFAZCH2WTDYK]',
103+
hierarchy: '[2CP3MJ5KTNH8ZFZHFAZCH2WTDYK]'
104+
},
105+
members: [
106+
{
107+
key: '2024',
108+
value: '2024'
109+
}
110+
]
111+
}
112+
])
113+
114+
console.log(result)
115+
116+
expect(result).toStrictEqual([])
117+
})
118+
})
119+
})

packages/analytics/src/chatbi/tools/answer.ts

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@ import {
33
ChartAnnotation,
44
ChartBusinessService,
55
ChartDimensionRoleType,
6-
ChartDimensionSchema,
7-
ChartMeasureSchema,
86
DataSettings,
9-
DataSettingsSchema,
107
Dimension,
118
EntityType,
129
FilteringLogic,
@@ -23,22 +20,18 @@ import {
2320
isTimeRangesSlicer,
2421
Measure,
2522
OrderBy,
26-
OrderBySchema,
2723
PresentationVariant,
2824
PropertyMeasure,
2925
slicerAsString,
30-
SlicerSchema,
3126
TimeRangesSlicer,
3227
timeRangesSlicerAsString,
33-
TimeSlicerSchema,
3428
toAdvancedFilter,
3529
tryFixDimension,
3630
tryFixSlicer,
3731
tryFixVariableSlicer,
3832
workOutTimeRangeSlicers
3933
} from '@metad/ocap-core'
4034
import { firstValueFrom, Subject, takeUntil } from 'rxjs'
41-
import { z } from 'zod'
4235
import { ChatLarkMessage } from '../message'
4336
import { ChatAnswerSchema, ChatBILarkContext, ChatContext, IChatBIConversation } from '../types'
4437
import { createBaseChart } from './charts/chart'
@@ -62,25 +55,6 @@ export type ChatAnswer = {
6255
orders: OrderBy[]
6356
}
6457

65-
// export const ChatAnswerSchema = z.object({
66-
// preface: z.string().describe('preface of the answer'),
67-
// visualType: z.enum(['Chart', 'Table', 'KPI']).describe('Visual type of result'),
68-
// dataSettings: DataSettingsSchema.optional().describe('The data settings of the widget'),
69-
// chartType: z
70-
// .object({
71-
// type: z.enum(['Column', 'Line', 'Pie', 'Bar']).describe('The type of chart')
72-
// })
73-
// .optional()
74-
// .describe('Chart configuration'),
75-
// dimensions: z.array(ChartDimensionSchema).optional().describe('The dimensions used by the chart'),
76-
// measures: z.array(ChartMeasureSchema).optional().describe('The measures used by the chart'),
77-
// orders: z.array(OrderBySchema).optional().describe('The orders used by the chart'),
78-
// top: z.number().optional().describe('The number of top members'),
79-
// slicers: z.array(SlicerSchema).optional().describe('The slicers to filter data'),
80-
// timeSlicers: z.array(TimeSlicerSchema).optional().describe('The time slicers to filter data'),
81-
// variables: z.array(VariableSchema).optional().describe('The variables to the query of cube'),
82-
// conclusion: z.string().optional().describe('conclusion of the answer')
83-
// })
8458

8559
export function createChatAnswerTool(context: ChatContext, larkContext: ChatBILarkContext) {
8660
const { chatId, logger, dsCoreService, conversation } = context
@@ -242,7 +216,8 @@ const colors = [
242216
'carmine' //洋红色
243217
]
244218

245-
function createSlicersTitle(slicers: ISlicer[]) {
219+
export function createSlicersTitle(slicers: ISlicer[]) {
220+
// console.log(JSON.stringify(slicers, null, 2))
246221
return slicers.map((slicer) => {
247222
return {
248223
tag: 'text_tag',

packages/server/src/integration-lark/lark.service.ts

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -149,28 +149,23 @@ export class LarkService {
149149
this.logger.debug('im.message.receive_v1:')
150150
this.logger.debug(data)
151151

152-
const user = await this.getUser(client, tenant.id, data.sender.sender_id.union_id)
153-
154-
const result = await this.commandBus.execute<LarkMessageCommand, Observable<any>>(
155-
new LarkMessageCommand({
156-
tenant,
157-
organizationId,
158-
integrationId: integration.id,
159-
user,
160-
message: data as any,
161-
chatId,
162-
chatType: data.message.chat_type,
163-
larkService: this
164-
})
165-
)
166-
result.subscribe({
167-
next: () => {
168-
//
169-
},
170-
error: () => {
171-
//
172-
}
173-
})
152+
try {
153+
const user = await this.getUser(client, tenant.id, data.sender.sender_id.union_id)
154+
await this.commandBus.execute<LarkMessageCommand, Observable<any>>(
155+
new LarkMessageCommand({
156+
tenant,
157+
organizationId,
158+
integrationId: integration.id,
159+
user,
160+
message: data as any,
161+
chatId,
162+
chatType: data.message.chat_type,
163+
larkService: this
164+
})
165+
)
166+
} catch(err) {
167+
console.error(err)
168+
}
174169

175170
this.logger.debug('Return for message:' + data.event_id)
176171
return 'ok'

0 commit comments

Comments
 (0)