Skip to content

Commit

Permalink
feat: timeout in tool of chatbi lark
Browse files Browse the repository at this point in the history
  • Loading branch information
meta-d committed Sep 29, 2024
1 parent 4fdf462 commit dce15d5
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 54 deletions.
11 changes: 5 additions & 6 deletions packages/analytics/src/chatbi/conversation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,9 @@ import {
} from '@metad/ocap-core'
import {
AgentState,
Copilot,
CopilotCheckpointSaver,
CopilotKnowledgeService,
createExampleFewShotPrompt,
createLLM,
createReactAgent,
createReferencesRetrieverTool,
} from '@metad/server-ai'
Expand Down Expand Up @@ -51,8 +49,9 @@ import { createIndicatorTool } from './tools/indicator'
* ChatBI conversation for Lark
*/
export class ChatBIConversation implements IChatBIConversation {
static readonly toolCallTimeout = 30 * 1000 // 30s

private readonly logger = new Logger(ChatBIConversation.name)
static readonly toolCallTimeout = 10000
readonly commandName = 'chatbi'

public id: string = null
Expand Down Expand Up @@ -339,7 +338,7 @@ ${createAgentStepsInstructions(
if (isString(content) && content.startsWith('Error:')) {
this.logger.error(content)
const toolCallMessage = state.messages[state.messages.length - 2]
this.logger.debug((<ToolMessage>toolCallMessage).lc_kwargs)
this.logger.verbose((<ToolMessage>toolCallMessage).lc_kwargs)
return 'agent'
}

Expand Down Expand Up @@ -443,7 +442,7 @@ ${createAgentStepsInstructions(

if (content) {
verboseContent = content
this.logger.debug(`[ChatBI] [Graph]: verbose content`, verboseContent)
this.logger.debug(`[ChatBI] [Graph] verbose content: `, verboseContent)
// 对话结束时还有正在思考的消息,则意味着出现错误
if (['thinking', 'continuing', 'waiting'].includes(this.message?.status)) {
this.message.update({
Expand All @@ -462,7 +461,7 @@ ${createAgentStepsInstructions(
this.status = 'idle'

} catch (err: any) {
console.error(err)
this.logger.error(err)
this.status = 'error'
if (err instanceof ToolInputParsingException) {
this.chatContext.larkService.errorMessage(this.chatContext, err)
Expand Down
78 changes: 36 additions & 42 deletions packages/analytics/src/chatbi/tools/answer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import {
tryFixVariableSlicer,
workOutTimeRangeSlicers
} from '@metad/ocap-core'
import { race } from '@metad/server-common'
import { getErrorMessage, race } from '@metad/server-common'
import { firstValueFrom, Subject, takeUntil } from 'rxjs'
import { ChatBIConversation } from '../conversation'
import { ChatLarkMessage } from '../message'
Expand Down Expand Up @@ -63,52 +63,46 @@ export function createChatAnswerTool(context: ChatContext, larkContext: ChatBILa
async (answer): Promise<string> => {
logger.debug(`Execute copilot action 'answerQuestion':`, JSON.stringify(answer, null, 2))
try {
try {
// 限制总体超时时间
return await race(
ChatBIConversation.toolCallTimeout,
(async () => {
let entityType = null
if (answer.dataSettings) {
// Make sure datasource exists
const _dataSource = await dsCoreService._getDataSource(answer.dataSettings.dataSource)
const entity = await firstValueFrom(
dsCoreService.selectEntitySet(
answer.dataSettings.dataSource,
answer.dataSettings.entitySet
)
// 限制总体超时时间
return await race(
ChatBIConversation.toolCallTimeout,
(async () => {
let entityType = null
if (answer.dataSettings) {
// Make sure datasource exists
const _dataSource = await dsCoreService._getDataSource(answer.dataSettings.dataSource)
const entity = await firstValueFrom(
dsCoreService.selectEntitySet(
answer.dataSettings.dataSource,
answer.dataSettings.entitySet
)
entityType = entity.entityType
}

// Fetch data for chart or table or kpi
if (answer.dimensions?.length || answer.measures?.length) {
const { categoryMembers } = await drawChartMessage(
{ ...context, entityType: entityType || context.entityType },
conversation,
answer as ChatAnswer
)
// Max limit 20 members
const members = categoryMembers
? JSON.stringify(Object.values(categoryMembers).slice(0, 20))
: 'Empty'
)
entityType = entity.entityType
}

return `The analysis data has been displayed to the user. The dimension members involved in this data analysis are:
// Fetch data for chart or table or kpi
if (answer.dimensions?.length || answer.measures?.length) {
const { categoryMembers } = await drawChartMessage(
{ ...context, entityType: entityType || context.entityType },
conversation,
answer as ChatAnswer
)
// Max limit 20 members
const members = categoryMembers
? JSON.stringify(Object.values(categoryMembers).slice(0, 20))
: 'Empty'

return `The analysis data has been displayed to the user. The dimension members involved in this data analysis are:
${members}
Please give more analysis suggestions about other dimensions or filter by dimensioin members, 3 will be enough.`
}

return `图表答案已经回复给用户了,请不要重复回答了。`
})()
)
} catch (err) {
throw new Error(
`Timeout in getting cube context (dataSource=${answer.dataSettings.dataSource}, cube=${answer.dataSettings.entitySet})`
)
}
}

return `图表答案已经回复给用户了,请不要重复回答了。`
})()
)
} catch (err) {
logger.error(err)
return `Error: ${err}。如果需要用户提供更多信息,请直接提醒用户。`
logger.debug(getErrorMessage(err))
return `Error: ${getErrorMessage(err)}; If more information is needed from the user, remind the user directly.`
}
},
{
Expand Down
8 changes: 5 additions & 3 deletions packages/analytics/src/chatbi/tools/cube-context.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { tool } from '@langchain/core/tools'
import { isEntitySet, markdownModelCube } from '@metad/ocap-core'
import { race } from '@metad/server-common'
import { getErrorMessage, race } from '@metad/server-common'
import { firstValueFrom, switchMap } from 'rxjs'
import { ChatBIModelService } from '../../chatbi-model/'
import { ChatContext, GetCubesContextSchema } from '../types'
Expand All @@ -17,7 +17,7 @@ export function createCubeContextTool(context: ChatContext, modelService: ChatBI
(async () => {
let context = ''
for await (const item of cubes) {
logger.debug(` get context for:`, item.modelId, item.name)
logger.debug(` get context for (modelId=${item.modelId}, cube=${item.name})`)

let entityType = await conversation.getCubeCache(item.modelId, item.name)
if (!entityType) {
Expand Down Expand Up @@ -53,7 +53,9 @@ export function createCubeContextTool(context: ChatContext, modelService: ChatBI
})()
)
} catch (err) {
return 'Error:' + err.message
const errorInfo = 'Error: ' + getErrorMessage(err)
logger.debug(`Call getCubeContext: ` + errorInfo)
return errorInfo
}
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class OlapQueryHandler implements IQueryHandler<DataSourceOlapQuery> {
const { id, sessionId, dataSourceId, body, forceRefresh, acceptLanguage } = query.input
const user = query.user

this.logger.debug(`Executing OLAP query [${id}] for dataSource: ${dataSourceId}`)
this.logger.verbose(`Executing OLAP query [${id}] for dataSource: ${dataSourceId}`)

let dataSource = await this.dsService.findOne(dataSourceId, {
relations: ['type', 'authentications']
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ITryRequest, RequestContext } from '@metad/server-core'
import { ITryRequest } from '@metad/server-core'
import { Logger } from '@nestjs/common'
import { ConfigService } from '@nestjs/config'
import { IQueryHandler, QueryBus, QueryHandler } from '@nestjs/cqrs'
Expand Down Expand Up @@ -26,7 +26,7 @@ export class ModelOlapQueryHandler implements IQueryHandler<ModelOlapQuery> {
const { id, sessionId, modelId, body, forceRefresh, acceptLanguage } = query.input
const user = query.user

this.logger.debug(`Executing OLAP query [${id}] for model: ${modelId}`)
this.logger.verbose(`Executing OLAP query [${id}] for model: ${modelId}`)

let key = ''
const model = await this.semanticModelService.findOne(modelId, {
Expand Down

0 comments on commit dce15d5

Please sign in to comment.