Mix.install([
{:artefact_kino, "~> 0.3.0"},
{:req, "~> 0.5"}
])Overview
This livebook is about both Artefact and ArtefactKino.
Artefacts (note Australian spelling) are made objects, and in our universe (an Artefactory) these represent a fragment of knowledge, typically: abstract, insightful, contextual.
Artefacts may also be stored/manipulated in an Artefactory. While Artefacts may be generated and exchanged, our interpretation of them is our own.
As we yarn we naturally exchange and create Artefacts.
ArtefactKino is a Livebook Kino for viewing an Artefact. It isn't an editor.
Us Two
Us Two is the fundamental concept in Agent Society. Matt and Claude yarned about Us Two and memorialized our shared understanding in a the us_two Artefact.
In the cell below us_two is an Artefact struct, you can edit it and change how it renders in the livebook.
I've drawn it, so from my perspective (Matt - Me) I've got an US_TWO relationship with (claude: You).
Try highlighting nodes and relationships in the graph. Explore the Artefact struct, and have examine the create and merge cypher.
require Artefact
us_two = Artefact.new!(
title: "UsTwo",
base_label: "UsTwo",
nodes: [
matt: [labels: ["Agent", "Me"], properties: %{"name" => "Matt"},
uuid: "019da897-f2de-77ca-b5a4-40f0c3730943"],
claude: [labels: ["Agent", "You"], properties: %{"name" => "Claude"},
uuid: "019da897-f2de-768c-94e2-3005f2431f37"]
],
relationships: [
[from: :matt, type: "US_TWO", to: :claude]
]
)
ArtefactKino.new(us_two)Harmonising Artefacts
The Harmonising Artefact memorialises concepts involved in combining knowledge. As this one is a bit more complicated we've just loaded Arrows.App JSON.
artefact =
Req.get!("https://raw.githubusercontent.com/diffo-dev/artefactory/dev/artefact/test/data/artefact_harmonise/arrows.json", decode_body: false).body
|> Artefact.Arrows.from_json!()
ArtefactKino.new(artefact)Harmonizing Artefacts with Bindings
require Artefact
base_url = "https://raw.githubusercontent.com/diffo-dev/artefactory/dev/artefact/test/data"
artefact =
Req.get!("#{base_url}/artefact/arrows.json", decode_body: false).body
|> Artefact.Arrows.from_json!()
create_merge =
Req.get!("#{base_url}/create_merge/arrows.json", decode_body: false).body
|> Artefact.Arrows.from_json!()
{:ok, bindings} = Artefact.Binding.find(artefact, create_merge)
harmonised = Artefact.harmonise(artefact, create_merge, bindings)
ArtefactKino.new(harmonised)In this Kino we produce a new Artefact from two which share a common node.
Binding.find() finds bindings. Artefact.harmonise() creates the new combined Artefact.
Harmonise merges labels and properties of bound nodes, and properties of bound relationships. The left side (heart-side) is the knowledge we hold most dear. Properties with the same key and different value have the value have heart side precedence.
The knowledge we have harmonized here is ArtefactCreateMerge, a combination of Artefact and the CreateMerge Artefacts.
Side by Side
A common pattern is showing knowledge grow progressively — a section artefact on the left,
the integrated whole on the right, chapter by chapter. Kino.Layout.grid places two
ArtefactKino widgets side by side. Two small things make this work well.
Consistent colours. The same label string always produces the same colour, regardless
of how many labels either artefact contains. An Agent node will be the same shade of
blue-green in a two-label artefact as it is in a ten-label one. You can follow a concept
by colour across panels without thinking about it.
Stable header height. When artefacts have descriptions of different lengths — or when
one has no description at all — the headers expand differently and the graph viewports no
longer align. Pass description_lines: to reserve a fixed-height description area of
exactly that many lines. Content is clipped if it is longer; the space is held empty if
there is no description. Both panels share the same header height and the graphs line up.
require Artefact
section =
Artefact.new!(
title: "Section 1",
base_label: "Knowing",
description: "MATCH (a:Agent)-[:KNOWS]->(b:Concept)\nRETURN a, b",
nodes: [
matt: [labels: ["Agent"], properties: %{"name" => "Matt"}, uuid: "019da897-f2de-77ca-b5a4-40f0c3730943"],
knowing: [labels: ["Concept"], properties: %{"name" => "Knowing"}, uuid: "019da897-0000-7000-8000-000000000001"]
],
relationships: [
[from: :matt, type: "KNOWS", to: :knowing]
]
)
integrated =
Artefact.new!(
title: "Integrated",
base_label: "Valuing",
description: "MATCH (a:Agent)-[:KNOWS|VALUES]->(b:Concept)\nRETURN a, b",
nodes: [
matt: [labels: ["Agent"], properties: %{"name" => "Matt"}, uuid: "019da897-f2de-77ca-b5a4-40f0c3730943"],
know: [labels: ["Concept"], properties: %{"name" => "Knowing"}, uuid: "019da897-0000-7000-8000-000000000001"],
value: [labels: ["Concept"], properties: %{"name" => "Valuing"}, uuid: "019da897-0000-7000-8000-000000000002"]
],
relationships: [
[from: :matt, type: "KNOWS", to: :know],
[from: :matt, type: "VALUES", to: :value]
]
)
Kino.Layout.grid([
ArtefactKino.new(section, description_lines: 2),
ArtefactKino.new(integrated, description_lines: 2)
], columns: 2)Add panel_height_px: to fix the total widget height. The header takes what it needs and
the graph row fills the rest. Use both options together and the widget dimensions are fully
locked — the page never reflows as the artefact grows across panels.
Kino.Layout.grid([
ArtefactKino.new(section, description_lines: 2, panel_height_px: 600),
ArtefactKino.new(integrated, description_lines: 2, panel_height_px: 600)
], columns: 2)Notice that the Agent node (Matt) is the same colour in both panels, and the two graph
viewports sit at the same height despite the descriptions being different lengths.
What Next?
Artefacts are knowledge graph fragments. We like to store knowledge in graphical databases, so explore exporting cypher to a graph database with creat and merge. Review the CreateMerge Artifact to understand what create and merge are best for.
Artefacts are Elixir structs so can be peristed as using ETS or similar, and manipulated with code. Write some functions on Artefacts which abstract knowledge or even wisdom. Tell stories.
Experiment memorializing with Artefacts, particularly when yarning or creating with other intelligences, human or otherwise.
Yarn with us about what you'd want in Artefactory DSL, what an Artefactable Elixir Protocol should do, or anything else if you are strangely attracted.
Acknowledgements
Artefactory is new, but the ideas are not. At diffo-dev we are on a journey inspired by Indigenous Systems Thinking and offer our respect and gratitude for the profound wisdom presented by Tyson Yunkaporta in Sand Talk, grounded in countless years of sustainable, harmonious living.