<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def air_gap(self, volume: float = None, height: float = None) -> 'InstrumentContext': """ Pull air into the pipette current tip at the current location :param volume: The amount in uL to aspirate air into the tube. (Default will use all remaining volume in tip) :type volume: float :param height: The number of millimiters to move above the current Well to air-gap aspirate. (Default: 5mm above current Well) :type height: float :raises NoTipAttachedError: If no tip is attached to the pipette :raises RuntimeError: If location cache is None. This should happen if `touch_tip` is called without first calling a method that takes a location (eg, :py:meth:`.aspirate`, :py:meth:`dispense`) :returns: This instance """

        if not self.hw_pipette['has_tip']:
            raise hc.NoTipAttachedError('Pipette has no tip. Aborting air_gap')

        if height is None:
            height = 5
        loc = self._ctx.location_cache
        if not loc or not isinstance(loc.labware, Well):
            raise RuntimeError('No previous Well cached to perform air gap')
        target = loc.labware.top(height)
        self.move_to(target)
        self.aspirate(volume)
        return self