LangSmith 调试

1. 为什么需要 LangSmith

在简单案例中,我们通常只看终端输出:

复制代码
回答:退款通常在 1 至 3 个工作日到账。

但真实项目出问题时,只看最终输出远远不够。

例如:

复制代码
RAG 回答错了

你需要知道:

  • 用户原始问题是什么
  • Retriever 检索到了哪些文档
  • Prompt 最终长什么样
  • 模型输入了多少 Token
  • 模型输出了什么
  • 哪一步耗时最长
  • Agent 有没有调用工具
  • 工具参数是否正确
  • 工具返回了什么

LangSmith 就是用来观察、调试和评估大模型应用的平台。

它可以把一次 LangChain 调用记录成完整链路。

2. LangSmith 能看到什么

开启追踪后,LangSmith 中可以看到:

|-----------|---------------|
| 内容 | 作用 |
| Trace | 一次完整调用链路 |
| Run | 链路中的一个步骤 |
| Input | 当前步骤输入 |
| Output | 当前步骤输出 |
| Prompt | 发送给模型的提示词 |
| Tool Call | Agent 调用工具的记录 |
| Token | 模型输入和输出消耗 |
| Latency | 每一步耗时 |
| Error | 报错信息 |
| Metadata | 自定义业务信息 |

对于 RAG 项目,重点看:

  • 检索问题是否正确
  • 检索结果是否相关
  • 上下文是否传给模型
  • 模型是否根据资料回答

对于 Agent 项目,重点看:

  • 是否调用了工具
  • 调用了哪个工具
  • 工具参数是否正确
  • 工具结果是否被模型正确使用

3. 开通和配置 LangSmith

访问:

复制代码
https://smith.langchain.com

登录后创建 API Key。

在项目根目录创建 .env

复制代码
DEEPSEEK_API_KEY=你的DeepSeek API Key
DEEPSEEK_BASE_URL=https://api.deepseek.com

LANGSMITH_TRACING=true
LANGSMITH_API_KEY=你的LangSmith API Key
LANGSMITH_PROJECT=langchain-course-demo

环境变量说明:

|---------------------|------------------------|
| 变量 | 作用 |
| LANGSMITH_TRACING | 是否开启追踪 |
| LANGSMITH_API_KEY | LangSmith API Key |
| LANGSMITH_PROJECT | 追踪记录所属项目 |
| DEEPSEEK_API_KEY | DeepSeek API Key |
| DEEPSEEK_BASE_URL | DeepSeek OpenAI 兼容接口地址 |

如果暂时不想开启 LangSmith,可以改成:

复制代码
LANGSMITH_TRACING=false

4. 安装依赖

安装本章依赖:

复制代码
pip install langsmith

国内镜像:

复制代码
pip install langchain langchain-openai langsmith python-dotenv -i https://pypi.tuna.tsinghua.edu.cn/simple

如果要运行综合 RAG 和 Agent 项目,还需要:

复制代码
pip install langchain-community langchain-text-splitters sentence-transformers pypdf pydantic

5. 案例一:追踪一次普通模型调用

创建 01_trace_chat.py

复制代码
from utils.model_factory import get_deepSeek_model

model=get_deepSeek_model()
respone=model.invoke("帅哥为什么这么帅?")
print(respone.content)

运行:

复制代码
python 01_trace_chat.py

如果 .env 中配置了:

复制代码
LANGSMITH_TRACING=true
LANGSMITH_API_KEY=...
LANGSMITH_PROJECT=langchain-course-demo

运行后就可以在 LangSmith 项目中看到这次调用。

你可以重点查看:

  • 输入内容
  • 模型输出
  • 调用耗时
  • Token 消耗
  • 模型名称

6. 案例二:追踪 LCEL Chain

创建 02_trace_chain.py

复制代码
from langchain_core.output_parsers import StrOutputParser

from utils.model_factory import get_deepSeek_model
from utils.prompt_template import getPromptTemplate

model=get_deepSeek_model()
prompt_template=getPromptTemplate(
	"你是一个python讲师,善于使用最简洁易懂的语言讲解问题",
	"{question}"
)
parser=StrOutputParser()

chain=prompt_template | model | parser

result=chain.invoke(
	{"question":"python中的魔法方法有哪些?"},
	config={
        "run_name": "concept_explain_chain",
        "tags": ["chapter10", "lcel"],
        "metadata": {
            "course": "LangChain",
            "chapter": 10,
        },
    },
)
print(result)
print(type(result).__name__)

运行:

复制代码
python 02_trace_chain.py

这里的 config 可以给本次运行增加信息:

复制代码
config={
    "run_name": "concept_explain_chain",
    "tags": ["chapter10", "lcel"],
    "metadata": {
        "course": "LangChain",
        "chapter": 10,
    },
}

在 LangSmith 中,run_nametagsmetadata 可以帮助你筛选和定位调用记录。

过滤:

7. 案例三:追踪 Agent 工具调用

创建 03_trace_agent.py

复制代码
from langchain.agents import create_agent
from langchain_core.messages import HumanMessage
from langchain_core.tools import tool

from utils.model_factory import get_deepSeek_model

@tool
def search_order_wuliu(order_id:str)->str:
	"""根据订单号查询订单状态,包括是否付款、是否发货、快递单号和签收状态。"""
	fake_orders = {
		"A1001": "已付款,等待发货",
		"A1002": "已发货,快递单号 SF123456",
		"A1003": "已签收",
	}

	return fake_orders.get(order_id, "没有查询到该订单")

# agent
agent=create_agent(
	model=get_deepSeek_model(),
	tools=[search_order_wuliu],
	system_prompt="你是一个电商客户,善于使用工具查询物流信息"
)

result=agent.invoke(
	{
		"messages":[HumanMessage(content="帮我查询一下订单编号为A1001的物流信息")]
	},
	config={
		"run_name":"agent电商客服助手"
	}
)

print(result['messages'][-1].content)

运行:

复制代码
python 03_trace_agent.py

在 LangSmith 中可以看到:

复制代码
用户问题
  -> 模型请求调用 get_order_status
  -> 工具返回订单状态
  -> 模型生成最终回答

用户提问 → 大模型识别需要调用工具 → 调用查询订单接口 → 获取接口数据 → 大模型把原始数据整理成自然语言回答用户

这对调试 Agent 非常有用。

如果 Agent 没有调用工具,可以在 Trace 中检查:

  • 工具描述是否传给模型
  • 用户问题是否包含订单号
  • 模型是否直接生成了答案
  • 工具调用参数是否错误

8. 什么是评估

调试解决的是单次调用问题。

评估关注的是一批问题的整体效果。

例如 RAG 知识库问答,我们希望知道:

复制代码
10 个测试问题中,有几个回答正确?

最简单的评估方式是准备测试集:

复制代码
test_cases = [
    {
        "question": "退款多久到账?",
        "expected_keyword": "1 至 3 个工作日",
    },
    {
        "question": "每个月可以补卡几次?",
        "expected_keyword": "两次",
    },
]

然后批量调用应用,检查答案中是否包含预期关键词。

这种程序可以称为一个简单的评估 harness。

9. 案例四:评估普通 Chain

创建 04_eval_chain.py

复制代码
from langchain.agents import create_agent
from langchain_core.output_parsers import StrOutputParser

from utils.model_factory import get_deepSeek_model
from utils.prompt_template import getPromptTemplate

model=get_deepSeek_model()
prompt_template=getPromptTemplate(
	"你是一个langchain老师,善于回答各种关于langchain的问题,答案要简洁,不要超过30个字",
	"{question}"
)
test_cases = [
    {
        "question": "LangChain 中 PromptTemplate 的作用是什么?",
        "expected_keyword": "模版",
    },
    {
        "question": "RAG 的核心流程是什么?",
        "expected_keyword": "检索",
    },
    {
        "question": "Agent 为什么需要 Tool?",
        "expected_keyword": "外部",
    },
]

chain = prompt_template | model | StrOutputParser()

pass_num=0
for index,case in enumerate(test_cases,start=1):
	question=case['question']
	expected_keyword=case['expected_keyword']
	print(f"开始第{index}个问题")
	result=chain.invoke({
		"question":question
	})
	passed=False
	if expected_keyword in result:
		passed=True
		pass_num+=1
	print("-" * 60)
	print(f"用例 {index}")
	print(f"问题:{question}")
	print(f"答案:{result}")
	print(f"预期关键词:{expected_keyword}")
	print(f"是否通过:{passed}")
# 计算通过率
print(f"总共有{len(test_cases)}个问题")
print(f"通过了{pass_num}个")
print(f"通过率是:{pass_num/len(test_cases):.2f}")

运行:

复制代码
python 04_eval_chain.py

关键词评估很简单,但适合入门。

真实项目中还可以继续增加:

  • 人工评分
  • 大模型评分
  • 标准答案对比
  • 检索结果相关性评估
  • 工具调用正确性评估

10、案例七:通过 langsmith 进行评估

以上三个案例都是本地进行评估测试,和 langsmith 无关

复制代码
import os
from dotenv import load_dotenv
from langchain.chat_models import init_chat_model
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langsmith import Client, evaluate

load_dotenv()
client = Client()

model = init_chat_model(
    model="deepseek-v4-flash",
    model_provider="openai",
    api_key=os.getenv("DEEPSEEK_API_KEY"),
    base_url=os.getenv("DEEPSEEK_BASE_URL"),
    temperature=0,
)

prompt_template = ChatPromptTemplate.from_messages(
    [
        ("system", "你是一名课程助教,请用简洁中文回答。回答中尽量使用行业标准术语。"),
        ("human", "{question}"),
    ])
chain = prompt_template | model | StrOutputParser()

# ---------------------- 关键词评估器 ----------------------
def keyword_check_evaluator(run, example):
    try:
        output_text = run.outputs["output"]
        expected_keyword = example.outputs["expected_keyword"]
        hit = expected_keyword in output_text
        return {
            "key": "keyword_match",
            "score": 1 if hit else 0,
            "comment": f"预期关键词:{expected_keyword},是否命中:{hit}"
        }
    except Exception as e:
        return {
            "key": "keyword_match",
            "score": None,
            "comment": f"评估执行异常: {str(e)}"
        }

# ---------------------- 数据集 ----------------------
dataset_name = "llm_course_qa_testset2"
try:
    dataset = client.read_dataset(dataset_name=dataset_name)
except Exception as e:
    print(e)
    dataset = client.create_dataset(dataset_name=dataset_name)
    client.create_examples(
        inputs=[
            {"question": "LangChain 中 PromptTemplate 的作用是什么?"},
            {"question": "RAG 的核心流程是什么?"},
            {"question": "Agent 为什么需要 Tool?"},
        ],
        outputs=[
            {"expected_keyword": "提示词"},
            {"expected_keyword": "检索"},
            {"expected_keyword": "外部"},
        ],
        dataset_id=dataset.id
    )

# ==========【重点改动】替换lambda,定义包装函数 ==========
def target_function(inputs):
    result_str = chain.invoke(inputs)
    # 强制返回字典,保证run.outputs["output"]稳定存在
    return {"output": result_str}

# 启动评估
experiment = evaluate(
    target_function,
    data=dataset_name,
    evaluators=[keyword_check_evaluator],
    experiment_prefix="keyword_eval_course_qa_fixed",
)

print("评估任务已提交,请前往LangSmith网页查看实验结果!")

运行,查看结果:

数据集:

评估效果:

相关推荐
DRXB25072010 小时前
开源自由还是生态红利?LangChain 的灵活性与小艺开放平台的鸿蒙流量池,开发者该如何抉择?
langchain·开源·harmonyos
鱼饼Y14 小时前
AI时代,使用大模型学习LangChain (3)——LCEL
人工智能·langchain
用户6676750937914 小时前
LangChain 向量检索为什么要用 as_retriever?从 LCEL 到 RunnableParallel 一次讲清
langchain
lzjava202415 小时前
LangGraph Subgraphs 子图
langchain
元Y亨H15 小时前
大模型技术-RAG 常用的向量数据库
langchain·llm
元Y亨H15 小时前
大模型技术 Agents 概述
langchain·llm
元Y亨H15 小时前
大模型技术 Agent添加MCP工具
langchain·llm
元Y亨H15 小时前
大模型技术-RAG 向量存储和检索 概述
langchain·llm
元Y亨H15 小时前
大模型技术 LangChain使用MCP
langchain·llm