“LangChain代码解析:新手友好,一起深入探索AI编程的魅力

代码

我们将在colab调试我们的代码,colab是Google推出的在线机器学习平台,除了一些模型训练、比较费GPU的任务外,我的学习型demo都可以在这里free跑起来。

image.png

安装依赖

!pip install -q -U langchain langchain_openai langgraph google-search-results

  • 首先!是什么意思呢?pip install 是安装依赖包,我们在写python的时候,好像前面没有加过!。这里的!是指在特定交互环境中(如 Jupyter Notebook、JupyterLab 或 Google Colab)的命令执行标记。用于告诉该环境应当以系统shell来执行紧跟在其后的命令,而不是将其当作Python代码来执行。

  • -q -U 是什么意思

    -q 只显示 错误信息,如果没有,就不显示,让安装以安静模式运行 -U update 表示安装最新版本的包

  • langchain_openai

    我们在玩node的时候,会到npmjs.org去查看包的详细信息。当我们用pip安装包的时候,可以到pypi.org/,去看。

    langchain框架负责核心模块,langchain_openaiLangChain集成了 OpenAI SDK的调用。

    langgraph是新功能,为langchain带来了多代理的编程方式 google-search-results 来自serapi

  • 注册serapi, 并拿到sdk

    我们在开发生成式应用时,多次使用到serapi先从google搜索中拿到数据,再去生成。

  • 环境变量设置

import os # os 模块提供了与操作系统相关的接口, 比如文件、目录,环境变量、进程管理等 这里主要使用环境变量
from google.colab import userdata 

os.environ['SERPAPI_API_KEY'] = userdata.get('GOOGLE_API_KEY') os.environ['OPENAI_API_KEY'] = userdata.get('OPENAI_API_KEY') os.environ["LANGCHAIN_TRACING_V2"] = "true" 
# 项目名
os.environ["LANGCHAIN_PROJECT"] = "LangGraph" 
# LANGCHAIN_API_KEY
os.environ["LANGCHAIN_API_KEY"] = userdata.get('LANGSMITH_API_KEY')


colab 为我们提供了userdata, 统一存放OPENAI_API_KEYGOOGLE_API_KEY等,我们可以在任一notebook里根据key取出userData里的值。

image.png

image.png

  • LangSmith

    是一个用于构建生产级 LLM 应用程序的平台,用于交付,可以来到LangSmith注册拿到key, 它的使用我们后续开新的文章再细讲。

  • 搜索试运行

from langchain_community.utilities import SerpAPIWrapper
search = SerpAPIWrapper() 
search.run("Obama's first name?")

langchain_communitylangchain和一些第三方常用库结合的模块。当我们安装了langchaingoogle-search-results后,我们就可以调用langchain_community.utilities提供的SerpAPIWrapper来做搜索工作。可以这样理解,langchain_community.utilities将第三方工具封装得更适合langchain业务,比如在上面的代码里,实例化后的search是可以run的。所以,我们有langchain-opnai, 有SerpAPIWrapper, 第三方工具库由langchain_community.utilities提供。

Barack Hussein Obama II

  • 引入相应的模块
import functools, operator, requests, os, json 
from langchain.agents import AgentExecutor, create_openai_tools_agent 
from langchain_core.messages import BaseMessage, HumanMessage 
from langchain.output_parsers.openai_functions import JsonOutputFunctionsParser 
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder 
from langgraph.graph import StateGraph, END 
from langchain.tools import tool 
from langchain_openai import ChatOpenAI 
from typing import Annotated, Any, Dict, List, Optional, Sequence, TypedDict

首先,我们在标准库中引入functools, 它提供了一些函数式编程工具,比如等下要用到的装饰器;operator包含了很多预定义的函数,如算术运算add等,高阶函数map等;requests用于发送请求。

接着,我们从agents模块引入 AgentExecutorcreate_openai_tools_agentAgentExecutorLangChain框架中扮演着核心角色,它负责执行和管理不同类型的Agent, 并协调它们之间的交互。create_openai_tools_agent用于创建一个与OpenAI服务集成的Agent。让我们以Agent的方式调用OpenAI。

紧接着,langchain_core提供了相应角色message类,这里引入了BaseMessageHumanMessage。BaseMessage是基类,定义了消息的基本结构和行为,HumanMessage可以用来表示用户的chat。

再者,from langchain.output_parsers.openai_functions import JsonOutputFunctionsParser 输出格式化我们使用了JsonOutputFunctionsParser。LLM返回的是文本,output_parsers格式器提供了openai_functions,JsonOutputFunctionsParser函数会将文本转成json格式的输出。

又有 from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder langchain_coreprompts模块提供了MessagesPlaceholder和ChatPromptTemplate,用于Prompt设计。

接下来, from langgraph.graph import StateGraph, END LangGraph出场了,它是LangChain新功能,让我们从graph里引入StateGraph和结束结点

最后 from langchain_openai import ChatOpenAI在 LangChain 框架中引入一个与 OpenAI 的聊天模型,再后面是一堆的类型维束引入。

  • 实例化LLM
llm = ChatOpenAI(model="gpt-4-turbo-preview")

大家也可以使用gpt-3.5-turbo, 但是在处理一些复杂的agent时,gpt-4表现更优异。

  • 定义搜索函数
from langchain_core.messages import ( AIMessage, BaseMessage, ChatMessage, FunctionMessage, HumanMessage, SystemMessage ) 

@tool("web_search") 
def web_search(query: str) -> str: 
    """Search with Google SERP API by a query""" 
    search = SerpAPIWrapper() 
    return search.run(query)

Message 的类型真多啊,这个交给下次开篇讲,这里我们focus等下生成agent的web_search函数。functools提供的装饰器模式,将web_search装饰成为能够搜索的工具函数。这个函数负责调用SerpAPIWrapper,根据传入的查询参数,拿到google的搜索结果。

  • twitter_writer 工具函数
@tool("twitter_writer") 
def write_tweet(content: str) -> str: 
"""Based a piece of content, write a tweet.""" 
    chat = ChatOpenAI() 
    messages = [ 
    SystemMessage( content="You are a Twitter account operator." 
    " You are responsible for writing a tweet based on the content given." 
    " You should follow the Twitter policy and make sure each tweet has no more than 140 characters." ), 
    HumanMessage( content=content ), ]
    response = chat(messages) 
    return response.content

装饰器仍然是帮助函数成为创建agent的工具函数。函数通过ChatOpenAI提供的聊天实例,然后准备好消息数组。SystemMessage 是聊天开始前的系统设置,在这里指定了它的角色是Twitter writter, 任务是基于给定任务写一篇tweet, 要求不超过140字。HummanMessage 即用户聊天信息,content是传进来的内容,接着 response = chat(messages) 让聊天模型运行, 并返回结果。这个工具函数主要负责生成。从这里可以看出,twitter的生成是以聊天模型调用的方式生成。

  • GraphState
class AgentState(TypedDict): 
# The annotation tells the graph that new messages will always 
# be added to the current states 
    messages: Annotated[Sequence[BaseMessage], operator.add] 
# The 'next' field indicates where to route to next 
    next: str


langgraph的第一个核心是graphstate, 这个状态标记当前的应用状态。 typing 是 Python 的一个标准库模块,用于提供Type Hints功能。AgentState是一个基于TypedDict的类,里面包含相应的字段。

  • 创建一个agent
def create_agent(llm: ChatOpenAI, tools: list, system_prompt: str): 
    prompt = ChatPromptTemplate.from_messages( [ ( "system", system_prompt, ), 
        MessagesPlaceholder(variable_name="messages"),            MessagesPlaceholder(variable_name="agent_scratchpad"), ] ) 
    agent = create_openai_tools_agent(llm, tools, prompt) executor = AgentExecutor(agent=agent, tools=tools) 
    return executor 
def agent_node(state, agent, name): 
    result = agent.invoke(state) return {"messages": [HumanMessage(content=result["output"], name=name)]}


封装了一个create_agent方法,参数为llm、tools、system_prompt。我们这里要做的是一个聊天agent。我们准备了prompt, 调用ChatPromptTemplate的from_messages方法。调用create_openai_tools_agent方法生成聊天agent,接受了参数分别是llm,tools数组, prompt。返回AgentExectutor的实例。

  • supervisor_chain
# 两个agent
members = ["Search_Engine", "Twitter_Writer"]


system_prompt = ( 
"You are a supervisor tasked with managing a conversation between the" 
" following workers: {members}. Given the following user request," 
" respond with the worker to act next. Each worker will perform a"
" task and respond with their results and status. When finished," 
" respond with FINISH." )


在这个系统prompt里,我们首先指定它是一个监管上面两个agent的supervisor代理。

options = ["FINISH"] + members


function_def = { "name": "route", "description": "Select the next role.", "parameters": { "title": "routeSchema", "type": "object", "properties": { "next": { "title": "Next", "anyOf": [ {"enum": options}, ], } }, "required": ["next"], }, }


prompt = ChatPromptTemplate.from_messages( [ ("system", system_prompt), MessagesPlaceholder(variable_name="messages"), ( "system", "Given the conversation above, who should act next?" " Or should we FINISH? Select one of: {options}", ), ] ).partial(options=str(options), members=", ".join(members))

supervisor_chain = ( prompt | llm.bind_functions(functions=[function_def], function_call="route") | JsonOutputFunctionsParser() )


  • 生成相应的agent和节点
# 调用create_agent方法,tool 为web_search, prompt 给的身份是web 搜索引擎
search_engine_agent = create_agent(llm, [web_search], "You are a web search engine.") 
# 搜索引擎节点 
functools.partial会返回一个对象,它预填了agent_node函数的部分参数,agent为 search_engine_agent, 名字为Search_Engine
search_engine_node = functools.partial(agent_node, agent=search_engine_agent, name="Search_Engine") 
# twitter 写作agent
twitter_operator_agent = create_agent(llm, [write_tweet], "You are responsible for writing a tweet based on the content given.") 
# twitter写作节点
twitter_operator_node = functools.partial(agent_node, agent=twitter_operator_agent, name="Twitter_Writer") 
# 实例化StateGraph, 将上面的AgentState 作为状态
workflow = StateGraph(AgentState) 
# 给工作流添加工作节点Search_Engine和Twitter_Writer
workflow.add_node("Search_Engine", search_engine_node) workflow.add_node("Twitter_Writer", twitter_operator_node) 
# 最后再添加监督节点,它会看在每个工作节点的状态
workflow.add_node("supervisor", supervisor_chain)


  • 添加边
for member in members: 
    workflow.add_edge(member, "supervisor") 
    # 条件边
    conditional_map = {k: k for k in members} 
    # 是否结束
    conditional_map["FINISH"] = END 
    # 给监管节点添加条件边 加上supervisor上,它来决定
    # lambda x: x["next"]  去看在节点的next 值 是多少,下一步做什么
    workflow.add_conditional_edges("supervisor", lambda x: x["next"], conditional_map) 
    # 将supervisor 添加为初始点
    workflow.set_entry_point("supervisor") 
    # compile 编译生成graph
    graph = workflow.compile()


添加完后如图 image.png

  • 给任务,并监听状态
# graph.stream是一个流式接口,遍历所有的节点,拿到输出信息
for s in graph.stream( 
    { 
        "messages": [ 
        # 使用HumanMesasage 代表用户发表任务
            HumanMessage(content="Write a tweet about LangChain news") ]
    } 
): 
    # 如果没有__end__ 就输出反馈
    if "__end__" not in s: 
        print(s) 
        print("----")


总结

静下心来,分析了一版LangChain关于LangGraph的代码,对Prompt、Agent的理解更深入了。

LangGraph还是不如AutoGen 聊天式多代理好理解,代理间的聊天是用chatOpenAI解决的,代理间的执行顺序是由边和条件边来处理的,而任务状态由grapState来搞定。

在这里插入图片描述

如何学习AI大模型?

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

在这里插入图片描述

第一阶段: 从大模型系统设计入手,讲解大模型的主要方法;

第二阶段: 在通过大模型提示词工程从Prompts角度入手更好发挥模型的作用;

第三阶段: 大模型平台应用开发借助阿里云PAI平台构建电商领域虚拟试衣系统;

第四阶段: 大模型知识库应用开发以LangChain框架为例,构建物流行业咨询智能问答系统;

第五阶段: 大模型微调开发借助以大健康、新零售、新媒体领域构建适合当前领域大模型;

第六阶段: 以SD多模态大模型为主,搭建了文生图小程序案例;

第七阶段: 以大模型平台应用与开发为主,通过星火大模型,文心大模型等成熟大模型构建大模型行业应用。

在这里插入图片描述

👉学会后的收获:👈
• 基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;

• 能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;

• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;

• 能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。

在这里插入图片描述

1.AI大模型学习路线图
2.100套AI大模型商业化落地方案
3.100集大模型视频教程
4.200本大模型PDF书籍
5.LLM面试题合集
6.AI产品经理资源合集

👉获取方式:
😝有需要的小伙伴,可以保存图片到wx扫描二v码免费领取【保证100%免费】🆓

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员辣条

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值