From 0835b40afec82e7db70bdbb8205c608982ef7113 Mon Sep 17 00:00:00 2001
From: JUN SUN <18810256350@163.com>
Date: Thu, 25 Jan 2024 14:20:29 +0800
Subject: [PATCH 01/11] support sensetime api
---
src/backend/bisheng/default_node.yaml | 2 +
.../bisheng_langchain/chat_models/__init__.py | 3 +-
.../chat_models/sensetime.py | 347 ++++++++++++++++++
3 files changed, 351 insertions(+), 1 deletion(-)
create mode 100644 src/bisheng-langchain/bisheng_langchain/chat_models/sensetime.py
diff --git a/src/backend/bisheng/default_node.yaml b/src/backend/bisheng/default_node.yaml
index d32b77e7b..3851d4847 100644
--- a/src/backend/bisheng/default_node.yaml
+++ b/src/backend/bisheng/default_node.yaml
@@ -192,6 +192,8 @@ llms:
documentation: ""
CustomLLMChat:
documentation: ""
+ SenseChat:
+ documentation: ""
###
# There's a bug in this component deactivating until we get it sorted: _language_models.py", line 804, in send_message
# is_blocked=safety_attributes.get("blocked", False),
diff --git a/src/bisheng-langchain/bisheng_langchain/chat_models/__init__.py b/src/bisheng-langchain/bisheng_langchain/chat_models/__init__.py
index cc96c8912..f71539035 100644
--- a/src/bisheng-langchain/bisheng_langchain/chat_models/__init__.py
+++ b/src/bisheng-langchain/bisheng_langchain/chat_models/__init__.py
@@ -5,8 +5,9 @@
from .wenxin import ChatWenxin
from .xunfeiai import ChatXunfeiAI
from .zhipuai import ChatZhipuAI
+from .sensetime import SenseChat
__all__ = [
'ProxyChatLLM', 'ChatMinimaxAI', 'ChatWenxin', 'ChatZhipuAI', 'ChatXunfeiAI', 'HostChatGLM',
- 'HostBaichuanChat', 'HostLlama2Chat', 'HostQwenChat', 'CustomLLMChat', 'ChatQWen'
+ 'HostBaichuanChat', 'HostLlama2Chat', 'HostQwenChat', 'CustomLLMChat', 'ChatQWen', 'SenseChat'
]
diff --git a/src/bisheng-langchain/bisheng_langchain/chat_models/sensetime.py b/src/bisheng-langchain/bisheng_langchain/chat_models/sensetime.py
new file mode 100644
index 000000000..61e09a28c
--- /dev/null
+++ b/src/bisheng-langchain/bisheng_langchain/chat_models/sensetime.py
@@ -0,0 +1,347 @@
+from __future__ import annotations
+
+import logging
+import sys
+from typing import TYPE_CHECKING, Any, Callable, Dict, List, Mapping, Optional, Tuple, Union
+from langchain.callbacks.manager import AsyncCallbackManagerForLLMRun, CallbackManagerForLLMRun
+from langchain.chat_models.base import BaseChatModel
+from langchain.schema import ChatGeneration, ChatResult
+from langchain.schema.messages import (AIMessage, BaseMessage, ChatMessage, FunctionMessage,
+ HumanMessage, SystemMessage)
+from langchain.utils import get_from_dict_or_env
+from langchain_core.pydantic_v1 import Field, root_validator
+from tenacity import (before_sleep_log, retry, retry_if_exception_type, stop_after_attempt,
+ wait_exponential)
+from bisheng_langchain.utils.requests import Requests
+
+import time
+import requests
+import json
+
+
+import jwt
+# if TYPE_CHECKING:
+# import jwt
+
+logger = logging.getLogger(__name__)
+
+def llll(dd):
+ with open(f"/app/{dd}.txt",'w') as f:
+ f.write(dd+'\n')
+
+
+def _import_pyjwt() -> Any:
+ try:
+ import jwt
+ except ImportError:
+ raise ValueError('Could not import jwt python package. '
+ 'This is needed in order to calculate get_token_ids. '
+ 'Please install it with `pip install PyJWT`.')
+ return jwt
+
+
+def _create_retry_decorator(llm):
+
+ min_seconds = 1
+ max_seconds = 20
+ # Wait 2^x * 1 second between each retry starting with
+ # 4 seconds, then up to 10 seconds, then 10 seconds afterwards
+ return retry(
+ reraise=True,
+ stop=stop_after_attempt(llm.max_retries),
+ wait=wait_exponential(multiplier=1, min=min_seconds, max=max_seconds),
+ retry=(retry_if_exception_type(Exception)),
+ before_sleep=before_sleep_log(logger, logging.WARNING),
+ )
+
+
+def _convert_dict_to_message(_dict: Mapping[str, Any]) -> BaseMessage:
+ role = _dict['role']
+ if role == 'user':
+ return HumanMessage(content=_dict['content'])
+ elif role == 'assistant':
+ content = _dict['content'] or '' # OpenAI returns None for tool invocations
+ if _dict.get('function_call'):
+ additional_kwargs = {'function_call': dict(_dict['function_call'])}
+ else:
+ additional_kwargs = {}
+ return AIMessage(content=content, additional_kwargs=additional_kwargs)
+ elif role == 'system':
+ return SystemMessage(content=_dict['content'])
+ elif role == 'function':
+ return FunctionMessage(content=_dict['content'], name=_dict['name'])
+ else:
+ return ChatMessage(content=_dict['content'], role=role)
+
+
+def _convert_message_to_dict(message: BaseMessage) -> dict:
+ if isinstance(message, ChatMessage):
+ message_dict = {'role': message.role, 'content': message.content}
+ elif isinstance(message, HumanMessage):
+ message_dict = {'role': 'user', 'content': message.content}
+ elif isinstance(message, AIMessage):
+ message_dict = {'role': 'assistant', 'content': message.content}
+ elif isinstance(message, SystemMessage):
+ message_dict = {'role': 'system', 'content': message.content}
+ # raise ValueError(f"not support system role {message}")
+
+ elif isinstance(message, FunctionMessage):
+ raise ValueError(f'not support funciton {message}')
+ else:
+ raise ValueError(f'Got unknown type {message}')
+
+ # if "name" in message.additional_kwargs:
+ # message_dict["name"] = message.additional_kwargs["name"]
+ return message_dict
+
+
+def _convert_message_to_dict2(message: BaseMessage) -> List[dict]:
+ if isinstance(message, ChatMessage):
+ message_dict = {'role': message.role, 'content': message.content}
+ elif isinstance(message, HumanMessage):
+ message_dict = {'role': 'user', 'content': message.content}
+ elif isinstance(message, AIMessage):
+ message_dict = {'role': 'assistant', 'content': message.content}
+ elif isinstance(message, SystemMessage):
+ raise ValueError(f'not support system role {message}')
+
+ elif isinstance(message, FunctionMessage):
+ raise ValueError(f'not support funciton {message}')
+ else:
+ raise ValueError(f'Got unknown type {message}')
+
+ return [message_dict]
+
+def encode_jwt_token(ak, sk):
+ headers = {
+ "alg": "HS256",
+ "typ": "JWT"
+ }
+ payload = {
+ "iss": ak,
+ "exp": int(time.time()) + 1800, # 填写您期望的有效时间,此处示例代表当前时间+30分钟
+ "nbf": int(time.time()) - 5 # 填写您期望的生效时间,此处示例代表当前时间-5秒
+ }
+ token = jwt.encode(payload, sk, headers=headers)
+ return token
+
+url = "https://api.sensenova.cn/v1/llm/chat-completions"
+
+class SenseChat(BaseChatModel):
+
+ client: Optional[Any] #: :meta private:
+ model_name: str = Field(default='SenseChat', alias='model')
+ """Model name to use."""
+ temperature: float = 0.8
+ top_p: float = 0.7
+ """What sampling temperature to use."""
+ model_kwargs: Optional[Dict[str, Any]] = Field(default_factory=dict)
+ """Holds any model parameters valid for `create` call not explicitly specified."""
+ api_token: Optional[str] = None
+ # secret_access_key: Optional[str] = None
+
+ repetition_penalty: float = 1.05
+ request_timeout: Optional[Union[float, Tuple[float, float]]] = None
+ """Timeout for requests to OpenAI completion API. Default is 600 seconds."""
+ max_retries: Optional[int] = 6
+ """Maximum number of retries to make when generating."""
+ streaming: Optional[bool] = False
+ """Whether to stream the results or not."""
+ n: Optional[int] = 1
+ """Number of chat completions to generate for each prompt."""
+ max_tokens: Optional[int] = 1024
+ """Maximum number of tokens to generate."""
+ tiktoken_model_name: Optional[str] = None
+ """The model name to pass to tiktoken when using this class.
+ Tiktoken is used to count the number of tokens in documents to constrain
+ them to be under a certain limit. By default, when set to None, this will
+ be the same as the embedding model name. However, there are some cases
+ where you may want to use this Embedding class with a model name not
+ supported by tiktoken. This can include when using Azure embeddings or
+ when using one of the many model providers that expose an OpenAI-like
+ API but with different models. In those cases, in order to avoid erroring
+ when tiktoken is called, you can specify a model name to use here."""
+ verbose: Optional[bool] = False
+
+ class Config:
+ """Configuration for this pydantic object."""
+
+ allow_population_by_field_name = True
+
+ @root_validator()
+ def validate_environment(cls, values: Dict) -> Dict:
+
+ """Validate that api key and python package exists in environment."""
+
+ _import_pyjwt()
+ # values['access_key_id'] = get_from_dict_or_env(values, 'access_key_id',
+ # 'ACCESS_KEY_ID')
+ # values['secret_access_key'] = get_from_dict_or_env(values, 'secret_access_key',
+ # 'SECRET_ACCESS_KEY')
+
+ values['api_token'] = get_from_dict_or_env(values, 'api_token',
+ 'API_TOKEN')
+
+ # try:
+ # header = {'Authorization': 'Bearer {}'.format(api_key), 'Content-Type': 'application/json'}
+ # values['client'] = requests
+ # except AttributeError:
+ # raise ValueError('Try upgrading it with `pip install --upgrade requests`.')
+ return values
+
+ @property
+ def _default_params(self) -> Dict[str, Any]:
+ """Get the default parameters for calling ZhipuAI API."""
+ return {
+ 'model': self.model_name,
+ 'temperature': self.temperature,
+ 'top_p': self.top_p,
+ 'max_tokens': self.max_tokens,
+ **self.model_kwargs,
+ }
+
+ def completion_with_retry(self, **kwargs: Any) -> Any:
+ retry_decorator = _create_retry_decorator(self)
+
+ @retry_decorator
+ def _completion_with_retry(**kwargs: Any) -> Any:
+ messages = kwargs.get('messages')
+ temperature = kwargs.get('temperature')
+ top_p = kwargs.get('top_p')
+ # messages
+ params = {
+ 'messages': messages,
+ 'model': self.model_name,
+ 'top_p': top_p,
+ 'temperature': temperature,
+ 'repetition_penalty': self.repetition_penalty,
+ 'n': self.n,
+ "max_new_tokens": self.max_tokens,
+ 'stream': False#self.streaming
+ }
+
+ # llll(self.api_token)
+ # api_key = encode_jwt_token(self.access_key_id, self.secret_access_key)
+ # logger.info(f"#####{self.api_token}#####")
+ header = {'Authorization': 'Bearer {}'.format(self.api_token), 'Content-Type': 'application/json'}
+ # logger.info(f"#####{params}#####")
+ # logger.info(f"#####{response}#####")
+ response = requests.post(url, json=params, headers=header)
+ logger.info(f"#####{response.json()}#####")
+ # response = requests.post(url, headers=header, data=json.dumps(params))
+ res = response.json()
+ # res["role"] = messages[0]["role"]
+ return res
+
+ return _completion_with_retry(**kwargs)
+
+ def _combine_llm_outputs(self, llm_outputs: List[Optional[dict]]) -> dict:
+ overall_token_usage: dict = {}
+ for output in llm_outputs:
+ if output is None:
+ # Happens in streaming
+ continue
+ token_usage = output['token_usage']
+ for k, v in token_usage.items():
+ if k in overall_token_usage:
+ overall_token_usage[k] += v
+ else:
+ overall_token_usage[k] = v
+ return {'token_usage': overall_token_usage, 'model_name': self.model_name}
+
+ def _generate(
+ self,
+ messages: List[BaseMessage],
+ stop: Optional[List[str]] = None,
+ run_manager: Optional[CallbackManagerForLLMRun] = None,
+ **kwargs: Any,
+ ) -> ChatResult:
+
+ message_dicts, params = self._create_message_dicts(messages, stop)
+ params = {**params, **kwargs}
+ response = self.completion_with_retry(messages=message_dicts, **params)
+
+ if "error" in response:
+ logger.error(f"invalid result: {response}")
+ return self._create_chat_result(response)
+
+ async def _agenerate(
+ self,
+ messages: List[BaseMessage],
+ stop: Optional[List[str]] = None,
+ run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
+ **kwargs: Any,
+ ) -> ChatResult:
+ return self._generate(messages, stop, run_manager, **kwargs)
+
+ def _create_message_dicts(
+ self, messages: List[BaseMessage],
+ stop: Optional[List[str]]) -> Tuple[List[Dict[str, Any]], Dict[str, Any]]:
+ params = dict(self._client_params)
+ if stop is not None:
+ if 'stop' in params:
+ raise ValueError('`stop` found in both the input and default params.')
+ params['stop'] = stop
+
+ system_content = ''
+ message_dicts = []
+ for m in messages:
+ if m.type == 'system':
+ system_content += m.content
+ continue
+ message_dicts.extend(_convert_message_to_dict2(m))
+
+ if system_content:
+ message_dicts[-1]['content'] = system_content + message_dicts[-1]['content']
+
+ return message_dicts, params
+
+ def _create_chat_result(self, response: Mapping[str, Any]) -> ChatResult:
+ generations = []
+
+ def _norm_text(text):
+ if text[0] == '"' and text[-1] == '"':
+ out = eval(text)
+ else:
+ out = text
+ return out
+
+ for res in response['data']['choices']:
+ res['content'] = _norm_text(res['message'])
+ res["role"] = 'user' # 写死了角色
+ message = _convert_dict_to_message(res)
+ gen = ChatGeneration(message=message)
+ generations.append(gen)
+
+ llm_output = {'token_usage': response['data']['usage'], 'model_name': self.model_name}
+ return ChatResult(generations=generations, llm_output=llm_output)
+
+ @property
+ def _identifying_params(self) -> Mapping[str, Any]:
+ """Get the identifying parameters."""
+ return {**{'model_name': self.model_name}, **self._default_params}
+
+ @property
+ def _client_params(self) -> Mapping[str, Any]:
+ """Get the parameters used for the openai client."""
+ zhipu_creds: Dict[str, Any] = {
+ 'api_key': self.api_token,
+ 'model': self.model_name,
+ }
+ return {**zhipu_creds, **self._default_params}
+
+ def _get_invocation_params(self,
+ stop: Optional[List[str]] = None,
+ **kwargs: Any) -> Dict[str, Any]:
+ """Get the parameters used to invoke the model FOR THE CALLBACKS."""
+ return {
+ **super()._get_invocation_params(stop=stop, **kwargs),
+ **self._default_params,
+ 'model': self.model_name,
+ 'function': kwargs.get('functions'),
+ }
+
+ @property
+ def _llm_type(self) -> str:
+ """Return type of chat model."""
+ return 'sense-chat'
\ No newline at end of file
From 76f4d8ac52cbe68d271ae91ef9eabb980d8f38ce Mon Sep 17 00:00:00 2001
From: JUN SUN <18810256350@163.com>
Date: Thu, 25 Jan 2024 14:24:36 +0800
Subject: [PATCH 02/11] update
---
.../chat_models/sensetime.py | 19 +++----------------
1 file changed, 3 insertions(+), 16 deletions(-)
diff --git a/src/bisheng-langchain/bisheng_langchain/chat_models/sensetime.py b/src/bisheng-langchain/bisheng_langchain/chat_models/sensetime.py
index 61e09a28c..776ef5d0d 100644
--- a/src/bisheng-langchain/bisheng_langchain/chat_models/sensetime.py
+++ b/src/bisheng-langchain/bisheng_langchain/chat_models/sensetime.py
@@ -19,17 +19,10 @@
import json
-import jwt
-# if TYPE_CHECKING:
-# import jwt
+import jwt # pip3 install PyJWT
logger = logging.getLogger(__name__)
-def llll(dd):
- with open(f"/app/{dd}.txt",'w') as f:
- f.write(dd+'\n')
-
-
def _import_pyjwt() -> Any:
try:
import jwt
@@ -219,18 +212,12 @@ def _completion_with_retry(**kwargs: Any) -> Any:
"max_new_tokens": self.max_tokens,
'stream': False#self.streaming
}
-
- # llll(self.api_token)
+
# api_key = encode_jwt_token(self.access_key_id, self.secret_access_key)
- # logger.info(f"#####{self.api_token}#####")
header = {'Authorization': 'Bearer {}'.format(self.api_token), 'Content-Type': 'application/json'}
- # logger.info(f"#####{params}#####")
- # logger.info(f"#####{response}#####")
+
response = requests.post(url, json=params, headers=header)
- logger.info(f"#####{response.json()}#####")
- # response = requests.post(url, headers=header, data=json.dumps(params))
res = response.json()
- # res["role"] = messages[0]["role"]
return res
return _completion_with_retry(**kwargs)
From bb4f5ba5271a26361387a721db4c9359b6efa132 Mon Sep 17 00:00:00 2001
From: JUN SUN <18810256350@163.com>
Date: Fri, 26 Jan 2024 00:42:12 +0800
Subject: [PATCH 03/11] update
---
.../chat_models/sensetime.py | 126 ++++++++++++++----
1 file changed, 103 insertions(+), 23 deletions(-)
diff --git a/src/bisheng-langchain/bisheng_langchain/chat_models/sensetime.py b/src/bisheng-langchain/bisheng_langchain/chat_models/sensetime.py
index 776ef5d0d..6cfefe47d 100644
--- a/src/bisheng-langchain/bisheng_langchain/chat_models/sensetime.py
+++ b/src/bisheng-langchain/bisheng_langchain/chat_models/sensetime.py
@@ -19,10 +19,17 @@
import json
-import jwt # pip3 install PyJWT
+import jwt
+# if TYPE_CHECKING:
+# import jwt
logger = logging.getLogger(__name__)
+def llll(dd):
+ with open(f"/app/{dd}.txt",'w') as f:
+ f.write(dd+'\n')
+
+
def _import_pyjwt() -> Any:
try:
import jwt
@@ -53,7 +60,7 @@ def _convert_dict_to_message(_dict: Mapping[str, Any]) -> BaseMessage:
if role == 'user':
return HumanMessage(content=_dict['content'])
elif role == 'assistant':
- content = _dict['content'] or '' # OpenAI returns None for tool invocations
+ content = _dict['message'] or '' # OpenAI returns None for tool invocations
if _dict.get('function_call'):
additional_kwargs = {'function_call': dict(_dict['function_call'])}
else:
@@ -121,6 +128,7 @@ def encode_jwt_token(ak, sk):
url = "https://api.sensenova.cn/v1/llm/chat-completions"
class SenseChat(BaseChatModel):
+# class ChatQWen(BaseChatModel):
client: Optional[Any] #: :meta private:
model_name: str = Field(default='SenseChat', alias='model')
@@ -167,19 +175,15 @@ def validate_environment(cls, values: Dict) -> Dict:
"""Validate that api key and python package exists in environment."""
_import_pyjwt()
- # values['access_key_id'] = get_from_dict_or_env(values, 'access_key_id',
- # 'ACCESS_KEY_ID')
- # values['secret_access_key'] = get_from_dict_or_env(values, 'secret_access_key',
- # 'SECRET_ACCESS_KEY')
values['api_token'] = get_from_dict_or_env(values, 'api_token',
'API_TOKEN')
- # try:
- # header = {'Authorization': 'Bearer {}'.format(api_key), 'Content-Type': 'application/json'}
- # values['client'] = requests
- # except AttributeError:
- # raise ValueError('Try upgrading it with `pip install --upgrade requests`.')
+ try:
+ header = {'Authorization': 'Bearer {}'.format(values['api_token']), 'Content-Type': 'application/json'}
+ values['client'] = Requests(headers=header, )
+ except AttributeError:
+ raise ValueError('Try upgrading it with `pip install --upgrade requests`.')
return values
@property
@@ -212,15 +216,56 @@ def _completion_with_retry(**kwargs: Any) -> Any:
"max_new_tokens": self.max_tokens,
'stream': False#self.streaming
}
+
+ response = self.client.post(url=url, json=params).json()
+ return response
+ rsp_dict = _completion_with_retry(**kwargs)
+ if 'error' in rsp_dict:
+ logger.error(f'sensechat_error resp={rsp_dict}')
+ message = rsp_dict['error']['message']
+ raise Exception(message)
+ else:
+ # return rsp_dict['data'], rsp_dict.get('usage', '')
+ return rsp_dict, rsp_dict.get('usage', '')
- # api_key = encode_jwt_token(self.access_key_id, self.secret_access_key)
- header = {'Authorization': 'Bearer {}'.format(self.api_token), 'Content-Type': 'application/json'}
- response = requests.post(url, json=params, headers=header)
- res = response.json()
- return res
+ async def acompletion_with_retry(self, **kwargs: Any) -> Any:
+ """Use tenacity to retry the async completion call."""
+ retry_decorator = _create_retry_decorator(self)
+ if self.streaming:
+ self.client.headers.update({'Accept': 'text/event-stream'})
+ else:
+ self.client.headers.pop('Accept', '')
- return _completion_with_retry(**kwargs)
+ @retry_decorator
+ async def _acompletion_with_retry(**kwargs: Any) -> Any:
+ messages = kwargs.pop('messages', '')
+ input, params = SenseChat._build_input_parameters(self.model_name,
+ messages=messages,
+ **kwargs)
+ inp = {'input': input, 'parameters': params, 'model': self.model_name}
+ # Use OpenAI's async api https://github.com/openai/openai-python#async-api
+ async with self.client.apost(url=url, json=inp) as response:
+ async for line in response.content.iter_any():
+ if b'\n' in line:
+ for txt_ in line.split(b'\n'):
+ yield txt_.decode('utf-8').strip()
+ else:
+ yield line.decode('utf-8').strip()
+
+ async for response in _acompletion_with_retry(**kwargs):
+ is_error = False
+ if response:
+ if response.startswith('event:error'):
+ is_error = True
+ elif response.startswith('data:'):
+ yield (is_error, response[len('data:'):])
+ if is_error:
+ break
+ elif response.startswith('{'):
+ yield (is_error, response)
+ else:
+ continue
def _combine_llm_outputs(self, llm_outputs: List[Optional[dict]]) -> dict:
overall_token_usage: dict = {}
@@ -246,10 +291,8 @@ def _generate(
message_dicts, params = self._create_message_dicts(messages, stop)
params = {**params, **kwargs}
- response = self.completion_with_retry(messages=message_dicts, **params)
+ response, usage = self.completion_with_retry(messages=message_dicts, **params)
- if "error" in response:
- logger.error(f"invalid result: {response}")
return self._create_chat_result(response)
async def _agenerate(
@@ -259,7 +302,44 @@ async def _agenerate(
run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
**kwargs: Any,
) -> ChatResult:
- return self._generate(messages, stop, run_manager, **kwargs)
+ message_dicts, params = self._create_message_dicts(messages, stop)
+ params = {**params, **kwargs}
+ if self.streaming:
+ inner_completion = ''
+ role = 'assistant'
+ params['stream'] = True
+ function_call: Optional[dict] = None
+ async for is_error, stream_resp in self.acompletion_with_retry(messages=message_dicts,
+ **params):
+ output = None
+ msg = json.loads(stream_resp)
+ if is_error:
+ logger.error(stream_resp)
+ raise ValueError(stream_resp)
+ if 'data' in msg:
+ output = msg['data']
+ choices = output.get('choices')
+ if choices:
+ for choice in choices:
+ role = choice['message'].get('role', role)
+ token = choice['message'].get('message', '')
+ inner_completion += token or ''
+ _function_call = choice['message'].get('function_call', '')
+ if run_manager:
+ await run_manager.on_llm_new_token(token)
+ if _function_call:
+ if function_call is None:
+ function_call = _function_call
+ else:
+ function_call['arguments'] += _function_call['arguments']
+ message = _convert_dict_to_message({
+ 'content': inner_completion,
+ 'role': role,
+ 'function_call': function_call,
+ })
+ return ChatResult(generations=[ChatGeneration(message=message)])
+ else:
+ return self._generate(messages, stop, run_manager, **kwargs)
def _create_message_dicts(
self, messages: List[BaseMessage],
@@ -286,16 +366,16 @@ def _create_message_dicts(
def _create_chat_result(self, response: Mapping[str, Any]) -> ChatResult:
generations = []
+ # print('response', response)
def _norm_text(text):
if text[0] == '"' and text[-1] == '"':
out = eval(text)
else:
out = text
return out
-
for res in response['data']['choices']:
res['content'] = _norm_text(res['message'])
- res["role"] = 'user' # 写死了角色
+ res["role"] = 'user'
message = _convert_dict_to_message(res)
gen = ChatGeneration(message=message)
generations.append(gen)
From b5d1cd95e90b1ed67536532fd432cadf2160ad3f Mon Sep 17 00:00:00 2001
From: JUN SUN <18810256350@163.com>
Date: Fri, 26 Jan 2024 00:43:40 +0800
Subject: [PATCH 04/11] update
---
.../bisheng_langchain/chat_models/sensetime.py | 14 --------------
1 file changed, 14 deletions(-)
diff --git a/src/bisheng-langchain/bisheng_langchain/chat_models/sensetime.py b/src/bisheng-langchain/bisheng_langchain/chat_models/sensetime.py
index 6cfefe47d..61f614b6e 100644
--- a/src/bisheng-langchain/bisheng_langchain/chat_models/sensetime.py
+++ b/src/bisheng-langchain/bisheng_langchain/chat_models/sensetime.py
@@ -112,23 +112,9 @@ def _convert_message_to_dict2(message: BaseMessage) -> List[dict]:
return [message_dict]
-def encode_jwt_token(ak, sk):
- headers = {
- "alg": "HS256",
- "typ": "JWT"
- }
- payload = {
- "iss": ak,
- "exp": int(time.time()) + 1800, # 填写您期望的有效时间,此处示例代表当前时间+30分钟
- "nbf": int(time.time()) - 5 # 填写您期望的生效时间,此处示例代表当前时间-5秒
- }
- token = jwt.encode(payload, sk, headers=headers)
- return token
-
url = "https://api.sensenova.cn/v1/llm/chat-completions"
class SenseChat(BaseChatModel):
-# class ChatQWen(BaseChatModel):
client: Optional[Any] #: :meta private:
model_name: str = Field(default='SenseChat', alias='model')
From 9ddb677cbf74dc7476947570018a76144a0e6cfd Mon Sep 17 00:00:00 2001
From: JUN SUN <18810256350@163.com>
Date: Fri, 26 Jan 2024 12:05:13 +0800
Subject: [PATCH 05/11] update
---
.../chat_models/sensetime.py | 36 +++++++++++++------
1 file changed, 25 insertions(+), 11 deletions(-)
diff --git a/src/bisheng-langchain/bisheng_langchain/chat_models/sensetime.py b/src/bisheng-langchain/bisheng_langchain/chat_models/sensetime.py
index 61f614b6e..7929a9f17 100644
--- a/src/bisheng-langchain/bisheng_langchain/chat_models/sensetime.py
+++ b/src/bisheng-langchain/bisheng_langchain/chat_models/sensetime.py
@@ -25,11 +25,6 @@
logger = logging.getLogger(__name__)
-def llll(dd):
- with open(f"/app/{dd}.txt",'w') as f:
- f.write(dd+'\n')
-
-
def _import_pyjwt() -> Any:
try:
import jwt
@@ -39,6 +34,18 @@ def _import_pyjwt() -> Any:
'Please install it with `pip install PyJWT`.')
return jwt
+def encode_jwt_token(ak, sk):
+ headers = {
+ "alg": "HS256",
+ "typ": "JWT"
+ }
+ payload = {
+ "iss": ak,
+ "exp": int(time.time()) + 1800, # 填写您期望的有效时间,此处示例代表当前时间+30分钟
+ "nbf": int(time.time()) - 5 # 填写您期望的生效时间,此处示例代表当前时间-5秒
+ }
+ token = jwt.encode(payload, sk, headers=headers)
+ return token
def _create_retry_decorator(llm):
@@ -124,8 +131,8 @@ class SenseChat(BaseChatModel):
"""What sampling temperature to use."""
model_kwargs: Optional[Dict[str, Any]] = Field(default_factory=dict)
"""Holds any model parameters valid for `create` call not explicitly specified."""
- api_token: Optional[str] = None
- # secret_access_key: Optional[str] = None
+ access_key_id: Optional[str] = None
+ secret_access_key: Optional[str] = None
repetition_penalty: float = 1.05
request_timeout: Optional[Union[float, Tuple[float, float]]] = None
@@ -162,11 +169,17 @@ def validate_environment(cls, values: Dict) -> Dict:
_import_pyjwt()
- values['api_token'] = get_from_dict_or_env(values, 'api_token',
- 'API_TOKEN')
+ values['access_key_id'] = get_from_dict_or_env(values, 'access_key_id',
+ 'ACCESS_KEY_ID')
+ values['secret_access_key'] = get_from_dict_or_env(values, 'secret_access_key',
+ 'SECRET_ACCESS_KEY')
+ token = encode_jwt_token(values['access_key_id'], values['secret_access_key'])
+ if isinstance(token, bytes):
+ token = token.decode('utf-8')
try:
- header = {'Authorization': 'Bearer {}'.format(values['api_token']), 'Content-Type': 'application/json'}
+ header = {'Authorization': 'Bearer {}'.format(token),
+ 'Content-Type': 'application/json'}
values['client'] = Requests(headers=header, )
except AttributeError:
raise ValueError('Try upgrading it with `pip install --upgrade requests`.')
@@ -378,7 +391,8 @@ def _identifying_params(self) -> Mapping[str, Any]:
def _client_params(self) -> Mapping[str, Any]:
"""Get the parameters used for the openai client."""
zhipu_creds: Dict[str, Any] = {
- 'api_key': self.api_token,
+ 'access_key_id': self.access_key_id,
+ 'secret_access_key': self.secret_access_key,
'model': self.model_name,
}
return {**zhipu_creds, **self._default_params}
From 4ce24b2197f2448c10fad23cf48390406fb57244 Mon Sep 17 00:00:00 2001
From: dolphin <78075021@qq.com>
Date: Fri, 26 Jan 2024 21:12:07 +0800
Subject: [PATCH 06/11] fix: password char vaildata
---
src/frontend/package.json | 2 +-
src/frontend/public/locales/en/bs.json | 2 +-
src/frontend/public/locales/zh/bs.json | 2 +-
src/frontend/src/CustomNodes/GenericNode/index.tsx | 2 +-
src/frontend/src/contexts/tabsContext.tsx | 2 +-
.../src/pages/FlowPage/components/PageComponent/index.tsx | 2 ++
.../pages/FlowPage/components/extraSidebarComponent/index.tsx | 2 +-
src/frontend/src/pages/SkillPage/l2Edit.tsx | 2 +-
src/frontend/src/pages/login.tsx | 2 +-
9 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/src/frontend/package.json b/src/frontend/package.json
index fb9125ebb..35d7a082f 100644
--- a/src/frontend/package.json
+++ b/src/frontend/package.json
@@ -1,6 +1,6 @@
{
"name": "bisheng",
- "version": "0.2.3",
+ "version": "0.2.2.4",
"private": true,
"dependencies": {
"@emotion/react": "^11.11.1",
diff --git a/src/frontend/public/locales/en/bs.json b/src/frontend/public/locales/en/bs.json
index 9744123a4..f57d244fd 100644
--- a/src/frontend/public/locales/en/bs.json
+++ b/src/frontend/public/locales/en/bs.json
@@ -15,7 +15,7 @@
"pleaseEnterPassword": "Please enter your password",
"accountTooShort": "Account is too short",
"passwordTooShort": "Password is too short, at least 8 characters",
- "passwordError": "The password must include upper and lower case letters, numbers, and special characters!",
+ "passwordError": "The password must include upper and lower case letters, numbers, and characters!",
"passwordMismatch": "Passwords do not match",
"registrationSuccess": "Registration successful. Please enter your password to log in",
"pleaseEnterCaptcha": "Please enter captcha"
diff --git a/src/frontend/public/locales/zh/bs.json b/src/frontend/public/locales/zh/bs.json
index 347f5b757..c121e1508 100644
--- a/src/frontend/public/locales/zh/bs.json
+++ b/src/frontend/public/locales/zh/bs.json
@@ -15,7 +15,7 @@
"pleaseEnterPassword": "请填写密码",
"accountTooShort": "账号过短",
"passwordTooShort": "请填写密码,至少8位",
- "passwordError": "密码必须包含大小写字母、数字和特殊字符!",
+ "passwordError": "密码必须包含大小写字母、数字和字符!",
"passwordMismatch": "两次密码不一致",
"registrationSuccess": "注册成功,请输入密码进行登录",
"pleaseEnterCaptcha": "请输入验证码"
diff --git a/src/frontend/src/CustomNodes/GenericNode/index.tsx b/src/frontend/src/CustomNodes/GenericNode/index.tsx
index 0f0a94445..681ec88c3 100644
--- a/src/frontend/src/CustomNodes/GenericNode/index.tsx
+++ b/src/frontend/src/CustomNodes/GenericNode/index.tsx
@@ -142,7 +142,7 @@ export default function GenericNode({ data, selected }: {
*/}
-
e.stopPropagation()}>
+
{data.node.description}
<>
{Object.keys(data.node.template)
diff --git a/src/frontend/src/contexts/tabsContext.tsx b/src/frontend/src/contexts/tabsContext.tsx
index 590d8233d..632ef3081 100644
--- a/src/frontend/src/contexts/tabsContext.tsx
+++ b/src/frontend/src/contexts/tabsContext.tsx
@@ -47,7 +47,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
async function saveFlow(flow: FlowType) {
// save api
const newFlow = await captureAndAlertRequestErrorHoc(updateFlowApi(flow))
- if (!newFlow) return {}
+ if (!newFlow) return null;
console.log('action :>> ', 'save');
setFlow(newFlow)
setTabsState((prev) => {
diff --git a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx
index 37fa39229..b87495d08 100644
--- a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx
+++ b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx
@@ -399,6 +399,8 @@ const useKeyBoard = (reactFlowWrapper) => {
useEffect(() => {
// this effect is used to attach the global event handlers
const onKeyDown = (event: KeyboardEvent) => {
+ if (event.target.tagName === 'INPUT') return // 排除输入框内复制粘贴
+
if (
(event.ctrlKey || event.metaKey) &&
event.key === "c" &&
diff --git a/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/index.tsx
index 5cd3c475a..e4e90b178 100644
--- a/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/index.tsx
+++ b/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/index.tsx
@@ -119,7 +119,7 @@ export default function ExtraSidebar({ flow }: { flow: FlowType }) {