<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Satwik Sai Prakash Sahoo</title>
    <description>The latest articles on DEV Community by Satwik Sai Prakash Sahoo (@satwiksps).</description>
    <link>https://dev.to/satwiksps</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3961574%2Fb848de46-61a0-4598-b0be-053b4b8b5dca.jpeg</url>
      <title>DEV Community: Satwik Sai Prakash Sahoo</title>
      <link>https://dev.to/satwiksps</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/satwiksps"/>
    <language>en</language>
    <item>
      <title>Halfway Through GSoC</title>
      <dc:creator>Satwik Sai Prakash Sahoo</dc:creator>
      <pubDate>Mon, 20 Jul 2026 05:33:56 +0000</pubDate>
      <link>https://dev.to/satwiksps/halfway-through-gsoc-14ba</link>
      <guid>https://dev.to/satwiksps/halfway-through-gsoc-14ba</guid>
      <description>&lt;p&gt;Hey everyone! We have officially hit the halfway mark of the Google Summer of Code (GSoC) 2026 coding period. &lt;/p&gt;

&lt;p&gt;These past two weeks have been heavily focused on expanding the &lt;a href="https://summerofcode.withgoogle.com/programs/2026/projects/P5QOhl9F" rel="noopener noreferrer"&gt;Neural Network Builder API&lt;/a&gt; beyond just standard NPE (Neural Posterior Estimation) models. I have successfully merged PRs &lt;a href="https://github.com/sbi-dev/sbi/pull/1904" rel="noopener noreferrer"&gt;#1904&lt;/a&gt; and &lt;a href="https://github.com/sbi-dev/sbi/pull/1912" rel="noopener noreferrer"&gt;#1912&lt;/a&gt; into the &lt;code&gt;gsoc-2026&lt;/code&gt; branch for &lt;strong&gt;&lt;a href="https://github.com/sbi-dev/sbi" rel="noopener noreferrer"&gt;sbi&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here is a breakdown of what I worked on, the architectural challenges we solved, and some vital lessons learned about failing fast and role-neutral design.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/sbi-dev/sbi/pull/1904" rel="noopener noreferrer"&gt;PR #1904&lt;/a&gt;: Integrating the Builder into NLE
&lt;/h2&gt;

&lt;p&gt;In my previous PR, we successfully wired the &lt;code&gt;DensityEstimatorBuilder&lt;/code&gt; into NPE trainers. The next logical step was to do the same for Neural Likelihood Estimation (NLE) trainers. However, this brought up an immediate architectural challenge regarding how the builder signs its inputs.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Role-Neutral &lt;code&gt;build()&lt;/code&gt; Signature
&lt;/h3&gt;

&lt;p&gt;Previously, the &lt;code&gt;build()&lt;/code&gt; method took &lt;code&gt;(batch_theta, batch_x)&lt;/code&gt;. This made sense for NPE, which estimates the posterior distribution 

&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;p&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="mord"&gt;∣&lt;/span&gt;&lt;span class="mord"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, meaning 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is the input and 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is the condition.&lt;/p&gt;

&lt;p&gt;However, NLE estimates the likelihood 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;p&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="mord"&gt;∣&lt;/span&gt;&lt;span class="mord"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. In this case, 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is the input and 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is the condition.&lt;/p&gt;

&lt;p&gt;If we kept the &lt;code&gt;(batch_theta, batch_x)&lt;/code&gt; signature on the base builder, it would be extremely confusing and semantically incorrect for NLE.&lt;/p&gt;

&lt;p&gt;The fix? &lt;strong&gt;Role-Neutral Signatures&lt;/strong&gt;.&lt;br&gt;
My mentor &lt;a href="https://github.com/janfb" rel="noopener noreferrer"&gt;Jan Teusen&lt;/a&gt; suggested that I should refactor the base builder and &lt;code&gt;DensityEstimatorBuilder&lt;/code&gt; methods to accept &lt;code&gt;(batch_input, batch_condition)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now, the trainers handle the role assignment via the &lt;code&gt;_wrap_builder()&lt;/code&gt; closure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;For NPE:&lt;/strong&gt; &lt;code&gt;build(batch_input=batch_theta, batch_condition=batch_x)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;For NLE:&lt;/strong&gt; &lt;code&gt;build(batch_input=batch_x, batch_condition=batch_theta)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This change cleanly decouples the mathematical model the network represents from the data types the network consumes.&lt;/p&gt;
&lt;h3&gt;
  
  
  Parameterizing Tests
&lt;/h3&gt;

&lt;p&gt;During review, my mentor also suggested that the NPE and NLE integration tests were essentially "twin" tests doing the exact same thing with different objects, we parameterized them!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;TRAINERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;NPE_C&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;posterior_nn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;theta&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NLE_A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;likelihood_nn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;x&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="nd"&gt;@pytest.mark.parametrize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trainer,factory&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;TRAINERS&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;npe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nle&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_string_emits_deprecation_warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trainer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;prior&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MultivariateNormal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;zeros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;eye&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;FutureWarning&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;deprecated&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;trainer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prior&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;density_estimator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;maf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;show_progress_bars&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This saved a ton of code duplication while keeping the coverage identical.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/sbi-dev/sbi/pull/1912" rel="noopener noreferrer"&gt;PR #1912&lt;/a&gt;: Mixed Density Estimators (MNLE &amp;amp; MNPE)
&lt;/h2&gt;

&lt;p&gt;For datasets containing mixed data types (both continuous and discrete variables), sbi uses Mixed Neural Posterior/Likelihood Estimators (MNPE/MNLE).&lt;/p&gt;

&lt;p&gt;To support these, I created a sibling class to our main builder: the &lt;code&gt;MixedDensityEstimatorBuilder&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  "continuous_model" over "model"
&lt;/h3&gt;

&lt;p&gt;Our main design choice here was using the field &lt;code&gt;continuous_model&lt;/code&gt; instead of just &lt;code&gt;model&lt;/code&gt;. This is because the supported mixed architectures include non-flow models like MDN and MADE. Now, a user can explicitly configure the continuous sub-network: &lt;code&gt;MixedDensityEstimatorBuilder(continuous_model="nsf")&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Failing Fast is Better Than Failing Late
&lt;/h3&gt;

&lt;p&gt;MNPE requires a &lt;code&gt;MixedDensityEstimator&lt;/code&gt;. If a user accidentally passed a standard &lt;code&gt;DensityEstimatorBuilder&lt;/code&gt; (e.g., &lt;code&gt;MNPE(density_estimator=DensityEstimatorBuilder())&lt;/code&gt;), the code would gladly accept it, train an entire continuous normal flow for hundreds of epochs, and then crash at the very end when it finally checked the returned class type.&lt;/p&gt;

&lt;p&gt;Failing at the end of a long training run with a cryptic error is terrible UX.&lt;/p&gt;

&lt;p&gt;We added a strict type-check inside the trainer initialization to fail fast:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;density_estimator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_EstimatorBuilderBase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;density_estimator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MixedDensityEstimatorBuilder&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;MNPE requires a MixedDensityEstimatorBuilder; got &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;density_estimator&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;. Use &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;MixedDensityEstimatorBuilder(continuous_model=...).&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if a user makes this mistake, the code crashes instantly with clear instructions on how to fix it, saving hours of compute time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Catching Configuration Drift
&lt;/h3&gt;

&lt;p&gt;We defined &lt;code&gt;_VALID_MIXED_CONTINUOUS_MODELS&lt;/code&gt; to validate inputs. However, hardcoding this set means it could drift away from the actual supported models in the factory if another developer adds a model later. To prevent this, I added a test specifically designed to catch configuration drift:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_valid_continuous_models_match_builders&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sbi.neural_nets.net_builders.mixed_nets&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;model_builders&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;_VALID_MIXED_CONTINUOUS_MODELS&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;frozenset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_builders&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;We are halfway there! The continuous and mixed density estimators are successfully wired into the system. Next up, we will be tackling the remaining likelihood and classifier builders to complete the NN Builder ecosystem.&lt;/p&gt;

&lt;p&gt;Thanks for reading, and stay tuned for the next update!&lt;/p&gt;

</description>
      <category>gsoc</category>
      <category>opensource</category>
      <category>google</category>
      <category>github</category>
    </item>
    <item>
      <title>First internal integration of the new API</title>
      <dc:creator>Satwik Sai Prakash Sahoo</dc:creator>
      <pubDate>Mon, 29 Jun 2026 17:47:42 +0000</pubDate>
      <link>https://dev.to/satwiksps/first-internal-integration-of-the-new-api-25ii</link>
      <guid>https://dev.to/satwiksps/first-internal-integration-of-the-new-api-25ii</guid>
      <description>&lt;p&gt;Hello again! The GSoC coding period is in full swing, and weeks 3 and 4 have been absolutely packed with progress. &lt;/p&gt;

&lt;p&gt;Following up on the foundational work from my first PR, I have just successfully merged two major PRs (&lt;a href="https://github.com/sbi-dev/sbi/pull/1877" rel="noopener noreferrer"&gt;#1877&lt;/a&gt; and &lt;a href="https://github.com/sbi-dev/sbi/pull/1882" rel="noopener noreferrer"&gt;#1882&lt;/a&gt;) into the gsoc-2026 branch for &lt;a href="https://github.com/sbi-dev" rel="noopener noreferrer"&gt;sbi&lt;/a&gt;. These PRs introduce the first concrete builder class and wire it directly into the core Neural Posterior Estimation (NPE) trainers. &lt;/p&gt;

&lt;p&gt;Here is a dive into what I built, the technical hurdles, and a very valuable lesson I learned about software architecture along the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/sbi-dev/sbi/pull/1877" rel="noopener noreferrer"&gt;PR #1877&lt;/a&gt;: The &lt;code&gt;DensityEstimatorBuilder&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The primary goal of this phase was to replace the old, opaque &lt;code&gt;posterior_nn()&lt;/code&gt; and &lt;code&gt;likelihood_nn()&lt;/code&gt; factory closures with something typed, inspectable, and much more robust. &lt;/p&gt;

&lt;p&gt;To solve this, I introduced the &lt;code&gt;DensityEstimatorBuilder&lt;/code&gt;. It inherits from the base contract we established in Week 1 and serves as the unified entry point for creating neural networks in &lt;code&gt;sbi&lt;/code&gt;. Using the &lt;code&gt;__post_init__&lt;/code&gt; method in Python dataclasses, it immediately validates the model name against a &lt;code&gt;_VALID_DENSITY_MODELS&lt;/code&gt; set, failing early if the user provides an unknown architecture.&lt;/p&gt;

&lt;h3&gt;
  
  
  Major architectural shift
&lt;/h3&gt;

&lt;p&gt;Initially, our plan dictated that the &lt;code&gt;build()&lt;/code&gt; method should take a &lt;code&gt;BuildContext&lt;/code&gt; object. The idea was that this context would hold all necessary information, including pre-computed z-scoring stats, and pass it neatly down the chain. &lt;/p&gt;

&lt;p&gt;However, as I implemented the body of the &lt;code&gt;build()&lt;/code&gt; method, my mentor &lt;a href="https://github.com/janfb" rel="noopener noreferrer"&gt;Jan Teusen&lt;/a&gt; noticed that the &lt;code&gt;context&lt;/code&gt; parameter wasn't actually being used. Every piece of information the builder needed could be derived directly from the raw &lt;code&gt;batch_theta&lt;/code&gt; and &lt;code&gt;batch_x&lt;/code&gt; tensors. &lt;/p&gt;

&lt;p&gt;We realized that forcing the &lt;code&gt;BuildContext&lt;/code&gt; into this signature was a &lt;strong&gt;premature abstraction&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Instead of holding onto a design just because it was the original plan, we decided to defer the context object entirely until the z-scoring stats are actually pre-computed in a later phase. We updated our roadmap and simplified the &lt;code&gt;build&lt;/code&gt; signature.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;batch_theta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;batch_x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It was a great decision to defer the &lt;code&gt;context&lt;/code&gt; implementation to work on the breadth first and then move towards depth.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/sbi-dev/sbi/pull/1882" rel="noopener noreferrer"&gt;PR #1882&lt;/a&gt;: Integrating the Builder into NPE Trainers
&lt;/h2&gt;

&lt;p&gt;With the builder merged, the next step was integration. I updated &lt;code&gt;PosteriorEstimatorTrainer&lt;/code&gt;, &lt;code&gt;NPE_B&lt;/code&gt;, &lt;code&gt;NPE_C&lt;/code&gt;, and &lt;code&gt;MNPE&lt;/code&gt; to accept the new &lt;code&gt;DensityEstimatorBuilder&lt;/code&gt; instead of relying solely on strings or callables.&lt;/p&gt;

&lt;p&gt;To maintain backward compatibility while moving the API forward, a graceful deprecation path was implemented. If a user passes a string (e.g., &lt;code&gt;"maf"&lt;/code&gt;), the code still works perfectly, but it now emits a &lt;code&gt;FutureWarning&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;density_estimator&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_build_neural_net&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_wrap_builder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DensityEstimatorBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;maf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;density_estimator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;warnings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Passing a string for `density_estimator` is deprecated. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use DensityEstimatorBuilder(model=...) instead.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nb"&gt;FutureWarning&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;stacklevel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_build_neural_net&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;posterior_nn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;density_estimator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;density_estimator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_EstimatorBuilderBase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_build_neural_net&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_wrap_builder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;density_estimator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_build_neural_net&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;density_estimator&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Overal feedback on my work
&lt;/h2&gt;

&lt;p&gt;The code review for &lt;a href="https://github.com/sbi-dev/sbi/pull/1882" rel="noopener noreferrer"&gt;PR #1882&lt;/a&gt; was intense but incredibly rewarding. My mentor provided feedback on how to write tests that are not just concise, but strong and explicit in their intent.&lt;/p&gt;

&lt;p&gt;For example, I originally wrote a test that checked if passing a callable avoided triggering the deprecation warning. But I wasn't actually asserting that no warning was thrown, I was just running the code and assuming silence meant success.&lt;/p&gt;

&lt;p&gt;My mentor showed me how to use &lt;code&gt;warnings.catch_warnings()&lt;/code&gt; with a strict filter to instantly fail the test if a &lt;code&gt;FutureWarning&lt;/code&gt; leaked through:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;warnings&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;warnings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;catch_warnings&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;warnings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;simplefilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;FutureWarning&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;inference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;NPE_C&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prior&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;density_estimator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;show_progress_bars&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also did a deep dive into correct type hinting and managing default arguments. I initially left &lt;code&gt;density_estimator="maf"&lt;/code&gt; as the default argument in the &lt;code&gt;NPE_C&lt;/code&gt; initialization. My mentor pointed out that this would cause the deprecation warning to fire every single time a user initialized the class without arguments! The fix was to change the type hint default to &lt;code&gt;None&lt;/code&gt; and handle the &lt;code&gt;"maf"&lt;/code&gt; fallback inside the logic block.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;Weeks 3 and 4 were a massive leap forward for the API refactor. We now have a working, integrated builder that correctly handles all continuous density estimators.&lt;/p&gt;

&lt;p&gt;Next up, I will be tackling the remaining likelihood and classifier builders. Thanks for following along on this journey, and see you in the next update!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>gsoc</category>
      <category>python</category>
      <category>ai</category>
    </item>
    <item>
      <title>Merging My First PR for GSoC!</title>
      <dc:creator>Satwik Sai Prakash Sahoo</dc:creator>
      <pubDate>Mon, 15 Jun 2026 13:12:48 +0000</pubDate>
      <link>https://dev.to/satwiksps/merging-my-first-pr-for-gsoc-542h</link>
      <guid>https://dev.to/satwiksps/merging-my-first-pr-for-gsoc-542h</guid>
      <description>&lt;p&gt;Hey everyone! The official coding period for Google Summer of Code (GSoC) has begun, and I am thrilled to share that my very first Pull Request (PR) for the &lt;strong&gt;sbi&lt;/strong&gt; (Simulation-Based Inference) repository has been officially merged! &lt;/p&gt;

&lt;p&gt;These first two weeks have been packed with writing code, writing tests, and most importantly, going through an incredibly insightful code review process with my mentors. &lt;/p&gt;

&lt;p&gt;Here is a breakdown of what I worked on, the technical challenges I faced, and the best practices I learned along the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Laying the Foundation (&lt;a href="https://github.com/sbi-dev/sbi/pull/1872" rel="noopener noreferrer"&gt;PR #1872&lt;/a&gt;)
&lt;/h2&gt;

&lt;p&gt;My GSoC project is focused on refactoring the Neural Network (NN) Builder API. Before we can build the new, shiny network builders, we need a solid foundation. This first PR was all about setting up the necessary data structures and renaming existing protocols to make room for the new architecture.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The New &lt;code&gt;build_context.py&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;I created a new file to house the core pieces needed to set up a neural network. This centralizes how the data is prepared before it hits the network:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;ZScoreConfig&lt;/code&gt;&lt;/strong&gt;: Tracks how the user wants to preprocess data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;ZScoreStats&lt;/code&gt;&lt;/strong&gt;: Holds the calculated mean and standard deviation for the data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;BuildContext&lt;/code&gt;&lt;/strong&gt;: Bundles everything required to build a network (shapes, device, dtype, and z-score stats) into a single, clean dataclass.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;compute_z_score_stats()&lt;/code&gt;&lt;/strong&gt;: A helper function to calculate these statistics directly from the training tensors.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Clearing the Naming Space
&lt;/h3&gt;

&lt;p&gt;To make the codebase more intuitive, I had to rename a few core components across 16 different trainer files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Changed &lt;code&gt;ConditionalEstimatorBuilder&lt;/code&gt; to &lt;code&gt;ConditionalEstimatorBuildFn&lt;/code&gt;. This clarifies that the protocol is actually a function, not an object, and frees up the "Builder" name for upcoming classes.&lt;/li&gt;
&lt;li&gt;Changed &lt;code&gt;_EstimatorConfigBase&lt;/code&gt; to &lt;code&gt;_EstimatorBuilderBase&lt;/code&gt;, giving it an empty &lt;code&gt;build()&lt;/code&gt; method to prepare for the next phase.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Big Takeaways from Code Review
&lt;/h2&gt;

&lt;p&gt;Getting the code working was only half the battle. The review process with my mentor, taught me several advanced Python and PyTorch practices. &lt;/p&gt;

&lt;h3&gt;
  
  
  Managing Tensor Devices
&lt;/h3&gt;

&lt;p&gt;When creating the &lt;code&gt;BuildContext&lt;/code&gt;, the data (&lt;code&gt;x&lt;/code&gt; and &lt;code&gt;theta&lt;/code&gt;) are passed in as PyTorch tensors. My mentor pointed out that if &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;theta&lt;/code&gt; accidentally end up on different devices (e.g., one on CPU, one on GPU), it will cause runtime failures. I updated the code to explicitly check that both tensors share the same device and added GPU-specific pytest runs to ensure everything handles device placement gracefully.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dataclasses and Tensor Equality
&lt;/h3&gt;

&lt;p&gt;I originally set up my statistics classes as &lt;code&gt;@dataclass(frozen=True)&lt;/code&gt;. However, because they hold PyTorch tensors, this creates a subtle bug. PyTorch's implementation of equality (&lt;code&gt;==&lt;/code&gt;) for tensors returns a boolean tensor, not a single boolean value, which breaks the dataclass equality checks. &lt;/p&gt;

&lt;p&gt;The fix was simple but crucial:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@dataclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frozen&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ZScoreStats&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;theta_mean&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;theta_std&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;x_mean&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;x_std&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By adding &lt;code&gt;eq=False&lt;/code&gt;, equality becomes identity-based, completely bypassing the PyTorch tensor comparison crash.&lt;/p&gt;

&lt;h3&gt;
  
  
  Graceful Deprecation with PEP 562
&lt;/h3&gt;

&lt;p&gt;Since &lt;code&gt;ConditionalEstimatorBuilder&lt;/code&gt; was used by the community, we couldn't just delete the name and break everyone's code. Instead of leaving a dummy class, I learned how to use module-level &lt;code&gt;__getattr__&lt;/code&gt; to intercept the import and throw a &lt;code&gt;FutureWarning&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__getattr__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ConditionalEstimatorBuilder&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;warnings&lt;/span&gt;
        &lt;span class="n"&gt;warnings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;`ConditionalEstimatorBuilder` has been renamed to &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;`ConditionalEstimatorBuildFn`. The old name still works but will be &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;removed in a future release. Update your import to: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;`from sbi.neural_nets.estimators.base import ConditionalEstimatorBuildFn`.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nb"&gt;FutureWarning&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;stacklevel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ConditionalEstimatorBuildFn&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;AttributeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;module &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="s"&gt; has no attribute &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Refactoring Tests
&lt;/h3&gt;

&lt;p&gt;I used Claude Opus to help generate initial test coverage for the new context types. It gave me class-based tests. However, the &lt;code&gt;sbi&lt;/code&gt; standard relies heavily on function-based tests and &lt;code&gt;pytest&lt;/code&gt; fixtures. I completely refactored the test suite to use &lt;code&gt;@pytest.mark.parametrize&lt;/code&gt; to test valid combinations of inputs, ensuring maximum coverage with minimal, highly readable code.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;With the foundation types successfully merged into the &lt;code&gt;gsoc-2026&lt;/code&gt; branch, the groundwork is officially laid out! Up next is &lt;a href="https://github.com/sbi-dev/sbi/pull/1877" rel="noopener noreferrer"&gt;PR #1877&lt;/a&gt;, where I will be adding the actual &lt;code&gt;DensityEstimatorBuilder&lt;/code&gt; with dynamic &lt;code&gt;build()&lt;/code&gt; dispatching.&lt;/p&gt;

&lt;p&gt;Stay tuned for week 3 and 4 updates!&lt;/p&gt;

</description>
      <category>gsoc</category>
      <category>ai</category>
      <category>python</category>
      <category>opensource</category>
    </item>
    <item>
      <title>GSoC Community Bonding Period: Getting Ready to Code</title>
      <dc:creator>Satwik Sai Prakash Sahoo</dc:creator>
      <pubDate>Thu, 04 Jun 2026 06:51:17 +0000</pubDate>
      <link>https://dev.to/satwiksps/gsoc-community-bonding-period-getting-ready-to-code-5hl9</link>
      <guid>https://dev.to/satwiksps/gsoc-community-bonding-period-getting-ready-to-code-5hl9</guid>
      <description>&lt;p&gt;Hey everyone! Welcome back to my Google Summer of Code (GSoC) journey.&lt;/p&gt;

&lt;p&gt;In my last post, I shared the story of how I got into open source and was selected for GSoC with NumFOCUS to work on the &lt;strong&gt;&lt;a href="https://summerofcode.withgoogle.com/programs/2026/projects/P5QOhl9F" rel="noopener noreferrer"&gt;Neural Network Builder API Refactor&lt;/a&gt;&lt;/strong&gt; project for &lt;strong&gt;sbi&lt;/strong&gt; (Simulation-Based Inference).&lt;/p&gt;

&lt;p&gt;Since the official announcement, the past three weeks have been dedicated to the &lt;strong&gt;Community Bonding Period&lt;/strong&gt;. It is designed to help contributors get to know their mentors, understand the community culture, and familiarize themselves with the codebase and tools.&lt;/p&gt;

&lt;p&gt;Here is exactly what I did during these past three weeks to get ready for the main coding phase!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Kickoff Meeting
&lt;/h2&gt;

&lt;p&gt;We started the bonding period with a great kickoff call on Google Meet. It was a joint meeting that included the mentors for both of the selected sbi projects, the selected GSoC candidates. We were also joined by the mentee who successfully completed the GSoC project for sbi last year!&lt;/p&gt;

&lt;p&gt;Everyone introduced themselves, and it was incredibly inspiring to meet the team face-to-face (virtually!) and hear about everyone's backgrounds. Having a former GSoC student there was a huge bonus, as they shared some great insights into what to expect in the coming months.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up the Machine
&lt;/h2&gt;

&lt;p&gt;A big part of getting started is making sure the development environment is properly configured. During our meetings, we discussed the machine setup in detail to ensure both candidates had everything required to run and test the sbi codebase locally without any hiccups.&lt;/p&gt;

&lt;h2&gt;
  
  
  Embracing AI Coding Assistants
&lt;/h2&gt;

&lt;p&gt;One of the most interesting discussions we had was about using AI coding assistants. In the modern development world, tools like these are becoming standard, and our mentors actually encouraged us to use them!&lt;/p&gt;

&lt;p&gt;However, they emphasized using them carefully and strictly following project guidelines. To help us get the most out of these tools without compromising code quality, the mentors shared some excellent Claude code tutorials and provided us with resources to level up our AI coding skills. It is all about using AI to augment our capabilities, not to blindly write code for us.&lt;/p&gt;

&lt;h2&gt;
  
  
  Diving into the Codebase and Planning
&lt;/h2&gt;

&lt;p&gt;With the setup out of the way, the rest of the three weeks was all about reading. I spent a lot of time diving deep into the sbi codebase and reading through the documentation properly.&lt;/p&gt;

&lt;p&gt;Understanding the architecture is critical for my API refactor project. To keep everything organized and on track, we were provided with a &lt;code&gt;plan.md&lt;/code&gt; file. This document serves as our roadmap, outlining exactly what needs to be tackled, the skills required, and the milestones we need to hit.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;The community bonding period was incredibly helpful. It gave me the time to get comfortable with the team, set up my workflow, and build a solid foundation before the heavy lifting begins.&lt;/p&gt;

&lt;p&gt;Now, the official coding phase is here! I am beyond excited to start pushing commits and working on the Neural Network Builder API Refactor.&lt;/p&gt;

&lt;p&gt;Thanks for reading, and stay tuned. I will be sharing more technical updates and lessons learned as I start writing code for GSoC!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>gsoc</category>
      <category>machinelearning</category>
      <category>python</category>
    </item>
    <item>
      <title>How I Got Selected for GSoC: My Journey with sbi</title>
      <dc:creator>Satwik Sai Prakash Sahoo</dc:creator>
      <pubDate>Sun, 31 May 2026 19:55:27 +0000</pubDate>
      <link>https://dev.to/satwiksps/how-i-got-selected-for-gsoc-my-journey-with-sbi-56g5</link>
      <guid>https://dev.to/satwiksps/how-i-got-selected-for-gsoc-my-journey-with-sbi-56g5</guid>
      <description>&lt;p&gt;Hey everyone! I am super excited to share that I have been selected for &lt;strong&gt;Google Summer of Code (GSoC)&lt;/strong&gt; with &lt;strong&gt;NumFOCUS&lt;/strong&gt;. I will be working on the &lt;strong&gt;&lt;a href="https://summerofcode.withgoogle.com/programs/2026/projects/P5QOhl9F" rel="noopener noreferrer"&gt;Neural Network Builder API Refactor&lt;/a&gt;&lt;/strong&gt; project for the organization &lt;strong&gt;sbi (Simulation-Based Inference)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you are wondering how to get started with open source or what the GSoC process is really like, here is the story of how I got here. Stay tuned, because I will keep updating you on my GSoC journey and sharing my experiences as I get deeper into the project!&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Started Open Source
&lt;/h2&gt;

&lt;p&gt;Being a fan of Linus Torvalds, I was always fascinated by open source. Also, I wanted to test my coding skills. I wanted to know: &lt;em&gt;Is my code actually good enough for the real world?&lt;/em&gt; In my first year of college, I spent a lot of time doing competitive programming. At the same time, I was teaching myself machine learning and mathematics, working mostly with Python and PyTorch. &lt;/p&gt;

&lt;h2&gt;
  
  
  Finding the Right Project
&lt;/h2&gt;

&lt;p&gt;When I decided to try open source, I wanted to find an organization that actually matched what I was learning. Because I was already into machine learning and PyTorch, I went looking for something in that space.&lt;/p&gt;

&lt;p&gt;That is how I found &lt;strong&gt;sbi&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Making my first Pull Request (PR) was a little scary, but the maintainers at sbi were incredibly welcoming. They patiently guided me through my early, beginner-level PRs. Thanks to their feedback, I learned so much about how to write clean, high-quality code. &lt;/p&gt;

&lt;h2&gt;
  
  
  The GSoC Surprise
&lt;/h2&gt;

&lt;p&gt;After a few months of fixing bugs and contributing, I found out from the maintainers that sbi would be participating in GSoC this year. They encouraged me and appreciated the work I had done over the past few months, for which I will be forever grateful.&lt;/p&gt;

&lt;p&gt;But there was one problem: I hadn't researched GSoC at all. I had no idea what the requirements were or how to write a project proposal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Help with the Proposal
&lt;/h2&gt;

&lt;p&gt;Writing the proposal was tough since it was my first time. Luckily, I didn't have to do it alone. &lt;/p&gt;

&lt;p&gt;The maintainers also stepped up to mentor me. They reviewed my proposal drafts, gave me detailed feedback, and helped me improve it step by step until it was ready.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;All that hard work and community support paid off, and I got accepted! &lt;/p&gt;

&lt;p&gt;The GSoC community bonding period just finished up. In my next blog post, I will share exactly what I did during this bonding period to get ready for the main coding phase. &lt;/p&gt;

&lt;p&gt;Thanks for reading, and stay tuned!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>github</category>
      <category>google</category>
      <category>gsoc</category>
    </item>
  </channel>
</rss>
