def replace_node_input(self, node_name: str, old_input: str, new_input: str):
        """Replace an input of a node.

        :param node_name: name of the node.
        :param old_input: name of the input to replace.
        :param new_input: name of the new input.
        """
        if node_name not in self.nodes:
            raise ValueError(f"Node {node_name} does not exist in the graph.")
        if old_input not in self.nodes[node_name].inputs:
            raise ValueError(f"Input {old_input} does not exist in node {node_name}.")
        if new_input not in self.ios:
            raise ValueError(f"Input {new_input} does not exist in the graph.")

        node = self.nodes[node_name]
        # update the node object and proto
        node.inputs[node.inputs.index(old_input)] = new_input
        num_updated = 0
        for i in range(len(node.inputs)):
            if node.proto.input[i] == old_input:
                node.proto.input[i] = new_input

                # update the ios
                self.ios[old_input].destination.remove(node_name)
                self.ios[new_input].destination.append(node_name)

                # update the connections
                old_parent = self.ios[old_input].source
                if not SpecialInput.is_special_input(old_parent):
                    self.connections[old_parent].remove(node_name)

                new_parent = self.ios[new_input].source
                if not SpecialInput.is_special_input(new_parent):
                    self.connections[new_parent].append(node_name)

                num_updated += 1

        if num_updated < 1:
            raise ValueError(f"Input {old_input} does not exist in node {node_name} proto.")
Replace an input of a node.

        :param node_name: name of the node.
        :param old_input: name of the input to replace.
        :param new_input: name of the new input.
        
olive/passes/onnx/onnx_dag.py