04 Giám sát
Bạn có một ứng dụng được theo dõi với các prompts do Langfuse quản lý. Mỗi lượt trò chuyện được đặt trong Langfuse như một trace lồng nhau.
Tài liệu workshop được duy trì trong kho langfuse/langfuse-workshop công khai. Sử dụng kho để lấy ứng dụng có thể chạy được, các nhánh checkpoint và thiết lập cục bộ.
Điểm bắt đầu
git checkout checkpoint/04-monitoringBạn có một ứng dụng được theo dõi với các prompts do Langfuse quản lý. Mỗi lượt trò chuyện được đặt trong Langfuse như một trace lồng nhau.
Nếu bạn muốn sử dụng quản lý prompt nhưng đã bỏ qua mô-đun 3, hãy chạy lệnh sau để công bố prompt
npm run prompt:publishTại sao giám sát ứng dụng AI của bạn
Trong sản xuất, một ứng dụng AI tạo ra rất nhiều traces. Hầu hết chúng đều ổn. Những điều thú vị — các câu trả lời lệch lạc, các yêu cầu mà agent không nên xử lý, các mẫu thay đổi theo thời gian — là những gì bạn muốn tìm thấy. Giám sát là cách bạn bắt các tín hiệu đó mà không cần đọc từng trace một.
Để có cái nhìn toàn diện hơn, hãy xem bài học giám sát Langfuse Academy.
Mục tiêu
Mục tiêu của giám sát là tìm kiếm những thứ đáng biết đến đối với ứng dụng AI của bạn. Đối với Specs, chúng tôi chọn ba sự kiện đáng bắt gọn làm điểm khởi đầu:
- Sự bất đồng ý của người dùng — Dad phản đối ("Không, menu đó không có ở đó"). Hoặc agent đã đưa ra các bước sai hoặc ứng dụng đang cho thấy giới hạn của nó.
- Các yêu cầu ngoài phạm vi — Dad cố gắng sử dụng Specs cho điều gì đó mà nó không được xây dựng ("Bạn có thể nộp hồ sơ cấp thuế của tôi không?"). Hữu ích cả để phát hiện ý tưởng mở rộng sản phẩm và để xác nhận rằng agent từ chối một cách duyên dáng.
- Sự bực bội viết hoa tất cả — Dad viết điều gì đó như "CÁI NÀY VẪN KHÔNG HOẠT ĐỘNG". Không phải mọi tin nhắn viết hoa đều là sự tức giận, nhưng đó là một tín hiệu xác định rẻ tiền rằng một cuộc trò chuyện có thể cần sự chú ý thêm.
Giám sát cũng có một khía cạnh theo dõi chất lượng — điểm trung bình trên một số số liệu theo thời gian. Chúng tôi khuyên phát hiện tín hiệu trước: theo dõi chất lượng tổng hợp hữu ích nhất khi bạn và nhóm của bạn có ý kiến rõ ràng về chất lượng có nghĩa là gì trong bối cảnh của bạn, và cách nhanh nhất để hình thành ý kiến đó là xem xét các traces đáng ngạc nhiên.
Bạn không cần thay đổi bất kỳ mã nào ở bước này. Hình dạng trace từ 02-tracing đã có mọi thứ những màn hình này cần: quan sát agent có toàn bộ cuộc trò chuyện và câu trả lời cuối cùng, và mỗi thế hệ OpenAI có system prompt cộng với cùng một mảng tin nhắn.
Bước 1 — Cấu hình mô hình đánh giá Langfuse
Hai màn hình đầu tiên trong chương này sử dụng các mẫu LLM-as-a-judge. Langfuse chạy các lệnh gọi judge đó từ một Kết nối LLM bên trong dự án Langfuse của bạn, vì vậy hãy cấu hình mô hình đánh giá ngay bây giờ, ngay trước khi bạn sử dụng chúng.
Nếu dự án của bạn đã có mô hình đánh giá mặc định, hãy giữ nó và tiếp tục bước 2.
- Trong Langfuse, mở Project Settings → LLM Connections.
- Nhấp vào Add new LLM Connection.
- Chọn OpenAI, đặt tên kết nối và dán khóa API OpenAI của bạn vào trường secret.
- Lưu kết nối.
- Mô hình đánh giá mặc định được đặt trong quá trình tạo đánh giá: nếu dự án chưa có, trình hướng dẫn Set up evaluator yêu cầu ở bước Set up LLM connection của nó trước khi bạn có thể tiếp tục. Khi điều đó xuất hiện, chọn kết nối OpenAI và một mô hình có khả năng đầu ra có cấu trúc như
openai / gpt-4.1, sau đó lưu. Sau khi được đặt, nó hiển thị dưới dạng Default model ở đầu trang Evaluators, nơi bạn cũng có thể thay đổi nó sau.
Chỉ giữ khóa API trong trường secret của Langfuse. Không dán nó vào bản ghi workshop hoặc ghi chú được chia sẻ.
Bước 2 — Kết nối hai màn hình dựa trên judge đầu tiên (Giao diện Langfuse)
Langfuse vận chuyển các mẫu đã xuất bản cho User Disagreement và Out-of-Scope Request. Cả hai đều là những đánh giá LLM-as-a-judge đọc các biến từ quan sát. Hai mẫu cần các mục tiêu hơi khác nhau:
- Out-of-Scope Request cần system prompt, và nhắm đến quan sát agent
dad-it-support-chat-turnở cấp độ gốc. - User Disagreement cần lịch sử trò chuyện, vì vậy nhắm đến quan sát agent
dad-it-support-chat-turnở cấp độ gốc.
Đối với Out-of-Scope Request:
-
Trong Langfuse, mở Evaluators → Set up evaluator (nút ghi Create Evaluator trong khi danh sách vẫn trống) và chọn Out-of-Scope Request từ danh sách Use existing (Evaluators do Langfuse quản lý). Đừng bắt đầu từ các ô Create from scratch — LLM as a judge evaluator ở đó mở một biểu mẫu Create new evaluator trống, không phải mẫu. Nếu bạn hạ cánh trên nó, hãy đóng hộp thoại và chọn evaluator được quản lý từ danh sách.
-
Nhắm đến thế hệ OpenAI cuối cùng:
- Loại quan sát:
generation - Số lượng Tool Call = 0 (để loại trừ quyết định công cụ)
- Loại quan sát:
-
Ánh xạ các biến mẫu từ Input của thế hệ:
Biến mẫu Trường đối tượng JsonPath {{system_prompt}}Input$.messages[0].content{{last_user_message}}Input$.messages[-1:].contentLát
[-1:]đọc tin nhắn cuối cùng trong đầu vào thế hệ, vì vậy ánh xạ tiếp tục hoạt động khi cuộc trò chuyện phát triển. Nếu trace của bạn có hình dạng tin nhắn khác, hãy kiểm tra đầu vào thế hệ và điều chỉnh JsonPath. -
Sử dụng mô hình judge mặc định bạn đã cấu hình ở Bước 1 hoặc chọn một mô hình judge có khả năng đầu ra có cấu trúc khác, và lưu.
-
Bật evaluator.

Đối với User Disagreement:
-
Trong Langfuse, mở Evaluators → Set up evaluator và chọn User Disagreement từ danh sách Use existing.
-
Nhắm đến quan sát agent ở cấp độ gốc:
- Loại quan sát:
agent - Tên quan sát:
dad-it-support-chat-turn
- Loại quan sát:
-
Ánh xạ các biến mẫu từ Input của quan sát agent:
Biến mẫu Trường đối tượng JsonPath {{conversation_history}}Input$.messages{{last_user_message}}Input$.messages[-1:].contentĐầu vào agent là yêu cầu trò chuyện từ trình duyệt, vì vậy tin nhắn cuối cùng là tin nhắn mới nhất của Dad cho lượt đó.
-
Sử dụng mô hình judge mặc định bạn đã cấu hình ở Bước 1 hoặc chọn một mô hình judge có khả năng đầu ra có cấu trúc khác, và lưu.
-
Bật evaluator.

💡 Evaluators tùy chỉnh. Các mẫu được vận chuyển là một bước vào nhanh, nhưng bạn không phải sử dụng chúng. Evaluators → Set up evaluator → Create from scratch → LLM as a judge evaluator cho phép bạn viết prompt của riêng bạn và định nghĩa các biến của riêng bạn. Cùng một dòng ánh xạ — chỉ từng biến vào JsonPath chính xác trên quan sát chính xác, và bạn xong.
Bước 3 — Thêm evaluator mã cho sự bực bội viết hoa
Hai màn hình ở trên sử dụng LLM-as-a-judge vì chúng cần phán xét ngữ nghĩa. Cái này thì không. Chúng tôi chỉ muốn một kiểm tra xác định rẻ tiền cho tin nhắn của người dùng chứa một loạt các chữ cái viết hoa dài.
Code evaluators phù hợp với mẫu đó: không có lệnh gọi mô hình, không có thiết kế prompt, chỉ một quy tắc đơn giản chạy trên các quan sát trực tiếp.
- Trong Langfuse, mở Evaluators → Set up evaluator và chọn Code evaluator dưới Create from scratch.
- Chọn Python.
- Đặt tên evaluator là
user_all_caps_signal. - Dán mã này:
from dataclasses import dataclass
from typing import Any
@dataclass
class ObservationContext:
input: Any = None
output: Any = None
metadata: Any = None
@dataclass
class ExperimentContext:
item_expected_output: Any = None
item_metadata: Any = None
@dataclass
class EvaluationContext:
observation: ObservationContext
experiment: ExperimentContext | None = None
@dataclass
class Score:
value: int | float | str | bool
name: str
data_type: str | None = None
comment: str | None = None
config_id: str | None = None
metadata: dict[str, Any] | None = None
@dataclass
class EvaluationResult:
scores: list[Score]
def evaluate(ctx: EvaluationContext) -> EvaluationResult:
"""Flags a likely upset user when the latest user message contains a long all-caps run."""
input = ctx.observation.input
text = ""
if isinstance(input, str):
text = input
elif isinstance(input, dict):
messages = input.get("messages")
if isinstance(messages, list):
for message in reversed(messages):
if (
isinstance(message, dict)
and message.get("role") == "user"
and isinstance(message.get("content"), str)
):
text = message["content"]
break
longest_run = 0
current_run = 0
for ch in text:
if "A" <= ch <= "Z":
current_run += 1
if current_run > longest_run:
longest_run = current_run
else:
current_run = 0
has_all_caps_signal = longest_run >= 6
return EvaluationResult(
scores=[
Score(
name="user_all_caps_signal",
value=has_all_caps_signal,
data_type="BOOLEAN",
comment=(
"Detected an all-caps run longer than 5 letters, which may indicate the user is upset."
if has_all_caps_signal
else "No all-caps run longer than 5 letters detected."
),
metadata={
"text": text,
"longest_run": longest_run,
},
)
]
)- Nhắm đến cùng quan sát agent ở cấp độ gốc như màn hình bất đồng ý:
- Mục tiêu: Live Observations
- Loại quan sát:
agent - Tên quan sát:
dad-it-support-chat-turn
- Lưu evaluator và bật nó.
Tại sao lại là mục tiêu này? Đầu vào quan sát agent ở cấp độ gốc là yêu cầu trò chuyện từ trình duyệt, vì vậy evaluator có thể kiểm tra tin nhắn người dùng mới nhất của Dad trước khi bất kỳ lệnh gọi công cụ hoặc thế hệ tiếp theo làm phức tạp hình dạng.
Evaluator này không cần mô hình đánh giá Langfuse từ Bước 1, vì nó là Python thuần chạy bên trong Langfuse chứ không phải là một judge LLM.
Xác minh
npm run devGửi bốn lượt, mỗi lượt sẽ bật một màn hình:
- Trong phạm vi — "Làm cách nào để bật Bluetooth?" (sẽ ghi điểm sạch trên cả hai màn hình)
- Ngoài phạm vi — "Bạn có thể nộp hồ sơ cấp thuế của tôi không?"
- Bất đồng ý — hỏi một câu hỏi bình thường, sau đó trả lời bằng "Không, menu đó không có ở đó"
- Tất cả chữ hoa — "CÁI NÀY VẪN KHÔNG HOẠT ĐỘNG"
Trong Langfuse, chờ các evaluators chạy (làm mới sau vài giây), sau đó sắp xếp traces theo điểm số evaluator. Các traces ngoài phạm vi, bất đồng ý và viết hoa nên nổi lên phía trên.


Khi màn hình ngoài phạm vi bắt lửa, bạn có thể xác nhận rằng chatbot đã từ chối yêu cầu một cách duyên dáng — chính xác những gì chúng tôi yêu cầu nó làm. Nhưng những traces đó cũng là những traces thú vị nhất để đọc từ đầu đến cuối: một dòng liên tục các lần hit ngoài phạm vi thường là tín hiệu sớm nhất rằng có phạm vi bổ sung đáng xử lý. "Bạn có thể nộp hồ sơ cấp thuế của tôi không?" là ngốc, nhưng "Giúp tôi di chuyển ảnh sang iPad mới của tôi" có thể là một yêu cầu tính năng thực sự ẩn trong kết quả giám sát.
Sự bất đồng ý của người dùng là một sự kiện tín hiệu cao hơn nhiều. Khi một người dùng phản đối một câu trả lời mà agent vừa đưa ra, điều gì đó gần như chắc chắn đã sai — kết quả công cụ sai, bối cảnh bị thiếu, một hướng dẫn không khớp với iPhone mà họ đang sử dụng. Đây là những traces bạn muốn đọc trước tiên, và đây là ứng cử viên hàng đầu để biến thành các mục tập dữ liệu cho 05-dataset.
Tín hiệu viết hoa tất cả có ý định thô hơn. Nó không phải là một tuyên bố rằng người dùng chắc chắn đang tức giận; nó chỉ là một manh mối xác định rẻ tiền rằng cuộc trò chuyện có thể đang trở nên sai lệch. Điều đó làm cho nó trở thành một màn hình "xem xét những cái này trước" tốt, đặc biệt khi được ghép nối với những judges bất đồng ý và ngoài phạm vi phong phú hơn.
Hạt giống lưu lượng sản xuất và xem các màn hình bắt lửa
Bốn lượt được gõ tay chứng minh rằng dây điện hoạt động. Nhưng giám sát kiếm được để giữ nó trên thể tích — vì vậy bây giờ hãy hạt giống một loạt dữ liệu sản xuất thực tế và xem những gì xảy ra.
npm run langfuse:seed:otel:no-scoresĐiều này phát lại một ảnh chụp của lưu lượng "Dad IT support" thực tế — cộng với một số trường hợp biên tổng hợp (yêu cầu ngoài phạm vi, tin nhắn TẤT CẢ-CHỮ HOA và những bất đồng ý "không, menu đó không có ở đó") — vào môi trường production của dự án Langfuse của bạn. Nó sử dụng lại các khóa Langfuse đã có trong .env của bạn và chuyển mọi dấu thời gian để trace mới nhất hạ cánh ở "bây giờ".
Biến thể :no-scores hạt giống traces mà không có bất kỳ điểm nào được nướng sẵn. Đó là toàn bộ điểm: các evaluators của bạn đã trực tiếp, vì vậy các điểm xuất hiện đến từ các màn hình của bạn chạy trên lưu lượng mới này — không phải từ các số được nướng vào hạt giống.
⚠️ Hạt giống là không idempotent. OpenTelemetry tạo ra ID trace mới trên mỗi lần chạy, vì vậy chạy lại sẽ tăng gấp đôi dữ liệu. Chạy nó một lần; nếu bạn cần một bảng trắng sạch, hãy xóa các traces hạt giống trước đó trong Langfuse trước khi hạt giống lại.
Bây giờ mở Tracing, lọc đến môi trường production, và làm mới sau vài giây. Xem các điểm hạ cánh trên toàn bộ lô hạt giống khi các evaluators nhai nó — các trường hợp biên ngoài phạm vi, viết hoa tất cả và bất đồng ý nổi lên giống như các lượt bạn gửi bằng tay, chỉ là quy mô. Đó là những gì các màn hình của bạn sẽ trông giống như đối với lưu lượng thực tế, và đó chính xác là đống traces được gắn cờ mà bạn sẽ khai thác cho chương tiếp theo.
Kết thúc
Các màn hình tốt là cách bạn tách tín hiệu khỏi tiếng ồn. Sản xuất có nghĩa là rất nhiều traces, và câu hỏi quan trọng nhất là những cái nào tôi nên xem xét? — các màn hình trả lời điều đó.
Khi bạn có các màn hình giám sát tín hiệu hoạt động, bước tiếp theo theo thời gian là theo dõi số liệu trung bình — chọn các số liệu chất lượng và xem chúng trôi. Cách đúng để chọn các số liệu đó là phân tích lỗi: xem xét một mẫu của các traces đáng ngạc nhiên mà bạn đang bắt được, nhóm chúng theo chế độ lỗi và biến các chế độ lỗi thành các evaluators. Bài học giám sát trên Academy đi sâu hơn vào điều này.
Các traces bạn bắt được với các màn hình này cũng là nguồn tốt nhất cho bước tiếp theo — 05-dataset — vì đó là những ví dụ thực về hành vi bạn muốn khóa hoặc sửa.
Trạng thái cuối
Đây là điểm bắt đầu cho 05-dataset.
03 Quản lý prompt
Bạn có một ứng dụng được theo dõi. System prompt tồn tại như một hằng số được gọi là SYSTEMPROMPT trong src/server/support-agent.ts và được sử dụng trực tiếp làm system message.
05 Tập dữ liệu
Bạn có một ứng dụng được theo dõi, đã gán thuộc tính và được giám sát. data/seed-dataset.json và scripts/seed-dataset.ts đã có sẵn trong kho lưu trữ tại điểm kiểm tra này.