NUL Digital Collections API
Mix.install(
[
{:nul, github: "bmquinn/nul_live"},
{:vega_lite, "~> 0.1.6"},
{:kino_vega_lite, "~> 0.1.7"},
{:kino_bumblebee, "~> 0.1.4"},
{:exla, "~> 0.4.1"}
],
config: [nx: [default_backend: EXLA.Backend]]
)
Smart Cell
result =
Req.post!("https://api.dc.library.northwestern.edu/api/v2/search?as=json",
body:
"{\n \"query\": {\n \"bool\": {\n \"must\": {\n \"match\": {\n \"work_type\": \"Image\"\n }\n }\n }\n },\n \"size\": 25\n}"
).body
Transforming the response
dataset = Map.get(result, "data")
images =
for {image, i} <- Enum.with_index(dataset, 1) do
label =
Kino.Markdown.new("""
#{i}/#{length(dataset)}
#{image["title"]}
""")
link =
Kino.Markdown.new(
"[link](https://digitalcollections.library.northwestern.edu/items/#{image["id"]})"
)
image =
Kino.Markdown.new(
"![#{image["rights_statement"]["label"]}](#{image["thumbnail"] <> "?size=300"})"
)
Kino.Layout.grid([label, image, link], boxed: true)
end
Kino.Layout.grid(images, columns: 2)
Visualizations: graphs and tables
dataset
|> Enum.map(fn record ->
Map.take(record, ~w|id create_date description|)
end)
|> Kino.DataTable.new()
alias VegaLite, as: Vl
Vl.new(width: 400, height: 400)
|> Vl.data_from_values(dataset)
|> Vl.mark(:bar)
|> Vl.encode_field(:x, "preservation_level")
|> Vl.encode(:y, aggregate: :count)
Neural Networks models
{:ok, model_info} = Bumblebee.load_model({:hf, "dslim/bert-base-NER"}, log_params_diff: false)
{:ok, tokenizer} = Bumblebee.load_tokenizer({:hf, "bert-base-cased"})
serving =
Bumblebee.Text.token_classification(model_info, tokenizer,
aggregation: :same,
compile: [batch_size: 1, sequence_length: 100],
defn_options: [compiler: EXLA]
)
select_input =
Kino.Input.select("Choose field:",
multivalued_description: "Description",
singular_title: "Title",
multivalued_alternate_title: "Alternate Title"
)
form = Kino.Control.form([selected: select_input], submit: "Run")
frame = Kino.Frame.new()
form
|> Kino.Control.stream()
|> Kino.listen(fn %{data: %{selected: selected}} ->
selected = Atom.to_string(selected)
texts =
case selected do
"singular_" <> field ->
dataset
|> Enum.map(&Map.get(&1, field))
"multivalued_" <> field ->
dataset
|> Enum.flat_map(&Map.get(&1, field))
end
case texts do
[] ->
Kino.Frame.render(frame, Kino.Markdown.new("No values for that field"))
_ ->
Kino.Frame.render(frame, Kino.Markdown.new(""))
Enum.each(texts, fn text ->
output = Nx.Serving.run(serving, text)
Kino.Frame.append(frame, Kino.Bumblebee.HighlightedText.new(text, output.entities))
end)
end
end)
Kino.Layout.grid([form, frame], boxed: true, gap: 16)