跳到主内容

使用 OpenTelemetry 追踪

LangSmith 可以接受来自基于 OpenTelemetry 的客户端的追踪。本指南将通过示例介绍如何实现这一点。

适用于自托管和欧盟区域部署

对于自托管安装或欧盟区域的组织,请在以下请求中相应更新 LangSmith URL。对于欧盟区域,请使用 eu.api.smith.langchain.com

使用基本的 OpenTelemetry 客户端记录追踪

本节首先介绍如何使用标准 OpenTelemetry 客户端将追踪记录到 LangSmith。

1. 安装

安装 OpenTelemetry SDK、OpenTelemetry 导出器包以及 OpenAI 包

pip install openai
pip install opentelemetry-sdk
pip install opentelemetry-exporter-otlp

2. 配置您的环境

设置端点环境变量,替换为您的具体值

OTEL_EXPORTER_OTLP_ENDPOINT=https://api.smith.langchain.com/otel
OTEL_EXPORTER_OTLP_HEADERS="x-api-key=<your langsmith api key>"

可选:指定一个非“default”的自定义项目名称

OTEL_EXPORTER_OTLP_ENDPOINT=https://api.smith.langchain.com/otel
OTEL_EXPORTER_OTLP_HEADERS="x-api-key=<your langsmith api key>,Langsmith-Project=<project name>"

3. 记录追踪

此代码设置了一个 OTEL 追踪器和导出器,用于将追踪发送到 LangSmith。然后它调用 OpenAI 并发送所需的 OpenTelemetry 属性。

from openai import OpenAI
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import (
BatchSpanProcessor,
)
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter

client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

otlp_exporter = OTLPSpanExporter(
timeout=10,
)
trace.set_tracer_provider(TracerProvider())
trace.get_tracer_provider().add_span_processor(
BatchSpanProcessor(otlp_exporter)
)
tracer = trace.get_tracer(__name__)

def call_openai():
model = "gpt-4o-mini"
with tracer.start_as_current_span("call_open_ai") as span:
span.set_attribute("langsmith.span.kind", "LLM")
span.set_attribute("langsmith.metadata.user_id", "user_123")
span.set_attribute("gen_ai.system", "OpenAI")
span.set_attribute("gen_ai.request.model", model)
span.set_attribute("llm.request.type", "chat")
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{
"role": "user",
"content": "Write a haiku about recursion in programming."
}
]

for i, message in enumerate(messages):
span.set_attribute(f"gen_ai.prompt.{i}.content", str(message["content"]))
span.set_attribute(f"gen_ai.prompt.{i}.role", str(message["role"]))

completion = client.chat.completions.create(
model=model,
messages=messages
)

span.set_attribute("gen_ai.response.model", completion.model)
span.set_attribute("gen_ai.completion.0.content", str(completion.choices[0].message.content))
span.set_attribute("gen_ai.completion.0.role", "assistant")
span.set_attribute("gen_ai.usage.prompt_tokens", completion.usage.prompt_tokens)
span.set_attribute("gen_ai.usage.completion_tokens", completion.usage.completion_tokens)
span.set_attribute("gen_ai.usage.total_tokens", completion.usage.total_tokens)
return completion.choices[0].message

if __name__ == "__main__":
call_openai()

您应该在 LangSmith 仪表盘中看到一个追踪,就像这个一样

支持的 OpenTelemetry 属性和事件映射

通过 OpenTelemetry 将追踪发送到 LangSmith 时,以下属性会映射到 LangSmith 字段。

核心 LangSmith 属性

运行层级属性

确定运行层级的以下属性(langsmith.span.idlangsmith.trace.idlangsmith.span.dotted_orderlangsmith.span.parent_id)在使用 OpenTelemetry 时通常不应手动设置。这些属性主要由 LangSmith SDK 在使用 OpenTelemetry 进行追踪时内部使用。虽然设置这些属性可以提高性能,但对于大多数用例不建议这样做,因为它们可能会干扰正确的运行树构建。有关这些属性如何工作的更多详细信息,请参阅运行数据格式文档

OpenTelemetry 属性LangSmith 字段备注
langsmith.trace.name运行名称覆盖运行的 span 名称
langsmith.span.kind运行类型值:llm, chain, tool, retriever, embedding, prompt, parser
langsmith.span.id运行 IDspan 的唯一标识符
langsmith.trace.id追踪 ID追踪的唯一标识符
langsmith.span.dotted_order点序在执行树中的位置
langsmith.span.parent_id父运行 ID父 span 的 ID
langsmith.trace.session_id会话 ID相关追踪的会话标识符
langsmith.trace.session_name会话名称会话名称
langsmith.span.tags标签附加到 span 的自定义标签(逗号分隔)
langsmith.metadata.{key}metadata.{key}带有 langsmith 前缀的自定义元数据

GenAI 标准属性

OpenTelemetry 属性LangSmith 字段备注
gen_ai.systemmetadata.ls_providerGenAI 系统(例如,“openai”、“anthropic”)
gen_ai.operation.name运行类型将“chat”/“completion”映射到“llm”,“embedding”映射到“embedding”
gen_ai.prompt输入发送到模型的输入提示
gen_ai.completion输出模型生成的输出
gen_ai.prompt.{n}.roleinputs.messages[n].role第 n 条输入消息的角色
gen_ai.prompt.{n}.contentinputs.messages[n].content第 n 条输入消息的内容
gen_ai.prompt.{n}.message.roleinputs.messages[n].role角色的备用格式
gen_ai.prompt.{n}.message.contentinputs.messages[n].content内容的备用格式
gen_ai.completion.{n}.roleoutputs.messages[n].role第 n 条输出消息的角色
gen_ai.completion.{n}.contentoutputs.messages[n].content第 n 条输出消息的内容
gen_ai.completion.{n}.message.roleoutputs.messages[n].role角色的备用格式
gen_ai.completion.{n}.message.contentoutputs.messages[n].content内容的备用格式
gen_ai.tool.nameinvocation_params.tool_name工具名称,同时将运行类型设置为“tool”

GenAI 请求参数

OpenTelemetry 属性LangSmith 字段备注
gen_ai.request.modelinvocation_params.model请求使用的模型名称
gen_ai.response.modelinvocation_params.model响应中返回的模型名称
gen_ai.request.temperatureinvocation_params.temperature温度设置
gen_ai.request.top_pinvocation_params.top_pTop-p 采样设置
gen_ai.request.max_tokensinvocation_params.max_tokens最大令牌设置
gen_ai.request.frequency_penaltyinvocation_params.frequency_penalty频率惩罚设置
gen_ai.request.presence_penaltyinvocation_params.presence_penalty存在惩罚设置
gen_ai.request.seedinvocation_params.seed用于生成的随机种子
gen_ai.request.stop_sequencesinvocation_params.stop停止生成的序列
gen_ai.request.top_kinvocation_params.top_kTop-k 采样参数
gen_ai.request.encoding_formatsinvocation_params.encoding_formats输出编码格式

GenAI 使用指标

OpenTelemetry 属性LangSmith 字段备注
gen_ai.usage.input_tokensusage_metadata.input_tokens使用的输入令牌数量
gen_ai.usage.output_tokensusage_metadata.output_tokens使用的输出令牌数量
gen_ai.usage.total_tokensusage_metadata.total_tokens使用的总令牌数量
gen_ai.usage.prompt_tokensusage_metadata.input_tokens使用的输入令牌数量(已弃用)
gen_ai.usage.completion_tokensusage_metadata.output_tokens使用的输出令牌数量(已弃用)

TraceLoop 属性

OpenTelemetry 属性LangSmith 字段备注
traceloop.entity.input输入来自 TraceLoop 的完整输入值
traceloop.entity.output输出来自 TraceLoop 的完整输出值
traceloop.entity.name运行名称来自 TraceLoop 的实体名称
traceloop.span.kind运行类型映射到 LangSmith 运行类型
traceloop.llm.request.type运行类型“embedding”映射到“embedding”,其他映射到“llm”
traceloop.association.properties.{key}metadata.{key}带有 traceloop 前缀的自定义元数据

OpenInference 属性

OpenTelemetry 属性LangSmith 字段备注
input.value输入完整的输入值,可以是字符串或 JSON
output.value输出完整的输出值,可以是字符串或 JSON
openinference.span.kind运行类型将各种类型映射到 LangSmith 运行类型
llm.systemmetadata.ls_providerLLM 系统提供商
llm.model_namemetadata.ls_model_name来自 OpenInference 的模型名称
tool.name运行名称当 span 类型为“TOOL”时的工具名称
metadatametadata.*要合并的元数据的 JSON 字符串

LLM 属性

OpenTelemetry 属性LangSmith 字段备注
llm.input_messagesinputs.messages输入消息
llm.output_messagesoutputs.messages输出消息
llm.token_count.promptusage_metadata.input_tokens提示令牌计数
llm.token_count.completionusage_metadata.output_tokens完成令牌计数
llm.token_count.totalusage_metadata.total_tokens总令牌计数
llm.usage.total_tokensusage_metadata.total_tokens备用总令牌计数
llm.invocation_parametersinvocation_params.*调用参数的 JSON 字符串
llm.presence_penaltyinvocation_params.presence_penalty存在惩罚
llm.frequency_penaltyinvocation_params.frequency_penalty频率惩罚
llm.request.functionsinvocation_params.functions函数定义

提示模板属性

OpenTelemetry 属性LangSmith 字段备注
llm.prompt_template.variables运行类型将运行类型设置为“prompt”,与 input.value 一起使用

检索器属性

OpenTelemetry 属性LangSmith 字段备注
retrieval.documents.{n}.document.contentoutputs.documents[n].page_content第 n 个检索文档的内容
retrieval.documents.{n}.document.metadataoutputs.documents[n].metadata第 n 个检索文档的元数据 (JSON)

工具属性

OpenTelemetry 属性LangSmith 字段备注
toolsinvocation_params.tools工具定义数组
tool_argumentsinvocation_params.tool_arguments工具参数,以 JSON 或键值对形式

Logfire 属性

OpenTelemetry 属性LangSmith 字段备注
prompt输入Logfire 提示输入
all_messages_events输出Logfire 消息事件输出
eventsinputs/outputsLogfire 事件数组,拆分输入/选择事件

OpenTelemetry 事件映射

事件名称LangSmith 字段备注
gen_ai.content.prompt输入从事件属性中提取提示内容
gen_ai.content.completion输出从事件属性中提取完成内容
gen_ai.system.messageinputs.messages[]对话中的系统消息
gen_ai.user.messageinputs.messages[]对话中的用户消息
gen_ai.assistant.messageoutputs.messages[]对话中的助手消息
gen_ai.tool.messageoutputs.messages[]工具响应消息
gen_ai.choice输出带有结束原因的模型选择/响应
exceptionstatus, error将状态设置为“error”并提取异常消息/堆栈追踪

事件属性提取

对于消息事件,提取以下属性

  • content → 消息内容
  • role → 消息角色
  • id → tool_call_id(用于工具消息)
  • gen_ai.event.content → 完整消息 JSON

对于选择事件

  • finish_reason → 选择结束原因
  • message.content → 选择消息内容
  • message.role → 选择消息角色
  • tool_calls.{n}.id → 工具调用 ID
  • tool_calls.{n}.function.name → 工具函数名称
  • tool_calls.{n}.function.arguments → 工具函数参数
  • tool_calls.{n}.type → 工具调用类型

对于异常事件

  • exception.message → 错误消息
  • exception.stacktrace → 错误堆栈追踪(附加到消息)

使用 Traceloop SDK 记录追踪

Traceloop SDK 是一个兼容 OpenTelemetry 的 SDK,涵盖了一系列模型、向量数据库和框架。如果您有兴趣集成此 SDK 支持的工具,可以使用此 SDK 与 OpenTelemetry 一起将追踪记录到 LangSmith。

要查看 Traceloop SDK 支持的集成,请参阅Traceloop SDK 文档

要开始使用,请按照以下步骤操作

1. 安装

pip install traceloop-sdk
pip install openai

2. 配置您的环境

设置环境变量

TRACELOOP_BASE_URL=https://api.smith.langchain.com/otel
TRACELOOP_HEADERS=x-api-key=<your_langsmith_api_key>

可选:指定一个非“default”的自定义项目名称

TRACELOOP_HEADERS=x-api-key=<your_langsmith_api_key>,Langsmith-Project=<langsmith_project_name>

3. 初始化 SDK

要使用 SDK,您需要在记录追踪之前对其进行初始化

from traceloop.sdk import Traceloop
Traceloop.init()

4. 记录追踪

这是一个使用 OpenAI 聊天完成的完整示例

import os
from openai import OpenAI
from traceloop.sdk import Traceloop

client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
Traceloop.init()

completion = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{
"role": "user",
"content": "Write a haiku about recursion in programming."
}
]
)

print(completion.choices[0].message)

您应该在 LangSmith 仪表盘中看到一个追踪,就像这个一样

使用 Arize SDK 进行追踪

通过 Arize SDK 和 OpenTelemetry,您可以将来自其他多个框架的追踪记录到 LangSmith。下面是追踪 CrewAI 到 LangSmith 的示例,您可以在此处找到支持的框架的完整列表。要使此示例适用于其他框架,您只需更改 instrumentor 以匹配该框架。

1. 安装

首先,安装所需的包

pip install -qU arize-phoenix-otel openinference-instrumentation-crewai crewai crewai-tools

2. 配置您的环境

接下来,设置以下环境变量

OPENAI_API_KEY=<your_openai_api_key>
SERPER_API_KEY=<your_serper_api_key>

3. 设置 instrumentor

在运行任何应用程序代码之前,让我们设置 instrumentor(您可以将其替换为此处支持的任何框架)

from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter

# Add LangSmith API Key for tracing
LANGSMITH_API_KEY = "YOUR_API_KEY"
# Set the endpoint for OTEL collection
ENDPOINT = "https://api.smith.langchain.com/otel/v1/traces"
# Select the project to trace to
LANGSMITH_PROJECT = "YOUR_PROJECT_NAME"

# Create the OTLP exporter
otlp_exporter = OTLPSpanExporter(
endpoint=ENDPOINT,
headers={"x-api-key": LANGSMITH_API_KEY, "Langsmith-Project": LANGSMITH_PROJECT}
)

# Set up the trace provider
provider = TracerProvider()
processor = BatchSpanProcessor(otlp_exporter)
provider.add_span_processor(processor)

# Now instrument CrewAI
from openinference.instrumentation.crewai import CrewAIInstrumentor
CrewAIInstrumentor().instrument(tracer_provider=provider)

4. 记录追踪

现在,您可以运行 CrewAI 工作流,追踪将自动记录到 LangSmith

from crewai import Agent, Task, Crew, Process
from crewai_tools import SerperDevTool

search_tool = SerperDevTool()

# Define your agents with roles and goals
researcher = Agent(
role='Senior Research Analyst',
goal='Uncover cutting-edge developments in AI and data science',
backstory="""You work at a leading tech think tank.
Your expertise lies in identifying emerging trends.
You have a knack for dissecting complex data and presenting actionable insights.""",
verbose=True,
allow_delegation=False,
# You can pass an optional llm attribute specifying what model you wanna use.
# llm=ChatOpenAI(model_name="gpt-3.5", temperature=0.7),
tools=[search_tool]
)
writer = Agent(
role='Tech Content Strategist',
goal='Craft compelling content on tech advancements',
backstory="""You are a renowned Content Strategist, known for your insightful and engaging articles.
You transform complex concepts into compelling narratives.""",
verbose=True,
allow_delegation=True
)

# Create tasks for your agents
task1 = Task(
description="""Conduct a comprehensive analysis of the latest advancements in AI in 2024.
Identify key trends, breakthrough technologies, and potential industry impacts.""",
expected_output="Full analysis report in bullet points",
agent=researcher
)

task2 = Task(
description="""Using the insights provided, develop an engaging blog
post that highlights the most significant AI advancements.
Your post should be informative yet accessible, catering to a tech-savvy audience.
Make it sound cool, avoid complex words so it doesn't sound like AI.""",
expected_output="Full blog post of at least 4 paragraphs",
agent=writer
)

# Instantiate your crew with a sequential process
crew = Crew(
agents=[researcher, writer],
tasks=[task1, task2],
verbose= False,
process = Process.sequential
)

# Get your crew to work!
result = crew.kickoff()

print("######################")
print(result)

您应该在您的 LangSmith 项目中看到一个像这样的追踪


此页面有帮助吗?


您可以留下详细反馈 在 GitHub 上.