Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
_merge.py209 linesDownload Raw Back to utils
1from __future__ import annotations2 3from typing import Any4 5 6def merge_dicts(left: dict[str, Any], *others: dict[str, Any]) -> dict[str, Any]:7    r"""Merge dictionaries.8 9    Merge many dicts, handling specific scenarios where a key exists in both10    dictionaries but has a value of `None` in `'left'`. In such cases, the method uses11    the value from `'right'` for that key in the merged dictionary.12 13    Args:14        left: The first dictionary to merge.15        others: The other dictionaries to merge.16 17    Returns:18        The merged dictionary.19 20    Raises:21        TypeError: If the key exists in both dictionaries but has a different type.22        TypeError: If the value has an unsupported type.23 24    Example:25        If `left = {"function_call": {"arguments": None}}` and26        `right = {"function_call": {"arguments": "{\n"}}`, then, after merging, for the27        key `'function_call'`, the value from `'right'` is used, resulting in28        `merged = {"function_call": {"arguments": "{\n"}}`.29    """30    merged = left.copy()31    for right in others:32        for right_k, right_v in right.items():33            if right_k not in merged or (34                right_v is not None and merged[right_k] is None35            ):36                merged[right_k] = right_v37            elif right_v is None:38                continue39            elif type(merged[right_k]) is not type(right_v):40                msg = (41                    f'additional_kwargs["{right_k}"] already exists in this message,'42                    " but with a different type."43                )44                raise TypeError(msg)45            elif isinstance(merged[right_k], str):46                # TODO: Add below special handling for 'type' key in 0.3 and remove47                # merge_lists 'type' logic.48                #49                # if right_k == "type":50                #     if merged[right_k] == right_v:51                #         continue52                #     else:53                #         raise ValueError(54                #             "Unable to merge. Two different values seen for special "55                #             f"key 'type': {merged[right_k]} and {right_v}. 'type' "56                #             "should either occur once or have the same value across "57                #             "all dicts."58                #         )59                if (right_k == "index" and merged[right_k].startswith("lc_")) or (60                    right_k in {"id", "output_version", "model_provider"}61                    and merged[right_k] == right_v62                ):63                    continue64                merged[right_k] += right_v65            elif isinstance(merged[right_k], dict):66                merged[right_k] = merge_dicts(merged[right_k], right_v)67            elif isinstance(merged[right_k], list):68                merged[right_k] = merge_lists(merged[right_k], right_v)69            elif merged[right_k] == right_v:70                continue71            elif isinstance(merged[right_k], int):72                # Preserve identification and temporal fields using last-wins strategy73                # instead of summing:74                # - index: identifies which tool call a chunk belongs to75                # - created/timestamp: temporal values that shouldn't be accumulated76                if right_k in {"index", "created", "timestamp"}:77                    merged[right_k] = right_v78                else:79                    merged[right_k] += right_v80            else:81                msg = (82                    f"Additional kwargs key {right_k} already exists in left dict and "83                    f"value has unsupported type {type(merged[right_k])}."84                )85                raise TypeError(msg)86    return merged87 88 89def merge_lists(left: list | None, *others: list | None) -> list | None:90    """Add many lists, handling `None`.91 92    Args:93        left: The first list to merge.94        others: The other lists to merge.95 96    Returns:97        The merged list.98    """99    merged = left.copy() if left is not None else None100    for other in others:101        if other is None:102            continue103        if merged is None:104            merged = other.copy()105        else:106            for e in other:107                if (108                    isinstance(e, dict)109                    and "index" in e110                    and (111                        isinstance(e["index"], int)112                        or (113                            isinstance(e["index"], str) and e["index"].startswith("lc_")114                        )115                    )116                ):117                    to_merge = [118                        i119                        for i, e_left in enumerate(merged)120                        if (121                            "index" in e_left122                            and e_left["index"] == e["index"]  # index matches123                            and (  # IDs not inconsistent124                                e_left.get("id") in (None, "")125                                or e.get("id") in (None, "")126                                or e_left.get("id") == e.get("id")127                            )128                        )129                    ]130                    if to_merge:131                        # TODO: Remove this once merge_dict is updated with special132                        # handling for 'type'.133                        if (left_type := merged[to_merge[0]].get("type")) and (134                            e.get("type") == "non_standard" and "value" in e135                        ):136                            if left_type != "non_standard":137                                # standard + non_standard138                                new_e: dict[str, Any] = {139                                    "extras": {140                                        k: v141                                        for k, v in e["value"].items()142                                        if k != "type"143                                    }144                                }145                            else:146                                # non_standard + non_standard147                                new_e = {148                                    "value": {149                                        k: v150                                        for k, v in e["value"].items()151                                        if k != "type"152                                    }153                                }154                                if "index" in e:155                                    new_e["index"] = e["index"]156                        else:157                            new_e = (158                                {k: v for k, v in e.items() if k != "type"}159                                if "type" in e160                                else e161                            )162                        merged[to_merge[0]] = merge_dicts(merged[to_merge[0]], new_e)163                    else:164                        merged.append(e)165                else:166                    merged.append(e)167    return merged168 169 170def merge_obj(left: Any, right: Any) -> Any:171    """Merge two objects.172 173    It handles specific scenarios where a key exists in both dictionaries but has a174    value of `None` in `'left'`. In such cases, the method uses the value from `'right'`175    for that key in the merged dictionary.176 177    Args:178        left: The first object to merge.179        right: The other object to merge.180 181    Returns:182        The merged object.183 184    Raises:185        TypeError: If the key exists in both dictionaries but has a different type.186        ValueError: If the two objects cannot be merged.187    """188    if left is None or right is None:189        return left if left is not None else right190    if type(left) is not type(right):191        msg = (192            f"left and right are of different types. Left type:  {type(left)}. Right "193            f"type: {type(right)}."194        )195        raise TypeError(msg)196    if isinstance(left, str):197        return left + right198    if isinstance(left, dict):199        return merge_dicts(left, right)200    if isinstance(left, list):201        return merge_lists(left, right)202    if left == right:203        return left204    msg = (205        f"Unable to merge {left=} and {right=}. Both must be of type str, dict, or "206        f"list, or else be two equal objects."207    )208    raise ValueError(msg)209 
codekingpro/portable-devtools · Team Ai