ModelScope-Agent从今年以来承接了魔搭交互式创空间(https://modelscope.cn/studios/agent)的背后应用底座,积累了大量的交互应用经验,并对相关接口能力进行了开源,即原有的agentfabric(https://github.com/modelscope/modelscope-agent/tree/master/apps/agentfabric)升级.

 

在这一过程中,我们收到了大量用户的反馈,需要将应用能力进一步抽象沉淀,变为基础api接口,从而使得用户能够更原子化的应用agent能力在自己的业务场景中。另外,项目团队也希望进一步降低业务对基础能力接口的侵入,能够在后续研发过程中有更好的扩展性。最后,从安全角度考虑,独立的基于容器的tool运行环境也是生产落地的必要条件,因此我们在项目中新增了Assistant API以及Tools API两个应用服务接口能力。

架构介绍

本次提供的两个接口服务Assistant API和Tools API是两个独立的服务,用户可以单独使用,也可以一并使用。

1.1 Assistant API介绍

Assistant API 提供了agent 的planning和action的原子能力,面向的场景是用户传入标准的tool calling信息,以及knowledge信息和message历史信息后,希望获得质量高且稳定的agent planning结果,或者甚至希望直接拿到agent的执行结果。因此,在assistant api中我们提供了两个主要的接口 v1/chat/completions 以及 v1/assistants/lite 接口,除此之外还提供了一个v1/files的接口用于上传外挂知识库。

  • v1/chat/completions:传统的llm的服务,大多仅有prompt输入,用户如果想要进行tool calling的使用,不得不自己进行各种prompt拼接使用不方便;而tool calling本身也是agent planning能力的之一,因此我们支持了允许用户传入需要调用tool信息以及简单的message,就可以返回用户所需要的tool calling能力,并且接口层面,tool信息的传入与openai相同。
  • v1/assistants/lite: 对于已经注册在modelscope-agent的tool,用户可以通过该接口进行调用agent的调用与执行,并最终获得执行后的结果,与openai的 assistant接口不同的是,我们提供了自定义的接口,暂时不返回执行中间的状态信息,仅返回执行结果,用户在使用上降低了接口返回信息的处理开发部分。
  • v1/files: 用户可以通过该接口将一些外挂知识库上传进来,并在调用前两个接口的时候进行使用。

1.2 Tools API介绍

Tools API 主要目的是对于那些工具调用苛刻的场景,希望tool在独立的容器环境中进行执行,隔绝宿主机与容器环境确保宿主机安全。Tools API由一个Tool Manager Server,以及一个基础的Tool Node Server构成。 Tool Manager Server负责创建,管理,移除具体的Tool 执行节点即,实例化后的Tool Node Server。每一个Tool Node Server内部运行着独立工具运行环境,对于需要多租户的场景,也支持不同的租户运行各自相同名字的tool。

值得注意的是,目前Tool的执行依赖docker环境,用户需要确保执行环境下有docker,以便tool能够执行。相关的接口详细较多,在后续具体使用的章节会详细介绍。

 

1.3 服务架构

根据上述两个API服务的介绍,用户应该能大致了解两个接口服务的能力,下图具体说明了Modelscope-Agent 与这两个接口服务的交互关系,从而加深用户对该接口的了解,目前相关代码均为开源代码,因此用户也可以基于架构图进行适用于自己业务场景的改造维护。

 

Modelscope-Agent 与APIs调用服务架构

 

可以从图中左侧看出基于Assistant API的能力,用户根据自己业务场景选择适用的agent阶段获得所需要的能力,通过Modelscope-agent上的不同的agent,用户可以在该流程中获得不同的推理能力增强,目前默认采用的是基于ReAct方做的增强,用户也可以通过在Modelscope-Agent上贡献自己的Agent,从而通过接口调用的方式完成应用业务落地。

图中右侧部分为Tools API即Tool Manager,默认已经适配到Modelscope-Agent框架中,用户只需要简单的参数配置即可决定是否使用。通过Tool Manager, 不同的Tool会被实例化出来成为独立的server,以便用户在独立的环境中更安全的执行应用。

同时,左右两侧模块相对独立,对于缺失docker环境的用户可以忽略使用Tools API, 同样对于安全性要求低,且仅需要利用agent推理能力提升的,则可以直接使用Assistant API即可。

 

Assistant API 使用详情

安装启动

依赖

- Modelscope-agent 0.5.0

- Python 3.8 or above

启动

# get latest code
git clone https://github.com/modelscope/modelscope-agent.git
cd modelscope-agent

# start the assistant server
sh scripts/run_assistant_server.sh

通过上述脚本启动后, Assistant API会默认启动到用户本地端口 31512上。

Assistant API接口详情

v1/files

files接口支持用户上传本地的文件,并在server端基于uuid_str进行管理。

用户可以通过Python的requests库进行文件上传,示例代码如下。

url = 'http://localhost:31512/v1/files'

datas = {
    'uuid_str': 'test'
}

files = [
    ('files', ('Agent.pdf', open('Agent.pdf', 'rb'), 'text/plain'))
]

response = requests.post(url, data=datas, files=files)
print(response.text)

其中,每个上传的文件需要指定文件名,文件名可在chat或者是assistantAPI中指定知识库范围使用。此外,为了方便管理,文件名中不能包含任何路径,例如,使用../Agent.pdf作为文件名是不被允许的。

v1/chat/completions

用户如果想要调用v1/chat/completionsAPI,主要涉及以下几个字段的定义:

  • llm_config:LLM的相关配置,包括
    • model:所使用的模型名称
    • model_server:该模型对应的服务后端
    • api_key:如果该模型需要使用api_key,用户可以在配置中传入

 

一个常用的llm_config配置如下所示。

llm_cfg = {
    'model': 'qwen-max',
    'model_server': 'dashscope',
    'api_key': os.environ.get('DASHSCOPE_API_KEY'),
}
  • messages:本次调用所发送的message信息。message应该遵循类似于如下的格式:
messages = [
    {"content": "海淀区天气", "role": "user"}
],

chat API基于modelscope agent框架,支持function calling和knowledge retrieval两个扩展功能。

  • uuid_str:用户uid,主要是对不同用户的请求进行简单的区分。

function callling

如果用户想要使用function calling功能,需要对tool字段进行配置。一个tool配置的例子如下所示:

"tools": [{
    "type": "function",
    "function": {
        "name": "amap_weather",
        "description": "amap weather tool",
        "parameters": [{
            "name": "location",
            "type": "string",
            "description": "城市/区具体名称,如`北京市海淀区`请描述为`海淀区`",
            "required": true
        }]
    }
}]

基于上述配置,我们可以使用curl构造一个完整的请求,如下:

curl -X POST 'http://localhost:31512/v1/chat/completions' \
-H 'Content-Type: application/json' \
-d '{
    "tools": [{
        "type": "function",
        "function": {
            "name": "amap_weather",
            "description": "amap weather tool",
            "parameters": [{
                "name": "location",
                "type": "string",
                "description": "城市/区具体名称,如`北京市海淀区`请描述为`海淀区`",
                "required": true
            }]
        }
    }],
    "tool_choice": "auto",
    "llm_config": {
        "model": "qwen-max",
        "model_server": "dashscope",
        "api_key": "YOUR DASHSCOPE API KEY"
    },
    "messages": [
        {"role": "user", "content": "海淀区天气"}
    ],
    "uuid_str": "test",
    "stream": false
}'

```

此时,可以得到如下的结果:

{
    "request_id":"xxxxx",
    "message":"",
    "output": None,
    "choices": [{
        "index":0,
        "message": {
            "role": "assistant",
            "content": "Action: amap_weather\nAction Input: {\"location\": \"海淀区\"}\n",
            "tool_calls": [
                {
                    "type": "function",
                    "function": {
                        "name": "amap_weather",
                        "arguments": "{\"location\":\"海淀区\"}"
                }
            }]
        },
        "finish_reason": "tool_calls"
    }]
}

knowledge retrieval

如果用户需要使用knowledge retrieval功能,需要首先基于v1/filesAPI 上传对应的文件。随后,用户可以通过use_knowledge字段指定是否使用知识库检索。

我们还支持了知识库范围的动态指定,用户可以通过在files字段中指定需要使用的文件名,如果不指定文件名则默认使用所有的文件。

使用知识库召回功能的curl请求构建如下所示:

curl -X POST 'http://localhost:31512/v1/chat/completions' \
-H 'Content-Type: application/json' \
-d '{
    "llm_config": {
        "model": "qwen-max",
        "model_server": "dashscope",
        "api_key": "YOUR DASHSCOPE API KEY"
    },
    "messages": [
        {"role": "user", "content": "高德天气api申请"}
    ],
    "uuid_str": "test",
    "stream": false,
    "use_knowledge": true,
    "files": ["QA.pdf"]
}'

如果文件存在,将会得到如下的结果:

{
    "request_id":"2bdb05fb-48b6-4ba2-9a38-7c9eb7c5c88e",
    "message":"",
    "output": None,
    "choices": [{
        "index":0,
        "message": {
            "role": "assistant",
            "content": "Information based on knowledge retrieval.",
        }
        "finish_reason": "stop"

    }]
}

如果不存在,则会给出相应的提示信息:

{
    "request_id":"f698aeb7-34bf-4471-9e55-d7ff212d483d",
    "message":"No valid knowledge contents."
}

v1/assistants/lite

v1/assistants/liteAPI的使用方式与v1/chat/completions类似,区别在于可以通过配置agent_config字段自定义角色信息和工具,并在server端完成工具调用,返回最终的结果。

 

在v1/assistants/liteAPI中,用户需要基于agent_config定义以下字段:

  • name:assistant的名称。
  • description:assistant的具体功能。
  • instruction:该assistant对应的system prompt相关信息。准确的instruction可以帮助assistant更好的决策,得到想要的结果。
  • tools:assistant可以使用的工具名称。
agent_config = {
    "name": "test",
    "description": "test assistant",
    "instruction": "you are a helpful assistant",
    "tools": ["amap_weather"]
}

 

由于需要agent执行代码,用户自定义传入的tools, 以及tool_choices这里无法产生效果,可以不传。与此同时,agent_config中会添加已经在modelscope-agent中注册过的Tool。 对于如何在框架中添加Tool,可以参考文章(https://github.com/modelscope/modelscope-agent/blob/feat/assistant_api/docs/contributing/tool_contribution_guide_CN.md)。

 

v1/assistants/liteAPI还支持了流式返回,用户可以通过指定stream=True使该功能生效。之后,可以通过下列代码获取输出结果:

# 构造request 
request = {
    'agent_config': agent_cfg,
    'llm_config': llm_cfg,
    'messages': [
        {'role': 'user', 'content': '高德天气API申请'}
    ],
    'uuid_str': 'test',
    'stream': True,
    'use_knowledge': True,
    'files': ['QA.pdf']
}
datas = {
    'agent_request': json.dumps(request)
}

# 处理返回结果
response = requests.post(url, json=request)
if response.encoding is None:
    response.encoding = 'utf-8'
print(response)
print(response.text)
for line in response.iter_lines(decode_unicode=True):
    if line:
        print(line)
        print('----------')

 

与Tools API联动使用

对于需要代码执行的接口,即v1/assistant/lite,用户需要按照下面Tool API 章节介绍启动 Tool Manager API后,在参数传递中加入额外的 user_tool_api: True, 即可实现与Tools API的联动。

同时,在Tool API 调用的时候,需要实时传入该工具的token,这里目前支持的token字段如下,输入ApiNames的name即可,如需要使用dashscope的接口则传入dashscope_api_key,如需要使用多个,则可传入多个。

class ApiNames(Enum):
    dashscope_api_key = 'DASHSCOPE_API_KEY'
    modelscope_api_key = 'MODELSCOPE_API_TOKEN'
    amap_api_key = 'AMAP_TOKEN'
    bing_api_key = 'BING_SEARCH_V7_SUBSCRIPTION_KEY'

因此,一个完整的请求会如下述,其中最后两行为tool调用所需要使用的token。

curl -X POST 'http://localhost:31512/v1/assistants/lite' \
-H 'Content-Type: application/json' \
-d '{
    "agent_config": {
        "tools": ["amap_weather"],
        "name": "test",
        "description": "test assistant",
        "instruction": "you are a helpful assistant"
    }
    "llm_config": {
        "model": "qwen-max",
        "model_server": "dashscope",
        "api_key": "YOUR DASHSCOPE API KEY"
    },
    "messages": [
        {"content": "海淀区天气", "role": "user"}
    ],
    "uuid_str": "test",
    "stream": false,
    "use_tool_api": true,
    "amap_api_key": "xxxxxxxxx"
}'

```

Tools API 使用详情

安装启动

依赖

- Docker installed

- Docker daemon running

- Modelscope-agent 0.5.0

- Python 3.8 or above

启动

对于第一次启动的用户,需要本地构建 Tool Node的镜像,以便进行后续Tool Node的启动。注意构建的时候会耗时较长,请耐心等待。

# get latest code
git clone https://github.com/modelscope/modelscope-agent.git
cd modelscope-agent

# for the first time please run the following command to install the dependencies and build tool images
sh scripts/run_tool_manager.sh build

对于已经构建过的用户,可以直接进行如下命令启动

# get latest code
git clone https://github.com/modelscope/modelscope-agent.git
cd modelscope-agent

# start tool manager
sh scripts/run_tool_manager.sh

通过上述脚本启动后, Tool Manager API会默认启动到用户本地端口 31511上。

Modelscope-Agent中调用Tools API

以下代码片段演示了如何在agent中运行工具服务。

  1. 确保将use_tool_api=True传入RolePlay类
  2. 将dashscope_api_key传递到run方法中,后续我们将提供Oauth server,以便存储管理用户的各种tool的token及server。
from modelscope_agent.agents.role_play import RolePlay
import os

llm_config = {'model': 'qwen-turbo', 'model_server': 'dashscope'}

# input tool name
function_list = ['image_gen']

bot = RolePlay(function_list=function_list, llm=llm_config, use_tool_api=True)

response = bot.run(
    '创建一个多啦A梦', dashscope_api_key=os.getenv('DASHSCOPE_API_KEY'))

text = ''
for chunk in response:
    text += chunk
print(text)
assert isinstance(text, str)
assert 'Answer:' in text
assert 'Observation:' in text
assert '![IMAGEGEN]' in text

可以看到,Tools API的使用几乎与本地工具调用没有区别,唯一的区别是,通过设置use_tool_api=True,此时的服务是在docker容器中运行的。

 

Tool API 接口详情

目前Tool调用已经封装到Modelscope-Agent框架中,用户可根据use_tool_api=True来启用。 如果用户需要对服务进行管理,可以基于以下接口完成。

 

create_tool_service

创建一个Tool Node实例,使用curl构造一个完整的请求,如下:

curl -X POST 'http://localhost:31511/create_tool_service' \
-H 'Content-Type: application/json' \
-d '{
    "tool_name": "RenewInstance",
    "tenant_id": "default",
    "tool_cfg": {},
    "tool_image": "modelscope-agent/tool-node:lastest"
}'

将会得到如下的结果:

{
    "request_id": "311f2e35-8dc3-48a3-a356-b255ee4b268c",
    "message": "",
    "output":
        {
          "tool_node_name": "RenewInstance_default",
          "status": "pending"
        }
}

check_tool_service_status

获取Tool Node实例状态,使用curl构造一个完整的请求,如下:

curl -X POST 'http://localhost:31511/check_tool_service_status/' \
-H 'Content-Type: application/json' \
-d '{
    "tool_name": "string",
    "tenant_id": "default"
}'

将会得到如下的结果:

{
    "request_id": "311f2e35-8dc3-48a3-a356-b255ee4b268c",
    "message": "",
    "output":
        {
          "tool_node_name": "RenewInstance_default",
          "status": "running"
        }
}

remove_tool

删除Tool Node实例,使用curl构造一个完整的请求,如下:

curl -X POST 'http://localhost:31511/remove_tool/' \
-H 'Content-Type: application/json' \
-d '{
    "tool_name": "RenewInstance",
    "tenant_id": "default"
}'

将会得到如下的结果:

{
    "request_id": "311f2e35-8dc3-48a3-a356-b255ee4b268c",
    "message": "",
    "output":
        {
          "tool_node_name": "RenewInstance_default",
          "status": "exited"
        }
}

tools/?tenant_id=default

获取租户Tool Node实例,使用curl构造一个完整的请求,如下:

curl -X GET 'http://localhost:31511/tools/?tenant_id=default' \
-H 'Content-Type: application/json'

将会得到如下的结果:

{
    "request_id": "311f2e35-8dc3-48a3-a356-b255ee4b268c",
    "message": "",
    "output":
        {
          "tools":{
            "RenewInstance_default": "running",
            "CreateInstance_default": "exited"
          }
        }
}

tool_info

获取工具信息,使用curl构造一个完整的请求,如下:

curl -X POST 'http://localhost:31511/tool_info/' \
-H 'Content-Type: application/json' \
-d '{
    "tool_name": "string",
    "tenant_id": "default",
}'

将会得到如下的结果:

{
    "request_id": "311f2e35-8dc3-48a3-a356-b255ee4b268c",
    "message": "",
    "output": {
        "description": "续费一台包年包月ECS实例",
        "name": "RenewInstance",
        "parameters"[{
            "name": "instance_id",
            "description": "ECS实例ID",
            "required": True,
            "type": "string"
        }, {
            "name": "period",
            "description": "续费时长以月为单位",
            "required": True,
            "type": "string"
        }]
    }
}

execute_tool

执行Tool Node,使用curl构造一个完整的请求,如下:

curl -X POST 'http://localhost:31511/execute_tool/' \
-H 'Content-Type: application/json' \
-d '{
    "tool_name": "string",
    "tenant_id": "default",
    "params": "{\"instance_id\": 123, \"period\": \"mon\"}",
    "kwargs": {}
}'

将会得到如下的结果:

{
    "request_id": "311f2e35-8dc3-48a3-a356-b255ee4b268c",
    "message": "",
    "output": "已完成ECS实例ID为123的续费,续费时长mon月"
}

Future work

目前,API相关的工作还处于起步阶段,在接口使用上面还有较多不便利性需要提升,集中体现如下:

  1. 增加鉴权模块,提供生产级别安全支持,进行用户权限管理
  2. 魔搭Agent的api接口v1/chat/completions以及v1/assistants/lite 与openai的原生接口有出入,这里我们会根据用户反馈确定是否开发与原生openai接口完全匹配的接口版本。
  3. 当前支持的tool数量、应用示例有限,需要持续拓展,希望开发者能够一起参与共建。
  4. rag能力的持续提升,提供多源多策略多模态的rag能力。

 

另外,我们也有RoadMap未完成的工作,需要社区同学一起共建,相关可查看:https://github.com/modelscope/modelscope-agent/issues/350, 欢迎有兴趣的小伙伴一起共建

 

 

 

我们的github地址:https://github.com/modelscope/modelscope-agent

 

欢迎对Agent生态感兴趣的开发者小伙伴们,可进入Agent品牌馆体验~

 

链接:https://www.modelscope.cn/brand/view/agent?branch=0&tree=11

 

Logo

ModelScope旨在打造下一代开源的模型即服务共享平台,为泛AI开发者提供灵活、易用、低成本的一站式模型服务产品,让模型应用更简单!

更多推荐