code: def create_component_search(index):
      alternative_dot = pynnd_dist.alternative_dot
      alternative_cosine = pynnd_dist.alternative_cosine
  
      data = index._raw_data
      indptr = index._search_graph.indptr
      indices = index._search_graph.indices
      dist = index._distance_func
  
      @numba.njit(
          fastmath=True,
          nogil=True,
          locals={
              "current_query": numba.types.float32[::1],
              "i": numba.types.uint32,
              "j": numba.types.uint32,
              "heap_priorities": numba.types.float32[::1],
              "heap_indices": numba.types.int32[::1],
              "candidate": numba.types.int32,
              "vertex": numba.types.int32,
              "d": numba.types.float32,
              "d_vertex": numba.types.float32,
              "visited": numba.types.uint8[::1],
              "indices": numba.types.int32[::1],
              "indptr": numba.types.int32[::1],
              "data": numba.types.float32[:, ::1],
              "heap_size": numba.types.int16,
              "distance_scale": numba.types.float32,
              "distance_bound": numba.types.float32,
              "seed_scale": numba.types.float32,
          },
      )
      def custom_search_closure(
          query_points, candidate_indices, k, epsilon, visited
      ):
          result = make_heap(query_points.shape[0], k)
          distance_scale = 1.0 + epsilon
  
          for i in range(query_points.shape[0]):
              visited[:] = 0
              if dist == alternative_dot or dist == alternative_cosine:
                  norm = np.sqrt((query_points[i] ** 2).sum())
                  if norm > 0.0:
                      current_query = query_points[i] / norm
                  else:
                      continue
              else:
                  current_query = query_points[i]
  
              heap_priorities = result[1][i]
              heap_indices = result[0][i]
              seed_set = [
                  (np.float32(np.inf), np.int32(-1)) for j in range(0)
              ]
  
              ############ Init ################
              n_initial_points = candidate_indices.shape[0]
  
              for j in range(n_initial_points):
                  candidate = np.int32(candidate_indices[j])
                  d = dist(data[candidate], current_query)
                  # indices are guaranteed different
                  simple_heap_push(
                      heap_priorities, heap_indices, d, candidate
                  )
                  heapq.heappush(seed_set, (d, candidate))
                  mark_visited(visited, candidate)
  
              ############ Search ##############
              distance_bound = distance_scale * heap_priorities[0]
  
              # Find smallest seed point
              d_vertex, vertex = heapq.heappop(seed_set)
  
              while d_vertex < distance_bound:
                  for j in range(indptr[vertex], indptr[vertex + 1]):
                      candidate = indices[j]
  
                      if has_been_visited(visited, candidate) == 0:
                          mark_visited(visited, candidate)
  
                          d = dist(data[candidate], current_query)
  
                          if d < distance_bound:
                              simple_heap_push(
                                  heap_priorities,
                                  heap_indices,
                                  d,
                                  candidate,
                              )
                              heapq.heappush(seed_set, (d, candidate))
                              # Update bound
                              distance_bound = (
                                  distance_scale * heap_priorities[0]
                              )
  
                  # find new smallest seed point
                  if len(seed_set) == 0:
                      break
                  else:
                      d_vertex, vertex = heapq.heappop(seed_set)
  
          return result
  
      return custom_search_closure
  
file_path: pynndescent/pynndescent/graph_utils.py
imports: import numba
  import numpy
  import heapq
  from scipy.sparse import coo_matrix
  from scipy.sparse.csgraph import connected_components
  from itertools import combinations
  import pynndescent.distances
  import joblib
  from pynndescent.utils import rejection_sample, make_heap, deheap_sort, simple_heap_push, has_been_visited, mark_visited
label_desc: Use image node_id 1 for calling a global function with example usage: create_component_search(index) and returns: custom_search_closure, result