Python与智能体:如何使用LangChain和LlamaIndex构建LLM应用。

Python与智能体:如何使用LangChain和LlamaIndex构建LLM应用

大家好,今天我们来聊聊如何使用Python,结合LangChain和LlamaIndex这两个强大的框架,构建基于大型语言模型(LLM)的智能体应用。LLM的应用场景非常广泛,例如智能客服、文档问答、数据分析等等。LangChain和LlamaIndex的出现,极大地简化了构建这些应用的过程。

1. LLM应用面临的挑战

直接使用LLM API,虽然可以完成很多任务,但构建复杂的应用往往会面临以下挑战:

  • 上下文管理: LLM有上下文长度限制,如何处理超出限制的长文档?
  • 知识整合: 如何将外部知识库(如数据库、文档)整合到LLM中?
  • 任务编排: 如何将复杂任务分解成多个步骤,并让LLM协同完成?
  • 可观测性: 如何追踪LLM的推理过程,方便调试和改进?

LangChain和LlamaIndex正是为了解决这些问题而诞生的。

2. LangChain:构建LLM应用的工具箱

LangChain是一个用于开发由语言模型驱动的应用程序的框架。它提供了一系列的组件,可以帮助我们轻松地构建复杂的LLM应用。

  • 模型 (Models): 提供与各种LLM的接口,如OpenAI、Hugging Face等。
  • 提示词 (Prompts): 管理和优化输入到LLM的提示词,提高输出质量。
  • 链 (Chains): 将多个组件组合在一起,形成一个完整的pipeline。
  • 索引 (Indexes): 针对大量文档建立索引,提高检索效率。
  • 记忆 (Memory): 在对话中保存历史信息,实现上下文感知。
  • 代理 (Agents): 让LLM根据输入自主选择工具,完成复杂任务。
  • 回调 (Callbacks): 提供对LLM执行过程的监控和干预机制。

2.1 安装LangChain

pip install langchain
pip install openai  # 如果使用OpenAI模型

2.2 使用LLM模型

首先,我们需要配置LLM API的密钥。以OpenAI为例:

import os
os.environ["OPENAI_API_KEY"] = "YOUR_OPENAI_API_KEY"  # 替换为你的API密钥

from langchain.llms import OpenAI

llm = OpenAI(model_name="text-davinci-003", temperature=0.7)  # 初始化OpenAI模型
output = llm("What is the capital of France?")
print(output)

这里,OpenAI类封装了OpenAI的模型,model_name指定模型名称,temperature控制生成文本的随机性。

2.3 提示词模板

使用提示词模板可以更有效地控制LLM的输出。

from langchain.prompts import PromptTemplate

prompt = PromptTemplate(
    input_variables=["product"],
    template="What is a good name for a company that makes {product}?",
)

from langchain.chains import LLMChain

chain = LLMChain(llm=llm, prompt=prompt)
print(chain.run("colorful socks"))

PromptTemplate允许我们定义带有占位符的模板,然后通过run方法传入参数。LLMChain则将LLM和提示词模板组合在一起,形成一个简单的链。

2.4 链 (Chains)

LangChain的核心概念之一就是链。链可以将多个组件连接起来,形成一个工作流。例如,我们可以创建一个链,先用LLM生成文本摘要,再用另一个LLM对摘要进行翻译。

from langchain.chains import SimpleSequentialChain

# 步骤1:生成摘要
prompt1 = PromptTemplate(
    input_variables=["topic"],
    template="Write a concise summary of the following text: {topic}",
)
chain1 = LLMChain(llm=llm, prompt=prompt1)

# 步骤2:翻译成法语
prompt2 = PromptTemplate(
    input_variables=["summary"],
    template="Translate the following summary to french: {summary}",
)
chain2 = LLMChain(llm=llm, prompt=prompt2)

# 组合成一个Sequential Chain
overall_chain = SimpleSequentialChain(chains=[chain1, chain2], verbose=True) # verbose=True 可以显示中间步骤

output = overall_chain.run("The quick brown fox jumps over the lazy dog.")
print(output)

SimpleSequentialChain按顺序执行链中的每个步骤,并将上一步的输出作为下一步的输入。

2.5 记忆 (Memory)

为了让LLM记住对话历史,可以使用ConversationBufferMemory

from langchain.chains import ConversationChain
from langchain.memory import ConversationBufferMemory

memory = ConversationBufferMemory()
conversation = ConversationChain(
    llm=llm, memory=memory, verbose=True
)  # verbose=True 可以显示memory内容

print(conversation.predict(input="Hi, my name is John."))
print(conversation.predict(input="What is my name?"))

ConversationBufferMemory会将所有对话内容存储在内存中,并在每次调用LLM时传递给它。

2.6 代理 (Agents)

代理是LangChain中最强大的组件之一。它可以让LLM自主选择工具,完成复杂任务。例如,我们可以让LLM使用搜索引擎查找信息,然后根据信息回答问题。

from langchain.agents import load_tools
from langchain.agents import initialize_agent
from langchain.agents import AgentType

# 加载工具
tools = load_tools(["serpapi", "llm-math"], llm=llm) # 需要安装 serpapi: pip install serpapi

# 初始化Agent
agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)

# 运行Agent
print(agent.run("What is the capital of France? What is 2 + 2?"))

这里,load_tools加载了serpapi(搜索引擎)和llm-math(数学计算)两个工具。initialize_agent创建了一个代理,AgentType.ZERO_SHOT_REACT_DESCRIPTION指定了代理的类型,verbose=True可以显示代理的推理过程。

3. LlamaIndex:LLM的知识引擎

LlamaIndex是一个用于连接LLM和外部数据的框架。它可以帮助我们构建基于LLM的知识库问答应用。

  • 数据连接器 (Data Connectors): 从各种数据源(如文档、网站、数据库)加载数据。
  • 索引 (Index): 将数据转换为LLM可以理解的格式,并建立索引。
  • 查询引擎 (Query Engine): 根据用户的问题,从索引中检索相关信息,并传递给LLM。
  • 聊天引擎 (Chat Engine): 构建交互式对话界面,支持多轮对话。

3.1 安装LlamaIndex

pip install llama-index

3.2 数据加载

首先,我们需要从数据源加载数据。LlamaIndex支持多种数据源,例如文档、网站、数据库等。

from llama_index import SimpleDirectoryReader

documents = SimpleDirectoryReader('./data').load_data() # 从./data目录加载所有文件

SimpleDirectoryReader可以从指定目录加载所有文件。

3.3 构建索引

加载数据后,我们需要构建索引。LlamaIndex支持多种索引类型,例如VectorStoreIndexTreeIndexKeywordTableIndex等。

from llama_index import VectorStoreIndex

index = VectorStoreIndex.from_documents(documents)

VectorStoreIndex会将文档嵌入到向量空间中,方便后续的相似性搜索。

3.4 查询索引

构建索引后,我们可以使用查询引擎来检索相关信息。

query_engine = index.as_query_engine()
response = query_engine.query("What is the document about?")
print(response)

as_query_engine方法创建了一个查询引擎,query方法根据用户的问题从索引中检索相关信息,并传递给LLM生成答案。

3.5 聊天引擎

LlamaIndex还提供了聊天引擎,可以构建交互式对话界面。

from llama_index.llms import OpenAI
from llama_index import (
    VectorStoreIndex,
    SummaryIndex,
    ServiceContext,
    StorageContext,
    load_index_from_storage
)
from llama_index.chat_engine import CondenseQuestionChatEngine
import os

# 重新加载索引

PERSIST_DIR = "./storage"

# 检查是否存在持久化文件
if not os.path.exists(PERSIST_DIR):
    # 如果不存在,则创建索引并保存
    documents = SimpleDirectoryReader("./data").load_data()
    index = VectorStoreIndex.from_documents(documents)
    index.storage_context.persist(persist_dir=PERSIST_DIR)
else:
    # 如果存在,则从磁盘加载索引
    storage_context = StorageContext.from_defaults(persist_dir=PERSIST_DIR)
    index = load_index_from_storage(storage_context)

# 创建聊天引擎
chat_engine = index.as_chat_engine(chat_mode="condense_question", verbose=True)

# 开始聊天
while True:
    query = input("You: ")
    if query.lower() == "exit":
        break
    response = chat_engine.chat(query)
    print(f"Bot: {response.response}")

as_chat_engine方法创建了一个聊天引擎,chat方法根据用户的问题从索引中检索相关信息,并传递给LLM生成答案。chat_mode="condense_question" 表示使用上下文压缩模式,可以记住之前的对话内容。

4. LangChain与LlamaIndex的结合

LangChain和LlamaIndex可以很好地结合在一起,构建更强大的LLM应用。例如,我们可以使用LangChain的代理来调用LlamaIndex的查询引擎,实现更复杂的知识库问答任务。

from langchain.agents import Tool
from langchain.agents import initialize_agent
from langchain.agents import AgentType
from llama_index.tools import LlamaIndexQueryTool

# 创建LlamaIndex查询工具
query_engine = index.as_query_engine()
query_tool = LlamaIndexQueryTool(query_engine=query_engine)

# 创建LangChain工具列表
tools = [
    Tool(
        name = "LlamaIndexQueryTool",
        func=query_tool.query,
        description="Useful for answering questions about the document."
    )
]

# 初始化LangChain Agent
agent = initialize_agent(
    tools,
    llm,
    agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
    verbose=True
)

# 运行Agent
print(agent.run("What are the key concepts discussed in the document?"))

这里,我们将LlamaIndex的查询引擎封装成一个LangChain工具,然后让LangChain的代理来调用这个工具。

5. 实例:构建一个基于本地知识库的问答系统

下面我们来构建一个基于本地知识库的问答系统。假设我们有一些关于公司产品的文档,我们希望用户可以通过问答系统来了解产品信息。

步骤1:准备数据

首先,我们需要准备一些关于公司产品的文档,例如产品介绍、用户手册、常见问题解答等。将这些文档放在一个目录中,例如./data

步骤2:加载数据

from llama_index import SimpleDirectoryReader

documents = SimpleDirectoryReader('./data').load_data()

步骤3:构建索引

from llama_index import VectorStoreIndex

index = VectorStoreIndex.from_documents(documents)

步骤4:创建聊天引擎

from llama_index.llms import OpenAI
from llama_index.chat_engine import CondenseQuestionChatEngine
import os
from llama_index import (
    VectorStoreIndex,
    SummaryIndex,
    ServiceContext,
    StorageContext,
    load_index_from_storage
)

PERSIST_DIR = "./storage"

# 检查是否存在持久化文件
if not os.path.exists(PERSIST_DIR):
    # 如果不存在,则创建索引并保存
    documents = SimpleDirectoryReader("./data").load_data()
    index = VectorStoreIndex.from_documents(documents)
    index.storage_context.persist(persist_dir=PERSIST_DIR)
else:
    # 如果存在,则从磁盘加载索引
    storage_context = StorageContext.from_defaults(persist_dir=PERSIST_DIR)
    index = load_index_from_storage(storage_context)

chat_engine = index.as_chat_engine(chat_mode="condense_question", verbose=True)

步骤5:运行问答系统

while True:
    query = input("You: ")
    if query.lower() == "exit":
        break
    response = chat_engine.chat(query)
    print(f"Bot: {response.response}")

6. 高级技巧

  • RAG (Retrieval-Augmented Generation): 这是一种将检索和生成结合起来的技术。先从外部知识库中检索相关信息,然后将信息传递给LLM生成答案。LlamaIndex擅长检索,LangChain擅长生成,两者结合可以构建更强大的RAG应用。
  • 向量数据库: 可以使用向量数据库(如Chroma、Pinecone)来存储文档的向量表示,提高检索效率。
  • 评估指标: 可以使用评估指标(如准确率、召回率)来评估LLM应用的性能,并进行优化。
  • 提示词工程: 优化提示词可以显著提高LLM的输出质量。可以使用LangChain的提示词模板来管理和优化提示词。
  • 微调 (Fine-tuning): 如果有大量特定领域的数据,可以对LLM进行微调,提高其在特定领域的性能。

表格:LangChain和LlamaIndex的比较

特性 LangChain LlamaIndex
核心功能 构建LLM应用的工作流 连接LLM和外部数据
主要组件 模型、提示词、链、索引、记忆、代理、回调 数据连接器、索引、查询引擎、聊天引擎
应用场景 智能客服、任务自动化、对话式AI 知识库问答、文档理解、数据分析
优势 灵活性高、可定制性强、支持多种LLM 易于上手、专注于数据连接和索引、提供聊天引擎
适用人群 开发者、研究人员 数据科学家、企业用户

总结:回顾和展望

今天我们学习了如何使用Python,结合LangChain和LlamaIndex这两个框架,构建基于LLM的智能体应用。LangChain提供了一系列的组件,可以帮助我们轻松地构建复杂的LLM应用,而LlamaIndex则专注于连接LLM和外部数据。两者结合可以构建更强大的RAG应用。希望今天的分享能帮助大家更好地理解和应用LLM技术。

未来的LLM应用将更加智能化、个性化和自动化。我们可以期待更多创新性的应用出现,例如:

  • 自主学习的智能体: 能够从环境中学习,不断提高自身能力。
  • 多模态智能体: 能够处理图像、语音、文本等多种类型的数据。
  • 可解释的智能体: 能够解释自己的推理过程,方便用户理解和信任。

LLM技术的发展将为我们带来无限的可能性。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注