from nuxt import route, logger, Request from nuxt.repositorys.validation import fields, use_args import traceback import tiktoken encoding_cache = {} support_models = set(["kimi-k2-turbo-preview", "gpt-3.5-turbo", "gpt-3.5-turbo-16k", "gpt-4", "gpt-4-32k"]) support_model_prefixes = ( "gpt-3.5-turbo-", "gpt-4-", "moonshot-", "kimi-", ) @route("/tokenizer/", methods=["POST"]) @use_args({ "role": fields.Str(required=True), "content": fields.Str(required=True), "name": fields.Str(required=False) }, location="json") def get_num_tokens(req: Request, message: dict, model_name: str): try: return { "code": 200, "num_tokens": num_tokens_from_messages([message], model=model_name) } except Exception as e: logger.error(traceback.format_exc()) return { "code": 500, "msg": "{}".format(e) } def num_tokens_from_messages(messages, model="gpt-3.5-turbo"): """Returns the number of tokens used by a list of messages.""" encoding = None if model in encoding_cache: encoding = encoding_cache.get(model) else: try: encoding = tiktoken.encoding_for_model(model) except KeyError: encoding = tiktoken.get_encoding("cl100k_base") encoding_cache[model] = encoding if model in support_models or model.startswith(support_model_prefixes): num_tokens = 0 for message in messages: num_tokens += 4 # every message follows {role/name}\n{content}\n for key, value in message.items(): num_tokens += len(encoding.encode(value)) if key == "name": # if there's a name, the role is omitted num_tokens += -1 # role is always required and always 1 token num_tokens += 3 # every reply is primed with assistant return num_tokens else: raise NotImplementedError(f"""num_tokens_from_messages() is not presently implemented for model {model}. See https://github.com/openai/openai-python/blob/main/chatml.md for information on how messages are converted to tokens.""")