开启左侧

LangChain

[复制链接]
作者:CSDN博客
一、langchain介绍

LangChian 可以将 LLM 模型、向量数据库、交互层 Prompt、外部知识、外部工具整合到一起,进而可以自由构建 LLM 应用。
LangChain-1.png


二、langchain模块分析

1. Models

三种类型的模型:Chat Modals, Embeddings, LLMs。
聊天模型的接口是基于消息而不是原始文本。LangChain 目前支持的消息类型有 AIMessage(ai生成的)、HumanMessage(人给出的)、SystemMessage(系统的)和 ChatMessage(ChatMessage 接受一个任意的角色参数)。大多数情况下,只需要处理 HumanMessage、AIMessage 和 SystemMessage。
  1. from langchain.chat_models import ChatOpenAI
  2. # 调用了langchain的一个现成的包
  3. from langchain.schema import (
  4.     AIMessage,
  5.     HumanMessage,
  6.     SystemMessage
  7. )
  8. chat = ChatOpenAI(temperature=0)
  9. chat([HumanMessage(content="Translate this sentence from English to French. I love programming.")])
复制代码
2. Prompts(提示词)

提示词模板:
LangChain-2.png


3.Indexs(索引)

加载、转换、存储和查询数据:Document loaders、Document transformers、Text embedding models、Vector stores 以及 Retrievers。
LangChain-3.png


Document loaders(文档加载)旨在从源中加载数据构建 Document。
Document transformers(文档转换)旨在处理文档拆分、合并、过滤等。
Text embedding model(s 文本嵌入模型)旨在将非结构化文本转换为嵌入表示。
Vector Stores(向量存储)是存储和检索非结构化数据的主要方式之一。它首先将数据转化为 嵌入表示,然后存储这些生成的嵌入向量。在查询阶段,系统会利用这些嵌入向量来检索与查询内 容“最相似”的文档。向量存储的主要任务是保存这些嵌入数据并执行基于向量的搜索。
Retrievers(检索器)是一个接口,其功能是基于非结构化查询返回相应的文档。
Text Splitters(文本拆分器)
LangChain-4.png


VectorStores(向量存储器):
LangChain-5.png


4.Chains(链)

链允许我们将多个组件组合在一起以创建一个单一的、连贯的任务。
  1. from langchain import PromptTemplate, OpenAI, LLMChain
  2. prompt_template = "What is a good name for a company that makes {product}?"
  3. llm = OpenAI(temperature=0)
  4. llm_chain = LLMChain(
  5.     llm=llm,
  6.     prompt=PromptTemplate.from_template(prompt_template)
  7. )
  8. llm_chain("colorful socks")
复制代码
可运行对象Runnble
LangChain-6.png


LangChain-7.png


chain.stream/invoke/ainvoke等方法
内置方法
LangChain-8.png


前一个可运行对象的 .invoke() 调用的输出将作为输入传递给下一个可运行对象。这可以使用管道运算符 (|) 或更明确的 .pipe() 方法来完成,它们的作用相同。
生成的 RunnableSequence 本身就是一个可运行对象,这意味着它可以像其他任何可运行对象一样被调用、流式传输或进一步链接。以这种方式链接可运行对象的优点是高效的流式传输(序列将在输出可用时立即流式传输输出),以及使用 LangSmith 等工具进行调试和跟踪。
  1. import getpass
  2. import os
  3. os.environ["OPENAI_API_KEY"] = getpass.getpass()
  4. from langchain_openai import ChatOpenAI
  5. model = ChatOpenAI(model="gpt-4o-mini")
  6. from langchain_core.output_parsers import StrOutputParser
  7. from langchain_core.prompts import ChatPromptTemplate
  8. prompt = ChatPromptTemplate.from_template("tell me a joke about {topic}")
  9. chain = prompt | model | StrOutputParser()
  10. chain.invoke({"topic": "bears"})
复制代码
假设我们想要将笑话生成链与另一个评估生成的笑话是否好笑的链组合在一起。
  1. from langchain_core.output_parsers import StrOutputParser
  2. analysis_prompt = ChatPromptTemplate.from_template("is this a funny joke? {joke}")
  3. composed_chain = {"joke": chain} | analysis_prompt | model | StrOutputParser()
  4. composed_chain.invoke({"topic": "bears"})
复制代码
以下这个方法效果相同:
  1. composed_chain_with_lambda = (
  2.     chain
  3.     | (lambda input: {"joke": input})
  4.     | analysis_prompt
  5.     | model
  6.     | StrOutputParser()
  7. )
  8. composed_chain_with_lambda.invoke({"topic": "beets"})
复制代码
可运行对象并行执行
  1. from langchain_community.vectorstores import FAISS
  2. from langchain_core.output_parsers import StrOutputParser
  3. from langchain_core.prompts import ChatPromptTemplate
  4. from langchain_core.runnables import RunnablePassthrough
  5. vectorstore : FAISS.from texts(
  6. ["张三在华为工作”,“熊喜欢吃蜂蜜”],embedding=embeddings)
  7. retriever = vectorstore.as_retriever()
  8. template ="""仅根据以下上下文回答问题
  9. {context}
  10. 问题:{question}
  11. """
  12. prompt :ChatPromptTemplate.from_terplate(template)
  13. retrieval_chain =({"context": retriever,"question": RunnablePassthrough()]
  14. |prompt
  15. |model
  16. |StrOutputParser()
  17. )# retriever给context,question通过RunnablePassthrough将张三在哪工作?给它
  18. retrieval_chain.invoke("张三在哪工作?”)
复制代码
使用itemgetter
  1. from operator import itemgetter
  2. from langchain_community.vectorstores import FAISS
  3. from langchain_core.output_parsers import StrOutputParser
  4. from langchain_core.prompts import ChatPromptTemplate
  5. from langchain_core.runnables import RunnablePassthrough
  6. vectorstore : FAISS.from_texts(
  7. ["张三在华为工作”],embedding=embeddings)
  8. retriever = vectorstore.as_retriever()
  9. template ="""仅根据以下上下文回答问题
  10. {context}
  11. 问题:{question}
  12. 用以下语言回答:{language}
  13. """
  14. prompt=ChatPromptTemplate.from_terplate(template)
  15. retrieval_chain =({
  16. "context": itemgetter("question")|retriever,#context取到question给retriever再返回给context
  17. "question": itemgetter("question")|,
  18. "language": itemgetter("language)|,}
  19. |prompt
  20. |model
  21. |StrOutputParser())
  22. retrieval_chain.invoke({"question":"张三在哪工作?”,"language":"日语"})
复制代码
LangChain-9.png


LangChain-10.png


5.Memory(记忆)

ConversationBufferMemory
该组件类似我们上面的描述,只不过它会将聊天内容记录在内存中,而不需要每次再手动拼接聊天记录。
ConversationBufferWindowMemory
相比较第一个记忆组件,该组件增加了一个窗口参数,会保存最近看 k 论的聊天内容。
ConversationTokenBufferMemory
在内存中保留最近交互的缓冲区,并使用 token 长度而不是交互次数来确定何时刷新交互。
ConversationSummaryMemory
相比第一个记忆组件,该组件只会存储一个用户和机器人之间的聊天内容的摘要。
ConversationSummaryBufferMemory
结合了上面两个思路,存储一个用户和机器人之间的聊天内容的摘要并使用 token 长度来确定何时刷新交互。
VectorStoreRetrieverMemory
它是将所有之前的对话通过向量的方式存储到 VectorDB(向量数据库)中,在每一轮新的对话中,会根据用户的输入信息,匹配向量数据库中最相似的 K 组对话。
LangChain-11.png


6.Agents(代理)

在LangChain的世界里,Agent是一个智能代理,它的任务是听取你的需求(用户输入)和分析当前的情境(应用场景),然后从它的工具箱(一系列可用工具)中选择最合适的工具来执行操作。这些工具箱里装的是LangChain提供的各种积木,比如Models、Prompts、Indexes等。
如下图所示,Agent接受一个任务,使用LLM(大型语言模型)作为它的“大脑”或“思考工具”,通过这个大脑来决定为了达成目标需要执行什么操作。它就像是一个有战略眼光的指挥官,不仅知道战场上的每个小队能做什么,还能指挥它们完成更复杂的任务。
LangChain-12.png


Tool:工具
Toolkit:工具包
AgentExcutor:调度器,调度逻辑全靠它
LangChain 中的 Agent 有哪些常见类型?
比如说:
ZeroShotReAct
Structured Input ReAct
OpenAI Functions
Conversational Agent
……
解释一下名词:Zero Shot,就是指大模型推理的一种任务,这种任务给大模型一个全新的事物让它去推理,这种事物在模型的训练数据中没有出现过。也就是“零准备”推理。
ReAct 实际上是一种框架,ReAct = Reason + Act,就是推理+行动。
让Agent自己去网上搜索“北京的面积”和“纽约的面积”,然后计算出来两者的差值。
  1. """LangChainTools"""
  2. import os
  3. from langchain.agents import load_tools
  4. from langchain.agents import initialize_agent
  5. from langchain.agents import AgentType
  6. from langchain.llms import Tongyi#通义千问模型
  7. from langchain.tools import DuckDuckGoSearchRun#搜索引擎
  8. # duck duck search
  9. search = DuckDuckGoSearchRun()
  10. res = search.run("北京的面积有多大?")
  11. print(res)
  12. res = search.run("纽约的面积有多大?")
  13. print(res)
  14. os.environ["DASHSCOPE_API_KEY"] = "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  15. llm = Tongyi()
  16. tools = load_tools(["ddg-search", "llm-math"], llm=llm)#工具链条
  17. agent = initialize_agent(
  18.     tools,
  19.     llm,
  20.     agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,#Zero Shot”类型的“ReAct”代理人
  21.     verbose=True)
  22. agent.run("北京的面积和纽约的面积差是多少?")
复制代码
使用AgentExecutor
  1. import getpass
  2. import os
  3. #设置环境变量以开始langsmith记录跟踪信
  4. os.environ["LANGCHAIN_TRACING_V2"] = "true"
  5. os.environ["LANGCHAIN_API_KEY"] = getpass.getpass()
  6. #定义tool 在线搜索
  7. from langchain_community.tools.tavily_search import TavilySearchResults#在线搜索
  8. export TAVILY_API_KEY="..."
  9. search = TavilySearchResults(max_results=2)
  10. search.invoke("what is the weather in SF")
  11. #定义检索器
  12. from langchain_community.document_loaders import WebBaseLoader
  13. from langchain_community.vectorstores import FAISS
  14. from langchain_openai import OpenAIEmbeddings
  15. from langchain_text_splitters import RecursiveCharacterTextSplitter
  16. loader = WebBaseLoader("https://docs.smith.langchain.com/overview")
  17. docs = loader.load()
  18. documents = RecursiveCharacterTextSplitter(
  19.     chunk_size=1000, chunk_overlap=200
  20. ).split_documents(docs)
  21. vector = FAISS.from_documents(documents, OpenAIEmbeddings())
  22. retriever = vector.as_retriever()
  23. retriever.invoke("how to upload a dataset")[0]
  24. #将检索器转换为tool
  25. from langchain.tools.retriever import create_retriever_tool
  26. retriever_tool = create_retriever_tool(
  27.     retriever,
  28.     "langsmith_search",
  29.     "Search for information about LangSmith. For any questions about LangSmith, you must use this tool!",
  30. )
  31. #工具tools
  32. tools = [search, retriever_tool]
  33. #使用语言模型
  34. from langchain_openai import ChatOpenAI
  35. os.environ["OPENAI_API_KEY"] = getpass.getpass()
  36. model = ChatOpenAI(model="gpt-4")
  37. #用此模型进行工具调用  
  38. #还没有调用该工具 - 它只是在告诉我们要调用它。为了真正调用它,我们将需要创建我们的代理。
  39. model_with_tools = model.bind_tools(tools)
  40. response = model_with_tools.invoke([HumanMessage(content="Hi!")])
  41. print(f"ContentString: {response.content}")
  42. print(f"ToolCalls: {response.tool_calls}")
  43. #创建代理
  44. from langchain import hub
  45. # Get the prompt to use - you can modify this!
  46. prompt = hub.pull("hwchase17/openai-functions-agent")
  47. prompt.messages
  48. #使用 LLM、提示和工具来初始化代理
  49. #代理负责接收输入并决定采取哪些操作。至关重要的是,代理不执行这些操作 - 这些操作由 AgentExecutor(下一步)完成。
  50. from langchain.agents import create_tool_calling_agent
  51. agent = create_tool_calling_agent(model, tools, prompt)
  52. #将代理(大脑)与 AgentExecutor 中的工具结合起来(AgentExecutor 将反复调用代理并执行工具)。
  53. from langchain.agents import AgentExecutor
  54. agent_executor = AgentExecutor(agent=agent, tools=tools)
  55. #运行代理
  56. agent_executor.invoke({"input": "hi!"})
复制代码
为了让它有记忆,我们需要传递以前的 `chat_history`。
  1. #自动跟踪消息
  2. from langchain_community.chat_message_histories import ChatMessageHistory
  3. from langchain_core.chat_history import BaseChatMessageHistory
  4. from langchain_core.runnables.history import RunnableWithMessageHistory
  5. store = {}
  6. def get_session_history(session_id: str) -> BaseChatMessageHistory:
  7.     if session_id not in store:
  8.         store[session_id] = ChatMessageHistory()
  9.     return store[session_id]
  10. agent_with_chat_history = RunnableWithMessageHistory(
  11.     agent_executor,
  12.     get_session_history,
  13.     input_messages_key="input",
  14.     history_messages_key="chat_history",
  15. )
  16. agent_with_chat_history.invoke(
  17.     {"input": "hi! I'm bob"},
  18.     config={"configurable": {"session_id": "<foo>"}},
  19. )
  20. #{'input': "hi! I'm bob",
  21. # 'chat_history': [],
  22. #'output': 'Hello Bob! How can I assist you today?'}
  23. agent_with_chat_history.invoke(
  24.     {"input": "what's my name?"},
  25.     config={"configurable": {"session_id": "<foo>"}},
  26. )
  27. #{'input': "what's my name?",
  28. #'chat_history': [HumanMessage(content="hi! I'm bob"),
  29.   #AIMessage(content='Hello Bob! How can I assist you today?')],
  30. #'output': 'Your name is Bob.'}
复制代码
三、常用库

获取模型:
from langchain_openai import OpenAI
from langchain_community.llms import Ollama
from langchain.community.llms import HuggingFaceHub
嵌入模型:
from.langchain_community.embeddings import HuggingFaceInferenceAPIEmbeddings
from langchain_community.embeddings import OllamaEmbeddings
from langchain_openai import OpenAIEmbeddings
加载数据:
from langchain_community.document_loaders import PyPDFLoader
文档分割:
from langchain.text_splitter import RecursivecharacterTextSplitter
向量库存储:
from langchain_community.vectorstores import FAISS
向量检索:
from langchain.chains import RetrievalQA
template模板:
from langchain.prompts import PromptTemplate
from langchain.prompts.chat import SystemMessagePromptTemplate
from langchain_core.prompts import ChatPromptTemplate
LangChain-13.png


FewShotPrompt Template
LangChain-14.png


格式化输出:
from langchain_core.output_parsers import

LangChain-15.png


四、langchain实现rag的步骤

    先用本地的各种文件,利用Embeddings 模型构建一个向量数据库,做为本地的知识库。
    然后当用户对大模型提问时,先在本地的向量数据库里面查找跟问题相关的内容。这一步叫做 Retrieval 检索。
    再把从向量数据库中查找到的内容,和用户的原始问题合到一起,作为 Prompt 发给大模型。这一步叫做 Augmented 增强。
    最后,大模型会根据 prompt 返回内容。这一步叫做 Generation 生成。
切分文本的时候,chunk_size 和 chunk_overlap 取多少合适?
文本转向量时,使用哪个 Embeddings 模型最佳?
查找问题的相关上下文时,用欧式距离还是别的距离,比如余弦距离还是?
每个 Embeddings 模型,以多大的的相关度数值做为阈值合适?
如何评估 RAG 的整体效果?
五、实战

Llama 3 + LangChain + HuggingFace 实现本地部署RAG(检索增强生成)_大模型_王玉川_InfoQ写作社区
【记录】LangChain|Ollama结合LangChain使用的速通版(包含代码以及切换各种模型的方式)_ollama langchain-CSDN博客
探索Hugging Face在LangChain中的集成:从安装到进阶使用_langchain-huggingface安装-CSDN博客
【喂饭教程】大模型基于Huggingface+Langchain快速实现RAG问答系统的构建,从原理讲解到代码解读,简单易学的保姆级教程!附代码_哔哩哔哩_bilibili
GitHub - anarojoecheburua/RAG-with-Langchain-and-FastAPI: This repository contains the code for building a Retrieval-Augmented Generation (RAG) system using LangChain and FastAPI. It includes document loading, text splitting, vector embedding, and API deployment for a scalable and efficient RAG-based application.GitHub - NanGePlus/RagLangChainTest: 在本项目中模拟健康档案私有知识库构建和检索全流程,通过一份代码实现了同时支持多种大模型(如OpenAI、阿里通义千问等)的RAG(检索增强生成)功能:(1)离线步骤:文档加载->文档切分->向量化->灌入向量数据库;在线步骤:获取用户问题->用户问题向量化->检索向量数据库->将检索结果和用户问题填入prompt模版->用最终的prompt调用LLM->由LLM生成回复
全网首发GLM4+最新langchain v0.3版本+RAG详细教程—环境配置、模型本地部署、模型微调、效果展示_哔哩哔哩_bilibili
参考说明

09-Langchain最新0.2版讲解:(5)Model I_O_哔哩哔哩_bilibili
使用 AgentExecutor (Legacy) 构建代理 |
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

发布主题
阅读排行更多+

Powered by Discuz! X3.4© 2001-2013 Discuz Team.( 京ICP备17022993号-3 )