目标 今天咱们介绍一下如何使用 LangChain 构建一个简单的 LLM 应用程序。
这个应用程序能够将英文文本翻译成其他语言。
这是一个相对简单的 LLM 应用程序 —— 它仅包含一个 LLM 调用和一些提示。
今天的学习目的是初步了解下面的概念
使用语言模型 (必须)
使用 PromptTemplates 和 OutputParsers(必须)
使用 LangChain 表达式语言 (LCEL) 将组件连接在一起(必须)
使用 LangSmith 调试和跟踪您的应用程序 (不用也问题不大)
使用 LangServe 部署您的应用程序(不用也问题不大)
准备阶段 我们全程使用windows + python, 其他的方法就不介绍了,同学们可以自己探索~
安装
关于 Jupyter Notebook
咱们用能跑python的编程工具就可以,用什么来跑不是很重要-。-
LangSmith
langsmith 是一个可以跟踪runnable 的工具,可以跟踪和记录复杂流程中的大部分参数,对于复杂问题分析很有帮助。在学习初期,我们可以先不使用这个工具,到后面遇到复杂逻辑和chain的时候,我们再使用。 感兴趣的同学可以自己去注册一下,每月有免费的使用额度。
薅羊毛 langsmith 的提示:截止2024 7.1日前,免费账户每月有5K 的使用次数
New Pricing:All free accounts will be rate limited to 5k traces per month starting on July 1st. To avoid this, sign up for our paid plans
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 你可以这样简单使用 # 新建一个ID 号,用于记录你的Log unique_id = uuid4 ().hex [0 :8 ] # 写一个TAG os.environ ["LANGCHAIN_PROJECT" ] = f" Agent RAG - {unique_id}" # 这个表示你要使用langsmith 开始记录,不用就false os.environ ["LANGCHAIN_TRACING_V2" ] = 'true' # 这个是你注册langsmith 后的KEY # 你可以把你的key 放到环境中,用MY_LANGCHAIN_API_KEY 来引用 os.environ ["LANGCHAIN_API_KEY" ] = os.getenv ('MY_LANGCHAIN_API_KEY' ) # 要是你觉得麻烦 你就这样 os.environ ["LANGCHAIN_API_KEY" ] = 'dsad6487dfdhb... 你的key'
使用语言模型 官网列出一堆模型,好是好,国内能用的没几个…(不翻墙的情况)
我们先用官网中的 Azure OpenAi 以及 千帆 来做演示~
创建一个 Azure OpenAi chatModel 1 2 3 4 5 6 os.environ ["AZURE_OPENAI_API_KEY" ] =AZURE_OPENAI_API_KEY os.environ ["AZURE_OPENAI_ENDPOINT" ] =AZURE_OPENAI_ENDPOINT gpt3p5_model = AzureChatOpenAI ( openai_api_version="2024-02-15-preview" , azure_deployment=DEPLOYMENT_NAME_GPT3P5 , )
AZURE_OPENAI_API_KEY : 你的Azure OpenAI KEY, 需要在微软Azure中申请订阅
AZURE_OPENAI_ENDPOINT : 你的服务端endpit,一个url地址,订阅后从Azure获取
openai_api_version : 你使用模型的版本号,依赖你使用的模型
azure_deployment :你给你部署的模型起的名字,从Azure获取
给出提示词,并调用invoke (LCEL 的方法之一)
1 2 3 4 5 6 7 messages = [ SystemMessage (content="Translate the following from English into Italian" ), HumanMessage (content="hi!" ), ] res = gpt3p5_model.invoke (messages) print (res.content )
messages: 消息列表,通常包含整个对话历史
SystemMessage:系统提示词,在messages 中一般只出现一次,表明系统的身份
HumanMessage: 用户消息
输出
模型输出的内容是 一个 AIMessage
1 2 3 AIMessage (content='ciao!.... content=' Ciao !' response_metadata={' token_usage': {' completion_tokens': 3, ' prompt_tokens': 20, ' total_tokens': 23}, ' model_name': ' gpt-35 -turbo', ' system_fingerprint': None, ' prompt_filter_results': [{' prompt_index': 0, ' content_filter_results': {' hate': {' filtered': False, ' severity': ' safe'}, ' self_harm': {' filtered': False, ' severity': ' safe'}, ' sexual': {' filtered': False, ' severity': ' safe'}, ' violence': {' filtered': False, ' severity': ' safe'}}}], ' finish_reason': ' stop', ' logprobs': None, ' content_filter_results': {' hate': {' filtered': False, ' severity': ' safe'}, ' self_harm': {' filtered': False, ' severity': ' safe'}, ' sexual': {' filtered': False, ' severity': ' safe'}, ' violence': {' filtered': False, ' severity': ' safe'}}} id=' run-2340cccd-9b63-4b07-9dfd-3c154bbef121-0 '
创建 文心一言4 chatModel 1 2 3 4 5 6 7 8 9 # 千帆的 AK 和 SK , 需要我们去百度网站申请 os.environ ["QIANFAN_AK" ] = MY_QIANFAN_AK os.environ ["QIANFAN_SK" ] = MY_QIANFAN_SK # 文心一言4 模型ERNIE -Bot -4 wenxin4_model = QianfanChatEndpoint (model="ERNIE-Bot-4" ) res = wenxin4_model.invoke (messages) print (res.content )pass
输出
1 2 AIMessage (content='salve!.... content=' salve!' additional_kwargs={' finish_reason': ' normal', ' request_id': ' as -hpbfyf1uqr', ' object': ' chat.completion ', ' search_info': [], ' function_call': {}, ' tool_calls': [{' type': ' function ', ' function ': {}}]} response_metadata={' token_usage': {' prompt_tokens': 10, ' completion_tokens': 3, ' total_tokens': 13}, ' model_name': ' ERNIE -Bot -4 ', ' finish_reason': ' normal', ' id': ' as -hpbfyf1uqr', ' object': ' chat.completion ', ' created': 1718674042, ' result': ' salve!', ' is_truncated': False, ' need_clear_history': False, ' usage': {' prompt_tokens': 10, ' completion_tokens': 3, ' total_tokens': 13}} id=' run-4f50bc84-86a6-46dd-8c6f-03d0fbafc3d5-0 '
输出解析器 1 2 3 4 5 6 7 8 9 10 11 12 from langchain_core.output_parsers import StrOutputParser parser = StrOutputParser () # 大模型的输出 result = model.invoke (messages) # 解析器 解析模型的输出 parser.invoke (result) # 将 AIMessage 解析成 字符串 (这一步要理解一下...) 'Ciao!'
为了让上面几步连贯,这也是langchain 的 精华之一
1 2 # 使用 chain chain = model | parser
于是 文心一言4 的chain, 可以这样
1 2 3 4 chain = wenxin4_model | parser res = chain.invoke(messages) print (res.content)pass
使用提示词模板 我们可以在提示词中使用变量, 变量的表示方法是把变量放到{ }中
系统提示词: 通过变量language, 我们可以改变目标语言的类型
1 system_template = "Translate the following into {language}:"
将用户输入,放入变量 text;组合成一个[]
1 2 3 prompt_template = ChatPromptTemplate.from_messages( [("system" , system_template), ("user" , "{text}" )] )
通过invoke 方法,指定变量的内容
1 2 result = prompt_template.invoke({"language" : "italian" , "text" : "hi" }) print (result.to_messages())
输出
1 messages=[SystemMessage(content='Translate the following into italian:' ), HumanMessage(content='hi' )]
将上面的各个部分组合起来: chain ! 1 2 3 4 ful_chain = prompt_template | wenxin4_model | parser res = ful_chain.invoke({"language" : "italian" , "text" : "hi" }) print (res)pass
初步体验一下 Langserve 核心
用 FastAPI 创建一个APP,再调用 langserve add_routes方法,将消息路由到chain 上,作为chain 的输入
需要安装
pip install sse_starlette
pip install langserve
文心4 作为模型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 import osfrom typing import List from fastapi import FastAPIfrom langchain_community.chat_models import QianfanChatEndpointfrom langchain_core.prompts import ChatPromptTemplatefrom langchain_core.output_parsers import StrOutputParserfrom langchain_openai import ChatOpenAIfrom langserve import add_routesfrom llm_cfg import MY_QIANFAN_AK, MY_QIANFAN_SKsystem_template = "Translate the following into {language}:" prompt_template = ChatPromptTemplate.from_messages([ ('system' , system_template), ('user' , '{text}' ) ]) os.environ["QIANFAN_AK" ] = MY_QIANFAN_AK os.environ["QIANFAN_SK" ] = MY_QIANFAN_SK model = QianfanChatEndpoint(model="ERNIE-Bot-4" ) parser = StrOutputParser() chain = prompt_template | model | parser app = FastAPI( title="LangChain Server" , version="1.0" , description="A simple API server using LangChain's Runnable interfaces" , ) add_routes( app, chain, path="/chain" , ) if __name__ == "__main__" : import uvicorn uvicorn.run(app, host="localhost" , port=8000 )
直接运行main 方法,看到命令行成功后,浏览器中打开 :http://localhost:8000/chain/playground/
客户端调用服务端 有了上面的服务端,Langchain 可以支持远程chain的调用,小伙伴们可以自行尝试。
在单位里,小伙伴们可以自己建立一个大模型服务,然后让单位里的小伙伴调用~~
1 2 3 4 from langserve import RemoteRunnableremote_chain = RemoteRunnable("http://localhost:8000/chain/" ) remote_chain.invoke({"language" : "italian" , "text" : "hi" })
代码附录 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 import osfrom langchain_community.chat_models import QianfanChatEndpointfrom langchain_core.prompts import ChatPromptTemplatefrom langchain_openai import AzureChatOpenAIfrom langchain_core.messages import HumanMessage, SystemMessagefrom llm_cfg import AZURE_OPENAI_API_KEY, AZURE_OPENAI_ENDPOINT, DEPLOYMENT_NAME_GPT3P5, MY_QIANFAN_AK, MY_QIANFAN_SKif __name__ == '__main__' : os.environ["AZURE_OPENAI_API_KEY" ] =AZURE_OPENAI_API_KEY os.environ["AZURE_OPENAI_ENDPOINT" ] =AZURE_OPENAI_ENDPOINT gpt3p5_model = AzureChatOpenAI( openai_api_version="2024-02-15-preview" , azure_deployment=DEPLOYMENT_NAME_GPT3P5, ) messages = [ SystemMessage(content="Translate the following from English into Italian" ), HumanMessage(content="hi!" ), ] res = gpt3p5_model.invoke(messages) print (res.content) pass os.environ["QIANFAN_AK" ] = MY_QIANFAN_AK os.environ["QIANFAN_SK" ] = MY_QIANFAN_SK wenxin4_model = QianfanChatEndpoint(model="ERNIE-Bot-4" ) res = wenxin4_model.invoke(messages) print (res.content) pass from langchain_core.output_parsers import StrOutputParser parser = StrOutputParser() chain = wenxin4_model | parser res = chain.invoke(messages) print (res.content) pass system_template = "Translate the following into {language}:" prompt_template = ChatPromptTemplate.from_messages( [("system" , system_template), ("user" , "{text}" )] ) result = prompt_template.invoke({"language" : "italian" , "text" : "hi" }) print (result.to_messages()) pass ful_chain = prompt_template | wenxin4_model | parser res = ful_chain.invoke({"language" : "italian" , "text" : "hi" }) print (res) pass