<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def dot_attention(queries: mx.sym.Symbol, keys: mx.sym.Symbol, values: mx.sym.Symbol, lengths: Optional[mx.sym.Symbol] = None, dropout: float = 0.0, bias: Optional[mx.sym.Symbol] = None, prefix: Optional[str] = ''):
 """ Computes dot attention for a set of queries, keys, and values. :param queries: Attention queries. Shape: (n, lq, d). :param keys: Attention keys. Shape: (n, lk, d). :param values: Attention values. Shape: (n, lk, dv). :param lengths: Optional sequence lengths of the keys. Shape: (n,). :param dropout: Dropout probability. :param bias: Optional 3d bias tensor. :param prefix: Optional prefix :return: 'Context' vectors for each query. Shape: (n, lq, dv). """

    utils.check_condition(lengths is not None or bias is not None,
                          "Must provide either length or bias argument for masking")

    # (n, lq, lk)
    logits = mx.sym.batch_dot(lhs=queries, rhs=keys, transpose_b=True, name='%sdot' % prefix)

    if lengths is not None:
        # mask lk dimension
        # (lk, n, lq)
        logits = mx.sym.transpose(data=logits, axes=(2, 0, 1))
        logits = mx.sym.SequenceMask(data=logits,
                                     use_sequence_length=True,
                                     sequence_length=lengths,
                                     value=C.LARGE_NEGATIVE_VALUE)
        # (n, lq, lk)
        logits = mx.sym.transpose(data=logits, axes=(1, 2, 0))

    if bias is not None:
        logits = mx.sym.broadcast_add(logits, bias, name='%sbias_add' % prefix)

    probs = mx.sym.softmax(logits, axis=-1)
    probs = mx.sym.Dropout(probs, p=dropout) if dropout > 0.0 else probs

    # (n, lq, lk) x (n, lk, dv) -> (n, lq, dv)
    return mx.sym.batch_dot(lhs=probs, rhs=values, name='%scontexts' % prefix)