Agent 多跳链路追踪实现
import { trace, context, SpanKind, SpanStatusCode } from '@opentelemetry/api';
const tracer = trace.getTracer('agent-tracer', '1.0.0');
class AgentTracer {
// 追踪 Agent 对话
async traceConversation(
userId: string,
message: string
): Promise {
return tracer.startActiveSpan(
'agent-conversation',
{ kind: SpanKind.SERVER },
async (span) => {
// 设置 Tags
span.setAttributes({
'user.id': userId,
'message.length': message.length,
'conversation.type': 'customer-support'
});
try {
// 1. 理解用户意图
const intent = await this.traceIntentAnalysis(span, message);
// 2. 检索知识库
const knowledge = await this.traceKnowledgeRetrieval(span, intent);
// 3. 调用 LLM 生成回复
const response = await this.traceLLMCompletion(span, intent, knowledge);
// 4. 后处理与验证
const finalResponse = await this.tracePostProcessing(span, response);
span.setStatus({ code: SpanStatusCode.OK });
return finalResponse;
} catch (error) {
span.setStatus({
code: SpanStatusCode.ERROR,
message: error.message
});
span.recordException(error);
throw error;
} finally {
span.end();
}
}
);
}
// 追踪意图分析
private async traceIntentAnalysis(parentSpan: any, message: string) {
return tracer.startActiveSpan(
'intent-analysis',
{ kind: SpanKind.INTERNAL },
async (span) => {
span.setAttributes({
'analysis.model': 'intent-classifier-v2',
'message.preview': message.substring(0, 100)
});
try {
// 模拟意图分析
await new Promise(resolve => setTimeout(resolve, 50));
const intent = {
category: 'billing',
confidence: 0.92,
entities: ['invoice', 'payment']
};
span.setAttributes({
'intent.category': intent.category,
'intent.confidence': intent.confidence
});
span.setStatus({ code: SpanStatusCode.OK });
return intent;
} catch (error) {
span.setStatus({ code: SpanStatusCode.ERROR });
throw error;
} finally {
span.end();
}
}
);
}
// 追踪知识检索
private async traceKnowledgeRetrieval(parentSpan: any, intent: any) {
return tracer.startActiveSpan(
'knowledge-retrieval',
{ kind: SpanKind.CLIENT },
async (span) => {
span.setAttributes({
'retrieval.system': 'vector-database',
'retrieval.topK': 5
});
try {
// 模拟向量检索
await new Promise(resolve => setTimeout(resolve, 120));
const knowledge = [
{ id: 'doc-1', score: 0.89 },
{ id: 'doc-2', score: 0.85 }
];
span.setAttributes({
'retrieval.results.count': knowledge.length
});
span.setStatus({ code: SpanStatusCode.OK });
return knowledge;
} catch (error) {
span.setStatus({ code: SpanStatusCode.ERROR });
throw error;
} finally {
span.end();
}
}
);
}
// 追踪 LLM 调用
private async traceLLMCompletion(
parentSpan: any,
intent: any,
knowledge: any[]
) {
return tracer.startActiveSpan(
'llm-completion',
{ kind: SpanKind.CLIENT },
async (span) => {
span.setAttributes({
'llm.provider': 'openai',
'llm.model': 'gpt-4-turbo',
'llm.temperature': 0.7,
'llm.max_tokens': 1024
});
try {
// 模拟 LLM 调用
await new Promise(resolve => setTimeout(resolve, 1500));
const response = {
content: 'Here is the answer...',
usage: {
prompt_tokens: 256,
completion_tokens: 128,
total_tokens: 384
}
};
span.setAttributes({
'llm.token_count': response.usage.total_tokens,
'llm.response.length': response.content.length
});
// 记录事件
span.addEvent('llm.response.received', {
'response.tokens': response.usage.total_tokens
});
span.setStatus({ code: SpanStatusCode.OK });
return response;
} catch (error) {
span.setStatus({ code: SpanStatusCode.ERROR });
throw error;
} finally {
span.end();
}
}
);
}
// 追踪后处理
private async tracePostProcessing(parentSpan: any, response: any) {
return tracer.startActiveSpan(
'post-processing',
{ kind: SpanKind.INTERNAL },
async (span) => {
try {
// 模拟后处理(内容过滤、格式化等)
await new Promise(resolve => setTimeout(resolve, 30));
span.setStatus({ code: SpanStatusCode.OK });
return response.content;
} catch (error) {
span.setStatus({ code: SpanStatusCode.ERROR });
throw error;
} finally {
span.end();
}
}
);
}
}
// 使用示例
const agentTracer = new AgentTracer();
// 处理用户请求
async function handleUserMessage(userId: string, message: string) {
try {
const response = await agentTracer.traceConversation(userId, message);
return response;
} catch (error) {
console.error('Conversation failed:', error);
throw error;
}
}