gallyga's picture
Add n8n Chinese version
aec3094
import type {
NodeParameterValueType,
INodeParameterResourceLocator,
IRunData,
INodeExecutionData,
} from 'n8n-workflow';
import { NodeConnectionTypes } from 'n8n-workflow';
type TokenUsageValues = {
completionTokens: number;
promptTokens: number;
totalTokens: number;
};
type TokenUsageInfo = Record<`${string}__${number}` | 'total', TokenUsageValues>;
function isRlcValue(value: NodeParameterValueType): value is INodeParameterResourceLocator {
return Boolean(
typeof value === 'object' && value && 'value' in value && '__rl' in value && value.__rl,
);
}
export function checkNodeParameterNotEmpty(value: NodeParameterValueType) {
if (value === undefined || value === null || value === '') {
return false;
}
if (isRlcValue(value)) {
return checkNodeParameterNotEmpty(value.value);
}
return true;
}
export function extractTokenUsage(executionRunData: IRunData) {
const result: TokenUsageInfo = {
total: {
completionTokens: 0,
promptTokens: 0,
totalTokens: 0,
},
};
const extractFromNode = (nodeName: string, nodeData: INodeExecutionData, index: number) => {
function isValidTokenInfo(data: unknown): data is TokenUsageValues {
return (
typeof data === 'object' &&
data !== null &&
'completionTokens' in data &&
'promptTokens' in data &&
'totalTokens' in data &&
typeof data.completionTokens === 'number' &&
typeof data.promptTokens === 'number' &&
typeof data.totalTokens === 'number'
);
}
const tokenInfo = nodeData.json?.tokenUsage ?? nodeData.json?.tokenUsageEstimate;
if (tokenInfo && isValidTokenInfo(tokenInfo)) {
result[`${nodeName}__${index}`] = {
completionTokens: tokenInfo.completionTokens,
promptTokens: tokenInfo.promptTokens,
totalTokens: tokenInfo.totalTokens,
};
result.total.completionTokens += tokenInfo.completionTokens;
result.total.promptTokens += tokenInfo.promptTokens;
result.total.totalTokens += tokenInfo.totalTokens;
}
};
for (const [nodeName, nodeData] of Object.entries(executionRunData)) {
if (nodeData[0]?.data?.[NodeConnectionTypes.AiLanguageModel]) {
for (const [index, node] of nodeData.entries()) {
const modelNodeExecutionData = node.data?.[NodeConnectionTypes.AiLanguageModel]?.[0]?.[0];
if (modelNodeExecutionData) {
extractFromNode(nodeName, modelNodeExecutionData, index);
}
}
}
}
return result;
}