CoolFace
Apppublic

krinlove/open-webui

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
misc.py290 linesDownload Raw Back to utils
1from pathlib import Path2import hashlib3import json4import re5from datetime import timedelta6from typing import Optional, List, Tuple7import uuid8import time9 10 11def get_last_user_message(messages: List[dict]) -> str:12    for message in reversed(messages):13        if message["role"] == "user":14            if isinstance(message["content"], list):15                for item in message["content"]:16                    if item["type"] == "text":17                        return item["text"]18            return message["content"]19    return None20 21 22def get_last_assistant_message(messages: List[dict]) -> str:23    for message in reversed(messages):24        if message["role"] == "assistant":25            if isinstance(message["content"], list):26                for item in message["content"]:27                    if item["type"] == "text":28                        return item["text"]29            return message["content"]30    return None31 32 33def get_system_message(messages: List[dict]) -> dict:34    for message in messages:35        if message["role"] == "system":36            return message37    return None38 39 40def remove_system_message(messages: List[dict]) -> List[dict]:41    return [message for message in messages if message["role"] != "system"]42 43 44def pop_system_message(messages: List[dict]) -> Tuple[dict, List[dict]]:45    return get_system_message(messages), remove_system_message(messages)46 47 48def add_or_update_system_message(content: str, messages: List[dict]):49    """50    Adds a new system message at the beginning of the messages list51    or updates the existing system message at the beginning.52 53    :param msg: The message to be added or appended.54    :param messages: The list of message dictionaries.55    :return: The updated list of message dictionaries.56    """57 58    if messages and messages[0].get("role") == "system":59        messages[0]["content"] += f"{content}\n{messages[0]['content']}"60    else:61        # Insert at the beginning62        messages.insert(0, {"role": "system", "content": content})63 64    return messages65 66 67def stream_message_template(model: str, message: str):68    return {69        "id": f"{model}-{str(uuid.uuid4())}",70        "object": "chat.completion.chunk",71        "created": int(time.time()),72        "model": model,73        "choices": [74            {75                "index": 0,76                "delta": {"content": message},77                "logprobs": None,78                "finish_reason": None,79            }80        ],81    }82 83 84def get_gravatar_url(email):85    # Trim leading and trailing whitespace from86    # an email address and force all characters87    # to lower case88    address = str(email).strip().lower()89 90    # Create a SHA256 hash of the final string91    hash_object = hashlib.sha256(address.encode())92    hash_hex = hash_object.hexdigest()93 94    # Grab the actual image URL95    return f"https://www.gravatar.com/avatar/{hash_hex}?d=mp"96 97 98def calculate_sha256(file):99    sha256 = hashlib.sha256()100    # Read the file in chunks to efficiently handle large files101    for chunk in iter(lambda: file.read(8192), b""):102        sha256.update(chunk)103    return sha256.hexdigest()104 105 106def calculate_sha256_string(string):107    # Create a new SHA-256 hash object108    sha256_hash = hashlib.sha256()109    # Update the hash object with the bytes of the input string110    sha256_hash.update(string.encode("utf-8"))111    # Get the hexadecimal representation of the hash112    hashed_string = sha256_hash.hexdigest()113    return hashed_string114 115 116def validate_email_format(email: str) -> bool:117    if email.endswith("@localhost"):118        return True119 120    return bool(re.match(r"[^@]+@[^@]+\.[^@]+", email))121 122 123def sanitize_filename(file_name):124    # Convert to lowercase125    lower_case_file_name = file_name.lower()126 127    # Remove special characters using regular expression128    sanitized_file_name = re.sub(r"[^\w\s]", "", lower_case_file_name)129 130    # Replace spaces with dashes131    final_file_name = re.sub(r"\s+", "-", sanitized_file_name)132 133    return final_file_name134 135 136def extract_folders_after_data_docs(path):137    # Convert the path to a Path object if it's not already138    path = Path(path)139 140    # Extract parts of the path141    parts = path.parts142 143    # Find the index of '/data/docs' in the path144    try:145        index_data_docs = parts.index("data") + 1146        index_docs = parts.index("docs", index_data_docs) + 1147    except ValueError:148        return []149 150    # Exclude the filename and accumulate folder names151    tags = []152 153    folders = parts[index_docs:-1]154    for idx, part in enumerate(folders):155        tags.append("/".join(folders[: idx + 1]))156 157    return tags158 159 160def parse_duration(duration: str) -> Optional[timedelta]:161    if duration == "-1" or duration == "0":162        return None163 164    # Regular expression to find number and unit pairs165    pattern = r"(-?\d+(\.\d+)?)(ms|s|m|h|d|w)"166    matches = re.findall(pattern, duration)167 168    if not matches:169        raise ValueError("Invalid duration string")170 171    total_duration = timedelta()172 173    for number, _, unit in matches:174        number = float(number)175        if unit == "ms":176            total_duration += timedelta(milliseconds=number)177        elif unit == "s":178            total_duration += timedelta(seconds=number)179        elif unit == "m":180            total_duration += timedelta(minutes=number)181        elif unit == "h":182            total_duration += timedelta(hours=number)183        elif unit == "d":184            total_duration += timedelta(days=number)185        elif unit == "w":186            total_duration += timedelta(weeks=number)187 188    return total_duration189 190 191def parse_ollama_modelfile(model_text):192    parameters_meta = {193        "mirostat": int,194        "mirostat_eta": float,195        "mirostat_tau": float,196        "num_ctx": int,197        "repeat_last_n": int,198        "repeat_penalty": float,199        "temperature": float,200        "seed": int,201        "tfs_z": float,202        "num_predict": int,203        "top_k": int,204        "top_p": float,205        "num_keep": int,206        "typical_p": float,207        "presence_penalty": float,208        "frequency_penalty": float,209        "penalize_newline": bool,210        "numa": bool,211        "num_batch": int,212        "num_gpu": int,213        "main_gpu": int,214        "low_vram": bool,215        "f16_kv": bool,216        "vocab_only": bool,217        "use_mmap": bool,218        "use_mlock": bool,219        "num_thread": int,220    }221 222    data = {"base_model_id": None, "params": {}}223 224    # Parse base model225    base_model_match = re.search(226        r"^FROM\s+(\w+)", model_text, re.MULTILINE | re.IGNORECASE227    )228    if base_model_match:229        data["base_model_id"] = base_model_match.group(1)230 231    # Parse template232    template_match = re.search(233        r'TEMPLATE\s+"""(.+?)"""', model_text, re.DOTALL | re.IGNORECASE234    )235    if template_match:236        data["params"] = {"template": template_match.group(1).strip()}237 238    # Parse stops239    stops = re.findall(r'PARAMETER stop "(.*?)"', model_text, re.IGNORECASE)240    if stops:241        data["params"]["stop"] = stops242 243    # Parse other parameters from the provided list244    for param, param_type in parameters_meta.items():245        param_match = re.search(rf"PARAMETER {param} (.+)", model_text, re.IGNORECASE)246        if param_match:247            value = param_match.group(1)248 249            try:250                if param_type == int:251                    value = int(value)252                elif param_type == float:253                    value = float(value)254                elif param_type == bool:255                    value = value.lower() == "true"256            except Exception as e:257                print(e)258                continue259 260            data["params"][param] = value261 262    # Parse adapter263    adapter_match = re.search(r"ADAPTER (.+)", model_text, re.IGNORECASE)264    if adapter_match:265        data["params"]["adapter"] = adapter_match.group(1)266 267    # Parse system description268    system_desc_match = re.search(269        r'SYSTEM\s+"""(.+?)"""', model_text, re.DOTALL | re.IGNORECASE270    )271    system_desc_match_single = re.search(272        r"SYSTEM\s+([^\n]+)", model_text, re.IGNORECASE273    )274 275    if system_desc_match:276        data["params"]["system"] = system_desc_match.group(1).strip()277    elif system_desc_match_single:278        data["params"]["system"] = system_desc_match_single.group(1).strip()279 280    # Parse messages281    messages = []282    message_matches = re.findall(r"MESSAGE (\w+) (.+)", model_text, re.IGNORECASE)283    for role, content in message_matches:284        messages.append({"role": role, "content": content})285 286    if messages:287        data["params"]["messages"] = messages288 289    return data290