langfuse 用法
@observe 用法
as_type
在 Langfuse 中,chain 和 span 都是用于追踪应用逻辑的观测类型(observation),但它们在 UI 展示和数据模型中代表的逻辑工作单元层级不同:
Span:
Trace 中最基础的工作单元,用来表示某个操作在一段时间内的执行过程。它是一种通用类型,可用于记录任意操作,例如数据检索、Prompt 构造或其他函数调用;同时也可以作为一个容器,用于对相关操作进行分组。
Chain:
一种更高层次、语义更明确的 span 类型,用于表示不同应用步骤之间的连接或执行流程,通常涉及上下文在多个组件之间的传递(例如从检索器到 LLM 调用)。它常与 LangChain、LangGraph 等集成使用,用来在 Trace 可视化中清晰地表达整个应用逻辑的执行流。
capture_input,capture_output
当设置为True的时候
@observe 装饰器会自动捕获函数的参数(作为 input)和返回值(作为 output),并且会覆盖我们手动设置的值。
当我不希望默认的输入的输出在langfuse上显示,我希望通过手动的方式加工输入和输出的格式方便langfuse评测捕捉变量的时候。
当使用langgraph的时候,如果capture_output=False,将会导致graph 图断裂
@observe(
name="identify_intent",
as_type="span",
capture_input=False, # 🔑 禁用自动捕获 input
capture_output=False # 🔑 改为 True,让装饰器捕获返回值
)
def identify_intent(user_input: str) -> dict: # 返回字典而不是字符串
# ✅ as_type="span" → 使用 update_current_span()
langfuse.update_current_span(input={"query": user_input})
langfuse.flush()
time.sleep(0.3) # 模拟处理延迟
# 简单逻辑:根据关键词识别意图
if "支付" in user_input:
intent = "payment_info"
elif "订单" in user_input:
intent = "order_status"
else:
intent = "unknown"
langfuse.update_current_span(output={"intent": intent})
langfuse.flush()
# 🔑 直接返回结构化数据,让装饰器捕获为 output
return {"intent": intent, "raw_intent": intent}
完整例子
import time
from dotenv import load_dotenv
from langfuse import get_client
from langfuse import observe
# 加载环境变量
load_dotenv()
# 获取 Langfuse client
langfuse = get_client()
# ---------------------------
# 子函数 1:模拟意图识别
# ---------------------------
@observe(
name="identify_intent",
as_type="span",
capture_input=False, # 🔑 禁用自动捕获 input
capture_output=False # 🔑 改为 True,让装饰器捕获返回值
)
def identify_intent(user_input: str) -> dict: # 返回字典而不是字符串
# ✅ as_type="span" → 使用 update_current_span()
langfuse.update_current_span(input={"query": user_input})
langfuse.flush()
time.sleep(0.3) # 模拟处理延迟
# 简单逻辑:根据关键词识别意图
if "支付" in user_input:
intent = "payment_info"
elif "订单" in user_input:
intent = "order_status"
else:
intent = "unknown"
langfuse.update_current_span(output={"intent": intent})
langfuse.flush()
# 🔑 直接返回结构化数据,让装饰器捕获为 output
return {"intent": intent, "raw_intent": intent}
# ---------------------------
# 子函数 2:模拟响应生成
# ---------------------------
@observe(
name="generate_response",
as_type="generation",
capture_input=False, # 🔑 禁用自动捕获 input
capture_output=True # 🔑 改为 True,让装饰器捕获返回值
)
def generate_response(intent_data: dict) -> dict: # 返回字典
intent = intent_data.get("intent") or intent_data.get("raw_intent")
# ✅ as_type="generation" → 使用 update_current_generation()
langfuse.update_current_generation(input={"intent": intent})
langfuse.flush()
time.sleep(0.4) # 模拟生成延迟
responses = {
"payment_info": "我们支持支付宝、微信和信用卡支付。",
"order_status": "请提供订单号,我帮你查询状态。",
"unknown": "抱歉,我不太明白您的意思。"
}
answer = responses.get(intent, "抱歉,我无法回答。")
# 🔑 直接返回结构化数据,让装饰器捕获为 output
return {"generation": answer, "raw_answer": answer}
# ---------------------------
# 主函数:入口业务链
# ---------------------------
@observe(
name="customer_service_chat",
as_type="chain",
capture_input=False, # 🔑 禁用自动捕获 input
capture_output=True # 🔑 改为 True,让装饰器捕获返回值
)
def customer_service_chat(user_input: str) -> dict: # 返回字典
# ✅ as_type="chain" → 使用 update_current_span() (chain 是一种 span)
langfuse.update_current_span(input={"user_input": user_input})
langfuse.flush()
# 调用子函数 1:意图识别
intent_data = identify_intent(user_input)
# 调用子函数 2:生成响应
response_data = generate_response(intent_data)
answer = response_data.get("raw_answer")
intent = intent_data.get("raw_intent")
# 🔑 直接返回结构化数据,让装饰器捕获为 output
return {
"final_answer": answer,
"intent": intent,
"generation": answer
}
# ---------------------------
# 主程序入口
# ---------------------------
if __name__ == "__main__":
user_query = "请问你们支持哪些支付方式?"
result = customer_service_chat(user_query)
print("AI 回复:", result.get("final_answer"))

浙公网安备 33010602011771号