Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

NUL Digital Collections API

notebooks/smart_cell.livemd

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(&amp;Map.get(&amp;1, field))

      "multivalued_" <> field ->
        dataset
        |> Enum.flat_map(&amp;Map.get(&amp;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)