本文提供妙笔写作链路 API的几个最佳实践,帮助您快速入门并开发您自己的业务应用。
前提条件
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>alibabacloud-aimiaobi20230801</artifactId>
<version>1.0.11</version>
</dependency>1、实现直接生成文章
基于妙笔提供的API,本节通过直接生成文章场景来帮助您熟悉API的使用。
生成调用demo如下:
Java:
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.aliyun.sdk.service.aimiaobi20230801.AsyncClient;
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<>();
//构建文章篇幅字数300字左右 ,可根据实际需要填写字数,可选 800字,1000字,2000字
tags.add(RunWritingRequest.Tags.builder().tag("gcNumberSizeTag").keyword("300字").build());
//构建写作文体为新闻评论
//可以通过接口获取系统内置的文体类型 https://help.aliyun.com/zh/model-studio/api-aimiaobi-2023-08-01-listbuildconfigs?spm=a2c4g.11186623.help-menu-2400256.d_1_6_3_2_0_3_3_13.79502533pwFhax
//注意需要获取 "Tag": "writingStyle" 的keyword ,keyword 赋值为 Key 字段
tags.add(RunWritingRequest.Tags.builder().tag("writingStyle").keyword("新闻评论").build());
RunWritingRequest request = RunWritingRequest.builder()
.workspaceId(InitProvider.workspaceId)
.prompt("写一篇关于国足对战日本0:7 失败的报道")
.writingConfig(RunWritingRequest.WritingConfig.builder()
//设置传媒领域的写作 可选 media:传媒 government:政务 market:营销 custom 自定义文体
.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());
}
}Python:
import os
from alibabacloud_tea_openapi_sse.client import Client as OpenApiClient
from alibabacloud_tea_openapi_sse import models as open_api_models
from alibabacloud_tea_util_sse import models as open_api_util_models
import asyncio
import json
import dotenv
dotenv.load_dotenv()
endpoint = 'aimiaobi.cn-beijing.aliyuncs.com'
# 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考。
# 建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378659.html。
access_key_id = os.environ.get('accessKeyId')
access_key_secret = os.environ.get('accessKeySecret')
workspace_id = os.environ.get('WorkspaceId')
# 详情接口文档请参考:https://api.aliyun.com/api/AiMiaoBi/2023-08-01/RunWritingV2?spm=a2c4g.11186623.0.0.201c715eKrroz5&RegionId=cn-beijing
def _create_client() -> OpenApiClient:
config = open_api_models.Config(
access_key_id=access_key_id,
access_key_secret=access_key_secret,
endpoint=endpoint
)
return OpenApiClient(config)
def create_sse_api_info(action) -> open_api_models.Params:
"""
API 相关
@param path: params
@return: OpenApi.Params
"""
params = open_api_models.Params(
# 接口名称
action=action,
# 接口版本
version='2023-08-01',
# 接口协议
protocol='HTTPS',
# 接口 HTTP 方法
method='POST',
auth_type='AK',
style='RPC',
pathname="",
# 接口请求体内容格式,
req_body_type='formData',
# 接口响应体内容格式,
body_type='sse'
)
return params
class SseClient:
def __init__(self) -> None:
# 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考。
# 建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378659.html。
self.endpoint = endpoint
self._runtime = open_api_util_models.RuntimeOptions(read_timeout=1000 * 100)
self._client = _create_client()
async def run_writing(self, body):
request = open_api_models.OpenApiRequest(body=body)
return self._client.call_sse_api_async(params=create_sse_api_info("RunWritingV2"), request=request,
runtime=self._runtime)
async def test_run_writing():
client = SseClient()
writing_params = {
"WorkspaceId": workspace_id,
"Prompt": "写一篇关于中美关系的新闻评论"
}
async for item in await client.run_writing(writing_params):
try:
data = json.loads(item.get('event').data)
print(data)
except json.JSONDecodeError:
print('------json.JSONDecodeError--------')
if __name__ == '__main__':
asyncio.run(test_run_writing())
2、实现自定义文体生成文章
基于妙笔提供的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.aliyun.sdk.service.aimiaobi20230801.AsyncClient;
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<>();
//构建文章篇幅字数300字左右 ,可根据实际需要填写字数,可选 800字,1000字,2000字
tags.add(RunWritingRequest.Tags.builder().tag("gcNumberSizeTag").keyword("300字").build());
//构建写作文体为已经创建好的自定义文体
//可以通过接口获取系统内置的文体类型 https://help.aliyun.com/zh/model-studio/api-aimiaobi-2023-08-01-listbuildconfigs?spm=a2c4g.11186623.help-menu-2400256.d_1_6_3_2_0_3_3_13.79502533pwFhax
tags.add(RunWritingRequest.Tags.builder().tag("writingStyle").keyword("111111(通过上述接口返回的自定义文体的ID)").build());
RunWritingRequest request = RunWritingRequest.builder()
.workspaceId(InitProvider.workspaceId)
.prompt("写一篇关于国足对战日本0:7 失败的报道")
.writingConfig(RunWritingRequest.WritingConfig.builder()
//设置自定义文体的写作 可选 media:传媒 government:政务 market:营销 custom 自定义文体
.domain("custom")
//设置为自动补充素材,通过互联网检索
.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());
}
}3、分步骤创作文章
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.*;
import darabonba.core.ResponseIterable;
import darabonba.core.client.ClientOverrideConfiguration;
import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 妙笔AI分步写作示例程序(无需JUnit)
* 功能:生成大纲 → 摘编 → 正文
*
* 运行前请设置以下环境变量:
* accessKeyId
* accessKeySecret
* domain = aimiaobi.cn-hangzhou.aliyuncs.com
* WorkspaceId
*/
@Slf4j
public class RunStepByStepWritingMain {
public static void main(String[] args) {
try {
// 初始化客户端
AsyncClient asyncClient = createAsyncClient();
// 从环境变量获取参数
String workspaceId = System.getenv("WorkspaceId");
String prompt = "中美关系如何破局"; // 可替换为命令行参数
if (workspaceId == null || workspaceId.isEmpty()) {
log.error("环境变量 'WorkspaceId' 未设置!");
return;
}
log.info("开始执行分步写作,主题:{}", prompt);
// 1. 生成大纲
OutlineGenerateResult outlineResult = runOutlineGenerateResult(asyncClient, workspaceId, prompt);
if (!isSuccess(outlineResult.latestResponse)) {
log.error("大纲生成失败: {}", JSONObject.toJSONString(outlineResult.latestResponse));
return;
}
log.info("大纲生成成功");
log.info("检索Query: {}", outlineResult.searchQuery);
log.info("检索文章: {}", formatArticles(outlineResult.articles));
log.info("MiniDoc: {}", outlineResult.miniDoc);
log.info("大纲: {}", outlineResult.outlines);
// 2. 生成摘编
SummarizationResult summarizationResult = runSummarizationGenerate(
outlineResult.outlines, asyncClient, workspaceId,
outlineResult.miniDoc, prompt);
if (!isSuccess(summarizationResult.latestResponse)) {
log.error("摘编生成失败: {}", JSONObject.toJSONString(summarizationResult.latestResponse));
return;
}
log.info("摘编生成成功");
log.info("Cached Summarization: {}", summarizationResult.cachedSummarization);
// 3. 生成正文
RunWritingResult writingResult = runWriting(
asyncClient, workspaceId, prompt,
outlineResult.miniDoc,
convertToOutlineRequests(outlineResult.outlines),
summarizationResult.cachedSummarization);
if (!isSuccess(writingResult.latestResponse)) {
log.error("正文生成失败: {}", JSONObject.toJSONString(writingResult.latestResponse));
return;
}
String finalText = writingResult.latestResponse.getPayload().getOutput().getText();
log.info("最终生成的正文:\n{}", finalText);
} catch (Exception e) {
log.error("程序执行异常", e);
}
}
/**
* 创建异步客户端
*/
private static AsyncClient createAsyncClient() {
String accessKeyId = System.getenv("accessKeyId");
String accessKeySecret = System.getenv("accessKeySecret");
String domain = System.getenv("domain");
if (accessKeyId == null || accessKeySecret == null) {
throw new IllegalArgumentException("环境变量 accessKeyId 或 accessKeySecret 未设置!");
}
if (domain == null) {
domain = "aimiaobi.cn-hangzhou.aliyuncs.com"; // 默认值
}
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();
}
/**
* 判断响应是否成功
*/
private static boolean isSuccess(RunStepByStepWritingResponseBody response) {
if (response == null) return false;
String errorCode = response.getHeader().getErrorCode();
return errorCode == null || errorCode.isEmpty();
}
/**
* 格式化文章列表输出
*/
private static String formatArticles(List<RunStepByStepWritingResponseBody.Articles> articles) {
if (articles == null) return "null";
return articles.stream()
.map(a -> a.getTitle() + " -> " + a.getUrl())
.collect(Collectors.joining("; "));
}
/**
* 转换字符串列表为请求对象列表
*/
private static List<RunStepByStepWritingRequest.Outlines> convertToOutlineRequests(List<String> outlines) {
return outlines.stream()
.map(o -> RunStepByStepWritingRequest.Outlines.builder().outline(o).build())
.collect(Collectors.toList());
}
// ==================== 核心方法实现 ====================
public 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;
}
}
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()
);
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;
RunStepByStepWritingResponseBody.Output output = response.getPayload().getOutput();
if (articles == null && output != null && output.getArticles() != null) {
articles = output.getArticles();
}
if (miniDoc == null && output != null && output.getMiniDoc() != null) {
miniDoc = output.getMiniDoc();
}
if (searchQuery == null && output != null && output.getSearchQuery() != null) {
searchQuery = output.getSearchQuery();
}
// 大纲结束事件
if ("task-outline-end".equals(response.getHeader().getEvent())) {
String text = output.getText();
if (text != null && !text.trim().isEmpty()) {
outlines = Arrays.asList(text.trim().split("\n"));
}
}
}
return new OutlineGenerateResult(searchQuery, articles, miniDoc, outlines, 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 = convertToOutlineRequests(outlines);
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 response : iterable) {
latestResponse = response;
RunStepByStepWritingResponseBody.Output output = response.getPayload().getOutput();
if (output != null && output.getExtraOutput() != null) {
List<String> sum = output.getExtraOutput().getSummarization();
if (sum != null && !sum.isEmpty()) {
cachedSummarization = sum;
}
}
}
return new SummarizationResult(cachedSummarization, latestResponse);
}
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("流式响应: {}", JSONObject.toJSONString(item));
latestResponse = item;
}
return new RunWritingResult(latestResponse);
}
}
4、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 com.aliyun.sdk.service.aimiaobi20230801.AsyncClient;
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();
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());
}
}该文章对您有帮助吗?