模型
在上篇文章里,我们一起了解了LangChain是什么、LangChain组件的基础概念和LangChain的使用场景,现在我们通过实例,来学习LangChain的核心组件—模型。
模型
现在市面上的模型多如牛毛,各种各样的模型不断出现,最火的当属openai推出的GPT模型,GPT3.5对所有用户公开,GPT4则需要开通plus会员才能使用,国内百度文心一言、阿里通义千问也已经对部分用户开放。
LangChain模型组件提供了与各种模型的集成,并为所有模型提供一个精简的统一接口。
LangChain支持的模型可以分为三类,它们的使用场景不同,输入和输出不同,开发者需要根据项目需要选择相应的类型。
LLMs(大语言模型)
大语言模型接收字符串作为输入,并返回字符串作为输出,大部分场景下使用这类模型。
我们以OpenAI的GPT模型为例,看看怎么使用这类模型组件。
首先需要安装langchain和OpenAI
pip install openai
pip install langchain
要注意的是,使用openai模型前,需要开通OpenAI API服务(不是chatGPT plus),如何开通OpenAI API服务,可以查看OpenAI API权限开通经验分享 – 知乎 (zhihu.com),并在当前shell下增加环境变量,如下:
export OPENAI_API_KEY="你的OpenAI API token"
或者在代码中加入:
import os
os.environ["OPENAI_API_KEY"] = "你的OpenAI API token"
导入OpenAI
模型:
# 导入OpenAI模型
from langchain.llms import OpenAI
让OpenAI返回一个笑话:
llm = OpenAI(model_name="text-davinci-003", n=2, temperature=0.3)
llm("给我讲一个笑话")
#一个猴子去河里洗澡,洗完后他看见自己的影子,他觉得自己太瘦了,于是他又把头放进河里洗了一遍!
使用generate
方法可以同时接收多个输入,并且返回token使用信息,如下:
llm.generate(["给我讲一个故事", "给我讲一个笑话"])
# generations=[
# [Generation(text='nn一个叫玛丽的小女孩,有一只叫毛毛的小猫。nn每天晚上,玛丽都会和毛毛一起玩耍,一起跳舞,一起唱歌,一起玩游戏。nn有一天,玛丽和毛毛一起去海边玩,突然,毛毛被一只海鸥抓走了。玛丽非常伤心,她跑到海边哭了起来,哭着喊着毛毛的',
# generation_info={'finish_reason': 'length', 'logprobs': None}),
# Generation(text='nn一个叫小明的男孩,他很喜欢探险。有一天,他和他的朋友们一起去森林里玩,突然,他发现一个洞穴,他非常好奇,于是他决定去看看洞穴里面到底有什么。nn他走进洞穴,里面黑暗而又潮湿,他继续前行,突然,他看到一只大老虎,它正在吃一只小兔子。',
# generation_info={'finish_reason': 'length', 'logprobs': None})],
# [Generation(text='nn两个熊在森林里走,一个熊说:“嘿,你知道为什么树林里没有路吗?”另一个熊回答:“不知道,为什么?”第一个熊说:“因为它们都在绕树林跑!”', generation_info={'finish_reason': 'stop', 'logprobs': None}), Generation(text='nn两个熊在森林里拔萝卜,一个熊拔出一个萝卜,另一个熊说:“你拔的太慢了,我拔的快一点!”',
# generation_info={'finish_reason': 'stop', 'logprobs': None})]
# ]
# llm_output={'token_usage': {'prompt_tokens': 28, 'completion_tokens': 771, 'total_tokens': 799}, 'model_name': 'text-davinci-003'}
现在LangChain支持的LLMs模型有:
聊天模型
聊天模型基于LLMs,不同的是LLMs的输入输出是字符串,而聊天模型的输入输出是聊天消息。
聊天消息包含下面几种类型,使用时需要按照约定传入合适的值:
-
AIMessage
用来保存LLM的响应,以便在下次请求时把这些信息传回给LLM。
-
HumanMessage
发送给LLMs的提示信息,比如“实现一个快速排序方法”
-
SystemMessage
设置LLM模型的行为方式和目标。你可以在这里给出具体的指示,比如“作为一个代码专家”,或者“返回json格式”。
-
ChatMessage
ChatMessage可以接收任意形式的值,但是在大多数时间,我们应该使用上面的三种类型
我们看一个聊天模型的例子:
首先导入ChatOpenAI
模型:
from langchain.chat_models import ChatOpenAI
from langchain.schema import (
AIMessage,
HumanMessage,
SystemMessage
)
让OpenAI查询ModelY的尺寸数据,并且指定json格式返回:
chat = ChatOpenAI(temperature=0)
messages = [
SystemMessage(content="返回json object,不要纯文本,按照每项参数拆分,不要说明和解释信息"),
HumanMessage(content="告诉我model Y汽车的尺寸参数")
]
print(chat(messages))
# content='{n "车长": "4,750 mm",n "车宽": "1,921 mm",n "车高": "1,624 mm",n "轴距": "2,890 mm",n "最小离地间隙": "162 mm",n "行李箱容积": "1,900 L"n}' additional_kwargs={} example=False
和LLMs模型一样,聊天模型也有generate
方法,接收多组输入,返回token使用信息。
提示模板
在上面的例子中,模型默认是返回纯文本结果的,如下:
# content='以下是Model Y汽车的尺寸参数:nn- 长度:4,750毫米n- 宽度(包括外部镜子):2,189毫米n- 高度:1,624毫米n- 轴距:2,890毫米n- 最小离地间隙:162毫米n- 车重:1,996-2,162千克(取决于配置和电池选项)nn请注意,这些尺寸可能因配置和选项而有所不同。' additional_kwargs={} example=False
为了让模型返回json格式的数据,我进行了很多次尝试,不断优化SystemMessage中的条件,最终才实现了需求,对于小白怎么才能快速地让AI模型返回想要的结果呢?提示模板就出现了。
提示模板就是把一些常见的提示整理成模板,用户只需要修改模板中特定的词语,就能快速准确地告诉模型自己的需求。我们看个例子:
首先导入依赖
from langchain.chat_models import ChatOpenAI
from langchain.prompts import (
ChatPromptTemplate,
PromptTemplate,
SystemMessagePromptTemplate,
AIMessagePromptTemplate,
HumanMessagePromptTemplate,
)
from langchain.schema import (
AIMessage,
HumanMessage,
SystemMessage
)
实现提示模板:
system_template="你是一个把{input_language}翻译成{output_language}的助手"
system_message_prompt = SystemMessagePromptTemplate.from_template(system_template)
human_template="{text}"
human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)
chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])
messages = chat_prompt.format_prompt(input_language="英语", output_language="汉语", text="I love programming.")
print(messages)
#messages=[SystemMessage(content='你是一个把英语翻译成汉语的助手', additional_kwargs={}), HumanMessage(content='I love programming.', additional_kwargs={}, example=False)]
把messages传给ChatOpenAI
模型
chat = ChatOpenAI(temperature=0)
print(chat(messages.to_messages()))
# content='我喜欢编程。' additional_kwargs={} example=False
LangChain现在支持的聊天模型有:
模型 | 介绍 |
---|---|
ChatAnthropic | 一个前OpenAI员工创建的AI聊天助手,相比其他聊天工具,它的有害答案更少 |
AzureChatOpenAI | Azure提供的OpenAI聊天模型 |
ChatOpenAI | OpenAI聊天模型 |
PromptLayerChatOpenAI | 基于OpenAI的提示模板平台 |
文本嵌入模型(Text Embedding Model)
文本嵌入模型将字符串作为输入,返回一个浮动数的列表。
嵌入(Embedding)是NLP中的一个专业名词,把不可计算的非结构化数据转换成可计算的结构化数据,比如在一个句子中,单词的序列是“A B C D E”,NLP处理这个句子时,并不是把“A”、“B”、“C”这些单词输入模型,而是把单词转换为向量,比如“A”对应的向量为[0.7 0.5],“B”对应的向量为[0.2 -0.1],再把这些向量输入模型。
文本嵌入模型可以为文本创建向量映射,这样就能在向量空间里去考虑文本,执行诸如语义搜索之类的操作,比如说寻找相似的文本片段。
我们看一个OpenAI文本嵌入模型的例子。
首先导入依赖:
from langchain.embeddings import OpenAIEmbeddings
实现文本嵌入:
embeddings = OpenAIEmbeddings()
text = "这是一个测试文档。"
query_result = embeddings.embed_query(text)
doc_result = embeddings.embed_documents([text])
print(query_result)
# [-0.009422866627573967, 0.004315766040235758, 0.002380653750151396, -0.010300650261342525, -0.010433647781610489, 0.004894305020570755, -0.018366944044828415, -0.0019317874684929848, -0.004282516892999411, -0.017076868563890457, 0.0149622093886137, 0.024006033316254616, -0.014097725972533226, 0.007141961250454187, -0.004149519372731447, 0.012588205747306347, 0.012668004259467125, -0.018712736666202545, 0.005163624882698059, -0.00768725061789155, 0.002561862813308835, 0.002515313681215048, -0.010673042386770248, 0.007840197533369064, -0.038170259445905685, 0.010819340124726295, 0.01157077495008707, -0.02557540312409401, 0.011072034947574139, -0.01421742420643568, 0.018912233412265778, ...]
在这段代码中我们使用了embed_query
和embed_documents
两个方法,它们最大的不同是embed_query接收一个字符串作为输入,而embed_documents可以接收一组字符串,一些模型自身划分了这两个方法,LangChain也保留了下来。
LangChain集成的文本嵌入模型有:
模型 |
---|
Aleph Alpha |
AzureOpenAI |
Cohere |
Fake Embeddings |
Hugging Face Hub |
InstructEmbeddings |
Jina |
Llama-cpp |
OpenAI |
SageMaker Endpoint |
Self Hosted Embeddings |
SentenceTransformers |
TensorflowHub |
小结
这篇文章我们学习了LangChain的核心组件—模型,通过示例介绍了LangChain支持的三种模型的基本使用,在后面的教程里再去学习模型的高级操作。
由于示例涉及到了提示模板,这篇文章对提示模板做了简单介绍,下篇文章我们全面地学习提示模板是如何工作的。