用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/truera/trulens --skill trulens-evaluation-setup命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
| skill_spec_version | 0.1.0 |
| name | trulens-evaluation-setup |
| version | 1.0.0 |
| description | Configure feedback functions and selectors for TruLens evaluations |
| tags | ["trulens","llm","evaluation","feedback","selectors"] |
Configure feedback functions to evaluate your LLM app's quality.
Before proceeding, let's determine the right evaluations for your app.
Option A: RAG (Retrieval-Augmented Generation)
→ Recommended: RAG Triad metrics
Option B: Agent
→ Recommended: Agent GPA metrics (continue to Question 2)
Yes, my agent creates plans before executing:
→ Use all Agent GPA metrics:
No, my agent acts without explicit planning:
→ Use Agent GPA metrics (excluding plan metrics):
Consider adding these based on your needs:
| Evaluation | Use Case |
|---|---|
| Coherence | Check if output is well-structured and readable |
| Conciseness | Ensure responses aren't unnecessarily verbose |
| Harmlessness | Detect potentially harmful content |
| Sentiment | Analyze emotional tone of responses |
| Custom metrics | Domain-specific evaluations (see below) |
If you need domain-specific evaluations, describe what you want to measure:
What aspect of your app do you want to evaluate?
Examples:
Template for custom metrics:
def my_custom_metric(input_text: str, output_text: str) -> float:
"""
Describe what this metric evaluates.
Returns:
float: Score between 0.0 (worst) and 1.0 (best)
"""
# Option 1: Rule-based logic
# score = 1.0 if "required phrase" in output_text else 0.0
# Option 2: Use LLM-as-judge
# provider = OpenAI()
# response = provider.client.chat.completions.create(
# model="gpt-4o",
# messages=[{
# "role": "user",
# "content": f"Rate this response on [YOUR CRITERIA]. Input: {input_text} Output: {output_text}. Return only a number 0-10."
# }]
# )
# score = float(response.choices[0].message.content) / 10.0
return score
f_custom = Metric(
implementation=my_custom_metric,
name="My Custom Metric",
selectors={
"input_text": Selector.select_record_input(),
"output_text": Selector.select_record_output(),
},
)
Custom metric with context:
def custom_with_context(query: str, context: str, response: str) -> float:
"""Evaluate using query, retrieved context, and response."""
# Your evaluation logic
return score
f_custom_context = Metric(
implementation=custom_with_context,
name="Custom Context Metric",
selectors={
"query": Selector.select_record_input(),
"context": Selector.select_context(collect_list=True),
"response": Selector.select_record_output(),
},
)
Tell me what you want to evaluate and I'll help you create the metric!
Feedback functions evaluate specific aspects of your app by:
pip install trulens trulens-providers-openai
from trulens.providers.openai import OpenAI
provider = OpenAI(model_engine="gpt-4o")
TruLens provides shortcuts for common selection patterns:
from trulens.core import Metric, Selector
# Answer relevance: input → output
f_answer_relevance = Metric(
implementation=provider.relevance_with_cot_reasons,
name="Answer Relevance",
selectors={
"prompt": Selector.select_record_input(),
"response": Selector.select_record_output(),
},
)
# Context relevance: input → each context chunk
f_context_relevance = Metric(
implementation=provider.context_relevance_with_cot_reasons,
name="Context Relevance",
selectors={
"question": Selector.select_record_input(),
"context": Selector.select_context(collect_list=False),
},
)
# Groundedness: all contexts → output
f_groundedness = Metric(
implementation=provider.groundedness_measure_with_cot_reasons,
name="Groundedness",
selectors={
"source": Selector.select_context(collect_list=True),
"statement": Selector.select_record_output(),
},
)
Shortcut Reference:
| Shortcut | Selects | Required Span Type |
|---|---|---|
on_input() | App input | RECORD_ROOT |
on_output() | App output | RECORD_ROOT |
on_context() | Retrieved contexts | RETRIEVAL |
⚠️ IMPORTANT: .on_input() and .on_output() require RECORD_ROOT spans!
These shortcuts look for spans with span_type=SpanAttributes.SpanType.RECORD_ROOT. If you use manual instrumentation with a different span type (like AGENT), the shortcuts will not find any data.
Solutions:
TruGraph, TruChain, TruLlama) which create RECORD_ROOT automatically@instrument(span_type=SpanAttributes.SpanType.RECORD_ROOT, ...) on your entry pointSelector objects instead of shortcuts (see Step 3)For more control, use Selector to target specific span attributes:
from trulens.core import Metric
from trulens.core.feedback.selector import Selector
from trulens.otel.semconv.trace import SpanAttributes
f_answer_relevance = Metric(
implementation=provider.relevance_with_cot_reasons,
name="Answer Relevance",
selectors={
"prompt": Selector(
span_type=SpanAttributes.SpanType.RECORD_ROOT,
span_attribute=SpanAttributes.RECORD_ROOT.INPUT,
),
"response": Selector(
span_type=SpanAttributes.SpanType.RECORD_ROOT,
span_attribute=SpanAttributes.RECORD_ROOT.OUTPUT,
),
},
)
The collect_list parameter controls how multiple values are handled:
| Setting | Behavior | Use Case |
|---|---|---|
collect_list=False | Evaluate each value individually | Context relevance (score each chunk) |
collect_list=True | Concatenate all values | Groundedness (check against all context) |
# Evaluate each retrieved context individually (returns multiple scores)
f_context_relevance = Metric(
implementation=provider.context_relevance_with_cot_reasons,
name="Context Relevance",
selectors={
"question": Selector.select_record_input(),
"context": Selector(
span_type=SpanAttributes.SpanType.RETRIEVAL,
span_attribute=SpanAttributes.RETRIEVAL.RETRIEVED_CONTEXTS,
collect_list=False,
),
},
)
# Evaluate against all contexts combined (returns single score)
f_groundedness = Metric(
implementation=provider.groundedness_measure_with_cot_reasons,
name="Groundedness",
selectors={
"source": Selector(
span_type=SpanAttributes.SpanType.RETRIEVAL,
span_attribute=SpanAttributes.RETRIEVAL.RETRIEVED_CONTEXTS,
collect_list=True,
),
"statement": Selector.select_record_output(),
},
)
When collect_list=False produces multiple scores, aggregate them:
import numpy as np
f_context_relevance = Metric(
implementation=provider.context_relevance_with_cot_reasons,
name="Context Relevance",
selectors={
"question": Selector.select_record_input(),
"context": Selector.select_context(collect_list=False),
},
agg=np.mean,
)
Common aggregation functions:
np.mean - Average scorenp.min - Worst score (conservative)np.max - Best score (optimistic)import numpy as np
from trulens.core import Metric, Selector
from trulens.providers.openai import OpenAI
provider = OpenAI()
# Context Relevance: Is each retrieved chunk relevant to the query?
f_context_relevance = Metric(
implementation=provider.context_relevance_with_cot_reasons,
name="Context Relevance",
selectors={
"question": Selector.select_record_input(),
"context": Selector.select_context(collect_list=False),
},
agg=np.mean,
)
# Groundedness: Is the response grounded in the retrieved context?
f_groundedness = Metric(
implementation=provider.groundedness_measure_with_cot_reasons,
name="Groundedness",
selectors={
"source": Selector.select_context(collect_list=True),
"statement": Selector.select_record_output(),
},
)
# Answer Relevance: Does the response answer the original question?
f_answer_relevance = Metric(
implementation=provider.relevance_with_cot_reasons,
name="Answer Relevance",
selectors={
"prompt": Selector.select_record_input(),
"response": Selector.select_record_output(),
},
)
rag_feedbacks = [f_context_relevance, f_groundedness, f_answer_relevance]
from trulens.core import Metric, Selector
from trulens.providers.openai import OpenAI
provider = OpenAI()
# Logical Consistency
f_logical_consistency = Metric(
implementation=provider.logical_consistency_with_cot_reasons,
name="Logical Consistency",
selectors={"trace": Selector(trace_level=True)},
)
# Plan Quality (exclude if agent doesn't do explicit planning)
f_plan_quality = Metric(
implementation=provider.plan_quality_with_cot_reasons,
name="Plan Quality",
selectors={"trace": Selector(trace_level=True)},
)
# Plan Adherence (exclude if agent doesn't do explicit planning)
f_plan_adherence = Metric(
implementation=provider.plan_adherence_with_cot_reasons,
name="Plan Adherence",
selectors={"trace": Selector(trace_level=True)},
)
# Execution Efficiency
f_execution_efficiency = Metric(
implementation=provider.execution_efficiency_with_cot_reasons,
name="Execution Efficiency",
selectors={"trace": Selector(trace_level=True)},
)
# Tool Selection
f_tool_selection = Metric(
implementation=provider.tool_selection_with_cot_reasons,
name="Tool Selection",
selectors={"trace": Selector(trace_level=True)},
)
# Tool Calling
f_tool_calling = Metric(
implementation=provider.tool_calling_with_cot_reasons,
name="Tool Calling",
selectors={"trace": Selector(trace_level=True)},
)
# Tool Quality
f_tool_quality = Metric(
implementation=provider.tool_quality_with_cot_reasons,
name="Tool Quality",
selectors={"trace": Selector(trace_level=True)},
)
# Use all for agents with planning
agent_feedbacks_with_planning = [
f_logical_consistency,
f_plan_quality,
f_plan_adherence,
f_execution_efficiency,
f_tool_selection,
f_tool_calling,
f_tool_quality,
]
agent_feedbacks_no_planning = [
f_logical_consistency,
f_execution_efficiency,
f_tool_selection,
f_tool_calling,
f_tool_quality,
]
def my_custom_metric(input_text: str, output_text: str) -> float:
"""Custom evaluation returning score between 0.0 and 1.0."""
# Your evaluation logic here
score = len(output_text) / (len(input_text) + len(output_text))
return min(max(score, 0.0), 1.0)
f_custom = Metric(
implementation=my_custom_metric,
name="Custom Metric",
selectors={
"input_text": Selector.select_record_input(),
"output_text": Selector.select_record_output(),
},
)
RETRIEVAL.RETRIEVED_CONTEXTS is mapped in your @instrument() decoratorcollect_list=False is set when using .aggregate().on_input()/.on_output() returning no data: These shortcuts require RECORD_ROOT span type. Use framework wrappers or explicit @instrument(span_type=SpanAttributes.SpanType.RECORD_ROOT, ...). See the instrumentation skill for details.RECORD_ROOT spans with INPUT and OUTPUT attributes基于 SOC 职业分类