<jupyter_start><jupyter_text>Writing custom steps The Graph executes built-in task classes, or task classes and functions that you implement.The task parameters include the following:* `class_name` (str): the relative or absolute class name.* `handler` (str): the function handler (if class_name is not specified it is the function handler).* `**class_args`: a set of class `__init__` arguments.For example, see the following simple `echo` class:<jupyter_code>import mlrun
# mlrun: start
# echo class, custom class example
class Echo:
    def __init__(self, context, name=None, **kw):
        self.context = context
        self.name = name
        self.kw = kw
        
    def do(self, x):
        print("Echo:", self.name, x)
        return x
# mlrun: end<jupyter_output><empty_output><jupyter_text>Test the graph: first convert the code to function, and then add the step to the graph:<jupyter_code>fn_echo = mlrun.code_to_function("echo_function", kind="serving", image="mlrun/mlrun")

graph_echo = fn_echo.set_topology("flow")

graph_echo.to(class_name="Echo", name="pre-process", some_arg='abc')

graph_echo.plot(rankdir='LR')<jupyter_output><empty_output><jupyter_text>Create a mock server to test this locally:<jupyter_code>echo_server = fn_echo.to_mock_server(current_function="*")

result = echo_server.test("", {"inputs": 123})

print(result)<jupyter_output>{'id': '97397ea412334afdb5e4cb7d7c2e6dd3'}
Echo: pre-process {'inputs': 123}
{'fraction_non_alphanumeric': 0.11964038727524205, 'fraction_numerical': 0.016597510373443983, 'mean_word_length': 5.488789237668161, 'pattern_counts': {'":': 1, '<': 12, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '3', 'dir': 'jupyter-structured-clean-dedup', 'id': '7392', 'license': 'Apache-2.0', 'n_tokens_mistral': 488, 'n_tokens_neox': 467, 'n_words': 133, 'path': 'docs/serving/writing-custom-steps.ipynb', 'repo_name': 'george0st/mlrun', 'size': '1446'}