OpenTelemetry chỉ là việc theo dõi LLM được tiêu chuẩn hóa. Đây thực sự trông như thế nào trong mã.
AI/ML·Dev.to·0 lượt xem

OpenTelemetry chỉ là việc theo dõi LLM được tiêu chuẩn hóa. Đây thực sự trông như thế nào trong mã.

OpenTelemetry just standardized LLM tracing. Here's what it actually looks like in code.

AI Summary

OpenTelemetry vừa ra mắt GenAI Semantic Conventions, một tiêu chuẩn hóa quan trọng cho việc ghi lại dấu vết (tracing) các mô hình ngôn ngữ lớn (LLM). Trước đây, định dạng tracing này rất phân mảnh, mỗi công cụ có một kiểu riêng. Tiêu chuẩn mới này giúp thống nhất cách đặt tên cho các "span" (đơn vị trong tracing), định nghĩa các thuộc tính quan trọng như "prompt" (sẽ được log một cách an toàn, tránh lộ thông tin nhạy cảm - PII), và hành vi của "agent". Điều này giải quyết vấn đề "vendor lock-in" khi các công ty phải tự xây dựng hệ thống tracing tùy chỉnh. Các developer nên áp dụng các quy ước này để đảm bảo trace của LLM dễ dàng được các nền tảng observability hiểu và xử lý. Điều này sẽ giúp ích rất nhiều cho việc gỡ lỗi (debugging) và phân tích chi phí hiệu quả hơn. Spec này giới thiệu ba loại span chính: gọi mô hình (model calls), gọi agent (agent invocations) và thực thi công cụ (tool executions), với các định nghĩa rõ ràng về thuộc tính cho danh tính của agent và cách sử dụng công cụ.

Mỗi công cụ LLM đều phát minh ra định dạng theo dõi riêng. Langfuse có một cái. Helicone có một cái. Arize có một cái. Nếu bạn tự xây dựng - xin chúc mừng, bạn cũng có một cái. OpenTelemetry vừa công bố một tiêu chuẩn cho tất cả...

Mỗi công cụ LLM đều phát minh ra định dạng theo dõi riêng. Langfuse có một cái. Helicone có một cái. Arize có một cái. Nếu bạn đã tự xây dựng chiếc xe của riêng mình — xin chúc mừng, bạn cũng có một chiếc.

OpenTelemetry vừa xuất bản một tiêu chuẩn cho tất cả chúng.

Nó xác định cách đặt tên cho các phạm vi, những thuộc tính mà lệnh gọi công cụ nên có, cách ghi nhật ký lời nhắc mà không làm rò rỉ PII và loại phạm vi nào sẽ được sử dụng cho tổng đài viên. Nó được gọi là Quy ước ngữ nghĩa GenAI. Đó là thử nghiệm. Và hầu như không có ai viết về việc nó thực sự trông như thế nào khi bạn triển khai nó.

Tôi biết vì tôi đã tìm kiếm. "Quy ước ngữ nghĩa OTel GenAI" cung cấp cho bạn các trang thông số kỹ thuật. Không có bài viết thực tế. "Cách theo dõi tác nhân LLM bằng OpenTelemetry" cung cấp cho bạn những câu hỏi về StackOverflow không có câu trả lời.

Chúng tôi đã thực hiện nó. Bốn PR, một phân tích khoảng cách, mã trước/sau thực. Trong quá trình triển khai, chúng tôi cũng phát hiện ra rằng dấu vết của chúng tôi chưa bao giờ được xuất — nhưng đó lại là một câu chuyện khác.

Đây thực sự là nội dung thông số kỹ thuật, chúng tôi đã sai ở đâu và bạn nên làm gì hôm nay.

Miền Tây hoang dã của việc truy tìm LLM

Ngay bây giờ, nếu bạn theo dõi các cuộc gọi LLM, có thể bạn đang làm điều gì đó như thế này:

span.setAttribution("llm.provider" , "openai");
span.setAttribution("llm.model", "gpt-4o");
span.setAttribution("llm.tokens.input", 150); span.setAttribution("llm.cost", 0,003);

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Đó là những gì chúng tôi đã làm trong toad-eye v1. Có ý nghĩa với chúng tôi. Hoạt động tốt trong trang tổng quan của chúng tôi.

Vấn đề: không có trang tổng quan nào khác hiểu được các thuộc tính này. Chuyển từ Jaeger sang Arize Phoenix - cấu hình lại mọi thứ. Xuất dấu vết sang Datadog - họ thấy các nhịp thô không có ngữ cảnh LLM. Dấu vết của bạn là một khu vườn có tường bao quanh. Bạn đã tích hợp tính năng khóa nhà cung cấp vào mã của riêng mình.

Đây chính xác là những gì OpenTelemetry được tạo ra để giải quyết. Và bây giờ nó có thông số kỹ thuật dành cho GenAI.

Ba loại nhịp GenAI

Thông số kỹ thuật xác định ba thao tác. Mỗi khoảng liên quan đến LLM đều có một:

chat gpt-4o ← cuộc gọi mô hình
gọi_agent điều phối ← lời gọi tác nhân  
exec_tool web_search ← thực thi công cụ

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Định dạng tên nhịp là {Operation} {name. Không phải định dạng tùy chỉnh của bạn. Không phải gen_ai.openai.gpt-4o (đó là những gì chúng tôi có — không có chương trình phụ trợ nào nhận ra nó).

Đây là những gì chúng tôi đã thay đổi:

Ảnh chụp màn hình: Span
Di chuyển đặt tên theo phạm vi: định dạng cũ không hiển thị với mọi chương trình phụ trợ nhận biết GenAI.

Thuộc tính của tác nhân - chúng tôi đã sai đường dẫn

Nếu bạn đang xây dựng các tác nhân (ReAct, sử dụng công cụ, nhiều bước), thông số kỹ thuật sẽ xác định các thuộc tính nhận dạng và công cụ:

// Otel nói gì:
span. setAttribution("gen_ai.agent.name", "weather-bot");
span.setAttribution("gen_ai.agent.id", "agent-001");
span.setAttribution( "gen_ai.tool.name", "tìm kiếm");
span.setAttribution("gen_ai.tool.type", "chức năng");
// Những gì chúng tôi đã có:
span.setAttribution( "gen_ai.agent.tool.name", "tìm kiếm"); // đường dẫn sai
// gen_ai.agent.name — hoàn toàn không tồn tại

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

gen_ai.agent.tool.name đường đi có vẻ hợp lý Nó thậm chí còn đọc tốt. Tuy nhiên, thông số kỹ thuật đặt các thuộc tính công cụ tại gen_ai.tool.* — phẳng, không lồng trong tác nhân. Một lần nữa, định dạng của chúng tôi không hiển thị với bất kỳ chương trình phụ trợ nào tuân theo tiêu chuẩn.

Ghi nội dung - thông số kỹ thuật đồng ý với chúng tôi (cảm thấy tốt)

Đây là điều duy nhất chúng tôi đã làm đúng ngay từ ngày đầu tiên và đáng để lên tiếng vì hầu hết các đội đều mắc sai lầm.

Thông số kỹ thuật cho biết: không ghi lại lời nhắc và phần hoàn thành theo mặc định. Công cụ KHÔNG NÊN ghi lại nội dung trừ khi được bật rõ ràng.

Ba mẫu chính thức:

  1. Mặc định: không ghi. Không có lời nhắc, không có sự hoàn thành trong các khoảng thời gian. Quyền riêng tư là trên hết.
  2. Chọn tham gia thông qua thuộc tính span. gen_ai.input.messagesgen_ai.output.messages dưới dạng chuỗi JSON.
  3. Bộ nhớ ngoài. Lưu trữ nội dung ở nơi khác, đặt tham chiếu vào khoảng thời gian.

Chúng tôi đã có recordContent: false làm mặc định kể từ v1. Khi thông số kỹ thuật xác nhận phương pháp này, đó là một trong những khoảnh khắc hiếm hoi mà trực giác của bạn được xác nhận bởi một ủy ban gồm những người rất thông minh.

Nếu bạn đang ghi lại lời nhắc theo từng khoảng thời gian — bạn có thể muốn xem xét lại trước khi nhóm bảo mật thực hiện việc đó cho bạn.

Phân tích khoảng cách trung thực

Đây là hình ảnh đầy đủ. Không quay, không hái anh đào.

Những gì chúng tôi đã đạt được ngay từ ngày đầu tiên

Thuộc tính của chúng tôi Thông số Otel Bản án
gen_ai.provider.name gen_ai.provider.name ✅ Kết hợp chính xác
gen_ai.request.model gen_ai.request.model ✅ Kết hợp chính xác
gen_ai.usage.input_tokens gen_ai.usage.input_tokens ✅ Kết hợp chính xác
error.type error.type ✅ Kết hợp chính xác

Chúng tôi đã sai gì

Cái gì Phiên bản của chúng tôi Thông số Otel Trạng thái
Tên nhịp gen_ai.openai.gpt-4o trò chuyện gpt-4o Đã sửa
Thuộc tính tên công cụ gen_ai.agent.tool.name gen_ai.tool.name Đã sửa
Thuộc tính tùy chỉnh gen_ai.agent.step.* Không gian tên dành riêng Đã chuyển đến gen_ai.toad_eye.*
Danh tính đại lý Không tồn tại gen_ai.agent.name Đã thêm

Những gì chúng tôi đã xây dựng ngoài thông số kỹ thuật

Tính năng Không gian tên Tại sao nó không có trong OTel
Chi phí cho mỗi yêu cầu gen_ai.toad_eye.cost Giá cả tùy theo nhà cung cấp
Người bảo vệ ngân sách gen_ai.toad_eye.budget.* Thực thi thời gian chạy ≠ khả năng quan sát
Ran chắn bóng gen_ai.toad_eye.guard.* Xác thực ở cấp ứng dụng
Sự trôi dạt ngữ nghĩa gen_ai.toad_eye.semantic_drift Chỉ số chất lượng, không phải tiêu chuẩn theo dõi
Theo dõi bước ReAct gen_ai.toad_eye.agent.step.* ReAct là một mẫu; thông số kỹ thuật là bất khả tri về mẫu

Thông tin chi tiết quan trọng: Thông số kỹ thuật của Otel bao gồm ĐIỀU GÌ đã xảy ra. Chúng tôi đề cập đến TẠI SAO và BAO NHIÊU. Không cạnh tranh — bổ sung. Số liệu tùy chỉnh của bạn nằm trong không gian tên của bạn. Các thuộc tính của thông số kỹ thuật sẽ đi đến nơi mà chương trình phụ trợ mong đợi.

Quá trình di chuyển: phát ra kép, không làm gián đoạn người dùng

Chúng tôi đã không nghỉ ngơi hoàn toàn. v2.4 phát ra cả tên thuộc tính cũ và mới:

// Mới (tuân thủ thông số Otel)
span.setAttribution("gen_ai.tool.name", toolName);
// Cũ (không được dùng nữa, vẫn được phát ra để tương thích ngược)
span.setAttribution(" gen_ai.agent.tool.name", toolName);

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Ảnh chụp màn hình: Sự khác biệt trong quá trình di chuyển tiền tố thuộc tính với các thẻ @deprecated và phát ra kép
Phương pháp phát ra kép: các thuộc tính cũ nhận được @deprecated, các thuộc tính mới tuân theo thông số kỹ thuật. Cả hai đều phát ra cho đến v3.

Biến môi trường kiểm soát thời điểm ngừng phát các thuộc tính không được dùng nữa:

OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Đây là bốn PR (#170, #171, #172, #173). v3 sẽ xóa hoàn toàn các bí danh không được dùng nữa.

Điều trớ trêu

Trong khi triển khai tất cả những điều này, chúng tôi đã thực hiện một đợt thử nghiệm thủ công.

Hóa ra dấu vết của chúng tôi chưa bao giờ được xuất khẩu. Không có gì cả. Bao giờ. OTel NodeSDK âm thầm vô hiệu hóa việc xuất dấu vết khi bạn vượt qua spanProcessors: []. Chúng tôi đã có 252 bài kiểm tra đậu. Tất cả đều chế giễu SDK.

Vì vậy, chúng tôi đã chuẩn hóa các thuộc tính của mình một cách hoàn hảo — để tìm ra những dấu vết mà không ai có thể nhìn thấy.

Chúng tôi đã sửa cả hai. Xuất bản sáu phiên bản vá lỗi trong một ngày. toàn bộ câu chuyện có trong bài viết số 2.

Những chương trình phụ trợ nào thực sự hỗ trợ điều này

Đây là lý do để quan tâm. Phát ra các thuộc tính phù hợp ngay hôm nay → sáu chương trình phụ trợ trực quan hóa dấu vết của bạn vào ngày mai:

Phần cuối Nhận biết các phạm vi GenAI Hiển thị tác nhân Chi phí
Jaeger Cơ bản (các nhịp lồng nhau) Chế độ xem phân cấp Miễn phí
Phượng hoàng Arize Giao diện người dùng GenAI đầy đủ Quy trình làm việc của nhân viên Cấp miễn phí
Dấu hiệu Trang tổng quan GenAI Các nhịp lồng nhau Miễn phí / Đám mây
Chó dữ liệu Khả năng quan sát LLM Truy tìm tác nhân Đã trả tiền
Langfuse Giao diện người dùng GenAI đầy đủ Chế độ xem phiên Cấp miễn phí
Grafana + Nhịp độ Truy vấn theo thuộc tính Trang tổng quan tùy chỉnh Miễn phí

Không có sự ràng buộc của nhà cung cấp. Một tập hợp các thuộc tính. Sáu nơi để hình dung chúng.

Bạn nên làm gì hôm nay

Nếu bạn đang theo dõi các cuộc gọi LLM — ngay cả với mã tùy chỉnh — việc điều chỉnh theo thông số kỹ thuật hiện sẽ giúp bạn tránh được rắc rối sau này. Các quy ước chỉ mang tính thử nghiệm, nhưng hướng đi đã được xác định.

Danh sách kiểm tra nhanh:

  • Đặt gen_ai.Operation.name trên mỗi khoảng LLM: chat, invoke_agent hoặc execute_tool
  • Định dạng tên nhịp là {Operation} {model_or_agent_name
  • Sử dụng các thuộc tính chính thức: gen_ai.agent.name, gen_ai.tool.name, gen_ai.tool.type
  • Đặt các thuộc tính tùy chỉnh CỦA BẠN trong vùng tên CỦA BẠN — không phải gen_ai.*
  • Không ghi lại lời nhắc/hoàn thành theo mặc định — hãy chọn tham gia
  • Kiểm tra dấu vết của bạn trong ít nhất 2 chương trình phụ trợ (Jaeger + một chương trình dành riêng cho GenAI như Phoenix)

Thông số kỹ thuật đầy đủ: Quy ước ngữ nghĩa GenAI OpenTelemetry GenAI
Khoảng thời gian tác nhân: Các khoảng thời gian tác nhân GenAI

Các bài viết trước:

toad-eye — khả năng quan sát LLM mã nguồn mở, OTel-native: GitHub · npm

🐸👁️

Tác giả: Albert Alov

#ai#observability#typescript#opentelemetry