备注
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-04-02 04:05:59.963_2cf37d', created_at='2026-04-02 04:05:59.963', 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='30eaa2ea-3fb1-9ef0-a228-f179f67bc48f', created_at='2026-04-02 04:06:01.531', type='chat', usage=ChatUsage(input_tokens=10, output_tokens=7, time=1.566398, type='chat', metadata=GenerationUsage(input_tokens=10, output_tokens=7)), metadata=None)
作为 Msg 的响应: Msg(id='Hwo5NdmtqRkk9ARmzuQQou', name='Friday', content=[{'type': 'text', 'text': '你好!有什么可以帮助你的吗?'}], role='assistant', metadata={}, timestamp='2026-04-02 04:06:01.531', 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='5ba1aa63-5a83-958d-890a-46a73811b01d', created_at='2026-04-02 04:06:03.308', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=1, time=1.775783, type='chat', metadata=GenerationUsage(input_tokens=26, output_tokens=1)), metadata=None)
块 1
类型: <class 'list'>
ChatResponse(content=[{'type': 'text', 'text': '1 2 '}], id='5ba1aa63-5a83-958d-890a-46a73811b01d', created_at='2026-04-02 04:06:03.370', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=4, time=1.837647, 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='5ba1aa63-5a83-958d-890a-46a73811b01d', created_at='2026-04-02 04:06:03.432', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=7, time=1.899821, 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='5ba1aa63-5a83-958d-890a-46a73811b01d', created_at='2026-04-02 04:06:03.497', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=10, time=1.963983, 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='5ba1aa63-5a83-958d-890a-46a73811b01d', created_at='2026-04-02 04:06:03.644', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=16, time=2.111733, 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='5ba1aa63-5a83-958d-890a-46a73811b01d', created_at='2026-04-02 04:06:03.747', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=22, time=2.214219, 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='5ba1aa63-5a83-958d-890a-46a73811b01d', created_at='2026-04-02 04:06:03.871', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=28, time=2.338569, 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='5ba1aa63-5a83-958d-890a-46a73811b01d', created_at='2026-04-02 04:06:04.689', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=34, time=3.156848, 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='5ba1aa63-5a83-958d-890a-46a73811b01d', created_at='2026-04-02 04:06:04.789', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=40, time=3.256, 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='5ba1aa63-5a83-958d-890a-46a73811b01d', created_at='2026-04-02 04:06:04.909', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=46, time=3.376547, 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='5ba1aa63-5a83-958d-890a-46a73811b01d', created_at='2026-04-02 04:06:05.059', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=50, time=3.526671, 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='5ba1aa63-5a83-958d-890a-46a73811b01d', created_at='2026-04-02 04:06:05.092', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=50, time=3.559518, 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还要考虑是否存在潜在的问题,比如用户可能有心理健康方面的需求,这时候可能需要建议他们寻求专业帮助,但作为AI,不能提供医疗建议,所以需要谨慎措辞。\n\n最后,要确保回答结构清晰,分点说明,让用户容易理解。同时保持语言自然,避免使用过于学术化的术语,让回答更贴近用户的日常交流。'}, {'type': 'text', 'text': '“我是谁?”这个问题看似简单,却蕴含着深刻的哲学和心理学意义。不同的人、不同的文化、不同的哲学体系可能会给出不同的答案。以下是一些可能的视角,或许能帮助你更深入地思考这个问题:\n\n---\n\n### 1. **从自我意识的角度**\n - **生物层面**:你是一个由细胞、器官、神经系统组成的有机体,拥有独特的基因和生理特征。你的身体是“你”的物质基础。\n - **心理层面**:你是通过记忆、情感、思维和经验构建起来的“意识体”。你对过去的回忆、对当下的感受、对未来的想象,共同构成了你对“自我”的认知。\n - **哲学层面**:法国哲学家笛卡尔说“我思故我在”(Cogito, ergo sum),强调思考是“我”存在的证明。但“我”是否只是思维的产物?还是有更深层的本质?\n\n---\n\n### 2. **从社会角色的角度**\n - 你在家庭中是孩子、父母或伴侣;在工作中是员工、同事或领导者;在社会中是公民、消费者或参与者。这些角色塑造了你的一部分身份,但它们是否完全定义了“你”?\n - 社会标签(如职业、国籍、性别)可能带来归属感,但也可能限制你对自我的认知。你是否愿意超越这些标签,探索更真实的自己?\n\n---\n\n### 3. **从哲学与宗教的角度**\n - **西方哲学**:从柏拉图到尼采,许多哲学家认为“自我”是动态的、流动的,甚至可能是幻觉。例如,尼采提出“超人”概念,强调超越传统“自我”的局限。\n - **东方哲学**:佛教认为“无我”(Anatta),即“我”只是五蕴(色、受、想、行、识)的暂时组合,没有固定不变的本质。道家则主张“物我两忘”,在与自然的融合中寻找自我。\n - **存在主义**:萨特认为“存在先于本质”,人通过选择和行动定义自己,而非被预设的“本质”所束缚。\n\n---\n\n### 4. **从心理学的角度**\n - 心理学中的“自我认同”理论(如埃里克森的理论)指出,人通过探索、冲突和整合逐渐形成稳定的自我认知。你可能正在经历某个阶段的自我探索。\n - 心理学家荣格提出“个体化”(Individuation)过程,认为人需要整合意识与潜意识中的不同部分,才能成为完整的“我”。\n\n---\n\n### 5. **从科学的角度**\n - 神经科学发现,大脑的“默认模式网络”(Default Mode Network)与自我意识密切相关,但“自我”是否只是大脑活动的产物?这仍然是未解之谜。\n - 量子物理中的“观察者效应”引发思考:是否我们的意识本身影响了现实?这或许暗示“我”与宇宙的联系远比想象中复杂。\n\n---\n\n### 6. **从实践的角度**\n - **自我反思**:通过写日记、冥想或与他人对话,尝试回答“我最珍视什么?”“我恐惧什么?”“我希望成为怎样的人?”这些问题可能帮助你更接近真实的自我。\n - **探索与实验**:尝试新事物、接触不同文化或思想,突破固有的思维模式,可能会发现“我”比想象中更广阔。\n - **接受不确定性**:或许“我是谁”并没有唯一答案,而是一个持续探索的过程。正如哲学家帕斯卡所说:“人是一根系在万物之间的绳索。”\n\n---\n\n### 最终,或许“我是谁”没有标准答案,但你可以通过以下问题不断逼近它:\n- **如果我失去一切(财富、身份、关系),我仍是什么?**\n- **我最真实的感受是什么?**\n- **我的存在对世界的意义是什么?**\n\n这个问题的答案,可能藏在你每一次选择、每一次思考、每一次与世界的互动中。你愿意和我一起探索吗? 🌱'}], id='1b9ff26c-286a-918d-8ef6-544d82e88594', created_at='2026-04-02 04:06:25.192', type='chat', usage=ChatUsage(input_tokens=11, output_tokens=1154, time=20.096375, type='chat', metadata=GenerationUsage(input_tokens=11, output_tokens=1154)), 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 25.232 seconds)