LangChain P2 | 给LangChain装上手脚[MacOS]

前情提要

在 P1 中,我们已经学会了用 LCEL 搭一条最简单的链

python 复制代码
from langchain_core.output_parsers import StrOutputParser
from langchain_deepseek import ChatDeepSeek

llm = ChatDeepSeek(model="deepseek-v4-flash")
parser = StrOutputParser()
chain = llm | parser
print(chain.invoke("你好"))

创建上面这样一条链,这条链能跑,但有个问题------模型只会说,不会做。

你问它"今天昆明天气怎么样?",它只能回答"抱歉,我无法获取实时数据。"

在本篇博客中,我们就来解决这个LLM的痛点:我们会学会三种调用大模型的姿势,然后给 AI 上手脚,让它不再只有大脑,即工具,让它真正能动起来。

三种姿势调用大模型

在LangChain中,我们有多种方式来定义一个LLM,不同的姿势,适用于不同的环境,在本小节中,我们会学习到不同的调用方式

方式1:ChatOpenAI

这是最直接的用法,指定模型名就行。不仅支持 OpenAI,也兼容 DeepSeek 等国内厂商(因为它们都兼容 OpenAI 的 API 格式)。

不过需要注意的是,如果我们使用ChatOpenAI来调用非OpenAI的AI,我们需要引入一些其它的参数,此处我们以deepseek为例

python 复制代码
import os

from langchain_community.chat_models import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser

llm = ChatOpenAI(
    model="deepseek-v4-flash",
    base_url="https://api.deepseek.com",
    api_key=os.getenv("DEEPSEEK_API_KEY"),  # 从环境变量读取
)
paser = StrOutputParser()
chain = llm | paser
print(chain.invoke("你好"))

我们可以看到,我们需要单独给出这个厂商的base_url和api_key,api_key我们都知道,是从环境变量中获取到的,在P1里我们就已经讲过了,那么base_url是怎么来的呢?

让我们看到deepseek的接口文档,我们可以看到,在文档中都是给出来了的,所以我们在调用一个AI的时候,可以多看看它的API文档

适用场景:你就用一家厂商,代码写死就行

方式2:init_chat_model

一个工厂函数,模型名换一下就能切换厂商,不用改代码结构。我们同样用一个例子来看一下

python 复制代码
from langchain.chat_models import init_chat_model

llm = init_chat_model(
    model="deepseek-v4-flash",
    model_provider="deepseek"
)
llm.invoke("你好").pretty_print()

我们可以看到,在这个模式下,参数都是一样的,我们只需要修改里面的内容就可以实现调用不同的模型

适用场景:你要对比不同模型效果,或者项目需要灵活切换厂商

方式3:ChatOllama本地部署

模型跑在自己机器上,不依赖网络,数据不出门。

不过这个会涉及到本地部署的操作,我们这里就不多赘述了,大概给大家一个代码例子

python 复制代码
from langchain_ollama import ChatOllama

model = ChatOllama(
    model="llama3",
    base_url="http://localhost:11434",
)
print(model.invoke("你是谁?").content)

适用场景:离线环境、数据敏感场景、想省 API 费用

工具(Tools)

一句人话解释,为什么需要工具:大模型只会说话不会动手------它查不了天气、读不了数据库、算不了复杂数学,而工具就是 AI 的"外挂",让它能干"人"的活。

那么,我们到底要怎样才可以定义并用上工具呢?接下来,我们就会通过逐步实现一个可以进行运算的大模型来展示

创建工具

LangChain 提供了 '@tool'装饰器,把普通 Python 函数一键变成工具。

args_schema

python 复制代码
from langchain_core.tools import tool

@tool
def add(a: int, b: int) -> int:
    """两数相加
    Args:
        a: 第一个整数
        b: 第二个整数
    Returns:
        两数之和
    """
    return a + b

注意:函数名 = 工具名,文档字符串 = 工具描述,缺一不可!模型就是通过名称和描述来理解"这个工具是干什么的"。

💡 一个小彩蛋我们来讲讲,描述这里发生了什么

LangChain 自动把你的函数名、文档字符串、参数类型打包成 "JSON Schema" 发给模型

模型就是通过这个 Schema 来理解"add 是加法工具,参数 a 和 b 都是整数"。

因此工具描述是非常重要的,最好是像文章示例这样,把用途,参数,返回都写上去,帮助大模型更好理解工具的作用,不过是,除了这样的描述方式外,还有三种其它方式,我们简述一下

Pydantic

python 复制代码
from dataclasses import Field

from langchain_core.tools import tool
from pydantic import Field, BaseModel


class addInput(BaseModel):
    a: int = Field(description="第一个整数")
    b: int = Field(description="第二个整数")

@tool(args_schema=addInput)
def add(a: int, b: int) -> int:
    """两数之和"""
    return a + b

Annotated

python 复制代码
from langchain_core.tools import tool
from typing_extensions import Annotated


@tool
def add(a: Annotated[int, "第一个整数"], b: Annotated[int, "第二个整数"]) -> int:
    """两数之和"""
    return a + b

StructuredTool

python 复制代码
from langchain_core.tools import StructuredTool

def add(a: int, b: int) -> int:
    return a + b

add_tool = StructuredTool.from_function(
    func=add,
    name="add",
    description="两数之和"
)

绑定工具

工具定义好了,怎么让模型知道它可以用?用 'bind_tools()' 绑定工具。我们依旧用一个例子来帮助大家理解

python 复制代码
from langchain.chat_models import init_chat_model
from langchain_core.tools import tool

@tool
def add(a: int, b: int) -> int:
    """两数相加
    Args:
        a: 第一个整数
        b: 第二个整数
    Returns:
        两数之和
    """
    return a + b

llm = init_chat_model(
    model="deepseek-v4-flash",
    model_provider="deepseek"
)
llm_with_tools = llm.bind_tools([add])    # 绑定add工具
llm.invoke("3 + 5等于多少").pretty_print()

通过上述一个代码,我们就实现了一个简易的可以调用加法工具的大模型

注意!bind_tools() 这个方法里面需要传入工具列表,因此哪怕只有一个工具,也需要以列表形式存在

实战小练习

我们来实现一个输入城市名称就可以输出实时天气的工具

python 复制代码
from langchain_deepseek import ChatDeepSeek

import requests
from langchain_core.tools import tool


# 定义查询天气工具
@tool
def get_weather(city: str) -> str:
    """查询指定城市的实时天气。
    Args:
        city: 城市中文名称,如"昆明"、"北京"
    """
    resp = requests.get(
        f"https://wttr.in/{city}?format={city}今日:%t, %C&lang=zh",
        timeout=5,
    )
    return resp.text
llm = ChatDeepSeek(model="deepseek-v4-flash")    # 定义llm
llm_with_tools = llm.bind_tools([get_weather])   # 绑定工具
msg = llm_with_tools.invoke("北京")
tool_call = msg.tool_calls[0]                    # 手动调用一下工具
result = get_weather.invoke(tool_call["args"])
print(result)
相关推荐
齐 飞32 分钟前
LangChain快速入门-03Retrieval(上)
langchain
怕浪猫1 小时前
第9章 实战项目一:智能数据分析Agent
langchain·aigc·ai编程
invicinble5 小时前
总结一下LangChain+LangGraph这套体系
langchain
糖果店的幽灵5 小时前
langchain 所有内置中间件最详细解析
中间件·langchain
阿拉斯攀登7 小时前
Agent 框架对比:LangChain / AutoGPT / CrewAI
人工智能·langchain·agent·rag·function
中微极客8 小时前
LangChain 0.3实战:企业级RAG与多Agent架构解析
人工智能·langchain·新人首发
喵叔哟18 小时前
第一周概述
langchain·实战
RZhLyRaHv1 天前
LangChain教程-4、构建简易智能 PPT 生成器
人工智能·langchain·powerpoint
AI-好学者1 天前
RAG知识点_3_高级实践
人工智能·ai·架构·langchain·ai编程
大流星2 天前
LangChainJs之基础模型(一)
javascript·langchain