LangSmith简明教程

本文基于我的书“大型语言模型项目:应用和实施大型语言模型的策略”(Apress)和关于 LLM 的免费 G​​itHub 课程的内容。

为了创建这篇文章,我将使用上一篇文章中构建的代理:如何创建医疗代理/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 中生成一个条目,其中包含:

  • 查询。
  • 找到的文档。
  • 返回的文本。
  • 以及每个操作所花费的时间。
检索器在 langSmith 中记录

但还有更多!你还会发现与模型响应一起创建的提示。

LLM 在 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

汇智网翻译整理,转载请标明出处