@@ -31,7 +31,9 @@ import {
3131 tryFixVariableSlicer ,
3232 workOutTimeRangeSlicers
3333} from '@metad/ocap-core'
34+ import { race } from '@metad/server-common'
3435import { firstValueFrom , Subject , takeUntil } from 'rxjs'
36+ import { ChatBIConversation } from '../conversation'
3537import { ChatLarkMessage } from '../message'
3638import { ChatAnswerSchema , ChatBILarkContext , ChatContext , IChatBIConversation } from '../types'
3739import { createBaseChart } from './charts/chart'
@@ -55,41 +57,55 @@ export type ChatAnswer = {
5557 orders : OrderBy [ ]
5658}
5759
58-
5960export function createChatAnswerTool ( context : ChatContext , larkContext : ChatBILarkContext ) {
6061 const { chatId, logger, dsCoreService, conversation } = context
6162 return tool (
6263 async ( answer ) : Promise < string > => {
6364 logger . debug ( `Execute copilot action 'answerQuestion':` , JSON . stringify ( answer , null , 2 ) )
6465 try {
65- let entityType = null
66- if ( answer . dataSettings ) {
67- // Make sure datasource exists
68- const _dataSource = await dsCoreService . _getDataSource ( answer . dataSettings . dataSource )
69- const entity = await firstValueFrom (
70- dsCoreService . selectEntitySet ( answer . dataSettings . dataSource , answer . dataSettings . entitySet )
71- )
72- entityType = entity . entityType
73- }
74-
75- // Fetch data for chart or table or kpi
76- if ( answer . dimensions ?. length || answer . measures ?. length ) {
77- const { categoryMembers } = await drawChartMessage (
78- { ...context , entityType : entityType || context . entityType } ,
79- conversation ,
80- answer as ChatAnswer
81- )
82- // Max limit 20 members
83- const members = categoryMembers
84- ? JSON . stringify ( Object . values ( categoryMembers ) . slice ( 0 , 20 ) )
85- : 'Empty'
86-
87- return `The analysis data has been displayed to the user. The dimension members involved in this data analysis are:
66+ try {
67+ // 限制总体超时时间
68+ return await race (
69+ ChatBIConversation . toolCallTimeout ,
70+ ( async ( ) => {
71+ let entityType = null
72+ if ( answer . dataSettings ) {
73+ // Make sure datasource exists
74+ const _dataSource = await dsCoreService . _getDataSource ( answer . dataSettings . dataSource )
75+ const entity = await firstValueFrom (
76+ dsCoreService . selectEntitySet (
77+ answer . dataSettings . dataSource ,
78+ answer . dataSettings . entitySet
79+ )
80+ )
81+ entityType = entity . entityType
82+ }
83+
84+ // Fetch data for chart or table or kpi
85+ if ( answer . dimensions ?. length || answer . measures ?. length ) {
86+ const { categoryMembers } = await drawChartMessage (
87+ { ...context , entityType : entityType || context . entityType } ,
88+ conversation ,
89+ answer as ChatAnswer
90+ )
91+ // Max limit 20 members
92+ const members = categoryMembers
93+ ? JSON . stringify ( Object . values ( categoryMembers ) . slice ( 0 , 20 ) )
94+ : 'Empty'
95+
96+ return `The analysis data has been displayed to the user. The dimension members involved in this data analysis are:
8897${ members }
8998Please give more analysis suggestions about other dimensions or filter by dimensioin members, 3 will be enough.`
90- }
99+ }
91100
92- return `图表答案已经回复给用户了,请不要重复回答了。`
101+ return `图表答案已经回复给用户了,请不要重复回答了。`
102+ } ) ( )
103+ )
104+ } catch ( err ) {
105+ throw new Error (
106+ `Timeout in getting cube context (dataSource=${ answer . dataSettings . dataSource } , cube=${ answer . dataSettings . entitySet } )`
107+ )
108+ }
93109 } catch ( err ) {
94110 logger . error ( err )
95111 return `Error: ${ err } 。如果需要用户提供更多信息,请直接提醒用户。`
@@ -333,63 +349,6 @@ function createLineChart(
333349 unit = shortUnit
334350 } else {
335351 throw Error ( `图形配置错误` )
336- // let categoryProperty: PropertyHierarchy = null
337- // const fields = []
338- // if (chartAnnotation.dimensions?.length > 1) {
339- // const dimensions = chartAnnotation.dimensions.filter((d) => d.role !== ChartDimensionRoleType.Time)
340- // const series = getChartSeries(chartAnnotation) || dimensions[1] || dimensions[0]
341- // if (!series) {
342- // throw new Error(
343- // `Cannot find series dimension in chart dimensions: '${JSON.stringify(chartAnnotation.dimensions)}'`
344- // )
345- // }
346- // const seriesName = getPropertyHierarchy(series)
347- // const property = getEntityHierarchy(entityType, seriesName)
348- // if (!property) {
349- // throw new Error(`Cannot find hierarchy for series dimension '${JSON.stringify(series)}'`)
350- // }
351- // const seriesCaption = property.memberCaption
352- // chart_spec.seriesField = seriesCaption
353- // fields.push(seriesCaption)
354- // categoryProperty = getEntityHierarchy(
355- // entityType,
356- // chartAnnotation.dimensions.filter((d) => d.dimension !== series.dimension)[0]
357- // )
358- // const categoryCaption = categoryProperty.memberCaption
359- // chart_spec[categoryField] = categoryCaption
360- // fields.push(categoryCaption)
361- // } else if (chartAnnotation.dimensions?.length) {
362- // categoryProperty = getEntityHierarchy(entityType, chartAnnotation.dimensions[0])
363- // if (!categoryProperty) {
364- // throw new Error(`Not found dimension '${chartAnnotation.dimensions[0].dimension}'`)
365- // }
366- // const categoryCaption = categoryProperty.memberCaption
367- // chart_spec[categoryField] = categoryCaption
368- // fields.push(categoryCaption)
369- // }
370-
371- // chartAnnotation.measures?.forEach((measure) => {
372- // const property = getEntityProperty<PropertyMeasure>(entityType, measure)
373- // // // Type: measure
374- // // _data.forEach((item, index) => {
375- // // item['type'] = property.caption || property.name
376- // // })
377- // if (property.formatting?.unit === '%') {
378- // _data.forEach((item, index) => {
379- // item[property.name] = isNil(data[index][property.name])
380- // ? null
381- // : (data[index][property.name] * 100).toFixed(1)
382- // })
383- // } else {
384- // const result = formatDataValues(data, _data, property.name)
385- // _data = result.values
386- // unit = result.unit
387- // }
388- // })
389-
390- // chart_spec.data = {
391- // values: _data // 此处传入数据。
392- // }
393352 }
394353
395354 categoryMembers = { }
0 commit comments