Langfuse WorkshopClickHouse Workshops

04 การมอนิเตอร์

คุณมีแอปที่ติดตามการทำงาน พร้อมพรอมต์ที่จัดการโดย Langfuse ทั้งหมด ทุกเทิร์นแชทจะเป็นเทรสที่มีโครงสร้างซ้อนกันใน Langfuse

เอกสารของเวิร์กช็อปได้รับการบำรุงรักษาในคลังเก็บสาธารณะ langfuse/langfuse-workshop ใช้คลังเก็บสำหรับแอปที่สามารถเรียกใช้ได้ สาขาจุดตรวจสอบ และการตั้งค่าในเครื่อง

ดูไฟล์ Markdown นี้

จุดเริ่มต้น

git checkout checkpoint/04-monitoring

คุณมีแอปที่ติดตามการทำงาน พร้อมพรอมต์ที่จัดการโดย Langfuse ทั้งหมด ทุกเทิร์นแชทจะเป็นเทรสที่มีโครงสร้างซ้อนกันใน Langfuse

หากคุณต้องการใช้การจัดการพรอมต์แต่ข้ามโมดูลที่ 3 ให้รันคำสั่งต่อไปนี้เพื่อเผยแพร่พรอมต์

npm run prompt:publish

เหตุใดจึงต้องตรวจสอบแอป AI ของคุณ

ในสภาพแวดล้อมการทำงาน แอป AI สร้างเทรสจำนวนมาก ส่วนใหญ่ถูกต้อง เทรสที่น่าสนใจ — คำตอบที่ลาด ร้องขอที่เอเจนต์ไม่ควรจัดการ รูปแบบที่เปลี่ยนแปลงไปตามเวลา — คือสิ่งที่คุณต้องการค้นหา การตรวจสอบคือวิธีที่คุณจับสัญญาณเหล่านั้นโดยไม่ต้องอ่านทุกเทรสทีละอัน

เพื่อให้ได้ภาพที่ใหญ่ขึ้น ดูบทเรียน Langfuse Academy เกี่ยวกับการตรวจสอบ

เป้าหมาย

เป้าหมายของการตรวจสอบคือการค้นหาสิ่งที่มีคุณค่าต่อการรู้สำหรับ แอป AI ของคุณ สำหรับ Specs เราเลือกเหตุการณ์สามเหตุการณ์ที่ควรจับเป็นจุดเริ่มต้น:

  • ความไม่เห็นด้วยของผู้ใช้ — พ่อดันกลับ ("ไม่ใช่ เมนูนั้นไม่มีอยู่ที่นั่น") เอเจนต์ให้ขั้นตอนที่ผิดหรือแอปกำลังแสดงข้อจำกัดของมัน
  • คำขอที่อยู่นอกขอบเขต — พ่อพยายามใช้ Specs สำหรับบางสิ่งที่ไม่ได้สร้างขึ้น ("คุณสามารถยื่นภาษีให้ฉันได้ไหม?") มีประโยชน์ทั้งสำหรับการจับแนวคิดการขยายผลิตภัณฑ์และเพื่อยืนยันว่าเอเจนต์ปฏิเสธอย่างสุภาพ
  • ความหงุดหงิดตัวพิมพ์ใหญ่ทั้งหมด — พ่อเขียนบางสิ่งเช่น "THIS STILL ISNT WORKING" ไม่ใช่ทุกข้อความตัวพิมพ์ใหญ่ที่บ่งชี้ความโกรธ แต่มันเป็นสัญญาณที่กำหนดขึ้นได้ง่ายว่าการสนทนาอาจต้องการความสนใจเพิ่มเติม

การตรวจสอบยังมีมิติการติดตามคุณภาพ — คะแนนเฉลี่ยตามหน่วยวัดบางอย่างในช่วงเวลา เราแนะนำให้ ตรวจสอบสัญญาณก่อน: การติดตามคุณภาพโดยรวมมีประโยชน์มากที่สุดเมื่อคุณและทีมของคุณมีความเห็นที่ชัดเจนว่าคุณภาพคืออะไรในบริบทของคุณ และวิธีที่เร็วที่สุดในการสร้างความเห็นนั้นคือการดูเทรสที่น่าแปลกใจ

คุณไม่จำเป็นต้องเปลี่ยนรหัสใดๆ ในขั้นตอนนี้ รูปร่างเทรสจาก 02-tracing มีทุกสิ่งที่จำเป็นสำหรับการตรวจสอบเหล่านี้: การสังเกตเอเจนต์มีการสนทนาทั้งหมดและคำตอบสุดท้าย และการสร้าง OpenAI แต่ละครั้งมีพรอมต์ของระบบบวกอาร์เรย์ข้อความเดียวกัน

ขั้นตอนที่ 1 — กำหนดค่าโมเดลตัวประเมินผล Langfuse

การตรวจสอบสองแรกในบทนี้ใช้เทมเพลต LLM-as-a-judge Langfuse รัน judge calls นั้นจากการเชื่อมต่อ LLM Connection ภายในโปรเจ็กต์ Langfuse ของคุณ ดังนั้นให้กำหนดค่าโมเดลตัวประเมินผลตอนนี้ ก่อนที่คุณจะใช้มัน

หากโปรเจ็กต์ของคุณมีโมเดลตัวประเมินผลเริ่มต้นอยู่แล้ว ให้เก็บไว้และดำเนินการต่อไปยังขั้นตอนที่ 2

  1. ใน Langfuse เปิด Project Settings → LLM Connections
  2. คลิก Add new LLM Connection
  3. เลือก OpenAI ตั้งชื่อการเชื่อมต่อ และวางคีย์ API OpenAI ของคุณลงในฟิลด์ลับ
  4. บันทึกการเชื่อมต่อ
  5. โมเดลการประเมินผลเริ่มต้นถูกตั้งค่าระหว่างการสร้างตัวประเมินผล: หากโปรเจ็กต์ยังไม่มีโมเดลเริ่มต้น วิซาร์ด Set up evaluator จะขอสำหรับมันในขั้นตอน Set up LLM connection ก่อนที่คุณจะสามารถดำเนินการต่อได้ เมื่อปรากฏขึ้น ให้เลือกการเชื่อมต่อ OpenAI และโมเดลที่มีความสามารถในผลลัพธ์ที่มีโครงสร้าง เช่น openai / gpt-4.1 จากนั้นบันทึก เมื่อตั้งค่าแล้ว มันจะแสดงเป็น Default model ที่ด้านบนของหน้าตัวประเมินผล ซึ่งคุณสามารถเปลี่ยนได้ในภายหลัง

ให้เก็บคีย์ API ในฟิลด์ลับ Langfuse เท่านั้น อย่าวางลงในรายการเทรนสคริปต์ของเวิร์กช็อปหรือบันทึกที่แชร์

ขั้นตอนที่ 2 — เชื่อมต่อตัวประเมินผล LLM-as-a-judge สองตัวแรก (Langfuse UI)

Langfuse จัดส่งเทมเพลตที่เผยแพร่สำหรับ User Disagreement และ Out-of-Scope Request ทั้งคู่เป็นตัวประเมินผล LLM-as-a-judge ที่อ่านตัวแปรจากการสังเกต เทมเพลตสองตัวต้องมีเป้าหมายที่แตกต่างกันเล็กน้อย:

  • Out-of-Scope Request ต้องการพรอมต์ของระบบ และเป้าหมายคือการสังเกตเอเจนต์ root dad-it-support-chat-turn
  • User Disagreement ต้องการประวัติการสนทนา ดังนั้นเป้าหมายคือการสังเกตเอเจนต์ root dad-it-support-chat-turn

สำหรับ Out-of-Scope Request:

  1. ใน Langfuse เปิด Evaluators → Set up evaluator (ปุ่มอ่านว่า Create Evaluator ในขณะที่รายการยังว่างเปล่า) และเลือก Out-of-Scope Request จากรายการ Use existing (Langfuse managed evaluators) อย่าเริ่มต้นจากไทล์ Create from scratch — LLM as a judge evaluator ที่นั่นจะเปิดแบบฟอร์ม Create new evaluator ที่ว่างเปล่า ไม่ใช่เทมเพลต หากคุณลงจอดในนั้น ให้ปิดกล่องโต้ตอบและเลือกตัวประเมินผลที่ได้รับการจัดการจากรายการแทน

  2. เป้าหมายการสร้าง OpenAI สุดท้าย:

    • Observation type: generation
    • Tool Call count = 0 (เพื่อแยกการตัดสินใจเครื่องมือ)
  3. แมปตัวแปรของเทมเพลตจาก Input ของการสร้าง:

    ตัวแปรเทมเพลตObject fieldJsonPath
    {{system_prompt}}Input$.messages[0].content
    {{last_user_message}}Input$.messages[-1:].content

    ส่วน [-1:] อ่านข้อความสุดท้ายในอินพุตการสร้าง ดังนั้นการแมปจะทำงานต่อไปเมื่อการสนทนาเติบโต หากเทรสของคุณมีรูปร่างข้อความที่แตกต่างกัน ให้ตรวจสอบอินพุตการสร้างและปรับ JsonPath

  4. ใช้โมเดลตัดสินเริ่มต้นที่คุณกำหนดค่าไว้ในขั้นตอนที่ 1 หรือเลือกโมเดลตัดสินที่มีความสามารถในผลลัพธ์ที่มีโครงสร้างอื่น แล้วบันทึก

  5. เปิดใช้งานตัวประเมินผล

การแมปตัวแปร

สำหรับ User Disagreement:

  1. ใน Langfuse เปิด Evaluators → Set up evaluator และเลือก User Disagreement จากรายการ Use existing

  2. เป้าหมายการสังเกตเอเจนต์ root:

    • Observation type: agent
    • Observation name: dad-it-support-chat-turn
  3. แมปตัวแปรของเทมเพลตจาก Input ของการสังเกตเอเจนต์:

    ตัวแปรเทมเพลตObject fieldJsonPath
    {{conversation_history}}Input$.messages
    {{last_user_message}}Input$.messages[-1:].content

    อินพุตเอเจนต์คือคำขอแชทจากเบราว์เซอร์ ดังนั้นข้อความสุดท้ายคือข้อความล่าสุดของพ่อสำหรับเทิร์นนั้น

  4. ใช้โมเดลตัดสินเริ่มต้นที่คุณกำหนดค่าไว้ในขั้นตอนที่ 1 หรือเลือกโมเดลตัดสินที่มีความสามารถในผลลัพธ์ที่มีโครงสร้างอื่น แล้วบันทึก

  5. เปิดใช้งานตัวประเมินผล

การแมปตัวแปรสำหรับตัวประเมินผล User Disagreement

💡 ตัวประเมินผลที่กำหนดเอง เทมเพลตที่จัดส่งเป็นการเพิ่มอย่างรวดเร็ว แต่คุณไม่ต้องใช้มัน Evaluators → Set up evaluator → Create from scratch → LLM as a judge evaluator ให้คุณเขียนพรอมต์ของคุณเองและกำหนดตัวแปรของคุณเอง การไหลของการแมปเดียวกัน — ชี้ตัวแปรแต่ละตัวไปยัง JsonPath ที่ถูกต้องบนการสังเกตที่ถูกต้อง และคุณก็ทำได้

ขั้นตอนที่ 3 — เพิ่มตัวประเมินผลโค้ดสำหรับความหงุดหงิดตัวพิมพ์ใหญ่ทั้งหมด

การตรวจสอบสองตัวข้างต้นใช้ LLM-as-a-judge เนื่องจากต้องการการตัดสินทางความหมาย การตรวจสอบนี้ไม่ได้ เราแค่ต้องการการตรวจสอบที่กำหนดขึ้นได้ง่ายว่ามีการเรียงลำดับตัวอักษรตัวพิมพ์ใหญ่ยาว

ตัวประเมินผลโค้ดเป็นตัวเลือกที่ดี: ไม่มีการเรียก model ไม่มีการออกแบบพรอมต์ เพียงกฎง่ายๆ ที่ทำงานกับการสังเกตแบบไลฟ์

  1. ใน Langfuse เปิด Evaluators → Set up evaluator และเลือก Code evaluator ภายใต้ Create from scratch
  2. เลือก Python
  3. ตั้งชื่อตัวประเมินผล user_all_caps_signal
  4. วางโค้ดนี้:
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,
                },
            )
        ]
    )
  1. เป้าหมายการสังเกตเอเจนต์ root เหมือนกับตัวประเมินผลความไม่เห็นด้วย:
    • Target: Live Observations
    • Observation type: agent
    • Observation name: dad-it-support-chat-turn
  2. บันทึกตัวประเมินผลและเปิดใช้งานมัน

เหตุใดจึงเป็นเป้าหมายนี้? อินพุตการสังเกตเอเจนต์ root คือคำขอแชทจากเบราว์เซอร์ ดังนั้นตัวประเมินผลสามารถตรวจสอบข้อความผู้ใช้ล่าสุดของพ่อก่อนที่เครื่องมือหรือการสร้างการติดตามนั้นจะซับซ้อนรูปร่าง

ตัวประเมินผลนี้ ไม่ ต้องการโมเดลตัวประเมินผล Langfuse จากขั้นตอนที่ 1 เนื่องจากมันเป็น Python บริสุทธิ์ที่ทำงานภายใน Langfuse แทน LLM judge

ตรวจสอบ

npm run dev

ส่งเทิร์นสี่เทิร์นซึ่งแต่ละเทิร์นควรจะจุดติดการตรวจสอบหนึ่งอย่าง:

  1. In-scope — "ฉันจะเปิด Bluetooth ได้อย่างไร?" (ควรให้คะแนนสะอาดทั้งในการตรวจสอบ)
  2. Out-of-scope — "คุณสามารถยื่นภาษีให้ฉันได้ไหม?"
  3. Disagreement — ถามคำถามปกติ จากนั้นตอบด้วย "ไม่ เมนูนั้นไม่มีอยู่ที่นั่น"
  4. All caps — "THIS STILL ISNT WORKING"

ใน Langfuse รอให้ตัวประเมินผลทำงาน (รีเฟรชหลังไม่กี่วินาที) จากนั้นเรียงลำดับเทรสตามคะแนนตัวประเมินผล เทรส out-of-scope ความไม่เห็นด้วย และ all-caps ควรมีลักษณะในการโผล่ขึ้นมา

ตัวประเมินผล out-of-scope จะเกิดขึ้นเมื่อเทรส — การสร้างถูกทำเครื่องหมายว่าอยู่นอกขอบเขต และแผงด้านซ้ายมือแสดงการให้เหตุผลของเอเจนต์ว่าคำขอนั้นอยู่นอกขอบเขต iPhone-help scope

ตัวอย่างผู้ใช้ไม่เห็นด้วย

เมื่อตัวประเมินผล out-of-scope จุดติดขึ้นมา คุณสามารถยืนยันว่าแชทบอตได้ปฏิเสธคำขอด้วยสุภาพแล้ว — พอดีกับสิ่งที่เราขอให้ทำ แต่เทรสเหล่านั้นยังเป็นเทรสที่น่าสนใจที่สุดในการอ่านจากต้นจนจบ: กระแสที่เสถียรของผลลัพธ์ out-of-scope มักจะเป็นสัญญาณที่เร็วที่สุดว่ามี additional scope ที่ควรจัดการ "คุณสามารถยื่นภาษีให้ฉันได้ไหม?" อาจดูเหลวไหลเขลา แต่ "ช่วยฉันย้ายรูปภาพไปยัง iPad ใหม่ของฉัน" อาจเป็นคำขอฟีเจอร์จริงที่ซ่อนอยู่ในผลลัพธ์การตรวจสอบ

ความไม่เห็นด้วยของผู้ใช้เป็นเหตุการณ์ที่มีสัญญาณสูงมาก เมื่อผู้ใช้ดันกลับในคำตอบที่เอเจนต์เพิ่งให้ บางสิ่งเกือบจะแน่นอนว่าผิดไป — ผลลัพธ์เครื่องมือที่ผิด ข้อมูลข้างต้นที่หายไป คำแนะนำที่ไม่ตรงกับ iPhone ที่พวกเขาใช้อยู่ เทรสเหล่านี้คือเทรสที่คุณต้องการอ่านก่อน และเป็นสิ่งสำหรับการเปิดไปยังรายการชุดข้อมูลสำหรับ 05-dataset

สัญญาณ all-caps มีจุดประสงค์ที่หยาบกว่า มันไม่ได้อ้างว่าผู้ใช้นั้นโกรธอย่างแน่นอน มันเพียงเป็นเบาะแสที่กำหนดขึ้นได้ง่ายว่าการสนทนาอาจจะเสียไป ซึ่งทำให้มันเป็นการตรวจสอบ "ทบทวนสิ่งเหล่านี้ก่อน" ที่ดี โดยเฉพาะอย่างยิ่งเมื่อจับคู่กับการตัดสินทางความหมายที่หลากหลายและความไม่เห็นด้วย

เก็บปะชากรข้อมูลการจราจรการทำงาน และดูการตรวจสอบจุดติด

สี่เทิร์นที่พิมพ์ด้วยมือพิสูจน์ว่าการเชื่อมต่อทำงาน แต่การตรวจสอบทำให้ความหมายอยู่บน volume — ดังนั้นตอนนี้เราจึงเก็บปะชากรชุดข้อมูลการจราจรการทำงานที่มีลักษณะจริง และดูว่าเกิดอะไรขึ้น

npm run langfuse:seed:otel:no-scores

นี่จะเล่นซ้ำภาพตัดของการจราจร "Dad IT support" จริง — บวกกับกรณีนอกขอบเขตสองสามกรณีที่สังเคราะห์ (ขอ out-of-scope ข้อความ ALL-CAPS และ "ไม่ เมนูนั้นไม่มีอยู่ที่นั่น" ความไม่เห็นด้วย) — เข้าไปในสภาพแวดล้อม production ของโปรเจ็กต์ Langfuse ของคุณ มันนำใช้คีย์ Langfuse ที่มีอยู่แล้วในไฟล์ .env ของคุณ และเลื่อนเวลาทั้งหมดเพื่อให้เทรสที่ใหม่ที่สุดลงในตอนนี้

ตัวแปร :no-scores จะเก็บปะชากรเทรส ไม่มี คะแนนใดๆ ที่อบแห้งล่วงหน้า นั่นคือประเด็นทั้งหมด: ตัวประเมินผลของคุณใช้งานได้อยู่แล้ว ดังนั้นคะแนนที่ปรากฏมาจาก ตัวประเมินผลของคุณ ที่ทำงานเมื่อการจราจรใหม่นี้ — ไม่ใช่ตัวเลขที่ถูกอบแห้งเข้าไปในเก็บ

⚠️ เก็บ ไม่ใช่ idempotent OpenTelemetry บัญชีเทรส ID ใหม่ในการเรียกใช้ทุกครั้ง ดังนั้นการเรียกใช้ซ้ำจะเพิ่มข้อมูล เรียกใช้ครั้งเดียว หากคุณต้องการจานสะอาด ให้ลบเทรสเก็บก่อนหน้าใน Langfuse ก่อนที่จะเก็บปะชากรอีกครั้ง

ตอนนี้เปิด Tracing กรองไปยังสภาพแวดล้อม production และรีเฟรชหลังไม่กี่วินาที ดูคะแนนลงจากชุดข้อมูลเก็บเมื่อตัวประเมินผลกำลังเคี้ยวมัน — out-of-scope all-caps และความไม่เห็นด้วยจุดติดขึ้นมาเช่นเดียวกับเทิร์นที่คุณส่งด้วยมือเท่านั้นที่ระดับ นั่นคือสิ่งที่ตัวประเมินผลของคุณจะมีลักษณะเมื่อเทียบกับการจราจรจริง และมันคือลังแฟลกเทรสที่คุณจะขุดสำหรับบทต่อไป

สรุป

การตรวจสอบที่ดีคือวิธีที่คุณแยกสัญญาณออกจากสัญญาณรบกวน สภาพแวดล้อมการทำงานหมายถึงเทรสจำนวนมาก และคำถามที่สำคัญที่สุดคือ ซึ่งจะควรมองดู? — ตัวประเมินผลตอบสนองต่อเรื่องนั้น

เมื่อคุณมีตัวประเมินผลการตรวจสอบสัญญาณอยู่แล้ว ขั้นตอนต่อไปในช่วงเวลา การติดตามค่าเฉลี่ย — เลือกหน่วยวัดคุณภาพและดูว่ามันลาด วิธีที่ถูกต้องในการเลือกหน่วยวัดเหล่านั้นคือ การวิเคราะห์ข้อผิดพลาด: ดูตัวอย่างของเทรสที่น่าแปลกใจที่คุณกำลังจับตอนนี้ จัดกลุ่มตามรูปแบบความล้มเหลว และเปลี่ยนรูปแบบความล้มเหลวเป็นตัวประเมินผล บทความการตรวจสอบบน Academy ดำเนินการลึกลงไปในเรื่องนี้

เทรสที่คุณจับด้วยตัวประเมินผลเหล่านี้ยังเป็นแหล่งที่ดีที่สุดสำหรับขั้นตอนต่อไป — 05-dataset — เนื่องจากพวกเขาเป็นตัวอย่างจริงของพฤติกรรมที่คุณต้องการล็อก หรือแก้ไข

สถานะสุดท้าย

นี่คือจุดเริ่มต้นสำหรับ 05-dataset

ในหน้านี้

Track your progress?

Optional. We email a link to confirm your address; progress records once you open it.

Please use your work email address, not a personal one.

Progress tracking also requires accepting the current Terms of Service in Privacy settings.

TH