目录1、认识消息1.1 消息的内部结构1.2 消息的类型1、系统消息2、用户消息3、助手(AI)消息4、工具调用消息1.3 消息格式格式1JSON格式格式2对象格式1.4 举 例举例1JSON格式举例2对象格式1.5 消息对象字段说明1.5.1 SystemMessage参数列表1.5.2 HumanMessage参数列表1.5.3 AIMessage参数列表1.5.4 ToolMessage参数列表(拓展)1.6 实战1.6.1 对话历史管理1.6.2 对话历史优化1.6.3 多轮对话聊天机器人1.7 拓展-消息属性content、content_blocks1.7.1 content1.7.2 content_blocks1、认识消息大模型没有记忆它的输出只和输入模型的内容有关上下文。很多大模型API服务也没有在服务端维 护会话历史是“ 无状态 ”的。因此如果应用需要“记住”对话历史需要在程序中维护消息列表在 LangChain 中Message消息是模型交互的最基本单元。它既代表模型接收到的 输入 Input 也代表模型生成的 输出Output 。每一轮与大模型的对话都由一条或多条 Message 构成。每个 Message 不仅包含 文字内容 还 携带描述上下文状态的 元信息metadata 用于保持对话的一致性和可追踪性。比如模型 在多轮交互中理解“谁在说话”、“说了什么”、“这条信息属于哪一轮对话”。LangChain 在 1.0 中提供了跨模型统一的 Message 标准。无论你使用的是 OpenAI、Anthropic、 Gemini 还是本地模型这一标准都能保持一致的行为。好处兼容性强 不同模型的消息格式自动对齐。可扩展性高 方便添加多模态内容或自定义字段。可追踪性好 为 LangSmith 等调试工具提供一致的上下文数据结构。1.1 消息的内部结构LangChain的消息Message对象包含三种字段Role消息所属的角色或类型如 system 、 user 、 assistant 。Content消息内容Metadata可选元数据存储额外信息。如消息ID、响应时间、token消耗量、消息标签 等1.2 消息的类型LangChain定义了很多消息类型通过 role 区分。常用的有四种。1、系统消息也称为系统提示词用于在对话开始时为模型设定角色、行为准则和上下文背景。它像是给AI助手的一 份工作说明书决定了其回答问题的风格、领域和专业范围。{role: system, content: 你是个精通编程的软件架构师2、用户消息也称为用户提示词在多轮对话中它表示用户的一次输入。可以包含简单的文本问题也可以是复杂 的多模态内容如图片、音频、文档等。{role: user, content: 你好啊~}3、助手(AI)消息代表模型的回复包括生成的文本、工具调用、元数据等。{role: assistant, content: 我也很高兴认识你}{ role: assistant, content: , tool_calls: [{ name: get_weather, args: {location: 北京}, id: call_00_nUD2NC9QRN5Cg1GaoIkBJQ4s }] }4、工具调用消息工具调用结果匹配的消息类型。将此消息返回给模型让模型基于这个结果继续生成回复。在Tools一节 详细介绍。{role: tool, content: 今天天气很好, tool_call_id: call_00_nUD2NC9QRN5Cg1GaoIkBJQ4s}问题为什么使用不同的消息类型明确角色 清晰区分系统提示、用户输入和 AI 回复控制行为 通过 SystemMessage 精确控制 AI 的行为对话历史 构建完整的多轮对话上下文调试友好 更容易追踪和调试对话流程1.3 消息格式LangChain支持二种消息格式。格式1JSON格式1、系统消息{role: system, content: 你是个善解人意的助手}2、用户消息{role: user, content: 你好啊~}3、助手消息{role: assistant, content: 我也很高兴认识你}4、工具调用消息{role: tool, content: 工具输出, tool_call_id: call_00_nUD2NC9QRN5Cg1GaoIkBJQ4s}格式2对象格式1、系统消息SystemMessage(content你是个善解人意的助手)2、用户消息HumanMessage(content你好啊~)3、助手消息{role: assistant, content: 我也很高兴认识你}4、工具调用消息ToolMessage( content工具输出, tool_call_idcall_00_nUD2NC9QRN5Cg1GaoIkBJQ4s # 一定要和AI消息中的调用ID匹 配 )举例from langchain_core.messages import ( HumanMessage, # 用户消息 AIMessage, # AI 消息 SystemMessage, # 系统消息 ToolMessage # 工具返回消息 ) # 消息列表示例 messages [ SystemMessage(content你是一个助手), HumanMessage(content你好), AIMessage(content你好有什么可以帮你), HumanMessage(content天气怎么样), AIMessage(content让我查询一下...), ToolMessage(content北京晴天, tool_call_idcall_123), AIMessage(content北京今天是晴天) ]小结1.4 举 例举例1JSON格式from dotenv import load_dotenv from langchain.chat_models import init_chat_model import os load_dotenv(overrideTrue) DEEPSEEK_API_KEY os.getenv(DEEPSEEK_API_KEY) DEEPSEEK_BASE_URL os.getenv(DEEPSEEK_BASE_URL) modelinit_chat_model( modeldeepseek-v4-flash, model_providerdeepseek, api_keyDEEPSEEK_API_KEY, base_urlDEEPSEEK_BASE_URL, ) messages[ {role:system,content:你是一个友好的ai助手}, {role:user,content:11?}, {role:assistant,content:3}, {role:user,content:我刚才问了什么?} ] resmodel.invoke(messages) print(res)举例2对象格式from dotenv import load_dotenv from langchain.chat_models import init_chat_model import os from langchain_core.messages import SystemMessage from langchain_core.messages import HumanMessage from langchain_core.messages import AIMessage load_dotenv(overrideTrue) DEEPSEEK_API_KEY os.getenv(DEEPSEEK_API_KEY) DEEPSEEK_BASE_URL os.getenv(DEEPSEEK_BASE_URL) modelinit_chat_model( modeldeepseek-v4-flash, model_providerdeepseek, api_keyDEEPSEEK_API_KEY, base_urlDEEPSEEK_BASE_URL, ) messages[ SystemMessage(content你是一个友好的ai助手), HumanMessage(11?), AIMessage(3), SystemMessage(content我刚才问了什么) ] resmodel.invoke(messages) print(res)1.5 消息对象字段说明此处仅说明常用字段完整字段列表查阅官方手册或阅读源码。1.5.1 SystemMessage参数列表content 消息内容字段名可以省略SystemMessage(你是个善解人意的助手)相当于SystemMessage(content 你是个善解人意的助手)1.5.2 HumanMessage参数列表content 消息内容字段名可以省略HumanMessage(你好啊~)相当于HumanMessage(content 你好啊~)metadata 元数据字段可以有很多自定义举例带有元数据字段HumanMessage( contentHello!, namealice, # 可选用户名 idmsg_123, # 可选message的ID )name 和 id 都属于元数据字段当消息类型相同对消息进行区分。但不是所有模型都支持这一功 能是否支持取决于模型供应商需要查看官方手册。比如OpenAI的API手册告诉我们HumanMessage支持 name 作为元数据字段如下图所示。而 DeepSeek的API官方文档明确支持 name 作为元数据但实测发现模型无法识别。举例使用aicodemirror调用 没有将name正确传递 给模型服务。即import os from dotenv import load_dotenv from langchain.chat_models import init_chat_model from langchain_core.messages import SystemMessage, HumanMessage # 读取 .env 配置文件 load_dotenv(verboseTrue) AICODE_KEY os.getenv(AICODE_KEY) AICODE_URL os.getenv(AICODE_URL) # 初始化模型 model init_chat_model( modelopenai:gpt-5.4, api_keyAICODE_KEY, base_urlAICODE_URL, ) messages [ SystemMessage(你是一个信息抽取器。你会收到多条来自不同发言者的 user 消息。每条消息可能带有 name 字段。你的任务是严格根据每条消息的 name 提取发言者及其观点并输出JSON。禁止使用“第一个人/第二个人”这种相对称呼。若某条消息没有 name则输出 unknown。输出格式{\speakers\:[{\name\:\...\,\claim\:\...\}]}), HumanMessage( content我认为 112, nameBob, ), HumanMessage( content我认为 112, nameTom, ), HumanMessage( content请列出谁说了什么不要判断对错。, nameaudience, ), ] response model.invoke(messages) print(response.content)1.5.3 AIMessage参数列表content 模型输出的原始内容字段名可以省略AIMessage(你好~)相当于AIMessage(content你好~)response_metadata AIMessage特有属性LLM的响应中附加元数据根据不同模型会有不同如 可能会包含本次token使用量等信息。tool_calls AIMessage特有属性表示工具调用信息。当LLM决定调用工具时在AIMessage 中就会 包含这个属性没有工具调用则为空。结构如下tool_calls[ { name: get_weather, // 应调用的工具名 args: {city: 杭州}, // 调用工具的参数 id: call_00_gIXYOD1Q1OkEXmdDBqXR1578, // 工具调用的唯一标识ID type: tool_call }, {name: get_news, args: {}, id: call_01_jD3phD5PEaIZf0mVLhKt0861, type: tool_call } ]tool_calls属性是一个ToolCall 列表每个ToolCall 是一个字典包含字段见上。usage_metadata 用量信息。举例举例1AIMessage给出最终答案AIMessage(content北京今天晴天温度 15°C)举例2AIMessage调用工具AIMessage( content, tool_calls[{ name: get_weather, args: {city: 北京}, id: call_xxx }] )举例3更丰富的参数from langchain_core.messages import SystemMessage,HumanMessage from langchain.chat_models import init_chat_model from dotenv import load_dotenv import os from rich import print as rprint # 从.env文件中加载环境变量 load_dotenv(overrideTrue) AICODE_KEY os.getenv(AICODE_KEY) AICODE_URL os.getenv(AICODE_URL) model init_chat_model( modelgpt-5.4-mini, model_provideropenai, api_keyAICODE_KEY, base_urlAICODE_URL ) messages [ SystemMessage(你叫小智是一名助人为乐的助手。), HumanMessage(你好好久不见请介绍下你自己。) ] response model.invoke(messages) rprint(response)AIMessage( content你好好久不见很高兴见到你。\n\n我是小智一个由 AI 驱动的助手可以帮你做很多事情比如\n\n- 解答问题、解释概念\n- 写作润色、改写、总结\n- 翻译中英文和其他语言\n- 头脑风暴、起名字、列提纲\n- 编程辅助、调试思路、代码示例\n- 生成图片创意或帮你设计视觉内容\n\n你可以把我当成一个随时在线的搭档直接告诉我你的需求我会尽量快速、清楚地帮你 。\n\n如果你愿意我也可以顺便介绍一下我最擅长的几类任务。, additional_kwargs{refusal: None}, response_metadata{ token_usage: { completion_tokens: 222, prompt_tokens: 330, total_tokens: 552, completion_tokens_details: { accepted_prediction_tokens: None, audio_tokens: None, reasoning_tokens: 61, rejected_prediction_tokens: None }, prompt_tokens_details: {audio_tokens: None, cached_tokens: 0} }, model_provider: openai, model_name: gpt-5.4-mini-2026-03-17, system_fingerprint: None, id: resp_06d6ce06afd26fba016a448f09ce1c8195a2ca09e379e0fee8, finish_reason: stop, logprobs: None }, idlc_run--019f1bce-b4eb-79d0-97ab-11afc03d8011-0, tool_calls[], invalid_tool_calls[], usage_metadata{ input_tokens: 330, output_tokens: 222, total_tokens: 552, input_token_details: {cache_read: 0}, output_token_details: {reasoning: 61} } ) { input_tokens: 2677, output_tokens: 179, total_tokens: 2856, input_token_details: {cache_read: 2304}, output_token_details: {reasoning: 83} }1 rprint(response.usage_metadata){ input_tokens: 330, output_tokens: 222, total_tokens: 552, input_token_details: {cache_read: 0}, output_token_details: {reasoning: 61} }返回的内容分析1.5.4 ToolMessage参数列表(拓展)content 文件内容name 工具名称tool_call_id 工具调用唯一IDToolMessage必须紧邻匹配的AIMessage和前者tool_calls中的id一 致。ToolMessage( content工具输出, nameget_weather tool_call_idcall_00_nUD2NC9QRN5Cg1GaoIkBJQ4s # 一定要和AI消息中的调用ID匹 配 )举例1工具调用json格式不必深究学过 tools 章节再来看这个示例就会很简单。import os from dotenv import load_dotenv from langchain.chat_models import init_chat_model # 加载环境变量 load_dotenv(overrideTrue) AICODE_KEY os.getenv(AICODE_KEY) AICODE_URL os.getenv(AICODE_URL) # 初始化模型 model init_chat_model( modelgpt-5.4-mini, model_provideropenai, api_keyAICODE_KEY, base_urlAICODE_URL, ) def get_weather(city: str) - str: return 不错哦~ # Assistant 返回的 Tool Call ai_message { role: assistant, content: , tool_calls: [ { name: get_weather, args: { location: 北京, }, id: call_00_nUD2NC9QRN5Cg1GaoIkBJQ4s, } ], } # Tool 返回结果 tool_message { role: tool, content: 今天北京天气晴朗万里无云~, tool_call_id: call_00_nUD2NC9QRN5Cg1GaoIkBJQ4s, } messages [ { role: user, content: 北京天气如何, }, ai_message, tool_message, ] response model.invoke(messages) print(response)举例2工具调用对象格式import os from dotenv import load_dotenv from langchain.chat_models import init_chat_model from langchain_core.messages import ( AIMessage, HumanMessage, ToolMessage, ) # 加载环境变量 load_dotenv(overrideTrue) AICODE_KEY os.getenv(AICODE_KEY) AICODE_URL os.getenv(AICODE_URL) # 初始化模型 model init_chat_model( modelgpt-5.4-mini, model_provideropenai, api_keyAICODE_KEY, base_urlAICODE_URL, ) # 工具函数 def get_weather(city: str) - str: return 不错哦~ # 模拟 AI 发起 Tool Call ai_message AIMessage( content[], tool_calls[ { name: get_weather, args: { location: 北京, }, id: call_00_nUD2NC9QRN5Cg1GaoIkBJQ4s, } ], ) # 模拟 Tool 返回结果 tool_message ToolMessage( content今天北京天气晴朗万里无云~, tool_call_idcall_00_nUD2NC9QRN5Cg1GaoIkBJQ4s, ) # 对话历史 messages [ HumanMessage(content北京天气如何), ai_message, tool_message, ] # 继续对话 response model.invoke(messages) print(response)1.6 实战1.6.1 对话历史管理关键规则每次调用必须传递完整的对话历史也就是说第 1 轮 [system, user] → AI回复 → 保存回复 第 2 轮 [system, user, assistant, user] → AI回复 → 保存回复 第 3 轮 [system, user, assistant, user, assistant, user] → AI回复注意每次对话都要在原有的消息列表中 添加新消息 不可重新创建新的列表。错误举例1❌# 第一次 response1 model.invoke(我叫张三) # 第二次没传历史 response2 model.invoke(我叫什么) # AI 不记得错误举例2❌conversation [{role: user, content: 问题1}] response1 model.invoke(conversation) conversation [{role: user, content: 问题2}] # 重新创建 response2 model.invoke(conversation) # 丢失了历史错误举例3❌conversation [] conversation.append({role: user, content: 问题1}) response1 model.invoke(conversation) # 忘记保存 response1.content conversation.append({role: user, content: 问题2}) response2 model.invoke(conversation) # AI 不知道之前的回答正确做法✅conversation [] # 第一次 conversation.append({role: user, content: 我叫张三}) response1 model.invoke(conversation) # 关键保存 AI 回复 conversation.append({role: assistant, content: response1.content}) # 第二次传递完整历史 conversation.append({role: user, content: 我叫什么}) response2 model.invoke(conversation) # AI 记得1.6.2 对话历史优化问题对话历史会越来越长消耗大量 tokens 和成本。解决方案只保留最近 N 轮对话。具体的总是保留 system 消息定义角色只保留最近 N 轮对话丢弃更早的历史举例定义保留最近对话轮数的函数from dotenv import load_dotenv from langchain.chat_models import init_chat_model import os from langchain_core.messages import HumanMessage, AIMessage from openrouter.components import SystemMessage load_dotenv(overrideTrue) DEEPSEEK_API_KEY os.getenv(DEEPSEEK_API_KEY) DEEPSEEK_BASE_URL os.getenv(DEEPSEEK_BASE_URL) modelinit_chat_model( modeldeepseek-v4-flash, model_providerdeepseek, api_keyDEEPSEEK_API_KEY, base_urlDEEPSEEK_BASE_URL, ) def keep_recent_messages(messages, max_pairs3): 保留最近的N轮对话 max_pairs :保留对话的轮数没轮 user assistant # 分离System消息和对话消息 system_msgs[m for m in messages if m.get(role)system] conversation_msgs[m for m in messages if m.get(role)!system] recent_msgs conversation_msgs[-(max_pairs * 2):] # 返回system 最近对话 return system_msgs recent_msgs测试# 初始化 long_conversation [ { role: system, content: 你是 Python 导师 } ] # 第 1 轮 long_conversation.append({ role: user, content: 什么是列表用一句解释 }) r1 model.invoke(long_conversation) long_conversation.append({ role: assistant, content: r1.content }) # 第 2 轮 long_conversation.append({ role: user, content: 列表和元组有什么区别用一句解释 }) r2 model.invoke(long_conversation) long_conversation.append({ role: assistant, content: r2.content }) # 第 3 轮 long_conversation.append({ role: user, content: 什么是字典呢用一句解释 }) r3 model.invoke(long_conversation) long_conversation.append({ role: assistant, content: r3.content }) print(f原始消息数: {len(long_conversation)}) # 优化只保留最近 2 轮对话 optimized keep_recent_messages( long_conversation, max_pairs2 ) print(f优化后消息数: {len(optimized)}) print(保留的内容system 最近2轮对话) # 添加新的用户问题 optimized.append({ role: user, content: 我第一个问题问的是什么 }) # 使用优化后的历史 response model.invoke(optimized) print(f\nAI 回复{response.content})1.6.3 多轮对话聊天机器人基于模型初始化、流式响应以及消息列表的拼接来创建多轮聊天机器人。from langchain.chat_models import init_chat_model import os from dotenv import load_dotenv load_dotenv(overrideTrue) # 1. 基础配置 MODEL_NAME deepseek-v4-flash MAX_PAIRS_HISTORY 10 EXIT_WORD quit def keep_recent_messages(messages, max_pairs3): 保留最近的 N 轮对话 max_pairs保留对话的轮数每轮 user assistant # 分离 System 消息和对话消息 system_msgs [m for m in messages if m.get(role) system] conversation_msgs [m for m in messages if m.get(role) ! system] # 保留最近 N 轮每轮两条消息 recent_msgs conversation_msgs[-(max_pairs * 2):] # 返回system 最近对话 return system_msgs recent_msgs # 2. 初始化模型 model init_chat_model( modelMODEL_NAME, model_provideropenai, api_keyos.getenv(DEEPSEEK_API_KEY), base_urlos.getenv(DEEPSEEK_BASE_URL), ) # 3. 维护消息列表 messages [ { role: system, content: 你是一个数字员工也是一名耐心友好的 AI 助手可以回答学生问题, } ] i 1 while True: print(\n, * 10, f- 第 {i} 轮对话开始 -, * 10, \n) user_input input( 请输入) # 退出判断 if user_input.lower() EXIT_WORD: print( 对话已结束欢迎下次再来) break # 追加用户消息 messages.append({role: user, content: user_input}) # 优化历史记忆 memory_messages keep_recent_messages( messages, max_pairsMAX_PAIRS_HISTORY, ) # 流式输出模型回复 print( AI, end, flushTrue) reply_content # 控制发送给模型的消息长度 for chunk in model.stream(memory_messages): if chunk.content: print(chunk.content, end, flushTrue) reply_content chunk.content # 一轮结束 print(\n, * 10, f- 第 {i} 轮对话结束 -, * 10, \n) # 追加 AI 回复 messages.append( { role: assistant, content: reply_content, } ) i 11.7 拓展-消息属性content、content_blocks1.7.1 content消息的 content 可以理解为数据内容它是弱类型的支持字符串和列表列表元素通常为字典。举例1存储字符串如果只是纯文本内容直接传递字符串就好from LangChain.messages import HumanMessage msg1 HumanMessage(content 你好啊) msg2 HumanMessage(你好啊) print(msg1) print(msg2)说明当content内容只有字符串时可以省略参数名称。举例2存储字典列表如果需要发送的不只是文本如多模态内容则需要content的 字典列表 形式。字典内容遵循模型供应商的API规范以 openai: gpt-4.4 为例。参考官方文档https://developers.openai.com/api/reference/python/resources/chat/subresource s/completions/methods/create将下图置于代码所在的目录下比如chapter04_message_prompt命名为 image_test.png测试代码如下import base64 import os from dotenv import load_dotenv from langchain.chat_models import init_chat_model from langchain.messages import HumanMessage load_dotenv(overrideTrue) AICODE_KEY os.getenv(AICODE_KEY) AICODE_URL os.getenv(AICODE_URL) # 初始化模型 model init_chat_model( modelopenai:gpt-5.4, api_keyAICODE_KEY, base_urlAICODE_URL, ) def encode_image(img_path, img_typejpeg): 将一张本地图片转换成 Base64 编码的 Data URI 字符串方便在文本中嵌入图片数据。 with open(img_path, rb) as img_file: return ( fdata:image/{img_type};base64, f{base64.b64encode(img_file.read()).decode(utf-8)} ) # 图像路径 img_path image_test.png # 获取图像 Base64 编码字符串 base64_image encode_image(img_path) response model.invoke( [ HumanMessage( content[ { type: text, text: 这张图里有什么, }, { type: image_url, image_url: base64_image, }, ] ) ] ) print(response.content)1.7.2 content_blocks在 LangChain 1.x 中 content_blocks 是消息对象BaseMessage的一项重大升级。它的核心目标 是提供一种跨模型供应商、标准化的多模态数据结构过去处理图片、音频、甚至是模型生成的“思维链Reasoning”内容时不同供应商OpenAI, Anthropic, Google 等的 API 格式各异导致开发者需要写大量的适配代码。 content_blocks 的出 现终结了这种混乱。在 LangChain 1.2 版本中消息对象的 content 属性依然存在为了向前兼容但新增了 content_blocks 属性可以将 content 解析为标准、类型安全的表示。数据结构它是一个 list[TypedDict] 。统一格式每个 block 都有一个 type 字段用于区分内容类型。支持类型包括 text 文本、 image 图片、 audio 音频、 video 视频、 tool_call 工具调用以及 reasoning 推理/思维链。支持的字段类型详见https://docs.langchain.com/oss/python/langchain/messages#openai① 输入格式化对于复杂的对话带图片或工具结果建议使用 content_blocks 列表形式构建 HumanMessage 或 AIMessage 。借助 content_blocks 我们可以用一套标准代码无缝地在不同厂商的模型之间切换。import base64 import os from dotenv import load_dotenv from langchain.chat_models import init_chat_model from langchain.messages import HumanMessage # 加载环境变量 load_dotenv(overrideTrue) # 初始化模型 AICODE_KEY os.getenv(AICODE_KEY) AICODE_URL os.getenv(AICODE_URL) # 初始化模型 model init_chat_model( modelopenai:gpt-5.4, api_keyAICODE_KEY, base_urlAICODE_URL, ) def encode_image(img_path): 将本地图片转换为 Base64 编码字符串。 with open(img_path, rb) as img_file: return base64.b64encode(img_file.read()).decode(utf-8) # 图片路径 img_path image_test.png # 获取图片 Base64 编码 base64_image encode_image(img_path) # 调用模型 response model.invoke( [ # 方式一传统格式 # HumanMessage( # content[ # { # type: text, # text: 这张图里有什么, # }, # { # type: image_url, # image_url: base64_image, # }, # ] # ) # 方式二推荐的统一写法LangChain HumanMessage( content_blocks[ { type: text, text: 这张图里有什么, }, { type: image, base64: base64_image, mime_type: image/png, }, ] ) ] ) # 输出结果 print(response.content)② 输出格式化content_blocks 还可用于输出格式化以deepseek官网的 deepseek-v4-flash 为例其输出包含思考 内容后者位于 additional_kwargs 的 reasoning_content 字段下。比如# 从 .env 文件中加载环境变量 load_dotenv(overrideTrue) # 初始化模型 model init_chat_model( modeldeepseek:deepseek-v4-flash, extra_body{ thinking: { type: enabled } }, ) # 向模型发送单条消息 response model.invoke(你好一句话回答) # 打印响应 print(response)不同的模型其输出格式可能不同仅为提取思考内容切换模型都可能需要更改代码非常不方便。content_blocks提供了 统一的输出格式 可以将不同格式的响应统一为标准格式。注意content_blocks是 懒加载 的即调用时才会解析from langchain.chat_models import init_chat_model from dotenv import load_dotenv load_dotenv() load_dotenv(overrideTrue) model init_chat_model( modeldeepseek:deepseek-v4-flash, extra_body{thinking: {type: enabled}}, ) response model.invoke(你好一句话回答) print( * 20, - response -, * 20) print(response) print( * 20, - response.content -, * 20) print(response.content) print( * 20, - response.content_blocks -, * 20) print(response.content_blocks)说明优先检查 response.content_blocks 而不是 response.content 特别是当你需要获取“思维 链”或者“引用Citations”信息时