def run_vectorise_pipeline(config: Config, queries: List[BulkSearchQueryEntity], device: Union[Device, str]) -> Dict[
    Qidx, List[float]]:
    """Run the query vectorisation process

    Raise:
        api_exceptions.InvalidArgError: If the vectorisation process fails or if the media cannot be downloaded.
    """

    # Prepend the prefixes to the queries if it exists (output should be of type List[BulkSearchQueryEntity])
    try:
        prefixed_queries = add_prefix_to_queries(queries)
    except s2_inference_errors.MediaDownloadError as e:
        raise api_exceptions.InvalidArgError(message=str(e)) from e

    # 1. Pre-process inputs ready for s2_inference.vectorise
    # we can still use qidx_to_job. But the jobs structure may need to be different
    vector_jobs_tuple: Tuple[Dict[Qidx, List[VectorisedJobPointer]], Dict[JHash, VectorisedJobs]] = create_vector_jobs(
        prefixed_queries, config, device)

    qidx_to_jobs, jobs = vector_jobs_tuple

    # 2. Vectorise in batches against all queries
    ## TODO: To ensure that we are vectorising in batches, we can mock vectorise (), and see if the number of calls is as expected (if batch_size = 16, and number of docs = 32, and all args are the same, then number of calls = 2)
    # TODO: we need to enable str/PIL image structure:
    job_ptr_to_vectors: Dict[JHash, Dict[str, List[float]]] = vectorise_jobs(config.inference, list(jobs.values()))

    # 3. For each query, get associated vectors
    qidx_to_vectors: Dict[Qidx, List[float]] = get_query_vectors_from_jobs(
        prefixed_queries, qidx_to_jobs, job_ptr_to_vectors, config, jobs
    )
    return qidx_to_vectors
Run the query vectorisation process

    Raise:
        api_exceptions.InvalidArgError: If the vectorisation process fails or if the media cannot be downloaded.
    
src/marqo/tensor_search/tensor_search.py