模型 I/O 与 Tools

面试官:「LangChain 支持哪些模型?」

你:「OpenAI、Anthropic、Google、Azure... 基本上主流的都支持。」

面试官:「Chat Model 和普通 LLM 有什么区别?」

你:「Chat Model 输入输出是消息对象,LLM 是纯文本...」

面试官:「流式输出怎么实现?」

🤔 流式输出是提升用户体验的关键。这一章深入 Model 层,带你搞懂消息格式、流式回调、Tools 的本质。

4.1 LLMs vs Chat Model

LangChain 支持两种主要的模型类型:LLMs(通用语言模型)和 Chat Models(对话模型)。

🔍 两种模型的区别

特性 LLM Chat Model
输入格式 字符串文本 消息列表
输出格式 字符串文本 AI 消息对象
API 设计 llm.invoke("Hello") chat.invoke([HumanMessage("Hello")])
适用场景 文本补全、生成 对话系统
典型模型 text-davinci-003 gpt-4, claude-3, gemini-pro
图 4-1:LLM vs Chat Model 对比
LLM 输入 Input: "Translate to French: Hello" 输出 Output: "Bonjour" llm.invoke("Hello") VS Chat Model 输入 Input: Human: "Hello" System: "翻译成法语" 输出 Output: AIMessage("Bonjour") chat.invoke([...messages])

4.1.1 代码对比

python llm_vs_chat.py
# LLM 调用
from langchain_openai import OpenAI

llm = OpenAI(model="gpt-3.5-turbo-instruct")
response = llm.invoke("翻译成法语:Hello")
print(response)  # "Bonjour"

# Chat Model 调用
from langchain_openai import ChatOpenAI

chat = ChatOpenAI(model="gpt-4o-mini")
response = chat.invoke([
    SystemMessage(content="你是一个翻译专家"),
    HumanMessage(content="翻译成法语:Hello")
])
print(response.content)  # "Bonjour"
💡 推荐

在大多数现代应用场景中,推荐使用 Chat Model,因为它更符合对话交互的习惯,支持多轮对话,并且对上下文理解更好。

4.2 Chat Model 使用详解

4.2.1 基础调用

python basic_chat.py
from langchain_openai import ChatOpenAI
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage

chat = ChatOpenAI(model="gpt-4o-mini", temperature=0.7)

# 简单调用
response = chat.invoke([HumanMessage(content="你好")])
print(response.content)  # AI 的回复

# 带系统消息
response = chat.invoke([
    SystemMessage(content="你是一个幽默的助手"),
    HumanMessage(content="讲个笑话")
])
print(response.content)

4.2.2 模型参数

参数 说明 取值范围 默认值
temperature 控制随机性 0.0 - 2.0 0.7
max_tokens 最大输出 token 数 正整数 模型默认值
top_p 核采样概率 0.0 - 1.0 1.0
stop 停止序列 字符串列表 None
frequency_penalty 频率惩罚 -2.0 - 2.0 0
presence_penalty 存在惩罚 -2.0 - 2.0 0
python model_params.py
from langchain_openai import ChatOpenAI

chat = ChatOpenAI(
    model="gpt-4o-mini",
    temperature=0,          # 0 = 确定性强,1 = 随机
    max_tokens=100,          # 最大输出 100 tokens
    top_p=0.9,               # 核采样
    frequency_penalty=0.5,   # 减少重复
    presence_penalty=0.5,    # 鼓励话题扩展
)

response = chat.invoke([HumanMessage(content="写一首诗")])

4.3 消息类型详解

Chat Model 使用消息对象来表示对话的不同角色:

消息类型 角色标识 用途
系统消息 SystemMessage system 设定 AI 的行为和角色
人类消息 HumanMessage user 用户输入
AI 消息 AIMessage assistant AI 的回复
工具消息 ToolMessage tool 工具执行结果
通用消息 ChatMessage 自定义 其他角色

4.3.1 ToolMessage

在 Agent 场景中,工具执行结果通过 ToolMessage 返回:

图 4-2:ToolMessage 在 Agent 中的使用
1 HumanMessage content = "北京今天天气怎么样?" 2 AIMessage content = "" tool_calls = [{"id": "call_abc123", "function": {"name": "weather", "arguments": "{\"city\":\"北京\"}"}}] id 关联 3 ToolMessage content = "北京今天晴,15-25°C" tool_call_id = "call_abc123" messages = [HumanMessage(...), AIMessage(...), ToolMessage(...)] 三个消息按顺序组成列表,传给 chat.invoke(messages) 继续对话
python tool_message.py
from langchain_core.messages import HumanMessage, AIMessage, ToolMessage

# 在 Agent 中,ToolMessage 自动生成
# 但我们可以手动创建用于测试

tool_result = ToolMessage(
    content="北京今天晴,15-25°C",
    tool_call_id="call_abc123"  # 对应 AI 消息中的 tool_call id
)

messages = [
    HumanMessage(content="北京今天天气怎么样?"),
    AIMessage(content="", additional_kwargs={
        "tool_calls": [{
            "id": "call_abc123",
            "function": {"name": "weather", "arguments": '{"city":"北京"}'}
        }]
    }),
    tool_result,  # 工具返回结果
]

response = chat.invoke(messages)

4.4 多模型提供商

LangChain 提供了统一的接口来访问多个模型提供商:

提供商 集成包 模型示例
OpenAI langchain-openai gpt-4o, gpt-4o-mini, gpt-4-turbo
Anthropic langchain-anthropic claude-opus-4, claude-sonnet-4, claude-haiku
Google langchain-google-vertexai gemini-pro, gemini-ultra
Groq langchain-groq llama-3.1-70b, mixtral-8x7b
Mistral langchain-mistralai mistral-large, mistral-small
HuggingFace langchain-huggingface 本地部署模型

4.4.1 Anthropic Claude

python anthropic.py
# 安装: pip install langchain-anthropic

from langchain_anthropic import ChatAnthropic

claude = ChatAnthropic(
    model="claude-sonnet-4-20250514",
    anthropic_api_key="sk-ant-xxxx",  # 设置环境变量更安全
)

response = claude.invoke([
    SystemMessage(content="你是一个有帮助的助手"),
    HumanMessage(content="你好,介绍一下你自己")
])
print(response.content)

4.4.2 Google Gemini

python gemini.py
# 安装: pip install langchain-google-vertexai

from langchain_google_vertexai import ChatGemini

gemini = ChatGemini(
    model="gemini-1.5-pro",
    project="your-project-id",
    location="us-central1",
)

response = gemini.invoke([HumanMessage(content="你好")])
print(response.content)

4.4.3 本地模型 (HuggingFace)

python local_model.py
# 安装: pip install langchain-huggingface

from langchain_huggingface import HuggingFacePipeline

# 使用本地 HuggingFace 模型
llm = HuggingFacePipeline.from_model_id(
    model_id="microsoft/Phi-3-mini-128k-instruct",
    task="text-generation",
    pipeline_kwargs={"max_new_tokens": 256},
)

response = llm.invoke("翻译成法语:Hello")
print(response)
⚠️ API Key 安全

强烈建议使用环境变量来存储 API Key,而不是直接写在代码中:
export OPENAI_API_KEY="sk-..."
export ANTHROPIC_API_KEY="sk-ant-..."

4.5 流式输出

流式输出允许我们实时显示模型的响应,提升用户体验:

图 4-3:流式输出 vs 非流式输出
非流式输出 ⏳ 用户: 你好 等待 2-3 秒... 你好!很高兴认识你。 一次性显示完整回复 流式输出 ⚡ 用户: 你好 你好!很高兴认识你。 逐字显示,边生成边展示
python streaming.py
from langchain_openai import ChatOpenAI

chat = ChatOpenAI(model="gpt-4o-mini", streaming=True)

# 流式输出
print("流式响应: ", end="", flush=True)
for chunk in chat.stream([HumanMessage(content="讲一个关于AI的笑话")]):
    print(chunk.content, end="", flush=True)
print()  # 换行
💡 应用场景

流式输出特别适合:聊天机器人、实时写作辅助、代码补全、语音对话等需要实时反馈的场景。

4.6 结构化输出

使用工具调用(Function Calling / Tool Calling)可以获得可靠的结构化输出:

4.6.1 强制工具调用

python forced_tool_call.py
from langchain_openai import ChatOpenAI
from pydantic import BaseModel, Field
from typing import List

chat = ChatOpenAI(model="gpt-4o", temperature=0)

# 定义输出结构
class WeatherResponse(BaseModel):
    city: str = Field(description="城市名称")
    temperature: str = Field(description="温度范围")
    condition: str = Field(description="天气状况")
    humidity: str = Field(description="湿度")

# 强制使用工具
response = chat.bind_tools([WeatherResponse], tool_choice="WeatherResponse").invoke(
    [HumanMessage(content="北京今天的天气怎么样?")]
)

# 获取工具调用结果
tool_calls = response.additional_kwargs.get("tool_calls", [])
if tool_calls:
    import json
    result = json.loads(tool_calls[0]["function"]["arguments"])
    print(result)
    # {'city': '北京', 'temperature': '15-25°C', 'condition': '晴', 'humidity': '45%'}

4.6.2 with_structured_output

更简洁的写法:

python structured_output.py
from langchain_openai import ChatOpenAI
from pydantic import BaseModel, Field
from typing import List

chat = ChatOpenAI(model="gpt-4o", temperature=0)

# 定义输出结构
class PersonInfo(BaseModel):
    name: str = Field(description="人名")
    age: int = Field(description="年龄")
    occupation: str = Field(description="职业")
    skills: List[str] = Field(description="技能列表")

# 创建结构化链
structured_chat = chat.with_structured_output(PersonInfo)

# 调用
result = structured_chat.invoke(
    [HumanMessage(content="张三,28岁,是一名Python程序员,擅长Web开发和数据分析")]
)
print(result.name)       # 张三
print(result.age)        # 28
print(result.occupation)  # Python程序员
print(result.skills)     # ['Web开发', '数据分析']

4.7 本章小结

📝 关键概念回顾

概念 说明
LLM vs Chat Model 文本输入 vs 消息列表输入
消息类型 System/Human/AI/Tool/ChatMessage
多提供商 OpenAI, Anthropic, Google, HuggingFace 等
流式输出 边生成边展示,提升体验
结构化输出 with_structured_output 获得可靠 JSON
🚀 接下来学什么?

在下一章中,我们将学习 RAG 检索增强生成,这是构建知识库问答系统的核心技术。

关注我们