内部门户网站建设方案,如何设立外贸网站,龙岩网站建设龙岩网站制作,模板之家中文版在Why RAG is big中#xff0c;我表示支持检索增强生成#xff08;RAG#xff09;作为私有、离线、去中心化 LLM 应用程序的关键技术。 当你建造一些东西供自己使用时#xff0c;你就是在孤军奋战。 你可以从头开始构建#xff0c;但在现有框架上构建会更有效。 NSDT工具推…在Why RAG is big中我表示支持检索增强生成RAG作为私有、离线、去中心化 LLM 应用程序的关键技术。 当你建造一些东西供自己使用时你就是在孤军奋战。 你可以从头开始构建但在现有框架上构建会更有效。 NSDT工具推荐 Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - Three.js虚拟轴心开发包 AFAIK存在两种选择针对不同的范围
LangChain一个使用LLM开发东西的通用框架。LlamaIndex一个专门用于构建 RAG 系统的框架。
选择一个框架是一项巨大的投资。 你想要一个拥有强大维护者和充满活力的社区的产品。 幸运的是这两种选择在去年都已合并因此规模是相当可量化的。 以下是这些数字的比较 从财务数据来看LlamaIndex 表现强劲融资金额接近LangChain但其目标市场要小得多以 GitHub 星数作为社区兴趣的近似值。 这可能表明 LlamaIndex 有更好的生存机会。 话虽这么说LangChain提供了更多面向企业的、可以产生收入的产品LangServe、LangSmith……所以这个论点可能会颠倒过来。 从货币角度来看这是一个艰难的决定。
我的财务 101只能带我到此为止。 让我们谈谈我真正擅长的领域并用 Python 进行讨论。 在本文中我将使用这两个框架并行完成一些基本任务。 通过并排呈现代码片段我希望它可以帮助你做出更明智的决定决定在你自己的 RAG 聊天机器人中使用哪些代码片段。
1、用本地LLM创建聊天机器人
对于要实现的第一个任务我选择制作一个仅限本地的聊天机器人。 这是因为我不想在学习使用这些框架时为模拟聊天消息支付云服务费用。
我选择让 LLM 在独立的推理服务器中运行而不是让框架在每次运行脚本时将数 GB 模型加载到内存中。 这样可以节省时间并避免磁盘磨损。
虽然 LLM 推理有多种 API 模式但我选择了一种与 OpenAI 兼容的模式因此如果你愿意的话它与官方 OpenAI 端点最相似。
这是使用 LlamaIndex 的方法
from llama_index.llms import ChatMessage, OpenAILike llm OpenAILike( api_basehttp://localhost:1234/v1, timeout600, # secs api_keyloremIpsum, is_chat_modelTrue, context_window32768,
)
chat_history [ ChatMessage(rolesystem, contentYou are a bartender.), ChatMessage(roleuser, contentWhat do I enjoy drinking?),
]
output llm.chat(chat_history)
print(output)
下面是LangChain
from langchain.schema import HumanMessage, SystemMessage
from langchain_openai import ChatOpenAI llm ChatOpenAI( openai_api_basehttp://localhost:1234/v1, request_timeout600, # secs, I guess. openai_api_keyloremIpsum, max_tokens32768,
)
chat_history [ SystemMessage(contentYou are a bartender.), HumanMessage(contentWhat do I enjoy drinking?),
]
print(llm(chat_history))
对于这两种情况API 密钥可以是任意的但必须存在。 我猜想这是在两个框架中运行的 OpenAI SDK 的要求。
LangChain 区分可聊天的 LLM (ChatOpenAI) 和仅完成的 LLM (OpenAI)而 LlamaIndex 通过构造函数中的 is_chat_model 参数控制它。LlamaIndex 区分官方 OpenAI 端点和 OpenAILike 端点而 LangChain 通过 openai_api_base 参数确定将请求发送到哪里。LlamaIndex 使用角色参数标记聊天消息而 LangChain 使用单独的类。
到目前为止这两个框架的情况看起来并没有太大不同。 让我们继续吧。
2、为本地文件构建RAG系统
有了LLM的联系我们就可以开始做生意了。 现在让我们构建一个简单的 RAG 系统该系统从本地文件夹中的文本文件中读取数据。 以下是如何使用 LlamaIndex 实现这一目标主要取自本文档
from llama_index import ServiceContext, SimpleDirectoryReader, VectorStoreIndexservice_context ServiceContext.from_defaults( embed_modellocal, llmllm, # This should be the LLM initialized in the task above.
)
documents SimpleDirectoryReader(input_dirmock_notebook/,
).load_data()
index VectorStoreIndex.from_documents( documentsdocuments,service_contextservice_context,
)
engine index.as_query_engine( service_contextservice_context,
)
output engine.query(What do I like to drink?)
print(output)
使用 LangChain代码量会增加一倍但仍然是可以管理的
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_size1000, chunk_overlap200)
splits text_splitter.split_documents(docs) from langchain_community.embeddings.fastembed import FastEmbedEmbeddings
from langchain_community.vectorstores import Chroma vectorstore Chroma.from_documents(documentssplits, embeddingFastEmbedEmbeddings())
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 使用一个名为“查询引擎”的便捷包包装 RAG 管道而 LangChain 则向您展示内部组件。 它们包括检索文档的串联器、“基于 X 请回答 Y”的提示模板以及链本身如上面的 LCEL 所示。
这种抽象的缺乏对学习者有影响当使用 LangChain 进行构建时你必须在第一次尝试时准确地知道你想要什么。 例如比较 from_documents 的调用位置。 LlamaIndex 允许您在不显式选择存储后端的情况下使用向量存储索引而 LangChain 似乎建议您立即选择一个实现。 每个人在使用 LangChain 从文档创建向量索引时似乎都明确选择了后端。在遇到可扩展性问题之前我不确定在选择数据库时是否做出了明智的决定。
更有趣的是虽然LangChain和LlamaIndex都提供类似Hugging Face Hub的云服务即LangSmith Hub和LlamaHub但拨到11的是LangChain。注意LangChain的hub.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: 虽然这确实鼓励与社区分享雄辩的提示但我觉得这是一种矫枉过正。 存储约 1kB 的文本并不能真正证明拉取所涉及的网络调用是合理的。 我希望下载的工件被缓存。
3、将两者结合起来支持 RAG 的聊天机器人
到目前为止我们一直在构建不太智能的东西。 在第一个任务中我们构建了一个可以保持对话但不太了解你的东西 第二个我们构建了一些了解您但不保留聊天记录的东西。 让我们将这两者结合起来。
使用 LlamaIndex就像将 as_query_engine 与 as_chat_engine 交换一样简单
# Everything from above, till and including the creation of the index.
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我们需要把很多事情说清楚。 按照官方教程我们先来定义一下内存
# 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_messagesTrue, output_keyanswer, input_keyquestion
)
计划如下
1、在LLM开始时我们从内存中加载聊天记录。
load_history_from_memory RunnableLambda(memory.load_memory_variables) | itemgetter( history
)
load_history_from_memory_and_carry_along RunnablePassthrough.assign( chat_historyload_history_from_memory
)
2、我们要求LLM用上下文来丰富问题“考虑到聊天记录我应该在笔记中寻找什么来回答这个问题”
rephrase_the_question ( { question: itemgetter(question), chat_history: lambda x: get_buffer_string(x[chat_history]), } | PromptTemplate.from_template( Youre a personal assistant to the user.
Heres 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()
)
我们不能只是将两者连接起来因为话题可能在对话过程中发生了变化使得聊天日志中的大多数语义信息变得无关紧要。
3、我们运行 RAG 管道。 请注意我们如何通过暗示“我们作为用户将自己查找注释”来欺骗LLM但实际上我们现在要求LLM承担繁重的工作。 我心情不好。
retrieve_documents { docs: itemgetter(standalone_question) | retriever, question: itemgetter(standalone_question),
}
4、我们问LLM“以检索到的文档作为参考以及可选的迄今为止的对话您对用户最新问题的回应是什么”
def _combine_documents(docs): prompt PromptTemplate.from_template(template{page_content}) doc_strings [format_document(doc, prompt) for doc in docs] return \n\n.join(doc_strings)
compose_the_final_answer ( { context: lambda x: _combine_documents(x[docs]), question: itemgetter(question), } | ChatPromptTemplate.from_template( Youre a personal assistant.
With the context below:
{context}
To the question {question}, you answer: ) | llm
)
5、我们将最终回复附加到聊天记录中。
# Putting all 4 stages together...
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让它呈现不同的角色查询生成器、总结检索到的文档的人最后是我们对话的参与者。 我也希望您现在已经充分熟悉 LCEL。
4、升级为智能代理
如果将与你交谈的 LLM 角色视为一个人那么 RAG 管道可以被视为该人使用的工具。 一个人可以使用多种工具LLM也可以。 你可以给它提供搜索谷歌、查找维基百科、检查天气预报等的工具。通过这种方式你的聊天机器人可以回答有关其直接知识之外的问题。
它不一定是信息工具。 通过为我们的LLM提供搜索网络、下购物订单、回复电子邮件等工具您可以使其能够影响现实并改变世界。
工具很多需要决定使用哪些工具以及使用顺序。 这种能力被称为Agent或智能体。 因此具有代理权的LLM的角色被称为“代理”。
有多种方法可以为 LLM 申请提供代理权。 最模型通用因此对自托管友好的方式可能是 ReAct 范例我在上一篇文章中对此进行了更多介绍。
在 LlamaIndex 中做到这一点代码如下
# Everything above this line is the same as in the above two tasks,
# till and including where notes_query_engine is defined.
# Lets convert the query engine into a tool.
from llama_index.tools import ToolMetadata
from llama_index.tools.query_engine import QueryEngineTool notes_query_engine_tool QueryEngineTool( query_enginenotes_query_engine, metadataToolMetadata( namelook_up_notes, descriptionGives information about the user., ),
)
from llama_index.agent import ReActAgent agent ReActAgent.from_tools( tools[notes_query_engine_tool], llmllm, service_contextservice_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.
请注意对于我们的后续问题“如何煮咖啡”代理的回答与仅作为查询引擎时的回答不同。 这是因为代理可以自行决定是否从我们的笔记中查找。 如果他们有足够的信心回答问题代理可能会选择根本不使用任何工具。 我们的“我如何……”的问题可以有两种解释要么是关于通用选项要么是关于事实回忆。 显然代理选择以前一种方式理解它而我们的查询引擎负责从索引中查找文档必须选择后者。
有趣的是代理是 LangChain 决定提供高级抽象的一个用例
# Everything above is the same as in the 2nd task, till and including where we defined rag_chain.
# Lets convert the chain into a tool.
from langchain.agents import AgentExecutor, Tool, create_react_agent tools [ Tool( namelook_up_notes, funcrag_chain.invoke, descriptionGives 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(agentagent, toolstools) 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 涵盖了底层的大部分接线工作。
5、结束语
LlamaIndex 和 LangChain 是构建 LLM 应用程序的两个框架。 虽然 LlamaIndex 专注于 RAG 用例但 LangChain 似乎被更广泛地采用。 但它们在实践中有何不同 在这篇文章中我比较了这两个框架完成四个常见任务的情况
连接到本地 LLM 实例并构建聊天机器人。索引本地文件并构建 RAG 系统。将以上两者结合起来制作一个具有 RAG 功能的聊天机器人。将聊天机器人转变为代理使其可以使用更多的工具并进行简单的推理。
我希望它们能帮助你为 LLM 申请做出明智的选择。 另外祝你在构建自己的聊天机器人的过程中一切顺利 原文链接LangChain vs. LlamaIndex - BimAnt