LangSmith简明教程
本文基于我的书“大型语言模型项目:应用和实施大型语言模型的策略”(Apress)和关于 LLM 的免费 GitHub 课程的内容。
为了创建这篇文章,我将使用上一篇文章中构建的代理:如何创建医疗代理/RAG 系统。
但别担心;文章和随附的笔记本都包含所有必要的代码。关于如何创建代理的解释不会像提到的文章中那样详细,因为在这种情况下,我将更多地关注 LangSmith 以及如何跟踪代理的内部流量。
与往常一样,本文将基于笔记本中的代码,可以在此处找到。
我的建议是在阅读文章时打开笔记本,并在完成后创建自己的版本。
1、加载数据集
首先,让我们加载数据集。正如我之前提到的,我将包含代码,但不提供详细解释:
!pip install -q langchain==0.3.0
!pip install -q langchain-openai==0.2.0
!pip install -q langchainhub==0.1.21
!pip install -q datasets==3.0.0
!pip install -q chromadb==0.5.5
!pip install -q langchain-community==0.3.0
from datasets import load_dataset
data = load_dataset("keivalya/MedQuad-MedicalQnADataset", split='train')
data = data.to_pandas()
# Uncoment this line if you want to limit the size of the data.
# data = data[0:100]
现在你已将数据集加载到变量 Data 中。请记住,如果你正在运行测试,最好只使用部分数据以节省执行时间。
我们的代理使用的工具是一个检索器,它将搜索存储在矢量数据库中的信息,本质上充当一个简单的 RAG 系统。我将使用的矢量数据库是 ChromaDB,由于代理将使用 LangChain 构建,因此需要加载一些库并加载数据。
在继续之前,我想强调一下,创建代理不是必须使用 LangChain。你可以使用任何其他框架,例如 LlamaIndex,它与 LangSmith 配合使用效果也一样好。
2、存储在矢量数据库中
from langchain.document_loaders import DataFrameLoader
from langchain.vectorstores import Chroma
df_loader = DataFrameLoader(data, page_content_column="Answer")
我们的代理的相关数据存储在 df_loader
变量中,需要将其传输到矢量数据库。但是,由于这些是相当长的文本,因此需要先将它们分成块。
要将文档拆分成不同的块,我们将使用 Langchain 中的 CharacterTextSplitter
类。
from langchain.text_splitter import CharacterTextSplitter
text_splitter = CharacterTextSplitter(chunk_size=1250,
separator="\n",
chunk_overlap=100)
texts = text_splitter.split_documents(df_document)
chunk_overlap
(重叠) 是块之间重复的文本量。例如,如果你指定重叠为 100,则块的前 100 个字符将与前一个块的后 100 个字符匹配。
块不会总是在字符 1250 处拆分;事实上,这种情况很少发生。要拆分文本,该函数会等待,直到找到指定的分隔符,默认情况下是 \n\n
,但我将其更改为 \n
,因此有时会在之前拆分,有时会在之后拆分。
是时候将文本转换为嵌入并将其存储到 ChromaDB 中了。
但首先,让我们使用必要的密钥配置环境以继续开发:
os.environ["LANGCHAIN_API_KEY"] = getpass("LangChain API Key: ")
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_ENDPOINT"]="https://api.smith.langchain.com"
os.environ["LANGCHAIN_PROJECT"]="langsmith_test_agent"
你可以从 LangSmith 面板中的个人->设置区域获取你的 LangChain API 密钥。
现在一切都已准备就绪,可以创建数据库并将正确格式的信息加载到其中:
# We load the text-embedding-ada-002 model from OpenAI.
from langchain_openai import OpenAIEmbeddings
model_name = 'text-embedding-ada-002'
embed = OpenAIEmbeddings(
model=model_name
)
要将文本转换为嵌入,我们将使用 OpenAI 的模型“text-embedding-ada-002”。
你可以通过将文本和嵌入模型传递给它来创建矢量数据库:
directory_cdb = '/content/drive/MyDrive/chromadb'
chroma_db = Chroma.from_documents(
df_document, embed, persist_directory=directory_cdb
)
model="gpt-4o"
#model="gpt-3.5-turbo"
from langchain.chat_models import ChatOpenAI
from langchain_openai import OpenAI
from langchain.chains.conversation.memory import ConversationBufferWindowMemory
from langchain.chains import RetrievalQA
llm=OpenAI(temperature=0.0)
conversational_memory = ConversationBufferWindowMemory(
memory_key='chat_history',
k=4, #Number of messages stored in memory
return_messages=True #Must return the messages in the response.
)
qa = RetrievalQA.from_chain_type(
llm=llm,
#chain_type="stuff",
retriever=chroma_db.as_retriever()
)
看起来我们只创建了代理将用来访问矢量数据库中信息的检索器。这是真的,但是由于你已经配置了 LangSmith 运行所需的环境变量,因此一旦使用检索器,信息就会开始记录在 LangSmith 中。
3、在 LangSmith 中记录
例如,像这样调用检索器:
qa.run("What is the main symptom of LCM?")
在 LangSmith 中生成一个条目,其中包含:
- 查询。
- 找到的文档。
- 返回的文本。
- 以及每个操作所花费的时间。
但还有更多!你还会发现与模型响应一起创建的提示。
4、创建并跟踪代理
我想你和我第一次使用 LangSmith 时一样惊讶。“但我什么都没做!我只需要设置几个环境变量,就这样!”嗯,是的,它真的就这么简单——而且还有更多。
要继续,第一步是创建代理,从它将用于访问信息的工具开始:
from langchain.agents import Tool
#Defining the list of tool objects to be used by LangChain.
tools = [
Tool(
name='Medical KB',
func=qa.run,
description=(
"""use this tool when answering medical knowledge queries to get
more information about the topic"""
)
)
]
创建代理和代理执行器:
from langchain.agents import create_react_agent
from langchain import hub
prompt = hub.pull("hwchase17/react-chat")
agent = create_react_agent(
tools=tools,
llm=llm,
prompt=prompt,
)
# Create an agent executor by passing in the agent and tools
from langchain.agents import AgentExecutor
agent_executor2 = AgentExecutor(agent=agent,
tools=tools,
verbose=True,
memory=conversational_memory,
max_iterations=30,
max_execution_time=600,
handle_parsing_errors=True
)
现在,我们可以调用代理并查看信息如何存储在 LangChain 中:
agent_executor2.invoke({"input": """I have a patient that can have Botulism,
how can I confirm the diagnosis?"""})
可以看到跟踪的信息量相当高。对 Retriever 的调用分组在 RetrievalQA 下,最终响应在 OpenAI 下。
正如你所理解的,我无法将所有 LangSmith 屏幕与所有生成的信息一起包含在内。我认为这不会增加太多价值,而且会浪费时间和空间。如果你有兴趣探索存储的信息,最好的办法是运行笔记本并亲自查看!
5、结束语
如果你还不熟悉 LangSmith,我想你现在会对它的强大功能和易用性感到惊讶。
我建议你也阅读这篇文章:使用 LangSmith 的嵌入距离评估 LLM 摘要。它使用 LangSmith 的评估器来收集有关大型语言模型性能的指标。
LangSmith 是与大型语言模型世界相关的新一波工具的一部分,旨在使构建应用程序变得更容易。
原文链接:Tracing a LLM Agent with LangSmith
汇智网翻译整理,转载请标明出处