Spaces:
Running
Running
<!-- livebook:{"app_settings":{"access_type":"public","auto_shutdown_ms":5000,"multi_session":true,"output_type":"rich","show_existing_sessions":false,"slug":"mystery"},"autosave_interval_s":null,"file_entries":[{"file":{"file_system_id":"local","file_system_type":"local","path":"/data/messages.term"},"name":"messages.term","type":"file"}],"persist_outputs":true} --> | |
# Mysterious Crystal Ball | |
```elixir | |
Mix.install( | |
[ | |
{:bumblebee, "~> 0.5.3"}, | |
{:nx, "~> 0.7.0"}, | |
{:exla, "~> 0.7.0"}, | |
{:axon, "~> 0.6.1"}, | |
{:kino, "~> 0.12.0"}, | |
{:req, "~> 0.4.11"}, | |
{:kino_bumblebee, "~> 0.5.0"}, | |
{:nimble_csv, "~> 1.2"} | |
], | |
config: [nx: [default_backend: EXLA.Backend]] | |
) | |
Kino.Frame.new(placeholder: false) | |
``` | |
## Section | |
```elixir | |
html = | |
Kino.HTML.new(""" | |
<style> | |
.truth-container { | |
display: flex; | |
flex-direction: column; | |
justify-content: center; | |
height: 38.5rem; | |
padding: 0.5rem; | |
} | |
.collapse-x { | |
transform: scaleX(0); | |
transition: transform 0.8s; | |
} | |
.collapse-y { | |
transform: scaley(0); | |
transition: transform 0.8s; | |
} | |
.gone { | |
display: none; | |
} | |
.exists { | |
display: block; | |
} | |
#beyond-truth { | |
width: 100%; | |
display: flex; | |
justify-content: center; | |
} | |
#beyond-truth.gone { | |
margin: 0; | |
padding: 0; | |
height: 0; | |
} | |
#globe-canvas { | |
margin: auto; | |
max-width: 100%; | |
width: 37.5rem; | |
height: auto; | |
} | |
#globe-canvas.gone { | |
height: 0; | |
} | |
.orb { | |
width: 40rem; | |
height: 40rem; | |
border-radius: 50%; | |
box-shadow: 0px 0px 16px rgba(81, 81, 231, 0.4); /* Subtle shadow */ | |
} | |
.message { | |
margin-top: 20px; | |
font-family: monospace; | |
color: rgba(81, 81, 231, 1); | |
} | |
</style> | |
<div class="truth-container"> | |
<canvas id="globe-canvas" width="600" height="600" class="orb"></canvas> | |
<div id="beyond-truth" class="message gone"></div > | |
</div> | |
<script> | |
const canvas = document.getElementById('globe-canvas'); | |
canvas.addEventListener('click', shatterGlobe); | |
let isCollapsing = false; | |
let hasCollapsed = false; | |
const context = canvas.getContext('2d'); | |
const tiltAngle = Math.PI / 228; | |
let rotation = 90; | |
const dots = []; | |
const radius = 120; | |
// Create dots on the globe | |
for (let lat = 0; lat < Math.PI; lat += Math.PI / 30) { | |
for (let lon = 0; lon < 2 * Math.PI; lon += Math.PI / 30) { | |
const x = radius * Math.sin(lat) * Math.cos(lon); | |
const y = radius * Math.sin(lat) * Math.sin(lon); | |
const z = radius * Math.cos(lat); | |
dots.push({x: x, y: y, z: z}); | |
} | |
} | |
function draw() { | |
context.clearRect(0, 0, canvas.width, canvas.height); | |
context.translate(canvas.width / 2, canvas.height / 2); | |
context.rotate(tiltAngle); | |
// Rotate the globe | |
if (!hasCollapsed) { | |
rotation += 0.01; | |
} | |
dots.forEach(function(dot) { | |
const x = dot.x * Math.cos(rotation) - dot.z * Math.sin(rotation); | |
const y = dot.y; | |
const z = dot.z * Math.cos(rotation) + dot.x * Math.sin(rotation); | |
const brightness = 1 - (z / radius + 1.25) / 2; | |
const size = 2 - z / radius; | |
context.fillRect(x, y, size, size); | |
context.fillStyle = 'rgba(81, 81, 231, ' + brightness + ')'; | |
}); | |
context.rotate(-tiltAngle) | |
if (isCollapsing) { | |
let collapsed = true; | |
dots.forEach(dot => { | |
dot.y = (dot.y + 0.001 )* 1.015; // Adjust the speed of falling | |
// Check for bottom boundary | |
if (Math.abs(dot.y) > canvas.height / 2) { | |
dot.y = canvas.height / 2; // Stop it at the 'ground' | |
} else { | |
collapsed = false; | |
} | |
}); | |
if (collapsed) { | |
hasCollapsed = true; | |
} | |
} | |
context.translate(-canvas.width / 2, -canvas.height / 2); | |
if (!hasCollapsed) { | |
requestAnimationFrame(draw); | |
} else { | |
console.log({why: "Look what you have done to my precious orb!"}); | |
canvas.classList.add("collapse-x"); | |
setTimeout(() => { | |
canvas.classList.add("collapse-y"); | |
}, 1000) | |
setTimeout(() => { | |
canvas.classList.add("gone"); | |
}, 2000) | |
setTimeout(() => { | |
const beyondTruth = document.getElementById("beyond-truth"); | |
beyondTruth.classList.remove("gone"); | |
const subTitle = document.createElement("h3"); | |
subTitle.innerText = "Now what is the secret of Today?"; | |
beyondTruth.appendChild(subTitle); | |
}, 2100) | |
} | |
} | |
function shatterGlobe() { | |
isCollapsing = true; | |
} | |
draw(); | |
</script> | |
""") | |
main_frame = Kino.Frame.new() |> Kino.render() | |
Kino.Frame.render(main_frame, html) | |
Kino.Frame.new(placeholder: false) | |
``` | |
```elixir | |
message_frame = Kino.Frame.new(placeholder: false) |> Kino.render() | |
message_pid = | |
spawn(fn -> | |
receive_message = fn loop -> | |
receive do | |
{:message, message} -> | |
Kino.Frame.render( | |
message_frame, | |
Kino.HTML.new(""" | |
<div class="message" style="color: rgba(81, 81, 231, 0.8); display: flex;"> | |
<pre style="margin: auto;">#{message}</pre> | |
</div> | |
""") | |
) | |
loop.(loop) | |
_ -> | |
{:error} | |
end | |
end | |
receive_message.(receive_message) | |
end) | |
Kino.Frame.new(placeholder: false) | |
``` | |
```elixir | |
status_frame = Kino.Frame.new(placeholder: false) |> Kino.render() | |
status_pid = | |
spawn(fn -> | |
receive_messages = fn loop -> | |
receive do | |
{:status, status} -> | |
Kino.Frame.render( | |
status_frame, | |
Kino.HTML.new(""" | |
<div style="position: absolue; bottom: 0px; font-size: 6px; color: rgba(81, 81, 231, 0.4)"><pre>Status: #{status}</pre></div> | |
""") | |
) | |
loop.(loop) | |
_ -> | |
{:error} | |
end | |
end | |
receive_messages.(receive_messages) | |
end) | |
Kino.Frame.new(placeholder: false) | |
``` | |
```elixir | |
file_name = "messages.term" | |
case File.exists?(file_name) do | |
false -> File.touch!(file_name) | |
_ -> :ok | |
end | |
binary = File.read!(file_name) | |
extract_today = fn binary -> | |
case byte_size(binary) do | |
0 -> | |
[result | _] = :erlang.binary_to_term(binary) | |
case result.date == Date.utc_today() do | |
true -> {:ok, result.data} | |
_ -> {:no, false} | |
end | |
_ -> | |
{:no, false} | |
end | |
end | |
loaded_today_data = | |
case String.length(binary) == 0 do | |
true -> {:no, false} | |
_ -> extract_today.(binary) | |
end | |
frame = Kino.Frame.new(placeholder: false) | |
``` | |
```elixir | |
bumblebee = fn -> | |
{:ok, cosmo} = Bumblebee.load_model({:hf, "HuggingFaceTB/cosmo-1b"}) | |
{:ok, tokenizer} = Bumblebee.load_tokenizer({:hf, "HuggingFaceTB/cosmo-1b"}) | |
{:ok, generation_config} = Bumblebee.load_generation_config({:hf, "HuggingFaceTB/cosmo-1b"}) | |
generation_config = | |
Bumblebee.configure(generation_config, | |
max_new_tokens: 50, | |
strategy: %{type: :multinomial_sampling, top_p: 0.6} | |
) | |
serving = | |
Bumblebee.Text.generation(cosmo, tokenizer, generation_config, | |
compile: [batch_size: 1, sequence_length: 256], | |
stream: true, | |
defn_options: [compiler: EXLA] | |
) | |
Kino.start_child!({Nx.Serving, name: :cosmo, serving: serving}) | |
%{name: :cosmo, serving: serving} | |
end | |
crypticize = fn subject, i -> | |
prompt = | |
"<s> [INST]You will write a cryptic message in the form of a haiku in paragraph form about this headline: \"#{subject}\"[/INST]" | |
tokens = | |
Nx.Serving.batched_run(:cosmo, prompt) | |
|> Stream.chunk_every(2) | |
|> Enum.reduce([], fn token, acc -> acc ++ token end) | |
send(status_pid, {:status, i}) | |
tokens | |
|> Enum.join() | |
end | |
Kino.Frame.new(placeholder: false) | |
``` | |
```elixir | |
themes = [ | |
"business", | |
"technology", | |
"science", | |
"health", | |
"politics", | |
"world", | |
"education", | |
"entertainment", | |
"games", | |
"movie", | |
"TV", | |
"lifestyle", | |
"opinion", | |
"self-improvement", | |
"positivism", | |
"fun%20facts", | |
"community", | |
"wholesome", | |
"human%20interest", | |
"inspirational" | |
] | |
theme = themes |> Enum.random() | |
select_message = fn messages -> | |
sanitize = fn text -> | |
text | |
|> String.replace(~r/\[\/INST\]/, "") | |
|> String.replace(~r/\[INST\]/, "") | |
end | |
messages |> Enum.random() |> sanitize.() | |
end | |
news_loader = fn -> | |
response = | |
receive do | |
{:fetched, data} -> data | |
_ -> raise "Could not fetch data" | |
end | |
bumblebee.() | |
results = response.body["results"] | |
messages = | |
results | |
|> Enum.map(fn news_item -> news_item["title"] end) | |
|> Enum.with_index() | |
|> Enum.map(fn {subject, index} -> crypticize.(subject, index) end) | |
date = Date.utc_today() | |
data = | |
messages | |
|> Enum.join("{nextItem}") | |
map = %{date: date, data: data, theme: theme} | |
prev_data = | |
case String.length(binary) == 0 do | |
true -> [] | |
_ -> :erlang.binary_to_term(binary) | |
end | |
[map] ++ prev_data | |
end | |
handler_pid = | |
case loaded_today_data do | |
{:no, _} -> | |
spawn(fn -> | |
receive do | |
{:fetched, data} -> File.write(file_name, :erlang.term_to_binary(data)) | |
_ -> raise "Could not analyze data" | |
end | |
end) | |
_ -> | |
false | |
end | |
loader_pid = | |
case loaded_today_data do | |
{:no, _} -> | |
spawn(fn -> | |
data = news_loader.() | |
if is_pid(handler_pid) do | |
send(handler_pid, {:fetched, data}) | |
end | |
[first_data | _] = data | |
messages = | |
first_data.data | |
|> String.split("{nextItem}") | |
Process.send_after(message_pid, {:message, select_message.(messages)}, 500) | |
end) | |
_ -> | |
false | |
end | |
fetcher_pid = | |
case loaded_today_data do | |
{:no, _} -> | |
spawn(fn -> | |
apikey = System.fetch_env!("LB_NEWSDATA_KEY") | |
data = Req.get!("https://newsdata.io/api/1/news?apikey=#{apikey}&q=#{theme}") | |
if is_pid(loader_pid) do | |
send(loader_pid, {:fetched, data}) | |
end | |
end) | |
_ -> | |
false | |
end | |
get_first = fn binary -> | |
case byte_size(binary) do | |
0 -> | |
false | |
_ -> | |
[head | _tail] = :erlang.binary_to_term(binary) | |
head | |
end | |
end | |
unpack_data = fn data -> | |
{:ok, unpacked} = data | |
unpacked | |
end | |
today_data = | |
case loaded_today_data do | |
{:no, _} -> | |
case byte_size(binary) do | |
0 -> | |
"" | |
_ -> | |
first = get_first.(binary) | |
first.data | |
end | |
_ -> | |
unpack_data.(loaded_today_data) | |
end | |
Kino.Frame.new(placeholder: false) | |
``` | |
```elixir | |
random_message = | |
today_data | |
|> String.split("{nextItem}") | |
|> select_message.() | |
send(message_pid, {:message, random_message}) | |
Kino.Frame.new(placeholder: false) | |
``` | |
<!-- livebook:{"offset":11969,"stamp":{"token":"XCP.iIVI4xv_1GYusasCFjEbGmeI2kB0YkVy75HklXNmtEKySH2FCP_-meZfeL92Wb1W-5nHUJ3wUoqecAcQmJ114Z8RvFGkAgF_nzU6m63EhEdNgGuQcLIfhOp__iGeqT5HBvk9","version":2}} --> | |