- 可观测性
- AI 评测
- LLMOps
- AI 应用
- 人工智能
【免费下载链接】phoenix
AI Observability & Evaluation
导读:本文以 Phoenix 的 Python 自动插桩能力为主线,讲解如何在不修改业务代码的前提下,通过运行时补丁(runtime patching)为 OpenAI、Anthropic、LangChain、LlamaIndex 等主流 LLM SDK 与框架自动生成追踪 Span。读完本文,你将掌握phoenix.otel.register的完整配置(含选择性插桩与 OTel GenAI 原生插桩两种模式)、gen_ai.*语义约定的自动转换机制,以及自动插桩的边界与手动插桩的补充方案,让 Phoenix UI 自动呈现模型名、输入输出、Token 用量与耗时等关键信息。
一、自动插桩的工作原理
自动插桩(auto-instrumentation)的核心思想是:对已安装的受支持库在运行时打补丁(patch),从而自动创建 Span。它适用于 LangChain、LlamaIndex、OpenAI SDK 等官方支持框架;对于自定义业务逻辑,则需要配合手动插桩来补全。
从源码结构看,Phoenix 的自动插桩是围绕OpenInference 插桩器入口点(entry point)机制实现的。在 otel.py 中,_auto_instrument_installed_openinference_libraries会读取openinference_instrumentor组的所有 entry points,逐个实例化并调用其instrument(tracer_provider=...):
def _auto_instrument_installed_openinference_libraries(tracer_provider: TracerProvider) -> None: openinference_entry_points = entry_points(group="openinference_instrumentor") if not openinference_entry_points: warnings.warn( "No OpenInference instrumentors found. " "Maybe you need to update your OpenInference version? " "Skipping auto-instrumentation." ) return for entry_point in openinference_entry_points: instrumentor_cls = entry_point.load() instrumentor = instrumentor_cls() instrumentor.instrument(tracer_provider=tracer_provider)这段代码解释了"自动发现"的本质:只要你通过pip install openinference-instrumentation-{name}安装了对应的插桩包,Phoenix 就能在register(auto_instrument=True)时自动发现并启用它,无需在代码里显式 import 任何 instrumentor。
二、支持的框架一览
Python 生态下,Phoenix 自动插桩覆盖两类目标:
| 类别 | 支持范围 | 安装方式 |
|---|---|---|
| LLM SDK | OpenAI、Anthropic、Bedrock、Mistral、Vertex AI、Groq、Ollama | pip install openinference-instrumentation-{name} |
| 框架 | LangChain、LlamaIndex、DSPy、CrewAI、Instructor、Haystack | pip install openinference-instrumentation-{name} |
命名规律统一:包名均为openinference-instrumentation-<名称>,例如 OpenAI 对应openinference-instrumentation-openai、LangChain 对应openinference-instrumentation-langchain、LlamaIndex 对应openinference-instrumentation-llama-index(参考 setup-python.md 中的安装清单)。每个插桩器生成不同 Span Kind(LLM、CHAIN、RETRIEVER、TOOL 等)的完整属性结构,可查阅 references 目录下的span-*.md文件。
三、快速开始:两条命令 + 一行注册
第一步,安装核心包与目标插桩器:
pip install arize-phoenix-otel pip install openinference-instrumentation-openai # 按需添加其他插桩器第二步,注册并自动插桩:
from phoenix.otel import register register(project_name="my-app", auto_instrument=True) # 自动发现并启用所有已安装的插桩器第三步,正常使用客户端即可(无需任何埋点):
from phoenix.otel import register from openai import OpenAI register(project_name="my-app", auto_instrument=True) client = OpenAI() response = client.chat.completions.create( model="gpt-4", messages=[{"role": "user", "content": "Hello!"}] )运行后,Span 会出现在 Phoenix UI 的my-app项目中,模型名、输入/输出、Token 用量、耗时等属性均由插桩器自动采集。各 Span Kind 的完整属性 Schema 见 span-llm.md、span-chain.md 等文件。
四、register()参数详解:从源码理解默认行为
register是arize-phoenix-otel的入口函数,其完整签名定义于 otel.py,关键参数如下:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
endpoint | str | 环境变量推断 | Collector 端点;未传时读取PHOENIX_COLLECTOR_ENDPOINT,再回退到OTEL_EXPORTER_OTLP_ENDPOINT,最终默认为http://localhost:6006 |
project_name | str | 环境变量推断 | Span 归属的项目名;未传时读取PHOENIX_PROJECT(别名PHOENIX_PROJECT_NAME),最后回退到"default" |
batch | bool | False(源码签名) | 为True时使用BatchSpanProcessor,为False时使用SimpleSpanProcessor;生产环境建议显式传batch=True,并在启动时打印的配置详情中确认 Span Processor 类型 |
set_global_tracer_provider | bool | True | 是否将该 TracerProvider 设为 OpenTelemetry 全局默认,设为False可避免影响应用内已有的全局配置 |
headers | dict | 环境变量推断 | 发送给 Collector 的请求头,未传时读取PHOENIX_CLIENT_HEADERS或OTEL_EXPORTER_OTLP_HEADERS |
protocol | "http/protobuf"|"grpc" | 自动推断 | 传输协议,会根据 endpoint 的 URL 形态自动判断,也可显式指定 |
verbose | bool | True | 是否向 stdout 打印追踪配置详情 |
auto_instrument | bool | False | 为True时自动插桩所有已安装的 OpenInference 库 |
api_key | str | 环境变量推断 | Phoenix Cloud 认证用;未传时读取PHOENIX_API_KEY,内部会拼装为authorization: Bearer <api_key>请求头 |
从源码看两个容易被忽略的细节:
- 项目名始终写入资源:
register会强制把project_name合并进Resource的project.name属性(见 otel.py)。即使调用方传入自定义resource,project.name也会被合并进去,不会覆盖用户的其它资源属性。 - 协议推断逻辑:endpoint 路径以
/v1/traces结尾时走 HTTP+protobuf;无路径且端口等于PHOENIX_GRPC_PORT(默认 4317)时走 gRPC(见_maybe_http_endpoint/_maybe_grpc_endpoint)。HTTP 模式下register会自动补全/v1/traces后缀并保留已有路径前缀,因此部署在反向代理子路径下的 Phoenix 也能正常工作——例如endpoint="http://host/prefix"会实际发送到http://host/prefix/v1/traces。
生产推荐配置示例(完整示例见 otel.py 的 docstring):
from phoenix.otel import register tracer_provider = register( project_name="my-app", batch=True, # 批量上报,生产推荐 auto_instrument=True, # 自动插桩 api_key="your-api-key", # 或改用 PHOENIX_API_KEY 环境变量 )BatchSpanProcessor的批量行为还可通过标准 OTLP 环境变量调优(otel.py 的 docstring 列出):OTEL_BSP_SCHEDULE_DELAY(调度间隔)、OTEL_BSP_MAX_QUEUE_SIZE(队列上限)、OTEL_BSP_MAX_EXPORT_BATCH_SIZE(单批最大条数)、OTEL_BSP_EXPORT_TIMEOUT(导出超时)。
五、选择性插桩:显式控制插桩目标
如果希望精确控制启用哪些插桩器(例如避免自动发现引入意料之外的插桩),可以关闭auto_instrument,改为手动实例化指定 instrumentor:
from phoenix.otel import register from openinference.instrumentation.openai import OpenAIInstrumentor tracer_provider = register(project_name="my-app") # 不传 auto_instrument OpenAIInstrumentor().instrument(tracer_provider=tracer_provider)两种方式的取舍:
auto_instrument=True:适合"装了就用"的快速上手,新装的插桩包在下一次启动时自动生效;- 显式
instrument():适合对依赖集合有严格管控的生产环境,插桩对象一目了然,也便于按需传参。
六、OTel GenAI 原生插桩:不装 OpenInference 插桩器也能追踪
Phoenix 对 OpenTelemetry GenAI 语义约定(gen_ai.*属性)提供了原生兼容层:当 Phoenix 通过 OTLP 接收到 Span 时,会自动把gen_ai.*属性转换为 OpenInference 语义。这意味着,任何能产出gen_ai.*属性的OTel 原生 AI 插桩库都可以直接使用,无需安装 OpenInference instrumentor,Phoenix 即可正确展示 LLM Span Kind、模型名、Token 计数与消息内容。
转换规则要点:
- 优先级:如果 Span 上已带有 OpenInference 属性(例如来自双写插桩器),这些已有值优先于转换生成的值;
- 消息部分的结构化转换:消息内容按结构转换而非字符串拼接。
gen_ai消息中的文本(text)、图片(image)、Blob、推理(reasoning)等部分,各自成为llm.{input,output}_messages.{i}.message.contents.{j}下的一个条目,并以message_content.type(text、image、reasoning等)标记类型——因此模型的推理内容会以reasoning部分独立保留,而不会被折叠进回答文本。完整的 content part 结构见 span-llm.md#messages。
使用方式:客户端无需任何改动,照常向 Phoenix 发送 OTLP 即可:
from phoenix.otel import register # 适用于任何产出 gen_ai.* 属性的 OTel 原生 AI 插桩器 register(project_name="my-app")以 Anthropic 为例,使用 OTel GenAI 官方插桩包(来自opentelemetry-python-genai项目):
pip install opentelemetry-instrumentation-anthropicfrom phoenix.otel import register from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor import anthropic register(project_name="my-app") # 插桩 Anthropic AnthropicInstrumentor().instrument() # 正常使用 Anthropic 客户端,Span 自动创建 client = anthropic.Anthropic() response = client.messages.create( model="claude-3-5-sonnet-20241022", max_tokens=1024, messages=[ {"role": "user", "content": "Hello, Claude!"} ] )目前opentelemetry-python-genai提供的插桩包包括opentelemetry-instrumentation-anthropic与opentelemetry-instrumentation-openai等。选择哪条技术路线,取决于你更愿意依赖 OpenInference 生态(属性更完整、覆盖框架更广)还是 OTel 官方生态(gen_ai.*原生标准)。
七、环境变量与配置优先级
自动插桩的运行时配置既可以走代码参数,也可以走环境变量(详见 settings.py):
| 环境变量 | 作用 | 备注 |
|---|---|---|
PHOENIX_COLLECTOR_ENDPOINT | Collector 端点 | 优先于OTEL_EXPORTER_OTLP_ENDPOINT |
PHOENIX_PROJECT | 项目名(规范变量) | 优先于别名PHOENIX_PROJECT_NAME;两者同时设置且不同值时,以PHOENIX_PROJECT为准并打印一次性告警 |
PHOENIX_API_KEY | Phoenix Cloud API Key | 自动转为authorization: Bearer <key>头 |
PHOENIX_CLIENT_HEADERS | 自定义客户端请求头 | W3C Baggage 格式,需 URL 编码 |
PHOENIX_GRPC_PORT | gRPC 端口 | 默认 4317 |
PHOENIX_DISCOVER_CONFIG | 置为false/0/no/off时禁用.env.phoenix发现 | 仅读取进程环境 |
.env.phoenix凭据文件发现(settings.py):当某个配置既未以参数传入、也未在进程环境中设置时,register()会从当前工作目录向上逐级查找最近的.env.phoenix文件(dotenv 格式,仅读取PHOENIX_前缀键):
# .env.phoenix PHOENIX_COLLECTOR_ENDPOINT=http://localhost:6006 PHOENIX_API_KEY=your-api-key优先级恒定:显式参数 > 进程环境变量 >.env.phoenix文件,文件永远不会覆盖已设置的值。发现结果按工作目录缓存于进程生命周期内;对长驻进程(如 Jupyter Notebook),创建或修改文件后可调用phoenix.otel.settings.clear_env_file_cache()清除缓存(settings.py)。此外,解析器会检查文件是否为当前用户拥有的常规文件,并在权限过宽(如 0666)时给出警告,避免凭据泄露风险。
八、自动插桩的边界与手动补充
自动插桩不会捕获以下内容:
- 自定义业务逻辑(custom business logic)
- 内部函数调用(internal function calls)
以如下工作流为例,自动插桩只会覆盖其中对 LLM 客户端的调用:
def my_custom_workflow(query: str) -> str: preprocessed = preprocess(query) # 不会被追踪 response = client.chat.completions.create(...) # 自动插桩(被追踪) postprocessed = postprocess(response) # 不会被追踪 return postprocessed解决方案:叠加手动插桩,把整个工作流包装为 CHAIN Span:
@tracer.chain def my_custom_workflow(query: str) -> str: preprocessed = preprocess(query) response = client.chat.completions.create(...) postprocessed = postprocess(response) return postprocessed手动插桩提供的 Span Kind 装饰器还包括@tracer.retriever、@tracer.tool、@tracer.agent、@tracer.llm、@tracer.embedding等,装饰器会自动捕获函数入参与返回值作为input.value/output.value(Phoenix 评估器依赖这两个属性),完整用法见手动插桩文档。推荐组合:自动插桩负责框架层全覆盖,手动插桩补全业务编排层,二者叠加即可得到完整的调用链。
九、验证与排错
验证步骤:
- 启动 Phoenix(自托管默认可通过终端
pxi或 Docker 方式启动,参考 docs/phoenix/get-started.mdx),打开 UIhttp://localhost:6006; - 进入
my-app项目(register启动时打印的 "Phoenix Project" 即项目名); - 运行你的应用;
- 检查 Span 是否出现(使用
BatchSpanProcessor时会有批量延迟)。
常见问题:
| 现象 | 排查方向 |
|---|---|
| 完全没有 Span | 核对PHOENIX_COLLECTOR_ENDPOINT是否指向正确的 Phoenix 服务;Cloud 场景确认已设PHOENIX_API_KEY;确认已安装对应插桩包(register在未发现任何 instrumentor 时会打印 warning) |
| 属性缺失 | 对照 Span Kind 文件检查所需属性名,如 span-llm.md(模型名、Token、Cost、消息结构)与 span-chain.md |
| 插桩未生效 | 确认register(auto_instrument=True)在创建 SDK 客户端之前执行;选择性插桩模式下确认instrument(tracer_provider=...)传入了同一个 provider |
十、进一步阅读
- Python 追踪安装与配置(含 .env.phoenix 细节)
- 手动插桩(装饰器 / Context Manager / set_input / set_output)
- LLM Span 属性 Schema(messages、tokens、cost)
- 自动插桩原理源码:
_auto_instrument_installed_openinference_libraries - 环境变量与
.env.phoenix解析实现 - Phoenix 快速上手(get-started)
- 可观测性
- AI 评测
- LLMOps
- AI 应用
- 人工智能
【免费下载链接】phoenix
AI Observability & Evaluation
相关推荐
Cursor试用限制破解终极指南:机器码重置工具一招刷新设备指纹
Cursor试用限制破解终极指南:机器码重置工具一招刷新设备指纹 Cursor试用限制这道坎,几乎每个重度用户都踩过:正写着代码,屏幕突然弹出一句 Too ma
可观测性AI 评测LLMOpsAI 应用人工智能Opik Python SDK Span 对象详解:从手动插桩到分布式追踪的完整实践指南
Opik Python SDK Span 对象详解:从手动插桩到分布式追踪的完整实践指南 导读 opik.Span 是 Opik Python SDK 中描述
人工智能LLMOps模型评测可观测性AI AgentAI 应用后端前端Phoenix AGENT Span 完整指南:OpenInference 自主推理追踪语义与实战
Phoenix AGENT Span 完整指南:OpenInference 自主推理追踪语义与实战 AGENT span 是 OpenInference 语义约
可观测性AI 评测LLMOpsAI 应用人工智能
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考