LangChain content_blocks:统一处理多模态与跨模型厂商消息内容
目录前言一、什么是 content_blocks补充content 与 content_blocks 的关系二、为什么需要 content_blocks三、如何使用 content_blocks3.1 读取标准化内容3.2 创建消息时使用标准化块3.3 让模型直接返回标准化格式四、支持的内容块类型五、典型应用场景场景1统一处理来自不同模型的推理内容场景2构建包含多模态内容的用户消息场景3统一提取工具调用六、何时使用 content何时使用 content_blocks前言在开发基于大语言模型的应用时我们经常需要处理来自不同提供商OpenAI、阿里云百炼、本地模型等的消息内容。这些模型在消息格式上各有差异有的将推理步骤放在专用字段有的以不同结构表示多模态数据。如果直接使用原始的 content 字段我们得写大量针对特定模型的适配代码。说白了就是每个模型厂商都有自己的一套消息规范content我们调用模型厂商时需要按照每个厂商的规范定义content接收模型消息后也得根据这个规范解析内容LangChain 在 v1 版本引入的 content_blocks 正是为了解决这一问题。它提供了一套标准化的、类型安全的消息内容表示方式我们能够用同一套代码轻松处理文本、推理、图片、音频、工具调用等各类内容无缝兼容不同的模型提供商。一、什么是 content_blocks每个 LangChain 消息对象如 HumanMessage、AIMessage都有一个 content 属性它直接存储模型提供商原生格式的内容可能是字符串或字典列表。而 content_blocks 是这样发挥其作用的输入时你只需要用 LangChain 的标准内容块构造消息如 HumanMessage(content_blocks[…])LangChain 会根据目标模型自动将 content_blocks 转换为该模型厂商所需的原始 content 格式可能是字符串、特定字典列表等并填充到消息的 content 属性中。输出时模型返回的消息其 content 属性存储的是厂商原生格式如 OpenAI 的字典列表、Anthropic 的混合结构。当你访问消息的 content_blocks 属性时LangChain 会惰性解析这个原生 content将其转换为统一的标准内容块列表供你使用。fromlangchain.messagesimportAIMessage# 假设这是从 Anthropic 模型返回的消息messageAIMessage(content[{type:thinking,thinking:用户询问天气...,signature:...},{type:text,text:今天天气晴朗。}],response_metadata{model_provider:anthropic})# 通过 content_blocks 获取标准化内容forblockinmessage.content_blocks:ifblock[type]reasoning:print(block[reasoning])# 输出: 用户询问天气...elifblock[type]text:print(block[text])# 输出: 今天天气晴朗。可以看到无论原始 content 如何content_blocks 都能将推理内容统一表示为 {“type”: “reasoning”, “reasoning”: …}将文本统一表示为 {“type”: “text”, “text”: …}补充content 与 content_blocks 的关系那有人就会问既然有了 content_blocks为什么还要保留 content我平时只用 content 传字符串也能正常工作难道所有模型都接受纯字符串吗实际上LangChain 的 content 参数非常灵活它可以接受三种形式纯字符串如 “你好”厂商原生格式的列表如 OpenAI 的 [{“type”: “text”, “text”: “你好”}]标准内容块列表如 [{“type”: “text”, “text”: “你好”}]当我们传入一个字符串时LangChain 会根据目标模型的要求自动将其转换为该模型需要的格式。例如Anthropic 要求 content 必须是数组LangChain 就会将 “你好” 转换成 [{“type”: “text”, “text”: “你好”}] 再发送。所以你感觉“直接传字符串就行”其实是 LangChain 在底层帮你做了格式适配。而content_blocks 参数是专门为标准块设计的它强制要求传入符合标准块定义的列表提供了更好的类型安全和代码可读性。在构造消息时content 和 content_blocks 只需要传其中一个如果同时传入LangChain 通常会以 content_blocks 为准因为它更明确。为了代码清晰建议纯文本场景用 content“…”最简单。需要多模态、推理等复杂场景用 content_blocks[…]意图一目了然。另外你也可能会看到这样的代码original_blocksrequest.system_message.content_blocks new_blocksoriginal_blocks[{type:text,text:addendum}]new_system_messageSystemMessage(contentnew_blocks)# 把标准块传给了 content这段代码虽然能工作但混用了两种概念用 content_blocks 读取却用 content 写入。更好的写法是保持统一new_system_messageSystemMessage(content_blocksnew_blocks)这样无论是读还是写都通过 content_blocks 属性/参数代码自文档化避免歧义。二、为什么需要 content_blocks跨模型兼容性不同模型对相同类型内容的表达方式截然不同。例如OpenAI 可能将推理内容放在 content 的一个专用块中也可能通过 response_metadata 返回。Anthropic 使用 thinking 块。本地模型 可能有完全自定义的格式。使用 content_blocks你可以统一提取推理、工具调用等关键信息无需关心底层模型是谁。简化多模态输入当你需要向模型发送图片、音频、文件等时不同模型对多模态内容的字段要求各异。例如 OpenAI 要求{type: image_url, image_url: {...}}而某些模型可能使用{type: image, url: ...}。content_blocks 让你用一套标准描述多模态内容LangChain 会自动转换为目标模型所需的格式。三、如何使用 content_blocks3.1 读取标准化内容直接访问消息对象的 content_blocks 属性即可。forblockinai_message.content_blocks:ifblock[type]reasoning:reasoning_textblock[reasoning]elifblock[type]tool_call:tool_nameblock[name]tool_argsblock[args]3.2 创建消息时使用标准化块在创建HumanMessage、SystemMessage等消息对象时可以直接传入content_blocks参数。LangChain 会自动填充 content 字段为模型可接受的格式。fromlangchain.messagesimportHumanMessage messageHumanMessage(content_blocks[{type:text,text:描述这张图片},{type:image,url:https://example.com/photo.jpg}])# message.content 会被自动转换成对应模型需要的格式3.3 让模型直接返回标准化格式通过设置 output_version“v1”模型输出的 AIMessage 的 content 字段本身就是标准内容块列表方便序列化或后续处理。fromlangchain.chat_modelsimportinit_chat_model modelinit_chat_model(gpt-5-nano,output_versionv1)responsemodel.invoke(你好)# response.content 现在是一个标准内容块列表而不是原始提供商格式四、支持的内容块类型类型用途关键字段text普通文本text, annotationsreasoning模型推理过程reasoning, extrasimage图片数据url / base64, mime_typeaudio音频数据url / base64, mime_typevideo视频数据url / base64, mime_typefile通用文件如 PDFurl / base64, mime_typetool_call模型请求调用工具name, args, idtool_result工具执行结果content, tool_call_idtool_call_chunk流式工具调用片段name, args, id, indexserver_tool_call服务端工具调用id, name, args五、典型应用场景场景1统一处理来自不同模型的推理内容假设你的应用同时使用了 OpenAI 和 Anthropic 的模型并需要将模型的思考过程记录到日志中。deflog_reasoning(ai_message:AIMessage):forblockinai_message.content_blocks:ifblock[type]reasoning:print(f推理:{block[reasoning]})# 如果模型提供了额外元数据如签名ifsignatureinblock.get(extras,{}):print(f签名:{block[extras][signature]})场景2构建包含多模态内容的用户消息向模型发送一张本地图片和一段文本描述。importbase64withopen(photo.jpg,rb)asf:base64_imagebase64.b64encode(f.read()).decode()user_msgHumanMessage(content_blocks[{type:text,text:这张照片里有什么},{type:image,base64:base64_image,mime_type:image/jpeg}])responsemodel.invoke([user_msg])场景3统一提取工具调用当模型请求调用工具时content_blocks 会将工具调用统一为 tool_call 类型。# 假设模型返回了工具调用responsemodel_with_tools.invoke(巴黎天气怎么样)forblockinresponse.content_blocks:ifblock[type]tool_call:print(f调用工具:{block[name]})print(f参数:{block[args]})# 执行工具并返回结果...六、何时使用 content何时使用 content_blocks场景推荐使用只有纯文本且只使用一个模型直接用 content 字符串即可最简单。需要多模态输入图片、音频等推荐使用 content_blocks 构建免去记忆不同模型格式的烦恼。需要跨模型处理推理、工具调用等内容必须使用 content_blocks否则要写大量条件判断。对返回的消息进行结构化处理使用 content_blocks 获得统一表示。希望代码具备更好的可维护性和类型提示推荐使用 content_blocks。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2438008.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!