hyb
2025-12-31 6cdcd01f77e11b72c323603e27ebdb85b15223c9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import json
 
from redis._parsers.helpers import pairs_to_dict
from redis.commands.vectorset.commands import CallbacksOptions
 
 
def parse_vemb_result(response, **options):
    """
    Handle VEMB result since the command can returning different result
    structures depending on input options and on quantization type of the vector set.
 
    Parsing VEMB result into:
    - List[Union[bytes, Union[int, float]]]
    - Dict[str, Union[bytes, str, float]]
    """
    if response is None:
        return response
 
    if options.get(CallbacksOptions.RAW.value):
        result = {}
        result["quantization"] = (
            response[0].decode("utf-8")
            if options.get(CallbacksOptions.ALLOW_DECODING.value)
            else response[0]
        )
        result["raw"] = response[1]
        result["l2"] = float(response[2])
        if len(response) > 3:
            result["range"] = float(response[3])
        return result
    else:
        if options.get(CallbacksOptions.RESP3.value):
            return response
 
        result = []
        for i in range(len(response)):
            try:
                result.append(int(response[i]))
            except ValueError:
                # if the value is not an integer, it should be a float
                result.append(float(response[i]))
 
        return result
 
 
def parse_vlinks_result(response, **options):
    """
    Handle VLINKS result since the command can be returning different result
    structures depending on input options.
    Parsing VLINKS result into:
    - List[List[str]]
    - List[Dict[str, Number]]
    """
    if response is None:
        return response
 
    if options.get(CallbacksOptions.WITHSCORES.value):
        result = []
        # Redis will return a list of list of strings.
        # This list have to be transformed to list of dicts
        for level_item in response:
            level_data_dict = {}
            for key, value in pairs_to_dict(level_item).items():
                value = float(value)
                level_data_dict[key] = value
            result.append(level_data_dict)
        return result
    else:
        # return the list of elements for each level
        # list of lists
        return response
 
 
def parse_vsim_result(response, **options):
    """
    Handle VSIM result since the command can be returning different result
    structures depending on input options.
    Parsing VSIM result into:
    - List[List[str]]
    - List[Dict[str, Number]] - when with_scores is used (without attributes)
    - List[Dict[str, Mapping[str, Any]]] - when with_attribs is used (without scores)
    - List[Dict[str, Union[Number, Mapping[str, Any]]]] - when with_scores and with_attribs are used
 
    """
    if response is None:
        return response
 
    withscores = bool(options.get(CallbacksOptions.WITHSCORES.value))
    withattribs = bool(options.get(CallbacksOptions.WITHATTRIBS.value))
 
    # Exactly one of withscores or withattribs is True
    if (withscores and not withattribs) or (not withscores and withattribs):
        # Redis will return a list of list of pairs.
        # This list have to be transformed to dict
        result_dict = {}
        if options.get(CallbacksOptions.RESP3.value):
            resp_dict = response
        else:
            resp_dict = pairs_to_dict(response)
        for key, value in resp_dict.items():
            if withscores:
                value = float(value)
            else:
                value = json.loads(value) if value else None
 
            result_dict[key] = value
        return result_dict
    elif withscores and withattribs:
        it = iter(response)
        result_dict = {}
        if options.get(CallbacksOptions.RESP3.value):
            for elem, data in response.items():
                if data[1] is not None:
                    attribs_dict = json.loads(data[1])
                else:
                    attribs_dict = None
                result_dict[elem] = {"score": data[0], "attributes": attribs_dict}
        else:
            for elem, score, attribs in zip(it, it, it):
                if attribs is not None:
                    attribs_dict = json.loads(attribs)
                else:
                    attribs_dict = None
 
                result_dict[elem] = {"score": float(score), "attributes": attribs_dict}
        return result_dict
    else:
        # return the list of elements for each level
        # list of lists
        return response