From 8330ae93a912a4085d17fb3ea431bcb6e09743a3 Mon Sep 17 00:00:00 2001 From: userpj Date: Thu, 26 Dec 2024 17:04:54 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=84=E4=BB=B6=E5=A2=9E=E5=8A=A0sdk?= =?UTF-8?q?=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- python/__init__.py | 2 + .../core/console/component_client/__init__.py | 15 ++ .../component_client/component_client.py | 78 ++++++++++ .../console/component_client/data_class.py | 138 ++++++++++++++++++ 4 files changed, 233 insertions(+) create mode 100644 python/core/console/component_client/__init__.py create mode 100644 python/core/console/component_client/component_client.py create mode 100644 python/core/console/component_client/data_class.py diff --git a/python/__init__.py b/python/__init__.py index 432ae035..09fb670a 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -181,6 +181,7 @@ def get_default_header(): from appbuilder.core.console.appbuilder_client.async_appbuilder_client import AsyncAppBuilderClient from appbuilder.core.console.appbuilder_client.appbuilder_client import AgentBuilder from appbuilder.core.console.appbuilder_client.appbuilder_client import get_app_list, get_all_apps, describe_apps +from appbuilder.core.console.component_client.component_client import ComponentClient from appbuilder.core.console.knowledge_base.knowledge_base import KnowledgeBase from appbuilder.core.console.knowledge_base.data_class import CustomProcessRule, DocumentSource, DocumentChoices, DocumentChunker, DocumentSeparator, DocumentPattern, DocumentProcessOption @@ -218,6 +219,7 @@ def get_default_header(): "AppBuilderClient", "AsyncAppBuilderClient", "AgentBuilder", + "ComponentClient", "get_app_list", "get_all_apps", "describe_apps", diff --git a/python/core/console/component_client/__init__.py b/python/core/console/component_client/__init__.py new file mode 100644 index 00000000..15375537 --- /dev/null +++ b/python/core/console/component_client/__init__.py @@ -0,0 +1,15 @@ +# 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 .component_client import ComponentClient \ No newline at end of file diff --git a/python/core/console/component_client/component_client.py b/python/core/console/component_client/component_client.py new file mode 100644 index 00000000..ff3d4865 --- /dev/null +++ b/python/core/console/component_client/component_client.py @@ -0,0 +1,78 @@ +# 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 appbuilder.core.component import Component +from appbuilder.core.console.component_client import data_class +from appbuilder.utils.logger_util import logger +from appbuilder.utils.trace.tracer_wrapper import client_tool_trace + + +class ComponentClient(Component): + def __init__(self, **kwargs): + r"""初始化智能体应用 + + Returns: + response (obj: `ComponentClient`): 组件实例 + """ + super().__init__(**kwargs) + + @client_tool_trace + def run( + self, + component: str, + sys_origin_query: str, + version: str = None, + action: str = None, + stream: bool = False, + sys_file_urls: dict = None, + sys_conversation_id: str = None, + sys_end_user_id: str = None, + sys_chat_history: list = None, + **kwargs, + ) -> data_class.RunResponse: + headers = self.http_client.auth_header_v2() + headers["Content-Type"] = "application/json" + + url_suffix = f"/components/{component}" + if version is not None: + url_suffix += f"/version/{version}" + if action is not None: + url_suffix += f"?action={action}" + url = self.http_client.service_url_v2(url_suffix) + + all_params = { + '_sys_origin_query': sys_origin_query, + '_sys_file_urls': sys_file_urls, + '_sys_conversation_id': sys_conversation_id, + '_sys_chat_history': sys_chat_history, + '_sys_end_user_id': sys_end_user_id, + **kwargs + } + parameters = data_class.RunRequest.Parameters(**all_params) + request = data_class.RunRequest( + stream=stream, + parameters=parameters, + ) + + response = self.http_client.session.post( + url, + headers=headers, + json=request.model_dump(exclude_none=True, by_alias=True), + timeout=None, + ) + self.http_client.check_response_header(response) + data = response.json() + resp = data_class.RunResponse(**data) + return resp diff --git a/python/core/console/component_client/data_class.py b/python/core/console/component_client/data_class.py new file mode 100644 index 00000000..c8842011 --- /dev/null +++ b/python/core/console/component_client/data_class.py @@ -0,0 +1,138 @@ +# 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 pydantic import Field +from typing import Optional + + +class RunRequest(BaseModel): + """ Component Run方法请求体 """ + class Parameters(BaseModel): + """ Parameters""" + class Message(BaseModel): + """ Message""" + role: str = Field(..., description="对话角色,枚举:user、assistant") + content: str = Field(..., description="对话内容") + + sys_origin_query: str = Field( + ..., description="用户query文字,画布中开始节点的系统参数rawQuery", alias="_sys_origin_query" + ) + sys_file_urls: Optional[dict] = Field( + None, + description='{"xxx.pdf": "http:///"},画布中开始节点的系统参数fileUrls', alias="sys_file_urls" + ) + sys_conversation_id: Optional[str] = Field( + None, + description="对话id,可通过新建会话接口创建, 画布中开始节点的系统参数conversationId", alias="_sys_conversation_id" + ) + sys_end_user_id: Optional[str] = Field( + None, description="终端用户id,画布中开始节点的系统参数end_user_id", alias="_sys_end_user_id" + ) + sys_chat_history: Optional[list[Message]] = Field( + None, description="聊天历史记录", alias="_sys_chat_history" + ) + + class Config: + """ + Config Class + """ + + extra = "allow" + + stream: bool = Field(default=False, description='是否流式返回') + parameters: Parameters = Field(..., description="调用传参") + + +class RunResponse(BaseModel): + """ Component Run方法响应体 """ + class Data(BaseModel): + """ Data """ + + class Content(BaseModel): + """ Content """ + + class Usage(BaseModel): + """ Usage""" + prompt_tokens: int = Field(..., description="prompt token消耗") + completion_tokens: int = Field(..., description="问答返回消耗") + total_tokens: int = Field(..., description="总token消耗") + nodes: list[dict] = Field(None, description="工作流节点消耗情况") + + class Metrics(BaseModel): + """ Metrics""" + begin_time: str = Field( + ..., description="请求开始时间,示例:”2000-01-01T10:00:00.560430“" + ) + duration: float = Field( + ..., description="从请求到当前event总耗时,保留3位有效数字,单位秒s" + ) + + class Event(BaseModel): + """ Event""" + id: str = Field(..., description="事件id") + status: str = Field(..., + description="事件状态,枚举:preparing、running、error、done") + name: str = Field( + ..., + description="事件名,相当于调用的深度,深度与前端的渲染逻辑有关系", + ) + created_time: str = Field( + ..., + description="当前event发送时间", + ) + error_code: str = Field( + None, + description="错误码", + ) + error_message: str = Field( + None, + description="错误信息", + ) + + type: str = Field( + ..., + description="代表event 类型, text、json、code、files、urls、oral_text、references、image、chart、audio、function_call", + ) + name: str = Field(..., description="当前内容名称") + text: dict = Field( + ..., + description="代表当前 event 元素的内容,每一种 event 对应的 text 结构固定", + ) + visible_scope: str = Field( + ..., + description="为了界面展示明确的说明字段,枚举: all、llm、user、空", + ) + usage: Usage = Field( + None, description="大模型的token使用情况" + ) + metrics: Metrics = Field(..., description="耗时信息") + event: Event = Field(..., description="事件信息") + + conversation_id: str = Field(..., description="对话id") + message_id: str = Field(..., description="消息id") + trace_id: str = Field(..., description="追踪id") + user_id: str = Field(..., description="开发者UUID(计费依赖)") + end_user_id: str = Field(None, description="终端用户id") + is_completion: bool = Field(..., description="是否完成") + role: str = Field(..., description="当前消息来源,默认tool") + content: list[Content] = Field( + None, + description="当前组件返回内容的主要payload,List[Content],每个 Content 包括了当前 event 的一个元素,具体见下文Content对象定义", + ) + + request_id: str = Field(..., description="请求id") + code: str = Field(None, description="响应码") + message: str = Field(None, description="响应消息") + data: Data = Field(..., description="响应数据")