大型语言模型(LLMs) 是强大的人工智能工具,能够像人类一样理解和生成文本。它们功能多样,无需为每项任务进行专门训练,即可撰写内容、翻译语言、总结信息和回答问题。
除了文本生成,许多模型还支持:
工具调用 - 调用外部工具(如数据库查询或 API 调用),并在其响应中使用结果。
结构化输出 - 模型的响应被约束为遵循预定义的格式。
多模态 - 处理并返回除文本以外的数据,如图像、音频和视频。
推理 - 模型执行多步推理以得出结论。
有关特定提供商的集成信息和能力,请参阅提供商的集成页面 。
基本用法
在 LangChain 中开始使用模型最简单的方法是使用 init_chat_model 从您选择的提供商 初始化一个模型:
from langchain.chat_models import init_chat_model
model = init_chat_model( "openai:gpt-5-nano" )
response = model.invoke( "为什么鹦鹉会说话?" )
更多详情请参见 init_chat_model 。
关键方法
调用 模型以消息作为输入,在生成完整响应后输出消息。
批处理 批量向模型发送多个请求,以实现更高效的处理。
除了聊天模型,LangChain 还支持其他相关技术,例如嵌入模型和向量存储。详情请参阅集成页面 。
聊天模型接受可用于配置其行为的参数。支持的完整参数集因模型和提供商而异,但标准参数包括:
与模型提供商进行身份验证所需的密钥。通常在您注册获取模型访问权限时颁发。通常通过设置环境变量 来访问。
控制模型输出的随机性。较高的数值使响应更具创造性;较低的数值使其更具确定性。
在取消请求之前等待模型响应的最长时间(以秒为单位)。
如果请求因网络超时或速率限制等问题失败,系统将重试发送请求的最大次数。
要查找给定聊天模型支持的所有参数,请前往参考文档 。
必须调用聊天模型才能生成输出。有三种主要的调用方法,每种方法适用于不同的用例。
每种调用方法都有一个异步 等效方法,通常以字母 'a' 为前缀。 例如:ainvoke()、astream()、abatch()。 完整的异步方法列表可在参考文档 中找到。
调用模型最直接的方法是使用 invoke() 并传入单条消息或消息列表。
response = model.invoke( "为什么鹦鹉有彩色的羽毛?" )
print (response)
可以向模型提供消息列表以表示对话历史。每条消息都有一个角色,模型使用该角色来指示对话中发送消息的人。有关角色、类型和内容的更多详细信息,请参阅消息 指南。
from langchain.messages import HumanMessage, AIMessage, SystemMessage
conversation = [
SystemMessage( "你是一个将英语翻译成法语的助手。" ),
HumanMessage( "翻译:我喜欢编程。" ),
AIMessage( "J'adore la programmation." ),
HumanMessage( "翻译:我喜欢构建应用程序。" )
]
response = model.invoke(conversation)
print (response) # AIMessage("J'adore créer des applications.")
流式传输
大多数模型可以在生成输出内容时对其进行流式传输。通过逐步显示输出,流式传输显著改善了用户体验,特别是对于较长的响应。
调用 stream() 会返回一个迭代器 ,该迭代器在生成输出块时产生输出块。您可以使用循环实时处理每个块:
for chunk in model.stream( "为什么鹦鹉有彩色的羽毛?" ):
print (chunk.text, end = "|" , flush = True )
与在模型生成完整响应后返回单个 AIMessage 的 invoke() 不同,stream() 返回多个 AIMessageChunk 对象,每个对象包含输出文本的一部分。重要的是,流中的每个块都设计为可以通过求和聚合成完整的消息:
full = None # None | AIMessageChunk
for chunk in model.stream( "天空是什么颜色?" ):
full = chunk if full is None else full + chunk
print (full.text)
# 天
# 天空
# 天空是
# 天空通常是
# 天空通常是蓝色的
# ...
print (full.content_blocks)
# [{"type": "text", "text": "天空通常是蓝色的..."}]
生成的消息可以像使用 invoke() 生成的消息一样处理——例如,它可以聚合成消息历史并作为对话上下文传回给模型。
仅当程序中的所有步骤都知道如何处理块流时,流式传输才有效。例如,一个不具备流式传输能力的应用程序是需要在处理之前将整个输出存储在内存中的应用程序。
LangChain 通过在某些情况下自动启用流式传输模式来简化从聊天模型进行流式传输,即使您没有显式调用流式传输方法。当您使用非流式传输的调用方法但仍希望流式传输整个应用程序(包括聊天模型的中间结果)时,这特别有用。 例如,在 LangGraph 代理 中,您可以在节点内调用 model.invoke(),但如果在流式传输模式下运行,LangChain 会自动委托给流式传输。 工作原理 当您 invoke() 一个聊天模型时,如果 LangChain 检测到您正在尝试流式传输整个应用程序,它将自动切换到内部流式传输模式。就使用调用的代码而言,调用的结果是相同的;然而,在流式传输聊天模型时,LangChain 将负责在 LangChain 的回调系统中调用 on_llm_new_token 事件。 回调事件允许 LangGraph stream() 和 astream_events() 实时显示聊天模型的输出。
LangChain 聊天模型还可以使用 astream_events() 流式传输语义事件。 这简化了基于事件类型和其他元数据的过滤,并将在后台聚合完整的消息。请参见下面的示例。 async for event in model.astream_events( "你好" ):
if event[ "event" ] == "on_chat_model_start" :
print ( f "输入: { event[ 'data' ][ 'input' ] } " )
elif event[ "event" ] == "on_chat_model_stream" :
print ( f "令牌: { event[ 'data' ][ 'chunk' ].text } " )
elif event[ "event" ] == "on_chat_model_end" :
print ( f "完整消息: { event[ 'data' ][ 'output' ].text } " )
else :
pass
输入:你好
令牌:嗨
令牌: 那里
令牌:!
令牌: 我
令牌: 可以
令牌: 我
...
完整消息:嗨那里!我今天能帮什么忙?
有关事件类型和其他详细信息,请参见 astream_events() 参考。
批处理
对模型的一组独立请求进行批处理可以显著提高性能并降低成本,因为处理可以并行进行:
responses = model.batch([
"为什么鹦鹉有彩色的羽毛?" ,
"飞机如何飞行?" ,
"什么是量子计算?"
])
for response in responses:
print (response)
本节描述的是聊天模型方法 batch(),它在客户端并行化模型调用。 它与推理提供商支持的批处理 API 不同 ,例如 OpenAI 或 Anthropic 。
默认情况下,batch() 只会返回整个批处理的最终输出。如果您希望在每个输入完成生成时接收其输出,可以使用 batch_as_completed() 流式传输结果:
for response in model.batch_as_completed([
"为什么鹦鹉有彩色的羽毛?" ,
"飞机如何飞行?" ,
"什么是量子计算?"
]):
print (response)
使用 batch_as_completed() 时,结果可能会乱序到达。每个结果都包含输入索引,以便在需要时匹配以重建原始顺序。
使用 batch() 或 batch_as_completed() 处理大量输入时,您可能希望控制最大并行调用数。这可以通过在 RunnableConfig 字典中设置 max_concurrency 属性来完成。 model.batch(
list_of_inputs,
config = {
'max_concurrency' : 5 , # 限制为 5 个并行调用
}
)
有关支持的属性的完整列表,请参见 RunnableConfig 参考。
有关批处理的更多详细信息,请参见 参考 。
工具调用
模型可以请求调用执行任务的工具,例如从数据库获取数据、搜索网络或运行代码。工具是以下内容的配对:
一个模式,包括工具的名称、描述和/或参数定义(通常是一个 JSON 模式)
一个函数或协程 来执行。
您可能会听到“函数调用”这个术语。我们将其与“工具调用”互换使用。
要使您定义的工具可供模型使用,必须使用 bind_tools() 将其绑定。在后续调用中,模型可以根据需要选择调用任何绑定的工具。
一些模型提供商提供可以通过模型参数启用的内置工具。有关详细信息,请参阅相应的提供商参考 。
有关创建工具的详细信息和其他选项,请参阅工具指南 。
from langchain_core.tools import tool
@tool
def get_weather ( location : str ) -> str :
"""获取某个位置的天气。"""
return f " { location } 的天气晴朗。"
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' ] } " )
print ( f "参数: { tool_call[ 'args' ] } " )
绑定用户定义的工具时,模型的响应包括执行工具的请求 。由您执行请求的操作并将结果返回给模型,以便在后续推理中使用。
下面,我们展示了一些使用工具调用的常见方法。
当模型返回工具调用时,您需要执行工具并将结果传回给模型。这会创建一个对话循环,模型可以使用工具结果生成其最终响应。 # 将(可能多个)工具绑定到模型
model_with_tools = model.bind_tools([get_weather])
# 第 1 步:模型生成工具调用
messages = [{ "role" : "user" , "content" : "波士顿的天气怎么样?" }]
ai_msg = model_with_tools.invoke(messages)
messages.append(ai_msg)
# 第 2 步:执行工具并收集结果
for tool_call in ai_msg.tool_calls:
# 使用生成的参数执行工具
tool_result = get_weather.invoke(tool_call)
messages.append(tool_result)
# 第 3 步:将结果传回给模型以生成最终响应
final_response = model_with_tools.invoke(messages)
print (final_response.text)
# "波士顿当前的天气是 72°F,晴朗。"
工具返回的每个 ToolMessage 都包含一个 tool_call_id,该 ID 与原始工具调用匹配,帮助模型将结果与请求关联起来。
默认情况下,模型可以根据用户的输入自由选择使用哪个绑定工具。但是,您可能希望强制选择工具,确保模型使用特定工具或给定列表中的任何 工具: model_with_tools = model.bind_tools([tool_1], tool_choice = "any" )
许多模型在适当的情况下支持并行调用多个工具。这允许模型同时从不同来源收集信息。 model_with_tools = model.bind_tools([get_weather])
response = model_with_tools.invoke(
"波士顿和东京的天气怎么样?"
)
# 模型可能会生成多个工具调用
print (response.tool_calls)
# [
# {'name': 'get_weather', 'args': {'location': 'Boston'}, 'id': 'call_1'},
# {'name': 'get_time', 'args': {'location': 'Tokyo'}, 'id': 'call_2'}
#]
# 执行所有工具(可以使用异步并行执行)
results = []
for tool_call in response.tool_calls:
if tool_call[ 'name' ] == 'get_weather' :
result = get_weather.invoke(tool_call)
...
results.append(result)
模型根据所请求操作的独立性智能地确定何时适合并行执行。
流式传输响应时,工具调用通过 ToolCallChunk 逐步构建。这允许您在生成工具调用时查看它们,而不是等待完整响应。 for chunk in model_with_tools.stream(
"波士顿和东京的天气怎么样?"
):
# 工具调用块逐步到达
if chunk.tool_call_chunks:
for tool_chunk in chunk.tool_call_chunks:
print ( f "工具: { tool_chunk.get( 'name' , '' ) } " )
print ( f "参数: { tool_chunk.get( 'args' , '' ) } " )
# 输出:
# 工具:get_weather # 循环 1
# 参数:
# 工具: # 循环 2
# 参数:{"loc
# 工具: # 循环 3
# 参数:ation": "BOS"}
# 工具:get_time # 循环 4
# 参数:
# 参数:
# 工具: # 循环 5
# 参数:{"timezone": "Tokyo"}
您可以累积块以构建完整的工具调用: gathered = None
for chunk in model_with_tools.stream( "波士顿的天气怎么样?" ):
gathered = chunk if gathered is None else gathered + chunk
print (gathered.content_blocks)
结构化输出
可以请求模型以匹配给定模式的格式提供其响应。这对于确保输出可以轻松解析并在后续处理中使用非常有用。LangChain 支持多种模式类型和强制执行结构化输出的方法。
Pydantic
TypedDict
JSON 模式
Pydantic 模型 提供最丰富的功能集,包括字段验证、描述和嵌套结构。from pydantic import BaseModel, Field
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)
response = model_with_structure.invoke( "提供电影《盗梦空间》的详细信息" )
print (response) # Movie(title="盗梦空间", year=2010, director="克里斯托弗·诺兰", rating=8.8)
以下是您提供的英文技术文档的中文翻译:
结构化输出的关键注意事项:
方法参数 :部分提供商支持不同的方法('json_schema'、'function_calling'、'json_mode')
包含原始响应 :使用 include_raw=True 可同时获取解析后的输出和原始 AI 消息
验证机制 :Pydantic 模型提供自动验证,而 TypedDict 和 JSON Schema 需要手动验证
有时需要同时返回原始 AIMessage 对象和解析后的表示形式,以便访问响应元数据(例如 token 使用量 ): from pydantic import BaseModel, Field
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( "提供电影《盗梦空间》的详细信息" )
response
# {
# "raw": AIMessage(...),
# "parsed": Movie(title=..., year=..., ...),
# "parsing_error": None,
# }
Pydantic BaseModel
TypedDict
from pydantic import BaseModel, Field
class Actor ( BaseModel ):
name: str
role: str
class MovieDetails ( BaseModel ):
title: str
year: int
cast: list[Actor]
genres: list[ str ]
budget: float | None = Field( None , description = "预算(单位:百万美元)" )
model_with_structure = model.with_structured_output(MovieDetails)
支持的模型
LangChain 支持所有主流模型提供商,包括 OpenAI、Anthropic、Google、Azure、AWS Bedrock 等。每个提供商都提供多种具备不同能力的模型。如需查看 LangChain 支持的完整模型列表,请参阅 集成页面 。
高级配置
多模态支持
某些模型可以处理并返回非文本数据,如图像、音频和视频。您可以通过提供 内容块 向模型传递非文本数据。
所有具备底层多模态能力的 LangChain 聊天模型均支持:
跨提供商的标准数据格式(请参阅 消息指南 )
OpenAI 的 聊天补全格式
特定提供商的原生格式(例如,Anthropic 模型接受其原生格式)
详情请参阅消息指南中的 多模态章节 。
某些模型也可以在响应中返回多模态数据。在这种情况下,生成的 AIMessage 将包含具有多模态类型的内容块。
response = model.invoke( "生成一张猫的图片" )
print (response.content_blocks)
# [
# {"type": "text", "text": "这是一张猫的图片"},
# {"type": "image", "base64": "...", "mime_type": "image/jpeg"},
# ]
有关具体提供商的详细信息,请参阅 集成页面 。
推理能力
较新的模型能够执行多步推理以得出结论。这包括将复杂问题分解为更小、更易管理的步骤。
如果底层模型支持,您可以暴露这一推理过程,以便更好地理解模型是如何得出最终答案的。
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)
根据模型的不同,您有时可以指定模型应投入多少精力进行推理。或者,您可以要求模型完全关闭推理功能。这可能以推理“层级”(例如 'low' 或 'high')或整数 token 预算的形式体现。
详情请参阅 集成页面 中的相关聊天模型说明。
本地模型
LangChain 支持在您自己的硬件上本地运行模型。这在数据隐私要求严格或希望避免使用云端模型成本的场景中非常有用。
Ollama 是本地运行模型最简单的方式之一。完整的本地集成列表请参阅 集成页面 。
缓存机制
聊天模型 API 的调用通常较慢且昂贵。为缓解这一问题,LangChain 为聊天模型集成提供了可选的缓存层。
默认情况下缓存是禁用的。要启用缓存,请导入: from langchain_core.globals import set_llm_cache
接下来,选择一个缓存:
一种临时缓存,将模型调用存储在内存中。环境重启后会被清除,且不跨进程共享。 from langchain_core.caches import InMemoryCache
set_llm_cache(InMemoryCache())
response = model.invoke( "讲个笑话" )
response = model.invoke( "讲个笑话" ) # 快速,来自缓存
使用 SQLite 数据库存储响应,重启后依然有效 # 也可以使用 SQLite 缓存
from langchain_community.cache import SQLiteCache
set_llm_cache(SQLiteCache( database_path = ".langchain.db" ))
response = model.invoke( "讲个笑话" )
response = model.invoke( "讲个笑话" ) # 快速,来自缓存
速率限制
许多聊天模型提供商对单位时间内可执行的调用次数设置了限制。如果您触发了速率限制,通常会收到来自提供商的速率限制错误响应,需要等待一段时间后才能继续请求。
为帮助管理速率限制,聊天模型集成在初始化时接受一个 rate_limiter 参数,用于控制请求速率。
LangChain 内置(可选)的内存速率限制器。该限制器是线程安全的,可被同一进程中的多个线程共享。 from langchain_core.rate_limiters import InMemoryRateLimiter
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 = "gpt-5" ,
model_provider = "openai" ,
rate_limiter = rate_limiter
)
提供的速率限制器只能限制单位时间内的请求数量。如果您还需要根据请求大小进行限制,则无能为力。
基础 URL 或代理
对于许多聊天模型集成,您可以配置 API 请求的基础 URL,从而使用具有 OpenAI 兼容 API 的模型提供商或通过代理服务器访问。
许多模型提供商提供 OpenAI 兼容的 API(例如 Together AI 、vLLM )。您可以通过指定适当的 base_url 参数,在 init_chat_model 中使用这些提供商: model = init_chat_model(
model = "MODEL_NAME" ,
model_provider = "openai" ,
base_url = "BASE_URL" ,
api_key = "YOUR_API_KEY" ,
)
当直接实例化聊天模型类时,参数名称可能因提供商而异。请查阅相应的 参考文档 以获取详细信息。
对于需要 HTTP 代理的部署,部分模型集成支持代理配置: from langchain_openai import ChatOpenAI
model = ChatOpenAI(
model = "gpt-4o" ,
openai_proxy = "http://proxy.example.com:8080"
)
代理支持因集成而异。请查阅具体模型提供商的 参考文档 以了解代理配置选项。
对数概率(Log Probabilities)
某些模型可以配置为返回 token 级别的对数概率,表示给定 token 的可能性。只需在初始化模型时设置 logprobs 参数即可访问:
model = init_chat_model(
model = "gpt-4o" ,
model_provider = "openai"
).bind( logprobs = True )
response = model.invoke( "为什么鹦鹉会说话?" )
print (response.response_metadata[ "logprobs" ])
Token 使用量
许多模型提供商在调用响应中返回 token 使用量信息。当可用时,这些信息将包含在相应模型生成的 AIMessage 对象中。更多详情请参阅 消息指南 。
某些提供商 API(特别是 OpenAI 和 Azure OpenAI 聊天补全)要求用户在流式传输上下文中主动选择接收 token 使用量数据。详情请参阅集成指南中的 流式使用量元数据 部分。
您可以使用回调或上下文管理器跟踪应用程序中跨模型的总 token 计数,如下所示:
from langchain.chat_models import init_chat_model
from langchain_core.callbacks import UsageMetadataCallbackHandler
llm_1 = init_chat_model( model = "openai:gpt-4o-mini" )
llm_2 = init_chat_model( model = "anthropic:claude-3-5-haiku-latest" )
callback = UsageMetadataCallbackHandler()
result_1 = llm_1.invoke( "你好" , config = { "callbacks" : [callback]})
result_2 = llm_2.invoke( "你好" , config = { "callbacks" : [callback]})
callback.usage_metadata
{
'gpt-4o-mini-2024-07-18': {
'input_tokens': 8,
'output_tokens': 10,
'total_tokens': 18,
'input_token_details': {'audio': 0, 'cache_read': 0},
'output_token_details': {'audio': 0, 'reasoning': 0}},
'claude-3-5-haiku-20241022': {'input_tokens': 8,
'output_tokens': 21,
'total_tokens': 29,
'input_token_details': {'cache_read': 0, 'cache_creation': 0}
}
}
调用配置
调用模型时,您可以通过 config 参数传递额外配置,使用 [RunnableConfig][RunnableConfig] 字典。这提供了对执行行为、回调和元数据跟踪的运行时控制。
常见配置选项包括:
response = model.invoke(
"讲个笑话" ,
config = {
"run_name" : "joke_generation" , # 此次运行的自定义名称
"tags" : [ "humor" , "demo" ], # 用于分类的标签
"metadata" : { "user_id" : "123" }, # 自定义元数据
"callbacks" : [my_callback_handler], # 回调处理器
}
)
在日志和追踪中标识此次特定调用。不会被子调用继承。
由所有子调用继承的标签,用于调试工具中的过滤和组织。
用于跟踪额外上下文的自定义键值对,由所有子调用继承。
使用 batch() 或 batch_as_completed() 时控制最大并行调用数。
防止复杂管道中出现无限循环的链式调用的最大递归深度。
这些配置值在以下场景中特别有用:
使用 LangSmith 追踪进行调试
实现自定义日志记录或监控
在生产环境中控制资源使用
在复杂管道中追踪调用
有关所有支持的 RunnableConfig 属性的更多信息,请参阅 [RunnableConfig][RunnableConfig] 参考文档。
可配置模型
您还可以通过指定 configurable_fields 创建运行时可配置的模型。如果您未指定模型值,则 'model' 和 'model_provider' 默认为可配置项。
from langchain.chat_models import init_chat_model
configurable_model = init_chat_model( temperature = 0 )
configurable_model.invoke(
"你叫什么名字" ,
config = { "configurable" : { "model" : "gpt-5-nano" }}, # 使用 GPT-5-Nano 运行
)
configurable_model.invoke(
"你叫什么名字" ,
config = { "configurable" : { "model" : "claude-3-5-sonnet-latest" }}, # 使用 Claude 运行
)
我们可以创建一个带有默认模型值的可配置模型,指定哪些参数是可配置的,并为可配置参数添加前缀: first_llm = init_chat_model(
model = "gpt-4.1-mini" ,
temperature = 0 ,
configurable_fields = ( "model" , "model_provider" , "temperature" , "max_tokens" ),
config_prefix = "first" , # 当链中有多个模型时非常有用
)
first_llm.invoke( "你叫什么名字" )
first_llm.invoke(
"你叫什么名字" ,
config = {
"configurable" : {
"first_model" : "claude-3-5-sonnet-latest" ,
"first_temperature" : 0.5 ,
"first_max_tokens" : 100 ,
}
},
)
我们可以在可配置模型上调用声明式操作,如 bind_tools、with_structured_output、with_configurable 等,并以与常规实例化聊天模型对象相同的方式链接可配置模型。 from pydantic import BaseModel, Field
class GetWeather ( BaseModel ):
"""获取指定位置的当前天气"""
location: str = Field( ... , description = "城市和州,例如:旧金山,CA" )
class GetPopulation ( BaseModel ):
"""获取指定位置的当前人口"""
location: str = Field( ... , description = "城市和州,例如:旧金山,CA" )
llm = init_chat_model( temperature = 0 )
llm_with_tools = llm.bind_tools([GetWeather, GetPopulation])
llm_with_tools.invoke(
"2024年洛杉矶和纽约哪个更大" , config = { "configurable" : { "model" : "gpt-4.1-mini" }}
).tool_calls
[
{
'name': 'GetPopulation',
'args': {'location': 'Los Angeles, CA'},
'id': 'call_Ga9m8FAArIyEjItHmztPYA22',
'type': 'tool_call'
},
{
'name': 'GetPopulation',
'args': {'location': 'New York, NY'},
'id': 'call_jh2dEvBaAHRaw5JUDthOs7rt',
'type': 'tool_call'
}
]
llm_with_tools.invoke(
"2024年洛杉矶和纽约哪个更大" ,
config = { "configurable" : { "model" : "claude-3-5-sonnet-latest" }},
).tool_calls
[
{
'name': 'GetPopulation',
'args': {'location': 'Los Angeles, CA'},
'id': 'toolu_01JMufPf4F4t2zLj7miFeqXp',
'type': 'tool_call'
},
{
'name': 'GetPopulation',
'args': {'location': 'New York City, NY'},
'id': 'toolu_01RQBHcE8kEEbYTuuS8WqY1u',
'type': 'tool_call'
}
]