181 lines
4.7 KiB
TypeScript
181 lines
4.7 KiB
TypeScript
/*
|
|
* Copyright 2025 coze-dev Authors
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
import {
|
|
SpanCategory,
|
|
SpanStatus,
|
|
SpanType,
|
|
} from '@coze-arch/bot-api/ob_query_api';
|
|
|
|
import {
|
|
type CTrace,
|
|
type CSPanBatch,
|
|
type CSpan,
|
|
type CSpanSingle,
|
|
} from '../typings/cspan';
|
|
import { virtualStartSpanId } from '../constant';
|
|
|
|
export const getSpanProp = (span: CSpan | CTrace, key: string) => {
|
|
if (checkIsBatchBasicCSpan(span)) {
|
|
const batchSpan = span as CSPanBatch;
|
|
return (
|
|
batchSpan[key as keyof CSPanBatch] ??
|
|
batchSpan.spans[0]?.extra?.[key as keyof CSPanBatch['spans'][0]['extra']]
|
|
);
|
|
} else {
|
|
const singleSpan = span as CSpanSingle;
|
|
return (
|
|
singleSpan[key as keyof CSpanSingle] ??
|
|
singleSpan.extra?.[key as keyof CSpanSingle['extra']]
|
|
);
|
|
}
|
|
};
|
|
|
|
export const getTokens = (
|
|
span: CSpan,
|
|
): {
|
|
input_tokens?: number;
|
|
output_tokens?: number;
|
|
} => {
|
|
if ('spans' in span) {
|
|
const spanBatch = span as CSPanBatch;
|
|
let inputTokensSum = 0;
|
|
let outputTokensSum = 0;
|
|
spanBatch.spans.forEach(subSpan => {
|
|
const inputTokens = subSpan?.extra?.input_tokens ?? 0;
|
|
const outputTokens = subSpan?.extra?.output_tokens ?? 0;
|
|
inputTokensSum += inputTokens;
|
|
outputTokensSum += outputTokens;
|
|
});
|
|
return {
|
|
input_tokens: inputTokensSum,
|
|
output_tokens: outputTokensSum,
|
|
};
|
|
} else if (
|
|
span.type === SpanType.UserInput ||
|
|
span.type === SpanType.UserInputV2 ||
|
|
span.type === SpanType.Workflow
|
|
) {
|
|
// SingleSpan Node - Workflow
|
|
const inputTokens = getSpanProp(span, 'input_tokens_sum') as number;
|
|
const outputTokens = getSpanProp(span, 'output_tokens_sum') as number;
|
|
|
|
return {
|
|
input_tokens: inputTokens,
|
|
output_tokens: outputTokens,
|
|
};
|
|
} else {
|
|
// SingleSpan Node - Non-workflow Node
|
|
const inputTokens = getSpanProp(span, 'input_tokens') as number;
|
|
const outputTokens = getSpanProp(span, 'output_tokens') as number;
|
|
|
|
return {
|
|
input_tokens: inputTokens,
|
|
output_tokens: outputTokens,
|
|
};
|
|
}
|
|
};
|
|
|
|
export const isBatchSpanType = (type: SpanType): boolean => {
|
|
const whites = [
|
|
SpanType.LLMBatchCall,
|
|
SpanType.WorkflowLLMBatchCall,
|
|
SpanType.PluginToolBatch,
|
|
SpanType.WorkflowPluginToolBatch,
|
|
SpanType.CodeBatch,
|
|
SpanType.WorkflowCodeBatch,
|
|
];
|
|
return whites.includes(type);
|
|
};
|
|
|
|
export const checkIsBatchBasicCSpan = (span: CSpan | CTrace) => 'spans' in span;
|
|
|
|
export const isVisibleSpan = (span: CSpan) => {
|
|
const whites = [
|
|
SpanType.Unknown,
|
|
SpanType.UserInput,
|
|
SpanType.UserInputV2,
|
|
SpanType.ThirdParty,
|
|
SpanType.ScheduledTasks,
|
|
SpanType.OpenDialog,
|
|
SpanType.InvokeAgent,
|
|
SpanType.RestartAgent,
|
|
SpanType.SwitchAgent,
|
|
SpanType.LLMCall,
|
|
SpanType.WorkflowLLMCall,
|
|
SpanType.LLMBatchCall,
|
|
SpanType.WorkflowLLMBatchCall,
|
|
SpanType.Workflow,
|
|
SpanType.WorkflowStart,
|
|
SpanType.WorkflowEnd,
|
|
SpanType.PluginTool,
|
|
SpanType.WorkflowPluginTool,
|
|
SpanType.PluginToolBatch,
|
|
SpanType.WorkflowPluginToolBatch,
|
|
SpanType.Knowledge,
|
|
SpanType.WorkflowKnowledge,
|
|
SpanType.Code,
|
|
SpanType.WorkflowCode,
|
|
SpanType.CodeBatch,
|
|
SpanType.WorkflowCodeBatch,
|
|
SpanType.Condition,
|
|
SpanType.WorkflowCondition,
|
|
SpanType.Card,
|
|
SpanType.WorkflowMessage,
|
|
SpanType.Hook,
|
|
SpanType.BWStart,
|
|
SpanType.BWEnd,
|
|
SpanType.BWBatch,
|
|
SpanType.BWLoop,
|
|
SpanType.BWCondition,
|
|
SpanType.BWLLM,
|
|
SpanType.BWParallel,
|
|
SpanType.BWScript,
|
|
SpanType.BWVariable,
|
|
SpanType.BWCallFlow,
|
|
SpanType.BWConnector,
|
|
];
|
|
|
|
return whites.includes(span.type);
|
|
};
|
|
|
|
export const genVirtualStart = (spans: CSpan[]): CSpan => {
|
|
let startAt = Number.POSITIVE_INFINITY;
|
|
let endAt = Number.NEGATIVE_INFINITY;
|
|
spans.forEach(span => {
|
|
startAt = Math.min(startAt, span.start_time);
|
|
endAt = Math.max(endAt, span.start_time + span.latency);
|
|
});
|
|
if (
|
|
startAt === Number.POSITIVE_INFINITY ||
|
|
endAt === Number.NEGATIVE_INFINITY
|
|
) {
|
|
startAt = 0;
|
|
endAt = 0;
|
|
}
|
|
return {
|
|
id: virtualStartSpanId,
|
|
parent_id: '',
|
|
trace_id: '',
|
|
name: '',
|
|
type: SpanType.UserInput,
|
|
category: SpanCategory.Start,
|
|
status: SpanStatus.Unknown,
|
|
start_time: startAt,
|
|
latency: endAt - startAt,
|
|
};
|
|
};
|