pinecone.grpc.utils
1import uuid 2 3from google.protobuf.struct_pb2 import Struct 4 5 6def _generate_request_id() -> str: 7 return str(uuid.uuid4()) 8 9 10from pinecone.core.openapi.data.models import ( 11 Vector as _Vector, 12 Usage, 13 ScoredVector, 14 SparseValues, 15 FetchResponse, 16 QueryResponse, 17 DescribeIndexStatsResponse, 18 NamespaceSummary, 19) 20 21from typing import Optional 22 23 24def dict_to_proto_struct(d: Optional[dict]) -> "Struct": 25 if not d: 26 d = {} 27 s = Struct() 28 s.update(d) 29 return s 30 31 32def parse_sparse_values(sparse_values: dict): 33 return ( 34 SparseValues(indices=sparse_values["indices"], values=sparse_values["values"]) 35 if sparse_values 36 else SparseValues(indices=[], values=[]) 37 ) 38 39 40def parse_fetch_response(response: dict): 41 vd = {} 42 vectors = response.get("vectors", {}) 43 namespace = response.get("namespace", "") 44 45 for id, vec in vectors.items(): 46 vd[id] = _Vector( 47 id=vec["id"], 48 values=vec["values"], 49 sparse_values=parse_sparse_values(vec.get("sparseValues")), 50 metadata=vec.get("metadata", None), 51 _check_type=False, 52 ) 53 54 return FetchResponse( 55 vectors=vd, 56 namespace=namespace, 57 usage=parse_usage(response.get("usage", {})), 58 _check_type=False, 59 ) 60 61 62def parse_usage(usage: dict): 63 return Usage(read_units=int(usage.get("readUnits", 0))) 64 65 66def parse_query_response(response: dict, _check_type: bool = False): 67 matches = [] 68 for item in response.get("matches", []): 69 sc = ScoredVector( 70 id=item["id"], 71 score=item.get("score", 0.0), 72 values=item.get("values", []), 73 sparse_values=parse_sparse_values(item.get("sparseValues")), 74 metadata=item.get("metadata", None), 75 _check_type=_check_type, 76 ) 77 matches.append(sc) 78 79 # Due to OpenAPI model classes / actual parsing cost, we want to avoid 80 # creating empty `Usage` objects and then passing them into QueryResponse 81 # when they are not actually present in the response from the server. 82 args = { 83 "namespace": response.get("namespace", ""), 84 "matches": matches, 85 "_check_type": _check_type, 86 } 87 usage = response.get("usage") 88 if usage: 89 args["usage"] = parse_usage(usage) 90 return QueryResponse(**args) 91 92 93def parse_stats_response(response: dict): 94 fullness = response.get("indexFullness", 0.0) 95 total_vector_count = response.get("totalVectorCount", 0) 96 dimension = response.get("dimension", 0) 97 summaries = response.get("namespaces", {}) 98 namespace_summaries = {} 99 for key in summaries: 100 vc = summaries[key].get("vectorCount", 0) 101 namespace_summaries[key] = NamespaceSummary(vector_count=vc) 102 return DescribeIndexStatsResponse( 103 namespaces=namespace_summaries, 104 dimension=dimension, 105 index_fullness=fullness, 106 total_vector_count=total_vector_count, 107 _check_type=False, 108 )
def
dict_to_proto_struct(d: Optional[dict]) -> google.protobuf.struct_pb2.Struct:
def
parse_sparse_values(sparse_values: dict):
def
parse_fetch_response(response: dict):
41def parse_fetch_response(response: dict): 42 vd = {} 43 vectors = response.get("vectors", {}) 44 namespace = response.get("namespace", "") 45 46 for id, vec in vectors.items(): 47 vd[id] = _Vector( 48 id=vec["id"], 49 values=vec["values"], 50 sparse_values=parse_sparse_values(vec.get("sparseValues")), 51 metadata=vec.get("metadata", None), 52 _check_type=False, 53 ) 54 55 return FetchResponse( 56 vectors=vd, 57 namespace=namespace, 58 usage=parse_usage(response.get("usage", {})), 59 _check_type=False, 60 )
def
parse_usage(usage: dict):
def
parse_query_response(response: dict, _check_type: bool = False):
67def parse_query_response(response: dict, _check_type: bool = False): 68 matches = [] 69 for item in response.get("matches", []): 70 sc = ScoredVector( 71 id=item["id"], 72 score=item.get("score", 0.0), 73 values=item.get("values", []), 74 sparse_values=parse_sparse_values(item.get("sparseValues")), 75 metadata=item.get("metadata", None), 76 _check_type=_check_type, 77 ) 78 matches.append(sc) 79 80 # Due to OpenAPI model classes / actual parsing cost, we want to avoid 81 # creating empty `Usage` objects and then passing them into QueryResponse 82 # when they are not actually present in the response from the server. 83 args = { 84 "namespace": response.get("namespace", ""), 85 "matches": matches, 86 "_check_type": _check_type, 87 } 88 usage = response.get("usage") 89 if usage: 90 args["usage"] = parse_usage(usage) 91 return QueryResponse(**args)
def
parse_stats_response(response: dict):
94def parse_stats_response(response: dict): 95 fullness = response.get("indexFullness", 0.0) 96 total_vector_count = response.get("totalVectorCount", 0) 97 dimension = response.get("dimension", 0) 98 summaries = response.get("namespaces", {}) 99 namespace_summaries = {} 100 for key in summaries: 101 vc = summaries[key].get("vectorCount", 0) 102 namespace_summaries[key] = NamespaceSummary(vector_count=vc) 103 return DescribeIndexStatsResponse( 104 namespaces=namespace_summaries, 105 dimension=dimension, 106 index_fullness=fullness, 107 total_vector_count=total_vector_count, 108 _check_type=False, 109 )