1. 引言在使用 LangChain 进行大模型应用开发时content和content_block是两个经常出现但又容易混淆的概念。它们分别出现在不同的抽象层级中承担着不同的职责。本文将从定义、使用场景、代码示例和常见问题几个方面带你彻底搞懂这两个概念。2. 什么是 contentcontent是 LangChain 中消息Message对象的核心字段用于承载一条消息的实际文本内容。无论是用户输入、AI 回复还是系统提示最终都会以content的形式存储在消息对象中。2.1 基本用法在 LangChain 中构造一条消息非常简单fromlangchain_core.messagesimportHumanMessage,AIMessage# 构造用户消息user_msgHumanMessage(content你好请介绍一下你自己)# 构造 AI 回复ai_msgAIMessage(content你好我是基于大语言模型构建的 AI 助手。)2.2 content 的多种类型content字段并不局限于纯文本它还可以是其他类型# 纯文本msg1HumanMessage(content你好)# 多模态内容图片 文本msg2HumanMessage(content[{type:text,text:请描述这张图片},{type:image_url,image_url:{url:https://example.com/cat.jpg}}])# 工具调用结果msg3AIMessage(content,tool_calls[...])3. 什么是 content_blockcontent_block是 LangChain 中用于表示消息内容结构化组成部分的概念。当一条消息的content包含多个不同类型的片段时每个片段就是一个content_block。3.1 为什么需要 content_block在实际应用中一条消息往往不只是纯文本。例如一段文本 一张图片一段文本 一个工具调用请求多个文本片段组合如果只用单一的字符串来表示content就无法区分这些不同类型的片段。content_block正是为了解决这个问题而设计的。3.2 常见的 content_block 类型LangChain 提供了多种内置的 content block 类型fromlangchain_core.messagesimport(TextContentBlock,ImageContentBlock,ToolCallBlock,)# 文本块text_blockTextContentBlock(text这是一段文本)# 图片块image_blockImageContentBlock(urlhttps://example.com/image.png,detailauto)# 工具调用块tool_blockToolCallBlock(idcall_123,namesearch,args{query:LangChain})4. content 与 content_block 的关系理解两者的关系是掌握它们的关键content是消息的顶层字段是「容器」。content_block是content内部的结构化单元是「内容」。当content为字符串时它等价于一个纯文本块当content为列表时列表中的每个元素就是一个content_block。fromlangchain_core.messagesimportHumanMessage# 方式一content 为字符串隐式单个文本块msg1HumanMessage(content你好)# 方式二content 为列表显式多个 content_blockmsg2HumanMessage(content[{type:text,text:你好},{type:text,text:请分析下面的数据}])# 两种方式在底层都会被转换为 content_block 列表print(msg1.content)# 输出: 你好print(msg2.content)# 输出: [{type: text, text: 你好}, {type: text, text: 请分析下面的数据}]5. 实际应用场景5.1 多模态对话fromlangchain_core.messagesimportHumanMessage# 构造包含图片和文本的多模态消息messageHumanMessage(content[{type:text,text:这张图片里有什么},{type:image_url,image_url:{url:https://example.com/photo.jpg}}])# 发送给支持多模态的模型responsellm.invoke([message])5.2 流式输出处理fromlangchain_core.messagesimportAIMessageChunk# 流式输出时每个 chunk 的 content 可能是部分内容forchunkinllm.stream(讲个笑话):# 每个 chunk 都是一个 AIMessageChunk# 其 content 可能是字符串或 content_block 列表ifisinstance(chunk.content,list):forblockinchunk.content:ifblock.get(type)text:print(block[text],end)else:print(chunk.content,end)5.3 工具调用场景fromlangchain_core.messagesimportAIMessage# 模型返回工具调用时content 可能为空但 tool_calls 中有内容ai_messageAIMessage(content,tool_calls[{name:calculator,args:{expression:2 2},id:call_001}])# 此时可以通过 content_block 的方式访问fortool_callinai_message.tool_calls:print(f调用工具:{tool_call[name]}, 参数:{tool_call[args]})6. 常见问题与注意事项6.1 content 为 None 的情况某些消息如纯工具调用消息的content可能为None或空字符串处理时需要注意判空ifmessage.content:# 处理 contentpasselse:# content 为空可能是工具调用消息pass6.2 不同模型的兼容性不同模型对content_block的支持程度不同。OpenAI 支持text和image_url类型而 Anthropic 使用text和image类型。LangChain 会做自动转换但自定义时需要注意# OpenAI 风格openai_content[{type:text,text:你好},{type:image_url,image_url:{url:...}}]# Anthropic 风格anthropic_content[{type:text,text:你好},{type:image,source:{type:url,url:...}}]6.3 序列化与反序列化content_block在存储和传输时会被序列化为 JSON需要注意保持结构完整importjsonfromlangchain_core.messagesimportHumanMessage msgHumanMessage(content[{type:text,text:你好}])# 序列化serializedmsg.model_dump_json()print(serialized)# 反序列化fromlangchain_core.messagesimportmessage_to_dict,messages_from_dict restoredmessages_from_dict([json.loads(serialized)])7. 总结content是消息的顶层内容字段可以是字符串或结构化列表。content_block是content的结构化组成单元用于表达多模态、多类型内容。当content为字符串时LangChain 内部会将其视为单个文本块。处理多模态输入、流式输出和工具调用时理解content_block至关重要。掌握这两个概念能帮助你更灵活地构建复杂的对话应用充分发挥 LangChain 的能力。