妙笔API最佳实践

本文提供妙笔写作链路 API的几个最佳实践,帮助您快速入门并开发您自己的业务应用。

前提条件

<dependency>
  <groupId>com.aliyun</groupId>
  <artifactId>alibabacloud-aimiaobi20230801</artifactId>
  <version>1.0.11</version>
</dependency>

1、实现直接生成文章

基于妙笔提供的API,本节通过直接生成文章场景来帮助您熟悉API的使用。

生成调用demo如下:

package com.aliyun.sdk.service.aimiaobi20230801;


import com.aliyun.auth.credentials.Credential;
import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
import com.aliyun.sdk.gateway.pop.Configuration;
import com.aliyun.sdk.gateway.pop.auth.SignatureVersion;
import com.aliyun.sdk.service.aimiaobi20230801.models.RunWritingRequest;
import com.aliyun.sdk.service.aimiaobi20230801.models.RunWritingResponseBody;

import com.google.gson.Gson;
import darabonba.core.ResponseIterable;
import darabonba.core.ResponseIterator;
import darabonba.core.client.ClientOverrideConfiguration;

import java.util.ArrayList;

import java.util.List;

/**
 * packageName com.dayouz.lightapp
 *
 * @author dayouz
 * @version JDK 8
 * @className runStyleWriting
 * @date 2024/8/13
 * @description 直接写作demo
 */
public class RunWritingTest {

    public static void main(String[] args) {
        StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder()
                .accessKeyId(Constant.accessKeyId)
                .accessKeySecret(Constant.accessKeySecret)
                .build());

        AsyncClient client = AsyncClient.builder()
                .region("cn-beijing")
                .credentialsProvider(provider)
                .serviceConfiguration(Configuration.create().setSignatureVersion(SignatureVersion.V3)).overrideConfiguration(ClientOverrideConfiguration.create().setProtocol("HTTPS").setEndpointOverride("aimiaobi.cn-beijing.aliyuncs.com"))
                .build();

        //写作时的文体、篇幅、输出语言等控制参数
        List<RunWritingRequest.Tags> tags = new ArrayList<>();
        //构建语言为中文
      tags.add(RunWritingRequest.Tags.builder().tag("language").keyword("zh-CN").build());
        //构建文章篇幅字数300字左右
        tags.add(RunWritingRequest.Tags.builder().tag("gcNumberSizeTag").keyword("300字").build());
        //构建生成文章数量为1篇
        tags.add(RunWritingRequest.Tags.builder().tag("gcNumber").keyword("1").build());
        //构建写作文体为新闻评论
        tags.add(RunWritingRequest.Tags.builder().tag("writingStyle").keyword("新闻评论").build());


        RunWritingRequest request = RunWritingRequest.builder()
                .workspaceId(Constant.workspaceId)
                .prompt("写一篇关于国足对战日本0:7 失败的报道")
                .writingConfig(RunWritingRequest.WritingConfig.builder()
                        //设置传媒领域的写作
                        .domain("media")
                        //设置为自动补充素材,通过互联网检索
                        .useSearch(true)
                        //设置写作时的文体、篇幅、输出语言等控制参数
                        .tags(tags).build())
                .build();


        ResponseIterable<RunWritingResponseBody> x = client.runWritingWithResponseIterable(request);

        ResponseIterator<RunWritingResponseBody> iterator = x.iterator();
        while (iterator.hasNext()) {
            System.out.println("----event----");
            RunWritingResponseBody event = iterator.next();
            System.out.println(new Gson().toJson(event));
        }

        System.out.println("ALL***********************");
        System.out.println("请求成功的请求头值:");
        System.out.println(x.getStatusCode());
        System.out.println(x.getHeaders());
    }
}

2、分步骤创作文章

package org.example.miaobi;

import com.alibaba.fastjson2.JSONObject;
import com.aliyun.auth.credentials.Credential;
import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
import com.aliyun.sdk.gateway.pop.Configuration;
import com.aliyun.sdk.gateway.pop.auth.SignatureVersion;
import com.aliyun.sdk.service.aimiaobi20230801.AsyncClient;
import com.aliyun.sdk.service.aimiaobi20230801.models.RunStepByStepWritingRequest;
import com.aliyun.sdk.service.aimiaobi20230801.models.RunStepByStepWritingResponseBody;
import darabonba.core.ResponseIterable;
import darabonba.core.client.ClientOverrideConfiguration;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
public class RunStepByStepWritingTest {
    public static AsyncClient asyncClient() {

        //accessKeyId
        String accessKeyId = System.getenv("accessKeyId");

        //accessKeySecret
        String accessKeySecret = System.getenv("accessKeySecret");

        //域名:aimiaobi.cn-hangzhou.aliyuncs.com
        String domain = System.getenv("domain");

        return AsyncClient.builder().credentialsProvider(StaticCredentialProvider.create(Credential.builder()
                .accessKeyId(accessKeyId).accessKeySecret(accessKeySecret).build())).serviceConfiguration(Configuration.create().setSignatureVersion(SignatureVersion.V3)).overrideConfiguration(ClientOverrideConfiguration.create().setProtocol("HTTPS")
                .setEndpointOverride(domain)).build();
    }


    @Test
    public void runStepByStepWriting() {
        AsyncClient asyncClient = asyncClient();
        String workspaceId = System.getenv("WorkspaceId");
        String prompt = "中美关系如何破局";

        //大纲生成
        OutlineGenerateResult result = runOutlineGenerateResult(asyncClient, workspaceId, prompt);

        //判断是否成功失败
        if (result.latestResponse == null || result.latestResponse.getHeader().getErrorCode() != null || result.latestResponse.getHeader().getErrorMessage() != null) {
            log.error("runStepByStepWriting|runOutlineGenerateResult error:{}", JSONObject.toJSONString(result.latestResponse));
            return;
        }
        log.info("latestResponse:{}", JSONObject.toJSONString(result.latestResponse));
        log.info("searchQuery:{}", result.searchQuery);
        log.info("articles:{}", result.articles != null ? result.articles.stream().map(x -> {
            return String.format("%s:%s", x.getTitle(), x.getUrl());
        }).collect(Collectors.joining(",")) : null);
        log.info("miniDoc:{}", JSONObject.toJSONString(result.miniDoc));
        log.info("outlines:{}", JSONObject.toJSONString(result.outlines));

        List<String> miniDoc = result.miniDoc;
        List<String> outlines = result.outlines;

        //生成摘编
        SummarizationResult summarizationResult = runSummarizationGenerate(outlines, asyncClient, workspaceId, miniDoc, prompt);
        //判断是否成功失败
        if (summarizationResult.latestResponse == null || summarizationResult.latestResponse.getHeader().getErrorCode() != null || summarizationResult.latestResponse.getHeader().getErrorMessage() != null) {
            log.error("runStepByStepWriting|runSummarizationGenerate|error:{}", JSONObject.toJSONString(summarizationResult.latestResponse));
            return;
        }


        List<RunStepByStepWritingRequest.Outlines> outlineList = outlines.stream().map(x -> {
            return RunStepByStepWritingRequest.Outlines.builder().outline(x).build();
        }).collect(Collectors.toList());


        //生成文章
        RunWritingResult runWritingResult = runWriting(asyncClient, workspaceId, prompt, miniDoc, outlineList, summarizationResult.cachedSummarization);

        //判断是否成功失败
        if (runWritingResult.latestResponse == null || runWritingResult.latestResponse.getHeader().getErrorCode() != null || runWritingResult.latestResponse.getHeader().getErrorMessage() != null) {
            log.error("runStepByStepWriting|runSummarizationGenerate|error:{}", JSONObject.toJSONString(runWritingResult.latestResponse));
            return;
        }
        RunStepByStepWritingResponseBody.Output output = runWritingResult.latestResponse.getPayload().getOutput();

        //最终输出的正文
        String text = output.getText();
        log.info("最终输出的正文:{}", text);
    }

    public static class RunWritingResult {
        public final RunStepByStepWritingResponseBody latestResponse;
        public RunWritingResult(RunStepByStepWritingResponseBody latestResponse) {
            this.latestResponse = latestResponse;
        }
    }

    private static RunWritingResult runWriting(AsyncClient asyncClient, String workspaceId, String prompt, List<String> miniDoc, List<RunStepByStepWritingRequest.Outlines> outlineList, List<String> cachedSummarization) {
        ResponseIterable<RunStepByStepWritingResponseBody> iterable = asyncClient.runStepByStepWritingWithResponseIterable(
                RunStepByStepWritingRequest.builder()
                        .workspaceId(workspaceId).prompt(prompt)
                        .referenceData(
                                RunStepByStepWritingRequest.ReferenceData.builder()
                                        .miniDoc(miniDoc)
                                        .outlines(outlineList)
                                        .summarization(cachedSummarization)
                                        .build()
                        )
                        .writingConfig(
                                RunStepByStepWritingRequest.WritingConfig.builder()
                                        .step("Writing").build()
                        )
                        .build()
        );
        RunStepByStepWritingResponseBody latestResponse = null;

        //写作输出
        for (RunStepByStepWritingResponseBody item : iterable) {
            log.info("item:{}", JSONObject.toJSONString(item));
            latestResponse = item;
        }

        return new RunWritingResult(latestResponse);
    }


    public static class SummarizationResult {
        public final List<String> cachedSummarization;
        public final RunStepByStepWritingResponseBody latestResponse;

        public SummarizationResult(List<String> cachedSummarization, RunStepByStepWritingResponseBody latestResponse) {
            this.cachedSummarization = cachedSummarization;
            this.latestResponse = latestResponse;
        }
    }

    private static SummarizationResult runSummarizationGenerate(List<String> outlines,
                                                                AsyncClient asyncClient,
                                                                String workspaceId,
                                                                List<String> miniDoc,
                                                                String prompt) {
        List<RunStepByStepWritingRequest.Outlines> outlineList = outlines.stream().map(x -> {
            return RunStepByStepWritingRequest.Outlines.builder().outline(x).build();
        }).collect(Collectors.toList());

        ResponseIterable<RunStepByStepWritingResponseBody> iterable = asyncClient.runStepByStepWritingWithResponseIterable(
                RunStepByStepWritingRequest.builder()
                        .workspaceId(workspaceId).prompt(prompt)
                        .referenceData(
                                RunStepByStepWritingRequest.ReferenceData.builder().miniDoc(miniDoc).outlines(outlineList).build()
                        )
                        .writingConfig(
                                RunStepByStepWritingRequest.WritingConfig.builder()
                                        .step("MiniDocSummary").build()
                        )
                        .build()
        );

        List<String> cachedSummarization = null;

        RunStepByStepWritingResponseBody latestResponse = null;

        for (RunStepByStepWritingResponseBody responseBody : iterable) {
            latestResponse = responseBody;

            RunStepByStepWritingResponseBody.Output output = responseBody.getPayload().getOutput();
            if (output != null && output.getExtraOutput() != null && output.getExtraOutput().getSummarization() != null) {
                cachedSummarization = output.getExtraOutput().getSummarization();
            }
        }

        return new SummarizationResult(cachedSummarization, latestResponse);
    }


    private static OutlineGenerateResult runOutlineGenerateResult(AsyncClient asyncClient, String workspaceId, String prompt) {
        //生成大纲
        ResponseIterable<RunStepByStepWritingResponseBody> iterable = asyncClient.runStepByStepWritingWithResponseIterable(
                RunStepByStepWritingRequest.builder()
                        .workspaceId(workspaceId).prompt(prompt)
                        .writingConfig(
                                RunStepByStepWritingRequest.WritingConfig.builder()
                                        .step("OutlineGenerate").build()
                        )
                        .build()
        );

        //检索的Query
        String searchQuery = null;
        //检索的文章
        List<RunStepByStepWritingResponseBody.Articles> articles = null;

        //排序好的文章切片
        List<String> miniDoc = null;

        //生成的大纲
        List<String> outlines = null;


        RunStepByStepWritingResponseBody latestResponse = null;
        for (RunStepByStepWritingResponseBody response : iterable) {
            latestResponse = response;
            if (articles == null) {
                articles = response.getPayload().getOutput().getArticles();
            }

            if (miniDoc == null) {
                miniDoc = response.getPayload().getOutput().getMiniDoc();
            }

            //检索后的query
            if (searchQuery == null) {
                searchQuery = response.getPayload().getOutput().getSearchQuery();
            }


            //大纲生成结束
            if ("task-outline-end".equals(response.getHeader().getEvent())) {
                outlines = Arrays.asList(response.getPayload().getOutput().getText().split("\n"));
            }
        }

        return new OutlineGenerateResult(searchQuery, articles, miniDoc, outlines, latestResponse);
    }

    private static class OutlineGenerateResult {
        public final String searchQuery;
        public final List<RunStepByStepWritingResponseBody.Articles> articles;
        public final List<String> miniDoc;
        public final List<String> outlines;
        public final RunStepByStepWritingResponseBody latestResponse;

        public OutlineGenerateResult(String searchQuery, List<RunStepByStepWritingResponseBody.Articles> articles, List<String> miniDoc, List<String> outlines, RunStepByStepWritingResponseBody latestResponse) {
            this.searchQuery = searchQuery;
            this.articles = articles;
            this.miniDoc = miniDoc;
            this.outlines = outlines;
            this.latestResponse = latestResponse;
        }
    }
}

3、AI工具箱

AI工具箱包括内容续写、摘要生成、标题生成、内容缩写、内容扩写、关键词抽取等功能,最新实时能力可参考妙笔写作页面的AI工具箱。本节通过实现摘要生成场景来帮助您熟悉API的使用。

生成调用demo如下:

package com.aliyun.sdk.service.aimiaobi20230801;


import com.aliyun.auth.credentials.Credential;
import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
import com.aliyun.sdk.gateway.pop.Configuration;
import com.aliyun.sdk.gateway.pop.auth.SignatureVersion;
import com.aliyun.sdk.service.aimiaobi20230801.models.RunSummaryGenerateRequest;
import com.aliyun.sdk.service.aimiaobi20230801.models.RunSummaryGenerateResponseBody;
import com.aliyun.sdk.service.aimiaobi20230801.models.RunWritingRequest;
import com.aliyun.sdk.service.aimiaobi20230801.models.RunWritingResponseBody;
import com.google.gson.Gson;
import darabonba.core.ResponseIterable;
import darabonba.core.ResponseIterator;
import darabonba.core.client.ClientOverrideConfiguration;

import java.util.ArrayList;
import java.util.List;

/**
 * packageName com.dayouz.lightapp
 *
 * @author dayouz
 * @version JDK 8
 * @className runStyleWriting
 * @date 2024/8/13
 * @description 摘要生成Demo
 */
public class RunSummaryGenerateTest {

    public static void main(String[] args) {
        StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder()
                .accessKeyId(Constant.accessKeyId)
                .accessKeySecret(Constant.accessKeySecret)
                .build());

        AsyncClient client = AsyncClient.builder()
                .region("cn-beijing")
                .credentialsProvider(provider)
                .serviceConfiguration(Configuration.create().setSignatureVersion(SignatureVersion.V3)).overrideConfiguration(ClientOverrideConfiguration.create().setProtocol("HTTPS").setEndpointOverride("aimiaobi.cn-beijing.aliyuncs.com"))
                .build();

        //写作时的文体、篇幅、输出语言等控制参数
        List<RunWritingRequest.Tags> tags = new ArrayList<>();
        //构建语言
        tags.add(RunWritingRequest.Tags.builder().tag("language").keyword("zh-CN").build());
        //构建文章篇幅
        tags.add(RunWritingRequest.Tags.builder().tag("gcNumberSizeTag").keyword("300字").build());
        //构建生成文章数量
        tags.add(RunWritingRequest.Tags.builder().tag("gcNumber").keyword("2").build());
        //构建写作文体
        tags.add(RunWritingRequest.Tags.builder().tag("writingStyle").keyword("新闻评论").build());


        RunSummaryGenerateRequest request = RunSummaryGenerateRequest.builder()
                .workspaceId(Constant.workspaceId)
                .prompt("请为上述内容生成一段摘要,字数在100~200字以内。")
                .content("云服务器ECS(Elastic Compute Service)是阿里云提供的性能卓越、稳定可靠、弹性扩展的IaaS(Infrastructure as a Service)级别云计算服务。云服务器ECS免去了您采购IT硬件的前期准备,让您像使用水、电、天然气等公共资源一样便捷、高效地使用服务器,实现计算资源的即开即用和弹性伸缩。阿里云ECS持续提供创新型服务器,解决多种业务需求,助力您的业务发展。")
                .build();


        ResponseIterable<RunSummaryGenerateResponseBody> x = client.runSummaryGenerateWithResponseIterable(request);

        ResponseIterator<RunSummaryGenerateResponseBody> iterator = x.iterator();
        while (iterator.hasNext()) {
            System.out.println("----event----");
            RunSummaryGenerateResponseBody event = iterator.next();
            System.out.println(new Gson().toJson(event));
        }

        System.out.println("ALL***********************");
        System.out.println("请求成功的请求头值:");
        System.out.println(x.getStatusCode());
        System.out.println(x.getHeaders());
    }
}