本文基于高考查询小助手的实际业务场景,详细介绍了使用AgentScope框架开发AI Agent的完整实践。文章阐述了AgentScope框架的核心优势,包括ReAct范式的深度集成、并行工具调用、结构化输出等功能,提供了具体的代码实现,展示了如何利用ReActAgent、自定义工具和记忆组件构建智能体。通过测试案例验证了框架在工具调用、上下文记忆和推理能力方面的表现,为开发者提供了可借鉴的AI Agent开发经验。

1、什么是AgentScope?

AgentScope 是阿里通义实验室推出的开源智能体开发框架,聚焦多智能体应用场景,提供覆盖开发、部署与监控全生命周期的生产级解决方案。该框架以开发者为核心,采用模块化设计原则与ReAct范式构建智能体体系,支持动态工具配置、并行工具调用及自动化状态管理,包含消息、模型、记忆和工具四大基础组件。

官方文档地址:https://doc.agentscope.io/zh_CN/

核心优势

  1. 对 ReAct 范式的深度集成与工程化支持:
  • 实时介入(Realtime Steering):允许用户在智能体执行过程中(例如,当工具调用耗时过长或结果偏离预期时)通过 Ctrl+C 或调用 interrupt 方法进行中断。框架会自动捕获中断信号,保存当前状态和记忆,并通过 handle_interrupt 方法进行优雅的后处理,极大地提升了人机交互的灵活性和可控性。

  • 并行工具调用(Parallel Tool Calls):通过设置 parallel_tool_calls=True,当大模型生成多个工具调用指令时,AgentScope 会使用 asyncio.gather 并行执行这些工具,显著提高效率,尤其适用于处理多个独立的、耗时的任务。

  • 结构化输出(Structured Output):与工具调用紧密结合,允许开发者传入一个 pydantic.BaseModel 的子类作为参数。智能体会严格按照该模型的结构生成输出,并将结果存储在返回消息的 metadata 字段中,方便后续程序化处理,确保了输出的可靠性和一致性。

  • 自主记忆与状态管理:支持智能体自主管理其长期记忆和自动进行状态管理,这对于构建复杂的、多轮对话的智能体至关重要。

  • 开箱即用的 ReActAgent:框架直接提供了 ReActAgent 类,将 ReAct 范式所需的“思考(Reasoning)”和“行动(Acting)”环节进行了系统性的封装和实现,开发者无需从零开始搭建复杂的逻辑。

  • 丰富的内置功能:ReActAgent 集成了多项高级功能,包括但不限于:

  1. 高度的灵活性与可扩展性:
  • 清晰的抽象基类:提供了 AgentBase 和 ReActAgentBase 两个抽象基类。AgentBase 定义了所有智能体的基本接口(如 reply, observe),而 ReActAgentBase 则在此基础上增加了 _reasoning 和 _acting 等抽象方法,专为 ReAct 范式设计。
  • 强大的钩子(Hook)机制:在基类中预置了丰富的前置(pre_)和后置(post_)钩子函数,例如 pre_reply, post_reasoning 等。开发者可以通过覆盖这些钩子,在不修改核心逻辑的情况下,轻松地插入自定义的监控、日志记录、数据预处理或后处理等逻辑。
  • 易于自定义:开发者可以根据具体需求,选择继承 AgentBase 或 ReActAgentBase 来创建完全自定义的智能体,框架提供了坚实的底层支持,让开发者可以专注于业务逻辑的实现。
  1. 开发者友好:
  • 优雅的错误与中断处理:如前所述,其基于 asyncio 的中断机制和抽象的 handle_interrupt 方法,使得处理异常和用户干预变得非常规范和简单,保证了程序的稳定性和用户体验。
  • 模块化设计:框架将模型(model)、记忆(memory)、格式化器(formatter)、工具包(toolkit)等组件解耦,开发者可以自由组合和替换,例如使用不同的大模型API或内存存储方案。

2、架构设计

我们基于AgentScope实现我们的智能体,主要实现多轮对话、问题拆分,学习一些工具调用能力和记忆能力。总体设计设计如下:

3、代码实践

具体代码实现如下:


import json
import asyncio

from agentscope.message import TextBlock, Msg
from agentscope.tool import ToolResponse, Toolkit
from agentscope.agent import AgentBase, ReActAgent
from agentscope.formatter import OllamaChatFormatter
from agentscope.memory import InMemoryMemory
from agentscope.model import OllamaChatModel

from api_service import QueryService, SemanticService, AnalysisService

# 初始化服务
queryService = QueryService()
semanticService = SemanticService()
analysisService = AnalysisService()


# 自定义工具类
# 根据输入文本语义匹配表结构,每次返回一个最相关的表结构。对于需要多表查询的问题,需要多次调用此工具。
async def match_metadata(user_query: str) -> ToolResponse:
    table = semanticService.hybrid_search(user_query, 1)

    return ToolResponse(
        content=[
            TextBlock(
                type="text",
                text=f"{[t['table_info'] for t in table]}",
            ),
        ],
    )


# 根据输入的SQL进行执行。
async def execute_sql(query_sql: str) -> ToolResponse:
    result = json.dumps(queryService.query_with_column(query_sql))

    return ToolResponse(
        content=[
            TextBlock(
                type="text",
                text=f"{result}",
            ),
        ],
    )


async def interactive_react_agent() -> None:
    """创建一个支持多轮对话的ReAct智能体。"""
    # 准备工具
    toolkit = Toolkit()
    toolkit.register_tool_function(match_metadata)
    toolkit.register_tool_function(execute_sql)

    jarvis = ReActAgent(
        name="Jarvis",
        sys_prompt="""
            你是一个数据分析助手,负责帮助用户查询数据库信息。
            请特别注意:用户的问题可能需要从多个表中查询数据。
            1. 首先确定需要查询哪些数据
            2. 使用match_metadata工具分别匹配包含这些数据的表结构
            3. 对每个表生成相应的SQL查询语句
            4. 执行查询并汇总结果
            5. 最后计算并给出答案

            请确保逐步执行,不要跳过任何步骤。
        """,
        model=OllamaChatModel(
            model_name="qwen3:32b",  # 指定模型名称
            stream=True,  # 根据需要设置是否流式输出
            enable_thinking=True,  # 为Qwen3启用思考功能(可选)
            # host="http://localhost:11434" # 如果Ollama不在默认地址,需指定
        ),
        formatter=OllamaChatFormatter(),
        toolkit=toolkit,
        memory=InMemoryMemory(),
    )

    print("数据分析助手已启动!输入问题进行查询(输入'exit'退出)")
    print("-" * 50)

    while True:
        # 使用run_in_executor处理阻塞的input调用
        user_input = await asyncio.get_event_loop().run_in_executor(
            None,
            input,
            "用户: "
        )

        # 检查是否退出指令 [[1]]
        if user_input.strip().lower() == 'exit':
            print("正在退出程序...")
            break

        if not user_input.strip():
            continue

        # 创建消息并发送给智能体
        msg = Msg(
            name="user",
            content=user_input,
            role="user",
        )

        print("\nJarvis正在思考...")

        # 获取智能体响应
        response = await jarvis(msg)

        # 显示回答
        print(f"\nJarvis: {response.content}\n")
        print("-" * 50)


# 运行交互式智能体
if __name__ == "__main__":
    asyncio.run(interactive_react_agent())

AgentScope依赖于Python的3.10版本及以上版本,这里我们使用Python3.13版本。

pip官方库版本0.x比较旧,直接源码安装,AgentScope最新1.x版本安装:

git clone -b main https://github.com/agentscope-ai/agentscope
cd agentscope
pip install -e .

该智能体基于 AgentScope 框架,使用了以下核心组件:

  • ReActAgent:具备“思考-行动”循环能力的智能体,可调用工具并基于结果推理下一步,指定推理次数max_iters,默认循环10次。
  • OllamaChatModel:本地运行的大语言模型(Qwen3:32b),负责推理与生成 SQL,封装ollama调用。
  • Toolkit + 自定义工具:封装数据库操作能力(执行 SQL)、语义检索能力(执行RAG检索)。
  • InMemoryMemory:会话记忆,保存对话历史。ReActAgent内,每次问答后缓存,推理时自动获取缓存的对话历史。
  • OllamaChatFormatter:格式化模型输入输出。
  • 自定义服务层:QueryService, SemanticService, AnalysisService —— 提供底层数据库查询与语义检索能力。

此智能体的核心是 ReActAgent 类,它实现了 ReAct 范式,即通过交替进行推理(Reasoning)和行动(Acting)来解决问题 。智能体会接收用户请求,并启动“思考→行动→观察”的循环,直到生成最终响应。

4、测试结果

QA1: 2016年考生人数 – 测试AgentScope基本工具调用能力

QA2: 那一年录取人数有多少? – 测试AgentScope上下文记忆能力

QA3: 2017年考生人数和录取人数分别有多少?-- 测试推理能力

数据分析助手已启动!输入问题进行查询(输入'exit'退出)
--------------------------------------------------
用户: 2016年考生人数

Jarvis正在思考...
Jarvis(thinking): 好的,我现在需要处理用户的问题:“2016年考生人数”。首先,我需要明确用户想要查询的是2016年的考生总人数,还是某个特定地区或类型的考生人数。不过根据问题本身,用户可能只是想知道全国范围内的总考生人数。

接下来,按照步骤,我需要确定需要查询哪些数据。这里显然需要考生的记录,可能涉及考生表,表中应该包含年份和考生人数的信息。因此,第一步是使用match_metadata工具来查找包含这些数据的表结构。

调用match_metadata函数,参数是用户的问题“2016年考生人数”。假设返回的表结构是exam_applicants,其中包含year和number_of_applicants两个字段。接下来,我需要生成相应的SQL查询语句,从exam_applicants表中查询year为2016年的记录的number_of_applicants值。

然后,使用execute_sql工具执行这个SQL查询。假设查询结果返回的是2016年的考生人数为940万人。最后,将结果通过generate_response工具返回给用户,给出明确的答案,并说明数据来源和可能的注意事项,比如数据是否为最终统计等。

需要注意的是,如果存在多个相关表,比如不同地区的考生表,可能需要进行汇总。但根据问题描述,用户可能只需要总人数,因此可能只需要查询主表。如果存在数据不一致或多个表的情况,可能需要进一步确认,但当前情况下按最简处理。
{
    "type": "tool_use",
    "id": "0_match_metadata",
    "name": "match_metadata",
    "input": {
        "user_query": "2016年考生人数"
    }
}
调用大模型llama2向量化:2016年考生人数,地址:http://localhost:11434/api/embeddings
自然语言语义检索字段成功,匹配到的元数据信息:[{'score': 0.6198425, 'table_info': '{"表名": "college_entrance_admission", "表备注": "录取人数与普通高校数信息表,包含字段:录取年份(主键)、录取人数(万人)、招生高\\n校数、本科录取人数(万人)、专科录取人数(万人)", "字段列表": [{"字段名": "admission_year", "字段类型": "int", "字段备注": "录取年份"}, ...}, {'score': 0.6008911, 'table_info': '{"表名": "college_entrance_examination", "表备注": "考生人数与复读人数信息表,包含字段:高考年份(主键)、考生人数(万人)、复读人数\\n(万人)", "字段列表": [{"字段名": "examination_year", "字段类型": "int", "字段备注": "高考年份"}, ...}]
自然语言分词搜索字段成功,匹配到的元数据信息:[{'score': 1.4999503, 'table_info': '{"表名": "college_entrance_examination", "表备注": "考生人数与复读人数信息表,包含字段:高考年份(主键)、考生人数(万人)、复读人数\\n(万人)", "字段列表": [{"字段名": "examination_year", "字段类型": "int", "字段备注": "高考年份"}, ...]}']}, {'score': 0.33530667, 'table_info': '{"表名": "college_entrance_admission", "表备注": "录取人数与普通高校数信息表,包含字段:录取年份(主键)、录取人数(万人)、招生高\\n校数、本科录取人数(万人)、专科录取人数(万人)", "字段列表": [{"字段名": "admission_year",  ...]}']}]
自然语言混合检索字段成功,匹配到的元数据信息:[{'id': 'JAFTZpkBNpD6YtdVxbQU', 'table_info': '{"表名": "college_entrance_examination", "表备注": "考生人数与复读人数信息表,包含字段:高考年份(主键)、考生人数(万人)、复读人数\\n(万人)", "字段列表": [{"字段名": "examination_year", "字段类型": "int", "字段备注": "高考年份"}, {"字段名": "candidates_count", "字段类型": "decimal(10,2)", "字段备注": "考生人数(万\\n人)"}, {"字段名": "retake_count", "字段类型": "decimal(10,2)", "字段备注": "复读人数(万人)"}]}', 'semantic_score': 0.6008911, 'keyword_score': 1.4999503, 'combined_score': 0.8706088600000002, ...]}]
system: {
    "type": "tool_result",
    "id": "0_match_metadata",
    "name": "match_metadata",
    "output": [
        {
            "type": "text",
            "text": "0['{\"表名\": \"college_entrance_examination\", \"表备注\": \"考生人数与复读人数信息表,包含字段:高考年份(主键)、考生人数(万人)、复读人数\\\\n(万人)\", \"字段列表\": [{\"字段名\": \"examination_year\", \"字段类型\": \"int\", \"字段备注\": \"高考年份\"}, {\"字段名\": \"candidates_count\", \"字段类型\": \"decimal(10,2)\", \"字段备注\": \"考生人数(万\\\\n人)\"}, {\"字段名\": \"retake_count\", \"字段类型\": \"decimal(10,2)\", \"字段备注\": \"复读人数(万人)\"}]}']"
        }
    ]
}
2025-09-24 19:54:24,041 | WARNING | _ollama_formatter:_format:121 - Unsupported block type thinking in the message, skipped.
Jarvis(thinking): 好的,用户需要查询2016年的考生人数。首先,我需要确定数据存储的表结构。通过调用match_metadata工具,发现有一个名为college_entrance_examination的表,其中包含examination_year、candidates_count和retake_count三个字段。用户的问题只需要考生人数,所以接下来需要生成对应的SQL查询语句。应该使用SELECT语句从该表中查询examination_year等于2016年的candidates_count。然后执行这个SQL,获取结果。假设查询结果返回了940万人,那么最终答案就是2016年的考生人数为940万人。需要确保步骤正确,没有遗漏。
{
    "type": "tool_use",
    "id": "0_execute_sql",
    "name": "execute_sql",
    "input": {
        "query_sql": "SELECT candidates_count FROM college_entrance_examination WHERE examination_year = 2016;"
    }
}


system: {
    "type": "tool_result",
    "id": "0_execute_sql",
    "name": "execute_sql",
    "output": [
        {
            "type": "text",
            "text": "0[{\"candidates_count\": 940.0}]"
        }
    ]
}
Jarvis(thinking): 好的,用户问的是2016年的考生人数。首先我需要确定数据存储在哪个表里。之前调用了match_metadata工具,找到了college_entrance_examination表,里面有examination_year、candidates_count和retake_count字段。接下来,我需要构造一个SQL查询,从该表中筛选出examination_year等于2016年的记录,并获取candidates_count的值。执行这个SQL后,返回的结果是940.0,单位是万人。所以,2016年的考生人数就是940万人。最后,将结果以自然的方式呈现给用户,确保数值和单位都正确无误。

Jarvis: 2016年的考生人数为940万人。


--------------------------------------------------
用户: 那一年录取人数有多少?

Jarvis正在思考...

Jarvis(thinking): 好的,用户现在问的是“那一年录取人数有多少?”,这里的“那一年”应该指的是之前提到的2016年。我需要先确认用户的问题是否需要从数据库中查询数据。

首先,用户之前询问了2016年的考生人数,现在想知道同一年的录取人数。因此,我需要查找2016年的录取人数数据。接下来,我需要确定数据库中是否有相关的表和字段。

使用match_metadata工具来匹配包含录取人数信息的表结构。用户的问题涉及“录取人数”,所以需要查找表中是否有相关字段。可能的表名可能是与高考相关的,比如之前提到的college_entrance_examination,或者另一个表,比如admission_statistics。

执行match_metadata工具,参数是“2016年录取人数”。根据返回的结果,如果存在相关表,比如admission_statistics,包含字段如enrollment_year(年份)和admitted_count(录取人数),那么就可以生成相应的SQL查询。

假设返回的表结构是admission_statistics,包含年份和录取人数字段。然后需要构造SQL查询,选择2016年的录取人数。例如:SELECT admitted_count FROM admission_statistics WHERE enrollment_year = 2016;

执行这个SQL查询后,获取结果,比如返回录取人数是749万人。最后,生成响应,告诉用户2016年的录取人数,并可能计算录取率,比如749/940≈79.7%。

需要确保步骤正确,先匹配元数据,再执行查询,最后生成回答。同时注意字段名和表名的正确性,以及可能的计算步骤。
{
    "type": "tool_use",
    "id": "0_match_metadata",
    "name": "match_metadata",
    "input": {
        "user_query": "2016年录取人数"
    }
}
调用大模型llama2向量化:2016年录取人数,地址:http://localhost:11434/api/embeddings
自然语言语义检索字段成功,匹配到的元数据信息:[{'score': 0.5988846, 'table_info': '{"表名": "college_entrance_admission", "表备注": "录取人数与普通高校数信息表,包含字段:录取年份(主键)、录取人数(万人)、招生高\\n校数、本科录取人数(万人)、专科录取人数(万人)", "字段列表": [{"字段名": "admission_year", "字段类型": "int", "字段备注": "录取年份"},...}, {'score': 0.59373474, 'table_info': '{"表名": "college_entrance_examination", "表备注": "考生人数与复读人数信息表,包含字段:高考年份(主键)、考生人数(万人)、复读人数\\n(万人)", "字段列表": [{"字段名": "examination_year", "字段类型": "int", "字段备注": "高考年份"},...}]
自然语言分词搜索字段成功,匹配到的元数据信息:[{'score': 1.2747635, 'table_info': '{"表名": "college_entrance_admission", "表备注": "录取人数与普通高校数信息表,包含字段:录取年份(主键)、录取人数(万人)、招生高\\n校数、本科录取人数(万人)、专科录取人数(万人)", "字段列表": [...{"字段名": "admission_count", "字段类型": "decimal(10,2)", "字段备注": "录取人数(万\\n人)"},...}]
自然语言混合检索字段成功,匹配到的元数据信息:[{'id': 'IwFTZpkBNpD6YtdVw7R2', 'table_info': '{"表名": "college_entrance_admission", "表备注": "录取人数与普通高校数信息表,包含字段:录取年份(主键)、录取人数(万人)、招生高\\n校数、本科录取人数(万人)、专科录取人数(万人)", "字段列表": [..., {"字段名": "admission_count", "字段类型": "decimal(10,2)", "字段备注": "录取人数(万\\n人)"}, ...]}', 'semantic_score': 0.5988846, 'keyword_score': 1.2747635, 'combined_score': 0.80164827, 'highlight': ...]
system: {
    "type": "tool_result",
    "id": "0_match_metadata",
    "name": "match_metadata",
    "output": [
        {
            "type": "text",
            "text": "0['{\"表名\": \"college_entrance_admission\", \"表备注\": \"录取人数与普通高校数信息表,包含字段:录取年份(主键)、录取人数(万人)、招生高\\\\n校数、本科录取人数(万人)、专科录取人数(万人)\", \"字段列表\": [{\"字段名\": \"admission_year\", \"字段类型\": \"int\", \"字段备注\": \"录取年份\"}, {\"字段名\": \"admission_count\", \"字段类型\": \"decimal(10,2)\", \"字段备注\": \"录取人数(\\\\n人)\"}, {\"字段名\": \"university_count\", \"字段类型\": \"int\", \"字段备注\": \"招生高校数\"}, {\"字段名\": \"undergraduate_admission_count\", \"字段类型\": \"decimal(10,2)\", \"字段备注\": \"本科录取人数(万人)\"}, {\"字段名\": \"specialty_admission_count\", \"字段类型\": \"decimal(10,2)\", \"字段备注\": \"专科录取人数(万人)\"}]}']"
        }
    ]
}
Jarvis(thinking): 好的,用户现在问的是“那一年录取人数有多少?”,也就是2016年的录取人数。之前已经处理过2016年考生人数的查询,现在需要处理录取人数。首先,我需要确定用户的问题涉及哪些数据,这里显然是2016年的录取人数。

接下来,使用match_metadata工具来查找包含录取人数的表结构。用户的问题关键词是“录取人数”,所以调用match_metadata函数,参数是“2016年录取人数”。根据返回的结果,找到了表college_entrance_admission,其中包含admission_count字段,即录取人数(万人),并且表中有admission_year字段作为年份。

现在需要生成对应的SQL查询语句。需要从college_entrance_admission表中查询admission_count,条件是admission_year等于2016。因此,构造的SQL语句应该是SELECT admission_count FROM college_entrance_admission WHERE admission_year = 2016;。

执行这个SQL语句后,预期会得到2016年的录取人数数据。假设返回的结果是749万人,那么最终的回答就是2016年的录取人数为749万人。需要确保所有步骤正确,特别是表名和字段名的准确性,以及条件的正确应用。如果有任何错误,比如表名或字段名不正确,或者年份条件错误,都会导致结果不准确,所以需要仔细检查每个步骤。
{
    "type": "tool_use",
    "id": "0_execute_sql",
    "name": "execute_sql",
    "input": {
        "query_sql": "SELECT admission_count FROM college_entrance_admission WHERE admission_year = 2016;"
    }
}
system: {
    "type": "tool_result",
    "id": "0_execute_sql",
    "name": "execute_sql",
    "output": [
        {
            "type": "text",
            "text": "0[{\"admission_count\": 772.0}]"
        }
    ]
}

Jarvis(thinking): 好的,用户现在问的是“那一年录取人数有多少?”,也就是2016年的录取人数。之前已经处理过2016年考生人数的查询,现在需要处理录取人数。

首先,我需要确定用户的问题涉及哪些数据。用户提到的“录取人数”应该对应数据库中的某个表。根据之前的步骤,用户的问题可能需要查询不同的表,所以需要先用match_metadata工具来找到正确的表结构。

调用match_metadata工具,参数是“2016年录取人数”。根据返回的结果,找到了表college_entrance_admission,其中包含admission_count字段,即录取人数。接下来需要生成SQL查询语句,从该表中选取admission_year为2016年的admission_count。

然后执行这个SQL查询,得到结果。根据返回的数据,2016年的录取人数是772万人。最后,使用generate_response工具将结果以自然语言回复给用户,确保信息准确且完整。

Jarvis: 2016年的录取人数为772万人。


--------------------------------------------------
用户: 2017年考生人数和录取人数分别有多少



Jarvis正在思考...
Jarvis(thinking): 好的,用户现在问的是2017年的考生人数和录取人数。首先我需要处理考生人数的部分。根据之前的对话,用户询问过2016年的考生人数,当时的表是college_entrance_examination,字段是examination_year和candidates_count。所以2017年的考生人数应该也是从这个表中查询,只需要把年份改成2017。

接下来是录取人数。用户之前问过2016年的录取人数,对应的表是college_entrance_admission,字段是admission_year和admission_count。同样,2017年的录取人数应该查询这个表,年份改为2017。

现在需要确认这两个表是否都有2017年的数据。可能需要分别调用match_metadata工具来验证表结构是否包含所需的字段,但根据之前的回复,这两个表的结构已经明确包含年份和对应的人数字段,所以可以直接生成SQL查询。

对于考生人数,SQL语句应该是SELECT candidates_count FROM college_entrance_examination WHERE examination_year = 2017; 对于录取人数,SQL语句是SELECT admission_count FROM college_entrance_admission WHERE admission_year = 2017;。

执行这两个查询后,将结果汇总,分别给出考生人数和录取人数。假设数据库中有数据,应该返回对应的数值。最后用generate_response将结果组合成自然语言的回答。
......

Jarvis(thinking): 好的,用户现在问的是2017年的考生人数和录取人数分别有多少。我需要先处理考生人数的部分。根据之前的对话流程,用户之前询问过2016年的考生人数和录取人数,我分别通过查询两个不同的表得到了结果。现在用户转向2017年,应该同样需要查询这两个表。

首先,用户的问题提到了“考生人数”,这应该对应到“college_entrance_examination”表,这个表包含高考年份和考生人数等字段。我需要使用match_metadata工具来确认表结构是否正确。根据用户之前的问题,已经知道这个表的字段有examination_year、candidates_count和retake_count。接下来需要生成SQL查询语句,选择2017年的考生人数。之前的例子中,用户查询2016年时用了SELECT candidates_count FROM college_entrance_examination WHERE examination_year = 2016;,所以这里应该类似,把年份改为2017。

接下来是录取人数的部分,用户之前询问2016年录取人数时,我通过match_metadata找到了“college_entrance_admission”表,该表包含admission_year和admission_count等字段。同样,现在需要查询2017年的录取人数,应该使用相同的表,并生成对应的SQL语句:SELECT admission_count FROM college_entrance_admission WHERE admission_year = 2017;。

需要注意的是,用户的问题同时询问了考生人数和录取人数,所以需要分别执行两次查询,分别获取这两个数据。然后将结果汇总,给出一个包含两者的回答。另外,必须确保两次查询的年份都是2017年,避免混淆。如果其中一个表没有2017年的数据,可能需要进一步处理,但根据之前的表结构,假设数据是存在的。最后,生成响应时要明确说明两个数字,确保用户的问题得到完整回答。
{
    "type": "tool_use",
    "id": "0_execute_sql",
    "name": "execute_sql",
    "input": {
        "query_sql": "SELECT candidates_count FROM college_entrance_examination WHERE examination_year = 2017;"
    }
}
system: {
    "type": "tool_result",
    "id": "0_execute_sql",
    "name": "execute_sql",
    "output": [
        {
            "type": "text",
            "text": "0[{\"candidates_count\": 940.0}]"
        }
    ]
}


现在需要分别执行这两个SQL查询。先执行考生人数的查询,得到结果后,再执行录取人数的查询。然后把两个结果合并,形成最终的回答。需要确保两个年份都是2017年,避免混淆。最后用generate_response返回结果。
{
    "type": "tool_use",
    "id": "0_execute_sql",
    "name": "execute_sql",
    "input": {
        "query_sql": "SELECT admission_count FROM college_entrance_admission WHERE admission_year = 2017;"
    }
}
system: {
    "type": "tool_result",
    "id": "0_execute_sql",
    "name": "execute_sql",
    "output": [
        {
            "type": "text",
            "text": "0[{\"admission_count\": 761.49}]"
        }
    ]
}


Jarvis(thinking): 好的,用户现在问的是2017年的考生人数和录取人数。我需要先处理这两个数据点。

首先,考生人数。之前用户问过2016年的,所以结构应该是类似的。使用match_metadata工具查找对应的表,应该是college_entrance_examination表,字段是candidates_count,条件是examination_year=2017。执行SQL后得到的结果是940.0万人,和2016年一样,可能那几年考生人数稳定。

然后是录取人数。对应的表是college_entrance_admission,字段admission_count,条件admission_year=2017。执行后得到761.49万人,比2016年的772万略少。需要注意这里的数据是否有小数点后的变化,可能反映了录取率的变化。

接下来需要将这两个结果整合到回答中,确保数字准确,并且用清晰的语句分开说明考生和录取人数。同时,检查是否有其他相关数据需要补充,比如本科和专科的录取人数,但用户只问了总录取人数,所以可能不需要额外信息。最后生成回答,确认无误后返回。

Jarvis: 2017年的考生人数为940万人,录取人数为761.49万人。


--------------------------------------------------
用户: 
Process finished with exit code 137 (interrupted by signal 9:SIGKILL)

QA1: 2016年考生人数 – 测试AgentScope基本工具调用能力

  • 回答正确,流程:调用match_metadata语义检索匹配元数据,然后生成SQL再调用execute_sql执行,查询数据后分析。

QA2: 那一年录取人数有多少? – 测试AgentScope上下文记忆能力

  • 回答符合我们的预期,根据上下文判断那一年是2026年。

QA3: 2017年考生人数和录取人数分别有多少?-- 测试推理能力

  • 回答正确,根据历史对话的回答中的表结构,判断需要进行问题的拆分,然后使用之前相同的表,只需要把条件从2016改为2017,然后分别生成SQL再调用execute_sql执行,查询数据后再合并分析。

总结

从上述测试中,我们体验了AgentScope框架的优雅之处,包括上下文记忆,支持多轮对话数据传递等能力,此外AgentScope还有长期记忆、MCP调用等更多实用能力,同学们可以自行学习探索~

如今技术圈降薪裁员频频爆发,传统岗位大批缩水,相反AI相关技术岗疯狂扩招,薪资逆势上涨150%,大厂老板们甚至开出70-100W年薪,挖掘AI大模型人才!

技术的稀缺性,才是你「值钱」的关键!

具备AI能力的程序员,比传统开发高出不止一截!有的人早就转行AI方向,拿到百万年薪!👇🏻👇🏻

请添加图片描述

是不是也想抓住这次风口,但卡在 “入门无门”?

  • 小白:想学大模型,却分不清 LLM、微调、部署,不知道从哪下手?
  • 传统程序员:想转型,担心基础不够,找不到适配的学习路径?
  • 求职党:备考大厂 AI 岗,资料零散杂乱,面试真题刷不完?

别再浪费时间踩坑!2025 年最新 AI 大模型全套学习资料已整理完毕,不管你是想入门的小白,还是想转型的传统程序员,这份资料都能帮你少走 90% 的弯路

👇👇扫码免费领取全部内容👇👇

在这里插入图片描述

部分资料展示

一、 AI大模型学习路线图,厘清要学哪些

一个明确的学习路线可以帮助新人了解从哪里开始,按照什么顺序学习,以及需要掌握哪些知识点。大模型领域涉及的知识点非常广泛,没有明确的学习路线可能会导致新人感到迷茫,不知道应该专注于哪些内容。

我们把学习路线分成L1到L4四个阶段,一步步带你从入门到进阶,从理论到实战。

img

L1级别:大模型核心原理与Prompt

在这里插入图片描述

L1阶段: 将全面介绍大语言模型的基本概念、发展历程、核心原理及行业应用。从A11.0到A12.0的变迁,深入解析大模型与通用人工智能的关系。同时,详解OpenAl模型、国产大模型等,并探讨大模型的未来趋势与挑战。此外,还涵盖Pvthon基础、提示工程等内容。
目标与收益:掌握大语言模型的核心知识,了解行业应用与趋势;熟练Python编程,提升提示工程技能,为AI应用开发打下坚实基础。

L2级别:RAG应用开发工程

请添加图片描述

L2阶段: 将深入讲解AI大模型RAG应用开发工程,涵盖Naive RAGPipeline构建、AdvancedRAG前治技术解读、商业化分析与优化方案,以及项目评估与热门项目精讲。通过实战项目,提升RAG应用开发能力。

目标与收益: 掌握RAG应用开发全流程,理解前沿技术,提升商业化分析与优化能力,通过实战项目加深理解与应用。

L3级别:Agent应用架构进阶实践

请添加图片描述

L3阶段: 将 深入探索大模型Agent技术的进阶实践,从Langchain框架的核心组件到Agents的关键技术分析,再到funcation calling与Agent认知框架的深入探讨。同时,通过多个实战项目,如企业知识库、命理Agent机器人、多智能体协同代码生成应用等,以及可视化开发框架与IDE的介绍,全面展示大模型Agent技术的应用与构建。

目标与收益:掌握大模型Agent技术的核心原理与实践应用,能够独立完成Agent系统的设计与开发,提升多智能体协同与复杂任务处理的能力,为AI产品的创新与优化提供有力支持。

L4级别:模型微调与私有化大模型

在这里插入图片描述

L4级别: 将聚焦大模型微调技术与私有化部署,涵盖开源模型评估、微调方法、PEFT主流技术、LORA及其扩展、模型量化技术、大模型应用引警以及多模态模型。通过chatGlM与Lama3的实战案例,深化理论与实践结合。

目标与收益:掌握大模型微调与私有化部署技能,提升模型优化与部署能力,为大模型项目落地打下坚实基础。

二、 全套AI大模型应用开发视频教程

从入门到进阶这里都有,跟着老师学习事半功倍。

在这里插入图片描述

三、 大模型学习书籍&文档

收录《从零做大模型》《动手做AI Agent》等经典著作,搭配阿里云、腾讯云官方技术白皮书,帮你夯实理论基础。

在这里插入图片描述

四、 AI大模型最新行业报告

2025最新行业报告,针对不同行业的现状、趋势、问题、机会等进行系统地调研和评估,以了解哪些行业更适合引入大模型的技术和应用,以及在哪些方面可以发挥大模型的优势。

img

五、大模型大厂面试真题

整理了百度、阿里、字节等企业近三年的AI大模型岗位面试题,涵盖基础理论、技术实操、项目经验等维度,每道题都配有详细解析和答题思路,帮你针对性提升面试竞争力。

img

六、大模型项目实战&配套源码

学以致用,在项目实战中检验和巩固你所学到的知识,同时为你找工作就业和职业发展打下坚实的基础。

img

适用人群

在这里插入图片描述

第一阶段(10天):初阶应用

该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。

  • 大模型 AI 能干什么?
  • 大模型是怎样获得「智能」的?
  • 用好 AI 的核心心法
  • 大模型应用业务架构
  • 大模型应用技术架构
  • 代码示例:向 GPT-3.5 灌入新知识
  • 提示工程的意义和核心思想
  • Prompt 典型构成
  • 指令调优方法论
  • 思维链和思维树
  • Prompt 攻击和防范
第二阶段(30天):高阶应用

该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。

  • 为什么要做 RAG
  • 搭建一个简单的 ChatPDF
  • 检索的基础概念
  • 什么是向量表示(Embeddings)
  • 向量数据库与向量检索
  • 基于向量检索的 RAG
  • 搭建 RAG 系统的扩展知识
  • 混合检索与 RAG-Fusion 简介
  • 向量模型本地部署
第三阶段(30天):模型训练

恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。

到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?

  • 为什么要做 RAG
  • 什么是模型
  • 什么是模型训练
  • 求解器 & 损失函数简介
  • 小实验2:手写一个简单的神经网络并训练它
  • 什么是训练/预训练/微调/轻量化微调
  • Transformer结构简介
  • 轻量化微调
  • 实验数据集的构建
第四阶段(20天):商业闭环

对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。

  • 硬件选型
  • 带你了解全球大模型
  • 使用国产大模型服务
  • 搭建 OpenAI 代理
  • 热身:基于阿里云 PAI 部署 Stable Diffusion
  • 在本地计算机运行大模型
  • 大模型的私有化部署
  • 基于 vLLM 部署大模型
  • 案例:如何优雅地在阿里云私有部署开源大模型
  • 部署一套开源 LLM 项目
  • 内容安全
  • 互联网信息服务算法备案

学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。

如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

在这里插入图片描述

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐