最佳实践-基于本地Function定制百炼应用

简介

本文基于百炼上已经创建的RAG应用(操作方法请参考最佳实践-基于RAG的官方文档助手),结合用户本地Function,帮助用户实现更加定制的应用。

您可以通过本篇帮助文档实现:

  • 在百炼官方文档助手的基础上,结合百炼平台相关API的调用,实现以下功能调用:

    • 返回百炼账户当前API Key;

    • 当前模型训练情况;

    • 获取百炼计费账单;

依赖功能

  • Assistant API的基础API参数生成能力。

  • Assistant APIFunction Call能力。

  • 百炼应用的RAG能力。

前期准备

设置您的API-KEY,替换YOUR_DASHCOPE_API_KEY为您自己的API key

export DASHSCOPE_API_KEY=YOUR_DASHSCOPE_API_KEY
def call_rag_app(prompt='请问百炼平台如何获取API KEY?'):
    #prompt= 请问百炼平台提供的混合训练能力是什么?
    #请问百炼平台如何获取API KEY?
    response = Application.call(app_id='your_app_id',
                                prompt=prompt)

    if response.status_code != HTTPStatus.OK:
        print('request_id=%s, code=%s, message=%s\n' % (response.request_id, response.status_code, response.message))
        answer = response.status_code
    else:
        print('request_id=%s\n output=%s\n usage=%s\n' % (response.request_id, response.output, response.usage))
        answer = response.output["text"]

    return answer

本地Function

  • 用户可以自行准备各类待使用的私有API或者Function能力,用于处理本地调用的请求。

  • 本文的最佳实践采用模拟的function模拟真实情况。

def get_api_key(user_id):
    return "sk_" + user_id+' 您已消费8.88元'

#
def get_code(user_id):
    return 'https://help.aliyun.com/document_detail/2782117.html'

def get_model_cost(user_id):
    answer =""
    model_name=['qwen-max','qwen-turbo','qwen_plus']
    for model in model_name:
        answer+='\nmodel_name: '+ model+ '\ncost '+str(len(model))+' \n token usage'+str(999)

    return str(answer)

def get_train_model(user_id):
    answer =""
    model_list=['qwen-max-sft-v1']
    for model in model_list:
        answer+='\nmodel_name: '+ model+ '\ntrain_acc '+str(86.44)+' \n training time'+'21 hours 40 mintues'

    return str(answer)

def get_application(user_id):
    # mocked api key
    return str([
        {'app_id':'123', 'app 名称':'智能助理'},
        {'app_id': '124', 'app 名称': '旅游助理'},
    ])

基于Assistant API,实现Function Call

实现在通过检索文档的基础上,完成各类本地function-call的能力,具体实现代码如下:

  • call_rag_app 模块:使用之前创建的应用

  • send_message 模块:传递messageassistant

  • user_config : 外部或环境变量中的部分用户信息

# coding: utf8
from http import HTTPStatus
from dashscope import Application, Assistants, Messages, Runs, Threads
from bailian_function_utils import *
import json
import os


# -*- encoding: utf-8 -*-
def create_assistant():
    # create assistant with information
    assistant = Assistants.create(
        model="qwen-max",
        name='smart helper',
        description='一个智能助手,可以通过用户诉求,调用已有的插件能力帮助用户。',
        instructions='你是一个信息处理者,不会和用户进行二次交互。首先需要总结用户当前输入。然后根据已有插件补充用户的语句。'
                     '请按优先级依次查询下列情况:'
                     '1.若提及训练模型相关,必须调用获取训练模型情况插件,该调用无需询问用户具体模型情况,获取训练模型情况会返回所有结果,请都展示给用户。'
                     '2.若提及assistant-api,必须调用最佳实践查询插件,返回具体assistant-api的最佳实践代码链接,该调用无需询问用户。'
                     '3.若上述情况都没出现,还询问api-key相关,请返回他的apikey具体值。'
                     '请不要主动询问用户,任何潜在的调用请主动发起。',
        tools=[
            {
                'type': 'function',
                'function': {
                    'name': '最佳实践查询',
                    'description': '返回assistant-api相关的最佳实践代码链接',
                    'parameters': {
                        'type': 'object',
                        'properties': {
                            'user_id': {
                                'type': 'str',
                                'description': '用户id'
                            },
                        },
                        'required': ['user_id']},
                },
            },
            {
                'type': 'function',
                'function': {
                    'name': '获取训练模型情况',
                    'description': '用于获取用户部署在百炼平台上用数据额外训练的模型情况。包含SFT模型的具体情况',
                    'parameters': {
                        'type': 'object',
                        'properties': {
                            'user_id': {
                                'type': 'str',
                                'description': '用户id'
                            },
                        },
                        'required': ['user_id']
                    }
                }
            },
            {
                'type': 'function',
                'function': {
                    'name': '应用创建情况',
                    'description': '可以查询应用相关信息。用于返回用户当前应用的具体创建情况,即用户路径下的应用创建数量和对应的id。',
                    'parameters': {
                        'type': 'object',
                        'properties': {
                            'user_id': {
                                'type': 'str',
                                'description': '用户id'
                            },
                        },
                        'required': ['user_id']
                    }
                }
            },
            {
                'type': 'function',
                'function': {
                    'name': '模型用量查询',
                    'description': '一个通用的超大规模语言模型用量查询接口,直接查询下所有模型(含通义千问)使用量。',
                    'parameters': {
                        'type': 'object',
                        'properties': {
                            'user_id': {
                                'type': 'str',
                                'description': '用户id'
                            },
                        },
                        'required': ['user_id']
                    }
                }
            },
            {
                'type': 'function',
                'function': {
                    'name': 'apikey查询',
                    'description': '用于apikey的具体值',
                    'parameters': {
                        'type': 'object',
                        'properties': {
                            'user_id': {
                                'type': 'str',
                                'description': '用户id'
                            },
                            'required': ['user_id']
                        }
                    }
                },
            },

        ],
    )

    return assistant


function_mapper = {
    "apikey查询": get_api_key,
    "获取训练模型情况": get_train_model,
    "应用创建情况": get_application,
    "最佳实践查询": get_code,
}


def send_message(assistant, message=''):
    print(f"Query: {message}")

    # create a thread.
    thread = Threads.create()
    print(thread)

    # create a message.
    message = Messages.create(thread.id, content=message)
    print(message)

    run = Runs.create(thread.id, assistant_id=assistant.id)
    print(run)

    # # get run statue
    # run_status = Runs.get(run.id, thread_id=thread.id)
    # print(run_status)

    # wait for run completed or requires_action
    run_status = Runs.wait(run.id, thread_id=thread.id)
    print('插件调用前:')
    print(run_status)
    if run_status.status == 'failed':
        print('run failed:')
        print(run_status.last_error)

    # if prompt input tool result, submit tool result.
    if run_status.required_action:

        f = run_status.required_action.submit_tool_outputs.tool_calls[0].function
        func_name = f['name']
        param = json.loads(f['arguments'])
        print(f)
        if func_name in function_mapper:
            output = function_mapper[func_name](**param)
        else:
            output = ""

        tool_outputs = [{
            'output':
                output
        }]

        run = Runs.submit_tool_outputs(run.id,
                                       thread_id=thread.id,
                                       tool_outputs=tool_outputs)

        # should wait for run completed
        run_status = Runs.wait(run.id, thread_id=thread.id)
        print(run_status)
        # verify_status_code(run_status)

    run_status = Runs.get(run.id, thread_id=thread.id)
    # print(run_status)
    # verify_status_code(run_status)

    # get the thread messages.
    msgs = Messages.list(thread.id)
    # print(msgs)
    # print(json.dumps(msgs, default=lambda o: o.__dict__, sort_keys=True, indent=4))

    print("运行结果:")
    for message in msgs['data'][::-1]:
        print("content: ", message['content'][0]['text']['value'])
    print("\n")


if __name__ == '__main__':
    assistant = create_assistant()

    # answer = call_rag_app(prompt='模型训练?') # example 1
    answer = call_rag_app(prompt='请问Assistant API如何创建?')  # example 2

    # 'assistant-api怎么使用'#output["text"]#call_rag_app(请问Assistant API如何创建?)
    user_config = os.environ["user_config"]
    send_message(assistant=assistant, message=user_config + answer)

运行结果

测试用例1

  • 输入:“请问Assistant API如何创建?”

    • answer = call_rag_app(prompt='请问Assistant API如何创建?')

  • 运行结果:

{'name': '最佳实践查询', 'arguments': '{"user_id": "user_123456"}', 'output': None}
运行结果:
content:  当前用户是user_123456。创建Assistant API主要涉及几个关键步骤,以下是根据提供的文档内容整理的简要流程:

1. **准备开发环境**:
   - 确保你的系统支持Python 3.8及以上版本。
   - 使用pip命令安装Dashscope库:`pip install dashscope>=1.17.0`
   - 设置环境变量以包含你的百炼API密钥:`export DASHSCOPE_API_KEY=YOUR_DASHSCOPE_API_KEY`,记得将`YOUR_DASHSCOPE_API_KEY`替换为实际的API密钥。

2. **创建Assistant**:
   - 导入必要的库:`from http import HTTPStatus import dashscope`
   - 使用`dashscope.Assistants.create`方法来创建Assistant。你需要提供模型名称(如`qwen-max`)、Assistant的名字、描述以及指令等信息。还可以指定使用的工具或函数,例如文本到图像转换、搜索引擎调用或自定义函数调用等。示例如下:
     ```python
     assistant = dashscope.Assistants.create(
         model='qwen-max',
         name='My helper',
         description='A tool helper.',
         instructions='You are a helpful assistant. When asked a question, use tools wherever possible.',
         tools=[
             {'type': 'text_to_image'},  # 图像生成插件
             {'type': 'quark_search'},  # 搜索引擎插件
             {
                 'type': 'function',
                 'function': {
                     'name': 'big_add',
                     'description': 'Add two numbers',
                     'parameters': {
                         'type': 'object',
                         'properties': {
                             'left': {'type': 'integer', 'description': 'The left operand'},
                             'right': {'type': 'integer', 'description': 'The right operand'}
                         },
                         'required': ['left', 'right']
                     }
                 }
             }
         ]
     )
     ```
   - 创建后,检查`assistant.status_code`是否为`HTTPStatus.OK`以确认Assistant创建成功,并获取其ID。

3. **创建Thread**:
   - 为了与Assistant交互,你需要创建一个Thread。Thread是承载消息(Message)的容器,每个Message代表一次用户提问或Assistant回复。
     ```python
     thread = dashscope.Threads.create(messages=[{"role": "user", "content": "Tell me something about AI."}])
     ```
   - 同样,检查`thread.status_code`以确保Thread创建成功,并记录Thread ID以便后续使用。

完成上述步骤后,你便成功创建了一个Assistant,并且为它创建了第一个对话Thread,接下来就可以向这个Thread发送消息来获取Assistant的响应了。
content:  为了帮助您更好地实现这些步骤,这里有一份关于[创建和使用Assistant API的详细最佳实践](https://help.aliyun.com/document_detail/2782117.html?spm=a2c4g.2712216.0.0.62166bf7Ng3xnx)。这份文档包含了具体的操作指南和代码示例,您可以参考以确保您的Assistant API开发过程顺利进行。

测试用例2

  • 输入:“模型训练?”

    • answer = call_rag_app(prompt='模型训练?')

  • 运行结果:

{'name': '获取训练模型情况', 'arguments': '{"user_id": "user_123456"}', 'output': None}
运行结果:
content:  当前用户是user_123456。模型训练是机器学习和深度学习中的关键环节,它涉及使用特定的数据集来调整模型的内部参数,以便模型能够根据输入数据做出准确的预测或决策。在阿里云百炼平台上,模型训练具体步骤如下:

1. **准备训练集数据**:
   - 首先,你需要准备符合要求的训练数据,这些数据应反映你希望模型学习的知识或技能。支持的文件格式包括jsonl、xls、xlsx等,且数据集至少包含40条内容。你可以在“训练数据”页面上传数据,如果需要,可下载提供的模板来格式化你的数据。

2. **选择训练方式**:
   - 百炼平台提供了不同的训练方式,包括全参训练、高效训练和RLHF训练。全参训练会更新所有模型参数,适合学习新能力和全局优化,但训练时间长;高效训练利用矩阵分解加速训练,适合局部优化;RLHF训练则通过奖励机制在强化学习框架下优化模型,适合特定性能提升。

3. **配置训练参数**:
   - 在“模型调优”模块,你可以选择“训练新模型”,然后配置训练参数,如选择基座模型、训练集、验证数据切分方式、混合训练比例(可选)以及超参数配置。混合训练允许你将自有的训练数据与平台的千问基础模型数据按一定比例混合,以增强模型的泛化能力。

4. **开始训练**:
   - 预览训练配置无误后,提交训练任务。训练任务会被排队执行,期间你可以在“模型管理列表”中查看训练状态和相关指标。请注意,训练过程会产生费用,费用计算基于训练集token数和循环次数,价格为0.1元/千tokens。

5. **监控与评估**:
   - 训练过程中,可以通过平台监控训练进度和性能指标。训练完成后,系统会通知你,你可以进一步测试和评估模型效果,决定是否部署应用。

6. **注意系统升级信息**:
   - 特别提醒,2024年3月15日至3月16日平台有计划的系统升级,期间训练任务可能会受到影响,建议避开此时间段安排训练任务。

确保在训练前已了解并同意相关的费用政策,并根据模型优化的需求,合理选择训练策略和参数,以达到最佳训练效果。
content:  user_123456,您在阿里云百炼平台上已有一个训练完成的模型,详情如下:

- **模型名称**: qwen-max-sft-v1
- **训练准确率**: 86.44%
- **训练时长**: 21小时40分钟

此模型已经过训练并可能准备好部署或进一步评估。请根据您的需求决定后续步骤。另外,请留意平台即将于2024年3月15日至3月16日进行的系统升级安排,以避免在此期间安排新的训练任务。

测试用例3

  • 输入:“我的apikey在百炼的账单?”

    • answer = call_rag_app(prompt='我的apikey在百炼的账单?')

  • 运行结果:

{'name': 'apikey查询', 'arguments': '{"user_id": "user_123456"}', 'output': None}

运行结果:
content:  当前用户是user_123456。在百炼平台上,API-KEY的使用与账单直接关联,其计费依据调用的模型及相应的费率进行计算<ref>[4][5]</ref>。当你通过API或SDK调用百炼平台的服务时,确保了解你的API-KEY的权限范围,这会影响到你能够访问的资源类型以及是否会产生费用<ref>[1]</ref>。具体到账单信息,虽然提供的文档没有直接展示账单详情,但提到不同的模型有不同的计费单价,例如`qwen-turbo`, `qwen-plus`有其特定的计费标准,并且存在免费额度以及基础限流规则来控制使用成本和资源分配<ref>[4][5]</ref>。若要查看或管理与API-KEY相关的费用和使用情况,通常需要访问阿里云的计费管理界面或百炼平台提供的相应板块进行查询<ref>[4][5]</ref>。
content:  您的API-KEY为`sk_user_123456`,截至目前,您已消费8.88元。 若要深入了解费用细节和管理您的API-KEY使用情况,请访问阿里云的计费管理界面或百炼平台的相关板块。