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.rhkb.cn/news/9399.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】1.20 极值追踪:高效获取数据特征的秘诀

1.20 极值追踪:高效获取数据特征的秘诀 1.20.1 目录 #mermaid-svg-RBxy2YCCN23ydzFu {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-RBxy2YCCN23ydzFu .error-icon{fill:#552222;}#mermaid-svg-RBxy2YC…

Vscode的AI插件 —— Cline

简介 vscode的一款AI辅助吃插件,主要用来辅助创建和编辑文件,探索大型项目,使用浏览器并执行终端命令(需要多个tokens),可以使用模型上下文协议(MCP)来创建新工具并扩展自己(比较慢…

C++ unordered_map和unordered_set的使用,哈希表的实现

文章目录 unordered_map,unorder_set和map ,set的差异哈希表的实现概念直接定址法哈希冲突哈希冲突举个例子 负载因子将关键字转为整数哈希函数除法散列法/除留余数法 哈希冲突的解决方法开放定址法线性探测二次探测 开放定址法代码实现 哈希表的代码 un…

c#使用log4Net配置日志文件

1.# 写一个通用类 LogHelper using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using log4net;namespace WindowsFormsApplication22 {public class LogHelper{static ILog mylog LogManager.GetLogge…

WebSocket 详解:全双工通信的实现与应用

目录 一、什么是 WebSocket?(简介) 二、为什么需要 WebSocket? 三、HTTP 与 WebSocket 的区别 WebSocket 的劣势 WebSocket 的常见应用场景 WebSocket 握手过程 WebSocket 事件处理和生命周期 一、什么是 WebSocket&#xf…

Qt Ribbon使用实例

采用SARibbon创建简单的ribbon界面 实例代码如下所示&#xff1a; 1、头文件&#xff1a; #pragma once #include <SARibbonBar.h> #include "SARibbonMainWindow.h" class QTextEdit; class SAProjectDemo1 : public SARibbonMainWindow { Q_OBJECT pub…

认识小程序的基本组成结构

1.基本组成结构 2.页面的组成部分 3.json配置文件 4.app.json文件(全局配置文件&#xff09; 5.project.config.json文件 6.sitemap.json文件 7.页面的.json配置文件 通过window节点可以控制小程序的外观

JVM--类加载器

概念 类加载器&#xff1a;只参与加载过程中的字节码获取并加载到内存中的部分&#xff1b;java虚拟机提供给应用程序去实现获取类和接口字节码数据的一种技术&#xff0c;也就是说java虚拟机是允许程序员写代码去获取字节码信息 类加载是加载的第一步&#xff0c;主要有以下三…

51单片机开发:定时器中断

目标&#xff1a;利用定时器中断&#xff0c;每隔1s开启/熄灭LED1灯。 外部中断结构图如下图所示&#xff0c;要使用定时器中断T0&#xff0c;须开启TE0、ET0。&#xff1a; 系统中断号如下图所示&#xff1a;定时器0的中断号为1。 定时器0的工作方式1原理图如下图所示&#x…

Greenplum临时表未清除导致库龄过高处理

1.问题 Greenplum集群segment后台日志报错 2.回收库龄 master上执行 vacuumdb -F -d cxy vacuumdb -F -d template1 vacuumdb -F -d rptdb 3.回收完成后检查 仍然发现segment还是有库龄报警警告信息发出 4.检查 4.1 在master上检查库年龄 SELECT datname, datfrozen…

小程序-视图与逻辑

前言 1. 声明式导航 open-type"switchTab"如果没有写这个&#xff0c;因为是tabBar所以写这个&#xff0c;就无法跳转。路径开始也必须为斜线 open-type"navigate"这个可以不写 现在开始实现后退的效果 现在我们就在list页面里面实现后退 2.编程式导航…

Kotlin开发(六):Kotlin 数据类,密封类与枚举类

引言 想象一下&#xff0c;你是个 Kotlin 开发者&#xff0c;敲着代码忽然发现业务代码中需要一堆冗长的 POJO 类来传递数据。烦得很&#xff1f;别急&#xff0c;Kotlin 贴心的 数据类 能帮你自动生成 equals、hashCode&#xff0c;直接省时省力&#xff01;再想想需要多种状…

games101-作业2

图形管线 Vertex Processing 对顶点进行加工&#xff0c;使其变换到屏幕空间坐标。 Triangle Processing 将加工后的顶点组装成三角形&#xff0c;用于下一步的光栅化。 void rst::rasterizer::draw(pos_buf_id pos_buffer, ind_buf_id ind_buffer, col_buf_id col_buffer, Pr…

Baklib引领企业内容中台建设的新思路与应用案例

内容概要 在数字化转型的浪潮中&#xff0c;内容中台的概念逐渐成为企业实现高效运营的重要基础。内容中台不仅是信息资产的集中管理平台&#xff0c;更是企业在应对快速变化市场需求时的一种敏捷响应机制。通过搭建内容中台&#xff0c;企业能够有效整合各类资源&#xff0c;…

准备知识——旋转机械的频率和振动基础

旋转频率&#xff0c;也称为转速或旋转速率&#xff08;符号ν&#xff0c;小写希腊字母nu&#xff0c;也作n&#xff09;&#xff0c;是物体绕轴旋转的频率。其国际单位制单位是秒的倒数(s −1 )&#xff1b;其他常见测量单位包括赫兹(Hz)、每秒周期数(cps) 和每分钟转数(rpm)…

Java 大视界 -- Java 大数据在生物信息学中的应用与挑战(67)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

【NLP251】NLP RNN 系列网络

NLP251 系列主要记录从NLP基础网络结构到知识图谱的学习 &#xff11;.原理及网络结构 &#xff11;.&#xff11;&#xff32;&#xff2e;&#xff2e; 在Yoshua Bengio论文中( http://proceedings.mlr.press/v28/pascanu13.pdf )证明了梯度求导的一部分环节是一个指数模型…

Unbutu虚拟机+eclipse+CDT编译调试环境搭建

问题1: 安装CDT&#xff0c;直接Help->eclipse Market space-> 搜cdt , install&#xff0c;等待重启即可. 问题2&#xff1a;C变量不识别vector ’could not be resolved 这是库的头文件没加好&#xff0c;右键Properties->C Build->Enviroment&#xff0c;增加…

关于opencv环境搭建问题:由于找不到opencv_worldXXX.dll,无法执行代码,重新安装程序可能会解决此问题

方法一&#xff1a;利用复制黏贴方法 打开opencv文件夹目录找到\opencv\build\x64\vc15\bin 复制该目录下所有文件&#xff0c;找到C:\Windows\System32文件夹&#xff08;注意一定是C盘&#xff09;黏贴至该文件夹重新打开VS。 方法二&#xff1a;直接配置环境 打开opencv文…

OpenEuler学习笔记(十五):在OpenEuler上搭建Java运行环境

一、在OpenEuler上搭建Java运行环境 在OpenEuler上搭建Java运行环境可以通过以下几种常见方式&#xff0c;下面分别介绍基于包管理器安装OpenJDK和手动安装Oracle JDK的步骤。 使用包管理器安装OpenJDK OpenJDK是Java开发工具包的开源实现&#xff0c;在OpenEuler上可以方便…