前情提要
在 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)