LLM大模型:通过4个任务比较LangChain和LlamaIndex

我们在本地使用大模型的时候,尤其是构建RAG应用的时候,一般会有2个成熟的框架可以使用

  • LangChain:用开发LLM的通用框架。
  • LlamaIndex:专门用于构建RAG系统的框架。

选择一个框架是对于项目的后续开发是非常重要的,因为如果后续更换框架是一个非常困难的事情,所以我们这里对这两个框架做一个简单的对比,这样对于选择会有一个初步的印象。

首先我们看看他们的Github表现和一些公开的信息:

从财务状况来看,LlamaIndex的融资规模接近LangChain,尽管他们的目标市场要小得多。这可能表明LlamaIndex的生存机会更大,因为资金比较宽裕。但是LangChain提供了更多的面向企业并且能够产生收入的产品(LangServe, LangSmith),所以可能LangChain的收入更高,这样看来LangChain会更好。。

上面是我们对企业资金方面的胡乱分析,仅供参考。下面让我们进入正题,在本文中我将使用两个框架并行完成一些基本任务。通过对比展示这些代码片段,我希望它能在你做出选择时有所帮助。

1、用本地LLM创建聊天机器人

第一个任务是制作一个聊天机器人,并且使用本地的LLM。

虽然是本地,但是我们让LLM在独立的推理服务器中运行,这样可以避免重复使用,2个框架直接使用同一服务即可。虽然LLM推理API有多种模式,但我们这里选择与OpenAI兼容的模式,这样如果切换成OpenAI的模型也不需要修改代码。

下面是LlamaIndex的方法:

代码语言:javascript

 from llama_index.llms import ChatMessage, OpenAILike  
   
 llm = OpenAILike(  
     api_base="http://localhost:1234/v1",  
     timeout=600,  # secs  
     api_key="loremIpsum",  
     is_chat_model=True,  
     context_window=32768,  
 )  
 chat_history = [  
     ChatMessage(role="system", content="You are a bartender."),  
     ChatMessage(role="user", content="What do I enjoy drinking?"),  
 ]  
 output = llm.chat(chat_history)  
 print(output)

这是LangChain:

代码语言:javascript

 from langchain.schema import HumanMessage, SystemMessage  
 from langchain_openai import ChatOpenAI  
   
 llm = ChatOpenAI(  
     openai_api_base="http://localhost:1234/v1",  
     request_timeout=600,  # secs, I guess.  
     openai_api_key="loremIpsum",  
     max_tokens=32768,  
 )  
 chat_history = [  
     SystemMessage(content="You are a bartender."),  
     HumanMessage(content="What do I enjoy drinking?"),  
 ]  
 print(llm(chat_history))

可以看到代码十分类似:

LangChain区分了聊天llm (ChatOpenAI)和llm (OpenAI),而LlamaIndex在构造函数中使用is_chat_model参数来进行区分。

LlamaIndex区分官方OpenAI端点和openaillike端点,而LangChain通过openai_api_base参数决定向何处发送请求。

LlamaIndex用role参数标记聊天消息,而LangChain使用单独的类。

2个框架基本没什么差别,我们继续

2、为本地文件构建RAG系统

我们构建一个简单的RAG系统:从本地的文本文件文件夹中读取文本。

以下是使用LlamaIndex文档的代码:

代码语言:javascript

 from llama_index import ServiceContext, SimpleDirectoryReader, VectorStoreIndex
 
 service_context = ServiceContext.from_defaults(  
     embed_model="local",  
     llm=llm, # This should be the LLM initialized in the task above.
 )  
 documents = SimpleDirectoryReader(
     input_dir="mock_notebook/",
 ).load_data()  
 index = VectorStoreIndex.from_documents(  
     documents=documents,
     service_context=service_context,
 )
 engine = index.as_query_engine(  
     service_context=service_context,  
 )
 output = engine.query("What do I like to drink?")  
 print(output)

使用LangChain,代码会变得很长:

代码语言:javascript

 from langchain_community.document_loaders import DirectoryLoader  
   
 # pip install "unstructured[md]"  
 loader = DirectoryLoader("mock_notebook/", glob="*.md")  
 docs = loader.load()  
   
 from langchain.text_splitter import RecursiveCharacterTextSplitter  
   
 text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)  
 splits = text_splitter.split_documents(docs)  
   
 from langchain_community.embeddings.fastembed import FastEmbedEmbeddings  
 from langchain_community.vectorstores import Chroma  
   
 vectorstore = Chroma.from_documents(documents=splits, embedding=FastEmbedEmbeddings())  
 retriever = vectorstore.as_retriever()  
   
 from langchain import hub  
   
 # pip install langchainhub  
 prompt = hub.pull("rlm/rag-prompt")  
   
   
 def format_docs(docs):  
     return "\n\n".join(doc.page_content for doc in docs)  
   
   
 from langchain_core.runnables import RunnablePassthrough  
   
 rag_chain = (  
     {"context": retriever | format_docs, "question": RunnablePassthrough()}  
     | prompt  
     | llm # This should be the LLM initialized in the task above.
 )  
 print(rag_chain.invoke("What do I like to drink?"))

这些代码片段清楚地说明了这两个框架的不同抽象级别。LlamaIndex用一个名为“query engines”的方法封装了RAG管道,而LangChain则需要更多的内部组件:包括用于检索文档的连接器、表示“基于X,请回答Y”的提示模板,以及他所谓的“chain”(如上面的LCEL所示)。

当使用LangChain构建时,必须确切地知道想要什么。比如调用from_documents的位置,这使得对于初学者来说是一个非常麻烦的事情,需要更多的学习曲线。

LlamaIndex可以无需显式选择矢量存储后端直接使用,而LangChain则需要显示指定这也需要更多的信息,因为我们不确定在选择数据库时是否做出了明智的决定。

虽然LangChain和LlamaIndex都提供类似于Hugging Face的云服务(即LangSmith Hub和LlamaHub),但是LangChain把它集成到了几乎所有的功能,我们使用pull只下载一个简短的文本模板,内容如下:

You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don’t know the answer, just say that you don’t know. Use three sentences maximum and keep the answer concise.Question: {question}Context: {context}Answer:**

这绝对是一种过度的做法。虽然这确实鼓励在社区中分享提示,但是这有必要吗。

3、支持RAG的聊天机器人

我们将上面两个简单的功能整合起来,这样我们可以获得一个可以和本地文件对话的真正的可用的简单应用。

使用LlamaIndex,就像将as_query_engine与as_chat_engine交换一样简单:

代码语言:javascript

 engine = index.as_chat_engine()
 output = engine.chat("What do I like to drink?")  
 print(output) # "You enjoy drinking coffee."
 output = engine.chat("How do I brew it?")  
 print(output) # "You brew coffee with a Aeropress."

使用LangChain时,按照官方教程,让我们首先定义memory(负责管理聊天记录):

代码语言:javascript

 # Everything above this line is the same as that of the last task.
 from langchain_core.runnables import RunnablePassthrough, RunnableLambda  
 from langchain_core.messages import get_buffer_string  
 from langchain_core.output_parsers import StrOutputParser  
 from operator import itemgetter  
 from langchain.memory import ConversationBufferMemory  
 from langchain.prompts.prompt import PromptTemplate  
 from langchain.schema import format_document  
 from langchain_core.prompts import ChatPromptTemplate  
   
 memory = ConversationBufferMemory(  
     return_messages=True, output_key="answer", input_key="question"  
 )

在LLM开始时,我们需要从memory中加载聊天历史记录。

代码语言:javascript

 load_history_from_memory = RunnableLambda(memory.load_memory_variables) | itemgetter(  
     "history"  
 )  
 load_history_from_memory_and_carry_along = RunnablePassthrough.assign(  
     chat_history=load_history_from_memory  
 )

然后要求LLM用上下文来丰富我们的提问

代码语言:javascript

 rephrase_the_question = (  
     {  
         "question": itemgetter("question"),  
         "chat_history": lambda x: get_buffer_string(x["chat_history"]),  
     }  
     | PromptTemplate.from_template(  
         """You're a personal assistant to the user.  
 Here's your conversation with the user so far:  
 {chat_history}  
 Now the user asked: {question}  
 To answer this question, you need to look up from their notes about """  
     )  
     | llm  
     | StrOutputParser()  
 )

但是我们不能只是将两者连接起来,因为话题可能在谈话过程中发生了变化,这使得聊天记录中的大多数语义信息无关紧要。

然后就是运行RAG。

代码语言:javascript

 retrieve_documents = {  
     "docs": itemgetter("standalone_question") | retriever,  
     "question": itemgetter("standalone_question"),  
 }

对提问进行回答:

代码语言:javascript

 rephrase_the_question = (  
     {  
         "question": itemgetter("question"),  
         "chat_history": lambda x: get_buffer_string(x["chat_history"]),  
     }  
     | PromptTemplate.from_template(  
         """You're a personal assistant to the user.  
 Here's your conversation with the user so far:  
 {chat_history}  
 Now the user asked: {question}  
 To answer this question, you need to look up from their notes about """  
     )  
     | llm  
     | StrOutputParser()  
 )

得到最终响应后将其附加到聊天历史记录。

代码语言:javascript

 final_chain = (  
     load_history_from_memory_and_carry_along  
     | {"standalone_question": rephrase_the_question}  
     | retrieve_documents  
     | compose_the_final_answer  
 )  
 # Demo.
 inputs = {"question": "What do I like to drink?"}  
 output = final_chain.invoke(inputs)  
 memory.save_context(inputs, {"answer": output.content})  
 print(output) # "You enjoy drinking coffee."
 inputs = {"question": "How do I brew it?"}  
 output = final_chain.invoke(inputs)  
 memory.save_context(inputs, {"answer": output.content})  
 print(output) # "You brew coffee with a Aeropress."

这是一个非常复杂的过程,我们通过这个过程可以了解了很多关于llm驱动的应用程是如何构建的。特别是调用了LLM几次,让它假设不同的角色:查询生成器、总结检索到的文档的人,对话的参与者。这对于学习来说是非常有帮助的,但是对于应用是不是有些复杂了。

4、Agent

RAG管道可以被认为是一个工具。而LLM可以访问多个工具,比如给它提供搜索、百科查询、天气预报等。通过这种方式聊天机器人可以回答关于它直接知识之外的问题。

工具也不一定要提供信息,还可以进行其他操作,例如下购物订单,回复电子邮件等。

LLM有了这些工具,就需要决定使用哪些工具,以及以什么顺序使用。而使用这些工具LLM角色被称为“代理”。

有多种方式可以为LLM提供代理。最具模型泛型的方法是ReAct范式。

在LlamaIndex中使用方法如下

代码语言:javascript

 from llama_index.tools import ToolMetadata  
 from llama_index.tools.query_engine import QueryEngineTool  
   
 notes_query_engine_tool = QueryEngineTool(  
     query_engine=notes_query_engine,  
     metadata=ToolMetadata(  
         name="look_up_notes",  
         description="Gives information about the user.",  
     ),  
 )  
 from llama_index.agent import ReActAgent  
   
 agent = ReActAgent.from_tools(  
     tools=[notes_query_engine_tool],  
     llm=llm,  
     service_context=service_context,  
 )  
 output = agent.chat("What do I like to drink?")  
 print(output) # "You enjoy drinking coffee."
 output = agent.chat("How do I brew it?")  
 print(output) # "You can use a drip coffee maker, French press, pour-over, or espresso machine."

对于我们的后续问题“how do I brew coffee”,代理的回答与它仅仅是一个查询引擎时不同。这是因为代理可以自己决定是否查看我们本地笔记。如果他们有足够的信心来回答这个问题,代理可能会选择不使用任何工具。如果LLM发现他无法回答这个问题,则会使用RAG搜索我们本地的文件(我们的查询引擎的其职责是从索引中查找文档,所以他肯定会选择这个)。

代理是LangChain高级API:

代码语言:javascript

 from langchain.agents import AgentExecutor, Tool, create_react_agent  
   
 tools = [  
     Tool(  
         name="look_up_notes",  
         func=rag_chain.invoke,  
         description="Gives information about the user.",  
     ),
 ]
 react_prompt = hub.pull("hwchase17/react-chat")  
 agent = create_react_agent(llm, tools, react_prompt)  
 agent_executor = AgentExecutor.from_agent_and_tools(agent=agent, tools=tools)  
   
 result = agent_executor.invoke(  
     {"input": "What do I like to drink?", "chat_history": ""}  
 )  
 print(result) # "You enjoy drinking coffee."
 result = agent_executor.invoke(  
     {  
         "input": "How do I brew it?",  
         "chat_history": "Human: What do I like to drink?\nAI: You enjoy drinking coffee.",  
     }
 )
 print(result) # "You can use a drip coffee maker, French press, pour-over, or espresso machine."

尽管我们仍然需要手动管理聊天记录,但与创建RAG相比,创建代理要容易得多。create_react_agent和AgentExecutor整合了底层的大部分工作。

总结

LlamaIndex和LangChain是构建LLM应用程序的两个框架。LlamaIndex专注于RAG用例,LangChain得到了更广泛的应用。我们可以看到,如果是和RAG相关的用例,LlamaIndex会方便很多,可以说是首选。

但是如果你的应用需要一些非RAG的功能,可能LangChain是一个更好的选择。

如何系统的去学习AI大模型LLM ?

作为一名热心肠的互联网老兵,我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。

但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的 AI大模型资料 包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来

所有资料 ⚡️ ,朋友们如果有需要全套 《LLM大模型入门+进阶学习资源包》,扫码获取~

👉CSDN大礼包🎁:全网最全《LLM大模型入门+进阶学习资源包》免费分享(安全链接,放心点击)👈

一、全套AGI大模型学习路线

AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

img

二、640套AI大模型报告合集

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

img

三、AI大模型经典PDF籍

随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。

img

在这里插入图片描述

四、AI大模型商业化落地方案

img

阶段1:AI大模型时代的基础理解

  • 目标:了解AI大模型的基本概念、发展历程和核心原理。
  • 内容
    • L1.1 人工智能简述与大模型起源
    • L1.2 大模型与通用人工智能
    • L1.3 GPT模型的发展历程
    • L1.4 模型工程
      - L1.4.1 知识大模型
      - L1.4.2 生产大模型
      - L1.4.3 模型工程方法论
      - L1.4.4 模型工程实践
    • L1.5 GPT应用案例

阶段2:AI大模型API应用开发工程

  • 目标:掌握AI大模型API的使用和开发,以及相关的编程技能。
  • 内容
    • L2.1 API接口
      - L2.1.1 OpenAI API接口
      - L2.1.2 Python接口接入
      - L2.1.3 BOT工具类框架
      - L2.1.4 代码示例
    • L2.2 Prompt框架
      - L2.2.1 什么是Prompt
      - L2.2.2 Prompt框架应用现状
      - L2.2.3 基于GPTAS的Prompt框架
      - L2.2.4 Prompt框架与Thought
      - L2.2.5 Prompt框架与提示词
    • L2.3 流水线工程
      - L2.3.1 流水线工程的概念
      - L2.3.2 流水线工程的优点
      - L2.3.3 流水线工程的应用
    • L2.4 总结与展望

阶段3:AI大模型应用架构实践

  • 目标:深入理解AI大模型的应用架构,并能够进行私有化部署。
  • 内容
    • L3.1 Agent模型框架
      - L3.1.1 Agent模型框架的设计理念
      - L3.1.2 Agent模型框架的核心组件
      - L3.1.3 Agent模型框架的实现细节
    • L3.2 MetaGPT
      - L3.2.1 MetaGPT的基本概念
      - L3.2.2 MetaGPT的工作原理
      - L3.2.3 MetaGPT的应用场景
    • L3.3 ChatGLM
      - L3.3.1 ChatGLM的特点
      - L3.3.2 ChatGLM的开发环境
      - L3.3.3 ChatGLM的使用示例
    • L3.4 LLAMA
      - L3.4.1 LLAMA的特点
      - L3.4.2 LLAMA的开发环境
      - L3.4.3 LLAMA的使用示例
    • L3.5 其他大模型介绍

阶段4:AI大模型私有化部署

  • 目标:掌握多种AI大模型的私有化部署,包括多模态和特定领域模型。
  • 内容
    • L4.1 模型私有化部署概述
    • L4.2 模型私有化部署的关键技术
    • L4.3 模型私有化部署的实施步骤
    • L4.4 模型私有化部署的应用场景

学习计划:

  • 阶段1:1-2个月,建立AI大模型的基础知识体系。
  • 阶段2:2-3个月,专注于API应用开发能力的提升。
  • 阶段3:3-4个月,深入实践AI大模型的应用架构和私有化部署。
  • 阶段4:4-5个月,专注于高级模型的应用和部署。
这份完整版的所有 ⚡️ 大模型 LLM 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

全套 《LLM大模型入门+进阶学习资源包↓↓↓ 获取~

👉CSDN大礼包🎁:全网最全《LLM大模型入门+进阶学习资源包》免费分享(安全链接,放心点击)👈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值