dashscope python sdk使用

dashscope是阿里云对外提供大模型的平台,通过dashscope sdk可以调用阿里云对外提供的大模型服务,目前可使用的模型有qwen,llama2等模型。

参考文档:https://help.aliyun.com/zh/dashscope/developer-reference

基本使用

安装sdk和设置api_key过程参考上述官方文档,setup完成后,dashscope提供了两种调用方式

方式1:通过message调用

from http import HTTPStatus
import dashscope


def call_with_messages():
    messages = [{'role': 'system', 'content': 'You are a helpful assistant.'},
                {'role': 'user', 'content': '如何做炒西红柿鸡蛋?'}]

    response = dashscope.Generation.call(
        dashscope.Generation.Models.qwen_turbo,
        messages=messages,
        result_format='message',  # set the result to be "message" format.
    )
    if response.status_code == HTTPStatus.OK:
        print(response)
    else:
        print('Request id: %s, Status code: %s, error code: %s, error message: %s' % (
            response.request_id, response.status_code,
            response.code, response.message
        ))


if __name__ == '__main__':
    call_with_messages()

调用后输出结果

{
    "status_code": 200,
    "request_id": "9da1ba31-b22a-9540-be18-793672d1ac8f",
    "code": "",
    "message": "",
    "output": {
        "text": null,
        "finish_reason": null,
        "choices": [
            {
                "finish_reason": "stop",
                "message": {
                    "role": "assistant",
                    "content": "做西红柿鸡蛋的步骤如下:\n\n材料:\n- 鸡蛋 3 个\n- 西红柿 2 个\n-葱 适量\n- 蒜 适量\n- 盐 适量\n- 生抽 适量\n- 糖 适量\n- 胡椒粉 适量\n- 水淀粉 适量\n\n步骤:\n1. 西红柿去皮,切块;鸡蛋打散,加入适量盐和胡椒粉调味;\n2. 锅中加入适量油,倒入鸡蛋液,炒散;\n3. 加入葱蒜末,翻炒均匀;\n4. 加入西红柿块,翻炒至软烂;\n5. 加入适量生抽和糖,翻炒均匀;\n6. 最后加入适量水淀粉,翻炒均匀即可。"
                }
            }
        ]
    },
    "usage": {
        "input_tokens": 31,
        "output_tokens": 183
    }
}

方式2:通过prompt调用

from http import HTTPStatus
import dashscope


def call_with_prompt():
    response = dashscope.Generation.call(
        model=dashscope.Generation.Models.qwen_turbo,
        prompt='如何做炒西红柿鸡蛋?'
    )

    if response.status_code == HTTPStatus.OK:
        print(response)
    else:
        print('Request id: %s, Status code: %s, error code: %s, error message: %s' % (
            response.request_id, response.status_code,
            response.code, response.message
        ))

if __name__ == '__main__':
    call_with_prompt()

调用后输出结果

{
    "status_code": 200,
    "request_id": "237a9bcc-4749-945c-805a-38c2345555d9",
    "code": "",
    "message": "",
    "output": {
        "text": "材料:\n西红柿2个,鸡蛋3个,盐1茶匙,糖1/2茶匙,植物油2大匙\n\n做法:\n\n1. 西红柿切块,鸡蛋打散。\n2. 锅中放油,油热后倒入鸡蛋液,用铲子快 速搅散,炒成金黄色盛出备用。\n3. 锅中再加一点油,放入西红柿块,加1/4茶匙糖,中火慢慢把西红柿炒成糊状,加少许水,一起煮沸。\n4. 煮沸后转小火,慢慢熬煮至浓稠,边煮边搅拌,防止糊锅。\n5. 加入炒好的鸡蛋,加盐调味,翻煮均匀即可。可以根据个人口味再加点香菜或者葱花提味。",
        "finish_reason": "stop",
        "choices": null
    },
    "usage": {
        "input_tokens": 24,
        "output_tokens": 171,
        "total_tokens": 195
    }
}

二者区别

官方解释:

  • messages:用户与模型的对话历史。list中的每个元素形式为{“role”:角色, “content”: 内容},角色当前可选值:systemuserassistanttool
    • system:表示系统级消息,只能用于对话历史的第一条(messages[0])。使用system角色是可选的,如果存在,必须位于列表的最开始。
    • userassistant:表示用户和模型的对话。它们应交替出现在对话中,模拟实际对话流程。
    • tool:在使用function_call功能时,如果要传入function的结果,这个message的形式为{“content”:”Boston is raining.”, “name”:”get_current_weather”, “role”:”tool”},其中name是function的名称,需要和上轮response中的tool_calls[i].function.name参数保持一致,content为function的输出。参考代码中的多轮调用给出了示例。
  • prompt:用户当前输入的期望模型执行指令,用于指导模型生成回复。

说明

messages和prompt任选一个参数使用即可。由于和prompt组合使用的对话历史参数history即将废弃,仅依赖prompt指令会限制模型进行有记忆的对话能力。

而messages参数允许模型参考历史对话,从而更准确地解析用户的意图,确保对话的流程性和连续性,因此在多轮对话场景下推荐您优先使用messages参数。

总结:

prompt需要和history参数结合似乎用才能使模型具有完整的上下文记忆能力,而history参数先处于deprecated状态,故建议使用messages。

messages中需要设定角色和角色的发言内容。

其他

  • call函数中result_format参数有text和message两种值,默认为text。如果为text类型则会输出md标记的文本内容,如果为message则输出无标记的内容(更省token)。

多轮调用

messages列表的先后顺序就表示了各个角色的发言顺序和内容

使用message方法,直接将上次调用结果返回的message加入到messages列表中,再加入用户输入即可。

from http import HTTPStatus
from dashscope import Generation
from dashscope.api_entities.dashscope_response import Role


def multi_round():
    messages = [{'role': Role.SYSTEM, 'content': 'You are a helpful assistant.'},
                {'role': Role.USER, 'content': '如何做西红柿炖牛腩?'}]
    response = Generation.call("qwen-turbo",
                               messages=messages,
                               # set the result to be "message" format.
                               result_format='message',
                               )
    if response.status_code == HTTPStatus.OK:
        print(response)
        # append result assistant response to messages.
        messages.append({'role': response.output.choices[0]['message']['role'],
                         'content': response.output.choices[0]['message']['content']})
    else:
        print('Request id: %s, Status code: %s, error code: %s, error message: %s' % (
            response.request_id, response.status_code,
            response.code, response.message
        ))
        # 如果失败,将最后一条user message从message列表里删除,确保user/assistant消息交替出现
        messages = messages[:-1]
    messages.append({'role': Role.USER, 'content': '不放糖可以吗?'})
    # make second round call
    response = Generation.call("qwen-turbo",
                               messages=messages,
                               result_format='message',  # set the result to be "message" format.
                               )
    if response.status_code == HTTPStatus.OK:
        print(response)
    else:
        print('Request id: %s, Status code: %s, error code: %s, error message: %s' % (
            response.request_id, response.status_code,
            response.code, response.message
        ))


if __name__ == '__main__':
    multi_round()

function call

在模型使用外部工具时会在返回的tools指明tool的名字以及调用参数(具体返回值含义见返回参数说明),应用程序应该根据参数调用该工具,之后将返回结果作为tool角色的发言记录在messages中供大模型参考,大模型会根据tool角色的发言来生成对user角色问题的回答。

import random
from http import HTTPStatus
import dashscope

# 改部分的格式定义见小节中的tools格式定义
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "Get the current weather in a given location",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "The city and state, e.g. San Francisco, CA"
                    },
                    "unit": {
                        "type": "string",
                        "enum": [
                            "celsius",
                            "fahrenheit"
                        ]
                    }
                },
                "required": [
                    "location"
                ]
            }
        }
    }
]


def call_with_messages():
    messages = [
        {
            "content": "What is the weather like in Boston?",
            "role": "user"
        },
        {
            "role": "assistant",
            "content": "",
            "tool_calls": [
                {
                    "function": {
                        "name": "get_current_weather",
                        "arguments": "{\"location\": \"Boston\", \"unit\": \"fahrenheit\"}"
                    },
                    "id": "",
                    "type": "function"
                }
            ]
        },
        {
            "content": "Boston is raining.",
            "name": "get_current_weather",
            "role": "tool"
        }
    ]
    response = dashscope.Generation.call(
        dashscope.Generation.Models.qwen_turbo,
        messages=messages,
        tools=tools,
        seed=random.randint(1, 10000),  # set the random seed, optional, default to 1234 if not set
        result_format='message',  # set the result to be "message" format.
    )
    if response.status_code == HTTPStatus.OK:
        print(response)
    else:
        print('Request id: %s, Status code: %s, error code: %s, error message: %s' % (
            response.request_id, response.status_code,
            response.code, response.message
        ))


if __name__ == '__main__':
    call_with_messages()

tools格式定义

tools列表定义

模型可选调用的工具列表。目前仅支持function,并且即使输入多个function,模型仅会选择其中一个生成结果。模型根据tools参数内容可以生产函数调用的参数,tools中每一个tool的结构如下:

  • type,类型为string,表示tools的类型,当前仅支持function。
  • function,类型为dict,包括name,description和parameters:
    • name,类型为string,表示function的名称,必须是字母、数字,或包含下划线和短划线,最大长度为64。
    • description,类型为string,表示function的描述,供模型选择何时以及如何调用function。
    • parameters,类型为dict,表示function的参数描述,需要是一个合法的json schema。json schema的描述可以见链接参考代码中给出了一个参数描述的示例。如果parameters参数缺省了,表示function没有入参。

使用tools功能时需要指定result_format为message。在多轮对话中,无论是发起function_call的轮次,还是向模型提交function的执行结果,均请设置tools参数。当前支持qwen-turbo、qwen-plus、qwen-max和qwen-max-longcontext。

返回参数说明

返回参数 类型 说明 备注
status_code int 200(HTTPStatus.OK)表示请求成功,否则表示请求失败,可以通过code获取错误码,通过message字段获取错误详细信息。说明Python才有这个字段,Java失败会抛异常,异常信息为code,message内容。  
request_Id string 系统生成的标志本次调用的id。  
code string 表示请求失败,表示错误码,成功忽略。python only  
message string 失败,表示失败详细信息,成功忽略。python only  
output dict 调用结果信息,对于千问模型,包含输出text。  
usage dict 计量信息,表示本次请求计量数据。  
output.text string 模型生成回复,仅prompt调用使用,过时的格式。  
output.finish_reason string 有四种情况:正在生成时为null,生成结束时如果由于停止token导致则为stop,如果因为生成长度过长导致则为length,如果因为发生工具调用则为tool_calls。  
usage.input_tokens int 用户输入文本转换成Token后的长度。 参考sdk提供的本地tokenizer统计token数据。
usage.output_tokens int 模型生成回复转换为Token后的长度。  
choices List [] 当result_format为message输出choices
choices[i].finish_reason string 有三种情况:正在生成时为null,生成结束时如果由于停止token导致则为stop,生成结束时如果因为生成长度过长导致则为length。 当result_format为message输出choices
choices[i].message dict 模型生成消息输出 当result_format为message输出choices
message.role string 模型role,固定为assistant  
message.content string 模型生成的文本  
message.tool_calls dict 如果模型判断需要调用工具,则会生成tool_calls参数,当前应用于function_call场景 其中包含type和function两个参数,返回结果中给出了function_call的示例。参数详情如下:type,类型为string,当前只可能为functionfunction,类型为dict,包含name和arguments两个参数:name,类型为string,表示需要调用的工具的名称,如果是function_call场景则表示要调用的function名称arguments,类型为string,表示模型生成的工具入参,一般情况下可以json.loads为dict类型。