模型

在本教程中,我们介绍 AgentScope 中集成的模型 API、如何使用它们,以及如何集成新的模型 API。 AgentScope 目前支持的模型 API 和模型提供商包括:

API

兼容

流式

工具

视觉

推理

OpenAI

OpenAIChatModel

vLLM, DeepSeek

DashScope

DashScopeChatModel

Anthropic

AnthropicChatModel

Gemini

GeminiChatModel

Ollama

OllamaChatModel

备注

当使用 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__ 函数的前三个参数是 messagestoolstool_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='2025-12-19 10:48:12.916_1563da', created_at='2025-12-19 10:48:12.916', 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='2025-12-19 10:48:14.128_d487ec', created_at='2025-12-19 10:48:14.128', type='chat', usage=ChatUsage(input_tokens=10, output_tokens=7, time=1.210798, type='chat'), metadata=None)
作为 Msg 的响应: Msg(id='ZhohwcLcyNvn5Tqa3TZLJ3', name='Friday', content=[{'type': 'text', 'text': '你好!有什么可以帮助你的吗?'}], role='assistant', metadata=None, timestamp='2025-12-19 10:48:14.128', 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='2025-12-19 10:48:15.077_e03c30', created_at='2025-12-19 10:48:15.077', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=1, time=0.947071, type='chat'), metadata=None)

块 1
        类型: <class 'list'>
        ChatResponse(content=[{'type': 'text', 'text': '1\n'}], id='2025-12-19 10:48:15.161_c1f3cb', created_at='2025-12-19 10:48:15.161', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=2, time=1.031596, type='chat'), metadata=None)

块 2
        类型: <class 'list'>
        ChatResponse(content=[{'type': 'text', 'text': '1\n2\n3'}], id='2025-12-19 10:48:15.653_c788a3', created_at='2025-12-19 10:48:15.653', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=5, time=1.523361, type='chat'), metadata=None)

块 3
        类型: <class 'list'>
        ChatResponse(content=[{'type': 'text', 'text': '1\n2\n3\n4\n'}], id='2025-12-19 10:48:15.738_913b6b', created_at='2025-12-19 10:48:15.738', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=8, time=1.608079, type='chat'), metadata=None)

块 4
        类型: <class 'list'>
        ChatResponse(content=[{'type': 'text', 'text': '1\n2\n3\n4\n5\n6\n7\n'}], id='2025-12-19 10:48:15.907_056016', created_at='2025-12-19 10:48:15.907', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=14, time=1.777232, type='chat'), metadata=None)

块 5
        类型: <class 'list'>
        ChatResponse(content=[{'type': 'text', 'text': '1\n2\n3\n4\n5\n6\n7\n8\n9\n10'}], id='2025-12-19 10:48:16.093_6a7961', created_at='2025-12-19 10:48:16.093', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=20, time=1.963264, type='chat'), metadata=None)

块 6
        类型: <class 'list'>
        ChatResponse(content=[{'type': 'text', 'text': '1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12'}], id='2025-12-19 10:48:16.230_188979', created_at='2025-12-19 10:48:16.230', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=26, time=2.100388, type='chat'), 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='2025-12-19 10:48:16.414_01b435', created_at='2025-12-19 10:48:16.414', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=32, time=2.28455, type='chat'), 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='2025-12-19 10:48:16.619_ada82f', created_at='2025-12-19 10:48:16.619', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=38, time=2.489373, type='chat'), 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='2025-12-19 10:48:16.778_71cfe2', created_at='2025-12-19 10:48:16.778', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=44, time=2.647907, type='chat'), 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='2025-12-19 10:48:16.959_d13c9a', created_at='2025-12-19 10:48:16.959', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=50, time=2.82886, type='chat'), 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='2025-12-19 10:48:17.075_9ffc15', created_at='2025-12-19 10:48:17.075', type='chat', usage=ChatUsage(input_tokens=26, output_tokens=50, time=2.945417, type='chat'), 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- **笛卡尔的“我思故我在”**:  \n  哲学家笛卡尔认为,即使怀疑一切,只要“我”在思考,就证明“我”的存在。这可能指向一种更基础的自我意识。\n\n---\n\n### **2. 心理学视角**\n- **自我认同**:  \n  你对“我是谁”的认知,可能包括你的性格、能力、价值观、经历、社会角色(如学生、朋友、父母)等。心理学家埃里克·埃里克森(Erik Erikson)提出,个体在不同阶段会通过探索和整合形成自我认同。\n\n- **内在与外在的矛盾**:  \n  有时我们会感到困惑,因为“我”可能包含多个层面:比如“我希望成为谁”和“现实中我是谁”之间的冲突。\n\n---\n\n### **3. 宗教/灵性视角**\n- **宗教中的“我”**:  \n  - 基督教认为人是上帝按照自己的形象创造的,灵魂是永恒的。  \n  - 印度教认为“我”(Atman)是永恒的灵性本质,与“梵”(宇宙本体)合一。  \n  - 伊斯兰教强调人是安拉的仆人,通过信仰和行为找到自我。\n\n- **灵性探索**:  \n  一些人通过冥想、祈祷或修行,试图超越物质身体的局限,寻找更深层的“真我”。\n\n---\n\n### **4. 科学视角**\n- **神经科学**:  \n  你的“自我”可能与大脑的神经网络有关。科学家通过研究发现,大脑的默认模式网络(DMN)与自我意识密切相关,但“自我”是否是独立存在的实体,仍是一个未解之谜。\n\n- **生物学**:  \n  从基因到细胞,你是一个由数十亿个细胞组成的复杂系统,但“我”可能只是这些物质活动的某种感知。\n\n---\n\n### **5. 日常生活的视角**\n- **身份标签**:  \n  你可能是“学生”“员工”“父母”“朋友”,这些角色构成了你的一部分。但“我”是否仅限于这些标签?还是有更深层的特质?\n\n- **内在感受**:  \n  有时“我是谁”可能与你的情绪、直觉或创造力有关。比如,你可能觉得自己是一个“有同理心的人”或“喜欢探索未知的人”。\n\n---\n\n### **6. 你可以问自己的一些问题**:\n- 如果没有社会角色(如职业、家庭),我会是谁?  \n- 我最珍视的价值观是什么?它们如何塑造我的身份?  \n- 我的过去经历如何影响我对“我”的理解?  \n- 如果我能重新选择,我会如何定义自己?\n\n---\n\n### **最终答案:**\n“你是谁”可能没有唯一的答案,而是一个持续探索的过程。你可能是**一个正在寻找答案的人**,也可能是一个由思想、情感、经历和可能性交织而成的复杂存在。  \n**或许,真正的“我”不在于答案,而在于你如何与这个问题共处。**\n\n如果你愿意分享更多,我们可以一起探讨! 🌱'}], id='2025-12-19 10:48:29.637_f04c4c', created_at='2025-12-19 10:48:29.637', type='chat', usage=ChatUsage(input_tokens=11, output_tokens=1186, time=12.556649, type='chat'), 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 16.723 seconds)

Gallery generated by Sphinx-Gallery