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

一系列更新 #169

Merged
merged 9 commits into from
Mar 13, 2024
15 changes: 8 additions & 7 deletions appbuilder/core/_exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,16 @@ class TypeNotSupportedException(BaseRPCException):
class AppBuilderServerException(BaseRPCException):
r"""AppBuilderServerException represent backend server failed response.
"""
description: str = "Interal Server Error"
code: int = 500

def __init__(self, request_id="", code="", message="", service_err_code="", service_err_message=""):
r"""__init__ a AppBuilderServerException instance.
:param request_id: str, request unique id.
:param code: str, backend .
:rtype:
"""
super().__init__("request_id={}, code={}, message={}, service_err_code={}, service_err_message={} ".format(
request_id, code, message, service_err_code, service_err_message))
self.description = "request_id={}, code={}, message={}, service_err_code={}, service_err_message={} ".format(
request_id, code, message, service_err_code, service_err_message)
self.code = code if code else self.code

def __str__(self):
return self.description


class InvalidRequestArgumentError(BaseRPCException):
Expand Down
30 changes: 15 additions & 15 deletions appbuilder/core/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
import copy
import os
import logging
import uuid
Expand Down Expand Up @@ -246,7 +247,11 @@ def warp():
app_builder_token = request.headers["X-Appbuilder-Token"]
self.component.set_secret_key_and_gateway(secret_key=app_builder_token)
except appbuilder.core._exception.BaseRPCException as e:
logging.error(f"failed to verify. err={e}", exc_info=True)
raise BadRequest("X-Appbuilder-Token invalid")
except Exception as e:
logging.error(f"failed to verify. err={e}", exc_info=True)
raise e
else:
pass

Expand Down Expand Up @@ -276,34 +281,29 @@ def warp():
def gen_sse_resp(stream_message):
with app.app_context():
try:
iterator = iter(stream_message.content)
prev_result = {
"content": next(iterator),
"extra": stream_message.extra if hasattr(stream_message, "extra") else {},
"token_usage": stream_message.token_usage if hasattr(stream_message, "token_usage") else {},
}
for sub_content in iterator:
content_iterator = iter(stream_message.content)
prev_content = next(content_iterator)
prev_result = copy.deepcopy(stream_message)
prev_result.content = prev_content
for sub_content in content_iterator:
logging.info(f"[request_id={request_id}, session_id={session_id}] streaming_result={prev_result}")
yield "data: " + json.dumps({
"code": 0, "message": "",
"result": {
"session_id": session_id,
"is_completion": False,
"answer_message": prev_result
"answer_message": json.loads(prev_result.json(exclude_none=True))
}
}, ensure_ascii=False) + "\n\n"
prev_result = {
"content": sub_content,
"extra": stream_message.extra if hasattr(stream_message, "extra") else {},
"token_usage": stream_message.token_usage if hasattr(stream_message, "token_usage") else {},
}
prev_result = copy.deepcopy(stream_message)
prev_result.content = sub_content
logging.info(f"[request_id={request_id}, session_id={session_id}] streaming_result={prev_result}")
yield "data: " + json.dumps({
"code": 0, "message": "",
"result": {
"session_id": session_id,
"is_completion": True,
"answer_message": prev_result
"answer_message": json.loads(prev_result.json(exclude_none=True))
}
}, ensure_ascii=False) + "\n\n"
self.user_session._post_append()
Expand All @@ -317,7 +317,7 @@ def gen_sse_resp(stream_message):
{'Content-Type': 'text/event-stream; charset=utf-8'},
)
else:
blocking_result = json.loads(answer.json(exclude_none=True))
blocking_result = json.loads(copy.deepcopy(answer).json(exclude_none=True))
logging.info(f"[request_id={request_id}, session_id={session_id}] blocking_result={blocking_result}")
self.user_session._post_append()
return {
Expand Down
5 changes: 3 additions & 2 deletions appbuilder/core/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

from pydantic import BaseModel
from typing import Dict, List, Optional, Any

from appbuilder.core.utils import ttl_lru_cache
from appbuilder.core._client import HTTPClient
from appbuilder.core.message import Message

Expand Down Expand Up @@ -81,7 +81,8 @@ def __init__(
self.lazy_certification = lazy_certification
if not self.lazy_certification:
self.set_secret_key_and_gateway(self.secret_key, self.gateway)


@ttl_lru_cache(seconds_to_live=1 * 60 * 60) # 1h
def set_secret_key_and_gateway(self, secret_key: Optional[str] = None, gateway: str = ""):
self.secret_key = secret_key
self.gateway = gateway
Expand Down
8 changes: 5 additions & 3 deletions appbuilder/core/components/excel2figure/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from appbuilder.core._exception import AppBuilderServerException, ModelNotSupportedException
from appbuilder.core.component import Component, ComponentArguments
from appbuilder.core.message import Message
from appbuilder.core.utils import ModelInfo
from appbuilder.core.utils import ModelInfo, ttl_lru_cache


class Excel2FigureArgs(ComponentArguments):
Expand Down Expand Up @@ -74,11 +74,13 @@ def __init__(
self._check_model_and_get_model_url(self.model, self.model_type)
self.server_sub_path = "/v1/ai_engine/copilot_engine/v1/api/agent/excel2figure"

@ttl_lru_cache(seconds_to_live=1 * 60 * 60) # 1h
def set_secret_key_and_gateway(self, secret_key: Optional[str] = None, gateway: str = ""):
super(Excel2Figure, self).set_secret_key_and_gateway(
secret_key=secret_key, gateway=gateway)
self.__class__.model_info = ModelInfo(client=self.http_client)

@ttl_lru_cache(seconds_to_live=1 * 60 * 60) # 1h
def _check_model_and_get_model_url(self, model, model_type):
if model and model in self.excluded_models:
raise ModelNotSupportedException(f"Model {model} not supported")
Expand Down Expand Up @@ -221,8 +223,8 @@ def tool_eval(
'text': [result_msg.content],
}
except Exception as e:
result = f'绘制图表时发生错误:{e}'
logging.error(result, exc_info=True)
raise RuntimeError(f'绘制图表时发生错误:{e}')

if streaming:
yield result
else:
Expand Down
16 changes: 15 additions & 1 deletion appbuilder/core/components/llms/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
from enum import Enum
import logging
import requests
import copy
import collections.abc
from appbuilder.core.constants import GATEWAY_URL, GATEWAY_INNER_URL
from pydantic import BaseModel, Field, ValidationError, HttpUrl, validator
from pydantic.types import confloat
Expand All @@ -27,7 +29,7 @@
from typing import Dict, List, Optional, Any

from appbuilder.core.component import ComponentArguments
from appbuilder.core.utils import ModelInfo
from appbuilder.core.utils import ModelInfo, ttl_lru_cache
from appbuilder.utils.sse_util import SSEClient
from appbuilder.core._exception import AppBuilderServerException, ModelNotSupportedException

Expand All @@ -40,6 +42,16 @@ class LLMMessage(Message):
def __str__(self):
return f"Message(name={self.name}, content={self.content}, " \
f"mtype={self.mtype}, extra={self.extra}, token_usage={self.token_usage})"

def __deepcopy__(self, memo):
new_instance = self.__class__()
memo[id(self)] = new_instance
for k, v in self.__dict__.items():
if k == "content" and isinstance(v, collections.abc.Iterator):
pass
else:
setattr(new_instance, k, copy.deepcopy(v, memo))
return new_instance


class CompletionRequest(object):
Expand Down Expand Up @@ -270,11 +282,13 @@ def __init__(
if not lazy_certification:
self._check_model_and_get_model_url(self.model_name, self.model_type)

@ttl_lru_cache(seconds_to_live=1 * 60 * 60) # 1h
def set_secret_key_and_gateway(self, secret_key: Optional[str] = None, gateway: str = ""):
super(CompletionBaseComponent, self).set_secret_key_and_gateway(
secret_key=secret_key, gateway=gateway)
self.__class__.model_info = ModelInfo(client=self.http_client)

@ttl_lru_cache(seconds_to_live=1 * 60 * 60) # 1h
def _check_model_and_get_model_url(self, model, model_type):
if model and model in self.excluded_models:
raise ModelNotSupportedException(f"Model {model} not supported")
Expand Down
4 changes: 2 additions & 2 deletions appbuilder/core/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@

import uuid

from pydantic import BaseModel
from pydantic import BaseModel, Extra
from typing import Optional, TypeVar, Generic


_T = TypeVar("_T")


class Message(BaseModel, Generic[_T]):
class Message(BaseModel, Generic[_T], extra=Extra.allow):
content: Optional[_T] = {}
name: Optional[str] = "msg"
mtype: Optional[str] = "dict"
Expand Down
16 changes: 16 additions & 0 deletions appbuilder/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
# 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 time
import itertools
from typing import List
from urllib.parse import urlparse
from appbuilder.core._client import HTTPClient
from appbuilder.core._exception import TypeNotSupportedException, ModelNotSupportedException
from appbuilder.utils.model_util import GetModelListRequest, Models, RemoteModelCollector
from functools import lru_cache


def utils_get_user_agent():
Expand Down Expand Up @@ -75,6 +77,20 @@ def is_url(string):
return all([result.scheme, result.netloc])


def ttl_lru_cache(seconds_to_live: int, maxsize: int = 128):
"""
Time aware lru caching
"""
def wrapper(func):
@lru_cache(maxsize)
def inner(__ttl, *args, **kwargs):
# Note that __ttl is not passed down to func,
# as it's only used to trigger cache miss after some time
return func(*args, **kwargs)
return lambda *args, **kwargs: inner(time.time() // seconds_to_live, *args, **kwargs)
return wrapper


class ModelInfo:
""" 模型信息类 """

Expand Down
Loading