Skip to content

Commit

Permalink
Load in models into context in Decapodes Creation Mode (#25)
Browse files Browse the repository at this point in the history
* Checkpoint some compose work

* Add full func

* Load in models

* Handle decapodes compile message again

* Cleanup the code a bit

* Write to intermediate file

* Write and unwrap graphviz

* Updates to kernel to better handle subrequests

* Remove SVG and unused context

* Fix weird conflicts

---------

Co-authored-by: Matthew Printz <[email protected]>
  • Loading branch information
fivegrant and mattprintz authored Nov 28, 2023
1 parent b6b3425 commit 7ff0beb
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 241 deletions.
2 changes: 0 additions & 2 deletions beaker/kernel.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
from contexts.subkernels.julia import JuliaSubkernel
from contexts.subkernels.rlang import RSubkernel
from contexts.toolsets import DatasetToolset, MiraModelToolset
from contexts.toolsets.decapodes_toolset import DecapodesToolset
from contexts.toolsets.decapode_creation_toolset import DecapodesCreationToolset


Expand All @@ -46,7 +45,6 @@
AVAILABLE_TOOLSETS = {
"dataset": DatasetToolset,
"mira_model": MiraModelToolset,
"decapodes": DecapodesToolset,
"decapodes_creation": DecapodesCreationToolset,
}

Expand Down
4 changes: 2 additions & 2 deletions contexts/codesets/decapodes/julia-1.9/construct_expr.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using SyntacticModels, Decapodes, Catlab
import JSON3, DisplayAs

{{ var_name|default("_expr") }} = Decapodes.parse_decapode(quote
{{ target }} = @decapode begin
{{ declaration }}
end)
end
20 changes: 14 additions & 6 deletions contexts/codesets/decapodes/julia-1.9/expr_to_info.jl
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
using SyntacticModels, Decapodes, Catlab
import JSON3, DisplayAs

function expr_to_svg(expr)
io = IOBuffer()
Catlab.Graphics.Graphviz.run_graphviz(io, to_graphviz(Decapodes.SummationDecapode(expr)), format="svg")
String(take!(io))
function expr_to_svg(model)
_path = "/tmp/decapode.json"
open(_path, "w") do f
io = IOBuffer()
Catlab.Graphics.Graphviz.run_graphviz(io, to_graphviz(model), format="svg")
end
open(_path, "r") do f
return String(take!(f))
end
end

_response = Dict(
"application/json" => {{ var_name|default("_expr") }},
"image/svg" => expr_to_svg({{ var_name|default("_expr") }})
"application/json" => generate_json_acset({{ target }}),
# "image/svg" => expr_to_svg({{ target }}) # TODO: Reinclude when graphviz bug is fixed
)



_response |> DisplayAs.unlimited JSON3.write
14 changes: 9 additions & 5 deletions contexts/codesets/decapodes/julia-1.9/output_model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ function decapode_to_svg(d)
String(take!(io))
end

_response = []
for model in [{{ var_names }}]
_item = Dict(
"application/json" => model |> Decapodes.Term,
"image/svg" => decapode_to_svg(model)
# {{ var_name|default("model") }} ∘ bytes ∘ gen_image
)
push!(_response, _item)

_response = Dict(
"json" => {{ var_name|default("model") }} |> Decapodes.Term,
"image" => decapode_to_svg({{ var_name|default("model") }})
# {{ var_name|default("model") }} ∘ bytes ∘ gen_image
)
end
_response |> DisplayAs.unlimited JSON3.write
30 changes: 23 additions & 7 deletions contexts/toolsets/decapode_creation_toolset.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class DecapodesCreationToolset(BaseToolset):
codeset_name = "decapodes"

decapodes_expression_dsl: Optional[str] = None
var_name: Optional[str] = "_expr"
target: str = "decapode"

def __init__(self, context, *args, **kwargs):
super().__init__(context=context, *args, **kwargs)
Expand All @@ -38,10 +38,26 @@ def __init__(self, context, *args, **kwargs):
self.reset()

async def setup(self, config, parent_header):
var_names = list(config.keys())

def fetch_model(model_id):
meta_url = f"{os.environ['DATA_SERVICE_URL']}/models/{model_id}"
response = requests.get(meta_url)
if response.status_code >= 300:
raise Exception(f"Failed to retrieve model {model_id} from server returning {response.status_code}")
model = json.dumps(response.json()["model"])
return model

load_commands = [
'%s = parse_json_acset(SummationDecapode{Symbol, Symbol, Symbol},"""%s""")' % (var_name, fetch_model(decapode_id))
for var_name, decapode_id in config.items()
]

command = "\n".join(
[
self.get_code("setup"),
f"{self.var_name} = parse_decapode(quote end)",
"decapode = @decapode begin end",
*load_commands
]
)
print(f"Running command:\n-------\n{command}\n---------")
Expand Down Expand Up @@ -186,8 +202,8 @@ async def send_decapodes_preview_message(
):
if parent_header is None:
parent_header = {}
result = await self.context.evaluate(self.get_code("expr_to_info"))
content = result["return"]
preview = await self.context.evaluate(self.get_code("expr_to_info", {"target": self.target}))
content = preview["return"]
if content is None:
raise RuntimeError("Info not returned for preview")

Expand All @@ -204,7 +220,7 @@ async def compile_expr(self, server, target_stream, data):

command = "\n".join(
[
self.get_code("construct_expr", {"declaration": declaration, "var_name": self.var_name}),
self.get_code("construct_expr", {"declaration": declaration, "target": self.target}),
"nothing"
]
)
Expand Down Expand Up @@ -232,7 +248,7 @@ async def construct_amr(self, server, target_stream, data):
if id_value:
header['id'] = id_value

preview = await self.context.evaluate(self.get_code("expr_to_info", {"var_name": self.var_name}))
preview = await self.context.evaluate(self.get_code("expr_to_info", {"target": self.target}))
model = preview["return"]["application/json"]

amr = {
Expand All @@ -253,7 +269,7 @@ async def save_amr_request(self, server, target_stream, data):
header = content["header"]
header["_type"] = "Header"

preview = await self.context.evaluate(self.get_code("expr_to_info", {"var_name": self.var_name}))
preview = await self.context.evaluate(self.get_code("expr_to_info", {"target": self.target}))
model = preview["return"]["application/json"]

amr = {
Expand Down
213 changes: 0 additions & 213 deletions contexts/toolsets/decapodes_toolset.py

This file was deleted.

6 changes: 4 additions & 2 deletions lib/jupyter_kernel_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,11 +182,13 @@ def sign(self, message, key=None):
return six.ensure_binary(h.hexdigest())

def make_multipart_message(
self, msg_type, content={}, parent_header={}, metadata={}
self, msg_type, content={}, parent_header={}, metadata={}, msg_id=None
):
if msg_id is None:
msg_id = str(uuid.uuid4())
header = {
"date": datetime.datetime.now().isoformat(),
"msg_id": str(uuid.uuid4()),
"msg_id": msg_id,
"username": "kernel",
"session": getattr(self, "session_id", str(uuid.uuid4())),
"msg_type": msg_type,
Expand Down
5 changes: 4 additions & 1 deletion service/dev_ui/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,11 @@ async function createApp(manager: ServiceManager.IManager): void {
}
else if (msg.msg_type === "decapodes_preview") {
const content = msg.content;
// dataPreview.innerHTML = `
// <div>${content["image/svg"]}</div>
// <div>${JSON.stringify(content["application/json"], null, 2)}</div>
// `;
dataPreview.innerHTML = `
<div>${content["image/svg"]}</div>
<div>${JSON.stringify(content["application/json"], null, 2)}</div>
`;
}
Expand Down
Loading

0 comments on commit 7ff0beb

Please sign in to comment.