随着AI的快速发展,开发者往往面临一个选择的悖论:如何选择正确的提示,如何权衡LLM质量与成本?评估可以通过结构化的流程来做出这些决策,从而加速开发。
下面介绍如何使用LangSmith进行评估,并讨论工作流程的每一部分。
一、准备数据集
在 LangSmith UI 中使用 csv 上传创建的数据集。
https://smith.langchain.com/public/730d833b-74da-43e2-a614-4e2ca2502606/d
在这里,我们确保设置了 OpenAI 和 LangSmith 的 API 密钥。
import getpass`import os`` ``def _set_env(var: str):` `if not os.environ.get(var):` `os.environ[var] = getpass.getpass(f"{var}: ")`` ``_set_env("OPENAI_API_KEY")``os.environ["LANGCHAIN_TRACING_V2"] = "true"``os.environ["LANGCHAIN_ENDPOINT"] = "https://api.smith.langchain.com" # Update appropriately for self-hosted installations or the EU region``_set_env("LANGCHAIN_API_KEY")`
指定数据集的名称。
\### Dataset name`dataset_name = "LCEL-QA"`
二、创建Task任务
接下来,使用LangChain来创建检索器并检索相关文档。
### INDEX`` ``from bs4 import BeautifulSoup as Soup``from langchain_community.vectorstores import Chroma``from langchain_openai import OpenAIEmbeddings``from langchain_community.document_loaders.recursive_url_loader import RecursiveUrlLoader``from langchain_text_splitters import RecursiveCharacterTextSplitter`` ``# Load docs``url = "https://python.langchain.com/v0.1/docs/expression_language/"``loader = RecursiveUrlLoader(` `url=url, max_depth=20, extractor=lambda x: Soup(x, "html.parser").text``)``docs = loader.load()`` ``# Split into chunks``text_splitter = RecursiveCharacterTextSplitter(chunk_size=4500, chunk_overlap=200)``splits = text_splitter.split_documents(docs)`` ``# Embed and store in Chroma``vectorstore = Chroma.from_documents(documents=splits, embedding=OpenAIEmbeddings())`` ``# Index``retriever = vectorstore.as_retriever()
创建聊天机器人。
### RAG bot`` ``import openai``from langsmith import traceable``from langsmith.wrappers import wrap_openai`` ``class RagBot:`` ` `def __init__(self, retriever, model: str = "gpt-4-0125-preview"):` `self._retriever = retriever` `# Wrapping the client instruments the LLM` `self._client = wrap_openai(openai.Client())` `self._model = model`` ` `@traceable()` `def retrieve_docs(self, question):` `return self._retriever.invoke(question)`` ` `@traceable()` `def invoke_llm(self, question, docs):` `response = self._client.chat.completions.create(` `model=self._model,` `messages=[` `{` `"role": "system",` `"content": "You are a helpful AI code assistant with expertise in LCEL."` `" Use the following docs to produce a concise code solution to the user question.\n\n"` `f"## Docs\n\n{docs}",` `},` `{"role": "user", "content": question},` `],` `)`` ` `# Evaluators will expect "answer" and "contexts"` `return {` `"answer": response.choices[0].message.content,` `"contexts": [str(doc) for doc in docs],` `}`` ` `@traceable()` `def get_answer(self, question: str):` `docs = self.retrieve_docs(question)` `return self.invoke_llm(question, docs)`` ``rag_bot = RagBot(retriever)
response = rag_bot.get_answer("How to build a RAG chain in LCEL?")``response["answer"][:150]
def predict_rag_answer(example: dict):` `"""Use this for answer evaluation"""` `response = rag_bot.get_answer(example["input_question"])` `return {"answer": response["answer"]}`` ``def predict_rag_answer_with_context(example: dict):` `"""Use this for evaluation of retrieved documents and hallucinations"""` `response = rag_bot.get_answer(example["input_question"])` `return {"answer": response["answer"], "contexts": response["contexts"]}
三、创建评估器
下面介绍4 种类型的 RAG 评估。
1. 响应与参考答案
目标:衡量“RAG 链答案相对于真实答案的相似/正确程度”。
模式:使用通过数据集提供的真值(参考)答案。
评判:使用 LLM-as-judge 来评估答案的正确性。
参考:https://smith.langchain.com/hub/langchain-ai/rag-answer-vs-reference
from langchain import hub``from langchain_openai import ChatOpenAI`` ``# Grade prompt``grade_prompt_answer_accuracy = prompt = hub.pull("langchain-ai/rag-answer-vs-reference")`` ``def answer_evaluator(run, example) -> dict:` `"""` `A simple evaluator for RAG answer accuracy` `"""`` ` `# Get question, ground truth answer, RAG chain answer` `input_question = example.inputs["input_question"]` `reference = example.outputs["output_answer"]` `prediction = run.outputs["answer"]`` ` `# LLM grader` `llm = ChatOpenAI(model="gpt-4-turbo", temperature=0)`` ` `# Structured prompt` `answer_grader = grade_prompt_answer_accuracy | llm`` ` `# Run evaluator` `score = answer_grader.invoke({"question": input_question,` `"correct_answer": reference,` `"student_answer": prediction})` `score = score["Score"]`` ` `return {"key": "answer_v_reference_score", "score": score}
from langsmith.evaluation import evaluate`` ``experiment_results = evaluate(` `predict_rag_answer,` `data=dataset_name,` `evaluators=[answer_evaluator],` `experiment_prefix="rag-answer-v-reference",` `metadata={"version": "LCEL context, gpt-4-0125-preview"},``)
- 响应与输入
目标:衡量“生成的响应对初始用户输入的处理程度”。
模式:无引用,因为它会将答案与输入问题进行比较。
评判:使用 LLM-as-judge 来评估答案的相关性、帮助性等。
参考:https://smith.langchain.com/hub/langchain-ai/rag-answer-helpfulness
# Grade prompt``grade_prompt_answer_helpfulness = prompt = hub.pull("langchain-ai/rag-answer-helpfulness")`` ``def answer_helpfulness_evaluator(run, example) -> dict:` `"""` `A simple evaluator for RAG answer helpfulness` `"""`` ` `# Get question, ground truth answer, RAG chain answer` `input_question = example.inputs["input_question"]` `prediction = run.outputs["answer"]`` ` `# LLM grader` `llm = ChatOpenAI(model="gpt-4-turbo", temperature=0)`` ` `# Structured prompt` `answer_grader = grade_prompt_answer_helpfulness | llm`` ` `# Run evaluator` `score = answer_grader.invoke({"question": input_question,` `"student_answer": prediction})` `score = score["Score"]`` ` `return {"key": "answer_helpfulness_score", "score": score}
experiment_results = evaluate(` `predict_rag_answer,` `data=dataset_name,` `evaluators=[answer_helpfulness_evaluator],` `experiment_prefix="rag-answer-helpfulness",` `metadata={"version": "LCEL context, gpt-4-0125-preview"},``)
- 响应与检索到的文档
目标:衡量“生成的响应与检索到的上下文在多大程度上一致”。
模式:无引用,因为它会将答案与检索到的上下文进行比较。
评判:使用 LLM-as-judge 来评估忠诚度、幻觉等。
参考:https://smith.langchain.com/hub/langchain-ai/rag-answer-hallucination
# Prompt``grade_prompt_hallucinations = prompt = hub.pull("langchain-ai/rag-answer-hallucination")`` ``def answer_hallucination_evaluator(run, example) -> dict:` `"""` `A simple evaluator for generation hallucination` `"""`` ` `# RAG inputs` `input_question = example.inputs["input_question"]` `contexts = run.outputs["contexts"]`` ` `# RAG answer` `prediction = run.outputs["answer"]`` ` `# LLM grader` `llm = ChatOpenAI(model="gpt-4-turbo", temperature=0)`` ` `# Structured prompt` `answer_grader = grade_prompt_hallucinations | llm`` ` `# Get score` `score = answer_grader.invoke({"documents": contexts,` `"student_answer": prediction})` `score = score["Score"]`` ` `return {"key": "answer_hallucination", "score": score}
- 检索到的文档与输入
目标:衡量“我对此查询检索到的结果有多好”。
模式:无引用,因为它会将问题与检索到的上下文进行比较。
评判:使用 LLM-as-judge 评估相关性。
参考:https://smith.langchain.com/hub/langchain-ai/rag-document-relevance
# Grade prompt``grade_prompt_doc_relevance = hub.pull("langchain-ai/rag-document-relevance")`` ``def docs_relevance_evaluator(run, example) -> dict:` `"""` `A simple evaluator for document relevance` `"""`` ` `# RAG inputs` `input_question = example.inputs["input_question"]` `contexts = run.outputs["contexts"]`` ` `# LLM grader` `llm = ChatOpenAI(model="gpt-4-turbo", temperature=0)`` ` `# Structured prompt` `answer_grader = grade_prompt_doc_relevance | llm`` ` `# Get score` `score = answer_grader.invoke({"question":input_question,` `"documents":contexts})` `score = score["Score"]`` ` `return {"key": "document_relevance", "score": score}
experiment_results = evaluate(` `predict_rag_answer_with_context,` `data=dataset_name,` `evaluators=[docs_relevance_evaluator],` `experiment_prefix="rag-doc-relevance",` `metadata={"version": "LCEL context, gpt-4-0125-preview"},``)
四、评估中间步骤
虽然在许多情况下,评估任务的最终输出就足够了,但在某些情况下,你可能想要评估管道的中间步骤。
例如,对于检索增强生成 (RAG),您可能希望:
-
评估检索步骤,以确保在输入查询中检索到正确的文档。
-
评估生成步骤,以确保在检索到的文档中生成正确的答案。
from langsmith.schemas import Example, Run``from langsmith.evaluation import evaluate`` ``def document_relevance_grader(root_run: Run, example: Example) -> dict:` `"""` `A simple evaluator that checks to see if retrieved documents are relevant to the question` `"""`` ` `# Get specific steps in our RAG pipeline, which are noted with @traceable decorator` `rag_pipeline_run = next(` `run for run in root_run.child_runs if run.name == "get_answer"` `)` `retrieve_run = next(` `run for run in rag_pipeline_run.child_runs if run.name == "retrieve_docs"` `)` `contexts = "\n\n".join(doc.page_content for doc in retrieve_run.outputs["output"])` `input_question = example.inputs["input_question"]`` ` `# LLM grader` `llm = ChatOpenAI(model="gpt-4-turbo", temperature=0)`` ` `# Structured prompt` `answer_grader = grade_prompt_doc_relevance | llm`` ` `# Get score` `score = answer_grader.invoke({"question":input_question,` `"documents":contexts})` `score = score["Score"]`` ` `return {"key": "document_relevance", "score": score}`` ``def answer_hallucination_grader(root_run: Run, example: Example) -> dict:` `"""` `A simple evaluator that checks to see the answer is grounded in the documents` `"""`` ` `# RAG input` `rag_pipeline_run = next(` `run for run in root_run.child_runs if run.name == "get_answer"` `)` `retrieve_run = next(` `run for run in rag_pipeline_run.child_runs if run.name == "retrieve_docs"` `)` `contexts = "\n\n".join(doc.page_content for doc in retrieve_run.outputs["output"])`` ` `# RAG output` `prediction = rag_pipeline_run.outputs["answer"]`` ` `# LLM grader` `llm = ChatOpenAI(model="gpt-4-turbo", temperature=0)`` ` `# Structured prompt` `answer_grader = grade_prompt_hallucinations | llm`` ` `# Get score` `score = answer_grader.invoke({"documents": contexts,` `"student_answer": prediction})` `score = score["Score"]`` ` `return {"key": "answer_hallucination", "score": score}`` ``experiment_results = evaluate(` `predict_rag_answer,` `data=dataset_name,` `evaluators=[document_relevance_grader, answer_hallucination_grader],` `metadata={"version": "LCEL context, gpt-4-0125-preview"},``)
如何学习大模型 AI ?
由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。
但是具体到个人,只能说是:
“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。
这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。
我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。
我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。
第一阶段(10天):初阶应用
该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。
- 大模型 AI 能干什么?
- 大模型是怎样获得「智能」的?
- 用好 AI 的核心心法
- 大模型应用业务架构
- 大模型应用技术架构
- 代码示例:向 GPT-3.5 灌入新知识
- 提示工程的意义和核心思想
- Prompt 典型构成
- 指令调优方法论
- 思维链和思维树
- Prompt 攻击和防范
- …
第二阶段(30天):高阶应用
该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。
- 为什么要做 RAG
- 搭建一个简单的 ChatPDF
- 检索的基础概念
- 什么是向量表示(Embeddings)
- 向量数据库与向量检索
- 基于向量检索的 RAG
- 搭建 RAG 系统的扩展知识
- 混合检索与 RAG-Fusion 简介
- 向量模型本地部署
- …
第三阶段(30天):模型训练
恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。
到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?
- 为什么要做 RAG
- 什么是模型
- 什么是模型训练
- 求解器 & 损失函数简介
- 小实验2:手写一个简单的神经网络并训练它
- 什么是训练/预训练/微调/轻量化微调
- Transformer结构简介
- 轻量化微调
- 实验数据集的构建
- …
第四阶段(20天):商业闭环
对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。
- 硬件选型
- 带你了解全球大模型
- 使用国产大模型服务
- 搭建 OpenAI 代理
- 热身:基于阿里云 PAI 部署 Stable Diffusion
- 在本地计算机运行大模型
- 大模型的私有化部署
- 基于 vLLM 部署大模型
- 案例:如何优雅地在阿里云私有部署开源大模型
- 部署一套开源 LLM 项目
- 内容安全
- 互联网信息服务算法备案
- …
学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。
如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。