AI大模型学习(二): LangChain(一)
LangChain介绍
官方文档:Introduction | 🦜️🔗 LangChain
Langchain是一个开源框架,它允许开发人员将像GTP-4这样的大型语言模型与外部的计算和数据源结合起来
ClangChain是一个用于开发由语言模型驱动的应用程序的框架
比如:如果我们想让聊天机器人不仅仅回答通用问题,它能从你自己的数据库或文件中提取信息,并根据这些信息执行具体操作,比如发邮件,那会是什么情况,LangChain正是为了实现着一目标而诞生的
它通过三个核心组件实现增强:
1.首先是Compent "组件",为LLMs提供接口封装,模块提示和信息检索索引
2.其次是Chains "链",它将不同的组件组合起来解决特定的任务,比如在大量文本中查找信息
3.最后是Agents "代理",它们使得LLMs能够与外部环境进行交互,例如通过API请求执行操作
LangChain的这种结构设计使LLMs不仅能够处理文本,还能够在更广泛的应用环境中进行操作和响应,大大扩展了她们的应用范围和有效性
什么时候要用Langchain?
数据连接:Langchain允许你将大型语言模型连接到你自己的数据源,比如数据库,PDF文件或其他文档,这意味着你可以使模型从你得私有数据中提取信息
行动执行:不仅仅可以提取信息,langchain还可以根据这些信息执行特定操作,如发送邮件
Langchain的核心
模型Models:包装器允许你连接到大型语言模型
Prompt Templates:这些模版让你便面硬编码文本输入,你可以动态将用户输入插入到模版中,并发送给语言模型
Chains:链允许你将多个组件组合在一起,解决特定的任务,并构建完整的语言模型应用程序
Agents:代理允许语言模型与外部API交互
Embedding:嵌入与向量存储VectorStore是数据表示和检索的手段,为模型提供必要的语言理解基础
Indexes:索引帮助你从语言模型中提取相关信息
Langchain的底层原理
举例:如上图所展示一个智能问答系统的工作流
1.从用户提出的问题(Question) 开始,然后通过相似性搜索(Similarity Search)在一个大型数据库或者向量空间找到与之相关的信息
2.得到的信息与原始问题结合后,由一个处理模型分析,以产生一个答案(Answer)
3.这个答案接着被用来指导一个代理采取行动(Action),这个代理可能会执行一个API调用或与外部系统交互以完成任务
整个流程反映了数据驱动的决策过程,其中包含了从信息检索到处理,再到最终行动的自动化步骤
Langchain的应用场景
个人助手:可以帮助预定航班,转账,缴税等
学习辅助:可以参考整个课程大纲,帮助你更快地学习材料
数据分析和数据科学:连接到公司的客户数据或市场数据,极大地促进数据分析的进展
LangChain实际操作
安装
pip install langchain
pip install langchain-openai
LangSmith
登录,并获取LangSmish的API key:LangSmith
LangSmith 是一款专为 LLM(大型语言模型)应用开发、监控和测试而打造的平台,以下是关于它的详细介绍:
-
核心功能
-
调试功能:可提供对 LLM 应用的全流程调用可见性,开发者能实时精准定位错误源头和性能瓶颈,比如通过查看详细的调用日志,能快速发现模型在处理哪类输入时出现异常。
-
协作功能:支持团队协作,开发者可轻松与同事、客户或终端用户共享链跟踪信息,还可通过 LangSmith Hub 编写、版本控制和评论提示,利用注释队列添加人工标签和反馈。
-
测试与评估功能:能进行数据集构建,快速保存调试和生产跟踪到数据集;支持自动评估,使用 LLM 和提示对应用输出评分;可进行回归测试,查看应用更改对评估标准的影响;还能进行在线评估,持续跟踪应用的定性特征。
-
性能监控功能:能实时分析和记录模型性能数据,帮助开发者跟踪模型的运行状况,如监控模型的响应时间、准确率、召回率等指标,及时发现性能下降或异常情况。
-
-
适用场景
-
LLM 应用开发全周期:在原型开发阶段,方便代码调试、基础测试等;测试阶段,能收集用户反馈和跟踪信息以优化模型;生产阶段,可进行监控、A/B 测试及自动化操作。
-
多框架支持:不仅与 LangChain 无缝集成,也可用于其他 LLM 框架开发的应用,比如使用其他框架构建的聊天机器人、文本生成器等应用,都能通过 LangSmith 进行管理和优化。
-
-
使用方式
-
SDK 接入:提供 Python 和 TypeScript 的 SDK,开发者通过设置环境变量等简单操作,就能将 LLM 应用与 LangSmith 连接,实现数据上报和功能使用。
-
API 接入:对于非 Python 或 TypeScript 编写的应用,可通过 API 进行交互,实现日志跟踪、数据集创建和评估等功能
-
初步使用
from langchain_core.messages import SystemMessage, HumanMessage
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
model = ChatOpenAI(model='gpt-4-turbo', api_key='your_api_key')
# api_key除了显示的也可以在系统环境变量里设置 OPENAI_API_KEY
message = [
SystemMessage(content=''), # 我们固定的提示词
HumanMessage(content='') # 用户的输入
]
response = model.invoke(message) # 这个返回的内容很多,响应数据需要进一步解析
print(response)
# 简单的解析响应
parser = StrOutputParser()
result = parser.invoke(response) # 这个解析的结果是模型回答的问题
"""
message = [
SystemMessage(content='你是一个友好的助手,能回答各种常识问题。'),
HumanMessage(content='世界上最深的海洋是哪个?')
]
"""
SystemMessage
和HumanMessage
是langchain_core.messages
模块中的类,用于创建系统消息和用户消息。在与语言模型进行对话时,系统消息通常用于设定对话的上下文、任务或模型的行为模式,而用户消息则代表用户输入的具体内容。ChatOpenAI
是langchain_openai
模块中的类,它提供了一个方便的接口来调用 OpenAI 的聊天模型SystemMessage(content='')
:创建了一个系统消息对象,不过content
字段为空字符串。在实际应用中,你可以在这个字段中填入一些引导信息,例如 “你是一个知识渊博的助手,专注于回答科学相关的问题”。HumanMessage(content='')
:创建了一个用户消息对象,同样content
字段为空字符串。你需要将用户实际输入的问题填入这个字段,例如 “太阳系有多少颗行星”- 调用
model
实例的invoke
方法,将消息列表message
作为参数传入。该方法会将消息发送给gpt - 4 - turbo
模型,并等待模型返回响应。返回的响应存储在response
变量中StrOutputParser
类是 LangChain 库中的一个输出解析器,其主要功能是对大型语言模型(LLM)生成的输出进行解析和处理,将模型的输出转换为特定格式,方便开发者在后续代码中使用
使用链
from langchain_core.messages import SystemMessage, HumanMessage
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI
model = ChatOpenAI(model='gpt-4-turbo', api_key='your_api_key')
# api_key除了显示的也可以在系统环境变量里设置 OPENAI_API_KEY
message = [
SystemMessage(content=''),
HumanMessage(content='')
]
# 创建返回的数据解析器
parser = StrOutputParser()
# 得到链
chain = model | parser
# 直接使用chain来调用
print(chain.invoke(message))
加入提示模版
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
model = ChatOpenAI(model='gpt-4-turbo', api_key='your_api_key')
# 创建返回的数据解析器
parser = StrOutputParser()
# 定义提示模版
prompt_template = ChatPromptTemplate.from_messages(
[('system', '请将下面的内容翻译成{language}'),
('user', '{text}')]
)
"""
使用 ChatPromptTemplate.from_messages 方法创建一个聊天提示模板 prompt_template。
模板包含两条消息:
系统消息:'请将下面的内容翻译成{language}',用于向模型说明任务,其中 {language} 是一个占位符,后续会被具体的语言名称替换。
用户消息:'{text}',表示用户输入的待翻译文本,{text} 也是一个占位符
"""
# 得到链
chain = prompt_template | model | parser
"当调用这个链时,输入数据会依次经过提示模板的处理、模型的推理,最后由解析器进行输出解析"
# 直接使用chain来调用
print(chain.invoke({
'language': 'English',
'text': '我下午还有一节课,不能去打球了',
}))
"""
调用 chain 的 invoke 方法,传入一个字典作为输入,其中 'language' 键对应的值为 'English',表示要翻译成英语;'text' 键对应的值为 '我下午还有一节课,不能去打球了',即待翻译的文本。
处理链会根据提示模板将输入数据转换为合适的消息格式,调用模型进行翻译,最后将模型的输出解析为字符串并打印出来
"""
关于ChatPromptTemplate中的system和user
在使用 ChatPromptTemplate
时,使用 system
和 user
并不是严格意义上的 “固定写法”,但它们是遵循 OpenAI 等大语言模型对话 API 规范的常用约定
在许多大语言模型的交互场景中,使用 system
和 user
是一种被广泛接受和推荐的做法,具有以下特点和优势:
大语言模型通常对不同类型的消息有不同的处理逻辑。system
消息一般用于设置全局的指令、上下文或行为准则,而 user
消息用于传递用户的实际输入内容。这种区分有助于模型更好地理解任务和生成更符合预期的回复
system
消息为模型设定了角色和回答风格,user
消息提出了具体问题,使得模型能按照要求给出准确回答
OpenAI 的聊天模型 API 就是按照这种 system
、user
等消息类型来组织输入的。LangChain 作为一个封装库,沿用了这种规范,以确保与底层模型 API 的兼容性,方便开发者使用
简单的部署
安装包
pip install "langserve[all]"
代码
from fastapi import FastAPI
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langserve import add_routes
model = ChatOpenAI(model='gpt-4-turbo', api_key='your_api_key')
# 创建返回的数据解析器
parser = StrOutputParser()
# 定义提示模版
prompt_template = ChatPromptTemplate.from_messages(
[('system', '请将下面的内容翻译成{language}'),
('user', '{text}')]
)
# 得到链
chain = prompt_template | model | parser
#
# # 直接使用chain来调用
# print(chain.invoke({
# 'language': 'English',
# 'text': '我下午还有一节课,不能去打球了',
# }))
# 创建FastAPI的应用
app = FastAPI(title='Language Chain', version='1.0.1', description='第一个服务')
add_routes(
app,
chain,
path='/api/v1/chain'
)
if __name__ == '__main__':
import uvicorn
uvicorn.run(app, host='0.0.0.0', port=8080)
"""
请求方式:POST
请求地址:http://0.0.0.0:8080/api/v1/chain/invoke
请求格式:
{
"input": {
"language": "English",
"text": "我要去上班了,不能跟你聊天了"
}
}
"""
__ ___ .__ __. _______ _______. _______ .______ ____ ____ _______
| | / \ | \ | | / _____| / || ____|| _ \ \ \ / / | ____|
| | / ^ \ | \| | | | __ | (----`| |__ | |_) | \ \/ / | |__
| | / /_\ \ | . ` | | | |_ | \ \ | __| | / \ / | __|
| `----./ _____ \ | |\ | | |__| | .----) | | |____ | |\ \----. \ / | |____
|_______/__/ \__\ |__| \__| \______| |_______/ |_______|| _| `._____| \__/ |_______|
LANGSERVE: Playground for chain "/api/v1/chain/" is live at:
LANGSERVE: │
LANGSERVE: └──> /api/v1/chain/playground/
LANGSERVE:
LANGSERVE: See all available routes at /docs/
INFO: Started server process [24156]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)
代码调用部署的接口
from langserve import RemoteRunnable
client = RemoteRunnable('http://0.0.0.0:8080/api/v1/chain/')
# 这行代码创建了一个 RemoteRunnable 实例 client,并传入一个 URL 作为参数。这个 URL 指向一个已经部署好的 LangChain 链服务的端点
client.invoke({'language': 'English', 'text': '你好'})
# 这行代码调用了 client 实例的 invoke 方法,并传入一个字典作为参数。这个字典包含了要传递给远程链服务的输入数据
# 当调用 invoke 方法时,client 会向指定的 URL 发送一个请求,将输入数据传递给远程链服务。服务接收到请求后,会对输入数据进行处理,并返回处理结果。最后,invoke 方法会返回服务的响应结果