当前位置: 首页 > article >正文

LangChain的开发流程

文章目录

    • LangChain的开发流程
      • 开发密钥指南
      • 3种使用密钥的方法
      • 编写一个取名程序
    • LangChain表达式

LangChain的开发流程

    为了更深人地理解LangChain的开发流程,本文将以构建聊天机器人为实际案例进行详细演示。下图展示了一个设计聊天机器人的LLM应用程序。

图片名称

    除了Wb服务器等传统组件,这个应用程序架构中还引人了两个额外的组件:一个LLM集成中间件,如LangChain(图上的中间部分),以及一个大语言模型(上图左侧)。中间件提供一个API,业务逻辑控制器调用它以启用聊天机器人功能。具体的LLM是基于配置决定的。当用户提问时(步骤①),聊天机器人控制器代码调用LangChain API(通过LangChain的6大模块设置的接口),在内部与LLM(步骤②)交互,由LLM来理解问题并生成回答(步骤③),显示在终端用户的聊天界面上(上图右侧的Web页面)。

    清单1展示了如何使用LangChain和OpenAI的GPT-3.5-Turbo-0613大语言模型实现聊天机器人业务逻辑。这段Python代码首先创建了ChatOpenAI类的实例(代表GPT-3.5聊天模型包装器)。第49行在路径chat’下建立了一个POST端点,可以利用FastAPI库。当用户向聊天机器人提交一个问题时,chat函数就会被触发,请求对象在其输人属性中封装用户的提问。为了处理请求,代码第7行实例化了一个LLMChain链组件,接收了一个聊天模型包装器Ilm和一个提示词模板prompt,实现了一个LangChain的内置预配置聊天机器人,可以与终端用户交互。第8行处理用户的提问:运行LLMChain链组件,接收用户的提问并将其作为输人,返回大语言模型生成的响应。这个响应持有对用户提问的答案,并在第9行代码执行后返回给用户。

llm = ChatOpenAI(#LLM initialization parameters
model_name=("gpt-3.5-turbo-0613",openai_api_key="你的密钥"',
temperature=0.9)
_prompt=""你是一个发言友好的AI助理。请现在回答用户的提问:《question}。""
@app.post ("/chat")#Chatbot controller URL endpoint
async def chat (request):
	prompt PromptTemplate.from template(prompt)
	chat_chain = LLMChain(llm=llm,prompt=prompt)
	response=chat_chain(request.input)#终端用户的提问字符串
	return {"response":response ["text"])

开发密钥指南

    LangChain自身是一个集成框架,不需要开发者注册和登录,也不需要设置密钥。但是在LLM开发过程中,要使用第三方平台的模型或者工具,需要遵守第三方的开发者协议,而且几乎所有的付费平台都使用密钥作为API调用的计费依据,这一点不仅适用于LLM,还适用于其他各种API工具。这意味着,如果你没有相应平台的密钥,你将无法使用其服务,特别是当你依赖像OpenAI这样的第三方平台时,保护密钥的安全并确保其不被泄露是非常关键的。在本文中,代码示例中使用了3种密钥策略。本节将以OpenAI平台为例,详细说明如何获取和使用密钥。尽管各个平台可能有所不同,但其密钥获取和使用方法大致相似。你可以查看第三方平台的官方文档或教程,通常会提供详细的步骤和示例。

    获取开发密钥在开始使用OpenAI的API之前,你需要先注册一个OpenAI账户并获取API密钥。以下是获取密钥的步骤:访问OpenAI官方网站,如果你还没有账户,请点击“注册”并按照提示完成注册过程;登录你的账户,跳转到“我的”“API Keys”部分,你可以看到你的API密钥,或通过一个“+”选项来生成新的密钥;复制密钥并将其保存在一个安全的地方,确保不要与他人分享或公开你的密钥。

3种使用密钥的方法

  1. 方法1:直接将密钥硬编码在代码中。这是最直接的方法,但也是最不安全的。直接在代码中提供密钥的示例如下所示:
# 硬编码传参方式
openai_api_key="填人你的密钥"
from langchain.llms import OpenAI
11m OpenAI(openai_api_key openai_api_key)
# 或者在引人os模块后硬编码设置os的环境变量,简单地使用11m=OpenAI()来初始化类
import os
os.environ["OPENAI API KEY"]="填人你的密钥"
llm =OpenAI()

    注意:这种方法的缺点是,如果你的代码被公开或与他人分享,你的密钥也可能被泄露。由于本书案例主要用于解释,因此每个需要开发密钥的代码示例都采用这种“显眼”的方式。但是推荐开发者使用方法2或者方法3。方法1通常是为了简化和说明如何使用API密钥,在教程、文档或示例代码中向用户展示如何设置和使用密钥,并不是实际应用中推荐的做法。在实际的生产环境或项目中,直接在代码中硬编码密钥是不推荐的。

  1. 方法2:使用环境变量。这是一种更安全的方法,你可以在你的本地环境或服务器上设置环境变量,将密钥保存为环境变量,然后在代码中使用它。例如,在Liux或macOS系统上,你可以在命令行中执行:export OPENAI API KEY="填人你的密钥"。当你在Python代码中初始化OpenAI类时,不需要传递任何参数,因为LangChain框架会自动从环境中检测并使用这个密钥。你可以简单地使用Ilm=OpenAIO命令来初始化类,如下所示:
from langchain.llms import OpenAI
llm OpenAI()

    这样,即使代码被公开,你的密钥也不会被泄露,因为它不是直接写在代码中的。

  1. 方法3:使用getpass模块。这是一种交互式的方法,允许用户在运行代码时输人密钥,你可以简单地使用llm=OpenAI()命令来初始化类,如下所示:
import os
import getpass
os.environ ['OPENAI API KEY']=getpass.getpass ('OpenAI API Key:')
from langchain.llms mport OpenAI
llm =OpenAI()

    当你运行这段代码时,它会提示你输人OpenAI API密钥。这种方法的好处是,密钥不会被保存在代码或环境变量中,而是直接从用户那里获取。管理和使用密钥是一个重要的任务,需要确保密钥的安全。上述3种方法提供了不同的密钥使用方式,你可以根据自身需求和安全考虑选择合适的方法。无论选择哪种方法,都要确保不要公开或与他人分享你的密钥。

编写一个取名程序

    在LLM应用开发领域,LangChain为开发者带来了前所未有的可能性。通过编写一个取名程序,你将对LangChain框架有一个初步的了解。安装和基础配置首先,为了能够顺利进行开发工作,需要确保计算机上安装了相应的Python包。开发者可以通过以下命令轻松完成安装:pip install openai langchain每一个与API交互的应用都需要一个API密钥。开发者可以创建一个账户并获取密钥,为了保障API密钥的安全,最佳实践是将其设置为环境变量:export OPENAI_API_KEY="你的API密钥”但是,如果开发者不熟悉如何设置环境变量,也可以直接在初始化模型包装器OpenAI时传人密钥:

from langchain.llms import OpenAI
llm=OpenAI(openai_api_key="你的API密钥")

    编写取名程序有了这些基础设置,接下来就可以利用LLM进行实际的编程工作了。想象一下,有一个程序可以基于用户的描述来为公司、产品或项目提供创意取名建议。比如,当输人“为一家生产多彩袜子的公司起一个好名字”时:

llm.predict("
What would be a good company name for a company that makes"
"colorful socks?"
)

    Feetful of Fun这个名字听起来不错。如此,一个简洁的、能提供创意取名建议的程序就诞生了。

LangChain表达式

    LangChain秉持的核心设计理念是“做一件事并把它做好”。这种设计理念强调,每一个工具或组件都应该致力于解决一个特定的问题,并能够与其他工具或组件集成。在LangChain中,这种设计理念的体现是,它的各个组件都是独立且模块化的。例如,通过使用管道操作符“”,开发者可以轻松地实现各个组件链的组合,开发者可以像说话一样编写代码,“直接”和“简洁”就是LangChain表达式的精髓所在。这种表达式不仅使得代码结构更为清晰,还让编程的方式更加接近自然语言的表达,为开发者提供了更为直观和顺滑的编程体验。

    考虑到LangChain的目标是构建LLM应用,因此,开发者可以轻松地利用其提供的组件,如PromptTemplate、ChatOpenAI和OutputParser,为LLM应用创建自定义的处理链。例如,基于StrOutputParser,开发者可以轻松地将LLM或Chat Model输出的原始格式转换为更易于处理的字符串格式。以下代码示例展示了LangChain表达式的实际应用:

from langchain.prompts import ChatPromptTemplate
from langchain.chat models import ChatopenAI
from langchain.schema.output parser import StrOutputParser
# 实例化提示词模板和聊天模型包装器
prompt =ChatPromptTemplate.from template("tell me a joke about (topic)")
model=ChatopenAI(openai_api_key="你的API密钥")
# 定义处理链
chain =prompt I model I StrOutputParser (
response =chain.invoke ({"foo":"bears"))
print(response)
# 输出:"why don't bears wear shoes?\n\nBecause they have bear feet!"

    此外,LangChain的另一个关键是流水线处理。在软件开发中,氵流水线处理是一种将多个处理步骤组合在一起的方法,其中每个步骤的输出都是下一个步骤的输人。这种设计不仅简化了LLM应用开发流程,还确保了输出的高效性和可靠性。开发者们在使用LangChain构建LLM应用时,不仅可以利用其组件化的设计优势,还可以确保应用具有较高的灵活性和可扩展性,这些都是现代LLM应用开发中的关键要素。注意,使用管道操作符进行链式调用(即prompt|model|StrOutputParser()需要新版本的LangChain仓库支持,开发者们请务必将LangChain升级到最新版本。

    为了帮助开发者更好地理解和使用LangChain表达式,接下来的部分将详细介绍LangChain中的一些常见表达式。提示词模板+模型包装器,提示词模板与模型包装器的组合构成了最基础的链组件,通常用在大多数复杂的链中。复杂的链组件通常都包含提示词模板和模型包装器,这是与LLM交互的基础组件,可以说缺一不可。请看以下示例:

from langchain.prompts import ChatPromptTemplate
from langchain.chat models import ChatopenAI
# 实例化提示词模板和聊天模型包装器
prompt =ChatPromptTemplate.from template ("tell me a joke about (topic)")
model=ChatOpenAI(openai_api_key="你的API密钥")
# 定义处理链
chain =prompt I model
# 调用处理链
response =chain.invoke ({"foo":"bears"))
print (response)
# 输出:AIMessage(content='Why don\'t bears use cell phones?\n\n
Because they always get terrible "grizzly"reception!',
additional_kwargs=(),example=False)

    为了获得更加可控和有针对性的输出,确保输出的文本符合期望和需求,经常要将additional kwargs传人模型包装器。在下面给出的代码示例中,chain=,prompt|model.bind(stop=["n"])这行代码表示,当LLM生成文本并遇到换行符n时,应该停止进一步的文本生成:

chain =prompt I model.bind(stop=["\n"])
response= chain.invoke ({"foo":"bears"})
#response:AIMessage(content="Why don't bears use cell phones?",
additional kwargs=(},example=False)

    bind方法同样支持OpenAI的函数回调功能,可以将函数描述列表绑定到模型包装器上:

functions ={
	{
		"name":"joke",
		"description":"A joke",
		"parameters":{
			"type":"object",
			"properties":{
				"setup":{
					"type":"string",
					"description":"The setup for the joke"
					},
				"punchline":{
					"type":"string",
					"description":"The punchline for the joke"
					}
			},
			"required":["setup","punchline"]
			}
		}
}
chain =prompt I model.bind(function call={"name":"joke"),functions=
functions)
response =chain.invoke ({"foo":"bears"},config=())
# 输出response:AIMessage (content='',additional_kwargs=('function_call':
('name':joke','arguments':(\n "setup":"Why don\'t bears wear
shoes?",\n "punchline":"Because they have bear feet!"\n)')),
example=False)

    提示词模板+模型包装器+输出解析器。可以在提示词模板与模型包装器的组合基础上,再增加一个输出解析器。示例如下:

from langchain.schema.output parser import StrOutputParser
chain= prompt I model I StrOutputParser()
response= chain.invoke ({"foo":"bears"),config=())
#response:"Why don't bears wear shoes?\n\nBecause they have bear feet!"

    当定义一个要返回的函数时,你可能不希望进行额外的处理,而只希望直接对函数进行解析。为了满足这个需求,LangChain为OpenAI提供了一个专门的函数回调解析器,名为JsonOutputFunctionsParser。这意味着在LangChain…output_parsers下的所有内置输出解析器的类型都是可用的。此外,还可以根据自己的需要使用自定义的输出解析器:

from langchain.output_parsers.openai functions import JsonOutputFunctionsParser
chain =prompt I model.bind(
		function call=("name":"joke"),
		functions=functions)
	| JsonOutputFunctionsParser()
)
response chain.invoke ({"foo":"bears"))
#response:('setup':"Why don't bears wear shoes?",
'punchline':'Because they have bear feet!')

    多功能组合链,首先定义两个提示词模板prompt1和prompt2,分别用来询问某人来自哪个城市,以及这个城市位于哪个国家。chain1是由promptl、model和StrOutputParser组成的链,目的是根据给定的人名返回此人来自哪个城市。chain2是更复杂的链。它首先使用chainl的结果(城市),然后结合itemgetter提取的language键值,生成输入prompt2的完整问题。这个问题随后会被传递给模型,并通过StrOutputParser解析:

from operator import itemgetter
prompt1 = ChatPromptTemplate.from_template("what is the city (person)is from?")
prompt2 = ChatPromptTemplate.from template"what country is the city (city}in?respond in (language)"
chain1 promptl I model I StroutputParser (
chain2 =
{"city":chainl,"language":itemgetter("language"))
I prompt2
| model
I StrOutputParser()
chain2.invoke (("person":"obama","language":"spanish"))

    当调用chain2并传递{"person'":"obama","language":"spanish"}作为输入时,整个流程将按顺序执行,并返回最终结果:

'El pais en el que nacio la ciudad de Honolulu,Hawai,donde nacio Barack
Obama,el 44 presidente de los Estados Unidos,es Estados Unidos.'

    下面我们加大难度,创建一个更复杂的组合链。先定义4个提示词模板,涉及颜色、水果、某国家国旗颜色,以及水果和国家(国旗)的颜色对应关系。chain1是一个简单的链,根据promptl生成一个随机颜色。chain2是一个复杂的链,首先使用RunnableMap和chainl来获取一个随机颜色。接下来,这个颜色被用作两个并行链的输人,分别询问此颜色的水果有什么,以及哪个国家的国旗是这个颜色的。示例代码如下:

from langchain.schema.runnable import RunnableMap
prompt1 =ChatPromptTemplate.from template ("generate a random color")
prompt2 =ChatPromptTemplate.from template ("what is a fruit of color:(color)")
prompt3 =ChatPromptTemplate.from template ("what is countries flag that has the color:{color)")
prompt4 =ChatPromptTemplate.from template ("What is the color of (fruit}and{country)")
chainl prompt1 I model I StrOutputParser()
chain2 RunnableMap(steps=("color":chain1))("fruit":prompt2 I model I StroutputParser (),"country":prompt3 I model I StroutputParser(),}I prompt4

    最后,这两个并行链的返回结果(一个水果和一个国家)被用作prompt44的输人,询问这个水果和这个国家的国旗是什么颜色的。

chain2.invoke ((}ChatPromptValue(messages=[HumanMessage(content="What is the color of Afruit that has a color similar to #7E7DE6 is the Peruvian Apple Cactus (Cereusrepandus).It is a tropical fruit with a vibrant purple or violet exterior.andThe country's flag that has the color #7E7DE6 is North Macedonia.",additional_kwargs=(},example=False)])

http://www.kler.cn/a/525049.html

相关文章:

  • mybatis(134/134)完结
  • 【微服务与分布式实践】探索 Sentinel
  • Java创建项目准备工作
  • 二进制安卓清单 binary AndroidManifest - XCTF apk 逆向-2
  • Cannot resolve symbol ‘XXX‘ Maven 依赖问题的解决过程
  • Ansible自动化运维实战--通过role远程部署nginx并配置(8/8)
  • HTB:Active[RE-WriteUP]
  • Go语言中的Select
  • 芯片AI深度实战:进阶篇之vim内verilog实时自定义检视
  • 03链表+栈+队列(D2_栈)
  • Windows 11 应用开发实战指南
  • 【Elasticsearch 】悬挂索引(Dangling Indices)
  • 指针的介绍3后
  • Kafka 日志存储 — 磁盘存储
  • LeetCode:40. 组合总和 II(回溯 + 剪枝 Java)
  • Python3 【高阶函数】水平考试:30道精选试题和答案
  • SOME/IP--协议英文原文讲解4
  • 人工智能如何驱动SEO关键词优化策略的转型与效果提升
  • Unity阿里云OpenAPI 获取 Token的C#【记录】
  • Windows程序设计4:API函数URLDownloadToFile和ShellExecuteEx
  • Python3 【函数】:见证算法的优雅与力量
  • 论文阅读(十三):复杂表型关联的贝叶斯、基于系统的多层次分析:从解释到决策
  • 26.useScript
  • 如何将DeepSeek部署到本地电脑
  • Shell特殊状态变量以及常用内置变量总结
  • Kmesh v1.0 正式发布