Assistant API 为您提供了一套 Assistant 的开发工具,帮助您方便地管理对话消息,以及调用工具。本文以从零开始构建绘画智能助手为例,帮助您快速掌握 Assistant API 的基础编码方法。
典型流程
构建智能体应用(Assistant)的典型流程如下:
创建 Assistant:创建智能体时,您需要选择模型、输入指令并添加实用工具,如代码解释器、夸克搜索和函数调用。
创建 Thread:当用户发起对话时,创建一个会话线程来追踪连续的对话历史。
发送 Message 到 Thread:随着用户提出问题,将消息逐条加入会话线程。
发起 Run:在会话线程上运行智能体,它会解析消息,调用相应的工具或服务,生成响应并返回给您。
示例场景
文本生成模型自身不具备生成图像的功能,一般需要通过特定的文生图模型,可以将文本转化为图像。借助 Assistant API 创建的智能体应用,能够自动优化用户提供的描述词,通过互联网搜索工具丰富细节,最终调用文生图工具生成高质量图像。例如,为了生成一幅栩栩如生的宠物猫图像,您只需提供基础描述,绘图助手将自动完善提示词,并直接输入至文生图工具中,高效完成图像绘制任务。
操作步骤
以下是在非流式输出模式下,以 Python 为例的详细流程指引。本文末尾还介绍了流式和非流式输出的 Python 及 Java SDK 完整代码。
第一步:准备开发环境
|
|
第二步:创建 Assistant导入 Dashscope SDK 后,您需使用 Assistant 类的 create 方法创建 Assistant 智能体。这一过程涉及以下关键参数的设定:
具体到我们的案例,目标是构建一个专注于绘画的 Assistant。基于文生图工具对语言理解能力的较高要求,我们选用了通义千问-Max作为文本推理模型,以此强化 Assistant 的语义理解和文本生成能力。 智能体的配置细节,包括其名称、功能描述及指令,均在随附的代码片段中有明确展示。 为了丰富智能体的功能性和实用性,我们集成了两个官方预置插件:
|
|
第三步:创建 ThreadThread(线程)是 Assistant API 中的一个关键概念,它代表了一个持续的对话上下文。 Thread 允许您在用户启动新对话时创建一个会话管理线程。Assistant 可以通过 Thread 理解整个对话的上下文,从而提供更加连贯和相关的回应。 建议您:
在绘画助手的场景中,Thread 可以跟踪用户的初始请求、Assistant 的初步建议、用户的反馈,以及最终的绘画结果,形成一个完整的创作过程。这确保了整个创作过程的连贯性和可追溯性。 |
|
第四步:添加 Message 到 Thread您输入的内容将通过 Message 对象传递。 Assistant API支持向单一 Thread 发送一个或多个消息。创建 Message 时,您需要考虑以下参数:
尽管 Thread 可接收的 Token 数量无硬性限制,但实际传递给大模型的 Token 数量需符合该模型的最大输入长度限制,具体参照各通义千问系列模型的官方文档中关于上下文长度的说明。 在我们的场景中,您将通过 Message 在 Thread 中发出第一条消息:“请帮我画一只布偶猫的图片”。您需要创建一个 Message 类,详细参数设置均在随附的代码片段中。 |
|
第五步:创建 Run 并执行用户将消息分配至特定 Thread 后,可以通过启动一个运行(Run)来激活预设的助手(Assistant)。该助手会以线程内的所有消息为背景,利用指定的模型和可用的插件,智能地回应用户的问题,并将生成的答案插入到线程的消息序列中。 在本场景中,您需执行以下步骤:
这一系列操作确保了助手从接收问题到输出结果的自动化处理流程。 说明 考虑到可能会有大量用户同时使用模型,导致处理时间延长,建议等候状态显示为"complete"后再执行下一步操作,以确保流程顺畅。 |
|
完整代码
非流式输出
import dashscope
from http import HTTPStatus
import json
def check_status(component, operation):
if component.status_code == HTTPStatus.OK:
print(f"{operation} 成功。")
return True
else:
print(f"{operation} 失败。状态码:{component.status_code},错误码:{component.code},错误信息:{component.message}")
return False
# 1. 创建绘画助手
painting_assistant = dashscope.Assistants.create(
model='qwen-max',
name='Art Maestro',
description='用于绘画和艺术知识的AI助手',
instructions='''提供绘画技巧、艺术史和创意指导的信息。
使用工具进行研究和生成图像。''',
tools=[
{'type': 'quark_search', 'description': '用于研究艺术主题'},
{'type': 'text_to_image', 'description': '用于创建视觉示例'}
]
)
if not check_status(painting_assistant, "助手创建"):
exit()
# 2. 创建一个新线程
thread = dashscope.Threads.create()
if not check_status(thread, "线程创建"):
exit()
# 3. 向线程发送消息
message = dashscope.Messages.create(thread.id, content='请帮我画一幅布偶猫的画。')
if not check_status(message, "消息创建"):
exit()
# 4. 在线程上运行助手
run = dashscope.Runs.create(thread.id, assistant_id=painting_assistant.id)
if not check_status(run, "运行创建"):
exit()
# 5. 等待运行完成
print("等待助手处理请求...")
run = dashscope.Runs.wait(run.id, thread_id=thread.id)
if check_status(run, "运行完成"):
print(f"运行完成,状态:{run.status}")
else:
print("运行未完成。")
exit()
# 6. 检索并显示助手的响应
messages = dashscope.Messages.list(thread.id)
if check_status(messages, "消息检索"):
if messages.data:
# 显示最后一条消息的内容(助手的响应)
last_message = messages.data[0]
print("\n助手的回应:")
print(json.dumps(last_message, ensure_ascii=False, default=lambda o: o.__dict__, sort_keys=True, indent=4))
else:
print("在线程中未找到消息。")
else:
print("未能检索到助手的响应。")
# 提示: 这段代码创建了一个绘画助手,开始了一段关于如何绘制布偶猫的对话,
# 并展示了助手的回答。
package com.example;
import java.util.Arrays;
import com.alibaba.dashscope.assistants.Assistant;
import com.alibaba.dashscope.assistants.AssistantParam;
import com.alibaba.dashscope.assistants.Assistants;
import com.alibaba.dashscope.common.GeneralListParam;
import com.alibaba.dashscope.common.ListResult;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.InvalidateParameter;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.threads.AssistantThread;
import com.alibaba.dashscope.threads.ThreadParam;
import com.alibaba.dashscope.threads.Threads;
import com.alibaba.dashscope.threads.messages.Messages;
import com.alibaba.dashscope.threads.messages.TextMessageParam;
import com.alibaba.dashscope.threads.messages.ThreadMessage;
import com.alibaba.dashscope.threads.runs.Run;
import com.alibaba.dashscope.threads.runs.RunParam;
import com.alibaba.dashscope.threads.runs.Runs;
import com.alibaba.dashscope.tools.T2Image.Text2Image;
import com.alibaba.dashscope.tools.search.ToolQuarkSearch;
public class PaintingAssistant {
private static boolean checkStatus(Object response, String operation) {
if (response != null) {
System.out.println(operation + " 成功。");
return true;
} else {
System.out.println(operation + " 失败。");
return false;
}
}
public static void main(String[] args) {
try {
// 1. 创建绘画助手
Assistants assistants = new Assistants();
AssistantParam assistantParam = AssistantParam.builder()
.model("qwen-max")
.name("Art Maestro")
.description("用于绘画和艺术知识的AI助手")
.instructions("提供绘画技巧、艺术史和创意指导的信息。使用工具进行研究和生成图像。")
.tools(Arrays.asList(ToolQuarkSearch.builder().build(),Text2Image.builder().build()))
.build();
Assistant paintingAssistant = assistants.create(assistantParam);
if (!checkStatus(paintingAssistant, "助手创建")) {
System.exit(1);
}
// 2. 创建一个新线程
Threads threads = new Threads();
AssistantThread thread = threads.create(ThreadParam.builder().build());
if (!checkStatus(thread, "线程创建")) {
System.exit(1);
}
// 3. 向线程发送消息
Messages messages = new Messages();
ThreadMessage message = messages.create(thread.getId(),
TextMessageParam.builder()
.role("user")
.content("请帮我画一幅布偶猫的画。")
.build());
if (!checkStatus(message, "消息创建")) {
System.exit(1);
}
// 4. 在线程上运行助手
Runs runs = new Runs();
RunParam runParam = RunParam.builder().assistantId(paintingAssistant.getId()).build();
Run run = runs.create(thread.getId(), runParam);
if (!checkStatus(run, "运行创建")) {
System.exit(1);
}
// 5. 等待运行完成
System.out.println("等待助手处理请求...");
while (true) {
if (run.getStatus().equals(Run.Status.COMPLETED) ||
run.getStatus().equals(Run.Status.FAILED) ||
run.getStatus().equals(Run.Status.CANCELLED) ||
run.getStatus().equals(Run.Status.REQUIRES_ACTION) ||
run.getStatus().equals(Run.Status.EXPIRED)) {
break;
}
Thread.sleep(1000);
run = runs.retrieve(thread.getId(), run.getId());
}
if (checkStatus(run, "运行完成")) {
System.out.println("运行完成,状态:" + run.getStatus());
} else {
System.out.println("运行未完成。");
System.exit(1);
}
// 6. 检索并显示助手的响应
ListResult<ThreadMessage> messagesList = messages.list(thread.getId(), GeneralListParam.builder().build());
if (checkStatus(messagesList, "消息检索")) {
if (!messagesList.getData().isEmpty()) {
// 显示最后一条消息(助手的响应)
ThreadMessage lastMessage = messagesList.getData().get(0);
System.out.println("\n助手的回应:");
System.out.println(lastMessage.getContent());
} else {
System.out.println("在线程中未找到消息。");
}
} else {
System.out.println("未能检索到助手的响应。");
}
} catch (ApiException | NoApiKeyException | InputRequiredException | InvalidateParameter | InterruptedException e) {
e.printStackTrace();
}
}
}
流式输出
Java SDK 暂不支持流式调用 图片生成 工具。
import dashscope
from http import HTTPStatus
import json
import sys
def check_status(response, operation):
if response.status_code == HTTPStatus.OK:
print(f"{operation} 成功。")
return True
else:
print(f"{operation} 失败。状态码:{response.status_code},错误码:{response.code},错误信息:{response.message}")
sys.exit(response.status_code)
# 1. 创建绘画助手
def create_painting_assistant():
return dashscope.Assistants.create(
model='qwen-max',
name='Art Maestro',
description='AI助手,用于绘画和艺术知识',
instructions='''提供绘画技巧、艺术史和创意指导的信息。
使用工具进行研究和生成图像。''',
tools=[
{'type': 'quark_search', 'description': '用于研究艺术主题'},
{'type': 'text_to_image', 'description': '用于创建视觉示例'}
]
)
if __name__ == '__main__':
# 创建绘画助手
painting_assistant = create_painting_assistant()
print(painting_assistant)
check_status(painting_assistant, "助手创建")
# 创建一个带有初始消息的新线程
thread = dashscope.Threads.create(
messages=[{
'role': 'user',
'content': '请帮我画一幅布偶猫的画。'
}]
)
print(thread)
check_status(thread, "线程创建")
# 创建流式输出的运行
run_iterator = dashscope.Runs.create(
thread.id,
assistant_id=painting_assistant.id,
stream=True
)
# 迭代事件和消息
print("处理请求中...")
for event, msg in run_iterator:
print(event)
print(msg)
# 检索并显示助手的响应
messages = dashscope.Messages.list(thread.id)
check_status(messages, "消息检索")
print("\n助手的回应:")
print(json.dumps(messages, ensure_ascii=False, default=lambda o: o.__dict__, sort_keys=True, indent=4))
# 提示: 这个脚本创建了一个流式输出的绘画助手,开始一段关于绘制布偶猫的对话,
# 并实时显示助手的回应。
import java.util.Arrays;
import com.alibaba.dashscope.assistants.Assistant;
import com.alibaba.dashscope.assistants.AssistantParam;
import com.alibaba.dashscope.assistants.Assistants;
import com.alibaba.dashscope.common.GeneralListParam;
import com.alibaba.dashscope.common.ListResult;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.InvalidateParameter;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.threads.AssistantThread;
import com.alibaba.dashscope.threads.ThreadParam;
import com.alibaba.dashscope.threads.Threads;
import com.alibaba.dashscope.threads.messages.Messages;
import com.alibaba.dashscope.threads.messages.TextMessageParam;
import com.alibaba.dashscope.threads.messages.ThreadMessage;
import com.alibaba.dashscope.threads.runs.AssistantStreamMessage;
import com.alibaba.dashscope.threads.runs.Run;
import com.alibaba.dashscope.threads.runs.RunParam;
import com.alibaba.dashscope.threads.runs.Runs;
import com.alibaba.dashscope.tools.T2Image.Text2Image;
import com.alibaba.dashscope.tools.search.ToolQuarkSearch;
import io.reactivex.Flowable;
public class PaintingAssistant {
private static boolean checkStatus(Object response, String operation) {
if (response != null) {
System.out.println(operation + " 成功。");
return true;
} else {
System.out.println(operation + " 失败。");
return false;
}
}
private static Assistant createPaintingAssistant() throws ApiException, NoApiKeyException {
Assistants assistants = new Assistants();
AssistantParam assistantParam = AssistantParam.builder()
.model("qwen-max")
.name("Art Maestro")
.description("用于绘画和艺术知识的AI助手")
.instructions("提供绘画技巧、艺术史和创意指导的信息。使用工具进行研究和生成图像。")
.tools(Arrays.asList(ToolQuarkSearch.builder().build()))
.build();
return assistants.create(assistantParam);
}
private static void runPaintingAssistant(String assistantId) throws ApiException, NoApiKeyException, InvalidateParameter, InputRequiredException, InterruptedException {
Threads threads = new Threads();
AssistantThread thread = threads.create(ThreadParam.builder().build());
if (!checkStatus(thread, "线程创建")) {
System.exit(1);
}
Messages messages = new Messages();
ThreadMessage message = messages.create(thread.getId(),
TextMessageParam.builder()
.role("user")
.content("请帮我画一幅布偶猫的画。")
.build());
if (!checkStatus(message, "消息创建")) {
System.exit(1);
}
Runs runs = new Runs();
RunParam runParam = RunParam.builder().assistantId(assistantId).stream(true).build();
try {
System.out.println("尝试流式输出助手的响应...");
Flowable<AssistantStreamMessage> runFlowable = runs.createStream(thread.getId(), runParam);
runFlowable.blockingForEach(assistantStreamMessage -> {
System.out.println("事件:" + assistantStreamMessage.getEvent());
System.out.println("数据:" + assistantStreamMessage.getData());
});
} catch (Exception e) {
System.out.println("流式输出失败,切换为非流式输出方法。");
e.printStackTrace();
// 切换到非流式输出方法
Run run = runs.create(thread.getId(), RunParam.builder().assistantId(assistantId).build());
while (true) {
if (run.getStatus().equals(Run.Status.COMPLETED) ||
run.getStatus().equals(Run.Status.FAILED) ||
run.getStatus().equals(Run.Status.CANCELLED) ||
run.getStatus().equals(Run.Status.REQUIRES_ACTION) ||
run.getStatus().equals(Run.Status.EXPIRED)) {
break;
}
Thread.sleep(1000);
run = runs.retrieve(thread.getId(), run.getId());
}
System.out.println("运行完成,状态:" + run.getStatus());
}
// 检索并显示助手的响应
GeneralListParam listParam = GeneralListParam.builder().limit(100L).build();
ListResult<ThreadMessage> messagesList = messages.list(thread.getId(), listParam);
if (checkStatus(messagesList, "消息检索")) {
if (!messagesList.getData().isEmpty()) {
System.out.println("\n助手的回应:");
for (ThreadMessage threadMessage : messagesList.getData()) {
System.out.println(threadMessage.getContent());
}
} else {
System.out.println("在线程中未找到消息。");
}
} else {
System.out.println("未能检索到助手的响应。");
}
}
public static void main(String[] args) {
try {
Assistant paintingAssistant = createPaintingAssistant();
if (!checkStatus(paintingAssistant, "助手创建")) {
System.exit(1);
}
runPaintingAssistant(paintingAssistant.getId());
} catch (ApiException | NoApiKeyException | InputRequiredException | InvalidateParameter | InterruptedException e) {
System.out.println("运行绘画助手时发生错误:");
e.printStackTrace();
}
}
}
后续操作
若您希望深入了解API的详细配置与参数,不妨查阅Assistant API。