<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[To Boldly Code]]></title><description><![CDATA[Explore articles by Daniel Alves Rösel on AI engineering, open-source software, self-hosting, and data science. Discover practical guides and cutting edges projects like JUNO and DIET COKE.]]></description><link>https://blog.alves.world</link><generator>RSS for Node</generator><lastBuildDate>Tue, 13 Oct 2026 14:09:29 GMT</lastBuildDate><atom:link href="https://blog.alves.world/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[TPUs for Reinforcement Learning and Behavioral Modeling]]></title><description><![CDATA[Given that you have created a TPU deployment on GCP, you are now probably trying to figure out how to run your carefully crafted training on this compute. This overview will highlight my learning from]]></description><link>https://blog.alves.world/tpus-for-reinforcement-learning-and-behavioral-modeling</link><guid isPermaLink="true">https://blog.alves.world/tpus-for-reinforcement-learning-and-behavioral-modeling</guid><category><![CDATA[tpu]]></category><category><![CDATA[GCP]]></category><category><![CDATA[Reinforcement Learning]]></category><category><![CDATA[behavior]]></category><category><![CDATA[Ray Bans Arcadia]]></category><category><![CDATA[parallelism]]></category><category><![CDATA[hpc]]></category><category><![CDATA[weights and biases]]></category><dc:creator><![CDATA[Daniel Alves Rosel]]></dc:creator><pubDate>Sun, 15 Mar 2026 17:47:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6793605016666de203f20485/4720346d-2549-494e-8d96-2904d82629c2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Given that you have created a TPU deployment on <a href="https://cloud.google.com/">GCP</a>, you are now probably trying to figure out how to run your carefully crafted training on this compute. This overview will highlight my learning from working with TPUs and orchestrating training.</p>
<p>Once you have a <a href="https://docs.cloud.google.com/tpu/docs/v4">TPU</a> such as a <code>v4-32</code> deployed in whatever region and zone, I would recommend deploying with the <code>tpu-ubuntu2204-base</code> software version, as it provides the most complete setup for whatever training needs. The next step is to SSH into your machine and check it's still there ;). The process I developed for working with <a href="https://docs.cloud.google.com/compute/docs/instances/spot">spot instances</a> which might be preempted at any point by the provider starts with a bootstrap run which turns the bare VM into a <a href="https://www.ray.io/">Ray</a> cluster. This starts with per-heating all the workers in the topology:</p>
<pre><code class="language-shell">gcloud compute tpus tpu-vm ssh v4-32-us-spot \
  --zone ZONE --project PROJECT --worker=all \
  --command='python3 -m pip install --user "jax[tpu]" \
    -f https://storage.googleapis.com/jax-releases/libtpu_releases.html \
    stable-baselines3 gymnasium wandb tensorboard "ray[default]"'
</code></pre>
<p>If you want actual isolation, create and activate a venv on each node first. At this point it would be good to run a test to ask each worker to report on its world:</p>
<pre><code class="language-shell">gcloud compute tpus tpu-vm ssh v4-32-us-spot \
  --zone ZONE --project PROJECT --worker=all \
  --command='python3 -c "import jax; jax.distributed.initialize(); print(jax.process_index(), jax.device_count())"'
</code></pre>
<p>This will print out a report from each node on its position and chip count.</p>
<h2>Creating the Head</h2>
<p>Now we have setup ray on all the workers, next we establish the head which we can then connect to with:</p>
<pre><code class="language-plaintext">gcloud compute tpus tpu-vm ssh v4-32-us-spot \
  --zone ZONE --project PROJECT --worker=0 \
  --command='export PATH=\(HOME/.local/bin:\)PATH &amp;&amp; \
    ray start --head --port=6379 --dashboard-host=0.0.0.0 \
    --resources="{\"TPU\":8}" --disable-usage-stats'
</code></pre>
<p>The head will let us connect to the cluster and make the deployment of our code much easier (we will later create an SSH tunnel for the head portal). Now we need to configure each of the workers to connect to the head and listen for jobs:</p>
<pre><code class="language-plaintext">for w in 1 2 3; do
  gcloud compute tpus tpu-vm ssh v4-32-us-spot \
    --zone ZONE --project PROJECT --worker=$w \
    --command='export PATH=\(HOME/.local/bin:\)PATH &amp;&amp; \
      ray start --address=INTERNAL_IP:6379 \
      --resources="{\"TPU\":8}" --disable-usage-stats'
done
</code></pre>
<p>This should be tailored to your worker count but it will use the internal IP of the main node which you can find on the GCP console or with a quick command. And with that we have aligned all the TPU workers to enable the full parallelization across the entire cluster. Great, but we still have no access from our local machine, to do that we need to create an ssh tunnel for the port 8265 or whichever you want to configure.</p>
<pre><code class="language-shell">gcloud compute tpus tpu-vm ssh v4-32-us-spot \
  --zone ZONE --project PROJECT --worker=0 \
  -- -L 8265:localhost:8265 -L 10001:localhost:10001 -N
</code></pre>
<p>Now if you open <code>http://localhost:8265</code> you will see the dashboard with your ray cluster with all the nodes we configured.</p>
<h2>Submitting Jobs</h2>
<p>Now we are finally at the fun part: actually sending training to the cluster.</p>
<p>The key idea is to submit jobs from your local machine to the Ray head through the tunnel on <code>localhost:8265</code>. Ray will package your working directory, install dependencies from a runtime env, and execute your entrypoint remotely.</p>
<p>I usually start with a runtime payload so every run is reproducible and self-contained:</p>
<pre><code class="language-json">{
  "pip": [
    "stable-baselines3&gt;=2.2.0",
    "gymnasium&gt;=0.29.0",
    "wandb",
    "tensorboard",
    "python-dotenv",
    "pandas"
  ],
  "env_vars": {
    "WANDB_PROJECT": "PROJECT",
    "WANDB_ENTITY": "YOUR_ENTITY",
    "WANDB_API_KEY": os.getenv("WANDB_API_KEY", "")
  }
}
</code></pre>
<p>With this in place, do a smoke test first:</p>
<pre><code class="language-shell">ray job submit \
  --address http://localhost:8265 \
  --working-dir . \
  --runtime-env-json "$RUNTIME_ENV_JSON" \
  -- \
  python -m engine.train --algo ppo --total-timesteps 5000 --alpha 0.3 --device cpu
</code></pre>
<p>If that succeeds, scale to your real training command.</p>
<p>For distributed execution (one trainer per host or per TPU allocation), use your distributed launcher which will make the distribution of parameters or allocation of configuration easier for us to handle:</p>
<pre><code class="language-shell">ray job submit \
  --address http://localhost:8265 \
  --working-dir . \
  --runtime-env-json "$RUNTIME_ENV_JSON" \
  -- \
  python scripts/ray_distributed_train.py \
    --train-args "--algo ppo --total-timesteps 100000 --alpha 0.4 --device cpu" \
    --num-nodes 4 \
    --tpu-per-task 8 \
    --base-seed 42
</code></pre>
<p>If you wrapped this in <code>submit_ray_job.sh</code> (which I recommend), the same flow is shorter and harder to mess up:</p>
<pre><code class="language-shell">RAY_MODE=distributed \
NUM_NODES=4 \
TPU_PER_TASK=8 \
TRAIN_ARGS="--algo ppo --total-timesteps 100000 --alpha 0.4 --device cpu" \
bash ./submit_ray_job.sh
</code></pre>
<p>Once single runs look healthy, launch sweep agents so Ray fans out trials massively in parallel.</p>
<pre><code class="language-shell">RAY_MODE=sweep \
SWEEP_KIND=ppo_rl_study \
SWEEP_METHOD=random \
SWEEP_RUN_CAP=900 \
NUM_NODES=4 \
AGENTS_PER_NODE=16 \
TPU_PER_TASK=0 \
WANDB_PROJECT=capstone_tpu \
WANDB_ENTITY=YOUR_ENTITY \
bash ./submit_ray_job.sh
</code></pre>
<p>A practical note: for SB3-based algorithms, most compute is CPU-side, so high agent parallelism is usually more useful than trying to reserve TPU for each actor. TPU matters most for JAX-heavy paths. The dashboard gives the visual view, but I still use CLI for reliability:</p>
<pre><code class="language-shell">ray status
ray job list
ray job status &lt;submission_id&gt;
ray job logs -f &lt;submission_id&gt;
</code></pre>
<p>If something is off, these are the first things I check:</p>
<ul>
<li><p>Are all expected nodes alive in <code>ray status</code>? (Maybe got preempted)</p>
</li>
<li><p>Are two Ray nodes accidentally on the same TPU host IP?</p>
</li>
<li><p>Did the job start with the expected env vars (<code>PHANTOM_JAX_PLATFORM</code>, W&amp;B settings)?</p>
</li>
<li><p>Are metrics arriving in W&amp;B at steady cadence? (Or did the run crash?)</p>
</li>
</ul>
<h3>Checkpoints and Artifact Uploads</h3>
<p>For spot instances, assume interruption will happen. The minimum reliable setup is:</p>
<ol>
<li><p>Save final model weights locally at end of training.</p>
</li>
<li><p>Upload that final checkpoint to W&amp;B as an artifact.</p>
</li>
<li><p>Use deterministic aliases (<code>latest</code>, <code>step-&lt;N&gt;</code>) so resuming logic stays simple.</p>
</li>
</ol>
<p>A minimal upload pattern looks like this:</p>
<pre><code class="language-python">artifact = wandb.Artifact(name="phantom-ppo-final", type="checkpoint")
artifact.add_file("engine/models/phantom_ppo.zip", name="model.zip")
wandb.log_artifact(artifact, aliases=["latest", f"step-{num_timesteps}"])
</code></pre>
<p>I intentionally upload only final weights for sweep runs to avoid artifact noise and storage bloat (you can maybe also use the new <a href="https://huggingface.co/blog/storage-buckets">HF Buckets</a>). When a spot VM gets reclaimed, the recovery loop is straightforward:</p>
<ol>
<li><p>Re-run the bootstrap install on all workers. You can put this into a watchdog script that runs either in a foreground shell on your computer or in a docker container.</p>
</li>
<li><p>Start Ray head + workers again.</p>
</li>
<li><p>Re-open the SSH tunnel to <code>8265</code>.</p>
</li>
<li><p>Re-launch sweep agents with the <strong>same</strong> <code>SWEEP_ID</code>.</p>
</li>
</ol>
<p>Because sweep state is on W&amp;B, agents can continue pulling remaining runs after cluster recovery. When you are done, stop Ray everywhere so the next startup is clean:</p>
<pre><code class="language-shell">gcloud compute tpus tpu-vm ssh v4-32-us-spot \
  --zone ZONE --project PROJECT --worker=all \
  --command='export PATH=\(HOME/.local/bin:\)PATH &amp;&amp; ray stop -f'
</code></pre>
<p>That is basically the full lifecycle: bootstrap, form cluster, tunnel, submit, monitor, recover, and tear down. Once this loop is scripted, TPU experimentation becomes much less painful and much more reproducible.</p>
<h2>Behavior Modeling Parallelization</h2>
<p>![](<a href="https://cdn.hashnode.com/uploads/covers/6793605016666de203f20485/62efc20e-428c-48a3-92d1-aa667e0d7484.png">https://cdn.hashnode.com/uploads/covers/6793605016666de203f20485/62efc20e-428c-48a3-92d1-aa667e0d7484.png</a> align="middle")</p>
<p>One thing that gave me a real throughput jump was moving the behavioral-profile logic into JAX parallel batches instead of evaluating profiles in Python loops. In practice, I keep a profile bank for human and agent transition kernels (and any synthetic contamination profiles) as fixed-shape tensors, then run divergence scoring and robust alpha selection with <code>jax.jit</code> + <code>jax.vmap</code> so each step evaluates all profile candidates in one compiled pass. If you want to scale beyond a single host, the same computation can be sharded across workers with pmap/multi-process JAX, where each process gets a slice of the profile bank and we aggregate worst-case signals at the end; this is especially useful when you are screening many levels at once. The important engineering detail is to keep shapes static (pad trajectories, use masks, avoid Python-side branching) so recompilation does not kill performance, and to pre-place profile tensors on device once to avoid host-to-device transfer overhead on every step. I also strongly recommend deterministic PRNG handling with <code>jax.random.fold_in(process_index, global_step)</code> so profile comparisons remain reproducible across nodes, which makes sweep analysis and equilibrium claims much easier to trust in your results.</p>
<h2>Conclusion</h2>
<p>At the end of the day, running RL at TPU scale is less about a single launch command and more about building a resilient workflow: bootstrap all workers, form a clean Ray cluster, submit jobs through a reproducible runtime env, and treat spot preemption as a normal event instead of a failure. Once that loop is scripted, the infrastructure gets out of your way and you can focus on the actual science and using JAX-parallel logic to evaluate policies fast and consistently. That is when the cluster stops feeling like ops overhead or MLOps project and starts feeling like a research accelerator.</p>
<blockquote>
<p>PS: Let your AI agents help you with configuration and testing of the clusters itself.</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[Familiar Monitoring of TPU Workloads]]></title><description><![CDATA[How can I see the usage of my TPU chip? Can I run nvtop on a TPU machine?

These were some of the biggest questions I had when I started working with zt for my research. When running code on a TPU bas]]></description><link>https://blog.alves.world/familiar-monitoring-of-tpu-workloads</link><guid isPermaLink="true">https://blog.alves.world/familiar-monitoring-of-tpu-workloads</guid><category><![CDATA[tpu]]></category><category><![CDATA[observability]]></category><category><![CDATA[Google]]></category><category><![CDATA[Machine Learning]]></category><dc:creator><![CDATA[Daniel Alves Rosel]]></dc:creator><pubDate>Tue, 10 Mar 2026 15:00:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6793605016666de203f20485/6e7751da-35f0-44a6-bfcf-999ca6c6660b.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>How can I see the usage of my TPU chip? Can I run nvtop on a TPU machine?</p>
</blockquote>
<p>These were some of the biggest questions I had when I started working with zt for my research. When running code on a TPU based setup, be that inside of <a href="https://colab.research.google.com/">Google Colab</a> or via <a href="http://cloud.google.com">GCP</a> it is helpful to get a better understanding of the current load on the chips you might be using. When you google "nvtop for TPUs" not much comes up apart from some issues on GitHub. Looking through the pull requests of <a href="https://github.com/Syllo/nvtop/">nvtop</a> you might come across the way to re-compile the code with support for TPU chips.</p>
<p>First, what is a TPU? A <strong>Tensor Processing Unit</strong> is a specialized chip designed by Google to speed up machine learning workloads, especially neural networks and large matrix operations used in training and inference. I was fortunate enough to work with a large allocation of multiple chips from Google and for the ease of future use, setup a small bash gist: <a href="https://gist.github.com/velocitatem/53ff537d3c439c3bd63d8a0f1370801b">here</a>.</p>
<p>This mini-script will install the necessary requirements and fetch the source code of nvtop. Then it will compile it with TPU support enabled. A very simple way to run it is to do the following:</p>
<pre><code class="language-shell">curl -sSL https://gist.githubusercontent.com/velocitatem/53ff537d3c439c3bd63d8a0f1370801b/raw/c348e534f7c24646c52eabce11cad9ee01611fb1/install_nvtop_tpu.sh | bash
</code></pre>
<p>What this does is simply fetch the script and run it on your machine (with the expectation of <a href="https://releases.ubuntu.com/jammy/">Ubuntu 22.04</a>). This is not limited to running on provisioned virtual machines, but can also be run in the colab terminal:</p>
<p>![](<a href="https://cdn.hashnode.com/uploads/covers/6793605016666de203f20485/4697660f-ef58-4fd8-b827-b421b2f34426.png">https://cdn.hashnode.com/uploads/covers/6793605016666de203f20485/4697660f-ef58-4fd8-b827-b421b2f34426.png</a> align="middle")</p>
<p>You can then run some <a href="https://github.com/jax-ml/jax">Jax</a> powered script to test it out and monitor the load.</p>
]]></content:encoded></item><item><title><![CDATA[A Reproducible LaTeX Thesis Workflow with CI/CD and Public PDF Links on Your Own Terms.]]></title><description><![CDATA[Before I started the heavy work on my thesis, I wanted to make sure down the line I can focus as much on just content and I wont end up spending time fighting with configs and struggling to manage my ]]></description><link>https://blog.alves.world/a-reproducible-latex-thesis-workflow-with-ci-cd-and-public-pdf-links-on-your-own-terms</link><guid isPermaLink="true">https://blog.alves.world/a-reproducible-latex-thesis-workflow-with-ci-cd-and-public-pdf-links-on-your-own-terms</guid><category><![CDATA[latex]]></category><category><![CDATA[academic writing]]></category><category><![CDATA[thesis]]></category><category><![CDATA[cloudflare]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[ci-cd]]></category><dc:creator><![CDATA[Daniel Alves Rosel]]></dc:creator><pubDate>Sun, 08 Mar 2026 14:27:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6793605016666de203f20485/26cd75c2-3cac-4ad6-8d3e-cc1428e97a3d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Before I started the heavy work on my thesis, I wanted to make sure down the line I can focus as much on just content and I wont end up spending time fighting with configs and struggling to manage my writing/code. This is why when I started the monorepo of my work, I created a latex template as most people will. I decided that I will not use Overleaf because it's vendor lock-in is something I do not want to deal with and my preference to write in Emacs dose not really align with that either.</p>
<p>With the paper/ directory setup I then created a few entries in my Makefile which helps me orchestrate everything else in my research. I have <code>paper.build</code> and <code>paper.watch</code> as targets which help with the day-to-day writing and the watch target will re-compile and render my paper in <a href="https://github.com/pwmt/zathura">zathura</a> which I could not recommend more.</p>
<p>The beauty of my workflow comes in the CI/CD stage. I want my advisor and stakeholders to always see the updated version of my work in the same place, like you can in Overleaf. I do not however want to make anyone clone my repo and self compile my work. That is why I built an on-commit build of my paper which ofcourse creates an artifact on GitHub. This however is still a bit cumbersome. Then I thought, what if I could use object storage like <a href="https://www.cloudflare.com/developer-platform/products/r2/">CloudFlare R2</a> (because setting up AWS S3 is a bit too tedious) to host my work?</p>
<p>![](<a href="https://cdn.hashnode.com/uploads/covers/6793605016666de203f20485/a28af780-d708-4220-bca4-c1ecb0a282b1.png">https://cdn.hashnode.com/uploads/covers/6793605016666de203f20485/a28af780-d708-4220-bca4-c1ecb0a282b1.png</a> align="middle")</p>
<p>Every commit, triggers a build, which triggers a push to the 'paper registry' under a timestamp aswell as <code>-latest.pdf</code> tag. Originally I wanted a persistent undo-tree for all the source files of my thesis, this however proved to not be such a good idea, nor would it make sense since each edit is tracked in a git repository. With this I have a full history of all the states of my work aswell as a unified place for the head of the process with a publicly sharable URL.</p>
<p>Since my work has multiple possible stakeholders each with different things they want to see, I created an automated mirroring pipeline which leverages <a href="https://chatgpt.com/codex">codex</a> to use per-mirror instructions to create perishable edits to the main work of the body and compiles the adjusted version. This way I can create a less technical or more technical mirror alongside my main fully humanly authored work.</p>
]]></content:encoded></item><item><title><![CDATA[Game Theoretic Exploration of Rio's Traffic Information Signaling Patterns]]></title><description><![CDATA[In Rio de Janeiro, you will see motorcyclists lane split, especially when a red light has blocked the intersection and there all lanes queued with cars. As they go between cars they beep to let other know of their presence. this is an intended safety...]]></description><link>https://blog.alves.world/game-theoretic-exploration-of-rios-traffic-information-signaling-patterns</link><guid isPermaLink="true">https://blog.alves.world/game-theoretic-exploration-of-rios-traffic-information-signaling-patterns</guid><category><![CDATA[traffic]]></category><category><![CDATA[Game Theory]]></category><category><![CDATA[Information]]></category><dc:creator><![CDATA[Daniel Alves Rosel]]></dc:creator><pubDate>Tue, 06 Jan 2026 13:20:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1767705290398/ba609208-7199-4c3a-a04a-3646c5f1a142.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In Rio de Janeiro, you will see motorcyclists lane split, especially when a red light has blocked the intersection and there all lanes queued with cars. As they go between cars they beep to let other know of their presence. this is an intended safety warning but to a pedestrian or drive it might come across as just noise with diminishing returns if over-used.</p>
<p>We demonstrate that the current state represents a sub-optimal Nash Equilibrium. The collective acoustic output informationally equivalent to silence, despite the high energetic cost and noise pollution. We look at this from a very naïve perspective just as an observational analysis.</p>
<h2 id="heading-game-theoretic-analysis">Game Theoretic Analysis</h2>
<p>We model the dynamic between motorists as N player non-cooperative game. We specifically look at a sub-game of two drivers M one and two. Each player has two options of actions in a given state, <strong>B</strong> or <strong>Q</strong> which stand for beep or quiet. They earn a reward or payoff made of of a positive value (V) of safety with a negative cost of beeping which is almost negligible (C). This minimal cost mirrors what literature tells us to be true: costless signaling leads to informationally inefficient equilibria. Finally we take into account a parameter of degradation which helps us model the number of agents beeping (δ).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767703267445/8cad76f8-277c-4fca-9128-b0c2b0f3702a.png" alt class="image--center mx-auto" /></p>
<p>If M2 is Quiet, M1 should Beep because V − C &gt; 0. If M2 Beeps, M1 should still Beep, provided that the degraded safety V (1 − δ) − C &gt; 0. Since the cost of beeping C is functionally low (extremely low), the strategy B becomes strictly dominant. The system converges to the Nash Equilibrium (B, B) as defined in standard non-cooperative game theory. However, as N (the number of riders) increases, the total degradation δ approaches 1… The collective payoff becomes:</p>
<p>$$\lim_{N \to \infty} \sum U_i = N \cdot (V(1 - 1) - C) = -N \cdot C$$</p><p>This socially creates a local jamming equilibrium where the added benefit of safety is vanishing but the negligible cost still has secondary effects on the environment. Yet, no individual can rationally switch to silence without assuming maximum risk.</p>
<h2 id="heading-information-theoretic-analysis-entropy">Information Theoretic Analysis: Entropy</h2>
<p>We make X be the variable representing the presence of a motorcycle and Y be the auditory signal received by the driver. In an ideal system, warnings are rare (P(beep) approx 0.05), meaning the information content of a signal is high. However, in the Rio system, the dominant strategy described above forces the probability of beeping to approach 1 (p → 1). The entropy H(Y) will regress to 0 in this model (more in the paper):</p>
<p>$$H(Y)\approx−(1 \log_2​1)=0 \text{bits}$$</p><p>A signal that is always present conveys zero bits of information. The driver learns nothing new about the state of the traffic from hearing a beep, simply because the beep is a constant (in practice this might not however be the dominant case).</p>
<p>We can further view the traffic environment as a communication channel, where the capacity C is limited by the signal to noise Ratio (SNR) according to the Shannon-Hartley theorem:</p>
<p>$$C = B \log_2 \left( 1 + \frac{S}{N_{oise}} \right)$$</p><p>The channel effectively becomes saturated. The acoustic energy is high, but the information transmission rate is zero.</p>
<p>The observed model from Rio presents a paradox where deviation from the strategy is not in the interest of a drive but creates a lock-in. Our entropy model also hints that the signal overuse creates a vanishing value.</p>
<p>safe riders and dangerous riders use the same signal with probability 1. Consequently, the signal fails to distinguish types. The "baseline" of beeping becomes informationally identical to a baseline of silence in a prolific use of the dominant strategy.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767704974011/d653ad00-0145-4a56-8747-1a4b8f089b5c.jpeg" alt class="image--center mx-auto" /></p>
<ol>
<li><p>Cover, T. M., &amp; Thomas, J. A. (2006). <em>Elements of Information Theory</em> (2nd ed.). Wiley-Interscience.</p>
</li>
<li><p>Crawford, V. P., &amp; Sobel, J. (1982). Strategic information transmission. <em>Econometrica</em>, 50(6), 1431–1451.</p>
</li>
<li><p>Fudenberg, D., &amp; Tirole, J. (1991). <em>Game Theory</em>. MIT Press.</p>
</li>
<li><p>Hardin, G. (1968). The tragedy of the commons. <em>Science</em>, 162(3859), 1243–1248.</p>
</li>
<li><p>Shannon, C. E. (1948). A mathematical theory of communication. <em>The Bell System Technical Journal</em>, 27(3), 379–423.</p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[AI Built It. You Still Have to Make It Work.]]></title><description><![CDATA[The value in being able to create software in AI comes from the many different ways it can be developed for any specific objective you have in mind. It usually starts with identifying a problem you are trying to solve, and you might put it into v0 or...]]></description><link>https://blog.alves.world/ai-built-it-you-still-have-to-make-it-work</link><guid isPermaLink="true">https://blog.alves.world/ai-built-it-you-still-have-to-make-it-work</guid><category><![CDATA[AI]]></category><category><![CDATA[vibe coding]]></category><category><![CDATA[genai]]></category><category><![CDATA[LLM's ]]></category><dc:creator><![CDATA[Daniel Alves Rosel]]></dc:creator><pubDate>Fri, 24 Oct 2025 10:10:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/KrYbarbAx5s/upload/a18ec5783998d9f09b16eaaf81defeb8.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The value in being able to create software in AI comes from the many different ways it can be developed for any specific objective you have in mind. It usually starts with identifying a problem you are trying to solve, and you might put it into v0 or Lovable, which creates your baseline.</p>
<p>Often, this initial version is just for show; it looks nice, but nothing functions. Many people, even experienced developers, assume that the starting version doesn't affect what you end up with after 10 adjustment prompts. This is simply how the software is designed to work. You might ask, “build me an Uber for dogs,” and you get a specific page. Then you ask, “make all the buttons blue with a shimmering effect,” and the results can be a bit disappointing. This is especially true in a conversation thread of 500,000 tokens, where some models might experience <a target="_blank" href="https://inkeep.com/blog/context-anxiety">context anxiety</a> (a fear of soon running out of context and not being able to complete the task).</p>
<p>For any one input of instructions of what to build, there are nearly an infinite variations of how that software might look - this is what puts the <strong>vibe</strong> into “vibe coding”. Using AI assistance to build software should not be a threat filled argument in a chat window. Many of these coding agent platforms do implement options of rules and setting up guidance but what in my experience works the best, is being very opinionated in choices relating to the technological stack of whatever your dream platform is.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/kayladotdev/status/1853272891023872450?ref_src=twsrc%5Etfw">https://twitter.com/kayladotdev/status/1853272891023872450?ref_src=twsrc%5Etfw</a></div>
<p> </p>
<p>The interaction loop of chatting does not incentivize a lot of precision from the human side, where you might end up with people taking screenshots of code to give it back to the chat window and asking for adjustments or, in general, not writing very high-quality prompts. After all this back and forth, you might end up with a software solution that very often will not be useful to many people because it's hard to deploy or maintain and is very narrow.</p>
<p>This ends up polluting the software space with thousands of random landing pages, half-done web apps with poor security, and overall no production-quality software. With the increasing capability of code-generating models (+ their autonomy) and decreasing cost per token on these models, my hypothesis is the following: Instead of progressively introducing features and adjustments to the model and codebase via a chat interface, we can have a single source of truth, which I call the statement of purpose.</p>
<h3 id="heading-the-place-for-ai-software-tooling">The Place for AI Software Tooling</h3>
<p>In a given organization with N individuals, there will be various identifiable bottlenecks that could be resolved with AI-generated software. A person in this group might have a specific problem of data transformation or connectivity between services, which they themselves do not have the technical skills to resolve but can describe well enough for AI to build a solution. The current existence of that solution might be isolated to one of these platforms like Lovable. Three weeks later, a colleague might face a similar issue but with a slight twist; however, they would be unable to reuse any part of the previously generated software and would have to do it from scratch. This isolation in human usage, software interoperability, and LLM context creates a significant slowdown in AI-assisted progress.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761295927820/146303ea-09b1-47d5-a608-d0bffd6412e9.png" alt class="image--center mx-auto" /></p>
<p>My new platform proposes to fix this by capturing the essence of various issues in these SoPs (statements of purpose), which then turn into one-click deployable software. Some of the key features this methodology allows for are:</p>
<ul>
<li><p>Progression of software capability at the speed of innovation: Imagine you vibe code the Uber for dogs, and 2 months later GPT-6 comes out. Half of the features that might not have worked in your previous versions, this new model is now capable of building. This allows your app to ride the wave of any new model advancement.</p>
</li>
<li><p>The ability for AI-generated software to be interoperable with previously generated solutions. If each employee in a 1000-person company generates 5 Lovable apps, chances are a lot of work is being done in repetition. Peakz allows for software solutions to communicate with each other in established frameworks.</p>
</li>
</ul>
<h3 id="heading-technical-overview">Technical Overview</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761298095835/65db663b-e500-4398-bc1c-3b8c789bded8.png" alt="A detailed flowchart of the platform." class="image--center mx-auto" /></p>
<p>The control plane centers on a FastAPI orchestration server and a PostgreSQL registry. Statements of Purpose and code references live in the registry. A worker picks up build requests, runs the Building &amp; Deployment pipeline, and records artifacts and metadata. Generated outputs and run results are pushed to MinIO, which also serves as the source of truth for later redeploys.</p>
<p>The runtime plane is container-first. For each request the worker orchestrates isolated containers that mount two layers: a Deployment Layer for serving and a Development Layer for iterative work. Containers boot from a consistent Development Image with defined entrypoints. The image includes OpenAI Codex, a toolchain, and a lightweight devkit on Alpine Linux, enabling predictable startup and stack autodetection.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761297573285/0da40238-09e4-49a5-8d53-22877c457d89.png" alt="Diagram showing a system architecture from a high level view." class="image--center mx-auto" /></p>
<p>The access plane exposes running apps through a Next.js proxy that routes to the Deployment Layer. Users interact with the proxied endpoints while the worker manages lifecycle and scaling. Results and logs flow back to MinIO, and the registry database keeps state for SOPs, codebases, deployments, and versions. The separation of planes keeps apps isolated, auditable, and quickly reproducible.</p>
<p>Go ahead and visit <a target="_blank" href="http://abundantsoftware.eu">abundantsoftware.eu</a> to see more about how things look and feel. This is a platform that was built over 10 hours at <a target="_blank" href="https://www.linkedin.com/posts/daniel-rosel_a-weekend-with-palantir-technologies-openai-activity-7384164609928118272-MooE?utm_source=share&amp;utm_medium=member_desktop&amp;rcm=ACoAAC6cJtEBcIyFMPgyYbScM8Ki0ZbA9y6Oz6w">this</a> event.</p>
]]></content:encoded></item><item><title><![CDATA[Not Just for Hackers: How I Repurposed a Pentest Tool for a Blackout]]></title><description><![CDATA[The Network Is Down — Now What?
When the lights went out across Spain and Portugal in April 2025, it wasn’t just a power cut. It was a silence.
Elevators jammed mid-floor. Metro tunnels went black. Airports turned into echo chambers of confusion. For...]]></description><link>https://blog.alves.world/not-just-for-hackers-how-i-repurposed-a-pentest-tool-for-a-blackout</link><guid isPermaLink="true">https://blog.alves.world/not-just-for-hackers-how-i-repurposed-a-pentest-tool-for-a-blackout</guid><category><![CDATA[wifipineapple]]></category><category><![CDATA[hak5]]></category><category><![CDATA[Spain]]></category><category><![CDATA[offline]]></category><category><![CDATA[community]]></category><category><![CDATA[PHP]]></category><category><![CDATA[self-hosted]]></category><category><![CDATA[BLACKOUT,]]></category><dc:creator><![CDATA[Daniel Alves Rosel]]></dc:creator><pubDate>Wed, 30 Apr 2025 07:34:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1745996799156/295d743a-97d2-4785-91e6-7cc1f6847901.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-the-network-is-down-now-what">The Network Is Down — Now What?</h3>
<p>When the lights went out across Spain and Portugal in April 2025, it wasn’t just a power cut. It was a silence.</p>
<p>Elevators jammed mid-floor. Metro tunnels went black. Airports turned into echo chambers of confusion. For 8+ hours, even as power slowly flickered back into buildings, something more vital was still missing:</p>
<p><strong>Information.</strong></p>
<p>Phones had charge, but no signal. Laptops had Wi-Fi toggled on, but nowhere to connect. And in that vacuum, whispers started doing what they always do in a crisis — spreading fast, mutating faster.</p>
<p>No one knew what had happened. No one knew when help was coming.</p>
<p>And that’s exactly the moment a tiny, often-overlooked device can make a world of difference.</p>
<hr />
<h3 id="heading-what-if-there-was-a-way-to-stay-informed-digitally-together-even-offline">What if there was a way to stay informed digitally— together — even offline?</h3>
<p>The <a target="_blank" href="https://hak5.org/products/wi-fi-pineapple">Wi-Fi Pineapple Nano</a>, a cheap pocket router best known to cybersecurity tinkerers, wasn’t built for disaster relief. But it happens to be perfect for it. With a bit of preparation, this little box becomes an emergency communications node — quietly powerful in the most human way:</p>
<p>When people say “Where can I find water?” serve a map and list of nearby resources — no Internet needed. “I need to let my neighbor know I’m okay.” Host a local chat, instantly accessible to anyone nearby. “Did you hear a hospital was out of X?” Provide a single, verified source of local updates to stop rumors cold. “I have one phone with Internet left…” Share it via the Nano, fairly and securely, across the neighborhood.</p>
<p>The Nano can broadcasts an open Wi-Fi network — something like <strong>“EmergencyNet”</strong> — and any phone that connects instantly gets a pop-up page. No app. No login. Just local, living information.</p>
<h3 id="heading-this-isnt-about-tech-its-about-trust">This isn’t about tech. It’s about trust.</h3>
<p>When disaster strikes, misinformation spreads faster than help.<br />It’s not malicious — it’s human. In the absence of news, people fill the gap with whatever they can find. An overheard conversation, a</p>
<p>But that’s exactly why a <strong>shared, live, low-tech bulletin board</strong> can matter more than extra food or candles. It becomes an anchor.</p>
<p>With a static site and a couple of JSON files, your Nano can carry:</p>
<ul>
<li><p><strong>Updates from neighbors</strong> — who’s safe, who needs medicine, where traffic is backed up.</p>
</li>
<li><p><strong>Shared files</strong> — like emergency contacts, translated guides, or relief info in multiple languages.</p>
</li>
<li><p><strong>Voice bulletin streams</strong> — with a mic and a radio dongle, the Nano can broadcast looped updates over low-bandwidth audio.</p>
</li>
</ul>
<p>And all of this works from a power bank — no grid, no cell towers, no problem.</p>
<h3 id="heading-it-doesnt-take-much">It doesn’t take much</h3>
<p>A USB power bank is enough to keep the Nano running for up to <strong>16 hours</strong>, realistically. Two batteries, swapped morning and evening, can keep a whole street connected through the chaos.</p>
<p>With a second Wi-Fi dongle, it can also act as a <strong>gateway</strong> — tapping into any working hotspot and safely sharing the connection with everyone nearby. If someone has signal, <strong>everyone gets it.</strong></p>
<p>Or set it higher — on a tree, balcony, or roof — and it becomes a <strong>range extender</strong>, passing messages from block to block. With a few of them daisy-chained together, even a full district can stay looped in.</p>
<h3 id="heading-a-few-files-a-little-prep-real-resilience">A few files, a little prep — real resilience</h3>
<p>Set up your Nano now, before the next blackout:</p>
<ul>
<li><p>Preload a small HTML portal with chat and bulletin board.</p>
</li>
<li><p>Point captive portal domains to the Nano’s IP so phones auto-open it.</p>
</li>
<li><p>Drop in maps, contact lists, APKs, even a copy of the Red Cross first-aid handbook.</p>
</li>
<li><p>Add a hand written label: <em>“Emergency Wi-Fi — join ‘EmergencyNet’”</em></p>
</li>
</ul>
<p>That’s it. No database. No server. No DNS. Just one open SSID and a page everyone sees the moment they connect.</p>
<h3 id="heading-because-when-everything-else-fails-clarity-still-matters">Because when everything else fails… clarity still matters</h3>
<p>In a blackout, power is the first thing to go.<br />But <strong>certainty</strong> — or the lack of it — is what really shapes the days that follow.</p>
<p>A €100 box can’t replace the Internet. But it can help <strong>replace uncertainty with intel.</strong> It can bring <strong>structure to the mess.</strong><br />And most of all, it can remind us that even when the grid collapses, <strong>we don’t have to go dark.</strong></p>
]]></content:encoded></item><item><title><![CDATA[Distilling Giants: Making BERT Models Lightweight and Interpretable with DIET COKE]]></title><description><![CDATA[This past semester, I embarked on an exciting NLP project: building DIET COKE — short for Decision trees Interpreting Efficient Transformers - Compression Of Knowledge Extraction. It's a project that sits at the crossroads of deep learning and classi...]]></description><link>https://blog.alves.world/distilling-giants-making-bert-models-lightweight-and-interpretable-with-diet-coke</link><guid isPermaLink="true">https://blog.alves.world/distilling-giants-making-bert-models-lightweight-and-interpretable-with-diet-coke</guid><category><![CDATA[nlp]]></category><category><![CDATA[knowledge]]></category><category><![CDATA[BERT]]></category><category><![CDATA[transformers]]></category><category><![CDATA[decisiontree]]></category><category><![CDATA[edgecomputing]]></category><category><![CDATA[ Edge AI]]></category><dc:creator><![CDATA[Daniel Alves Rosel]]></dc:creator><pubDate>Thu, 24 Apr 2025 09:00:27 GMT</pubDate><content:encoded><![CDATA[<p>This past semester, I embarked on an exciting NLP project: building <a target="_blank" href="https://github.com/velocitatem/diet-coke"><strong>DIET COKE</strong></a> — short for <strong>Decision trees Interpreting Efficient Transformers - Compression Of Knowledge Extraction</strong>. It's a project that sits at the crossroads of deep learning and classic machine learning, blending the sophistication of transformers with the simplicity and transparency of decision trees.</p>
<p>In essence, DIET COKE is a pipeline that distills the knowledge of a heavyweight BERT model into lightweight, interpretable models like decision trees, random forests, or linear classifiers — models that are fast, transparent, and, crucially, can run without needing a data center in your backpack.</p>
<h2 id="heading-why-even-bother-distilling">Why Even Bother Distilling?</h2>
<p>Large models like BERT are brilliant — but also notoriously impractical outside of cloud servers. They are slow, expensive, opaque, and massive. Great if you're Google. Not great if you're deploying to a Raspberry Pi in a rural village or trying to explain your model's prediction to a non-technical client.</p>
<p>The idea behind DIET COKE is simple: <strong>take the wisdom of a large model, and compress it into a small one</strong>. Think of it as writing a pocket guidebook based on a Nobel Prize winner’s 600-page dissertation. You lose a little nuance, but keep most of the real-world value.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745421970553/a4e89d65-8677-428f-b6ed-9b1efcf6a24e.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-whats-inside-the-diet-coke-pipeline">What’s Inside the DIET COKE Pipeline?</h2>
<p>The project is structured with the kind of modular, end-to-end design I love (and insist on building). Here’s the high-level flow:</p>
<ul>
<li><p><strong>Train the Teacher</strong>: Fine-tune a BERT model on IMDB movie reviews for sentiment classification.</p>
</li>
<li><p><strong>Soft Targets and Temperature Scaling</strong>: Instead of teaching the student from hard labels ("positive" or "negative"), we use the teacher’s soft probability outputs (logits) — softened even further with temperature scaling to better reveal hidden patterns.</p>
</li>
<li><p><strong>Vectorize the Text</strong>: Since our student models can’t eat raw text, we use good old TF-IDF to turn movie reviews into sparse, meaningful feature vectors.</p>
</li>
<li><p><strong>Train the Student</strong>: Train a simple model (like a decision tree) to imitate the teacher's nuanced outputs.</p>
</li>
<li><p><strong>Evaluate and Benchmark</strong>: Compare not just on raw accuracy, but on <strong>fidelity</strong> — how well the student mimics the teacher.</p>
</li>
</ul>
<h2 id="heading-the-magic-of-distillation-teaching-by-uncertainty">The Magic of Distillation: Teaching by Uncertainty</h2>
<p>One of the coolest parts of this project was diving deep into temperature scaling. At a high temperature (say, 4 or 5), the teacher’s output probabilities become softer — meaning that even "wrong" answers get some probability mass.</p>
<p>This subtle information about <strong>what the model thinks might also be true</strong> is pure gold when teaching smaller models. It lets the student not just memorize labels, but <strong>inherit the teacher’s worldview</strong>.</p>
<p>It’s the difference between:</p>
<ul>
<li><p>Telling a kid "2 + 2 = 4", full stop, versus</p>
</li>
<li><p>Teaching them <em>why</em> "2 + 2 = 4" but also explaining how addition works for any numbers.</p>
</li>
</ul>
<p>In knowledge distillation, <strong>temperature</strong> controls how much uncertainty the teacher model reveals to the student. Higher temperatures soften the teacher's predictions, exposing richer secondary patterns beyond the top choice. This often boosts <strong>fidelity</strong> — the student’s ability to mimic the teacher's behavior — but can slightly lower <strong>raw accuracy</strong> on hard labels. In contrast, lower temperatures sharpen predictions, favoring accuracy but at the cost of losing some of the teacher's deeper knowledge. Finding the right balance between fidelity and accuracy is key to building student models that are both smart and practical.</p>
<h2 id="heading-when-to-use-which-student-model">When to Use Which Student Model?</h2>
<p>After extensive experiments, here's the quick cheat-sheet:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Model</td><td>Best For</td><td>Pros</td><td>Cons</td></tr>
</thead>
<tbody>
<tr>
<td>Decision Tree</td><td>Explainability</td><td>Easy to visualize and interpret</td><td>Lower accuracy</td></tr>
<tr>
<td>Random Forest</td><td>Best accuracy</td><td>Robust, close to BERT performance</td><td>Less interpretable</td></tr>
<tr>
<td>Sparse Linear</td><td>Edge devices</td><td>Tiny models, fast</td><td>Needs careful feature tuning</td></tr>
</tbody>
</table>
</div><p>Temperature settings? A sweet spot is usually T=4 for softer distributions, but T=2 works surprisingly well if you're targeting more accuracy over fidelity.</p>
<h2 id="heading-final-thoughts-why-diet-coke-matters">Final Thoughts: Why DIET COKE Matters</h2>
<p><strong>DIET COKE</strong> isn’t just an academic exercise. It’s a blueprint for the future of <em>practical</em> AI: how we can compress enormous models into smaller, understandable pieces that still capture most of the power, without the computational footprint.</p>
<p>In a world increasingly moving toward edge computing, decentralized apps, and explainable AI, pipelines like DIET COKE aren’t just nice-to-haves — they’re the future.</p>
<p>If you're curious, you can dive into the repo and experiment with different configurations, tweak temperatures, or even distill other transformer models. There's a lot of frontier here.</p>
<p><strong>Big brains compressed into small, fast, human-friendly models.</strong><br />That's a future I’m excited to build toward.</p>
<p>If you have any questions or thoughts, feel free to reach out via my website: <a target="_blank" href="https://alves.world">alves.world</a></p>
]]></content:encoded></item><item><title><![CDATA[How to Manage Virtual Environments in JupyterLab: Introduction to JUNO]]></title><description><![CDATA[As someone who has spent countless hours wrestling with Python dependency conflicts in Jupyter notebooks, I've felt the unique pain that comes with hearing "but it works on my machine" when sharing notebooks with colleagues. The problem isn't just an...]]></description><link>https://blog.alves.world/how-to-manage-virtual-environments-in-jupyterlab-introduction-to-juno</link><guid isPermaLink="true">https://blog.alves.world/how-to-manage-virtual-environments-in-jupyterlab-introduction-to-juno</guid><category><![CDATA[AI]]></category><category><![CDATA[Jupyter Notebook ]]></category><category><![CDATA[JupyterLab]]></category><category><![CDATA[Python]]></category><category><![CDATA[Data Science]]></category><category><![CDATA[environment setup]]></category><category><![CDATA[notebook]]></category><category><![CDATA[efficiency]]></category><dc:creator><![CDATA[Daniel Alves Rosel]]></dc:creator><pubDate>Mon, 10 Mar 2025 11:00:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1740957965831/b192407a-fab9-441f-b445-850722054c53.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As someone who has spent countless hours wrestling with Python dependency conflicts in <a target="_blank" href="https://jupyter.org/">Jupyter</a> notebooks, I've felt the unique pain that comes with hearing "but it works on my machine" when sharing notebooks with colleagues. The problem isn't just annoying—it's a fundamental barrier to reproducible data science.</p>
<p>That's why I was excited to discover <a target="_blank" href="https://github.com/velocitatem/juno">JUNO</a>, a tool that elegantly solves one of the most persistent challenges in the Jupyter ecosystem: managing virtual environments and packages directly within JupyterLab.</p>
<h2 id="heading-the-virtual-environment-problem">The Virtual Environment Problem</h2>
<p>If you've used Jupyter notebooks for any serious data science work, you've likely encountered these frustrating scenarios:</p>
<ul>
<li><p>Installing a package breaks your existing notebooks because of version conflicts</p>
</li>
<li><p>Sharing notebooks that work perfectly for you but fail for colleagues</p>
</li>
<li><p>Maintaining multiple projects with different dependencies</p>
</li>
<li><p>Switching between different Python versions for specific projects</p>
</li>
</ul>
<p>Traditional solutions involve creating separate virtual environments outside of Jupyter, then manually registering kernels—a process that's error-prone and requires command-line gymnastics.</p>
<h2 id="heading-enter-juno-virtual-environments-made-simple">Enter JUNO: Virtual Environments Made Simple</h2>
<p>JUNO reimagines how we manage environments in JupyterLab by integrating virtual environment creation and package management directly into the interface.</p>
<h3 id="heading-key-features">Key Features</h3>
<p>JUNO provides an intuitive UI for:</p>
<ol>
<li><p>Creating and managing new isolated environments</p>
</li>
<li><p>Installing and managing packages with a visual interface</p>
</li>
<li><p>Switching between environments seamlessly</p>
</li>
<li><p>Sharing environment specifications for reproducibility</p>
</li>
</ol>
<h2 id="heading-hands-on-getting-started-with-juno">Hands-On: Getting Started with JUNO</h2>
<p>Let's walk through a typical workflow to see how JUNO simplifies environment management.</p>
<h3 id="heading-installation">Installation</h3>
<pre><code class="lang-bash">pip install juno-manager
</code></pre>
<h3 id="heading-creating-a-new-environment">Creating a New Environment</h3>
<p>Instead of the traditional approach:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># The old way</span>
python -m venv my_new_env
<span class="hljs-built_in">source</span> my_new_env/bin/activate
pip install ipykernel
python -m ipykernel install --user --name my_new_env
jupyter lab
</code></pre>
<p>With JUNO, you simply:</p>
<ol>
<li><p>Open <code>juno-manager</code></p>
</li>
<li><p>Name your environment and specify which packages to install (you can also do this later)</p>
</li>
<li><p>Verify your environment was created and add any other packages directly if you want</p>
</li>
</ol>
<p>Behind the scenes, JUNO handles the virtual environment creation and kernel registration automatically.</p>
<h2 id="heading-real-world-use-case-managing-ml-project-dependencies">Real-World Use Case: Managing ML Project Dependencies</h2>
<p>Recently, I was working on a machine learning project that required TensorFlow for one notebook and PyTorch for another. Before JUNO, I would have:</p>
<ol>
<li><p>Created separate virtual environments with different packages in various directories</p>
</li>
<li><p>Registered each as a kernel into my lab</p>
</li>
<li><p>Carefully selected the right kernel for each notebook</p>
</li>
<li><p>Documented the environment setup for teammates</p>
</li>
</ol>
<p>With JUNO, I created two environments through the UI, installed the required packages with a few clicks, and could switch between them without any hassle.</p>
<pre><code class="lang-python"><span class="hljs-comment"># In my TensorFlow notebook (using the tensorflow-env kernel)</span>
<span class="hljs-keyword">import</span> tensorflow <span class="hljs-keyword">as</span> tf
model = tf.keras.Sequential([...])

<span class="hljs-comment"># In my PyTorch notebook (using the pytorch-env kernel)</span>
<span class="hljs-keyword">import</span> torch
model = torch.nn.Sequential(...)
</code></pre>
<p>The best part? I could export the environment specifications directly from JUNO, making it trivial for teammates to recreate the exact environment.</p>
<h2 id="heading-under-the-hood">Under the Hood</h2>
<p>JUNO isn't just a pretty interface—it leverages proven technologies like <code>venv</code> or <a target="_blank" href="https://anaconda.org/anaconda/conda"><code>conda</code></a> while abstracting away their complexities. The software communicates with a backend service that manages:</p>
<ul>
<li><p>Environment creation and deletion</p>
</li>
<li><p>Package installation and removal</p>
</li>
<li><p>Kernel registration with JupyterLab</p>
</li>
<li><p>Environment activation and deactivation</p>
</li>
</ul>
<p>This architecture ensures that JUNO integrates seamlessly with existing <a target="_blank" href="https://anaconda.org/anaconda/conda">Python</a> packaging tools while providing a superior user experience.</p>
<h2 id="heading-why-this-matters-for-data-science-teams">Why This Matters for Data Science Teams</h2>
<p>For teams building data products, reproducibility isn't just a nice-to-have—it's essential. JUNO addresses this need by:</p>
<ul>
<li><p>Reducing environment setup time from minutes to seconds</p>
</li>
<li><p>Eliminating "works on my machine" problems</p>
</li>
<li><p>Simplifying onboarding for new team members</p>
</li>
<li><p>Making dependency management accessible to less technical users</p>
</li>
</ul>
<p>The productivity gains are substantial. In my experience, teams using <a target="_blank" href="https://github.com/velocitatem/juno">JUNO</a> spend significantly less time debugging environment issues and more time solving actual problems.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Managing virtual environments in JupyterLab has long been a pain point for data scientists and analysts. JUNO transforms this experience by bringing environment management into the JupyterLab interface, making it accessible and intuitive.</p>
<p>Whether you're a solo data scientist juggling multiple projects or part of a team that needs reproducible environments, JUNO offers a compelling solution that streamlines your workflow and eliminates one of the most persistent headaches in the Jupyter ecosystem.</p>
<p>Give it a try on your next project—your future self (and your teammates) will thank you.</p>
]]></content:encoded></item><item><title><![CDATA[Highlights from FOSDEM 2025: Key Takeaways]]></title><description><![CDATA[The first weekend of February I had the pleasure to attend the FOSDEM 2025 conference in Brussels. This university event brought me a lot of insight into the future of the Open Source world and how I can work within it. Although a lot of attendees co...]]></description><link>https://blog.alves.world/highlights-from-fosdem-2025-key-takeaways</link><guid isPermaLink="true">https://blog.alves.world/highlights-from-fosdem-2025-key-takeaways</guid><category><![CDATA[Digital Public Goods]]></category><category><![CDATA[fosdem]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[open ai]]></category><category><![CDATA[#cybersecurity]]></category><category><![CDATA[sustainability]]></category><category><![CDATA[EU]]></category><dc:creator><![CDATA[Daniel Alves Rosel]]></dc:creator><pubDate>Tue, 04 Feb 2025 19:10:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738669260585/84938420-fe1d-4214-a718-09a80bb2b37a.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The first weekend of February I had the pleasure to attend the FOSDEM 2025 conference in Brussels. This university event brought me a lot of insight into the future of the Open Source world and how I can work within it. Although a lot of attendees come to visit the more <em>technical</em> dev-rooms to learn more about Rust or Swift, I tried to come as close to a 50-50 split between the more community and policy focused talks and tracks that go deep on AI in open-source.</p>
<h2 id="heading-saturday">Saturday</h2>
<p>I started the day <strong>community dev-room</strong> where I came to see the <strong>Build a Great Business on Open Source without Selling Your Soul</strong> - this was the second talk of that day as it is paramount to come early to get a seat in the lecture halls. This talk emphasized ways of monetizing successful open-source projects through feature development, enterprise support, consulting, education. All these aspects come together in three different models of structuring business around the OSS.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Model</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td><strong>Giving Back</strong></td><td>Community-driven approach, giving back via support services.</td></tr>
<tr>
<td><strong>Open Core</strong></td><td>Core product is open source, with proprietary add-ons (authentication, authorization, clustering, performance enhancements, libraries, integrations) generating up to 80% margins. (Example: DBeaver offers both community and pro versions.)</td></tr>
<tr>
<td><strong>Cloud Management</strong></td><td>Offers cloud-based management (automation, monitoring, upgrades) with high gross margins (50-80%), creating sticky customer relationships.</td></tr>
</tbody>
</table>
</div><p>Another highlight of this day was <strong>To Mine Or Not To Mine - Training of (Generative) AI Models under the TDM Exception in EU Copyright Laws</strong>, in which the speaker highlights how lacking definition, structuring and comprehension of law-makers in the field of AI contributes to an unhealthy ecosystem where businesses and developers are left with a lot ambiguity and possible legal threat models which affect core functionalities of the business, opening them up for lawsuits. In a talk on Scaling Open-Source Solutions to Achieve the Sustainable Development Goal I had also learned about DGP (Digital Public Good) and its new members: Wikipedia, Open Food Facts and the Tor browser. Some references I took away from the mentions by the UN Members are:</p>
<ul>
<li><p><a target="_blank" href="https://drive.google.com/file/d/1IxkT9dOG0lTtLirle3jPEUg_L7WczfPz/view?usp=sharing">OSSCoP</a></p>
</li>
<li><p><a target="_blank" href="https://unite.un.org/news/un-eu-launch-2nd-oss4sdg-hackathon-sustainable-cities-communities%E2%80%94register-today">OSS4SDG</a></p>
</li>
<li><p><a target="_blank" href="https://europeunlocked.eu/"><code>&lt;UNLOCKED/&gt;</code></a> - I was unable to find this newsletter online.</p>
</li>
<li><p><a target="_blank" href="https://www.un.org/digital-emerging-technologies/content/open-source-digital-transformation">UN OpenSource Portal</a></p>
</li>
<li><p><a target="_blank" href="https://unite.un.org/reboot">Reboot The Earth</a></p>
</li>
</ul>
<p>A presented list of opportunities associated with OSS in the EU can be found below, taken from <a target="_blank" href="https://fosdem.org/2025/schedule/event/fosdem-2025-5687-scaling-open-source-solutions-to-achieve-the-sustainable-development-goals-a-global-call-to-action/">this slide-deck.</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738668197128/d0a17468-e664-4590-97ae-e021904b5b23.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-sunday">Sunday</h2>
<p>The last day of the conference I started in the Cybersecurity rooms where I was met with an interesting concept of the contrast between anonymity and surveillance. These talks explored various methods of de-centralized communication and proof of ownership which was reliant only on the end-user to verify in order to avoid third-party trust necessity. <a target="_blank" href="https://arxiv.org/abs/2305.08533">Trustchain</a> was a big highlight of the security talks, touching on <a target="_blank" href="https://www.w3.org/TR/did-1.0/">DIDs</a> and <a target="_blank" href="https://www.w3.org/TR/vc-data-model-2.0/">Verifiable Credentials</a>. Continuing the day I attended a talk in one of the main tracks on how to build better README files for open source projects, which much more than anything stressed the need for automation, clarity and the overall sanity of the community.</p>
<p>Attending FOSDEM 2025 was an enlightening experience that provided a comprehensive view of the current and future landscape of open-source technology. The conference highlighted the diverse ways in which open-source projects can be monetized while maintaining their core values, as well as the legal and ethical challenges posed by AI developments. The discussions on sustainable development and cybersecurity underscored the importance of collaboration and innovation in addressing global challenges. Overall, FOSDEM 2025 reinforced the critical role of open-source communities in driving technological advancement and societal progress.</p>
]]></content:encoded></item><item><title><![CDATA[Maximize Meal Prep Efficiency Using Coding and AI]]></title><description><![CDATA[As a preface, I am a big fan of self-hosted and open-source software, I try to use as much of it to manage various digital parts of my life. Trying to find a way to better organize my meals I came across Grocy, a web-based self-hosted groceries & hou...]]></description><link>https://blog.alves.world/maximize-meal-prep-efficiency-using-coding-and-ai</link><guid isPermaLink="true">https://blog.alves.world/maximize-meal-prep-efficiency-using-coding-and-ai</guid><category><![CDATA[mealprepp]]></category><category><![CDATA[AI]]></category><category><![CDATA[Scraping]]></category><dc:creator><![CDATA[Daniel Alves Rosel]]></dc:creator><pubDate>Sun, 26 Jan 2025 23:00:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1737722749495/733f8900-2f50-4310-8b1e-1bad9e326635.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As a preface, I am a big fan of self-hosted and open-source software, I try to use as much of it to manage various digital parts of my life. Trying to find a way to better organize my meals I came across <a target="_blank" href="https://grocy.info/">Grocy</a>, a web-based self-hosted groceries &amp; household management solution for your home. After two weeks of heavy use, there is nothing better for planning and managing meals especially when it comes to preparing my meals for a week ahead.</p>
<h2 id="heading-the-issues-with-the-basics">The Issues with the Basics</h2>
<p>After some time, searching up “meal prep recipes” stops yielding meaningful or novel results and one gets stuck on websites with recipes that you dont really want. What if there were a recommendation algorithm for food? Although not meant for food, <a target="_blank" href="https://www.instagram.com/">Instagram</a> is a very big knowledge base of recipes + visuals and instructions for food you might really like.</p>
<p>As I started making recipes from Instagram, I couldnt help but find the process very inefficient and bothersome - having to keep a post open and read chaotic captions. One evening I had finally decided to solve this issue as it had been bothering me for a while and the solution just seems so simple.</p>
<h2 id="heading-solution">Solution</h2>
<p>I quickly got to opening Emacs and starting a new project. First steps: i) Function that can extract the description from an instagram post. ii) Structure data from description into defined format. With a little help from <a target="_blank" href="https://chatgpt.com/">ChatGPT</a> and <a target="_blank" href="https://github.com/features/copilot">GitHub Copilot</a> I was able to get these two down within about 20 minutes. And was then able to move on the a more high level approach to serving this app in a minimal and yet viable way.</p>
<h3 id="heading-instagram-descriptions-extraction">Instagram Descriptions Extraction</h3>
<p>The first safe bet for getting data from websites is selenium, which for this project has just the right amount of complexity, however in my search I did come across <a target="_blank" href="https://seleniumbase.io/">SeleniumBase</a> which is actually capable of extracting much more information from website that other tools just cannot get to. Since the web is a very structured place, extracting the description was quite simple:</p>
<pre><code class="lang-python">driver = webdriver.Chrome(options=options)
<span class="hljs-keyword">try</span>:
    driver.get(url)
    time.sleep(<span class="hljs-number">5</span>)  <span class="hljs-comment"># Wait for page to load</span>

    <span class="hljs-comment"># Instagram caption is often in the og:description meta tag</span>
    <span class="hljs-keyword">try</span>:
        description = driver.find_element(
            By.XPATH, <span class="hljs-string">"//meta[@property='og:description']"</span>
        ).get_attribute(<span class="hljs-string">"content"</span>)
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        print(<span class="hljs-string">"Error fetching description:"</span>, e)
        description = <span class="hljs-string">""</span>
<span class="hljs-keyword">finally</span>:
    driver.quit()
</code></pre>
<p>And we now have our description given literally any instagram post form a public page.</p>
<h3 id="heading-parsing-data-into-structure">Parsing Data into Structure</h3>
<p>Once we have our description from the above function, we can then use a simple snippet form the OpenAI documentation which takes care of extracting any text data into a defined pydantic model. Our model is very simple:</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Ingredient</span>(<span class="hljs-params">BaseModel</span>):</span>
    name: str
    quantity: float
    unit: str
    optional: bool

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RecipeSchema</span>(<span class="hljs-params">BaseModel</span>):</span>
    name: str
    ingredients: List[Ingredient]
    instructions: List[str]
</code></pre>
<p>To make this a bit more efficient, I wrote some custom decorators which will cache our extraction and formatting functions so we do not over-send any requests and save on our OpenAI calls. Alternatively one could also use locally hosted LLMs or perhaps some regex parsing since this is a very simple case, but for the sake of my time I chose the easy solution.</p>
<h3 id="heading-packaging">Packaging</h3>
<p>Once we have our core functionality I chose to create a flask wrapper which hosts our features in a minimal UI where anyone can submit a URL and view the recipes created and stored in an sqlite database. One reason why I did not go for streamlit which would be much easier in terms of development, is that I wanted to make this as interoperable as I could, so anyone could fetch the recipe with just a simple <code>?format=json</code> flag at the recipe URL.</p>
<p>Once the app was up and running I span up a web app an <a target="_blank" href="https://www.pythonanywhere.com/">pythonanywhere</a> and could instantly get structured recipes from anywhere in the world. This is a very naive implementation as it was done very quickly and just as a tool for anyone to use when they need.</p>
<p>In conclusion, leveraging technology like Grocy, Instagram, and AI tools can significantly enhance the meal prepping process, making it more efficient and enjoyable. By automating the extraction and structuring of recipe data from Instagram, you can save time and effort, allowing for a more streamlined approach to meal planning. The integration of open-source software and AI not only simplifies the task but also offers a customizable and scalable solution for anyone looking to optimize their meal preparation routine. This innovative approach demonstrates the potential of combining technology with everyday tasks to improve productivity and convenience. You can find the website here: <a target="_blank" href="https://velocitatem.pythonanywhere.com/">https://velocitatem.pythonanywhere.com/</a> or on my <a target="_blank" href="https://github.com/velocitatem/chefbyte">GitHub</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Boost Your Emacs Setup: Implement AI in Spacemacs with Fabric]]></title><description><![CDATA[Last weekend, I decided to tackle a project that had been on my mind for a while: integrating AI capabilities directly into my Spacemacs environment. The result was Fabric.el, a wrapper around Fabric that supercharges text work with AI-driven pattern...]]></description><link>https://blog.alves.world/boost-your-emacs-setup-implement-ai-in-spacemacs-with-fabric</link><guid isPermaLink="true">https://blog.alves.world/boost-your-emacs-setup-implement-ai-in-spacemacs-with-fabric</guid><category><![CDATA[Emacs]]></category><category><![CDATA[AI]]></category><category><![CDATA[LLM's ]]></category><dc:creator><![CDATA[Daniel Alves Rosel]]></dc:creator><pubDate>Thu, 23 Jan 2025 23:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/qAjJk-un3BI/upload/e418669efeb23c67e39f9b8f864b657b.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Last weekend, I decided to tackle a project that had been on my mind for a while: integrating AI capabilities directly into my Spacemacs environment. The result was Fabric.el, a wrapper around <a target="_blank" href="https://github.com/danielmiessler/fabric">Fabric</a> that supercharges text work with AI-driven patterns. Here’s how I did it.</p>
<h1 id="heading-the-idea">The Idea</h1>
<p>The idea was simple: bring the power of AI directly into Spacemacs. Having tried various Chat GPT integrations, none of which seemed to align with the way I wanted to use LLMs, I was very glad that I came across <a target="_blank" href="https://github.com/danielmiessler/fabric">fabric</a> I wanted to make it easy to apply AI patterns to text, whether it was an entire buffer or just a selected region. The goal was to enhance workflow efficiency by making advanced AI tools more accessible.</p>
<h1 id="heading-getting-started">Getting Started</h1>
<p>I started by cloning installing the Fabric AI repository. Fabric AI is an impressive tool that allows you to apply various AI patterns to text. My task was to create a seamless integration with Spacemacs, so users could leverage these capabilities without leaving their editor.</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/danielmiessler/fabric.git
</code></pre>
<p>With the Fabric AI code in hand, I began writing the wrapper. It is just a simple wrapper around the CLI interface provided by fabric, you can clone it from <a target="_blank" href="https://github.com/velocitatem/fabric.el">here</a> and them simply load the lisp file into your configuration:</p>
<pre><code class="lang-lisp">(<span class="hljs-name">load</span> <span class="hljs-string">"/path/to/fabric.el/fabric.el"</span>)
</code></pre>
<h1 id="heading-key-features">Key Features</h1>
<p>The core features of Fabric.el are straightforward but powerful:</p>
<ul>
<li><p><strong>AI Integration</strong>: Directly integrates with Fabric AI, bringing advanced AI capabilities to your fingertips.</p>
</li>
<li><p><strong>Effortless Pattern Application</strong>: Apply AI patterns to your entire buffer or just a selected region with ease.</p>
</li>
<li><p><strong>Workflow Efficiency</strong>: Custom keybindings designed for Spacemacs enhance your workflow, making AI tools more accessible than ever.</p>
</li>
</ul>
<h1 id="heading-building-the-integration">Building the Integration</h1>
<p>The integration itself was built around a few key functions. The most important were <code>fabric-run-pattern-on-buffer</code> and <code>fabric-run-pattern-on-region</code>. These functions allow users to apply AI patterns to either the entire buffer or a specific region of text.</p>
<p>Here’s a simplified version of what these functions look like:</p>
<pre><code class="lang-lisp">(<span class="hljs-name">defun</span> fabric-run-pattern-on-buffer ()
  (<span class="hljs-name">interactive</span>)
  (<span class="hljs-name">let</span> ((<span class="hljs-name">content</span> (<span class="hljs-name">buffer-string</span>)))
    (<span class="hljs-name">fabric-apply-pattern</span> content)))
</code></pre>
<pre><code class="lang-lisp">(<span class="hljs-name">defun</span> fabric-run-pattern-on-region (<span class="hljs-name">start</span> end)
  (<span class="hljs-name">interactive</span> <span class="hljs-string">"r"</span>)
  (<span class="hljs-name">let</span> ((<span class="hljs-name">content</span> (<span class="hljs-name">buffer-substring</span> start end)))
    (<span class="hljs-name">fabric-apply-pattern</span> content)))
</code></pre>
<p>These functions call <code>fabric-apply-pattern</code>, which sends the text to Fabric AI and returns the transformed content. The transformed content is then displayed in a separate buffer, ensuring that the original text remains untouched.</p>
<h1 id="heading-example-use-case">Example Use-Case</h1>
<p>Imagine you’re working on a large text file and want to enhance its content using an AI pattern. With Fabric.el, you can simply write your prompt into a buffer or highlight a region you want to send to the LLM. Then, use <code>fabric-run-pattern-on-buffer</code> or <code>fabric-run-pattern-on-region</code> to apply the selected pattern (or use the keybindings). Fabric AI transforms your content, all within your Spacemacs environment. One of my favorite use-cases so far is writing email and working with daily text messages and other common text modalities.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737808500189/2c967e46-f3e8-4d83-92d5-4dc5b73a1c31.gif" alt class="image--center mx-auto" /></p>
<h1 id="heading-contributing">Contributing</h1>
<p>One of the best parts of working on open-source projects is the community. I welcome contributions from everyone! If you’re interested in improving Fabric.el or adding new features, please fork the repository, make your changes, and submit a pull request. Let’s make Fabric.el even better together.</p>
<h1 id="heading-final-thoughts">Final Thoughts</h1>
<p>Building Fabric.el over a weekend was a rewarding experience. It’s amazing how much you can accomplish with a clear goal and a bit of determination. If you’re a Spacemacs user looking to enhance your workflow with AI, give Fabric.el a try. It might just take your productivity to new heights.</p>
]]></content:encoded></item></channel></rss>