From 8c01fb89949728d1a18cc7a9eaf5a71181236614 Mon Sep 17 00:00:00 2001 From: userpj Date: Thu, 26 Dec 2024 20:12:13 +0800 Subject: [PATCH] update --- go/appbuilder/component_client.go | 50 ++++ go/appbuilder/component_client_data.go | 187 ++++++++++++ .../ComponentClientRunRequest.java | 31 ++ .../ComponentClientRunResponse.java | 278 ++++++++++++++++++ .../console/component_client/data_class.py | 30 +- 5 files changed, 556 insertions(+), 20 deletions(-) create mode 100644 java/src/main/java/com/baidubce/appbuilder/model/componentclient/ComponentClientRunRequest.java create mode 100644 java/src/main/java/com/baidubce/appbuilder/model/componentclient/ComponentClientRunResponse.java diff --git a/go/appbuilder/component_client.go b/go/appbuilder/component_client.go index cf5a34d1..e18cb2f1 100644 --- a/go/appbuilder/component_client.go +++ b/go/appbuilder/component_client.go @@ -15,8 +15,13 @@ package appbuilder import ( + "bufio" + "bytes" + "encoding/json" "errors" + "fmt" "net/http" + "strings" "time" ) @@ -35,3 +40,48 @@ func NewComponentClient(config *SDKConfig) (*ComponentClient, error) { } return &ComponentClient{sdkConfig: config, client: client}, nil } + +func (t *ComponentClient) Run(component, version, action string, req ComponentRunRequest) (ComponentClientIterator, error) { + request := http.Request{} + + urlSuffix := fmt.Sprintf("/components/%s", component) + if version != "" { + urlSuffix += fmt.Sprintf("/version/%s", version) + } + if action != "" { + if strings.Contains(urlSuffix, "?") { + urlSuffix += fmt.Sprintf("&action=%s", action) + } else { + urlSuffix += fmt.Sprintf("?action=%s", action) + } + } + + serviceURL, err := t.sdkConfig.ServiceURLV2(urlSuffix) + if err != nil { + return nil, err + } + + header := t.sdkConfig.AuthHeaderV2() + request.URL = serviceURL + request.Method = "POST" + header.Set("Content-Type", "application/json") + request.Header = header + data, _ := json.Marshal(req) + request.Body = NopCloser(bytes.NewReader(data)) + request.ContentLength = int64(len(data)) // 手动设置长度 + + t.sdkConfig.BuildCurlCommand(&request) + resp, err := t.client.Do(&request) + if err != nil { + return nil, err + } + requestID, err := checkHTTPResponse(resp) + if err != nil { + return nil, fmt.Errorf("requestID=%s, err=%v", requestID, err) + } + r := NewSSEReader(1024*1024, bufio.NewReader(resp.Body)) + if req.Stream { + return &ComponentClientStreamIterator{requestID: requestID, r: r, body: resp.Body}, nil + } + return &ComponentClientOnceIterator{body: resp.Body}, nil +} diff --git a/go/appbuilder/component_client_data.go b/go/appbuilder/component_client_data.go index 4cbec095..8215c336 100644 --- a/go/appbuilder/component_client_data.go +++ b/go/appbuilder/component_client_data.go @@ -14,3 +14,190 @@ package appbuilder +import ( + "encoding/json" + "fmt" + "io" + "strings" +) + +const ( + SysOriginQuery = "_sys_origin_query" + SysFileUrls = "_sys_file_urls" + SysConversationID = "_sys_conversation_id" + SysEndUserID = "_sys_end_user_id" + SysChatHistory = "_sys_chat_history" +) + +type ComponentRunRequest struct { + Stream bool `json:"stream"` + Parameters map[string]any `json:"parameters"` +} + +type Message struct { + Role string `json:"role"` + Content string `json:"content"` +} + +type ComponentRunResponse struct { + RequestID string `json:"request_id"` + Code string `json:"code"` + Message string `json:"message"` + Data ComponentRunResponseData `json:"data"` +} + +type ComponentRunResponseData struct { + ConversationID string `json:"conversation_id"` + MessageID string `json:"message_id"` + TraceID string `json:"trace_id"` + UserID string `json:"user_id"` + EndUserID string `json:"end_user_id"` + IsCompletion bool `json:"is_completion"` + ComponentOutput ComponentOutput `json:"component_output"` +} + +type ComponentOutput struct { + Role string `json:"role"` + Content []Content `json:"content"` +} + +type Content struct { + Name string `json:"name"` + VisibleScope string `json:"visible_scope"` + RawData map[string]any `json:"raw_data"` + Usage map[string]any `json:"usage"` + Metrics map[string]any `json:"metrics"` + Type string `json:"type"` + Text map[string]any `json:"text"` + Event ComponentEvent `json:"event"` +} + +type ComponentEvent struct { + ID string `json:"id"` + Status string `json:"status"` + Name string `json:"name"` + CreatedTime string `json:"created_time"` + ErrorCode string `json:"error_code"` + ErrorMessage string `json:"error_message"` +} + +type Text struct { + Info string `json:"info"` +} + +type Code struct { + Code string `json:"code"` +} + +type Files struct { + Filename string `json:"filename"` + Url string `json:"url"` +} + +type Urls struct { + Url string `json:"url"` +} + +type OralText struct { + Info string `json:"info"` +} + +type References struct { + Type string `json:"type"` + Source string `json:"source"` + DocID string `json:"doc_id"` + Title string `json:"title"` + Content string `json:"content"` + Extra map[string]any `json:"extra"` +} + +type Image struct { + Filename string `json:"filename"` + Url string `json:"url"` + Byte []byte `json:"byte"` +} + +type Chart struct { + Type string `json:"type"` + Data string `json:"data"` +} + +type Audio struct { + Filename string `json:"filename"` + Url string `json:"url"` + Byte []byte `json:"byte"` +} + +type PlanStep struct { + Name string `json:"name"` + Arguments map[string]any `json:"arguments"` + Thought string `json:"thought"` +} + +type Plan struct { + Detail string `json:"detail"` + Steps []PlanStep `json:"steps"` +} + +type FunctionCall struct { + Thought string `json:"thought"` + Name string `json:"name"` + Arguments map[string]any `json:"arguments"` +} + +type Json struct { + Data string `json:"data"` +} + +type ComponentClientIterator interface { + // Next 获取处理结果,如果返回error不为空,迭代器自动失效,不允许再调用此方法 + Next() (*ComponentRunResponseData, error) +} + +type ComponentClientStreamIterator struct { + requestID string + r *sseReader + body io.ReadCloser +} + +func (t *ComponentClientStreamIterator) Next() (*ComponentRunResponseData, error) { + data, err := t.r.ReadMessageLine() + if err != nil && !(err == io.EOF) { + t.body.Close() + return nil, fmt.Errorf("requestID=%s, err=%v", t.requestID, err) + } + if err != nil && err == io.EOF { + t.body.Close() + return nil, err + } + if strings.HasPrefix(string(data), "data:") { + var resp ComponentRunResponse + if err := json.Unmarshal(data[5:], &resp); err != nil { + t.body.Close() + return nil, fmt.Errorf("requestID=%s, err=%v", t.requestID, err) + } + return &resp.Data, nil + } + // 非SSE格式关闭连接,并返回数据 + t.body.Close() + return nil, fmt.Errorf("requestID=%s, body=%s", t.requestID, string(data)) +} + +// ComponentClientOnceIterator 非流式返回时对应的迭代器,只可迭代一次 +type ComponentClientOnceIterator struct { + body io.ReadCloser + requestID string +} + +func (t *ComponentClientOnceIterator) Next() (*ComponentRunResponseData, error) { + data, err := io.ReadAll(t.body) + if err != nil { + return nil, fmt.Errorf("requestID=%s, err=%v", t.requestID, err) + } + defer t.body.Close() + var resp ComponentRunResponse + if err := json.Unmarshal(data, &resp); err != nil { + return nil, fmt.Errorf("requestID=%s, err=%v", t.requestID, err) + } + return &resp.Data, nil +} diff --git a/java/src/main/java/com/baidubce/appbuilder/model/componentclient/ComponentClientRunRequest.java b/java/src/main/java/com/baidubce/appbuilder/model/componentclient/ComponentClientRunRequest.java new file mode 100644 index 00000000..f9d10a86 --- /dev/null +++ b/java/src/main/java/com/baidubce/appbuilder/model/componentclient/ComponentClientRunRequest.java @@ -0,0 +1,31 @@ +package com.baidubce.appbuilder.model.componentclient; + +import java.util.HashMap; +import java.util.Map; + +public class ComponentClientRunRequest { + public static final String SysOriginQuery = "_sys_origin_query"; + public static final String SysFileUrls = "_sys_file_urls"; + public static final String SysConversationID = "_sys_conversation_id"; + public static final String SysEndUserID = "_sys_end_user_id"; + public static final String SysChatHistory = "_sys_chat_history"; + + private boolean stream; + private Map parameters = new HashMap<>(); + + public boolean isStream() { + return stream; + } + + public void setStream(boolean stream) { + this.stream = stream; + } + + public Map getParameters() { + return parameters; + } + + public void setParameters(Map parameters) { + this.parameters = parameters; + } +} diff --git a/java/src/main/java/com/baidubce/appbuilder/model/componentclient/ComponentClientRunResponse.java b/java/src/main/java/com/baidubce/appbuilder/model/componentclient/ComponentClientRunResponse.java new file mode 100644 index 00000000..3c08df96 --- /dev/null +++ b/java/src/main/java/com/baidubce/appbuilder/model/componentclient/ComponentClientRunResponse.java @@ -0,0 +1,278 @@ +package com.baidubce.appbuilder.model.componentclient; + +import java.util.Map; + +import com.google.gson.annotations.SerializedName; + +import java.util.HashMap; + +public class ComponentClientRunResponse { + @SerializedName("request_id") + private String requestID; + private String code; + private String message; + private ComponentRunResponseData data; + + public String getRequestID() { + return requestID; + } + + public void setRequestID(String requestID) { + this.requestID = requestID; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public ComponentRunResponseData getData() { + return data; + } + + public void setData(ComponentRunResponseData data) { + this.data = data; + } + + public static class ComponentRunResponseData { + @SerializedName("conversation_id") + private String conversationID; + @SerializedName("message_id") + private String messageID; + @SerializedName("trace_id") + private String traceID; + @SerializedName("user_id") + private String userID; + @SerializedName("end_user_id") + private String endUserID; + @SerializedName("is_completion") + private boolean isCompletion; + @SerializedName("component_output") + private ComponentOutput componentOutput; + + public String getConversationID() { + return conversationID; + } + + public void setConversationID(String conversationID) { + this.conversationID = conversationID; + } + + public String getMessageID() { + return messageID; + } + + public void setMessageID(String messageID) { + this.messageID = messageID; + } + + public String getTraceID() { + return traceID; + } + + public void setTraceID(String traceID) { + this.traceID = traceID; + } + + public String getUserID() { + return userID; + } + + public void setUserID(String userID) { + this.userID = userID; + } + + public String getEndUserID() { + return endUserID; + } + + public void setEndUserID(String endUserID) { + this.endUserID = endUserID; + } + + public boolean isCompletion() { + return isCompletion; + } + + public void setCompletion(boolean completion) { + isCompletion = completion; + } + + public ComponentOutput getComponentOutput() { + return componentOutput; + } + + public void setComponentOutput(ComponentOutput componentOutput) { + this.componentOutput = componentOutput; + } + + public static class ComponentOutput { + private String role; + private Content content; + + public String getRole() { + return role; + } + + public void setRole(String role) { + this.role = role; + } + + public Content getContent() { + return content; + } + + public void setContent(Content content) { + this.content = content; + } + + public static class Content { + private String name; + @SerializedName("visible_scope") + private String visibleScope; + @SerializedName("raw_data") + private Map rawData = new HashMap<>(); + private Map usage = new HashMap<>(); + private Map metrics = new HashMap<>(); + private String type; + private Map text = new HashMap<>(); + private ComponentEvent event; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getVisibleScope() { + return visibleScope; + } + + public void setVisibleScope(String visibleScope) { + this.visibleScope = visibleScope; + } + + public Map getRawData() { + return rawData; + } + + public void setRawData(Map rawData) { + this.rawData = rawData; + } + + public Map getUsage() { + return usage; + } + + public void setUsage(Map usage) { + this.usage = usage; + } + + public Map getMetrics() { + return metrics; + } + + public void setMetrics(Map metrics) { + this.metrics = metrics; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Map getText() { + return text; + } + + public void setText(Map text) { + this.text = text; + } + + public ComponentEvent getEvent() { + return event; + } + + public void setEvent(ComponentEvent event) { + this.event = event; + } + + public static class ComponentEvent { + private String id; + private String status; + private String name; + @SerializedName("created_time") + private String createdTime; + @SerializedName("error_code") + private String errorCode; + @SerializedName("error_message") + private String errorMessage; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCreatedTime() { + return createdTime; + } + + public void setCreatedTime(String createdTime) { + this.createdTime = createdTime; + } + + public String getErrorCode() { + return errorCode; + } + + public void setErrorCode(String errorCode) { + this.errorCode = errorCode; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + } + } + } + } +} \ No newline at end of file diff --git a/python/core/console/component_client/data_class.py b/python/core/console/component_client/data_class.py index a01d53c5..5761c556 100644 --- a/python/core/console/component_client/data_class.py +++ b/python/core/console/component_client/data_class.py @@ -20,7 +20,7 @@ class RunRequest(BaseModel): """ Component Run方法请求体 """ - class Parameters(BaseModel): + class Parameters(BaseModel, extra="allow"): """ Parameters""" class Message(BaseModel): """ Message""" @@ -32,7 +32,7 @@ class Message(BaseModel): ) sys_file_urls: Optional[dict] = Field( None, - description='{"xxx.pdf": "http:///"},画布中开始节点的系统参数fileUrls', alias="sys_file_urls" + description='{"xxx.pdf": "http:///"},画布中开始节点的系统参数fileUrls', alias="_sys_file_urls" ) sys_conversation_id: Optional[str] = Field( None, @@ -45,18 +45,11 @@ class Message(BaseModel): None, description="聊天历史记录", alias="_sys_chat_history" ) - class Config: - """ - Config Class - """ - - extra = "allow" - stream: bool = Field(default=False, description='是否流式返回') parameters: Parameters = Field(..., description="调用传参") -class Content(Content): +class ContentWithEvent(Content): """ ContentWithEvent """ class Event(BaseModel): @@ -84,25 +77,22 @@ class Event(BaseModel): event: Event = Field(..., description="事件信息") -class ComponentOutput(ComponentOutput): - content: list[Content] = Field( - None, - description="当前组件返回内容的主要payload,List[ContentWithEvent],每个 Content 包括了当前 event 的一个元素", - ) - - class RunResponse(BaseModel): """ Component Run方法响应体 """ - class Data(ComponentOutput): - """ Data """ + class RunOutput(ComponentOutput): + """ RunOutput """ 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="是否完成") + content: list[ContentWithEvent] = Field( + None, + description="当前组件返回内容的主要payload,List[ContentWithEvent],每个 Content 包括了当前 event 的一个元素", + ) request_id: str = Field(..., description="请求id") code: str = Field(None, description="响应码") message: str = Field(None, description="响应消息") - data: Data = Field(..., description="响应数据") + data: RunOutput = Field(..., description="响应数据")