Langchain--如何使用大模型 2.0

2024-08-05 08:42:51 浏览数 (2)

Langchain使用大模型

我们除了可以使用Langchain进行模型对话、提示词创作、嵌入模型,还可以使用其他的组件对大模型封装使用,打造我们自己的大模型。

Agents

首先,我们来谈谈Agents。在Langchain,Agents是执行特定任务或功能的智能实体。它们可以被看作是自动化的小助手,能够根据预设的规则和逻辑,在Langchain生态系统中自主地执行操作。比如,有的Agent负责监控区块链上的交易活动,有的则负责处理语言任务,如文本生成、翻译或情感分析等。这些Agent的存在,极大地提高了Langchain系统的自动化程度和效率。

AI大模型虽然很强大,但是还有一些局限性,比如:

  • 数据不及时:ChatGPT数据更新到2022年底,也就是说今年的新闻它是不知道的。
  • 处理复杂任务:大模型虽然在问答方面很出色,但是不能直接处理复杂任务。
  • 大模型的核心能力是理解意图和文本生成。

我们在使用Langchain的时候,可以通过pycharm的某个函数,Ctrl b 查看提供的参数,也可以去Langchain官网查看提供的各种API,如我们之前使用的baiduqianfan:

可以看到LLMs是我们的LLMs模块,BaiduQianfan是其中的库。

其中:ERNIE-Bot-turbo是默认的模型(文心一言 ),也可以使用其他的模型,比如:Qianfan-Chinese-Llama-2-7B,是通过Llama微调的中文大模型。

我们先假设,想要查询山东省2023年高考人数有多少,我们可以使用多个代理工具,让Agents选择执行。

代码语言:javascript复制
pip install duckduckgo-search
  • 集成DuckDuckGo搜索引擎的功能,可以去浏览器搜索并集成信息。
代码语言:javascript复制
import os
from langchain_community.chat_models import QianfanChatEndpoint
from langchain.agents import load_tools
from langchain.agents import initialize_agent
from langchain.agents import AgentType

os.environ['QIANFAN_AK'] = "******"
os.environ['QIANFAN_SK'] = "******"

llm = QianfanChatEndpoint(model='Chinese-Llama-2-7B')

tools = load_tools(["ddg-search", "llm-math"], llm=llm)

agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)
# verbose=True参数是在执行任务时打印更多的调试信息。
print('agent', agent)

from langchain import PromptTemplate
prompt_template = "山东省2023年高考人数是多少"
prompt = PromptTemplate.from_template(prompt_template)
# 创建了一个提示模板,并将其转换为PromptTemplate对象。
print('prompt-->', prompt)


agent.run(prompt)

输出:

代码语言:javascript复制
agent verbose=True tags=['zero-shot-react-description'] agent=ZeroShotAgent(llm_chain=LLMChain(prompt=PromptTemplate(input_variables=['agent_scratchpad', 'input'], template='Answer the following questions as best you can. You have access to the following tools:nnduckduckgo_search - A wrapper around DuckDuckGo Search. Useful for when you need to answer questions about current events. Input should be a search query.nCalculator(*args: Any, callbacks: Union[List[langchain_core.callbacks.base.BaseCallbackHandler], langchain_core.callbacks.base.BaseCallbackManager, NoneType] = None, tags: Optional[List[str]] = None, metadata: Optional[Dict[str, Any]] = None, **kwargs: Any) -> Any - Useful for when you need to answer questions about math.nnUse the following format:nnQuestion: the input question you must answernThought: you should always think about what to donAction: the action to take, should be one of [duckduckgo_search, Calculator]nAction Input: the input to the actionnObservation: the result of the actionn... (this Thought/Action/Action Input/Observation can repeat N times)nThought: I now know the final answernFinal Answer: the final answer to the original input questionnnBegin!nnQuestion: {input}nThought:{agent_scratchpad}'), llm=QianfanChatEndpoint(client=<qianfan.resources.llm.chat_completion.ChatCompletion object at 0x0000019B86B203D0>, qianfan_ak=SecretStr('**********'), qianfan_sk=SecretStr('**********'))), output_parser=MRKLOutputParser(), allowed_tools=['duckduckgo_search', 'Calculator']) tools=[DuckDuckGoSearchRun(), Tool(name='Calculator', description='Useful for when you need to answer questions about math.', func=<bound method Chain.run of LLMMathChain(llm_chain=LLMChain(prompt=PromptTemplate(input_variables=['question'], template='Translate a math problem into a expression that can be executed using Python's numexpr library. Use the output of running this code to answer the question.nnQuestion: ${{Question with math problem.}}n```textn${{single line mathematical expression that solves the problem}}n```n...numexpr.evaluate(text)...n```outputn${{Output of running the code}}n```nAnswer: ${{Answer}}nnBegin.nnQuestion: What is 37593 * 67?n```textn37593 * 67n```n...numexpr.evaluate("37593 * 67")...n```outputn2518731n```nAnswer: 2518731nnQuestion: 37593^(1/5)n```textn37593**(1/5)n```n...numexpr.evaluate("37593**(1/5)")...n```outputn8.222831614237718n```nAnswer: 8.222831614237718nnQuestion: {question}n'), llm=QianfanChatEndpoint(client=<qianfan.resources.llm.chat_completion.ChatCompletion object at 0x0000019B86B203D0>, qianfan_ak=SecretStr('**********'), qianfan_sk=SecretStr('**********'))))>, coroutine=<bound method Chain.arun of LLMMathChain(llm_chain=LLMChain(prompt=PromptTemplate(input_variables=['question'], template='Translate a math problem into a expression that can be executed using Python's numexpr library. Use the output of running this code to answer the question.nnQuestion: ${{Question with math problem.}}n```textn${{single line mathematical expression that solves the problem}}n```n...numexpr.evaluate(text)...n```outputn${{Output of running the code}}n```nAnswer: ${{Answer}}nnBegin.nnQuestion: What is 37593 * 67?n```textn37593 * 67n```n...numexpr.evaluate("37593 * 67")...n```outputn2518731n```nAnswer: 2518731nnQuestion: 37593^(1/5)n```textn37593**(1/5)n```n...numexpr.evaluate("37593**(1/5)")...n```outputn8.222831614237718n```nAnswer: 8.222831614237718nnQuestion: {question}n'), llm=QianfanChatEndpoint(client=<qianfan.resources.llm.chat_completion.ChatCompletion object at 0x0000019B86B203D0>, qianfan_ak=SecretStr('**********'), qianfan_sk=SecretStr('**********'))))>)]
prompt--> input_variables=[] template='山东省2023年高考人数是多少'


> Entering new AgentExecutor chain...
[INFO][2024-07-29 21:08:22.357] oauth.py:228 [t:18880]: trying to refresh access_token for ak `CNzMCb***`
[INFO][2024-07-29 21:08:24.915] oauth.py:243 [t:18880]: sucessfully refresh access_token
Thought: 这个问题的关键是需要查找“山东省2023年高考人数”。

Action: duckduckgo_search
Action Input: 查询输入为“山东省2023年高考人数”
Observation: 一、山东高考考生人数2023. 山东是我国的教育大省 ,高考人数位列前茅, 2023年山东省高考报名考生98万人,其中春季高考26万人, 春季高考 一般在山东等地会举行春季高考。 夏季高考72万人, 这是全国绝大多数地区所举行的高考形式。 参加夏季高考统一考试考生67万人,比2022年增加7万人。 今天就给大家整理了2023年山东高考6选3选科数据分析,希望能帮助广大考生和家长们理清选科思路~. 2023山东高考概况梳理. 2023山东高考考生人数及升学基本情况. 据统计, 2023年全省考生人数共计达97.76万 ,其中夏季编场人数为66.86万(较2022年增长6.98万人 ... 原创 2023年山东高考录取数据出炉,录取率86.96%,滑档生9月下旬还有注册入学机会. 2023年山东高考录取数据出炉,录取率86.96%,滑档生9月下旬还有注册入学机会. 录取总人数比去年增加46967人。. 这说明尚有6402人未达到150分 (含缺考)。. 这样,2023年本科录取率 ... 今天(8月4日)上午9:00,山东省教育厅举行2023年普通高考第三次新闻发布会,邀请山东省教育招生考试院普招处处长赵丽,通报2023年山东省普通 ... 山东高考2023年情况汇总. 夏季高考分普通类、艺术类、体育类三类,按类别分批次录取;春季高考分30个专业类别及技能拔尖人才类型,分批次录取。. (一)强基计划. 2020年首次实施强基计划招生。. 考生在提前批之前由招生高校完成录取,不需要填报高考志愿 ...
Thought:我们现在已经知道了山东省2023年的高考人数为98万人。
Final Answer:山东省2023年高考人数为98万人。

> Finished chain.
Memory

LangChain的Memory模块是一个关键的组成部分,它专门用于存储和管理对话上下文信息,大模型本身不具备上下文的概念,它并不保存上次交互的内容,它之所以能够和人正常沟通对话,因为它进行了一层封装,将历史记录回传给了模型。

通过存储对话历史,Memory模块帮助模型更好地理解用户的意图,从而生成更加准确的响应。

代码语言:javascript复制
from langchain_community.chat_message_histories import ChatMessageHistory

history = ChatMessageHistory()
history.add_user_message("你好")
history.add_ai_message("怎么了?")
print(history.messages)

输出:

代码语言:javascript复制
[HumanMessage(content='你好'), AIMessage(content='怎么了?')]

或使用ConversationChain:支持对话记忆功能。

代码语言:javascript复制
from langchain import ConversationChain
llm = QianfanChatEndpoint()
conversation = ConversationChain(llm=llm)
resut1 = conversation.predict(input="小明有一辆自行车")
print(resut1)
print('*'*80)
resut2 = conversation.predict(input="小红有一辆山地车")
print(resut2)
print('*'*80)
resut3 = conversation.predict(input="小明和小红一共有几辆车?")
print(resut3)

输出:

代码语言:javascript复制
小明的确有一辆自行车。那么您想要询问什么相关信息呢?我了解到了您可以继续提问。
********************************************************************************
是的,小红有一辆山地车。您想要了解关于小红的山地车的什么信息呢?请告诉我,我会尽力帮助您。
********************************************************************************
根据您提供的信息,小明有一辆自行车,小红有一辆山地车。因此,小明和小红一共有两辆车。请问您需要我帮助您做些什么呢?

可以看到加入ConversationChain后,模型可以记忆之前的聊天了。

如果想要像文心一言一样,长期保存历史消息,,可以使用messages_to_dict 方法:

代码语言:javascript复制
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain.schema import messages_from_dict, messages_to_dict

history = ChatMessageHistory()
history.add_user_message("hello!")
history.add_ai_message("whats up?")

dicts = messages_to_dict(history.messages)

print(dicts)

now_messages = messages_from_dict(dicts)

print(now_messages)

输出:

代码语言:javascript复制
[{'type': 'human', 'data': {'content': 'hello!', 'additional_kwargs': {}, 'response_metadata': {}, 'type': 'human', 'name': None, 'id': None, 'example': False}}, {'type': 'ai', 'data': {'content': 'whats up?', 'additional_kwargs': {}, 'response_metadata': {}, 'type': 'ai', 'name': None, 'id': None, 'example': False, 'tool_calls': [], 'invalid_tool_calls': [], 'usage_metadata': None}}]
[HumanMessage(content='hello!'), AIMessage(content='whats up?')]
Indexes

Indexes组件的目的是让LangChain具备处理文档处理的能力,这些能力包括但不限于文档的加载、转换、存储、检索等。

文档加载器(Document Loaders)

  • 功能:文档加载器是LangChain处理文档的第一步,负责从各种来源加载文档。

文档转换器(Document Converters)

  • 功能:文档转换器在检索过程中发挥着关键作用,它负责将大型文档分割成较小的块,以便更高效地获取文档的相关部分。

向量存储(Vector Stores)

  • 功能:随着嵌入向量的广泛应用,对支持这些向量的数据库的需求也日益增长。

检索器(Retrievers)

  • 功能:检索器是LangChain索引中的核心组件之一,负责根据用户输入检索相关数据。

文档加载器主要基于Unstructured 包,Unstructured 是一个python包,可以把各种类型的文件转换成文本。

代码语言:javascript复制
from langchain_community.document_loaders import UnstructuredFileLoader
loader = UnstructuredFileLoader('a.txt', encoding='utf-8')
docs = loader.load()

first_01 = docs[0].page_content[:4]
print(first_01)
print('*'*80)
from langchain_community.document_loaders import TextLoader
loader = TextLoader('a.txt', encoding='utf-8')
docs = loader.load()
print(docs)
print(len(docs))
first_01 = docs[0].page_content[:4]
print(first_01)

LangChain支持的文档加载器 :

文档加载器

描述

CSV

CSV问价

JSON Files

加载JSON文件

Jupyter Notebook

加载notebook文件

Markdown

加载markdown文件

Microsoft PowerPoint

加载ppt文件

PDF

加载pdf文件

Images

加载图片

File Directory

加载目录下所有文件

HTML

网页

文档分割器

由于模型对输入的字符长度有限制,我们在碰到很长的文本时,需要把文本分割成多个小的文本片段。它基于单个字符分隔符(如空格、换行符等)来拆分文本。

  • RecursiveCharacterTextSplitter:这是LangChain中常用的一个文本分割器,它根据分隔符的层次结构(如双换行符、单换行符、空格等)来拆分文本,旨在通过优先考虑段落和句子等自然边界的拆分来保持文本的结构和连贯性。
  • TokenTextSplitter:按token来分割文本,适用于需要根据词汇或标记来分割文本的场景。
  • MarkdownHeaderTextSplitter:基于指定的标题来分割Markdown文件,适用于Markdown文档的结构化分割。
代码语言:javascript复制
from langchain.text_splitter import CharacterTextSplitter


text_splitter = CharacterTextSplitter(
    separator = " ", 
    chunk_size = 5,
    chunk_overlap  = 0,
)
a = text_splitter.split_text("a b c d e f")
print(a)
b = text_splitter.create_documents(["a b c d e f", "e f g h"], )
print(b)
  • separator = " ":设置分隔符为空格。这意味着文本将在空格处被分割。
  • chunk_size = 5:设置每个分割块的大小为 5。这意味着每次分割将产生包含最多 5 个字符的文本块。
  • chunk_overlap = 0:设置分割块之间的重叠量为 0。这意味着分割块之间不会有任何重叠,每个分割都是独立的。

输出:

代码语言:javascript复制
['a b c', 'd e f']
[Document(page_content='a b c'), Document(page_content='d e f'), Document(page_content='e f g'), Document(page_content='h')]
VectorStores

VectorStores即向量存储,是LangChain中用于存储和检索向量数据的组件;是连接语言模型与实际应用数据的关键桥梁,这些向量数据通常是通过文本嵌入模型(如Word2Vec、BERT、Sentence Transformers等)将文本转换成数值向量得到的。这些向量能够在多维空间中捕捉词语或文档之间的语义相似性,从而为基于内容的搜索提供基础。

langchain.vectorstores.FAISS模块封装了FAISS库的功能,可以将文本嵌入向量存储在FAISS向量数据库中。这些向量可以表示文档、段落或任何其他形式的文本数据。

先看一下原数据:

我们要写一句话,根据输入的查询进行相似性搜索,最后返回与查询最相关的文档。

代码语言:javascript复制
from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_community.embeddings import QianfanEmbeddingsEndpoint

loader = TextLoader('./pku.txt',encoding='utf-8')
documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=100, chunk_overlap=0)
texts = text_splitter.split_documents(documents)
print(texts)

embeddings = QianfanEmbeddingsEndpoint()

db = FAISS.from_documents(texts, embeddings)
# 相当于创建了根据这个嵌入模型的向量数据库
retriever = db.as_retriever(search_kwargs={'k': 1})
# 输出一个最相关的
docs = retriever.get_relevant_documents("北京大学什么时候成立的")
print(docs)

输出:

代码语言:javascript复制
[Document(metadata={'source': './pku.txt'}, page_content='北京大学创办于1898年,是戊戌变法的产物,也是中华民族救亡图存、兴学图强的结果,初名京师大学堂,是中国近现代第一所国立综合性大学,辛亥革命后,于1912年改为现名。'), Document(metadata={'source': './pku.txt'}, page_content='在悠久的文明历程中,古代中国曾创立太学、国子学、国子监等国家最高学府,在中国和世界教育史上具有重要影响。北京大学“上承太学正统,下立大学祖庭”,既是中华文脉和教育传统的传承者,也标志着中国现代高等教育的开端。其创办之初也是国家最高教育行政机关,对建立中国现代学制作出重要历史贡献。'), Document(metadata={'source': './pku.txt'}, page_content='作为新文化运动的中心和五四运动的策源地,作为中国最早传播马克思主义和民主科学思想的发祥地,作为中国共产党最初的重要活动基地,北京大学为民族的振兴和解放、国家的建设和发展、社会的文明和进步做出了突出贡献,在中国走向现代化的进程中起到了重要的先锋作用。爱国、进步、民主、科学的精神和勤奋、严谨、求实、创新的学风在这里生生不息、代代相传。'), Document(metadata={'source': './pku.txt'}, page_content='1917年,著名教育家蔡元培就任北京大学校长,他“循思想自由原则,取兼容并包主义”,对北京大学进行了卓有成效的改革,促进了思想解放和学术繁荣。陈独秀、李大钊、毛泽东以及鲁迅、胡适、李四光等一批杰出人士都曾在北京大学任教或任职。'), Document(metadata={'source': './pku.txt'}, page_content='1937年卢沟桥事变后,北京大学与清华大学、南开大学南迁长沙,共同组成国立长沙临时大学。1938年,临时大学又西迁昆明,更名为国立西南联合大学。抗日战争胜利后,北京大学于1946年10月在北平复员。')]
[INFO][2024-07-29 21:45:12.597] oauth.py:228 [t:4572]: trying to refresh access_token for ak `CNzMCb***`
[INFO][2024-07-29 21:45:14.418] oauth.py:243 [t:4572]: sucessfully refresh access_token
D:apolloanacondalibsite-packageslangchain_core_apideprecation.py:139: LangChainDeprecationWarning: The method `BaseRetriever.get_relevant_documents` was deprecated in langchain-core 0.1.46 and will be removed in 0.3.0. Use invoke instead.
  warn_deprecated(
[Document(metadata={'source': './pku.txt'}, page_content='北京大学创办于1898年,是戊戌变法的产物,也是中华民族救亡图存、兴学图强的结果,初名京师大学堂,是中国近现代第一所国立综合性大学,辛亥革命后,于1912年改为现名。')]

可以看出还是很符合我们的想法的~

通过学习LangChain的组件,我们可以再根据官方文档,去完成新的项目。

  1. 文本检索与搜索: 利用LangChain的文本加载器、文本分割器、向量存储和嵌入模型,可以构建一个强大的文本检索系统。该系统能够对大量文本数据进行索引,并支持基于语义的搜索查询,快速返回最相关的结果。
  2. 文档相似度分析: 通过计算文档之间的向量相似度,LangChain可以帮助识别内容相似的文档或段落。在去重、推荐系统或内容聚类等场景中非常有用。
  3. 自然语言理解与应用: LangChain与各种自然语言处理(NLP)模型兼容。可以利用这些模型进行文本分类、情感分析、实体识别等任务,进而构建聊天机器人、智能客服或文本分析工具。

0 人点赞