This cannot be done directly with pattern-matching, but pairing pattern matching with recursion works, though this is not really a good use case for structural pattern matching. We pattern match on the empty list or list of length one as an exit condition to break the recursion.
On each recursive call we slice the list to remove one element from the front.
We are assuming seq is of length two. Without that this use of pattern matching becomes quite difficult.
def has_seq(lst, seq):
  match lst:
    case [] | [_]: return False
    case [x, y, *_]: 
      if [x, y] == seq:
        return True
      else:
        return has_seq(lst[1:], seq)
It's important to remember that names in case patterns do not check to see if an element is equal to an existing variable. Rather they bind a name to that element. If this has the same name as an existing variable, it shadows that variable.
We can put a guard on a pattern to clean up the above.
def has_seq(lst, seq):
  match lst:
    case [] | [_]: return False
    case [x, y, *_] if [x, y] == seq: return True
    case _: return has_seq(lst[1:], seq)
A match can be used to match against literals. If we wanted to check if the first two elements of a list were 1 and 2:
match lst:
  case [1, 2, *_]: ...
But considering has_seq does not hardcode the values to look for, this cannot be utilized.
Of course, I think this looks nicer using a generator expression and any to see if any subsequence of lst of the same length as seq is equal to seq. This has the benefit of handling sequences of any length.
def has_seq(lst, seq):
  return any(lst[i:i+len(seq)] == seq 
             for i in range(len(lst) - len(seq) + 1))
Or, using in, just:
def has_seq(lst, seq):
  return seq in (lst[i:i+len(seq)]
                 for i in range(len(lst) - len(seq) + 1)