备注
Go to the end to download the full example code.
模型¶
在本教程中,我们介绍 AgentScope 中集成的模型 API、如何使用它们,以及如何集成新的模型 API。 AgentScope 目前支持的模型 API 和模型提供商包括:
API |
类 |
兼容 |
流式 |
工具 |
视觉 |
推理 |
|---|---|---|---|---|---|---|
OpenAI |
|
vLLM, DeepSeek |
✅ |
✅ |
✅ |
✅ |
DashScope |
|
✅ |
✅ |
✅ |
✅ |
|
Anthropic |
|
✅ |
✅ |
✅ |
✅ |
|
Gemini |
|
✅ |
✅ |
✅ |
✅ |
|
Ollama |
|
✅ |
✅ |
✅ |
✅ |
备注
当使用 vLLM 时,需要在部署时为不同模型配置相应的工具调用参数,例如 --enable-auto-tool-choice、--tool-call-parser 等参数。更多详情请参考 vLLM 官方文档。
备注
兼容 OpenAI API 的模型(例如 vLLM 部署的模型),推荐使用 OpenAIChatModel,并通过 client_kwargs={"base_url": "http://your-api-endpoint"} 参数指定 API 端点。例如:
OpenAIChatModel(client_kwargs={"base_url": "http://localhost:8000/v1"})
备注
模型的行为参数(如温度、最大长度等)可以通过 generate_kwargs 参数在构造函数中提前设定。例如:
OpenAIChatModel(generate_kwargs={"temperature": 0.3, "max_tokens": 1000})
为了提供统一的模型接口,上述所有类均被统一为:
__call__函数的前三个参数是messages,tools和tool_choice,分别是输入消息,工具函数的 JSON schema,以及工具选择的模式。非流式返回时,返回类型是
ChatResponse实例;流式返回时,返回的是ChatResponse的异步生成器。
备注
不同的模型 API 在输入消息格式上有所不同,AgentScope 通过 formatter 模块处理消息的转换,请参考 format。
ChatResponse 包含大模型生成的推理/文本/工具使用内容、身份、创建时间和使用信息。
import asyncio
import json
import os
from agentscope.message import TextBlock, ToolUseBlock, ThinkingBlock, Msg
from agentscope.model import ChatResponse, DashScopeChatModel
response = ChatResponse(
content=[
ThinkingBlock(
type="thinking",
thinking="我应该在 Google 上搜索 AgentScope。",
),
TextBlock(type="text", text="我将在 Google 上搜索 AgentScope。"),
ToolUseBlock(
type="tool_use",
id="642n298gjna",
name="google_search",
input={"query": "AgentScope"},
),
],
)
print(response)
ChatResponse(content=[{'type': 'thinking', 'thinking': '我应该在 Google 上搜索 AgentScope。'}, {'type': 'text', 'text': '我将在 Google 上搜索 AgentScope。'}, {'type': 'tool_use', 'id': '642n298gjna', 'name': 'google_search', 'input': {'query': 'AgentScope'}}], id='2026-05-25 08:53:25.269_d578f4', created_at='2026-05-25 08:53:25.269', type='chat', usage=None, metadata=None)
以 DashScopeChatModel 为例,调用和返回结果如下:
async def example_model_call() -> None:
"""使用 DashScopeChatModel 的示例。"""
model = DashScopeChatModel(
model_name="qwen-max",
api_key=os.environ["DASHSCOPE_API_KEY"],
stream=False,
)
res = await model(
messages=[
{"role": "user", "content": "你好!"},
],
)
# 您可以直接使用响应内容创建 ``Msg`` 对象
msg_res = Msg("Friday", res.content, "assistant")
print("LLM 返回结果:", res)
print("作为 Msg 的响应:", msg_res)
asyncio.run(example_model_call())
LLM 返回结果: ChatResponse(content=[{'type': 'text', 'text': '你好!有什么我可以帮助你的吗?'}], id='855abb35-10e3-985e-ade4-30b0252fd1aa', created_at='2026-05-25 08:53:27.624', type='chat', usage=ChatUsage(input_tokens=10, output_tokens=8, time=2.354106, type='chat', metadata=GenerationUsage(input_tokens=10, output_tokens=8)), metadata=None)
作为 Msg 的响应: Msg(id='P4eDMoVAVQscyEQQpwLAn3', name='Friday', content=[{'type': 'text', 'text': '你好!有什么我可以帮助你的吗?'}], role='assistant', metadata={}, timestamp='2026-05-25 08:53:27.624', invocation_id='None')
流式返回¶
要启用流式返回,请在模型的构造函数中将 stream 参数设置为 True。
流式返回中,__call__ 方法将返回一个 异步生成器,该生成器迭代返回 ChatResponse 实例。
备注
AgentScope 中的流式返回结果为 累加式,这意味着每个 chunk 中的内容包含所有之前的内容加上新生成的内容。
async def example_streaming() -> None:
"""使用流式模型的示例。"""
model = DashScopeChatModel(
model_name="qwen-max",
api_key=os.environ["DASHSCOPE_API_KEY"],
stream=True,
)
generator = await model(
messages=[
{
"role": "user",
"content": "从 1 数到 20,只报告数字,不要任何其他信息。",
},
],
)
print("响应的类型:", type(generator))
i = 0
async for chunk in generator:
print(f"块 {i}")
print(f"\t类型: {type(chunk.content)}")
print(f"\t{chunk}\n")
i += 1
asyncio.run(example_streaming())
响应的类型: <class 'async_generator'>
块 0
类型: <class 'list'>
ChatResponse(content=[{'type': 'text', 'text': '1'}], id='c2a1d2f0-9509-9ddd-95d1-0c348b6f3d2d', created_at='2026-05-25 08:53:28.750', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=1, time=1.124681, type='chat', metadata=GenerationUsage(input_tokens=26, output_tokens=1)), metadata=None)
块 1
类型: <class 'list'>
ChatResponse(content=[{'type': 'text', 'text': '1 2 '}], id='c2a1d2f0-9509-9ddd-95d1-0c348b6f3d2d', created_at='2026-05-25 08:53:28.848', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=4, time=1.222249, type='chat', metadata=GenerationUsage(input_tokens=26, output_tokens=4)), metadata=None)
块 2
类型: <class 'list'>
ChatResponse(content=[{'type': 'text', 'text': '1 2 3 4'}], id='c2a1d2f0-9509-9ddd-95d1-0c348b6f3d2d', created_at='2026-05-25 08:53:29.036', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=7, time=1.410099, type='chat', metadata=GenerationUsage(input_tokens=26, output_tokens=7)), metadata=None)
块 3
类型: <class 'list'>
ChatResponse(content=[{'type': 'text', 'text': '1 2 3 4 5 '}], id='c2a1d2f0-9509-9ddd-95d1-0c348b6f3d2d', created_at='2026-05-25 08:53:29.229', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=10, time=1.60345, type='chat', metadata=GenerationUsage(input_tokens=26, output_tokens=10)), metadata=None)
块 4
类型: <class 'list'>
ChatResponse(content=[{'type': 'text', 'text': '1 2 3 4 5 6 7 8 '}], id='c2a1d2f0-9509-9ddd-95d1-0c348b6f3d2d', created_at='2026-05-25 08:53:29.568', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=16, time=1.942703, type='chat', metadata=GenerationUsage(input_tokens=26, output_tokens=16)), metadata=None)
块 5
类型: <class 'list'>
ChatResponse(content=[{'type': 'text', 'text': '1 2 3 4 5 6 7 8 9 10 1'}], id='c2a1d2f0-9509-9ddd-95d1-0c348b6f3d2d', created_at='2026-05-25 08:53:29.838', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=22, time=2.212258, type='chat', metadata=GenerationUsage(input_tokens=26, output_tokens=22)), metadata=None)
块 6
类型: <class 'list'>
ChatResponse(content=[{'type': 'text', 'text': '1 2 3 4 5 6 7 8 9 10 11 12 1'}], id='c2a1d2f0-9509-9ddd-95d1-0c348b6f3d2d', created_at='2026-05-25 08:53:30.150', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=28, time=2.524629, type='chat', metadata=GenerationUsage(input_tokens=26, output_tokens=28)), metadata=None)
块 7
类型: <class 'list'>
ChatResponse(content=[{'type': 'text', 'text': '1 2 3 4 5 6 7 8 9 10 11 12 13 14 1'}], id='c2a1d2f0-9509-9ddd-95d1-0c348b6f3d2d', created_at='2026-05-25 08:53:30.579', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=34, time=2.953475, type='chat', metadata=GenerationUsage(input_tokens=26, output_tokens=34)), metadata=None)
块 8
类型: <class 'list'>
ChatResponse(content=[{'type': 'text', 'text': '1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1'}], id='c2a1d2f0-9509-9ddd-95d1-0c348b6f3d2d', created_at='2026-05-25 08:53:30.855', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=40, time=3.229169, type='chat', metadata=GenerationUsage(input_tokens=26, output_tokens=40)), metadata=None)
块 9
类型: <class 'list'>
ChatResponse(content=[{'type': 'text', 'text': '1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 1'}], id='c2a1d2f0-9509-9ddd-95d1-0c348b6f3d2d', created_at='2026-05-25 08:53:31.392', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=46, time=3.766565, type='chat', metadata=GenerationUsage(input_tokens=26, output_tokens=46)), metadata=None)
块 10
类型: <class 'list'>
ChatResponse(content=[{'type': 'text', 'text': '1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20'}], id='c2a1d2f0-9509-9ddd-95d1-0c348b6f3d2d', created_at='2026-05-25 08:53:31.604', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=50, time=3.978796, type='chat', metadata=GenerationUsage(input_tokens=26, output_tokens=50)), metadata=None)
块 11
类型: <class 'list'>
ChatResponse(content=[{'type': 'text', 'text': '1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20'}], id='c2a1d2f0-9509-9ddd-95d1-0c348b6f3d2d', created_at='2026-05-25 08:53:31.630', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=50, time=4.004538, type='chat', metadata=GenerationUsage(input_tokens=26, output_tokens=50)), metadata=None)
推理模型¶
AgentScope 通过提供 ThinkingBlock 来支持推理模型。
async def example_reasoning() -> None:
"""使用推理模型的示例。"""
model = DashScopeChatModel(
model_name="qwen-turbo",
api_key=os.environ["DASHSCOPE_API_KEY"],
enable_thinking=True,
)
res = await model(
messages=[
{"role": "user", "content": "我是谁?"},
],
)
last_chunk = None
async for chunk in res:
last_chunk = chunk
print("最终响应:")
print(last_chunk)
asyncio.run(example_reasoning())
最终响应:
ChatResponse(content=[{'type': 'thinking', 'thinking': '好的,用户问“我是谁?”,这是一个哲学性的问题,涉及到自我认知和存在。首先,我需要理解用户可能的意图。他们可能是在寻求对自我身份的深入思考,或者是在探索存在的意义。也有可能用户处于某种困惑或迷茫的状态,希望通过这个问题找到答案。\n\n接下来,我要考虑如何回应。直接回答“你是你自己”可能太简单,不够深入。需要提供一些哲学或心理学的角度,帮助用户从不同层面理解“我是谁”。比如,可以提到哲学家的观点,如笛卡尔的“我思故我在”,或者心理学中的自我认同理论。\n\n同时,要避免过于学术化的语言,保持自然和易懂。可能需要分点说明,比如从生理、心理、社会角色、哲学层面来探讨。还要注意用户可能的深层需求,比如他们可能在寻找自我价值感,或者面对人生选择时的困惑。\n\n另外,要确保回答积极正面,鼓励用户进行自我探索,而不是给出绝对的答案。因为“我是谁”没有标准答案,每个人的经历和视角都不同。可能需要引导用户思考自己的价值观、经历、兴趣等,帮助他们构建自己的答案。\n\n还要注意文化差异,不同文化对自我认知有不同的看法。比如东方文化可能更强调社会角色,而西方可能更注重个人主义。但用户可能来自任何背景,所以需要保持中立和包容。\n\n最后,检查是否有遗漏的方面,比如精神层面或存在主义的观点,确保回答全面且有深度,同时保持口语化,避免使用专业术语过多,让用户容易理解和接受。\n'}, {'type': 'text', 'text': '“我是谁?”是一个跨越哲学、心理学、宗教和日常生活的永恒命题。这个问题看似简单,却可能引发对自我本质的深刻思考。以下是几个角度的探索,或许能帮助你更接近答案:\n\n---\n\n### **1. 生理与存在层面**\n- **生物学角度**:你是一个由细胞、基因、神经系统组成的有机体,是宇宙中独特的生命形式。你的身体是数十亿年进化的结果,承载着遗传信息和生物本能。\n- **存在主义视角**:萨特说“存在先于本质”,你首先存在,然后通过选择和行动定义自己。你的“存在”本身就是一个未完成的创作。\n\n---\n\n### **2. 心理与意识层面**\n- **自我认同**:心理学家埃里克森认为,人的身份是通过“同一性探索”逐渐形成的。你可能在不断追问“我是谁”,正是在尝试整合过去的经历、现在的感受和未来的期待。\n- **意识的迷宫**:你是否曾感到“我”是流动的?比如在不同情境下(如工作、家庭、独处)表现出不同的角色,这是否意味着“我”是多个面向的集合?\n\n---\n\n### **3. 社会与关系层面**\n- **角色与标签**:你可能是“子女”“朋友”“员工”“爱好者”……这些社会角色塑造了你的一部分形象,但它们是否完全定义了你?\n- **他者视角**:他人对你的看法可能影响你的自我认知,但“你”是否需要依赖他人的评价来确认存在?\n\n---\n\n### **4. 哲学与终极追问**\n- **笛卡尔的“我思故我在”**:即使怀疑一切,思考本身证明了你的存在。但“思考”的主体是谁?是大脑的神经活动,还是某种更深层的“意识”?\n- **东方哲学的超越**:佛教认为“我”是五蕴(色、受、想、行、识)的暂时聚合,没有永恒不变的“自我”;道家则强调“无我”与自然的融合。\n- **存在主义的自由**:加缪说“人是被抛入世界的”,你没有预设的意义,但正因如此,你可以通过选择赋予生命意义。\n\n---\n\n### **5. 你可能正在经历的困惑**\n- **身份的流动性**:如果“我是谁”在不同阶段变化,是否意味着“我”是动态的?比如,你可能曾是学生,现在是职场人,未来可能成为父母……这些身份是否共同构成“你”?\n- **孤独与连接**:当一个人独自思考“我是谁”,可能感到孤独,但这种孤独也可能成为自我探索的契机。\n\n---\n\n### **6. 一个可能的回应**\n“你是**此刻正在思考‘我是谁’的你**。” \n这个问题的答案或许不在远处,而在你每一次呼吸、每一段经历、每一个选择中。它不需要被“找到”,而是通过生活慢慢“显现”。\n\n---\n\n**最后**:如果这个问题让你感到困扰,不妨试着写下: \n- 我最珍视什么? \n- 我害怕失去什么? \n- 如果没有社会标签,我会如何定义自己? \n答案可能藏在这些问题的缝隙里。'}], id='b59e29d7-e1aa-9c5c-a35e-f81ca34fc530', created_at='2026-05-25 08:53:44.344', type='chat', usage=ChatUsage(input_tokens=11, output_tokens=1011, time=12.710496, type='chat', metadata=GenerationUsage(input_tokens=11, output_tokens=1011)), metadata=None)
工具 API¶
不同的模型提供商在工具 API 方面有所不同,例如工具 JSON schema、工具调用/响应格式。 为了提供统一的接口,AgentScope 通过以下方式解决了这个问题:
提供了统一的工具调用结构 block ToolUseBlock 和工具响应结构 ToolResultBlock。
在模型类的
__call__方法中提供统一的工具接口tools,接受工具 JSON schema 列表,如下所示:
json_schemas = [
{
"type": "function",
"function": {
"name": "google_search",
"description": "在 Google 上搜索查询。",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "搜索查询。",
},
},
"required": ["query"],
},
},
},
]
进一步阅读¶
Total running time of the script: (0 minutes 19.079 seconds)