功能介绍
本文主要介绍如何基于阿里云百炼的应用中心快速创建RAG应用,并通过API/SDK低代码方式调用RAG应用进行文档问答的最佳实践。
创建应用
Step 1:数据管理-导入数据
在数据中心,选择“默认类目”后,点击“导入数据”,然后通过“本地上传”的方式导入数据。导入数据需要花费一定的时间,需要耐心等待数据转为“导入完成”的状态(通过手动点击刷新按钮)。
Step 2:创建知识索引
1)在数据应用-知识索引页面,创建知识库,输入知识库描述,选择推荐配置即可。
2)点击下一步,从数据中心选择相关文件,选择导入完成,进行文档切分、构建索引等后续操作。
注:导入数据后,需要耐心等待知识库中的数据转为“解析完成”状态,才能在后续的文档问答过程中被检索到。
3) 获取知识索引ID,支持与百炼Assistant API结合使用,支持RAG和插件的组合调用;
Step 3:创建应用
进入我的应用后,单击新增应用,单击智能体应用,创建RAG应用,然后在应用配置中,进行以下操作:
选择模型。同时,还支持配置与模型生成内容相关的参数,例如,温度系数等。
单击“配置知识库”。
选择知识库,即在Step2中创建的知识索引。
单击“发布”按钮。
应用发布后,即可在右侧的窗口进行效果测试。
调用应用
前提条件
已创建API-KEY:获取API-KEY。
已获取到APP_ID:获取API-KEY、APP-ID和Workspace ID。
已安装最新版SDK:安装SDK。
通过API/SDK调用应用
需要使用您的API-KEY替换示例中的YOUR_API_KEY,并将APP-ID替换示例中的YOUR_APP_ID,代码才能正常运行。
from http import HTTPStatus
from dashscope import Application
def call_agent_app():
response = Application.call(app_id='YOUR_APP_ID',
prompt='百炼的业务空间是什么?如何使用业务空间?',
api_key='YOUR_API_KEY',
)
if response.status_code != HTTPStatus.OK:
print('request_id=%s, code=%s, message=%s\n' % (response.request_id, response.status_code, response.message))
else:
print('request_id=%s\n output=%s\n usage=%s\n' % (response.request_id, response.output, response.usage))
if __name__ == '__main__':
call_agent_app()
import com.alibaba.dashscope.app.*;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import java.util.List;
public class Main{
public static void callAgentApp()
throws ApiException, NoApiKeyException, InputRequiredException {
ApplicationParam param = ApplicationParam.builder()
.apiKey("YOUR_API_KEY")
.appId("YOUR_APP_ID")
.prompt("百炼的业务空间是什么?如何使用业务空间?")
.build();
Application application = new Application();
ApplicationResult result = application.call(param);
System.out.printf("requestId: %s, text: %s, finishReason: %s\n",
result.getRequestId(), result.getOutput().getText(), result.getOutput().getFinishReason());
}
public static void main(String[] args) {
try {
callAgentApp();
} catch (ApiException | NoApiKeyException | InputRequiredException e) {
System.out.printf("Exception: %s", e.getMessage());
}
System.exit(0);
}
}
curl --location 'https://dashscope.aliyuncs.com/api/v1/apps/{YOUR_APP_ID}/completion' \
--header 'Authorization: Bearer {YOUR_API_KEY}' \
--header 'Content-Type: application/json' \
--data '{
"input": {
"prompt": "百炼的业务空间是什么?如何使用业务空间?"
},
"parameters": {},
"debug": {}
}' --verbose
通过Assistant API调用
设置您的API-KEY,替换YOUR_DASHCOPE_API_KEY为您自己的API key。
替换YOUR_PIPELINE_ID为百炼知识库创建的知识索引ID,具体参考
Step 2:创建知识索引
第三小节内容。其中${document1}为占位符,知识库检索回来的内容会替换instructions中${document1},请确保RAG工具中定义
query_word/value
的占位符与instructions中占位符一致。
export DASHSCOPE_API_KEY=YOUR_DASHSCOPE_API_KEY
from dashscope import Assistants, Messages, Runs, Threads
assistant = Assistants.create(
model='qwen-max',
name='smart helper',
description='智能助手,支持知识库查询和插件调用。',
instructions='你是一个智能助手,请记住以下信息。${document1}',
tools=[
{
"type": "code_interpreter"
},
{
"type": "rag",
"prompt_ra": {
"pipeline_id": "YOUR_PIPELINE_ID",
"parameters": {
"type": "object",
"properties": {
"query_word": {
"type": "str",
"value": "${document1}"
}
}
}
}
}]
)
def send_message(assistant, message='百炼是什么?'):
print(f"Query: {message}")
# create thread.
# create a thread.
thread = Threads.create()
print(thread)
# create a message.
message = Messages.create(thread.id, content=message)
# create run
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(run_status)
# if prompt input tool result, submit tool result.
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__":
send_message(assistant, message='百炼是什么?')
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.ContentText;
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.ToolBase;
import com.google.gson.JsonObject;
import com.google.gson.annotations.SerializedName;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.SuperBuilder;
public class AssistantApiRag {
public static Assistant createAssistant(String pipelineId) throws ApiException, NoApiKeyException {
//注意instructions的${document1}占位符和buildPromptRa的${document1}占位符必须保持一致
AssistantParam assistantParam = AssistantParam.builder()
.model("qwen-max")
.name("smart helper")
.description("智能助手,支持知识库查询和插件调用。")
.instructions("你是一个智能助手,请记住以下信息。${document1}")
.tool(ToolRag.builder()
.promptRa(ToolRag.buildPromptRa("${document1}", pipelineId))
.build())
.build();
Assistants assistants = new Assistants();
return assistants.create(assistantParam);
}
public static void sendMessage(Assistant assistant, String message) throws NoApiKeyException, InputRequiredException, InvalidateParameter, InterruptedException {
Threads threads = new Threads();
AssistantThread assistantThread = threads.create(ThreadParam.builder().build());
Runs runs = new Runs();
// create a new message
TextMessageParam textMessageParam = TextMessageParam.builder()
.role("user")
.content(message)
.build();
Messages messages = new Messages();
ThreadMessage threadMessage = messages.create(assistantThread.getId(), textMessageParam);
System.out.println(threadMessage);
RunParam runParam = RunParam.builder().assistantId(assistant.getId()).build();
Run run = runs.create(assistantThread.getId(), runParam);
while (true) {
if (run.getStatus().equals(Run.Status.CANCELLED) ||
run.getStatus().equals(Run.Status.COMPLETED) ||
run.getStatus().equals(Run.Status.FAILED) ||
run.getStatus().equals(Run.Status.REQUIRES_ACTION) ||
run.getStatus().equals(Run.Status.EXPIRED)) {
break;
} else {
Thread.sleep(1000);
}
run = runs.retrieve(assistantThread.getId(), run.getId());
}
System.out.println(run);
GeneralListParam listParam = GeneralListParam.builder().limit(100L).build();
ListResult<ThreadMessage> threadMessages = messages.list(assistantThread.getId(), listParam);
for (ThreadMessage threadMessage2 : threadMessages.getData()) {
System.out.printf("content: %s\n", ((ContentText) threadMessage2.getContent().get(0)).getText().getValue());
}
}
public static void main(String[] args) throws NoApiKeyException, InputRequiredException, InvalidateParameter, InterruptedException {
String pipelineId = "wa9vj93fwv";
Assistant assistant = createAssistant(pipelineId);
sendMessage(assistant, "百炼是什么?");
}
}
@Data
@EqualsAndHashCode(callSuper = false)
@SuperBuilder
class ToolRag extends ToolBase {
static {
registerTool("rag", ToolRag.class);
}
@Builder.Default
private String type = "rag";
@SerializedName("prompt_ra")
private JsonObject promptRa;
@Override
public String getType() {
return type;
}
public static JsonObject buildPromptRa(String placeholder, String pipelineId) {
JsonObject queryWord = new JsonObject();
queryWord.addProperty("type", "str");
queryWord.addProperty("value", placeholder);
JsonObject properties = new JsonObject();
properties.add("query_word", queryWord);
JsonObject parameters = new JsonObject();
parameters.addProperty("type", "object");
parameters.add("properties", properties);
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("pipeline_id", pipelineId);
jsonObject.add("parameters", parameters);
return jsonObject;
}
}