day13-LangChain核心之Models模型和Messages消息

今日内容

---------------重点核心部分---------------
# 1 LangChain核心组件之 Agents智能体

# 2 LangChain核心组件之 Models模型
# 3 LangChain核心组件之 Messages消息
# 4 LangChain核心组件之 Tools工具
# 6 LangChain核心组件之 Streaming流式传输

# 7 LangChain核心组件之Structured output 结构化输出

# 5 LangChain核心组件之 Short-term memory短期记忆
---------------高级应用部分---------------
# 8 LangChain高级之Middleware 中间件
# 9 LangChain高级之Guardrails 护栏
# 10 LangChain高级之runtime运行时
# 11 LangChain高级之Context engineering上下文工程
# 12 LangChain高级之Model Context Protocol (MCP)模型上下文协议
# 13 LangChain高级之 Human-in-the-loop 人机交互
# 14 LangChain高级之 Multi-agent 多智能体
# 15 LangChain高级之 Retrieval 检索
# 16 LangChain高级之 Long-term memory 长期记忆

--------------使用LangSmith-需要付费---------------------
# 17 LangSmith Studio
# 18 Test 测试
# 19 Agent 聊天用户界面
# 20 Deployment  部署
# 21 Observability 可观测性

1 LangChain核心组件之 Models模型

1.1 介绍[LLM大模型-DeepSeek,千问]

#  1 大语言模型(LLMs) 是强大的 AI 工具,能够像人类一样理解和生成文本。它们用途广泛,可用于撰写内容、翻译语言、总结信息和回答问题,而无需针对每项任务进行专门训练。

# 2 除了文本生成之外,许多模型还支持:【多模态】--》推理和决策能力
 	-工具调用 - 调用外部工具(如数据库查询或 API 调用)并将结果用于响应中。
    -结构化输出 - 模型的响应被限制为遵循定义的格式。
    -多模态 - 处理和返回非文本数据,如图像、音频和视频。
    -推理 - 模型执行多步推理以得出结论。
    -模型是 Agent 的推理引擎。它们驱动代理的决策过程,决定调用哪些工具、如何解释结果以及何时提供最终答案。
    
# 3 选择的模型的质量和能力直接影响Agent的可靠性和性能。不同模型在不同任务上表现出色——有些更擅长遵循复杂指令,有些更擅长结构化推理,有些支持更大的上下文窗口以处理更多信息。

# 4 LangChain 的标准模型接口为您提供对众多不同提供商集成的访问,这使得实验和切换模型以找到最适合您用例的模型变得非常容易

# 5 基本用法-Langchain中模型可以通过两种方式使用:
    -与Agent一起使用 - 创建代理时可动态指定模型。
    	-上次课学习的,创建Agent使用
    -独立使用 - 模型可直接调用(在代理循环之外),用于文本生成、分类或提取等任务,而无需代理框架。
    	-今天学的
        
# 6 支持的模型:
	-https://docs.langchain.com/oss/python/integrations/providers/overview
    -https://docs.langchain.com/oss/python/integrations/providers/all_providers

image-20260301142357770

1.2 不同大模型厂商

# 1 LangChain支持市面上绝大部分 大模型,都会有对应的包,有些模型对应的包不是最新:比如千问,我们可以使用通用方案,OpenAI,国内的大模型,都是遵循这个协议的。
# 2 注意:由于国内绝大部分大模型厂商都兼容OpenAI的接口,所以,我们直接使用OpenAI 即可

# 3 使用 兼容OpenAI的接口 调用国内模型
	-3.1 方式一:Model Class方式
    -3.2 方式二:init_chat_model方式
    
# 4 使用LangChain官方包,调用国内模型
	-4.1 方式一:
    -4.2 方式二:
    
    
# 5 国产模型,用OpenAI 都兼容,lanchain官方只对DeepSeek支持好,其它的支持不好,我们可以统一使用OpenAI;但是使用langchain-deepseek 对接DeepSeek 和使用 ChatOpenAI 对接DeepSeek,有区别吗?
	-有区别,最好是用 官方维护的包
    -区别在于:【面试】如果使用思考模型有区别,不是用思考模型,没有区别
        -思考模型的话:用官方适配 api-->会输出思考过程:reasoning_content
        -使用ChatOpenAI 的话,不会输出思考过程
### 兼容OpenAI的接口-方式一: Model Class方式
from langchain_openai import ChatOpenAI
model = ChatOpenAI(
    model="deepseek-chat", # 模型名称
    api_key="sk-8705cb6f2c734663a314a9b33a7bb865", # sk 密钥--》不同厂商获取--花钱购买的
    base_url="https://api.deepseek.com", # 不同模型厂商地址不一样
)
# model = ChatAnthropic(
#     model="claude-haiku-4-5-20251001",
# )
# model = ChatGoogleGenerativeAI(
#     model="gemini-3.1-pro-preview",
# )
# llm = ChatDeepSeek(
#     model="deepseek-chat",
# )
# 调用模型
res=model.invoke("介绍一下自己?")
print(res)


### 兼容OpenAI的接口-方式二: init_chat_model方式
from langchain.chat_models import init_chat_model
model = init_chat_model(
    model="deepseek-chat",
    api_key="sk-8705cb6f2c734663a314a9b33a7bb865",
    base_url="https://api.deepseek.com",
)
res=model.invoke("介绍一下自己?")
print(res)
### 方式一:Model Class方式 ,必须要安装:langchain-deepseek
# pip install langchain-deepseek
from langchain_deepseek import ChatDeepSeek
model = ChatDeepSeek(
    model="deepseek-chat",
    api_key="sk-8705cb6f2c734663a314a9b33a7bb865",
    #base_url="https://api.deepseek.com", # 自动识别deepseek的地址
)
res=model.invoke("介绍一下自己?")
print(res)

###  方式二:init_chat_model方式
import os
from langchain.chat_models import init_chat_model
model = init_chat_model(
    model="deepseek-chat",
    api_key="sk-4a782de375c04ad5b62e08dfac8e69b0",
    # base_url="https://api.deepseek.com",
)
res=model.invoke("介绍一下自己?")
print(res)

image-20260301145655172

# 对接通义千问--》理论上要找:langchain-tongyi--》没有,LangChain官方没有
# langchain_community 社区--》通义千问团队会提交,但是不是langchain 官方维护的
# pip install langchain-community
from langchain_community.chat_models import ChatTongyi
model = ChatTongyi (
    model="qwen-vl-max", # 多模态模型
    # model="qwen-image-max", # 文生图模型,但是不支持
    api_key="sk-6459007b813946289da12857950c955b",
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)

response = model.invoke(f"介绍一下自己")
print(response.content)

# 倒不如使用openai的兼容接口

1.3 参数

# 1 类实例化得到对象,有些参数,除了下面三个,还有哪些?
model = ChatOpenAI(
    model="deepseek-reasoner",# 思考模式
    api_key="sk-8705cb6f2c734663a314a9b33a7bb865",
    base_url="https://api.deepseek.com",
)
参数 类型 必填 说明
model string 您想使用的特定模型的名称或标识符。
api_key string 用于向模型提供商进行身份验证的密钥。通常在注册访问模型时颁发。通常通过设置环境变量访问,我建议放在.env中。
temperature number 控制模型输出的随机性。值越高,响应越具创造性;值越低,响应越确定性。
timeout number 在取消请求之前等待模型响应的最大时间(秒)。
max_tokens number 限制响应中的token令牌总数,有效控制输出长度。
max_retries number 如果因网络超时或速率限制等问题而失败,系统将重新发送请求的最大尝试次数。

1.4 方法

# 1 模型对象的方法:
res=model.invoke("介绍一下自己?")

# 2 其它的:
	InvokeL:调用
    Stream:流
    Batch:批量

方法 说明
Invoke 模型接受消息作为输入,并在生成完整响应后输出消息。
Stream 调用模型,但实时流式传输生成的输出。
Batch 将多个请求批量发送给模型,以实现更高效的处理。

from langchain_openai import ChatOpenAI
model = ChatOpenAI(
    model="deepseek-chat", # 模型名称
    api_key="sk-8705cb6f2c734663a314a9b33a7bb865", # sk 密钥--》不同厂商获取--花钱购买的
    base_url="https://api.deepseek.com", # 不同模型厂商地址不一样
)
# 1 invoke 方法
res=model.invoke("介绍一下自己?")


# 2 stream方法,流式返回
# 2.1 案例一:流式输出,依次打印
# for chunk in model.stream("为什么鹦鹉有五颜六色的羽毛?"):
#     print(chunk.text, end="|", flush=True)
# print()
# 2.2 案例二:打印出推理过程[思考过程]:用openai通用接口,没有reasoning过程,是空的;没有调用工具,也是空的,只会打印出 返回的文字
for chunk in model.stream("天空是什么颜色?"):
    for block in chunk.content_blocks:
        if block["type"] == "reasoning" and (reasoning := block.get("reasoning")):
            print(f"推理:{reasoning}")
        elif block["type"] == "tool_call_chunk":
            print(f"工具调用块:{block}")
        elif block["type"] == "text":
            print(block["text"])
        else:
            ...
# 比如我们做了个智能问诊智能体--->app形式展示--->血压80,180--->库一下一次返回; 像打字机一样,一点点给用户 

# 3  banch
responses = model.batch([
    "为什么鹦鹉有五颜六色的羽毛?",
    "飞机是如何飞行的?",
    "什么是量子计算?"
])
for response in responses:
    print(response)

image-20260301151531544

1.5 工具调用[讲Agent时讲过工具调用]

AI智能体--》最核心的就是 大模型 和 工具

model的选择,和工具的调用能力【众多工具】

​ -打开网页工具

-发送邮件工具

-整理文件工具

# 1 使用Agent调用工具 --之前学了
# 2 使用Model调用工具--》接下来要学
---------流程一样,功能一样;只是代码有稍微区别而已,跟之前学的function calling流程一样,但是Langchain给简化了,我们编写更简单-------------

image-20260301003232350

# 1 模型可以请求调用执行任务的工具,例如从数据库获取数据、搜索网络或运行代码
	注意:函数调用 等同于 工具调用
        function calling
        mcp
        
# 2 要使定义的工具可供模型使用,必须使用 bind_tools() 绑定它们。在后续调用中,模型可以根据需要选择调用任何绑定的工具。	
	一些模型提供商提供【内置工具】,可通过模型或调用参数启用(例如 ChatOpenAI、ChatAnthropic)。请查看相应的提供商参考以了解详细信息
    查询上海天气--》大模型是返回不了--》但是有的大模型直接问:上海天气如何--》正确返回原因是:模型提供商提供了内置工具

# 3 工具中要学的知识点:【因为后期我们不直接使用models,而是通过Agent去使用model,所以工具的使用,了解流程和功能即可】
	-大模型返回调用的工具和参数
    -工具执行循环
    -强制工具调用
    -并行工具调用
    -流式传输工具调用

from langchain.tools import tool
from langchain.chat_models import init_chat_model
model = init_chat_model( # 内部会自己使用 LangChain-DeepSeek
    model="deepseek-chat",
    api_key="sk-8705cb6f2c734663a314a9b33a7bb865",
    # base_url="https://api.deepseek.com",
)

# 定义工具-->定义函数,使用tool装饰
@tool
def get_weather(location: str) -> str:
    """获取某个位置的天气。"""
    return f"{location} 天气晴朗,22度,没有雨。"

# 绑定工具,传入多个工具
model_with_tools = model.bind_tools([get_weather])

response = model_with_tools.invoke("北京的天气怎么样?")
for tool_call in response.tool_calls:
    # 查看模型发出的工具调用
    print(f"工具:{tool_call['name']}")  # get_weather
    print(f"参数:{tool_call['args']}")  # 北京
# 工具执行循环
# pip install langchain-deepseek
from langchain.tools import tool
from langchain.chat_models import init_chat_model
model = init_chat_model(
    model="deepseek-chat",
    api_key="sk-8705cb6f2c734663a314a9b33a7bb865",
    # base_url="https://api.deepseek.com",
)

@tool
def get_weather(location: str) -> str:
    """获取某个位置的天气。"""
    return f"{location} 天气晴朗。"

# 将(可能多个)工具绑定到模型
model_with_tools = model.bind_tools([get_weather])

# 步骤 1:模型生成工具调用
messages = [{"role": "user", "content": "北京的天气怎么样?"}] # 后面讲消息会详细讲
# 大模型返回给我们的消息
ai_msg = model_with_tools.invoke(messages)
# 追加到messages中了
'''
messages = [
{"role": "user", "content": "北京的天气怎么样?"},
{"role": "assistant", "content": "调用哪个工具:get_weather,参数:北京"}
]
'''
messages.append(ai_msg)

# 步骤 2:执行工具并收集结果
for tool_call in ai_msg.tool_calls:
    # 使用生成的参数执行工具
    tool_result = get_weather.invoke(tool_call)
    # 调用工具:get_weather工具的结果,放到 messages 中
    messages.append(tool_result)

# 步骤 3:将结果传递回模型以获取最终响应
final_response = model_with_tools.invoke(messages)
print(final_response.text)
# 根据查询结果,北京目前天气晴朗。这是一个不错的天气状况,适合外出活动"

# 一套流程-->图--->之前学的functioncalling 就是这个流程呀:需要传入 [工具描述-说明书]--->这个不需要工具描述[说明书]-->自动读取被tool装饰函数的注释doc,自动制作说明书给大模型
# 比之前function calling 简单,但是流程其实一样

# 强制工具调用
# 默认情况下,模型可以根据用户输入自由选择使用哪个绑定的工具。但是,可能希望强制选择工具,确保模型使用特定工具或给定列表中的任何工具:
model_with_tools = model.bind_tools([tool_1,tool_2], tool_choice="any") # 自动选择工具
model_with_tools = model.bind_tools([tool_1,tool_2], tool_choice="tool_1")# 强制选择 tool_1
# 并行工具调用:许多模型支持在适当时并行调用多个工具。这允许模型同时从不同来源收集信息
from langchain.tools import tool
from langchain.chat_models import init_chat_model
model = init_chat_model(
    model="deepseek-chat",
    api_key="sk-8705cb6f2c734663a314a9b33a7bb865",
    # base_url="https://api.deepseek.com",
)

@tool
def get_weather(location: str) -> str:
    """获取某个位置的天气。"""
    return f"{location} 天气晴朗。"


model_with_tools = model.bind_tools([get_weather])

response = model_with_tools.invoke(
    "北京和上海的天气怎么样?"
)

# 模型可能会生成多个工具调用
print(response.tool_calls)
# [{'name': 'get_weather', 'args': {'location': '北京'}, 'id': 'call_00_7JJpVmBtWrOgj5UtvZeXNT87', 'type': 'tool_call'},
# {'name': 'get_weather', 'args': {'location': '上海'}, 'id': 'call_01_m3LH7QYr2oJd8LKaxmiX1eJ6', 'type': 'tool_call'}]

# 执行所有工具(可以使用 async 并行执行) -->图上,我们自己循环调用两次工具
results = []
for tool_call in response.tool_calls:
    if tool_call['name'] == 'get_weather':
        result = get_weather.invoke(tool_call)
    results.append(result)
print(results) # [ToolMessage(content='北京 天气晴朗。', name='get_weather', tool_call_id='call_00_7JJpVmBtWrOgj5UtvZeXNT87'), ToolMessage(content='上海 天气晴朗。', name='get_weather', tool_call_id='call_01_m3LH7QYr2oJd8LKaxmiX1eJ6')]
# 流式传输工具调用-->使用流式,我们需要自己拼接--》麻烦--》用的少

from langchain.tools import tool
from langchain.chat_models import init_chat_model
model = init_chat_model(
    model="deepseek-chat",
    api_key="sk-8705cb6f2c734663a314a9b33a7bb865",
    # base_url="https://api.deepseek.com",
)

@tool
def get_weather(location: str) -> str:
    """获取某个位置的天气。"""
    return f"{location} 天气晴朗。"


model_with_tools = model.bind_tools([get_weather])

for chunk in model_with_tools.stream(
    "上海和北京的天气怎么样?"
):
    # 工具调用块逐步到达
    for tool_chunk in chunk.tool_call_chunks:
        if name := tool_chunk.get("name"):
            print(f"工具:{name}")
        if id_ := tool_chunk.get("id"):
            print(f"ID:{id_}")
        if args := tool_chunk.get("args"):
            print(f"参数:{args}")
print('--------------------------')


# 累积块以构建完整的工具调用
gathered = None
for chunk in model_with_tools.stream("上海的天气怎么样?"):
    gathered = chunk if gathered is None else gathered + chunk
    print(gathered.tool_calls)



1.6 结构化输出

# 1 可以请求模型以匹配给定架构的格式提供其响应。这对于确保输出易于解析并用于后续处理非常有用。LangChain 支持多种架构类型和强制执行结构化输出的方法

# 2 知识点[先看,先理解--》后续会详细讲:有些类没见过]:对象形式返回,字典形式返回,json格式字符串形式返回
    # 1 Pydantic 方式 :把字典转成成python对象,把python对象转成字典--》有校验:类型不匹配会报错
    	-type模块--》类型限制--》函数:入参,返回值规定好类型--》官方模块
        -第三方模块:Pydantic,基础上加强了--》让类型限制更简洁
        -后续 python 官方采纳了 Pydantic--》官方支持模块
        	-python 基础内容
            -https://pydantic.com.cn/
    # 2 TypedDict方式:字典形式
    # 3 JSON Schema :字典形式--我们可以自己转json格式
    # 4 消息输出与解析结构并存
# 1 Pydantic 方式
from pydantic import BaseModel, Field
# 使用兼容模式ChatOpenAI--> 格式化输出报错  --> 开发中遇到什么问题及如何解决的?

# from langchain_openai import ChatOpenAI
# model = ChatOpenAI(
#     model="deepseek-chat", # 模型名称
#     api_key="sk-8705cb6f2c734663a314a9b33a7bb865", # sk 密钥--》不同厂商获取--花钱购买的
#     base_url="https://api.deepseek.com", # 不同模型厂商地址不一样
# )
from langchain.chat_models import init_chat_model
model = init_chat_model(
    model="deepseek-chat",
    api_key="sk-8705cb6f2c734663a314a9b33a7bb865",
    # base_url="https://api.deepseek.com",
)
# 定义一个类:Movie-->必须继承 BaseModel-->Pydantic 写法定义类    movie.title
class Movie(BaseModel):
    """一部带有详细信息的电影。"""
    title: str = Field(..., description="电影标题")
    year: int = Field(..., description="电影上映年份")
    director: str = Field(..., description="电影导演")
    rating: float = Field(..., description="电影评分,满分 10 分")

# 大模型的输出,要符合 Movie 对象格式-->格式
model_with_structure = model.with_structured_output(Movie)
response = model_with_structure.invoke("提供关于电影《盗梦空间》的详细信息")
print(type(response))  # title='盗梦空间' year=2010 director='克里斯托弗·诺兰' rating=8.8

# 打印对象 print(对象) -->输出什么样子,取决于: __str__
# 2 TypedDict方式:TypedDict 提供使用 Python 内置类型的更简单替代方案,适用于不需要运行时验证的情况

from langchain.chat_models import init_chat_model
from typing_extensions import TypedDict, Annotated
model = init_chat_model(
    model="deepseek-chat",
    api_key="sk-8705cb6f2c734663a314a9b33a7bb865",
    # base_url="https://api.deepseek.com",
)

class MovieDict(TypedDict):
    """一部带有详细信息的电影。"""
    title: Annotated[str, ..., "电影标题"]
    year: Annotated[int, ..., "电影上映年份"]
    director: Annotated[str, ..., "电影导演"]
    rating: Annotated[float, ..., "电影评分,满分 10 分"]

model_with_structure = model.with_structured_output(MovieDict)
response = model_with_structure.invoke("提供关于电影《盗梦空间》的详细信息")
print(response)  # {'title': '盗梦空间', 'year': 2010, 'director': '克里斯托弗·诺兰', 'rating': 8.8}
# 3 JSON Schema 为了获得最大控制或互操作性,您可以提供原始 JSON 架构

from langchain.chat_models import init_chat_model
model = init_chat_model(
    model="deepseek-chat",
    api_key="sk-8705cb6f2c734663a314a9b33a7bb865",
    # base_url="https://api.deepseek.com",
)

json_schema = {
    "title": "Movie",
    "description": "一部带有详细信息的电影",
    "type": "object",
    "properties": {
        "title": {
            "type": "string",
            "description": "电影标题"
        },
        "year": {
            "type": "integer",
            "description": "电影上映年份"
        },
        "director": {
            "type": "string",
            "description": "电影导演"
        },
        "rating": {
            "type": "number",
            "description": "电影评分,满分 10 分"
        }
    },
    "required": ["title", "year", "director", "rating"]
}

model_with_structure = model.with_structured_output(
    json_schema,
    method="json_schema",
)
response = model_with_structure.invoke("提供关于电影《盗梦空间》的详细信息")
print(response)  # {'title': '盗梦空间', 'year': 2010, 'director': '克里斯托弗·诺兰', 'rating': 8.8}
# 4 消息输出与解析结构并存:返回原始 AIMessage 对象与解析表示一起以访问响应元数据(如令牌计数)可能很有用。为此,在调用 with_structured_output 时设置 include_raw=True:

from langchain.chat_models import init_chat_model
from pydantic import BaseModel, Field
model = init_chat_model(
    model="deepseek-chat",
    api_key="sk-8705cb6f2c734663a314a9b33a7bb865",
)


class Movie(BaseModel):
    """一部带有详细信息的电影。"""
    title: str = Field(..., description="电影标题")
    year: int = Field(..., description="电影上映年份")
    director: str = Field(..., description="电影导演")
    rating: float = Field(..., description="电影评分,满分 10 分")

model_with_structure = model.with_structured_output(Movie, include_raw=True)
response = model_with_structure.invoke("提供关于电影《盗梦空间》的详细信息")
print(response) # 可以取到对象或字典

1.7 高级主题

# 1 多模态:某些模型可以处理和返回非文本数据,如图像、音频和视频。您可以通过提供内容块将非文本数据传递给模型:使用lanchain + 国产模型sdk 实现
	-正常来讲:LangChain 官方 大模型对接sdk--》可以使用多模态
    -LangChain 官方 没有千问,万象 大模型对接sdk---》openai兼容,社区写的
    	-openai兼容 无法用多模态--》不支持
        -社区写的--》有部分模型也不能用多模态
    -lanchain + 国产模型sdk 实现
    	-dashscope

# 2 模型配置文件

# 3 推理 较新的模型能够执行多步推理以得出结论。这涉及将复杂问题分解为更小、更易管理的步骤。
	如果底层模型支持,您可以显示此推理过程以更好地理解模型如何得出其最终答案
    
# 4 本地模型 ollama
# 5 服务器端工具使用:需要大模型厂商提供
# 6 速率限制
# 7 代理配置
# 8 对数概率
# 9 Token使用情况
# 10 调用配置
# 11 可配置模型
# 1 多模态

# pip install langchain-community  # 包含千问的集成适配器
# pip install dashscope  # 阿里通义千问的官方SDK(必须)
from langchain_community.chat_models import ChatTongyi
model = ChatTongyi (
    model="qwen-vl-max", # 多模态模型
    #model="qwen-image-max", # 文生图模型,但是不支持
    api_key="sk-6459007b813946289da12857950c955b",
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)

response = model.invoke(f"介绍一下自己")
print(response.content)

############目前LangChain对千问的文生图模型支持不好,所以不能直接用千问生图,其他大模型可以############
response = model.invoke("创建一张猫的图片")
print(response.content_blocks)
# 2 模型配置文件
# 2 模型配置文件
from langchain.chat_models import init_chat_model
model = init_chat_model(
    model="deepseek-chat",
    api_key="sk-8705cb6f2c734663a314a9b33a7bb865",
    # base_url="https://api.deepseek.com",
    temperature=0.5
)
print(model.profile) # 模型的一些属性,在这个变量中
'''
# {
#   "max_input_tokens": 400000,
#   "image_inputs": True,
#   "reasoning_output": True,
#   "tool_calling": True,
#   ...
# }
'''
# 3 推理
from langchain.chat_models import init_chat_model
model = init_chat_model(
    model="deepseek-reasoner",
    api_key="sk-8705cb6f2c734663a314a9b33a7bb865",
)
for chunk in model.stream("为什么鹦鹉有五颜六色的羽毛?"):
    reasoning_steps = [r for r in chunk.content_blocks if r["type"] == "reasoning"]
    print(reasoning_steps if reasoning_steps else chunk.text)
print('---------------')
response = model.invoke("为什么鹦鹉有五颜六色的羽毛?")
reasoning_steps = [b for b in response.content_blocks if b["type"] == "reasoning"]
print(" ".join(step["reasoning"] for step in reasoning_steps))
# 4 本地模型 ollama
# https://docs.langchain.com/oss/python/integrations/chat/ollama
# pip install langchain-ollama
from langchain_ollama import ChatOllama
llm = ChatOllama(
    model="qwen3-vl:2b",
    temperature=0,
    # other params...
    base_url="http://localhost:11434",
)
messages = [
    (
        "system",
        "You are a helpful assistant that translates English to French. Translate the user sentence.",
    ),
    ("human", "I love programming."),
]
ai_msg = llm.invoke(messages)
print(ai_msg)
# 5 服务器端工具使用:需要大模型厂商提供
from langchain.chat_models import init_chat_model
model = init_chat_model(
    model="deepseek-reasoner",
    api_key="sk-8705cb6f2c734663a314a9b33a7bb865"
)
# 大模型不能联网-->有的大模型自带联网查询工具
# tool = {"type": "web_search"}
# model_with_tools = model.bind_tools([tool])
model_with_tools = model.bind_tools([])
response = model_with_tools.invoke("今天有什么热点新闻?")
print(response.content_blocks)
# 6 速率限制:https://api-docs.deepseek.com/zh-cn/quick_start/rate_limit
from langchain.chat_models import init_chat_model
from langchain_core.rate_limiters import InMemoryRateLimiter
import time

rate_limiter = InMemoryRateLimiter(
    requests_per_second=0.1,  # 每 10 秒 1 个请求
    check_every_n_seconds=0.1,  # 每 100 毫秒检查是否允许发出请求
    max_bucket_size=10,  # 控制最大突发大小。
)
model = init_chat_model(
    model="deepseek-chat",
    api_key="sk-8705cb6f2c734663a314a9b33a7bb865",
    rate_limiter=rate_limiter
)
for i in range(3):
    start = time.time()
    response = model.invoke("介绍自己?")
    print('时间:',time.time() - start)
    print(response)
# 7 代理配置 对于需要 HTTP 代理的部署,某些模型集成支持代理配置
from langchain_openai import ChatOpenAI

model = ChatOpenAI(
    model="gpt-4o",
    openai_proxy="http://proxy.example.com:8080"
)
# 8 对数概率
from langchain.chat_models import init_chat_model
# model = init_chat_model(
#     model="deepseek-reasoner",
#     api_key="sk-4a782de375c04ad5b62e08dfac8e69b0",
# ).bind(logprobs=True)
# response = model.invoke("为什么鹦鹉会说话?")
# print(response.response_metadata["logprobs"])
#######################或者####
llm = init_chat_model(
    model="deepseek-reasoner",
    api_key="sk-8705cb6f2c734663a314a9b33a7bb865",
    logprobs=True,          # 启用 logprobs
    top_logprobs=5,         # 返回 top-5 token 的 logprobs
    temperature=0           # 通常配合低温使用
)

response = llm.invoke("你好!")
# 你好呀,我是xxx,我爱你。。。
	0             10 
print(response.response_metadata)

什么是“对数概率”(logprobs)?

在 LLM 推理过程中,模型每生成一个 token(词元),都会为词汇表中所有可能的 token分配一个概率,表示“下一个最可能是什么”。

但由于概率值非常小(如 0.000123),直接用浮点数容易下溢(underflow),所以模型内部通常用 对数概率(log probability)来表示:

logprob=log⁡(p)

其中 pp 是该 token 的原始概率( 0<p≤10<p≤1 ),所以 logprob 是 ≤ 0 的负数

  • 越接近 0(如 -0.1),表示概率越高(越确定)
  • 越小(如 -10),表示概率越低(越不确定)

logprobs 本质是模型对每个预测 token 的“置信度”量化

# 9 Token使用情况
# 许多模型提供商将令牌使用信息作为调用响应的一部分返回。当可用时,此信息将包含在相应模型生成的 AIMessage 对象上。# 

### 回调方式
from langchain_openai import ChatOpenAI
from langchain.chat_models import init_chat_model
from langchain_core.callbacks import UsageMetadataCallbackHandler

model_1 = init_chat_model(
    model="deepseek-reasoner",
    api_key="sk-4a782de375c04ad5b62e08dfac8e69b0",
)
model_2 = ChatOpenAI(
    model="qwen-plus",
    api_key="sk-6459007b813946289da12857950c955b",
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)

callback = UsageMetadataCallbackHandler()
result_1 = model_1.invoke("你好", config={"callbacks": [callback]})
result_2 = model_2.invoke("你好", config={"callbacks": [callback]})
print(callback.usage_metadata)
# {
# 'deepseek-reasoner': {'input_tokens': 5, 'output_tokens': 160, 'total_tokens': 165, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 90}}, 
# 'qwen-plus': {'input_tokens': 9, 'output_tokens': 41, 'total_tokens': 50, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}}}


### 上下文管理器方式


from langchain_openai import ChatOpenAI
from langchain.chat_models import init_chat_model
from langchain_core.callbacks import UsageMetadataCallbackHandler
from langchain_core.callbacks import get_usage_metadata_callback
model_1 = init_chat_model(
    model="deepseek-reasoner",
    api_key="sk-4a782de375c04ad5b62e08dfac8e69b0",
)
model_2 = ChatOpenAI(
    model="qwen-plus",
    api_key="sk-6459007b813946289da12857950c955b",
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)

with get_usage_metadata_callback() as cb:
    model_1.invoke("你好")
    model_2.invoke("你好")
    print(cb.usage_metadata)
# {'deepseek-reasoner': {'input_tokens': 5, 'output_tokens': 121, 'total_tokens': 126, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 89}}, 'qwen-plus': {'input_tokens': 9, 'output_tokens': 41, 'total_tokens': 50, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}}}

image-20260301170219925

# 10 调用配置:调用模型时,可以使用 RunnableConfig 字典通过 config 参数传递额外配置。这提供了对执行行为、回调和元数据跟踪的运行时控制。
这些配置值在以下情况下特别有用:
    使用 LangSmith 跟踪进行调试
    实现自定义日志或监控
    在生产中控制资源使用
    在复杂管道中跟踪调用
    关键配置属性
    
from langchain_core.callbacks import UsageMetadataCallbackHandler
from langchain.chat_models import init_chat_model
model = init_chat_model(
    model="deepseek-reasoner",
    api_key="sk-4a782de375c04ad5b62e08dfac8e69b0",
)
my_callback = UsageMetadataCallbackHandler()
response = model.invoke(
    "讲个笑话",
    config={
        "run_name": "joke_generation",      # 此运行的自定义名称
        "tags": ["humor", "demo"],          # 用于分类的标签
        "metadata": {"user_id": "123"},     # 自定义元数据
        "callbacks": [my_callback], # 回调处理程序
    }
)
print(response)

# 11 可配置模型
## 11.1 选择
from langchain.chat_models import init_chat_model
configurable_model = init_chat_model(
    # model="deepseek-reasoner",
    api_key="sk-8705cb6f2c734663a314a9b33a7bb865",
)
response=configurable_model.invoke(
    "介绍自己",
    config={"configurable": {"model": "deepseek-reasoner"}},  # 使用 deepseek-reasoner 运行
)
print(response)
configurable_model.invoke(
    "介绍自己",
    config={"configurable": {"model": "deepseek-chat"}},  # 使用 deepseek-chat 运行
)
print(response)




## 11.2 具有默认值的可配置模型

from langchain.chat_models import init_chat_model
first_model = init_chat_model(
        model="deepseek-reasoner",
    	api_key="sk-4a782de375c04ad5b62e08dfac8e69b0",
        temperature=0,
        configurable_fields=("model", "model_provider", "temperature", "max_tokens"),
        config_prefix="first",  # 当链中有多个模型时很有用
)

response=first_model.invoke("你叫什么名字")
print(response)
response=first_model.invoke(
    "你叫什么名字",
    config={
        "configurable": {
            "first_model": "deepseek-chat",
            "first_temperature": 0.5,
            "first_max_tokens": 100,
        }
    },
)
print(response)

## 11.3 以声明方式使用可配置模型

from langchain.chat_models import init_chat_model
from pydantic import BaseModel, Field
class GetWeather(BaseModel):
    """获取给定位置的当前天气"""
    location: str = Field(..., description="城市和州,例如 San Francisco, CA")
class GetPopulation(BaseModel):
    """获取给定位置的当前人口"""
    location: str = Field(..., description="城市和州,例如 San Francisco, CA")

model = init_chat_model(temperature=0,api_key="sk-4a782de375c04ad5b62e08dfac8e69b0",)

model_with_tools = model.bind_tools([GetWeather, GetPopulation])

print(model_with_tools.invoke(
    "北京天气怎么样", config={"configurable": {"model": "deepseek-reasoner"}}
).tool_calls)

print(model_with_tools.invoke(
    "北京人口多少",config={"configurable": {"model": "deepseek-chat"}},
).tool_calls)

2 LangChain核心组件之 Messages消息

2.1 介绍

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

# 2 消息是包含以下内容的对象:
    角色 - 标识消息类型(例如 system、user,)
    内容 - 表示消息的实际内容(例如文本、图像、音频、文档等)(content)
    元数据 - 可选字段,例如响应信息、消息 ID 和令牌使用情况(id=,。。。)
    
# 3 LangChain 提供了一种标准消息类型,可在所有模型提供商之间工作,确保无论调用哪个模型都能保持一致的行为
	-langchain 的消息对象---》可以通配 任意模型
    -系统消息【系统提示词】:SystemMessage("你是一个小品演员.")
    	-DeepSeek
        -千问
        -都通用,做人物设定
        
     

2.2 基本用法

# 1 基本使用
# 2 文本提示
# 3 消息提示
# 4 字典格式
# 1 基本使用:使用消息的最简单方式是创建消息对象,并在调用时将它们传递给模型。

from langchain.chat_models import init_chat_model
from langchain.messages import HumanMessage, AIMessage, SystemMessage
model = init_chat_model(model='deepseek-chat',api_key="sk-8705cb6f2c734663a314a9b33a7bb865",)
system_msg = SystemMessage("你是一个小品演员.") # 系统提示词
human_msg = HumanMessage("你好啊?")           # 用户提示词
# 与聊天模型一起使用
messages = [system_msg, human_msg]
response = model.invoke(messages)  #   [system_msg,human_msg] 返回 消息  AIMessage
print(response)
# 2 文本提示是字符串 - 适用于不需要保留对话历史的简单生成任务
# 何时使用文本提示:
# 只有一个独立的请求
# 不需要对话历史
# 希望代码复杂度最小

from langchain.chat_models import init_chat_model

model = init_chat_model(model='deepseek-chat', api_key="sk-8705cb6f2c734663a314a9b33a7bb865", )

response = model.invoke("介绍自己")  # 之前一直用,不需要做成消息对象
print(response)
# 3 消息提示 可以通过提供消息对象列表将消息列表传递给模型。
# 何时使用消息提示:
#     管理多轮对话
#     处理多模态内容(图像、音频、文件)
#     包含系统指令
#     字典格式

from langchain.chat_models import init_chat_model
from langchain.messages import SystemMessage, HumanMessage, AIMessage
model = init_chat_model(model='deepseek-chat',api_key="sk-8705cb6f2c734663a314a9b33a7bb865",)

messages = [
    SystemMessage("你是一个话剧演员"),
    HumanMessage("你好啊"),
    # 跟ai交互了一次,返回了AIMessage,追加到 messages --》后续继续追加---》保存上下文
    AIMessage("...")
]
response = model.invoke(messages)
print(response)
# 4 字典格式

from langchain.chat_models import init_chat_model
from langchain.messages import SystemMessage, HumanMessage, AIMessage
model = init_chat_model(model='deepseek-chat',api_key="sk-8705cb6f2c734663a314a9b33a7bb865",)

messages = [
    {"role": "system", "content": "你是一个话剧演员"},  # SystemMessage
    {"role": "user", "content": "介绍一下自己"},   # HumanMessage
    {"role": "assistant", "content": "..."}     # AIMessage
]
response = model.invoke(messages)
print(response)

2.3 消息类型

# 1 SystemMessage  系统消息:人物设定,告诉模型如何行为并为交互提供上下文

# 2 HumanMessage   用户消息:表示用户输入和与模型的交互
	    -基本使用
        -消息原数据
# 3 AIMessage      AI消息: 模型生成的响应,包括文本内容、工具调用和元数据
	    -大模型返回
        -手动创建
        -属性
        -工具调用
    	-令牌使用
        -流式传输和块
# 4 ToolMessage 工具消息:表示工具调用的输出
    	-基本使用
        -属性
        -注意
# 1 系统消息:SystemMessage 表示一组初始指令,用于引导模型的行为。您可以使用系统消息来设置语气、定义模型角色并建立响应指南
from langchain_openai import ChatOpenAI
from langchain.messages import HumanMessage,SystemMessage,AIMessage
model = ChatOpenAI(
    model="qwen-plus",
    api_key="sk-6459007b813946289da12857950c955b",
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)

# system_msg = SystemMessage("你是一个代码助手")
system_msg = SystemMessage("""
You are a senior Python developer with expertise in web frameworks.
Always provide code examples and explain your reasoning.
Be concise but thorough in your explanations.
""")
messages = [
    system_msg,
    HumanMessage("如何创建一个REST API?")
]
response = model.invoke(messages)

print(response)
# 用户消息基本使用和消息元数据
# 2 HumanMessage 表示用户输入和交互。它们可以包含文本、图像、音频、文件以及任何其他多模态内容
from langchain_openai import ChatOpenAI
from langchain.messages import HumanMessage,SystemMessage,AIMessage
model = ChatOpenAI(
    model="qwen-plus",
    api_key="sk-6459007b813946289da12857950c955b",
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)
### 1 基本使用
# 方式一:
response = model.invoke([
    HumanMessage("什么是机器学习?")
])
# 方式二:使用字符串是单个 HumanMessage 的快捷方式
# response = model.invoke("什么是机器学习?")
# 方式三:字典格式
# response = model.invoke({"role": "user", "content": "什么是机器学习?"})


### 2 消息原数据
human_msg = HumanMessage(
    content="你好!",
    name="lqz",  # 可选:标识不同用户
    id="lqz_616564099",  # 可选:用于追踪的唯一标识符
)
response = model.invoke([
    human_msg
])
print(response)
# AI消息:
    -大模型返回:就是AI消息
    -手动创建:ai_msg = AIMessage("I'd be happy to help you with that question!")
    -属性:AI消息中有很多属性
    -工具调用:拿到调用工具的名字和参数
    -令牌使用:获取消耗token
    -流式传输和块:stream形式调用大模型
# 3 AIMessage 表示模型调用的输出。它们可以包含多模态数据、工具调用和提供商特定的元数据,您可以稍后访问
from langchain_openai import ChatOpenAI
from langchain.messages import HumanMessage,SystemMessage,AIMessage
model = ChatOpenAI(
    model="qwen-plus",
    api_key="sk-6459007b813946289da12857950c955b",
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)
### 1 对象由调用模型时返回,其中包含响应中的所有关联元数据
# response = model.invoke("解释AI")
# print(type(response))  # <class 'langchain_core.messages.AIMessage'>

### 2 提供商对不同类型的消息的权重/上下文处理不同,这意味着有时手动创建新的 AIMessage 对象并将其插入消息历史中就像来自模型一样很有帮助
# 手动创建 AI 消息(例如,用于对话历史)
ai_msg = AIMessage("I'd be happy to help you with that question!")
# # 添加到对话历史
messages = [
    SystemMessage("You are a helpful assistant"),
    HumanMessage("Can you help me?"),
    ai_msg,  # 插入就像来自模型一样
    HumanMessage("Great! What's 2+2?")
]
# response=model.invoke(messages) # AI消息对象

### 3 属性  response.属性
'''
text (string)
消息的文本内容。

content (string | dict[])  # 包含的更多,有些废话
消息的原始内容。

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

tool_calls (dict[] | None)  # 之前用过:调用工具的名字和参数
模型进行的工具调用。如果没有调用工具,则为空。

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

usage_metadata (dict | None)  # 之前用过:使用了多少token。。。
消息的使用元数据,可包含可用时的令牌计数。

response_metadata (ResponseMetadata | None)
消息的响应元数据

'''

### 4 工具调用:当模型进行工具调用时,它们包含在 AIMessage 中
def get_weather(location: str) -> str:
    """Get the weather at a location."""
    return f'{str}天气晴朗'

model_with_tools = model.bind_tools([get_weather])
response = model_with_tools.invoke("上海天气怎么样?")

for tool_call in response.tool_calls:
    print(f"Tool: {tool_call['name']}")  #  get_weather
    print(f"Args: {tool_call['args']}") # 上海
    print(f"ID: {tool_call['id']}")    # call_fcb0a65e32b94d3592c423


### 5 token使用:AIMessage 可以在其 usage_metadata 字段中保存令牌计数和其他使用元数据
response = model.invoke("Hello!")
print(response.usage_metadata)
# {'input_tokens': 10, 'output_tokens': 11, 'total_tokens': 21, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}}

### 6 流式传输和块 :在流式传输期间,您将收到可以组合成完整消息对象的 AIMessageChunk 对象
chunks = []
full_message = None
for chunk in model.stream("你好"):
    chunks.append(chunk)
    print(chunk.text)
    full_message = chunk if full_message is None else full_message + chunk
print(full_message)
# 4 工具消息:对于支持工具调用的模型,AI 消息可以包含工具调用。工具消息用于将单个工具执行的结果传回模型。 工具 可以直接生成 ToolMessage 对象
from langchain_openai import ChatOpenAI
from langchain.messages import HumanMessage,SystemMessage,AIMessage,ToolMessage
model = ChatOpenAI(
    model="qwen-plus",
    api_key="sk-6459007b813946289da12857950c955b",
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)
### 1 基本使用
# 假设问了模型  上海天气怎么样---》返回AI消息:就是如下格式
ai_message = AIMessage(
    content=[],
    tool_calls=[{
        "name": "get_weather",
        "args": {"location": "上海"},
        "id": "call_123"
    }]
)

###  1.1 假设执行了工具执行工具并拿到工具结果
weather_result = "上海天气晴朗"
## 1.2 创建工具消息
tool_message = ToolMessage(
    content=weather_result,
    tool_call_id="call_123"  # 必须匹配调用 ID
)

# 继续对话
messages = [
    HumanMessage("上海天气如何?"),
    ai_message,  # 模型的工具调用
    tool_message,  # 工具执行结果
]
response = model.invoke(messages)  # 模型处理结果
print(response)


### 2 属性
'''
content (string, 必需)
工具调用的字符串化输出。

tool_call_id (string, 必需)
此消息响应的工具调用的 ID。(必须匹配 AIMessage 中的工具调用 ID)

name (string, 必需)
被调用的工具的名称。

artifact (dict)
不发送给模型但可以以编程方式访问的附加数据。
'''

### 3 注意:artifact 字段存储不会发送给模型但可以以编程方式访问的补充数据。这对于存储原始结果、调试信息或下游处理的数据而不会使模型上下文杂乱很有用。
'''
示例:使用 artifact 存储检索元数据
例如,检索工具可以从文档中检索一段文本供模型参考。其中消息 content 包含模型将参考的文本,而 artifact 可以包含应用程序可以使用的文档标识符或其他元数据(例如,用于渲染页面)
'''
# 发送给模型
message_content = "那是最好的时代,那也是最坏的时代."
# 下游可用的 artifact
artifact = {"document_id": "doc_123", "page": 0}
tool_message = ToolMessage(
    content=message_content, # 调用工具:search_books搜索图书,返回文字:message_content
    tool_call_id="call_123",
    name="search_books",
    artifact=artifact,# 不会发送给模型,但是后期要使用该字段,可以使用代码获取
)
messages = [
    tool_message,  # 工具执行结果
]
response = model.invoke(messages)  # 模型处理结果
print(response)
# 后续程序中使用的参数: tool_message.artifact.get(page+1)

2.4 消息内容

# 1 是什么
# 2 标准内容块
# 3 多模态
# 4 内容块参考
# 1 消息内容是什么
'''
1 可以将消息的内容视为发送给模型的数据负载。消息具有一个松散类型的 content 属性,支持字符串和未类型对象列表(例如字典)。这允许在 LangChain 聊天模型中直接支持提供商原生结构,例如多模态内容和其他数据。

2 LangChain 另外为文本、推理、引用、多模态数据、服务器端工具调用和其他消息内容提供了专用内容类型

3 LangChain 聊天模型接受 content 属性中的消息内容,可以包含:
    一个字符串
    提供商原生格式的内容块列表
    LangChain 的标准内容块列表
'''
from langchain_openai import ChatOpenAI
from langchain.messages import HumanMessage,SystemMessage,AIMessage,ToolMessage
model = ChatOpenAI(
    model="qwen-plus",
    api_key="sk-6459007b813946289da12857950c955b",
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)
# 字符串内容
human_message = HumanMessage("你好?")
# 提供商原生格式(例如 OpenAI)
human_message = HumanMessage(content=[
    {"type": "text", "text": "你好?"},
    {"type": "image_url", "image_url": {"url": "https://example.com/image.jpg"}}
])
# 标准内容块列表:在初始化消息时指定 content_blocks 仍将填充消息 content,但提供了一个类型安全的接口
human_message = HumanMessage(content_blocks=[
    {"type": "text", "text": "你好?"},
    {"type": "image", "url": "https://example.com/image.jpg"},
])
response = model.invoke([human_message])
print(response)
# 2 标准内容块 :LangChain 提供了一种跨提供商工作的消息内容的标准表示。消息对象实现了 content_blocks 属性,该属性将延迟解析 content 属性为标准、类型安全的表示。例如,从 anthropic或ChatOpenAI 生成的消息将以各自提供商的格式包含 thinking 或 reasoning 块,但可以延迟解析为一致的 ReasoningContentBlock 表示
from langchain_openai import ChatOpenAI
from langchain.messages import HumanMessage,SystemMessage,AIMessage,ToolMessage
### 1 下面两种方式的AIMessage【anthropic或openai返回】,都可以通过调用content_blocks,得到ReasoningContentBlock,从而实现格式一致、
### 方式一
message = AIMessage(
    content=[
        {"type": "thinking", "thinking": "...", "signature": "WaUjzkyp..."},
        {"type": "text", "text": "..."},
    ],
    response_metadata={"model_provider": "anthropic"}
)
print(message.content_blocks)
###  2 方式二
message = AIMessage(
    content=[
        {
            "type": "reasoning",
            "id": "rs_abc123",
            "summary": [
                {"type": "summary_text", "text": "summary 1"},
                {"type": "summary_text", "text": "summary 2"},
            ],
        },
        {"type": "text", "text": "...", "id": "msg_abc123"},
    ],
    response_metadata={"model_provider": "openai"}
)
print(message.content_blocks)
# 3 多模态:多模态指的是处理以不同形式出现的数据的能力,例如文本、音频、图像和视频。LangChain 包含可跨提供商使用的这些数据的标准类型。聊天模型 可以接受多模态数据作为输入并生成作为输出。下面展示包含多模态数据的输入消息的简短示例
### 图像输入
# 从 URL
message = {
    "role": "user",
    "content": [
        {"type": "text", "text": "描述这个图片内容."},
        {"type": "image", "url": "https://example.com/path/to/image.jpg"},
    ]
}

# 从 base64 数据
message = {
    "role": "user",
    "content": [
        {"type": "text", "text": "描述这个图片内容."},
        {
            "type": "image",
            "base64": "AAAAIGZ0eXBtcDQyAAAAAGlzb21tcDQyAAACAGlzb2...",
            "mime_type": "image/jpeg",
        },
    ]
}

# 从提供商管理的文件 ID
message = {
    "role": "user",
    "content": [
        {"type": "text", "text": "描述这个图片内容."},
        {"type": "image", "file_id": "file-abc123"},
    ]
}
### PDF 文档输入
# 从 URL
message = {
    "role": "user",
    "content": [
        {"type": "text", "text": "描述这个文档的内容."},
        {"type": "file", "url": "https://example.com/path/to/document.pdf"},
    ]
}

# 从 base64 数据
message = {
    "role": "user",
    "content": [
        {"type": "text", "text": "描述这个文档的内容."},
        {
            "type": "file",
            "base64": "AAAAIGZ0eYBtcDQyAAAAAGlzb21tcDQyAAACAGlzb2...",
            "mime_type": "application/pdf",
        },
    ]
}

# 从提供商管理的文件 ID
message = {
    "role": "user",
    "content": [
        {"type": "text", "text": "描述这个文档的内容."},
        {"type": "file", "file_id": "file-abc123"},
    ]
}
### 音频输入
# 从 base64 数据
message = {
    "role": "user",
    "content": [
        {"type": "text", "text": "描述这段音频内容."},
        {
            "type": "audio",
            "base64": "AAAAIGZ0eXBtcDQyAAAAAGlzb21tcDQyAAACAGlzb2...",
            "mime_type": "audio/wav",
        },
    ]
}

# 从提供商管理的文件 ID
message = {
    "role": "user",
    "content": [
        {"type": "text", "text": "描述这段音频内容."},
        {"type": "audio", "file_id": "file-abc123"},
    ]
}
### 视频输入
# 从 base64 数据
message = {
    "role": "user",
    "content": [
        {"type": "text", "text": "描述这段视频内容."},
        {
            "type": "video",
            "base64": "AAAAIGZ0eYBtcDQyAAAAAGlzb21tcDQyAAACAGlzb2...",
            "mime_type": "video/mp4",
        },
    ]
}

# 从提供商管理的文件 ID
message = {
    "role": "user",
    "content": [
        {"type": "text", "text": "描述这段视频内容."},
        {"type": "video", "file_id": "file-abc123"},
    ]
}

# 4 内容块参考 内容块在创建消息或访问 content_blocks 属性时表示为类型化字典列表。列表中的每个项目必须遵守以下块类型之一
	-核心
    -多模态
    -工具调用
    -服务器端工具执行
    -提供商特定块
### 核心
''' 
1 TextContentBlock - 用途: 标准文本输出
	-type (string, 必需) :始终为 "text"
	-text (string, 必需):文本内容
	-annotations (object[]):文本的注释列表
	-extras (object):额外的提供商特定数据
示例:
message = {
    "role": "user",
    "content": [
        {
            "type": "text",
            "text": "讲个笑话",
            "annotations": []
        }
    ]
}

2 ReasoningContentBlock - 用途: 模型推理步骤
	-type (string, 必需) :始终为 "text"
	-reasoning  (string, 必需):推理内容
	-extras (object):额外的提供商特定数据
示例:
{
    "type": "reasoning",
    "reasoning": "The user is asking about...",
    "extras": {"signature": "abc123"},
}
'''
### 多模态
'''
1 ImageContentBlock - 用途: 图像数据
    -type (string, 必需):始终为 "image"
    -url (string):指向图像位置的 URL。
    -base64 (string):Base64 编码的图像数据。
    -id (string):引用外部存储的图像的引用 ID(例如,在提供商的文件系统或存储桶中)。
    -mime_type (string):图像 MIME 类型(例如,image/jpeg、image/png)

2 AudioContentBlock -  用途: 音频数据
    -type (string, 必需): 始终为 "audio"
    -url (string):指向音频位置的 URL。
    -base64 (string):Base64 编码的音频数据。
    -id (string):引用外部存储的音频文件的引用 ID。
    -mime_type (string):音频 MIME 类型(例如,audio/mpeg、audio/wav)

3 VideoContentBlock - 用途: 视频数据
    -type (string, 必需):始终为 "video"
    -url (string):指向视频位置的 URL。
    -base64 (string):Base64 编码的视频数据。
    -id (string):引用外部存储的视频文件的引用 ID。
    -mime_type (string):视频 MIME 类型(例如,video/mp4、video/webm)

4 FileContentBlock - 用途: 通用文件(PDF 等)
    -type (string, 必需):始终为 "file"
    -url (string):指向文件位置的 URL。
    -base64 (string):Base64 编码的文件数据。
    -id (string):引用外部存储的文件的引用 ID。
    -mime_type (string):文件 MIME 类型(例如,application/pdf)

5 PlainTextContentBlock - 用途: 文档文本(.txt、.md)
    -type (string, 必需):始终为 "text-plain"
    -text (string):文本内容
    -mime_type (string):文本的 MIME 类型(例如,text/plain、text/markdown)
'''

### 工具调用
'''
1 ToolCall - 用途: 函数调用
    -type (string, 必需):始终为 "tool_call"
    -name (string, 必需):要调用的工具的名称
    -args (object, 必需):要传递给工具的参数
    -id (string, 必需):此工具调用的唯一标识符
示例:
message = {
    "role": "user",
    "content": [
        {
            "type": "tool_call",
            "name": "get_weather",
            "args": {"query": "北京"},
            "id": "call_123"
        }
    ]
}


2 ToolCallChunk - 用途: 流式工具调用片段
    -type (string, 必需):始终为 "tool_call_chunk"
    -name (string):正在调用的工具的名称
    -args (string):部分工具参数(可能是不完整的 JSON)
    -id (string):工具调用标识符
    -index (number | string):此块在流中的位置


3 InvalidToolCall - 用途: 格式错误的调用,用于捕获 JSON 解析错误。
    -type (string, 必需):始终为 "invalid_tool_call"
    -name (string):未能调用的工具的名称
    -args (object):要传递给工具的参数
    -error (string):出错的描述

'''

### 服务器端工具执行
'''
1 ServerToolCall - 用途: 服务器端执行的工具调用。
    -type (string, 必需):始终为 "server_tool_call"
    -id (string, 必需):与工具调用关联的标识符。
    -name (string, 必需):要调用的工具的名称。
    -args (string, 必需):部分工具参数(可能是不完整的 JSON)

2 ServerToolCallChunk - 用途: 流式服务器端工具调用片段
    -type (string, 必需):始终为 "server_tool_call_chunk"
    -id (string):与工具调用关联的标识符。
    -name (string):正在调用的工具的名称
    -args (string):部分工具参数(可能是不完整的 JSON)
    -index (number | string):此块在流中的位置
3 ServerToolResult - 用途: 搜索结果
    -type (string, 必需):始终为 "server_tool_result"
    -tool_call_id (string, 必需):对应服务器工具调用的标识符。
    -id (string):与服务器工具结果关联的标识符。
    -status (string, 必需):服务器端工具的执行状态。"success" 或 "error"。
    -output:执行工具的输出。
'''

### 提供商特定块
'''
1 NonStandardContentBlock - 用途: 提供商特定的逃生舱
    -type (string, 必需):始终为 "non_standard"
    -value (object, 必需):提供商特定的数据结构
用法: 用于实验性或提供商独特的功能
每个模型提供商的参考文档中可能包含其他提供商特定的内容类型
'''
posted @ 2026-03-19 19:56  凫弥  阅读(3)  评论(0)    收藏  举报