Code a compute graph

Code

Let's now try writing our own function. This assumes you have a running TinyChain host, following the instructions in Getting Started:

# new file: test.py

import tinychain as tc

# this is the local TinyChain host you just started with "docker run..."
HOST = tc.host.Host("http://127.0.0.1:8702")

# this endpoint will attempt to run whatever program you send it
# without committing any write operations
ENDPOINT = "/transact/hypothetical"

# define a GET Op
# the type annotations are important!
# without them, TinyChain doesn't know what type to expect the arguments to be
@tc.get_op
def hello(name: tc.String) -> tc.String:
    return tc.String("Hello, {{name}}").render(name=name)

if __name__ == "__main__":
    cxt = tc.Context() # construct a new execution context
    cxt.hello = hello # include our function definition in the context
    cxt.result = cxt.hello("Name") # call the function

    print(HOST.post(ENDPOINT, cxt)) # evaluate the context on the host
                    

Test

Check that it works as expected:

$ python3 test.py
Hello, Name         

This requires some scaffolding in order to set up but it's a very convenient starting point for more advanced use cases.

Understand

If you're curious about how this works under the hood, you can inspect the JSON that gets sent to the host:

# ...
tc.print_json(cxt)  

You should see something like:

[
    [
        "hello",
        {
            "/state/scalar/op/get": [
                "name",
                [
                    [
                        "String_7f8cf85223d0",
                        "Hello, {{name}}"
                    ],
                    [
                        "_return",
                        {
                            "$String_7f8cf85223d0/render": {
                                "name": {
                                    "$name": []
                                }
                            }
                        }
                    ]
                ]
            ]
        }
    ],
    [
        "result",
        {
            "$hello": [
                "Name"
            ]
        }
    ]
]
                    

In general you shouldn't have to worry about what the generated JSON looks like, but it can be convenient to give explicit names to the internal states of an Op. You can do this by using the cxt or txn keyword—just like Python treats the "self" keyword specially in a method declaration, assigning it a reference to the method's instance, TinyChain treats the cxt or txn keyword specially, assigning it a reference to the Op's execution context. For example:

# ...
@tc.get_op
def hello(cxt, name):
    cxt.template = tc.String("Hello, {{name}}")
    return cxt.template.render(name=name)
# ...
                    

If you again inspect the JSON representation of your compute graph, you'll see that the anonymous "String..." name has been replaced by "template."

Last updated