<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def construct_surface(direction, *args, **kwargs):
 """ Generates surfaces from curves. Arguments: * ``args``: a list of curve instances Keyword Arguments (optional):
 * ``degree``: degree of the 2nd parametric direction * ``knotvector``: knot vector of the 2nd parametric direction * ``rational``: flag to generate rational surfaces :param direction: the direction that the input curves lies, i.e. u or v :type direction: str :return: Surface constructed from the curves on the given parametric direction """

    # Input validation
    possible_dirs = ['u', 'v']
    if direction not in possible_dirs:
        raise GeomdlException("Possible direction values: " + ", ".join([val for val in possible_dirs]),
                              data=dict(input_dir=direction))

    size_other = len(args)
    if size_other < 2:
        raise GeomdlException("You need to input at least 2 curves")

    # Get keyword arguments
    degree_other = kwargs.get('degree', 2)
    knotvector_other = kwargs.get('knotvector', knotvector.generate(degree_other, size_other))
    rational = kwargs.get('rational', args[0].rational)

    # Construct the control points of the new surface
    degree = args[0].degree
    num_ctrlpts = args[0].ctrlpts_size
    new_ctrlpts = []
    new_weights = []
    for idx, arg in enumerate(args):
        if degree != arg.degree:
            raise GeomdlException("Input curves must have the same degrees",
                                  data=dict(idx=idx, degree=degree, degree_arg=arg.degree))
        if num_ctrlpts != arg.ctrlpts_size:
            raise GeomdlException("Input curves must have the same number of control points",
                                  data=dict(idx=idx, size=num_ctrlpts, size_arg=arg.ctrlpts_size))
        new_ctrlpts += list(arg.ctrlpts)
        if rational:
            if arg.weights is None:
                raise GeomdlException("Expecting a rational curve",
                                      data=dict(idx=idx, rational=rational, rational_arg=arg.rational))
            new_weights += list(arg.weights)

    # Set variables w.r.t. input direction
    if direction == 'u':
        degree_u = degree_other
        degree_v = degree
        knotvector_u = knotvector_other
        knotvector_v = args[0].knotvector
        size_u = size_other
        size_v = num_ctrlpts
    else:
        degree_u = degree
        degree_v = degree_other
        knotvector_u = args[0].knotvector
        knotvector_v = knotvector_other
        size_u = num_ctrlpts
        size_v = size_other
        if rational:
            ctrlptsw = compatibility.combine_ctrlpts_weights(new_ctrlpts, new_weights)
            ctrlptsw = compatibility.flip_ctrlpts_u(ctrlptsw, size_u, size_v)
            new_ctrlpts, new_weights = compatibility.separate_ctrlpts_weights(ctrlptsw)
        else:
            new_ctrlpts = compatibility.flip_ctrlpts_u(new_ctrlpts, size_u, size_v)

    # Generate the surface
    ns = shortcuts.generate_surface(rational)
    ns.degree_u = degree_u
    ns.degree_v = degree_v
    ns.ctrlpts_size_u = size_u
    ns.ctrlpts_size_v = size_v
    ns.ctrlpts = new_ctrlpts
    if rational:
        ns.weights = new_weights
    ns.knotvector_u = knotvector_u
    ns.knotvector_v = knotvector_v

    # Return constructed surface
    return ns