备注
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-02-07 17:28:43.836_a8b02a', created_at='2026-02-07 17:28:43.836', 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='2026-02-07 17:28:46.975_2c3828', created_at='2026-02-07 17:28:46.976', type='chat', usage=ChatUsage(input_tokens=10, output_tokens=7, time=3.138704, type='chat', metadata=GenerationUsage(input_tokens=10, output_tokens=7)), metadata=None)
作为 Msg 的响应: Msg(id='2rQvTNbeg98HUtEZJjqcew', name='Friday', content=[{'type': 'text', 'text': '你好!有什么可以帮助你的吗?'}], role='assistant', metadata=None, timestamp='2026-02-07 17:28:46.976', 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='2026-02-07 17:28:48.447_ec149c', created_at='2026-02-07 17:28:48.447', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=1, time=1.469649, type='chat', metadata=GenerationUsage(input_tokens=26, output_tokens=1)), metadata=None)
块 1
类型: <class 'list'>
ChatResponse(content=[{'type': 'text', 'text': '1\n'}], id='2026-02-07 17:28:48.540_39cf28', created_at='2026-02-07 17:28:48.540', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=2, time=1.562799, type='chat', metadata=GenerationUsage(input_tokens=26, output_tokens=2)), metadata=None)
块 2
类型: <class 'list'>
ChatResponse(content=[{'type': 'text', 'text': '1\n2\n3'}], id='2026-02-07 17:28:48.633_260878', created_at='2026-02-07 17:28:48.633', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=5, time=1.655394, type='chat', metadata=GenerationUsage(input_tokens=26, output_tokens=5)), metadata=None)
块 3
类型: <class 'list'>
ChatResponse(content=[{'type': 'text', 'text': '1\n2\n3\n4\n'}], id='2026-02-07 17:28:48.720_f771ce', created_at='2026-02-07 17:28:48.720', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=8, time=1.742357, type='chat', metadata=GenerationUsage(input_tokens=26, output_tokens=8)), metadata=None)
块 4
类型: <class 'list'>
ChatResponse(content=[{'type': 'text', 'text': '1\n2\n3\n4\n5\n6\n7\n'}], id='2026-02-07 17:28:48.892_38b68c', created_at='2026-02-07 17:28:48.892', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=14, time=1.914691, type='chat', metadata=GenerationUsage(input_tokens=26, output_tokens=14)), metadata=None)
块 5
类型: <class 'list'>
ChatResponse(content=[{'type': 'text', 'text': '1\n2\n3\n4\n5\n6\n7\n8\n9\n10'}], id='2026-02-07 17:28:49.094_11b376', created_at='2026-02-07 17:28:49.094', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=20, time=2.116859, type='chat', metadata=GenerationUsage(input_tokens=26, output_tokens=20)), metadata=None)
块 6
类型: <class 'list'>
ChatResponse(content=[{'type': 'text', 'text': '1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12'}], id='2026-02-07 17:28:49.248_e09ead', created_at='2026-02-07 17:28:49.248', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=26, time=2.271152, type='chat', metadata=GenerationUsage(input_tokens=26, output_tokens=26)), metadata=None)
块 7
类型: <class 'list'>
ChatResponse(content=[{'type': 'text', 'text': '1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14'}], id='2026-02-07 17:28:49.558_f4b4e7', created_at='2026-02-07 17:28:49.558', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=32, time=2.581187, type='chat', metadata=GenerationUsage(input_tokens=26, output_tokens=32)), metadata=None)
块 8
类型: <class 'list'>
ChatResponse(content=[{'type': 'text', 'text': '1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16'}], id='2026-02-07 17:28:49.727_ab8741', created_at='2026-02-07 17:28:49.727', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=38, time=2.750073, type='chat', metadata=GenerationUsage(input_tokens=26, output_tokens=38)), metadata=None)
块 9
类型: <class 'list'>
ChatResponse(content=[{'type': 'text', 'text': '1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18'}], id='2026-02-07 17:28:50.167_9520ec', created_at='2026-02-07 17:28:50.167', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=44, time=3.190154, type='chat', metadata=GenerationUsage(input_tokens=26, output_tokens=44)), metadata=None)
块 10
类型: <class 'list'>
ChatResponse(content=[{'type': 'text', 'text': '1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20'}], id='2026-02-07 17:28:50.346_07a95e', created_at='2026-02-07 17:28:50.346', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=50, time=3.369055, type='chat', metadata=GenerationUsage(input_tokens=26, output_tokens=50)), metadata=None)
块 11
类型: <class 'list'>
ChatResponse(content=[{'type': 'text', 'text': '1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20'}], id='2026-02-07 17:28:50.455_76d13b', created_at='2026-02-07 17:28:50.455', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=50, time=3.477317, 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最后,确保回答全面但不过于冗长,涵盖不同视角,同时鼓励用户继续探索自己的问题。'}, {'type': 'text', 'text': '“我是谁?”是一个古老而深邃的问题,它触及人类存在的核心。不同领域和文化对此有不同的解读,以下是一些可能的视角:\n\n---\n\n### **1. 哲学视角**\n- **笛卡尔的“我思故我在”**:法国哲学家笛卡尔认为,即使怀疑一切,只要“我”在思考,就证明“我”存在。这里的“我”是思考的主体,是意识的源头。\n- **佛教的“无我”**:佛教认为“我”是五蕴(色、受、想、行、识)的暂时聚合,并无永恒不变的实体。执着于“我”的存在是痛苦的根源。\n- **存在主义**:萨特等哲学家强调,人通过选择和行动定义自己。**“存在先于本质”**,人需要主动创造自己的意义。\n\n---\n\n### **2. 心理学视角**\n- **自我认同**:心理学家埃里克森认为,人的身份是通过与社会、文化、家庭的互动逐步形成的。你可能在不同角色(如学生、朋友、工作者)中寻找“我是谁”的答案。\n- **内在的多重自我**:荣格提出“个体化”过程,认为人内心包含多个面向(如本我、自我、超我),需要整合这些部分才能形成完整的自我。\n\n---\n\n### **3. 宗教与灵性视角**\n- **基督教**:认为人是上帝按照自己的形象创造的,灵魂与神的连接是身份的核心。\n- **印度教**:强调“梵我合一”,个体的“我”(Atman)与宇宙本体“梵”(Brahman)本质相同。\n- **道家**:老子说“知人者智,自知者明”,主张通过内在觉察超越对“我”的执着,回归自然本性。\n\n---\n\n### **4. 科学视角**\n- **生物学**:从基因、神经科学角度看,“我”是大脑复杂活动的产物,是物质与能量的动态平衡。\n- **量子物理**:某些理论认为,观察者(“我”)与被观察的现实相互影响,意识可能是宇宙的基石。\n\n---\n\n### **5. 你的个人视角**\n也许这个问题更贴近你的当下处境:\n- **如果你感到迷茫**:可能正在经历身份的重构(如职业转变、人生阶段变化),需要时间探索。\n- **如果你寻求意义**:可以思考什么价值观、目标或关系让你感到“真实”。\n- **如果你感到孤独**:或许需要与他人建立更深的联结,或通过艺术、写作表达内心。\n\n---\n\n### **如何探索“我是谁”?**\n- **内省练习**:写下你最珍视的价值观、梦想、恐惧,或记录日常中的“自我”感受。\n- **提问自己**: \n - 在什么情境下我感到最自由? \n - 如果没有社会标签(如职业、年龄),我会是谁? \n - 我的哪些特质是“天生”的?哪些是后天塑造的?\n- **与他人对话**:倾听他人的视角,可能帮助你看到自己未曾注意到的层面。\n\n---\n\n**最终答案**: \n“我是谁”没有固定答案,它是一个动态的过程。你可能是**一个正在探索生命意义的个体**,是**无数经历、选择和关系的总和**,也是**尚未完全定义的可能**。或许,问题本身比答案更重要——它提醒我们:**存在本身就是一种奇迹**。 🌱\n\n如果你愿意分享更多背景,我可以尝试更具体地回应你的困惑。'}], id='2026-02-07 17:29:02.405_833809', created_at='2026-02-07 17:29:02.405', type='chat', usage=ChatUsage(input_tokens=11, output_tokens=1038, time=11.94616, type='chat', metadata=GenerationUsage(input_tokens=11, output_tokens=1038)), 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 18.580 seconds)