自定义Prompt

本文主要介绍自定义Prompt(提示词)的实现方式。自定义prompt是指由客户自主定义大模型提示词,引导大模型完成客户定义的各类任务。若通义听悟提供的标准AI模型能力无法满足您的业务需求,则可以通过本功能更加灵活地使用大模型。例如:生成不同颗粒度的总结;提取业务特定的关键信息;定义业务标准并由大模型评判业务等。(注:Prompt的作用主要是给AI模型提示输入信息的上下文,促使模型更好地理解输入意图,并作出相应的响应。即给AI模型提供一个“提示”或“指引”,帮助它更好地理解和完成任务。)

请求参数

参数名

类型

说明

CustomPromptEnabled

boolean

默认为false。

CustomPrompt

object

自定义Prompt控制参数对象。

CustomPrompt.Contents

list[]

自定义Prompt的参数列表。单次提交最大长度为3

CustomPrompt.Contents[i].Name

string

Prompt的自定义名称,用于匹配输出结果。

CustomPrompt.Contents[i].Model

string

指定Prompt的模型,目前可选择tingwu-turbotingwu-plusqwen-max。如果不填写该参数,会默认设置为tingwu-turbo

CustomPrompt.Contents[i].Prompt

string

Prompt的自定义内容,需要包含{Transcription}标签,{Transcription}会被自动替换为语音转写结果来作为模型输入。

CustomPrompt.Contents[i].TransType

string

指定{Transcription}标签格式,目前可选chatdefault

chat: 转写结果包含发言人信息。

default: 转写结果为纯文本格式。

具体示例参考下文的标签参数

不同模型的token输入限制:

模型名

输入token限制

tingwu-turbo

28k

tingwu-plus

125k

qwen-max

28k

如果输入音频的转写结果超过了token限制,会发生截断,仅使用token限制内的文本作为大模型输入。可以根据返回结果中的CustomPrompt.Truncated参数来判断是否发生了截断。

示例设置

{
    "Input": {
      ...
    },
    "Parameters": {
        "CustomPromptEnabled": true,
        "CustomPrompt": {
            "Contents": [
                {
                    "Name": "split-summary-demo",
                    "Prompt": "请帮我将下面的对话进行总结,根据发言人来总结:\n {Transcription}",
                    "Model": "tingwu-turbo",
                    "TransType": "chat"
                },
                {
                    "Name": "inspection-demo",
                    "Prompt": "请帮我检查对话内容是否存在不文明用语,如果有请回复'有',如果没有请回复'无',对话内容如下:\n {Transcription}",
                    "Model": "tingwu-turbo",
                    "TransType": "default"
                }
            ]
        }
    }
}

标签参数

当TransType不同时,Prompt中的{Transcription}会被替换成不同格式的文本。以下面的转写结果为例,用户传入音频并开启了发言人分离,其中第一个说话人:北京天气怎么样,第二个说话人:上海天气怎么样。

{
    "TaskId":"10683ca4ad3f4f06bdf6e9dc*********",
    "Transcription":{
        "Paragraphs":[
            {
                "ParagraphId":"16987422100275*******",
                "SpeakerId":"1",
                "Words":[
                    {
                        "Id":10,
                        "SentenceId":1,
                        "Start":4970,
                        "End":5560,
                        "Text":"北京天气怎么样?"
                    }
                ]
            },
            {
                "ParagraphId":"16987422100276*******",
                "SpeakerId":"2",
                "Words":[
                    {
                        "Id":20,
                        "SentenceId":2,
                        "Start":4970,
                        "End":5560,
                        "Text":"上海天气怎么样?"
                    },
                ]
            }
        ]
    }
}

在prompt中,{Transcription}会被替换成不同格式的文本,如下所示。

标签名

格式类型

替换结果

{Transcription}

default

北京天气怎么样?上海天气怎么样?

chat

发言人1:北京天气怎么样?\n发言人2:上海天气怎么样\n

代码示例

#!/usr/bin/env python
#coding=utf-8

import os
import json
import datetime
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.request import CommonRequest
from aliyunsdkcore.auth.credentials import AccessKeyCredential

def create_common_request(domain, version, protocolType, method, uri):
    request = CommonRequest()
    request.set_accept_format('json')
    request.set_domain(domain)
    request.set_version(version)
    request.set_protocol_type(protocolType)
    request.set_method(method)
    request.set_uri_pattern(uri)
    request.add_header('Content-Type', 'application/json')
    return request

def init_parameters():
    root = dict()
    root['AppKey'] = '输入您在听悟管控台创建的Appkey'

    # 基本请求参数
    input = dict()
    input['SourceLanguage'] = 'cn'
    input['TaskKey'] = 'task' + datetime.datetime.now().strftime('%Y%m%d%H%M%S')
    input['FileUrl'] = '输入待测试的音频url链接'
    root['Input'] = input

    # AI相关参数,按需设置即可
    parameters = dict()
    # 摘要控制相关,包括: 全文摘要、发言人总结摘要、问答摘要(问答回顾)
    parameters['CustomPromptEnabled'] = True
    customPrompt = dict()
    customPrompt['Contents'] = [
        {
            "Name": "split-summary-demo",
            "Prompt": "请帮我将下面的对话进行总结,根据发言人来总结:\n {Transcription}",
            "Model": "tingwu-turbo",
            "TransType": "chat"
        },
        {
            "Name": "inspection-demo",
            "Prompt": "请帮我检查对话内容是否存在不文明用语,如果有请回复'有',如果没有请回复'无',对话内容如下:\n {Transcription}",
            "Model": "tingwu-turbo",
            "TransType": "default"
        }
    ]
    parameters['CustomPrompt'] = customPrompt
    root['Parameters'] = parameters
    return root

body = init_parameters()
print(body)

# TODO  请通过环境变量设置您的 AccessKeyId 和 AccessKeySecret
credentials = AccessKeyCredential(os.environ['ALIBABA_CLOUD_ACCESS_KEY_ID'], os.environ['ALIBABA_CLOUD_ACCESS_KEY_SECRET'])
client = AcsClient(region_id='cn-beijing', credential=credentials)

request = create_common_request('tingwu.cn-beijing.aliyuncs.com', '2023-09-30', 'https', 'PUT', '/openapi/tingwu/v2/tasks')
request.add_query_param('type', 'offline')

request.set_content(json.dumps(body).encode('utf-8'))
response = client.do_action_with_exception(request)
print("response: \n" + json.dumps(json.loads(response), indent=4, ensure_ascii=False))
package com.alibaba.tingwu.client.demo.aitest;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.FormatType;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.profile.DefaultProfile;
import org.junit.Test;

/**
 * @author tingwu2023
 */
public class CustomPromptTest {

    @Test
    public void testCustomPrompt() throws ClientException {
        CommonRequest request = createCommonRequest("tingwu.cn-beijing.aliyuncs.com", "2023-09-30", ProtocolType.HTTPS, MethodType.PUT, "/openapi/tingwu/v2/tasks");
        request.putQueryParameter("type", "offline");

        JSONObject root = new JSONObject();
        root.put("AppKey", "输入您在听悟管控台创建的Appkey");

        JSONObject input = new JSONObject();
        input.fluentPut("FileUrl", "输入待测试的音频url链接")
                .fluentPut("SourceLanguage", "cn")
                .fluentPut("TaskKey", "task" + System.currentTimeMillis());
        root.put("Input", input);

        JSONObject parameters = new JSONObject();
        parameters.put("CustomPromptEnabled", true);
        JSONObject customPrompt = new JSONObject();
        JSONArray contents = new JSONArray()
                .fluentAdd(new JSONObject()
                        .fluentPut("Name", "split-summary-demo")
                        .fluentPut("Prompt", "请帮我将下面的对话进行总结,根据发言人来总结:\n {Transcription}")
                        .fluentPut("Model", "tingwu-turbo")
                        .fluentPut("TransType", "chat"))
                .fluentAdd(new JSONObject()
                        .fluentPut("Name", "inspection-demo")
                        .fluentPut("Prompt", "请帮我检查对话内容是否存在不文明用语,如果有请回复'有',如果没有请回复'无',对话内容如下:\n {Transcription}")
                        .fluentPut("Model", "tingwu-turbo")
                        .fluentPut("TransType", "default"));
        customPrompt.put("Contents", contents);
        parameters.put("CustomPrompt", customPrompt);
        root.put("Parameters", parameters);
        System.out.println(root.toJSONString());
        request.setHttpContent(root.toJSONString().getBytes(), "utf-8", FormatType.JSON);

        // TODO 请通过环境变量设置您的AccessKeyId、AccessKeySecret
        DefaultProfile profile = DefaultProfile.getProfile("cn-beijing", System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"), System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
        IAcsClient client = new DefaultAcsClient(profile);
        CommonResponse response = client.getCommonResponse(request);
        System.out.println(response.getData());
    }
    public static CommonRequest createCommonRequest(String domain, String version, ProtocolType protocolType, MethodType method, String uri) {
        // 创建API请求并设置参数
        CommonRequest request = new CommonRequest();
        request.setSysDomain(domain);
        request.setSysVersion(version);
        request.setSysProtocol(protocolType);
        request.setSysMethod(method);
        request.setSysUriPattern(uri);
        request.setHttpContentType(FormatType.JSON);
        return request;
    }
}

示例输出

{
    "Code":"0",
    "Data":{
        "TaskId":"5a7343ad75e64z3da121ce65********",
        "TaskStatus":"COMPLETED",
        "Result":{
            "Transcription":"http://speech-swap-hangzhou.oss-cn-hangzhou.aliyuncs.com/tingwu/output/1503864348104017/5a7343ad75e6493da121ce653f9389eb/5a7343ad75e6493da121ce653f9389eb_Transcription_20231029224625.json?Expires=1698677343&OSSAccessKeyId=LTAI4G*********j6oX8nt5S&Signature=Kliw%2Fp2xCKHpKR06********Y8%3D",
            "CustomPrompt":"http://speech-swap-hangzhou.oss-cn-hangzhou.aliyuncs.com/tingwu/output/1503864348104017/5a7343ad75e6493da121ce653f9389eb/5a7343ad75e6493da121ce653f9389eb_CustomPrompt_20231029224656.json?Expires=1698677343&OSSAccessKeyId=LTAI4G*********j6oX8nt5S&Signature=rY5v4CbGjKnh0Nu*********Xhs%3D"
        }
    },
    "Message":"success",
    "RequestId":"4EEBD53F-BCC9-1A0E-B17E-C459********"
}

其中CustomPrompt字段对应的即为摘要结果的HTTP下载链接。

协议解析

上述输出中的大模型摘要结果url中的内容为JSON格式的报文,示例如下。

{
  "TaskId": "c8b8f8cac1134675a8722ae3********",
  "CustomPrompt": [
    {
      "Name": "split-summary-demo",
      "Result": "这段对话主要围绕着阿里巴巴达摩院的语音技术和相关的人工智能研究成果展开。发言人1(志杰)来自达摩院,负责介绍达摩院的研究成果和未来展望;而发言人2则是来自西瓜视频的科普视频创作者,主要通过提问和观察来了解并分享达摩院的技术。\n\n发言人1首先提到,虽然预测未来科技存在很大风险,但他们仍然坚持这样做,旨在向公众传达对未来科技的看法与态度。他随后介绍了达摩院在全球的分布,并重点提到达摩院位于杭州的总部及研究院的重要性和规模。此外,志杰还讨论了达摩院发布的关于未来十大科技的报告,表达了他们对人工智能前沿技术的研究兴趣,尤其是语音技术。\n\n在对语音技术的讨论中,志杰提出了在多种环境中(如嘈杂环境、多人讨论会议等)语音识别面临的挑战,并探讨了目前的技术解决方案,例如通过机器学习将问题分类后转交给相应的人工服务。他还谈到了一个长期目标-实现AI参与会议,以提高会议效率和决策质量。\n\n发言人2则从外部观察者的角度出发,通过实际体验来感受和展示达摩院的语音技术支持下的各种应用场景,比如语音控制贩卖机、智能电视机等,并通过直观的例子说明语音技术在现实生活中的应用潜力和挑战。\n\n最后,两位发言人共同强调了让语音交互“无处不在”的目标,并探讨了基于此技术,如何更好地服务于人类社会,以及企业在持续发展中如何坚持以用户需求为中心的原则。\n\n总之,这次对话深入探讨了达摩院在语音技术及其他人工智能领域的研究进展和未来规划,同时也反映了这些技术在实际生活中的应用现状和潜在影响。",
      "Truncated": false
    },
    {
      "Name": "inspection-demo",
      "Result": "无",
      "Truncated": false
    }
  ]
}

具体字段定义如下。

参数名

类型

说明

TaskId

string

创建任务时生成的TaskId。

CustomPrompt

list[]

自定义Prompt结果列表。

CustomPrompt.Name

string

与入参结构中的CustomPrompt.Contents[i].Name对应。

CustomPrompt.Result

string

大模型返回结果。

CustomPrompt.Truncated

boolean

是否发生了截断