chore: 添加虚拟环境到仓库

- 添加 backend_service/venv 虚拟环境
- 包含所有Python依赖包
- 注意:虚拟环境约393MB,包含12655个文件
This commit is contained in:
2025-12-03 10:19:25 +08:00
parent a6c2027caa
commit c4f851d387
12655 changed files with 3009376 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
# Copyright (c) Alibaba, Inc. and its affiliates.
from .tokenization import Tokenization
from .tokenizer import get_tokenizer, list_tokenizers
from .tokenizer_base import Tokenizer
__all__ = [Tokenization, Tokenizer, get_tokenizer, list_tokenizers]

View File

@@ -0,0 +1,111 @@
# Copyright (c) Alibaba, Inc. and its affiliates.
import base64
import unicodedata
from typing import Collection, Dict, List, Set, Union
from .tokenizer_base import Tokenizer
PAT_STR = r"""(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\r\n\p{L}\p{N}]?\p{L}+|\p{N}| ?[^\s\p{L}\p{N}]+[\r\n]*|\s*[\r\n]+|\s+(?!\S)|\s+""" # noqa E501
ENDOFTEXT = '<|endoftext|>'
IMSTART = '<|im_start|>'
IMEND = '<|im_end|>'
# as the default behavior is changed to allow special tokens in
# regular texts, the surface forms of special tokens need to be
# as different as possible to minimize the impact
EXTRAS = tuple((f'<|extra_{i}|>' for i in range(205)))
# changed to use actual index to avoid misconfiguration with vocabulary expansion
SPECIAL_START_ID = 151643
SPECIAL_TOKENS = tuple(
enumerate(
((
ENDOFTEXT,
IMSTART,
IMEND,
) + EXTRAS),
start=SPECIAL_START_ID,
))
SPECIAL_TOKENS_SET = set(t for i, t in SPECIAL_TOKENS)
class QwenTokenizer(Tokenizer):
@staticmethod
def _load_tiktoken_bpe(tiktoken_bpe_file: str) -> Dict[bytes, int]:
with open(tiktoken_bpe_file, 'rb') as f:
contents = f.read()
return {
base64.b64decode(token): int(rank)
for token, rank in (line.split() for line in contents.splitlines()
if line)
}
def __init__(self, vocab_file, errors='replace', extra_vocab_file=None):
self._errors = errors
self._vocab_file = vocab_file
self._extra_vocab_file = extra_vocab_file
self._mergeable_ranks = QwenTokenizer._load_tiktoken_bpe(
vocab_file) # type: Dict[bytes, int]
self._special_tokens = {
token: index
for index, token in SPECIAL_TOKENS
}
# try load extra vocab from file
if extra_vocab_file is not None:
used_ids = set(self._mergeable_ranks.values()) | set(
self._special_tokens.values())
extra_mergeable_ranks = self._load_tiktoken_bpe(extra_vocab_file)
for token, index in extra_mergeable_ranks.items():
if token in self._mergeable_ranks:
continue
if index in used_ids:
continue
self._mergeable_ranks[token] = index
# the index may be sparse after this, but don't worry tiktoken.Encoding will handle this
import tiktoken
enc = tiktoken.Encoding(
'Qwen',
pat_str=PAT_STR,
mergeable_ranks=self._mergeable_ranks,
special_tokens=self._special_tokens,
)
assert (
len(self._mergeable_ranks) +
len(self._special_tokens) == enc.n_vocab
), f'{len(self._mergeable_ranks) + len(self._special_tokens)} != {enc.n_vocab} in encoding'
self.decoder = {v: k
for k, v in self._mergeable_ranks.items()
} # type: dict[int, bytes|str]
self.decoder.update({v: k for k, v in self._special_tokens.items()})
self._tokenizer = enc # type: tiktoken.Encoding
self.eod_id = self._tokenizer.eot_token
self.im_start_id = self._special_tokens[IMSTART]
self.im_end_id = self._special_tokens[IMEND]
def encode(
self,
text: str,
allowed_special: Union[Set, str] = 'all',
disallowed_special: Union[Collection, str] = (),
) -> Union[List[List], List]:
text = unicodedata.normalize('NFC', text)
return self._tokenizer.encode(text,
allowed_special=allowed_special,
disallowed_special=disallowed_special)
def decode(
self,
token_ids: Union[int, List[int]],
skip_special_tokens: bool = False,
errors: str = None,
**kwargs,
) -> str:
if isinstance(token_ids, int):
token_ids = [token_ids]
if skip_special_tokens:
token_ids = [i for i in token_ids if i < self.eod_id]
return self._tokenizer.decode(token_ids, errors=errors or self._errors)

View File

@@ -0,0 +1,125 @@
# Copyright (c) Alibaba, Inc. and its affiliates.
import copy
from typing import Any, List
from dashscope.api_entities.dashscope_response import (DashScopeAPIResponse,
Message, Role)
from dashscope.client.base_api import BaseApi
from dashscope.common.constants import (CUSTOMIZED_MODEL_ID,
DEPRECATED_MESSAGE, HISTORY, MESSAGES,
PROMPT)
from dashscope.common.error import InputRequired, ModelRequired
from dashscope.common.logging import logger
class Tokenization(BaseApi):
FUNCTION = 'tokenizer'
"""API for get tokenizer result..
"""
class Models:
"""List of models currently supported
"""
qwen_turbo = 'qwen-turbo'
qwen_plus = 'qwen-plus'
qwen_7b_chat = 'qwen-7b-chat'
qwen_14b_chat = 'qwen-14b-chat'
llama2_7b_chat_v2 = 'llama2-7b-chat-v2'
llama2_13b_chat_v2 = 'llama2-13b-chat-v2'
text_embedding_v2 = 'text-embedding-v2'
qwen_72b_chat = 'qwen-72b-chat'
@classmethod
def call(cls,
model: str,
input: Any = None,
prompt: Any = None,
history: list = None,
api_key: str = None,
messages: List[Message] = None,
workspace: str = None,
**kwargs) -> DashScopeAPIResponse:
"""Call tokenization.
Args:
model (str): The requested model, such as qwen-v1
input: (Any): The model input body.
prompt (Any): The input prompt, for qwen serial model.
history (list):The user provided history,
deprecated, use messages instead.
examples:
[{'user':'The weather is fine today.',
'bot': 'Suitable for outings'}].
Defaults to None.
api_key (str, optional): The api api_key, can be None,
if None, will get by default rule(TODO: api key doc).
messages (list): The generation messages.
examples:
[{'role': 'user',
'content': 'The weather is fine today.'},
{'role': 'assistant', 'content': 'Suitable for outings'}]
workspace (str): The dashscope workspace id.
**kwargs:
see model input.
Raises:
InputRequired: input is required.
ModelRequired: model is required.
Returns:
DashScopeAPIResponse: The tokenizer output.
"""
if (input is None or not input) and \
(prompt is None or not prompt) and \
(messages is None or not messages):
raise InputRequired('prompt or messages is required!')
if model is None or not model:
raise ModelRequired('Model is required!')
if input is None:
input, parameters = cls._build_llm_parameters(
model, prompt, history, messages, **kwargs)
else:
parameters = kwargs
if kwargs.pop('stream', False): # not support stream
logger.warning('streaming option not supported for tokenization.')
return super().call(model=model,
task_group=None,
function=cls.FUNCTION,
api_key=api_key,
input=input,
is_service=False,
workspace=workspace,
**parameters)
@classmethod
def _build_llm_parameters(cls, model, prompt, history, messages, **kwargs):
parameters = {}
input = {}
if history is not None:
logger.warning(DEPRECATED_MESSAGE)
input[HISTORY] = history
if prompt is not None and prompt:
input[PROMPT] = prompt
elif messages is not None:
msgs = copy.deepcopy(messages)
if prompt is not None and prompt:
msgs.append({'role': Role.USER, 'content': prompt})
input = {MESSAGES: msgs}
else:
input[PROMPT] = prompt
if model.startswith('qwen'):
enable_search = kwargs.pop('enable_search', False)
if enable_search:
parameters['enable_search'] = enable_search
elif model.startswith('bailian'):
customized_model_id = kwargs.pop('customized_model_id', None)
if customized_model_id is None:
raise InputRequired('customized_model_id is required for %s' %
model)
input[CUSTOMIZED_MODEL_ID] = customized_model_id
return input, {**parameters, **kwargs}

View File

@@ -0,0 +1,45 @@
# Copyright (c) Alibaba, Inc. and its affiliates.
import os
from typing import List
from dashscope.common.error import UnsupportedModel
from dashscope.tokenizers.qwen_tokenizer import QwenTokenizer
from .tokenizer_base import Tokenizer
QWEN_SERIALS = ['qwen-7b-chat', 'qwen-turbo', 'qwen-plus', 'qwen-max']
current_path = os.path.dirname(os.path.abspath(__file__))
root_path = os.path.dirname(current_path)
def get_tokenizer(model: str) -> Tokenizer:
"""Get a tokenizer based on model name.
Args:
model (str): The model name.
Raises:
UnsupportedModel: Not support model
Returns:
Tokenizer: The `Tokenizer` of the model.
"""
if model in QWEN_SERIALS:
return QwenTokenizer(
os.path.join(root_path, 'resources', 'qwen.tiktoken'))
elif model.startswith('qwen'):
return QwenTokenizer(
os.path.join(root_path, 'resources', 'qwen.tiktoken'))
else:
raise UnsupportedModel(
f'Not support model: {model}, currently only support qwen models.')
def list_tokenizers() -> List[str]:
"""List support models
Returns:
List[str]: The model list.
"""
return QWEN_SERIALS

View File

@@ -0,0 +1,32 @@
# Copyright (c) Alibaba, Inc. and its affiliates.
from typing import List
class Tokenizer:
"""Base tokenizer interface for local tokenizers.
"""
def __init__(self):
pass
def encode(self, text: str, **kwargs) -> List[int]:
"""Encode input text string to token ids.
Args:
text (str): The string to be encoded.
Returns:
List[int]: The token ids.
"""
pass
def decode(self, token_ids: List[int], **kwargs) -> str:
"""Decode token ids to string.
Args:
token_ids (List[int]): The input token ids.
Returns:
str: The string of the token ids.
"""
pass