feat: manually mirror opencoze's code from bytedance
Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* 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节点 - 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节点 - 非workflow节点
|
||||
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,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user