跳过正文

·689 字·4 分钟
Chuck Chan
作者
Chuck Chan
分享技术、思考与生活

1. LangChain
#

LangChain 是一套开源的 Python/JavaScript 框架,核心是通过模块化组件与可组合的链(Chain)将大语言模型(LLM)与外部数据源、工具(如搜索、数据库、API)连接,实现上下文管理、多步推理、智能交互等复杂 AI 应用的快速开发。

  • 代码地址:https://github.com/langchain-ai/langchain
  • 官方文档:https://docs.langchain.com/
  • 中文文档:https://langchain-doc.cn/ (机翻,凑合着看)

LangChain的一些组件:

  • Models:模型,比如GPT-4o
  • Prompts:提示,包括提示管理、提示优化和提示序列化
  • Memory:记忆,用来保存和模型交互时的上下文
  • Indexes:索引,用于结构化文档,方便和模型交互如果要构建自己的知识库,就需要各种类型文档的加载,转换,长文本切割,文本向量计算,向量索引存储查询等
  • Chains:链,一系列对各种组件的调用
  • Agents:代理,决定模型采取哪些行动,执行并且观察流程,直到完成

2. 核心组件
#

代理
#

代理即Agent,其将语言模型与工具结合,创建能够对任务进行推理、决定使用哪些工具并迭代寻求解决方案的系统,简单来说,Agent像“人”一样能够通过思考来解决问题。

模型
#

模型即我们常说的大模型(如ChatGPT、Deepseek),能够像人类一样理解和生成文本。它们用途广泛,可用于撰写内容、翻译语言、总结信息和回答问题,而无需针对每项任务进行专门训练,模型是整个Langchain框架的大脑。模型可以通过两种方式使用:

  • 与Agent一起使用 - 创建Agent时可动态指定模型
  • 独立使用 - 模型可直接调用(在Agent循环之外),用于文本生成、分类或提取等任务,而无需Agent框架

初始化Model
#

使用init_chat_model即可初始化一个模型

import os
from langchain.chat_models import init_chat_model
os.environ["OPENAI_API_KEY"] = "sk-..."
model = init_chat_model("openai:gpt-4.1")

参数
#

可用于配置其行为的一组参数。支持的参数集因模型和提供商而异,但标准参数包括:

参数 类型 必填 说明
model string 您想使用的特定模型的名称或标识符。
api_key string 用于向模型提供商进行身份验证的密钥。通常在注册访问模型时颁发。通常通过设置环境变量访问。
temperature number 控制模型输出的随机性。值越高,响应越具创造性;值越低,响应越确定性。
timeout number 在取消请求之前等待模型响应的最大时间(秒)。
max_tokens number 限制响应中的token总数,有效控制输出长度。
max_retries number 如果因网络超时或速率限制等问题而失败,系统将重新发送请求的最大尝试次数。

不同的模型可能会有他们特殊的额外参数,例如,ChatOpenAI 具有 use_responses_api 以决定是否使用 OpenAI Responses 或 Completions API,可以查阅文档

静态模型
#

静态模型在创建智能体时配置一次,并在整个执行过程中保持不变,这是最常见且直接的方法。

from langchain.agents import create_agent
agent = create_agent(
    "openai:gpt-5",
    tools=tools
)

使用不同模型代理商的初始化包,这样可以对模型配置进行更多的控制。

from langhcain.agents import create_agent
from langchain_openai import ChatOpenAI
model = ChatOpenAI(
	model = "gpt-5",
  temperature = 0.1, #决定大模型有多放飞 越小越确定、保守、重复  越大越随机、创意、天马行空
  max_tokens = 1000,
  timeout = 30
  ... 
)

动态模型
#

如果需要根据当前状态上下文来选择模型,就需要动态模型。使用动态模型需要 @wrap_model_call装饰器来创建中间件,以修改请求中的模型。

from langchain_openai import ChatOpenAI
from langchain.agents import create_agent
from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse

basic_model = ChatOpenAI(model="gpt-4o-mini")
advanced_model = ChatOpenAI(model="gpt-4o")

@warp_model_call
def dynamic_model_selection(request: ModelRequest, handler) -> ModelResponse:
  """根据对话复杂性选择模型。"""
  message_count = len(request.state["message"])
  if meesage_count > 10: #如果长度大于10用高阶模型
    model = advanced_model
  else:
    model = basic_model
  request.model = model
  return handler(request)

agent = create_agent(
    model=basic_model,  # 默认模型
    tools=tools,
    middleware=[dynamic_model_selection]
)

消息
#

消息是 LangChain 中模型上下文的基本单位。它们代表模型的输入和输出,携带内容和元数据,用于在与 LLM 交互时表示对话状态。消息一般包含一下内容:

  • 角色 - 标识消息类型(例如 systemuser
  • 内容 - 表示消息的实际内容(例如文本、图像、音频、文档等)
  • 元数据 - 可选字段,例如响应信息、消息 ID 和令牌使用情况

LangChain 提供了一种标准消息类型,可在所有模型提供商之间工作,确保无论调用哪个模型都能保持一致的行为。

基础用法
#

from langchain.chat_models import init_chat_model
from langchain.messages import HumanMessage, AIMessage, SystemMessage

model = init_chat_model("openai:gpt-5-nano")

system_msg = SystemMessage("You are a helpful assistant.")
human_msg = HumanMessage("Hello, how are you?")

# 与聊天模型一起使用
messages = [system_msg, human_msg]
response = model.invoke(messages)  # 返回 AIMessage

# 或者直接把文本提示器给到大模型
response = model.invoke("Write a haiku about spring")

消息类型
#

from langchain.messages import HumanMessage, AIMessage, SystemMessage

# 系统消息 表示一组初始指令,用于引导模型的行为。您可以使用系统消息来设置语气、定义模型角色并建立响应指南。
system_msg = SystemMessage("你是一个帮助用户解决问题的助手")

# 用户消息 表示用户输入和交互。它们可以包含文本、图像、音频、文件以及任何其他多模态内容.
human_msg = HumanMessage(
    content="我有一个问题,请帮我解决",
    name="Chuck", # 可选 消息的名称,用于标识消息的来源或类型。
    id="msg_123", # 可选 消息的唯一标识符,用于标识消息的唯一性。
)

# 助手消息 表示模型调用的输出。它们可以包含多模态数据、工具调用和提供商特定的元数据.
ai_msg = AIMessage("好的,我可以帮助你解决这个问题")
""" 
AIMessage 包含的字段有:
    text (string)
    消息的文本内容。

    content (string | dict[])
    消息的原始内容。

    content_blocks (ContentBlock[])
    消息的标准化内容块。

    tool_calls (dict[] | None)
    模型进行的工具调用的具体信息 包括了name、args、id、artifact字段。如果没有调用工具,则为空。

    id (string)
    消息的唯一标识符(由 LangChain 自动生成或在提供商响应中返回)

    usage_metadata (dict | None)
    消息的使用元数据,可包含可用时的令牌计数。

    response_metadata (ResponseMetadata | None)
    消息的响应元数据,包含了模型提供商model_provider字段。
    
"""

token使用情况
#

AIMessageusage_metadata 字段中保存了令牌计数和其他使用元数据:

{
  'input_tokens': 8,   # 输入的token
  'output_tokens': 304, # 输出的token
  'total_tokens': 312,
  'input_token_details': {'audio': 0, 'cache_read': 0},
  'output_token_details': {'audio': 0, 'reasoning': 256}
}

消息内容
#

消息的字段content是一个联合类型,这意味着你可以用多种形式来表达content。

content: str | list[str | dict]
from langchain.messages import HumanMessage

# 字符串内容
human_message = HumanMessage("Hello, how are you?")

# 提供商原生格式(例如 OpenAI)随着提供商的不同 字段可能会改变
human_message = HumanMessage(content=[
    {"type": "text", "text": "Hello, how are you?"},
    {"type": "image_url", "image_url": {"url": "https://example.com/image.jpg"}}
])

# 标准内容块列表 不管是 OpenAI、Anthropic、Google 等,你拿到的都是同一套结构
human_message = HumanMessage(content_blocks=[
    {"type": "text", "text": "Hello, how are you?"},
    {"type": "image", "url": "https://example.com/image.jpg"},
])

多模态
#

多模态指的是处理以不同形式出现的数据的能力,例如文本、音频、图像和视频。LangChain 包含可跨提供商使用的这些数据的标准类型。

图像类型的消息:

# 从 URL
message = {
    "role": "user",
    "content": [
        {"type": "text", "text": "Describe the content of this image."},
        {"type": "image", "url": "https://example.com/path/to/image.jpg"},
    ]
}

# 从 base64 数据
message = {
    "role": "user",
    "content": [
        {"type": "text", "text": "Describe the content of this image."},
        {
            "type": "image",
            "base64": "AAAAIGZ0eXBtcDQyAAAAAGlzb21tcDQyAAACAGlzb2...",
            "mime_type": "image/jpeg",
        },
    ]
}

# 从提供商管理的文件 ID
message = {
    "role": "user",
    "content": [
        {"type": "text", "text": "Describe the content of this image."},
        {"type": "image", "file_id": "file-abc123"},
    ]
}

PDF类型的消息:

# 从 URL
message = {
    "role": "user",
    "content": [
        {"type": "text", "text": "Describe the content of this document."},
        {"type": "file", "url": "https://example.com/path/to/document.pdf"},
    ]
}

# 从 base64 数据
message = {
    "role": "user",
    "content": [
        {"type": "text", "text": "Describe the content of this document."},
        {
            "type": "file",
            "base64": "AAAAIGZ0eYBtcDQyAAAAAGlzb21tcDQyAAACAGlzb2...",
            "mime_type": "application/pdf",
        },
    ]
}

# 从提供商管理的文件 ID
message = {
    "role": "user",
    "content": [
        {"type": "text", "text": "Describe the content of this document."},
        {"type": "file", "file_id": "file-abc123"},
    ]
}

PDF类型的消息:

# 从 base64 数据
message = {
    "role": "user",
    "content": [
        {"type": "text", "text": "Describe the content of this video."},
        {
            "type": "video",
            "base64": "AAAAIGZ0eYBtcDQyAAAAAGlzb21tcDQyAAACAGlzb2...",
            "mime_type": "video/mp4",
        },
    ]
}

# 从提供商管理的文件 ID
message = {
    "role": "user",
    "content": [
        {"type": "text", "text": "Describe the content of this video."},
        {"type": "video", "file_id": "file-abc123"},
    ]
}

content_blocks
#

在content中你可以填入个个大模型提供商所需要的参数, content_blocks则是标准的内容块。假设有这么个场景,你的应用需要根据不同的场景来切换不同的大模型,如果使用content意味着需要给每个大模型都构建一套专门的调用参数(字段可能不一样),但如果使用content_blocks的话只需要一套参数,只需在特定的场景去切换大模型即可。

TextContentBlock

{
    "type": "text",
    "text": "Hello world",
    "annotations": []
}

ReasoningContentBlock

{
    "type": "reasoning",
    "reasoning": "The user is asking about...",
    "extras": {"signature": "abc123"},
}

其他类型的content_blocks可以参考官方文档

工具
#