Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support assistant sdk #251

Merged
merged 34 commits into from
Apr 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
3862127
add base code
MrChengmo Apr 10, 2024
74adfb3
update 0409 base code
MrChengmo Apr 10, 2024
35baaab
update
MrChengmo Apr 11, 2024
f2c0f1c
update for tiny job
MrChengmo Apr 11, 2024
b11cbf6
finish basic code
MrChengmo Apr 13, 2024
1eb415f
add ut
MrChengmo Apr 13, 2024
d7b1186
update ut
MrChengmo Apr 13, 2024
83a52e5
update funccall ut
MrChengmo Apr 15, 2024
f142263
update folder structure
MrChengmo Apr 19, 2024
a131a13
del assistants folder
MrChengmo Apr 19, 2024
715ac37
refactor
MrChengmo Apr 19, 2024
3c86929
finish assistant api
MrChengmo Apr 19, 2024
3dedc05
finish files py
MrChengmo Apr 21, 2024
37374ca
update
MrChengmo Apr 21, 2024
0cda38b
update ut
MrChengmo Apr 22, 2024
d1cdc0d
update ut for import and assistants
MrChengmo Apr 22, 2024
8c4394f
finish ut
MrChengmo Apr 22, 2024
218f6e2
code clean
MrChengmo Apr 22, 2024
507412b
update doc
MrChengmo Apr 23, 2024
6264aaf
update
MrChengmo Apr 23, 2024
4d7791c
update cookboog
MrChengmo Apr 23, 2024
71d417b
update doc
MrChengmo Apr 23, 2024
9fcc5cb
update function call
MrChengmo Apr 23, 2024
e42be98
update assistant response
MrChengmo Apr 25, 2024
e872424
update ut
MrChengmo Apr 25, 2024
8777361
finish ut
MrChengmo Apr 25, 2024
1018605
add instruction default value
MrChengmo Apr 25, 2024
1937b93
update assitant
MrChengmo Apr 25, 2024
d3db164
update header
MrChengmo Apr 28, 2024
6bc30e4
update cookbook
MrChengmo Apr 28, 2024
20f03e7
update ut
MrChengmo Apr 29, 2024
a4e27d4
update
MrChengmo Apr 29, 2024
1a5d839
update cookbook file
MrChengmo Apr 29, 2024
ef7a0fd
simple ut
MrChengmo Apr 29, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ jobs:
runs-on: ubuntu-latest
env:
APPBUILDER_TOKEN: bce-v3/ALTAK-RPJR9XSOVFl6mb5GxHbfU/072be74731e368d8bbb628a8941ec50aaeba01cd
APPBUILDER_TOKEN_V2: bce-v3/ALTAK-zX2OwTWGE9JxXSKxcBYQp/7dd073d9129c01c617ef76d8b7220a74835eb2f4
strategy:
fail-fast: false
matrix:
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ AppBuilder SDK面向开发者提供AI原生应用一站式开发工具,包括
* **2024.03.13 v0.4.1版本发布** [ReleaseNote](https://github.com/baidubce/app-builder/releases/tag/0.4.1)
* 支持以下功能进行FunctionCall调用:动植物识别、表格文字识别、条形码及二维码识别、身份证混贴识别、手写文字识别、text2image、excel2figure
* **2024.03.20 v0.5.0版本发布** [ReleaseNote](https://github.com/baidubce/app-builder/releases/tag/0.5.0)
* AppBuilderClient ConsoleSDK发布 [Agent调用CookBook](https://github.com/baidubce/app-builder/blob/0.5.0/cookbooks/app_builder_client.ipynb)
* AppBuilderClient SDK发布 [App调用CookBook](./cookbooks/agent_builder.ipynb)
* AI能力引擎组件新增:向量检索-VDB
* 支持以下功能进行FunctionCall调用并新增[CookBook](https://github.com/baidubce/app-builder/blob/master/cookbooks/general_ocr.ipynb):文本翻译-通用版、通用物体和场景识别-高级版、通用文字识别-高精度版、短语音识别-极速版
* **2024.03.21 v0.5.1版本发布** [ReleaseNote](https://github.com/baidubce/app-builder/releases/tag/0.5.1)
* 问题修复:修复了在Python 3.8 及以下环境无法使用AppBuilderClient ConsoleSDK的问题。同时,在即将发布的0.6.0版本中,将不再提供对Python 3.8及以下环境的支持,请升级Python版本到3.9
* **2024.04.12 v0.6.0版本发布** [ReleaseNote](https://github.com/baidubce/app-builder/releases/tag/0.6.0)
* AppBuilder Console SDK 支持 JAVA 语言 [AppBuilder Java ConsoleSDK](./java/README.md)
* AppBuilder Console SDK 支持 GO 语言 [AppBuilder GO ConsoleSDK](./go/README.md)
* AppBuilder Client SDK 支持 JAVA 语言
* AppBuilder Client SDK 支持 GO 语言
* 首页README更新,提供免费的公共试用TOKEN,方便开发者快速体验

## 教程与文档
Expand Down
4 changes: 4 additions & 0 deletions appbuilder/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ def get_default_header():
AppBuilderServerException,
)

from appbuilder.core.assistant.base import assistant

__all__ = [
'logger',

Expand Down Expand Up @@ -178,4 +180,6 @@ def get_default_header():
"MixCardOCR",
"AppBuilderClient",
"AgentBuilder",

"assistant",
]
72 changes: 67 additions & 5 deletions appbuilder/core/_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ def __init__(self,
返回:
"""
self.secret_key = secret_key if secret_key else os.getenv("APPBUILDER_TOKEN", "")
self.secret_key = secret_key if secret_key else os.getenv(
"APPBUILDER_TOKEN", "")
if not self.secret_key:
raise ValueError("secret_key is empty, please pass a nonempty secret_key "
"or set a secret_key in environment variable")
Expand Down Expand Up @@ -122,7 +123,8 @@ def check_response_json(data: dict):
:rtype: str.
"""
if "code" in data and "message" in data and "requestId" in data:
raise AppBuilderServerException(data["requestId"], data["code"], data["message"])
raise AppBuilderServerException(
data["requestId"], data["code"], data["message"])

@staticmethod
def check_console_response(response: requests.Response):
Expand All @@ -133,7 +135,8 @@ def check_console_response(response: requests.Response):
data = response.json()
if "code" in data and data.get("code") != 0:
requestId = __class__.response_request_id(response)
raise AppBuilderServerException(requestId, data["code"], data["message"])
raise AppBuilderServerException(
requestId, data["code"], data["message"])

def auth_header(self):
r"""auth_header is a helper method return auth info"""
Expand Down Expand Up @@ -161,10 +164,69 @@ def check_param(func):
def inner(*args, **kwargs):
retry = kwargs.get("retry", 0)
if retry < 0 or not isinstance(retry, int):
raise InvalidRequestArgumentError("retry must be int and bigger then zero")
raise InvalidRequestArgumentError(
"retry must be int and bigger then zero")
timeout = kwargs.get("timeout", None)
if timeout and not (isinstance(timeout, float) or isinstance(timeout, tuple)):
raise InvalidRequestArgumentError("timeout must be float or tuple of float")
raise InvalidRequestArgumentError(
"timeout must be float or tuple of float")
return func(*args, **kwargs)

return inner


class AssistantHTTPClient(HTTPClient):
def service_url(self, sub_path: str, prefix: str = None):
"""
根据给定的子路径和前缀,返回完整的服务URL。

Args:
sub_path (str): 子路径,例如 "/api/v1/user"。
prefix (str, optional): URL前缀,例如 "http://example.com"。默认为None。

Returns:
str: 完整的服务URL,例如 "http://example.com/api/v1/user"。
"""
prefix = prefix if prefix else ""
return self.gateway + prefix + sub_path

def auth_header(self):
"""
返回一个包含认证信息的字典

Args:
无参数。
"""
r"""auth_header is a helper method return auth info"""
auth_header = get_default_header()
auth_header["Authorization"] = self.secret_key
auth_header["X-Appbuilder-Request-Id"] = str(uuid.uuid4())
auth_header["X-Appbuilder-Authorization"] = self.secret_key
auth_header["Content-Type"] = "application/json"
logger.debug("Request header: {}\n".format(auth_header))
return auth_header

@staticmethod
def check_assistant_response(request_id, data):
"""
检查助手的响应结果,如果返回了错误信息,则抛出 AssistantServerException 异常。

Args:
request_id (str): 请求 ID。
data (dict): 助手返回的响应数据。

Returns:
None

Raises:
AssistantServerException: 如果助手返回了错误信息,则抛出该异常。

"""
if 'error' in data:
raise AssistantServerException(
request_id=request_id,
code=data['error']['code'],
message=data['error']['message'],
type=data['error']['type'],
params=data['error']['param'] if 'param' in data['error'] else data['error']['params'],
)
14 changes: 14 additions & 0 deletions appbuilder/core/_exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,20 @@ def __init__(self, request_id="", code="", message="", service_err_code="", serv
def __str__(self):
return self.description

class AssistantServerException(BaseRPCException):
r"""AssistantSercerException represent assistant server failed response.
"""
description: str = "Interal Server Error"
code: int = 500

def __init__(self, request_id= "", code="", message="", type="", params=""):
self.description = "request_id={}, code={}, message={}, type={}, params={} ".format(
request_id, code, message, type, params)
self.code = code if code else self.code

def __str__(self):
return self.description


class InvalidRequestArgumentError(BaseRPCException):
r"""InvalidRequestArgumentError invalid request param
Expand Down
13 changes: 13 additions & 0 deletions appbuilder/core/assistant/__init__.py
Original file line number Diff line number Diff line change
@@ -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.
26 changes: 26 additions & 0 deletions appbuilder/core/assistant/assistants/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# 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 .assistants import (
Assistants
)

from .files import (
Files
)

__all__ = [
'Assistants',
'Files',
]
96 changes: 96 additions & 0 deletions appbuilder/core/assistant/assistants/assistants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# 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.
import os
from typing import Optional
from appbuilder.core.assistant.type import assistant_type
from appbuilder.utils.collector import Collector
from appbuilder.utils.collector import AssistantKeys
from appbuilder.core._client import AssistantHTTPClient
from appbuilder.core.assistant.assistants.files import Files


class Assistants(object):
def __init__(self):
self._http_client = AssistantHTTPClient()

@property
def files(self):
return Files()


def create(self,
name: str,
description: str,
assistant_id: Optional[str] = "",
model: Optional[str] = "ERNIE-4.0-8K",
response_format: Optional[str] = 'text',
instructions: Optional[str] = "你是百度制作的AI助手",
thought_instructions: Optional[str] = "",
chat_instructions: Optional[str] = "",
tools: Optional[list[assistant_type.AssistantTool]] = [],
file_ids: Optional[list[str]] = [],
metadata: Optional[dict] = {},
) -> assistant_type.AssistantCreateResponse:
"""
创建助手实例

Args:
name (str): 助手名称
description (str): 助手描述
assistant_id (Optional[str], optional): 助手ID. Defaults to "".
model (Optional[str], optional): 模型名称. Defaults to "ERNIE-4.0-8K".
response_format (Optional[str], optional): 响应格式. Defaults to 'text'.
instructions (Optional[str], optional): 指令. Defaults to "".
thought_instructions (Optional[str], optional): 思考指令. Defaults to "".
chat_instructions (Optional[str], optional): 聊天指令. Defaults to "".
tools (Optional[list[assistant_type.AssistantTool]], optional): 工具列表. Defaults to [].
file_ids (Optional[list[str]], optional): 文件ID列表. Defaults to [].
metadata (Optional[dict], optional): 元数据. Defaults to {}.

Returns:
assistant_type.AssistantCreateResponse: 助手创建响应

"""
headers = self._http_client.auth_header()
url = self._http_client.service_url("/v2/assistants")

req = assistant_type.AssistantCreateRequest(
name=name,
description=description,
assistant_id=assistant_id,
model=model,
response_format=response_format,
instructions=instructions,
thought_instructions=thought_instructions,
chat_instructions=chat_instructions,
tools=tools,
file_ids=file_ids,
metadata=metadata,
)

response = self._http_client.session.post(
url=url,
headers=headers,
json=req.model_dump(),
timeout=None
)
self._http_client.check_response_header(response)

data = response.json()
request_id = self._http_client.response_request_id(response)
self._http_client.check_assistant_response(request_id, data)

resp = assistant_type.AssistantCreateResponse(**data)
Collector().add_to_collection(AssistantKeys.ASSISTANT, resp, resp.id)
return resp
70 changes: 70 additions & 0 deletions appbuilder/core/assistant/assistants/files.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# 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.

# -*- coding: utf-8 -*-


import os
import json
from appbuilder.core.assistant.type import assistant_type
from appbuilder.core._client import AssistantHTTPClient


class Files(object):
def __init__(self):
self._http_client = AssistantHTTPClient()

def create(self, file_path: str, purpose: str = "assistant") -> assistant_type.AssistantFilesCreateResponse:
"""
上传文件到助理存储中。

Args:
file_path (str): 要上传的文件路径。
purpose (str, optional): 上传文件的用途。默认为 "assistant"。

Returns:
assistant_type.AssistantFilesCreateResponse: 上传文件后返回的响应对象。

Raises:
ValueError: 如果指定的文件路径不存在,则会引发此异常。
"""
headers = self._http_client.auth_header()
headers.pop("Content-Type")
url = self._http_client.service_url("/v2/storage/files")

if not os.path.exists(file_path):
raise ValueError("File {} not exists".format(file_path))

with open(file_path, 'rb') as f:
files = [
('file',(os.path.basename(file_path), f))
]

response = self._http_client.session.post(
url,
headers=headers,
files=files,
params={
'purpose': purpose
}
)

self._http_client.check_response_header(response)

request_id = self._http_client.response_request_id(response)
data = response.json()

self._http_client.check_assistant_response(request_id, data)
resp = assistant_type.AssistantFilesCreateResponse(**data)
return resp
Loading
Loading