diff --git a/appbuilder/__init__.py b/appbuilder/__init__.py index e54f1f2c0..672571ebd 100644 --- a/appbuilder/__init__.py +++ b/appbuilder/__init__.py @@ -93,6 +93,8 @@ def check_version(self): from appbuilder.core.utils import get_model_list +from appbuilder.core.console.agent_builder.agent_builder import AgentBuilder + from .core._exception import ( BadRequestException, ForbiddenException, @@ -158,4 +160,5 @@ def check_version(self): "HandwriteOCR", "ImageUnderstand", "MixCardOCR", + "AgentBuilder", ] diff --git a/appbuilder/core/console/agent_builder/README.md b/appbuilder/core/console/agent_builder/README.md new file mode 100644 index 000000000..e47ac94d3 --- /dev/null +++ b/appbuilder/core/console/agent_builder/README.md @@ -0,0 +1,160 @@ +# AgentBuilder组件 + +## 简介 + +AgentBuilder组件支持调用在[百度智能云千帆AppBuilder](https://cloud.baidu.com/product/AppBuilder)平台上通过AgentBuilder构建并发布的智能体应用。 + +### 功能介绍 + +具体包括创建会话、上传文档、运行对话等 + +### 特色优势 + +与云端Console AgentBuilder能力打通,实现低代码会话 + +### 应用场景 + +快速、高效集成云端已发布智能体应用能力 + +## 基本用法 + +以下是使用SDK进行问答的示例代码 + +```python +import appbuilder +import os + +# 请前往千帆AppBuilder官网创建密钥,流程详见:https://cloud.baidu.com/doc/AppBuilder/s/Olq6grrt6#1%E3%80%81%E5%88%9B%E5%BB%BA%E5%AF%86%E9%92%A5 +# 设置环境变量 +os.environ["APPBUILDER_TOKEN"] = '...' +app_id = '...' # 已发布AgentBuilder应用ID,可在console端查看 +# 初始化智能体 +agent = appbuilder.AgentBuilder(app_id) +# 创建会话 +conversation_id = agent.create_conversation() +# 运行对话 +out = agent.run("北京天气怎么样", conversation_id) +# 打印会话结果 +print(out.content.answer) +``` + +## 参数说明 + +### 鉴权说明 + +使用组件之前,请首先申请并设置鉴权参数,可参考[使用流程](https://cloud.baidu.com/doc/AppBuilder/s/Olq6grrt6#1%E3%80%81%E5%88%9B%E5%BB%BA%E5%AF%86%E9%92%A5)。 + +```python +# 设置环境中的TOKEN,以下示例略 +os.environ["APPBUILDER_TOKEN"] = "bce-YOURTOKEN" +``` + +### 初始化参数 + +- `app_id`: 线上AgentBuilder应用ID,可在[百度智能云千帆AppBuilder](https://cloud.baidu.com/product/AppBuilder)我的应用中查看应用ID,示例如图 + +image + +### 调用参数 + +| 参数名称 | 参数类型 | 是否必须 | 描述 | 示例值 | +|-----------------|--------------|------|------------|------------| +| conversation_id | String | 是 | 会话ID | | +| query | String | 否 | query问题内容 | "今天天气怎么样?" | +| file_ids | list[String] | 否 | 对话可引用的文档ID | False | +| stream | Bool | 否 | 是否流式返回 | False | + +### 非流式返回 + +| 参数名称 | 参数类型 | 描述 | 示例值 | +|----------------|--------------------|------------------|------------------------------------------------------------------------| +| content | AgentBuilderAnswer | 对话返回结果 | | +| +code | Int | 错误码,0代码成功,非0表示失败 | 0 | +| +message | String | 错误具体消息 | | +| +answer | String | 智能体应用返回的回答 | | +| +events | List[Event] | 事件列表 | | +| +events[0] | Event | 具体事件内容 | | +| ++code | String | 错误码 | | +| ++message | String | 错误具体消息 | | +| ++status | String | 事件状态 | 状态描述,preparing(准备运行)running(运行中)error(执行错误) done(执行完成) | +| ++event_type | String | 事件类型 | | +| ++content_type | String | 内容类型 | 可选值包括:code text, image, status,image, function_call, rag, audio、video等 | +| ++detail | Dict | 事件输出详情 | 代码解释器、文生图、工具组件等的详细输出内容 | + +### 流式返回 + +| 参数名称 | 参数类型 | 描述 | 示例值 | +|---------|------------------|--------------------------------|-----| +| content | Python Generator | 可迭代,每次迭代返回AgentBuilderAnswer类型 | 无 | + +### 响应示例 + +``` +Message(name=msg, content=code=0 message='' answer='模型识别结果为:\n类别: 黑松 置信度: 0.599807\n根据植物识别工具的识别结果,图中的植物很可能是黑松,置信度为0.599807。需要注意的是,置信度并不是特别高,因此这个结果仅供参考。如果你需要更准确的识别结果,可以尝试提供更多的图片信息或者使用更专业的植物识别工具。如果你还有其他问题或者需要进一步的帮助,请随时告诉我。' events=[Event(code=0, message='', status='done', event_type='function_call', content_type='function_call', detail={'text': {'thought': '', 'name': 'plant_rec', 'arguments': {'img_path': 'tree.png'}, 'component': 'PlantRecognition', 'name_cn': '植物识别'}}), Event(code=0, message='', status='preparing', event_type='PlantRecognition', content_type='status', detail={}), Event(code=0, message='', status='done', event_type='PlantRecognition', content_type='text', detail={'text': '模型识别结果为:\n类别: 黑松 置信度: 0.599807\n'}), Event(code=0, message='', status='success', event_type='PlantRecognition', content_type='status', detail={}), Event(code=0, message='', status='done', event_type='function_call', content_type='function_call', detail={'text': {'thought': '', 'name': 'chat_agent', 'arguments': {}, 'component': 'ChatAgent', 'name_cn': '聊天助手'}}), Event(code=0, message='', status='preparing', event_type='ChatAgent', content_type='status', detail={}), Event(code=0, message='', status='done', event_type='ChatAgent', content_type='text', detail={'text': '根据植物识别工具的识别结果,图中的植物很可能是黑松,置信度为0.599807。需要注意的是,置信度并不是特别高,因此这个结果仅供参考。如果你需要更准确的识别结果,可以尝试提供更多的图片信息或者使用更专业的植物识别工具。如果你还有其他问题或者需要进一步的帮助,请随时告诉我。'}), Event(code=0, message='', status='success', event_type='ChatAgent', content_type='status', detail={})], mtype=AgentBuilderAnswer) +``` + +## 高级用法 + +```python + +import appbuilder +from appbuilder.core.console.agent_builder import data_class +import os + +# 请前往千帆AppBuilder官网创建密钥,流程详见:https://cloud.baidu.com/doc/AppBuilder/s/Olq6grrt6#1%E3%80%81%E5%88%9B%E5%BB%BA%E5%AF%86%E9%92%A5 +# 设置环境变量 +os.environ["APPBUILDER_TOKEN"] = '...' +app_id = '...' # 已发布AgentBuilder应用的ID +# 初始化智能体 +agent = appbuilder.AgentBuilder(app_id) +# 创建会话 +conversation_id = agent.create_conversation() + +# 上传一个介绍介绍北京旅游景点的文档 +file_id = agent.upload_local_file(conversation_id, "/path/to/pdf/file") +# 开始对话,引用上传的文档 +message = agent.run(conversation_id, "北京天气怎么样", file_ids=[file_id, ], stream=True) + + +answer = "" + +# 每次迭代返回AgentBuilderAnswer结构,内可能包括多个事件内容 +for content in message.content: + # stream=True时,将answer拼接起来才是完整的的对话结果 + answer += content.answer + for event in content.events: + content_type = event.content_type + detail = event.detail + # 根据content类型对事件详情进行解析 + if content_type == "code": + code_detail = data_class.CodeDetail(**detail) + print(code_detail.code) + elif content_type == "text": + text_detail = data_class.TextDetail(**detail) + print(text_detail.text) + elif content_type == "image": + image_detail = data_class.ImageDetail(**detail) + print(image_detail.url) + elif content_type == "rag": + rag_detail = data_class.RAGDetail(**detail) + print(rag_detail.references) + elif content_type == "function_call": + function_call_detail = data_class.FunctionCallDetail(**detail) + print(function_call_detail.video) + elif content_type == "audio": + audio_detail = data_class.AudioDetail(**detail) + print(audio_detail) + elif content_type == "video": + video_detail = data_class.VideoDetail(**detail) + print(video_detail) + elif content_type == "status": + data_class.StatusDetail(**detail) + else: + print(detail) + +# 打印完整的answer结果 +print(answer) +``` + +## 更新记录和贡献 +* 集成Console AgentBuilder能力(2024-03) \ No newline at end of file diff --git a/appbuilder/core/console/agent_builder/__init__.py b/appbuilder/core/console/agent_builder/__init__.py new file mode 100644 index 000000000..ba760dad3 --- /dev/null +++ b/appbuilder/core/console/agent_builder/__init__.py @@ -0,0 +1,13 @@ +# Copyright (c) 2024 Baidu, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/appbuilder/core/console/agent_builder/agent_builder.py b/appbuilder/core/console/agent_builder/agent_builder.py new file mode 100644 index 000000000..1bdd2ce78 --- /dev/null +++ b/appbuilder/core/console/agent_builder/agent_builder.py @@ -0,0 +1,180 @@ +# Copyright (c) 2024 Baidu, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""AgentBuilder组件""" + +import json +import os + +from appbuilder.core.component import Message, Component +from appbuilder.core.console.agent_builder import data_class +from appbuilder.core._exception import AppBuilderServerException +from appbuilder.utils.sse_util import SSEClient + + +class AgentBuilder(Component): + r""" + AgentBuilder组件支持调用在[百度智能云千帆AppBuilder](https://cloud.baidu.com/product/AppBuilder)平台上通过AgentBuilder + 构建并发布的智能体应用,具体包括创建会话、上传文档、运行对话等。 + Examples: + ... code-block:: python + import appbuilder + # 请前往千帆AppBuilder官网创建密钥,流程详见:https://cloud.baidu.com/doc/AppBuilder/s/Olq6grrt6#1%E3%80%81%E5%88%9B%E5%BB%BA%E5%AF%86%E9%92%A5 + os.environ["APPBUILDER_TOKEN"] = '...' + # 可在Console AgentBuilder应用页面获取 + app_id = "app_id" + agent_builder = appbuilder.AgentBuilder("app_id") + conversation_id = agent_builder.create_conversation() + file_id = agent_builder.upload_local_file(conversation_id, "/path/to/file") + message = agent_builder.run(conversation_id, "今天你好吗?") + # 打印对话结果 + print(message.content) + """ + + def __init__(self, app_id: str, **kwargs): + r"""初始化智能体应用 + 参数: + app_id (str: 必须) : 应用唯一ID + 返回: + response (obj: `AgentBuilder`): 智能体实例 + """ + super().__init__(**kwargs) + if (not isinstance(app_id, str)) or len(app_id) == 0: + raise ValueError("app_id must be a str, and length is bigger then zero," + "please go to official website which is 'https://cloud.baidu.com/product/AppBuilder'" + " to get a valid app_id after your application is published.") + self.app_id = app_id + + def create_conversation(self) -> str: + r"""创建会话并返回会话ID,会话ID在服务端用于上下文管理、绑定会话文档等,如需开始新的会话,请创建并使用新的会话ID + 参数: + 无 + 返回: + response (str: ): 唯一会话ID + """ + headers = self.http_client.auth_header() + headers["Content-Type"] = "application/json" + url = self.http_client.service_url("/v1/ai_engine/agi_platform/v1/conversation/create", "/api") + response = self.http_client.session.post(url, headers=headers, json={"app_id": self.app_id}, timeout=None) + self.http_client.check_response_header(response) + request_id = self.http_client.response_request_id(response) + data = response.json() + self._check_console_response(request_id, data) + resp = data_class.CreateConversationResponse(**data) + return resp.result.conversation_id + + def upload_local_file(self, conversation_id, local_file_path: str) -> str: + r"""上传文件并将文件与会话ID进行绑定,后续可使用该文件ID进行对话,目前仅支持上传xlsx、jsonl、pdf、png等文件格式 + 参数: + conversation_id (str: 必须) : 会话ID + local_file_path (str: 必须) : 本地文件路径 + 返回: + response (str: ): 唯一文件ID + """ + + if len(conversation_id) == 0: + raise ValueError("conversation_id is empty") + multipart_form_data = { + 'file': (os.path.basename(local_file_path), open(local_file_path, 'rb')), + 'app_id': (None, self.app_id), + 'conversation_id': (None, conversation_id), + 'scenario': (None, "assistant") + } + headers = self.http_client.auth_header() + url = self.http_client.service_url("/v1/ai_engine/agi_platform/v1/instance/upload", "/api") + response = self.http_client.session.post(url, files=multipart_form_data, headers=headers) + self.http_client.check_response_header(response) + request_id = self.http_client.response_request_id(response) + data = response.json() + self._check_console_response(request_id, data) + resp = data_class.FileUploadResponse(**data) + return resp.result.id + + def run(self, conversation_id: str, + query: str, + file_ids: list[str] = [], + stream: bool = False, + ) -> Message: + + r""" 动物识别 + 参数: + query (str: 必须): query内容 + conversation_id (str, 必须): 唯一会话ID,如需开始新的会话,请使用self.create_conversation创建新的会话 + file_ids(list[str], 可选): + stream (bool, 可选): 为True时,流式返回,需要将message.content.answer拼接起来才是完整的回答;为False时,对应非流式返回 + 返回: message (obj: `Message`): 对话结果. + """ + + if len(conversation_id) == 0: + raise ValueError("conversation_id is empty") + + req = data_class.HTTPRequest( + app_id=self.app_id, + conversation_id=conversation_id, + query=query, + response_mode="streaming" if stream else "blocking", + file_ids=file_ids, + ) + + headers = self.http_client.auth_header() + headers["Content-Type"] = "application/json" + url = self.http_client.service_url("/v1/ai_engine/agi_platform/v1/instance/integrated", '/api') + response = self.http_client.session.post(url, headers=headers, json=req.model_dump(), timeout=None, stream=True) + self.http_client.check_response_header(response) + request_id = self.http_client.response_request_id(response) + if stream: + client = SSEClient(response) + return Message(content=self._iterate_events(request_id, client.events())) + else: + data = response.json() + self._check_console_response(request_id, data) + resp = data_class.HTTPResponse(**data) + out = data_class.AgentBuilderAnswer() + _transform(resp, out) + return Message(content=out) + + def _iterate_events(self, request_id, events) -> data_class.AgentBuilderAnswer: + for event in events: + try: + data = event.data + if len(data) == 0: + data = event.raw + data = json.loads(data) + self._check_console_response(request_id, data) + except json.JSONDecodeError as e: + raise AppBuilderServerException(request_id=request_id, message="json decoder failed {}".format(str(e))) + inp = data_class.HTTPResponse(**data) + out = data_class.AgentBuilderAnswer() + _transform(inp, out) + yield out + + @staticmethod + def _check_console_response(request_id: str, data): + if data["code"] != 0: + raise AppBuilderServerException( + request_id=request_id, + service_err_code=data["code"], + service_err_message="message={}". + format(data["message"]) + ) + + +def _transform(inp: data_class.HTTPResponse, out: data_class.AgentBuilderAnswer): + out.code = inp.code + out.message = inp.message + out.answer = inp.result.answer + for ev in inp.result.content: + out.events.append(data_class.Event(code=ev.event_code, message=ev.event_message, + status=ev.event_status, event_type=ev.event_type, + content_type=ev.content_type, detail=ev.outputs)) diff --git a/appbuilder/core/console/agent_builder/data_class.py b/appbuilder/core/console/agent_builder/data_class.py new file mode 100644 index 000000000..069f6df3a --- /dev/null +++ b/appbuilder/core/console/agent_builder/data_class.py @@ -0,0 +1,234 @@ +# Copyright (c) 2024 Baidu, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from pydantic import BaseModel +from typing import Union + + +class HTTPRequest(BaseModel): + """会话请求参数 + 属性: + query (str): 查询参数 + response_mode (str): streaming或blocking + conversation_id (str): 会话ID + file_ids(list[str]): 文件ID + app_id:应用ID + """ + query: str = "" + response_mode: str + conversation_id: str + file_ids: list[str] = [] + app_id: str + + +class OriginalEvent(BaseModel): + """会话请求参数 + 属性: + event_code (int): 0代表成功,非0为失败 + event_message (str): 错误详情 + node_name (str): 节点名,保留字段 + dependency_nodes(str):依赖节点名,保留字段 + event_type(str):事件类型 + event_status(str):事件状态 + content_type(str):内容类型 + outputs(dict):事件输出 + """ + event_code: int = "" + event_message: str = "" + node_name: str = "" + dependency_nodes: list[str] = [] + event_type: str = "" + event_id: str = "" + event_status: str = "" + content_type: str = "" + outputs: dict = {} + + +class Result(BaseModel): + """会话请求参数 + 属性: + answer (str): query结果 + conversation_id (str): 会话ID + message_id (str): 消息ID + is_completion(bool): 会话是否结束 + content(list[OriginalEvent]): 事件列表 + """ + answer: str = "" + conversation_id: str = "" + message_id: str = "" + is_completion: Union[bool, None] = "" + content: list[OriginalEvent] = [] + + +class HTTPResponse(BaseModel): + """会话请求参数 + 属性: + code (int): 响应状态码 + message (str): 状态详情 + trace_id (str): 链路ID + time(int): 消息返回时间的时间戳 ,单位为毫秒 + prototype(str): 与前端交互时会用到的字段 + result: 响应结果 + """ + code: int = 0 + message: str = "" + trace_id: str = "" + time: int = 0 + prototype: str = "" + result: Result = Result() + + +class TextDetail(BaseModel): + """content_type=text,详情内容 + 属性: + text(str): 文本详情 + """ + text: str = "" + + +class CodeDetail(BaseModel): + """content_type=code,详情内容 + 属性: + text(str): 文本详情 + code: 代码解释器工具生产的代码 + files: 代码解释器生成的可下载文件地址列表 + """ + text: str = "" + code: str = "" + files: list[str] = [] + + +class RAGDetail(BaseModel): + """content_type=image,详情内容 + 属性: + text(str): 文本详情 + references(list[dict]): 引用详情 + """ + text: str = "" + references: list[dict] = [] + + +class FunctionCallDetail(BaseModel): + """content_type=function_call,详情内容 + 属性: + text(str): 文本详情 + """ + text: Union[str, dict] = "" + image: str = "" + audio: str = "" + video: str = "" + + +class ImageDetail(BaseModel): + """content_type=function_call,详情内容 + 属性: + image(str): 图片下载地址 + """ + image: str = "" + + +class AudioDetail(BaseModel): + """content_type=audio,详情内容 + 属性: + image(str): 音频下载地址 + """ + audio: str = "" + + +class VideoDetail(BaseModel): + """content_type=video,详情内容 + 属性: + vidoe(str): 视频下载地址 + """ + video: str = "" + + +class StatusDetail(BaseModel): + pass + + +class Event(BaseModel): + """执行步骤的具体内容 + 属性: + code (int): 响应code码 + message (str): 错误详情 + status (str): 状态描述,preparing(准备运行)running(运行中)error(执行错误) done(执行完成) + event_type(str): 事件类型 + content_type(str): 内容类型 + detail(dict): 事件详情, + """ + code: int = 0 + message: str = "" + status: str = "" + event_type: str = "" + content_type: str = "" + detail: dict = {} + + +class AgentBuilderAnswer(BaseModel): + """执行步骤的具体内容 + 属性: + code (int): 响应code码 + message (str): 错误详情 + answer(str): query回答内容 + events( list[Event]): 事件列表 + """ + code: int = 0 + message: str = "" + answer: str = "" + events: list[Event] = [] + + +class FileUploadResult(BaseModel): + """文档上传结果 + 属性: + id (str): 文档ID + conversation_id (str): 对话ID + """ + id: str = "" + conversation_id: str = "" + + +class FileUploadResponse(BaseModel): + """文档上传结果 + 属性: + code (int): 响应code码 + message (str): 错误详情 + Result (FileUploadResult): 上传结果 + """ + code: int = 0 + message: str = "" + result: FileUploadResult = FileUploadResult() + + +class CreateConversationResult(BaseModel): + """文档上传结果 + 属性: + code (int): 响应code码 + message (str): 错误详情 + conversation_id (str): 对话ID + """ + conversation_id: str = "" + + +class CreateConversationResponse(BaseModel): + """文档上传结果 + 属性: + code (int): 响应code码 + message (str): 错误详情 + Result (FileUploadResult): 上传结果 + """ + code: int = 0 + message: str = "" + result: CreateConversationResult = CreateConversationResult() diff --git a/appbuilder/core/console/rag/rag.py b/appbuilder/core/console/rag/rag.py index adde1261a..eebeaf11c 100644 --- a/appbuilder/core/console/rag/rag.py +++ b/appbuilder/core/console/rag/rag.py @@ -58,7 +58,7 @@ def run(self, query: Message, conversation_id: str = "", stream: bool = False): headers = self.http_client.auth_header() headers["Content-Type"] = "application/json" response = self.http_client.session.post(url=self.http_client.service_url(self.integrated_url), - headers=headers, data=payload) + headers=headers, data=payload, stream=True) response = ConsoleCompletionResponse(response, stream) return response.to_message() diff --git a/appbuilder/tests/test_agent_builder.py b/appbuilder/tests/test_agent_builder.py new file mode 100644 index 000000000..4c477dfb7 --- /dev/null +++ b/appbuilder/tests/test_agent_builder.py @@ -0,0 +1,45 @@ +import unittest +import appbuilder +import requests +import tempfile +import os + + +class TestAgentRuntime(unittest.TestCase): + def setUp(self): + """ + 设置环境变量。 + + Args: + 无参数,默认值为空。 + + Returns: + 无返回值,方法中执行了环境变量的赋值操作。 + """ + os.environ["APPBUILDER_TOKEN"] = "" + self.app_id = "" + + def test_agent_builder_run(self): + # 如果app_id为空,则跳过单测执行, 避免单测因配置无效而失败 + if len(self.app_id) == 0: + self.skipTest("self.app_id is empty") + + agent_builder = appbuilder.AgentBuilder(self.app_id) + conversation_id = agent_builder.create_conversation() + + with tempfile.NamedTemporaryFile(suffix=".png") as fp: + # 上传植物图片 + img_url = ("https://bj.bcebos.com/v1/appbuilder/test_agent_builder_tr" + "ee.png?authorization=bce-auth-v1%2FALTAKGa8m4qCUasgoljdEDAzL" + "m%2F2024-03-20T08%3A03%3A16Z%2F-1%2Fhost%2F8227f2bb97928b1957a9a6" + "c14c4e307ef195d18ec68b22764158690cecbd9fc7") + raw_image = requests.get(img_url).content + fp.write(raw_image) + file_id = agent_builder.upload_local_file(conversation_id, fp.name) + msg = agent_builder.run(conversation_id, "请识别图中的植物类别", file_ids=[file_id]) + print("助理回答内容:", msg.content.answer) + fp.close() + + +if __name__ == '__main__': + unittest.main() diff --git a/cookbooks/agent_builder.ipynb b/cookbooks/agent_builder.ipynb new file mode 100644 index 000000000..486726ba0 --- /dev/null +++ b/cookbooks/agent_builder.ipynb @@ -0,0 +1,160 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Console AgentBuilder示例\n", + "整体使用流程包括以下两个环节,其中流程1主要在[百度智能云千帆AppBuilder官网](https://cloud.baidu.com/product/AppBuilder)完成,流程2在AppBuilder SDK中以低代码的方式实现:\n", + "1. 官网创建并发布应用、获取应用ID、获取密钥\n", + "2. 初始化AgentBuidler实例、创建会话、上传文档(可选)、执行对话\n", + "\n", + "\n", + "以下分别提供两个样例,快递查询小助手、植物识别小助手来说明使用流程,注意以下流程用到的密钥可在图示位置中获取:\n", + "![配置](./agent_builder_resources/secret.png)\n", + "\n", + "## 1. 快递查询小助手\n", + "\n", + "### 1.1 Console端应用配置与发布\n", + "1. 进入[百度智能云千帆AppBuilder官网](https://cloud.baidu.com/product/AppBuilder),配置智能体指令、选择相应的工具组件\n", + "![配置](./agent_builder_resources/express_assistant.png)\n", + "2. 发布应用\n", + "![配置](./agent_builder_resources/express_assistant_release.png)\n", + "3. 获取应用ID\n", + "4. ![配置](./agent_builder_resources/express_assistant_app_id.png)\n", + "\n", + "\n", + "### 1.2 SDK代码调用示例" + ], + "metadata": { + "collapsed": false + }, + "id": "42eace26869295fb" + }, + { + "cell_type": "raw", + "source": [ + "pip install appbuilder-sdk" + ], + "metadata": { + "collapsed": false + }, + "id": "95aa0ec662d7e71b" + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], + "source": [ + "import appbuilder\n", + "import os\n", + "# 注意以下示例正确运行依赖的条件包括:\n", + "# 1. 在百度智能云千帆AppBuilder官网使用AgentBuilder创建应用且应用已发布\n", + "# 2. 密钥正确有效\n", + "# 3. 密钥需要与发布应用正确对应,即需要使用发布应用的账户下的密钥\n", + "\n", + "# 配置密钥与应用ID\n", + "os.environ[\"APPBUILDER_TOKEN\"] =\"secret_key\"\n", + "app_id = \"35f4fed3-d530-4dad-bc8e-f2150a4450be\"\n", + "\n", + "# 初始化Agent\n", + "agent_builder = appbuilder.AgentBuilder(app_id)\n", + "\n", + "# 创建会话ID\n", + "conversation_id = agent_builder.create_conversation()\n", + "\n", + "# 执行对话\n", + "msg = agent_builder.run(conversation_id, \"我的快递单号是:9858485940100; 请查询下此快递的状态\")\n", + "print(\"快递查询助理回答内容:\", msg.content.answer)\n", + "\n", + "# 执行流式对话\n", + "msg = agent_builder.run(conversation_id, \"使用语音播报快递当前状态\", stream=True)\n", + "for content in msg.content:\n", + " for ev in content.events:\n", + " if ev.content_type == \"audio\":\n", + " print(\"快递查询助理生成的音频播放地址:\", ev.detail[\"audio\"])" + ], + "metadata": { + "collapsed": false, + "is_executing": true + }, + "id": "5b3a8a246cf0b467" + }, + { + "cell_type": "markdown", + "source": [ + "## 2. 植物识别小助手\n", + "\n", + "### 2.1 Console端应用配置与发布\n", + "1. 进入[百度智能云千帆AppBuilder官网](https://cloud.baidu.com/product/AppBuilder),配置智能体指令、选择相应的工具组件\n", + "![配置](./agent_builder_resources/plant_recog_assistant.png)\n", + "2. 发布应用\n", + "![配置](./agent_builder_resources/plant_recog_assistant_release.jpg)\n", + "3. 获取应用ID\n", + "4. ![配置](./agent_builder_resources/plant_recog_assistant_app_id.png)\n", + "\n", + "### 2.2 SDK代码调用示例\n" + ], + "metadata": { + "collapsed": false + }, + "id": "3e462991dab3283d" + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], + "source": [ + "import os\n", + "import appbuilder\n", + "\n", + "# 注意以下示例正确运行依赖的条件包括:\n", + "# 1. 在百度智能云千帆AppBuilder官网使用AgentBuilder创建应用且应用已发布\n", + "# 2. 密钥正确有效\n", + "# 3. 密钥需要与发布的应用正确对应,即需要使用发布应用的账户下的密钥\n", + "\n", + "# 配置密钥与应用ID\n", + "os.environ[\"APPBUILDER_TOKEN\"] =\"...\"\n", + "app_id = \"7016e0d3-451b-4a47-a818-dc0a16d4b496\" \n", + "\n", + "# 初始化Agent实例\n", + "agent_builder = appbuilder.AgentBuilder(\"app_id\")\n", + "\n", + "# 创建会话ID\n", + "conversation_id = agent_builder.create_conversation()\n", + "\n", + "# 上传植物图片\n", + "file_id = agent_builder.upload_local_file(conversation_id, \"./tree.png\" )\n", + "\n", + "# 植物识别\n", + "msg = agent_builder.run(conversation_id, \"请识别图中的植物类别\", file_ids=[file_id])\n", + "print(\"植物识别助理回答内容:\", msg.content.answer)\n" + ], + "metadata": { + "collapsed": false, + "is_executing": true + }, + "id": "4b825feeecbd7a2f" + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/cookbooks/agent_builder_resources/express_assistant.png b/cookbooks/agent_builder_resources/express_assistant.png new file mode 100644 index 000000000..e685ffaa9 Binary files /dev/null and b/cookbooks/agent_builder_resources/express_assistant.png differ diff --git a/cookbooks/agent_builder_resources/express_assistant_app_id.png b/cookbooks/agent_builder_resources/express_assistant_app_id.png new file mode 100644 index 000000000..9ae940dc2 Binary files /dev/null and b/cookbooks/agent_builder_resources/express_assistant_app_id.png differ diff --git a/cookbooks/agent_builder_resources/express_assistant_release.png b/cookbooks/agent_builder_resources/express_assistant_release.png new file mode 100644 index 000000000..8c4f7a33c Binary files /dev/null and b/cookbooks/agent_builder_resources/express_assistant_release.png differ diff --git a/cookbooks/agent_builder_resources/plant_recog_assistant.png b/cookbooks/agent_builder_resources/plant_recog_assistant.png new file mode 100644 index 000000000..5e5955664 Binary files /dev/null and b/cookbooks/agent_builder_resources/plant_recog_assistant.png differ diff --git a/cookbooks/agent_builder_resources/plant_recog_assistant_app_id.png b/cookbooks/agent_builder_resources/plant_recog_assistant_app_id.png new file mode 100644 index 000000000..14e233300 Binary files /dev/null and b/cookbooks/agent_builder_resources/plant_recog_assistant_app_id.png differ diff --git a/cookbooks/agent_builder_resources/plant_recog_assistant_release.jpg b/cookbooks/agent_builder_resources/plant_recog_assistant_release.jpg new file mode 100644 index 000000000..508df0259 Binary files /dev/null and b/cookbooks/agent_builder_resources/plant_recog_assistant_release.jpg differ diff --git a/cookbooks/agent_builder_resources/secret.png b/cookbooks/agent_builder_resources/secret.png new file mode 100644 index 000000000..400f70732 Binary files /dev/null and b/cookbooks/agent_builder_resources/secret.png differ diff --git a/cookbooks/agent_builder_resources/tree.png b/cookbooks/agent_builder_resources/tree.png new file mode 100644 index 000000000..eed2390e4 Binary files /dev/null and b/cookbooks/agent_builder_resources/tree.png differ