I addressed some points in @Menglong Li's answer and simplified the code.
import inspect
import functools
def ignore_unmatched_kwargs(f):
    """Make function ignore unmatched kwargs.
    
    If the function already has the catch all **kwargs, do nothing.
    """
    if contains_var_kwarg(f):
        return f
    
    @functools.wraps(f)
    def inner(*args, **kwargs):
        filtered_kwargs = {
            key: value
            for key, value in kwargs.items()
            if is_kwarg_of(key, f)
        }
        return f(*args, **filtered_kwargs)
    return inner
def contains_var_kwarg(f):
    return any(
        param.kind == inspect.Parameter.VAR_KEYWORD
        for param in inspect.signature(f).parameters.values()
    )
def is_kwarg_of(key, f):
    param = inspect.signature(f).parameters.get(key, False)
    return param and (
        param.kind is inspect.Parameter.KEYWORD_ONLY or
        param.kind is inspect.Parameter.POSITIONAL_OR_KEYWORD
    )
Here are some test cases:
@ignore_unmatched_kwargs
def positional_or_keywords(x, y):
    return x, y
@ignore_unmatched_kwargs
def keyword_with_default(x, y, z = True):
    return x, y, z
@ignore_unmatched_kwargs
def variable_length(x, y, *args, **kwargs):
    return x, y, args,kwargs
@ignore_unmatched_kwargs
def keyword_only(x, *, y):
    return x, y
# these test should run without error
print(
    positional_or_keywords(x = 3, y = 5, z = 10),
    positional_or_keywords(3, y = 5),
    positional_or_keywords(3, 5),
    positional_or_keywords(3, 5, z = 10),
    keyword_with_default(2, 2),
    keyword_with_default(2, 2, z = False),
    keyword_with_default(2, 2, False),
    variable_length(2, 3, 5, 6, z = 3),
    keyword_only(1, y = 3),
    sep='\n'
)
# these test should raise an error
print(
    #positional_or_keywords(3, 5, 6, 4),
    #keyword_with_default(2, 2, 3, z = False),
    #keyword_only(1, 2),
    sep = '\n'
)