一、LangSmith
LangSmith是LangChain的一个子产品,是一个大模型应用开发平台。它提供了从原 型到生产的全流程工具和服务,帮助开发者构建、测试、评估和监控基于LangChain 或其他 LLM 框架的应用程序。
安装 LangSmith
pip install langsmith==0.1.137
官网:LangSmith
api_key创建
导入测试数据
新建一个测试集
import pandas as pd df=pd.read_csv('黑悟空.csv') example=list(df.itertuples(index=False,name=None))from langsmith import Client client=Client(api_key="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") dataset_name="example_code"dataset=client.create_dataset(dataset_name=dataset_name) for q,a in example:client.create_example(inputs={"问题": q}, outputs={"答案": a}, dataset_id=dataset.id)
api_key要替换为自己的
二、使用LangSmith进行评估
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
import os
from langsmith import evaluate, Client
from langsmith.schemas import Example, Run
1. 初始化模型
# ChatOpenAI 是一个封装了 OpenAI API 的类
chat_model = ChatOpenAI(# api_key 设置为 'EMPTY',因为本地服务通常不要求密钥api_key='EMPTY',# base_url 指向本地运行的兼容 OpenAI API 的服务,如 Qwen 或 ollamabase_url='http://127.0.0.1:10222/v1',# model 指定要使用的模型名称model='Qwen2.5-7B-Instruct'
)
2.定义聊天提示词模板
# ChatPromptTemplate 用于构建结构化的聊天输入
system_message = "你是一个机器人"
prompt = ChatPromptTemplate.from_messages([# ("system", ...) 定义了系统角色指令("system", system_message),# ("user", ...) 定义了用户的输入模板,{问题} 是一个占位符("user", "{问题}")
])
3. 定义输出解析器
# StrOutputParser 将模型的输出从对象格式解析为纯字符串
output_parser = StrOutputParser()
4. 使用 LCEL (LangChain 表达式语言) 将各个组件串联成一个链
# 管道符 "|" 将数据流依次从 prompt -> chat_model -> output_parser
chain = prompt | chat_model | output_parser
5. 设置 LangSmith 相关的环境变量
# 这些变量用于将本地的运行轨迹上传到 LangSmith 平台
os.environ["LANGCHAIN_TRACING_V2"] = "true" # 开启追踪功能
os.environ["LANGCHAIN_ENDPOINT"] = "https://api.smith.langchain.com" # LangSmith API 地址
# 注意:此处的 API 密钥是公共示例,生产环境请勿泄露
os.environ["LANGCHAIN_API_KEY"] = "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"
6.创建并/或选择数据集
# Client 用于与 LangSmith 平台交互
client = Client()
dataset_name = "example_code"
# 从 LangSmith 公共库克隆一个数据集,作为评估的“黄金标准”
dataset = client.clone_public_dataset("https://smith.langchain.com/public/a63525f9-bdf2-4512-83e3-077dc9417f96/d", dataset_name=dataset_name)
7.定义一个自定义评估器
# 评估器是一个函数,用于根据LLM的输出和数据集的黄金标准来打分
def is_concise_enough(root_run: Run, example: Example) -> dict:# 评估逻辑:检查模型的输出长度是否小于黄金标准答案长度的3倍score = len(root_run.outputs["output"]) < 3 * len(example.outputs["答案"])# 返回一个字典,其中 key 是评估指标名称,score 是分数return {"key": "is_concise", "score": int(score)}
8.运行评估
# evaluate() 函数用于执行自动化评估
evaluate(# 第一个参数是“待评估的函数”,即我们的 LLM 链# lambda x: chain.invoke(x["问题"]) 将数据集中的“问题”字段传递给链lambda x: chain.invoke(x["问题"]),data=dataset_name, # 指定要使用的数据集evaluators=[is_concise_enough], # 传入自定义评估器列表experiment_prefix="my first dataset experiment " # 为本次评估添加一个前缀
)
完整代码
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
import os
from langsmith import evaluate, Client
from langsmith.schemas import Example, Run# 1. 实例化 LLM 模型,并配置其连接到本地服务
# ChatOpenAI 是一个封装了 OpenAI API 的类
chat_model = ChatOpenAI(# api_key 设置为 'EMPTY',因为本地服务通常不要求密钥api_key='EMPTY',# base_url 指向本地运行的兼容 OpenAI API 的服务,如 Qwen 或 ollamabase_url='http://127.0.0.1:10222/v1',# model 指定要使用的模型名称model='Qwen2.5-7B-Instruct'
)# 2. 定义聊天提示词模板
# ChatPromptTemplate 用于构建结构化的聊天输入
system_message = "你是一个机器人"
prompt = ChatPromptTemplate.from_messages([# ("system", ...) 定义了系统角色指令("system", system_message),# ("user", ...) 定义了用户的输入模板,{问题} 是一个占位符("user", "{问题}")
])# 3. 定义输出解析器
# StrOutputParser 将模型的输出从对象格式解析为纯字符串
output_parser = StrOutputParser()# 4. 使用 LCEL (LangChain 表达式语言) 将各个组件串联成一个链
# 管道符 "|" 将数据流依次从 prompt -> chat_model -> output_parser
chain = prompt | chat_model | output_parser# 5. 设置 LangSmith 相关的环境变量
# 这些变量用于将本地的运行轨迹上传到 LangSmith 平台
os.environ["LANGCHAIN_TRACING_V2"] = "true" # 开启追踪功能
os.environ["LANGCHAIN_ENDPOINT"] = "https://api.smith.langchain.com" # LangSmith API 地址
# 注意:此处的 API 密钥是公共示例,生产环境请勿泄露
os.environ["LANGCHAIN_API_KEY"] = "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" # 6. 创建并/或选择数据集
# Client 用于与 LangSmith 平台交互
client = Client()
dataset_name = "example_code"
# 从 LangSmith 公共库克隆一个数据集,作为评估的“黄金标准”
dataset = client.clone_public_dataset("https://smith.langchain.com/public/a63525f9-bdf2-4512-83e3-077dc9417f96/d", dataset_name=dataset_name)# 7. 定义一个自定义评估器
# 评估器是一个函数,用于根据LLM的输出和数据集的黄金标准来打分
def is_concise_enough(root_run: Run, example: Example) -> dict:# 评估逻辑:检查模型的输出长度是否小于黄金标准答案长度的3倍score = len(root_run.outputs["output"]) < 3 * len(example.outputs["答案"])# 返回一个字典,其中 key 是评估指标名称,score 是分数return {"key": "is_concise", "score": int(score)}# 8. 运行评估
# evaluate() 函数用于执行自动化评估
evaluate(# 第一个参数是“待评估的函数”,即我们的 LLM 链# lambda x: chain.invoke(x["问题"]) 将数据集中的“问题”字段传递给链lambda x: chain.invoke(x["问题"]),data=dataset_name, # 指定要使用的数据集evaluators=[is_concise_enough], # 传入自定义评估器列表experiment_prefix="my first dataset experiment " # 为本次评估添加一个前缀
)
三、使用 LangSmith平台自动化评估
准备工作
from langchain_community.vectorstores import FAISS # 导入FAISS向量存储库
from langchain_huggingface import HuggingFaceEmbeddings # 导入Hugging Face嵌入模型
from langchain_community.document_loaders import TextLoader # 导入文本加载器
from langchain.text_splitter import RecursiveCharacterTextSplitter # 导入递归字符文本分割器
from langchain_openai import ChatOpenAI # 导入ChatOpenAI模型# 使用 OpenAI API 的 ChatOpenAI 模型,但配置为连接本地服务
# 这是评估的核心:需要被测试的 LLM 模型
chat_model = ChatOpenAI(api_key='EMPTY', # 本地服务通常不需要密钥base_url='http://127.0.0.1:10222/v1', # 指定本地模型的 API 地址model='Qwen2.5-7B-Instruct'
)
数据加载与处理模块
# 加载文本文件 "黑悟空.txt",编码格式为 'utf-8'
loader = TextLoader("黑悟空.txt", encoding='utf-8')
docs = loader.load() # 将文件内容加载到变量 docs 中# 把文本分割成 200 字一组的切片,每组之间有 20 字重叠
text_splitter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=20)
chunks = text_splitter.split_documents(docs) # 将文档分割成多个小块# 初始化嵌入模型,使用预训练的语言模型 'bge-large-zh-v1___5'
# 这个模型用于将文本块转换为向量
embedding = HuggingFaceEmbeddings(model_name='models/AI-ModelScope/bge-large-zh-v1___5')# 构建 FAISS 向量存储和对应的 retriever
vs = FAISS.from_documents(chunks, embedding) # 将文本块转换为向量并存储在FAISS中# 创建一个检索器,用于根据问题从向量存储中查找最相关的文档
retriever = vs.as_retriever()
RAG 链构建模块
from langchain.prompts import (ChatPromptTemplate,SystemMessagePromptTemplate,HumanMessagePromptTemplate,
)# 创建一个系统消息,用于定义机器人的角色和输入格式
# {context} 是一个占位符,用于填充检索到的相关信息
system_message = SystemMessagePromptTemplate.from_template("根据以下已知信息回答用户问题。\n 已知信息{context}"
)# 创建一个人类消息,用于接收用户的输入
# {question} 是一个占位符,用于填充用户的原始问题
human_message = HumanMessagePromptTemplate.from_template("用户问题:{question}"
)# 将这些模板结合成一个完整的聊天提示
chat_prompt = ChatPromptTemplate.from_messages([system_message,human_message,
])"""使用LCEL实现"""
# 格式化文档,将多个文档连接成一个大字符串
def format_docs(docs):return "\n\n".join(doc.page_content for doc in docs)# 创建字符串输出解析器,用于解析LLM的输出
from langchain_core.output_parsers import StrOutputParser
output_parser = StrOutputParser()from langchain_core.runnables import RunnablePassthrough
# 创建 rag_chain,这是整个 RAG 流程的核心管道
rag_chain = (# 这部分使用字典语法,并行执行两个任务:# 1. 'context': 使用 retriever 检索文档并用 format_docs 格式化# 2. 'question': 使用 RunnablePassthrough 将原始问题原样传递{"context": retriever | format_docs, "question": RunnablePassthrough()}| chat_prompt # 将格式化后的上下文和问题传递给提示模板| chat_model # 将提示词传递给 LLM 模型| output_parser # 将 LLM 的输出解析为字符串
)
# print(rag_chain.invoke("黑熊精自称为?")) # 这是一个用于手动测试的示例
LangSmith 评估配置模块
import os# 设置 LangSmith 相关的环境变量,用于连接平台并上传运行轨迹
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_ENDPOINT"] = "https://api.smith.langchain.com"
os.environ["LANGCHAIN_API_KEY"] = "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"
评估器定义与选择模块
from langsmith import evaluate, Client from langsmith.schemas import Example, Run# 1. 创建并/或选择你的数据集 client = Client() dataset_name = "example_code" # 克隆一个 LangSmith 公共数据集,作为评估的黄金标准 dataset = client.clone_public_dataset("https://smith.langchain.com/public/a63525f9-bdf2-4512-83e3-077dc9417f96/d", dataset_name=dataset_name)
1、方式1:原始的代码:评估简洁度。这是一个基于长度的简单评估器。
def is_concise_enough(root_run: Run, example: Example) -> dict:# 比较 LLM 输出的长度是否小于标准答案长度的3倍score = len(root_run.outputs["output"]) < 3 * len(example.outputs["答案"])return {"key": "is_concise", "score": int(score)}
2、更大的模型将原始答案与生成答案进行准确度评估。这是一个基于LLM的定性评估。
from langsmith.evaluation import LangChainStringEvaluator eval_model = ChatOpenAI(model="/home/AI_big_model/models/Qwen/Qwen2.5-7B-Instruct",api_key="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",base_url="https://api.siliconflow.cn/v1", )
3、通过余弦相似度进行评估。这是一个基于向量相似度的定量评估
from sentence_transformers import SentenceTransformer from sklearn.metrics.pairwise import cosine_similarity # 加载与用于生成向量数据库的embedding模型相同的模型 model = SentenceTransformer("/home/AI_big_model/models/AI-ModelScope/bge-large-zh-v1___5") def cal_cosine_similarity(root_run: Run, example: Example) -> dict:model_output = root_run.outputs["output"]reference_answer = example.outputs["答案"]# 将模型输出和标准答案编码成向量embeddings = model.encode([model_output, reference_answer])# 计算两个向量之间的余弦相似度similarity = cosine_similarity([embeddings[0]], [embeddings[1]])[0][0]# 定义一个分数:当相似度大于等于0.75时,得分为1,否则为0score = similarity >= 0.75return {"key": "cosine_similarity", "score": int(score)}
运行自动化评估
# 最终的评估执行函数
evaluate(# 传入要评估的链,lambda 函数用于从数据集行中提取问题lambda x: rag_chain.invoke(x["问题"]),# chain.invoke# graph.invokedata=dataset_name, # 指定用于评估的数据集evaluators=[cal_cosine_similarity], # 传入要使用的评估器(这里是方式3)experiment_prefix="my first dataset experiment " # 为实验添加一个唯一前缀
)