惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
Engineering at Meta
Engineering at Meta
D
DataBreaches.Net
Stack Overflow Blog
Stack Overflow Blog
Microsoft Security Blog
Microsoft Security Blog
Y
Y Combinator Blog
B
Blog RSS Feed
GbyAI
GbyAI
P
Proofpoint News Feed
aimingoo的专栏
aimingoo的专栏
MyScale Blog
MyScale Blog
D
Docker
阮一峰的网络日志
阮一峰的网络日志
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Recorded Future
Recorded Future
美团技术团队
The Register - Security
The Register - Security
V
Visual Studio Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
T
Tailwind CSS Blog
爱范儿
爱范儿
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
The Blog of Author Tim Ferriss
博客园 - 司徒正美
量子位
B
Blog
F
Fortinet All Blogs
Martin Fowler
Martin Fowler
博客园 - 【当耐特】
MongoDB | Blog
MongoDB | Blog
A
About on SuperTechFans
I
InfoQ
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
有赞技术团队
有赞技术团队
雷峰网
雷峰网
大猫的无限游戏
大猫的无限游戏
J
Java Code Geeks
L
LangChain Blog
Latest news
Latest news
S
SegmentFault 最新的问题
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Blog — PlanetScale
Blog — PlanetScale
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Cisco Talos Blog
Cisco Talos Blog
F
Full Disclosure
C
Cisco Blogs
D
Darknet – Hacking Tools, Hacker News & Cyber Security
W
WeLiveSecurity
T
Tenable Blog
T
Tor Project blog

博客园 - Yaopengfei

第五节:Claude Code的用法实操汇总 第十五节:LlamaIndex框架使用2() 第十四节:LlamaIndex框架介绍和入门1(基本用法、提示词、节点等) 第三节:Trae的基本使用 和 Skill的详细用法 第二节:Python基础2 第十三节:FastApi入门以及AI智能体案例落地实操 第二节:GitHub Copilot 用法(基于VSCode/VS、添加DeepSeek/千问等任意模型) 第一节:AI工具总览(Copilot、Cursor、Claude Code、OpenCode、Codex、Trae等) 第一节:Python基础1(数据类型、命名规范、输入输出、运算符、类型转换等) 第十节:预检索-索引优化(摘要、父子、假设问题、元数据、混合索引) 第十二节:MinerU处理复制PDF 和 综合性金融案例实战 第十一节:多检索查询、混合检索(多检索+RRF重排)、检索后优化(文档压缩) 第九节:RAG进阶和Advanced RAG简介 博文阅读密码验证 - 博客园 第六节:LangChain框架Model和数据检索详解 第五节:LangChain框架简介和快速入门(模型、模板、解释器、向量、RAG、代理) 第四节:补充pip相关指令大全 第三节:RAG基础(概念、工作流程、文档分块、向量和Embedding、RAG案例等等) 博文阅读密码验证 - 博客园 第一节:Python相关环境安装和配置(Python、PyCharm、Anaconda) 第三十六节:EFCore10.0新增功能和中断性变更 第七节:框架版本大升级(CoreMvc10.x + EFCore10.x) 第五十二节:Core10.0中OpenApi自定义文档(Swagger) 博文阅读密码验证 - 博客园 第三节:C#13、C#14新语法(数字字符串比较、Null分配、扩展成员新写法等等) 第二节:如何理解Embedding以及基于内存库简单实操
第七节:LangChain框架Chain链和Agent代理详解
Yaopengfei · 2026-04-15 · via 博客园 - Yaopengfei

一. Chain链详解

1. 链的基本使用

   为开发更复杂的应用程序,需要使用Chain来链接LangChain中的各个组件和功能,包括模型之间的链接以及模型与其他组件之间的链接

(1) 不用chain代码分享:

查看代码
 # 导入LangChain中的提示模板
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv

load_dotenv()
import os

llm = ChatOpenAI(api_key=os.getenv("api_key"), base_url=os.getenv("base_url"), model='qwen-plus', temperature=0)
# 原始字符串模板
template = "桌上有{num1}个苹果,{num2}个香蕉,四个桃子和 3 本书,一共有几个水果?"
# 创建LangChain模板
prompt_temp = PromptTemplate.from_template(template)
# 根据模板创建提示
prompt = prompt_temp.format(num1=2, num2=5)

# 传入提示,调用模型返回结果 【不用链,需要把prompt传给大模型】
result = llm.invoke(prompt)
print(result.content)

(2) 使用chain代码分享: 

from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
import os
from dotenv import load_dotenv

load_dotenv()
# 模型
llm = ChatOpenAI(api_key=os.getenv("api_key"), base_url=os.getenv("base_url"), model='qwen-plus', temperature=0)
# 模板
template = "桌上有{num1}个苹果,{num2}个香蕉,四个桃子和 3 本书,一共有几个水果?"
# ✅ 新版写法:管道链式调用(取代 LLMChain)
prompt = PromptTemplate.from_template(template)
chain = prompt | llm  # 管道符,新版核心
# 调用
result = chain.invoke({"num1": 2, "num2": 5})
# 输出
print(result.content)

(3) LCEL表达式语言

  LCEL 就致力于消除原型开发与生产部署间的鸿沟 —— 无论是基础的 "提示词 + LLM" 单链结构,还是包含 100 + 步骤的复杂工作流,均可通过同一套语法实现,无需修改代码逻辑。

  即 xxx|xxx|xxx|xxx

代码分享

from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser, JsonOutputParser
from langchain_core.prompts import ChatPromptTemplate
import os

load_dotenv()
# 创建llm模型
llm = ChatOpenAI(api_key=os.getenv("api_key"), base_url=os.getenv("base_url"), model="qwen-plus")
# 创建提示词
prompt = ChatPromptTemplate.from_template("讲一个笑话,关于 {topic}")
# 创建输出解释器
output_parser = StrOutputParser()
# 使用chain链在一起   实现的方法里面都有  runnable   必须是一个可运行单元
chain = prompt | llm | output_parser
print(chain.invoke({"topic": "哈士奇"}))

2. Runnable

  Runnable 接口是 LangChain 0.2 版本后推出的核心抽象层,旨在通过函数式编程模型统一各类 AI 组件的交互方式。它将语言模型(LLM)、链(Chain)、工具调用、数据处理等操作抽象为可组合的 "可运行单元"(Runnable),允许开发者以类似流水线(Pipeline)的方式编排复杂逻辑,而无需关注底层实现细节

(1) 核心特性

image

(2) 主要实现类

  • LangChain 中几乎所有核心组件都实现了 Runnable 接口

image

3. Chain链的调用原理

了解

class Chain():
    def __init__(self, value):
        self.value = value
    def __or__(self, other):
        # 调用 | 运算符  触发的魔法方法
        return other(self.value)

def prompt(text):
    return "请求回答问题:{}".format(text)

aa = Chain('人工智能是什么?')

res = aa | prompt
print(res)

4. Chain的调用方式

(1) invoke调用

 代码分享--前面代码都是通过invoke调用,主要处理单个的输入输出的。

(2) batch调用

   batch方法允许输入列表运行链,一次处理多个输入。 

代码分享

from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os

load_dotenv()

# 创建LLM
llm = ChatOpenAI(api_key=os.getenv("api_key"), base_url=os.getenv("base_url"), model='qwen-plus', temperature=0)
# 构建提示词
template = PromptTemplate(input_variables=["role", "fruit"], template="{role}喜欢吃{fruit}?")
input_list = [{"role": "猪八戒", "fruit": "人参果"}, {"role": "孙悟空", "fruit": "仙桃"}]
# 构建chain链
llm_chain = template | llm

# 调用LLMChain,返回结果  apply
result = llm_chain.batch(input_list)
# print(result)
# print(result[0].content)    #  猪八戒+人参果 相关
print(result[1].content)  #  孙悟空+仙桃 相关

(3) 数学链  【了解】

 LLMMathChain 数学链已经废弃了,下面是使用chain的通用写法。


from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from dotenv import load_dotenv
import os

load_dotenv()

llm = ChatOpenAI(api_key=os.getenv("api_key"), base_url=os.getenv("base_url"), model="qwen-plus")
# 0.3.7 正确写法:直接让模型计算(最简单、稳定、不报错)
prompt = ChatPromptTemplate.from_messages(
    [
        ("system", "你是一个计算器,只返回数学计算结果,不要解释。"),
        ("user", "计算:{question}"),
    ]
)
chain = prompt | llm
# 调用
res = chain.invoke({"question": "5 ** 3 + 100 / 2"})
print("结果:", res.content)

(4) SQL链【了解】

DB结构如下:

image

代码1

"""
  必须先安装:pip install pymysql -i https://pypi.tuna.tsinghua.edu.cn/simple
"""

from langchain_community.utilities import SQLDatabase

# 连接 MySQL 数据库
db_host = "60.xx.xx.80"
db_port = "3306"
db_user = "root"
db_password = "123456"
db_name = "shipdb"
db = SQLDatabase.from_uri(f"mysql+pymysql://{db_user}:{db_password}@{db_host}:{db_port}/{db_name}")

print("哪种数据库:", db.dialect)
print("获取数据表:", db.get_usable_table_names())
# 执行查询
res = db.run("SELECT count(*) FROM userinfo;")
print("查询结果:", res)

代码2

"""
  必须先安装:pip install pymysql -i https://pypi.tuna.tsinghua.edu.cn/simple
"""

from langchain_community.utilities import SQLDatabase
from langchain_openai import ChatOpenAI
from langchain.chains import create_sql_query_chain
from dotenv import load_dotenv
import os

load_dotenv()

# 连接 MySQL 数据库
db_host = "60.xx.xx.xx"
db_port = "3306"
db_user = "root"
db_password = "123456"
db_name = "shipdb"
db = SQLDatabase.from_uri(f"mysql+pymysql://{db_user}:{db_password}@{db_host}:{db_port}/{db_name}")

# 加上大模型
# 创建模型对象
llm = ChatOpenAI(api_key=os.getenv("api_key"), base_url=os.getenv("base_url"), model='qwen-plus')
chain = create_sql_query_chain(llm=llm, db=db)
# 限制使用的表
SQL = chain.invoke({"question": "哪些姓氏最多", "table_names_to_use": ["userinfo"]})
print(SQL)
print("查询结果:", db.run(SQL))

"""
生成的SQL如下:
    SELECT SUBSTRING(`userName`, 1, 1) AS `surname`, COUNT(*) AS `count`
    FROM userinfo
    WHERE `userName` IS NOT NULL AND TRIM(`userName`) != ''
    GROUP BY `surname`
    ORDER BY `count` DESC
    LIMIT 5;
"""

运行结果:

image

二. 案例实操

1. Tavily在线搜索

  • 访问Tavily(用于在线搜索)注册账号并登录,获取API 密钥

  • TAVILY_API_KEY申请:https://tavily.com/

代码分享:

"""
  新版本是单独的:  pip install langchain-tavily -i https://pypi.tuna.tsinghua.edu.cn/simple
"""

import os
from dotenv import load_dotenv

# 👇 新版导入(无警告)
from langchain_tavily import TavilySearch

load_dotenv()

# 查询 Tavily 搜索 API 并返回 json 的工具
search = TavilySearch(tavily_api_key=os.getenv("tavily_key"))
# 执行查询   能调用invoke
res = search.invoke("目前市场上iphone16的售价是多少?")
print(res)

三. Agent代理详解

1.  概述

 Agent代理的核心思想:使用LLM来选择要采取的一系列动作。在链中,动作序列是硬编码的。

 在代理中,语言模型用作推理引擎来确定要采取哪些动作以及按什么顺序进行因此,在LangChain中,Agent代理就是使用语言模型作为推理引擎,让模型自主判断、调用工具和决定下一步行动

 Agent代理像是一个多功能接口,能够使用多种工具,并根据用户输入决定调用哪些工具,同时能够将一个工具的输出数据作为另一个工具的输入数据

注意:在新版本当中langchain关于agent的创建都集成给了langgraph,目前这个内容作为了解

0.3.x版本agent代码(多了个agent_executor)

查看代码
 import os
from langsmith import Client
from langchain_tavily import TavilySearch
from langchain_community.document_loaders import WebBaseLoader
from langchain_community.vectorstores import FAISS
from langchain_community.embeddings import DashScopeEmbeddings
from langchain_openai import ChatOpenAI
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_core.tools.retriever import create_retriever_tool
from langchain_classic.agents import create_openai_functions_agent
from langchain_classic.agents import AgentExecutor
from dotenv import load_dotenv

load_dotenv()


# 1.初始化 Tavily 搜索工具
search = TavilySearch(tavily_api_key=os.getenv("tavily_key"))

# 2. 从网页抓取内容,分割、向量化、存入FAISS中
loader = WebBaseLoader("https://news.qq.com/rain/a/20240920A07Y5Y00")
docs = loader.load()
documents = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200).split_documents(docs)
# 向量化
vector = FAISS.from_documents(
    documents,
    DashScopeEmbeddings(dashscope_api_key=os.getenv('api_key')),
)
retriever = vector.as_retriever()  # 创建检索器
# 创建检索工具(从网页中获取,并存入向量DB中 )
retriever_tool = create_retriever_tool(
    retriever,
    "iPhone_price_search",
    "当前工具用于查询苹果16手机的售价, 其他任何版本都不能使用此工具, 苹果17不能使用此工具",
)
# 3. 将Tavily搜索和向量检索都合并到tools中
tools = [search, retriever_tool]

# 4.初始化大模型
llm = ChatOpenAI(api_key=os.getenv("api_key"), base_url=os.getenv("base_url"), model=os.getenv("model1"))
hub = Client()
# # https://smith.langchain.com/hub/hwchase17/openai-functions-agent
prompt = hub.pull_prompt("hwchase17/openai-functions-agent")

# 5. 构建agent
agent = create_openai_functions_agent(llm, tools, prompt)
# 6. 构建agent协调器
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)


# 下面测试出来的结论:只有iphone16相关的内容,走的是从索引库中获取,其它的都是调用搜索工具进行搜索,二者最后都是把结果返回给LLM
#  让LLM给出最后的答案
#  input哪里来的: 上面prompt模板中定义了input变量
# print(agent_executor.invoke({'input':"目前市场上苹果手机16的售价是多少?"}))
# print(agent_executor.invoke({'input': "目前市场上苹果17的售价是多少?"}))
print(agent_executor.invoke({'input': "2024年美国总统谁选上了"}))

1.x版本agent代码(删掉了agent_executor)

"""
   此处需要注意:下面的代码写法,要求 langgraph > 1.0.10
"""

from langchain.agents import create_agent
from langchain_core.tools import Tool
from langchain_tavily import TavilySearch
from langchain_openai import ChatOpenAI

import os
from dotenv import load_dotenv

load_dotenv()


# 定义查询订单状态的函数
def query_order_status(order_id):
    if order_id == "1024":
        return "订单 1024 的状态是:已发货,预计送达时间是 3-5 个工作日。"
    else:
        return f"未找到订单 {order_id} 的信息,请检查订单号是否正确。"


# 定义退款政策说明函数
def company_refund_policy(company_name):
    print(company_name)
    if company_name == "tom":
        return "tom公司的退款政策是:在购买后7天内可以申请全额退款,需提供购买凭证。"
    else:
        print('输入有误')


# 定义查询年龄的函数
def get_age(name):
    if name == "tom":
        print(name)
        return "我的年龄是56岁!"
    else:
        print('输入有误')


# 1. 初始化工具
# 这是另外一种创建tool的方式,之前讲的的是装饰器模式@tool,如上述02
tools = [
    TavilySearch(max_results=1, tavily_api_key=os.getenv("tavily_key")),
    Tool(
        name="queryOrderStatus",
        func=query_order_status,
        description="根据订单ID查询订单状态",
        args={"order_id": "订单的ID"},
    ),
    Tool(
        name="companyRefundPolicy",
        func=company_refund_policy,
        description="查询某某公司退款政策详细内容",
        args={"company_name": "公司名称"},
    ),
    Tool(
        name="getAge",
        func=get_age,
        description="查询tom年龄大小",
        args={"name": "年龄大小"},
    ),
]
# 2. 初始化LLM
llm = ChatOpenAI(api_key=os.getenv("api_key"), base_url=os.getenv("base_url"), model=os.getenv("model1"))
# 3. 初始化agent(新版不需要AgentExecutor)
agent = create_agent(model=llm, tools=tools, system_prompt="你是一个客服助手,使用工具回答问题。")


# 4. 定义了3个query,分别提交给agent调用
# 结果:前两个调用了对应的函数,第3个调用了Tavily,最终都是把结果返回给了LLM,由LLM给出最后的答案
queries = ["请问订单1024的状态是什么?", "请问tom公司退款政策是什么?", "2024年谁胜出了美国总统的选举"]
for myInput in queries:
    print('客户提问:' + myInput)
    inputs = {"messages": [{"role": "user", "content": myInput}]}
    result = agent.invoke(inputs)
    print(result['messages'][-1].content)

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。