<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://jaewonchung.me/feed.xml" rel="self" type="application/atom+xml" /><link href="https://jaewonchung.me/" rel="alternate" type="text/html" /><updated>2026-09-24T00:26:37-04:00</updated><id>https://jaewonchung.me/feed.xml</id><title type="html">Jae-Won’s Blog</title><subtitle>Jae-Won&apos;s Blog</subtitle><author><name>Jae-Won Chung</name></author><entry><title type="html">Continuously Monomorphized Systems</title><link href="https://jaewonchung.me/thoughts/research/Continuously-Monomorphized-Systems/" rel="alternate" type="text/html" title="Continuously Monomorphized Systems" /><published>2026-07-02T00:00:00-04:00</published><updated>2026-07-02T00:00:00-04:00</updated><id>https://jaewonchung.me/thoughts/research/Continuously-Monomorphized-Systems</id><content type="html" xml:base="https://jaewonchung.me/thoughts/research/Continuously-Monomorphized-Systems/"><![CDATA[<p>If AI for coding becomes more and more reliable, in the limit, what manner of system building would we converge to?</p>

<h2 id="ai-assisted-software-engineering">AI-Assisted Software Engineering</h2>

<p>Looking back, how did we do additions with computers?
A while ago we always wrote assembly, either by hand or using a C compiler, which is one instruction.
Today we still do some of that, but we’re also using Python a lot, where operands likely sit on the heap, and the interpreter will run much more than one instruction for the addition itself.
Apparently, addition has gotten so much inefficient!</p>

<p>However, the reason we use Python is that it is much easier to write code in those languages than in assembly, especially for complex things due to the higher-level abstractions they provide.
Due to that, when a human looks at the code, it’s also much easier to understand and debug.
So, the cost of doing the simplest thing (e.g., addition) can be much higher in those languages, but the <em>net</em> cost of doing complex things can be much lower (especially considering the time to ship new things).</p>

<p>Here, a very important property that enables this higher-level abstraction to be useful is it being <em>not leaky</em>.
When we write code in Python, we generally don’t worry about how the interpreter is going to boil down our class hierarchy and method resolution into machine code; we only reason at the higher-level API.
With the level of abstraction raised, the world of software engineering was able to produce more complex systems and generally do more cool stuff.</p>

<p>The way I view it, AI-assisted software engineering is a similar lift.
In 2020, if you wanted to create a new static website for your project, you would have to set up a web framework, write a bunch of boilerplate code, and write the actual content, and still no one could figure out how to center a <code class="language-plaintext highlighter-rouge">div</code>.
Or, if you find yourself repeating a similar command in your shell, you would briefly consider automating it with a shell script or a CLI tool, until you realize it’s unclear whether the amount of time you’ll spend on writing that thing is less than the amount of time you’ll save by using it.<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup>
AI-assisted software engineering is a lift in that, the time it takes to build many things that used to take a lot of human time and effort is now significantly reduced; you can ask for a website with a paragraph of natural langauge and get it working the next moment, or you can paste in part of your <code class="language-plaintext highlighter-rouge">~/.zsh_history</code> and get a working CLI tool in minutes.</p>

<p>As of today, however, these AI-assisted tools are not completely reliable.
In other words, they are still <em>leaky</em>; especially for tools that matter, or those with potentially large blast radius, you still have to review the code it generates.
But in the limit of AI-assisted software engineering, it will probably approach non-leakiness.</p>

<h2 id="systems-today-are-polymorphic">Systems Today are Polymorphic</h2>

<p>Now let’s switch to system building.
Why do we build general systems in the first place?
I believe that it is in large part because writing code has been expensive; a human had to write and maintain every line.
Much of software engineering practice, like libraries, frameworks, code sharing, and dynamic dispatch, exists so that we write less code; to have concise representations of our intent in code in higher-level abstractions.</p>

<p>ML systems is no exception.
One codebase runs every model, at every precision, on every accelerator, so that nobody has to write a system per workload.
Identical PyTorch code running on both NVIDIA GPUs and AMD GPUs is a beautiful example of this.
Things like <a href="http://blog.ezyang.com/2020/09/lets-talk-about-the-pytorch-dispatcher/">PyTorch’s dispatcher</a> allows you write one operator call (e.g., <code class="language-plaintext highlighter-rouge">torch.mm</code>), and the right kernel among the many registered ones is dispatched at runtime.
This leads to not only runtime overhead<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup> but also code complexity.
Different models, precisions, and GPU types route to different backends through layers of dynamic dispatch, and reading the code tells you the list of what could run, and figuring out what actually runs in your environment takes effort.</p>

<p>This isn’t merely an issue of PyTorch of course.
<a href="https://docs.vllm.ai/en/v0.25.0/features/">vLLM’s feature compatibility matrix</a> shows that it’s trying to cram in all these features into a single codebase and some combinations are not supported, which is sometimes not a fundamental incompatibility but rather due to the difficulty of maintaining a single codebase that supports all combinations.
vLLM’s hybrid KV cache manager reads each layer type’s attention spec (e.g., full attention, mamba, MLA) on startup, computes how many bytes its state needs per token, and adjusts block sizes until every layer type has the same bytes-per-page.
This is complex runtime resolution logic; it is hard to understand, maintain, keep bug-free, generalize to new model architectures that come out every week, and keep it working for all existing models.</p>

<p>I would call the current systems we’re building <strong>polymorphized</strong> systems: a single system codebase that is polymorphic over many workloads, and the polymorphism is resolved at runtime.</p>

<h2 id="monomorphized-systems">Monomorphized Systems</h2>

<p>I think most of this generalization is a compromise forced on us by the cost of producing code.
However, if AI-assisted software engineering makes writing code fast, we ought to reconsider this compromise.
We can couple the systems layer tightly with the application layer and build each system <strong>monomorphized</strong> for one workload, borrowing the compiler term for stamping out a specialized copy of generic code for each concrete type it is used with.</p>

<p>In such a <strong>monomorphized system</strong>, every choice that a general system defers to runtime dispatch or resolution is instead resolved and baked in at build time.
Places that used to be polymorphic will be replaced by an <em>interface</em> (e.g., prefill attention) and a list of functionally interchangeable implementations (e.g., FlashAttention, FlashInfer, CuDNN), and exactly one of those implementations will be chosen and baked into the system (i.e., the interface will be monomorphized) at build time.
Similarly, configurations are hard-coded, statically known shapes and precisions are baked in, and code paths that do not apply to the deployment are never generated in the first place.</p>

<p>If this is doable, there are many immediate benefits.
Smaller binary size. Minimal dependencies (and surface for supply chain attacks for at least that specific monomorphization). No runtime dispatch overhead or resolution/warmup time on startup or first-run. Trivial to read and step through code for understanding, debugging, and profiling. No worries about code changes of one part of the system unintentionally breaking some completely unrelated part of the system due to a hidden coupling, because that unrelated part of the system doesn’t even exist in your monomorphized system.</p>

<h2 id="continuously-monomorphized-systems">Continuously Monomorphized Systems</h2>

<p>But the world does not stay still; production systems sit on top of components that change at high velocity.
Key dependencies like kernel libraries release constantly (e.g., FlashAttention is the fastest long context prefill attention kernel for GB300 one day, and FlashInfer may take over tomorrow), and hardware architectures, drivers, and CUDA versions keep shifting underneath as well.
On top of that, the target workload the system was built for can itself change: the model, the precision, the request pattern, prefix cache hit rate, etc.</p>

<p>This is why monomorphization must be continuous, which I call <strong>continuously monomorphized systems</strong>.
Each monomorphized system declares its <em>system component dependencies</em> and a <em>workload signature</em>.
A <strong>centralized benchmarking authority</strong> (e.g., one per organization) continuously evaluates the performance of system components whenever a trigger occurs, such as a new release of a kernel library or a change in a workload pattern that corresponds to a workload signature.
When the authority detects that, for a certain workload signature, the performance ranking among interchangeable components compatible with an interface has changed, it will signal the downstream monomorphized system to trigger re-monomorphization.
Centralization is important here; this kind of continuous benchmarking is costly, but it only needs to happen once, rather than being repeated by every downstream system.</p>
<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>An exception is when you just enjoy building cute little tools, like myself. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>To be fair to PyTorch, in the common case, this runtime cost does not show up. This is because dispatch is asynchronous. As long as the CPU dispatching work to the GPU is not the bottleneck, the GPU will not be idle. Even when the CPU is slow, solutions like CUDA graphs can be used for roughly static/repeating sets of kernel. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Jae-Won Chung</name></author><category term="thoughts" /><category term="research" /><summary type="html"><![CDATA[A different way to build systems, enabled by AI-assisted software engineering.]]></summary></entry><entry><title type="html">Prospective PhD Students, Intern Abroad!</title><link href="https://jaewonchung.me/thoughts/research/Prospective-PhD-Students-Intern-Abroad/" rel="alternate" type="text/html" title="Prospective PhD Students, Intern Abroad!" /><published>2026-01-19T00:00:00-05:00</published><updated>2026-01-19T00:00:00-05:00</updated><id>https://jaewonchung.me/thoughts/research/Prospective-PhD-Students-Intern-Abroad</id><content type="html" xml:base="https://jaewonchung.me/thoughts/research/Prospective-PhD-Students-Intern-Abroad/"><![CDATA[<p>Boys, be ambitious!
Prospective PhD students, intern abroad!</p>

<p>Why?
If you’re aiming to get a PhD admission from a US university, interning at a research lab in a US university concretely boosts your chances.
You will get to know professors there, and if you do a good job, they may try to hire you as a PhD student themselves.
At the same time, you will get a strong letter of recommendation from them, which is crucial for PhD admissions.
You see, nearly all letters say that the applicant is <em>very good</em>.
What matters is who said that, and whether the reader of the letter knows the letter writer well enough to weigh in on their opinion.
A professor at a US university is more likely to be known by the letter readers at other US universities.</p>

<p>I never quite imagined that interning abroad was possible when I was a prospective PhD student in SNU.
However, I am now a fifth year PhD student at the University of Michigan CSE, and I can tell you for sure that there are <em>many</em> cases where international students intern abroad at labs in US universities.
I especially see Chinese students (particularly those from elite classes like Yao Class, Turing class, ACM class, etc.) doing this.
We’re always short on good interns; there are tons of engineering work (research and open-source) to be done, and also more project ideas than good people to work on them.</p>

<p>So, it’s worth it, and it’s possible.
Now, is it easy?
Not really.
You need to clearly demonstrate to the professor that you are worth the trouble of sponsoring a J-1 visiting scholar visa for you.
Being from a university that is well-known in the US (e.g., SNU, KAIST) definitely helps, and having a CV &amp; GitHub profile that demonstrate your research potential, engineering skill, and <strong>craftsmanship</strong> is crucial.
Establishing communications with PhD students in the lab beforehand should also help.</p>

<p>You will be traveling to the US for a few months, likely alone in a foreign country with unfamiliar language, culture, and work environment.
You will have to keep yourself alive there and handle unfamiliar paperwork on your own, while also scrambling to do a good job at work.
It’s a great challenge, but also a great opportunity.</p>]]></content><author><name>Jae-Won Chung</name></author><category term="thoughts" /><category term="research" /><summary type="html"><![CDATA[I never quite imagined this was possible when I was a prospective PhD student in Korea.]]></summary></entry><entry><title type="html">Vibe Coding is Speculative Decoding</title><link href="https://jaewonchung.me/thoughts/Vibe-coding-is-speculative-decoding/" rel="alternate" type="text/html" title="Vibe Coding is Speculative Decoding" /><published>2025-12-19T00:00:00-05:00</published><updated>2025-12-19T00:00:00-05:00</updated><id>https://jaewonchung.me/thoughts/Vibe-coding-is-speculative-decoding</id><content type="html" xml:base="https://jaewonchung.me/thoughts/Vibe-coding-is-speculative-decoding/"><![CDATA[<p>Imagine reviewing some text, be it code or a paper.
You find some weird parts about it and take the time to write down comments, only to be told “Oh, I used AI to generate that part.”
I don’t think this is a good answer.</p>

<p>I treat AI-assisted programming or writing as an instance of speculative decoding.
For those unfamiliar with the term, <a href="https://arxiv.org/abs/2211.17192"><em>speculative decoding</em></a> is a technique that speeds up LLM text generation by using a smaller, faster model (the <em>draft model</em>) to generate multiple tokens, and then having the original, larger model (the <em>verifier model</em>) accept or reject those tokens through rejection sampling.
The crucial property of speculative decoding is that once we go through rejection sampling, the resulting accepted tokens <em>exactly</em> follow the distribution of the original larger model; there is no quality loss.</p>

<p>When I use an AI coding assistant (e.g., Copilot, Cursor) to produce code, for instance, the AI model is the <em>draft model</em>, and I (the human programmer) am the <em>verifier model</em> that accepts or rejects AI-generated code based on whether they work correctly and fit my intent.
And I make sure that the code that ultimately gets committed follows the distribution of code that I would have written myself.</p>

<p>I put on this mindset not only when I write text, but also when I review others’ text.
I assume that whatever text has been put forward for review follows the distribution of text the author would have written themselves, and I don’t care whether they used AI assistance or not; it’s an implementation detail that should be hidden behind the <em>abstraction</em> of the author.
That’s why I get annoyed when the answer to my review comment is “Oh, I used AI to generate that part.”
It shows that the author doesn’t have a proper explicit intent for that part of the text, signaling that they didn’t verify thoroughly and is shifting accountability to the AI model.
This makes authorship a <em>leaky abstraction</em> and breaks the assumption that the text follows the author’s distribution.</p>

<p>This is why I think whatever has been put forward by a human author should be attributed only to the author, and whether AI assistance was used or not is irrelevant.
If the text is great, the author should get credit for it; if it’s bad, the author should take accountability for it.
I believe this mindset will help us reap the productivity benefits of AI assistance (with increasing <em>draft acceptance rate</em> as AI models get better) while maintaining quality and accountability.</p>]]></content><author><name>Jae-Won Chung</name></author><category term="thoughts" /><summary type="html"><![CDATA[AI assistance should be hidden behind the abstraction of the author.]]></summary></entry><entry><title type="html">Useful Matplotlib Tricks for Research</title><link href="https://jaewonchung.me/research/technical/Useful-Matplotlib-tricks-for-research/" rel="alternate" type="text/html" title="Useful Matplotlib Tricks for Research" /><published>2024-09-20T00:00:00-04:00</published><updated>2024-09-20T00:00:00-04:00</updated><id>https://jaewonchung.me/research/technical/Useful-Matplotlib-tricks-for-research</id><content type="html" xml:base="https://jaewonchung.me/research/technical/Useful-Matplotlib-tricks-for-research/"><![CDATA[<p>I believe Matplotlib is the de facto standard for plotting.
Because it’s entirely Python code, it’s reproducible (given the same input data), easy to version control, and easy to generate and iterate with ChatGPT.</p>

<p>I’ll go over a couple tricks with Matplotlib that I’ve found useful, especially for research.</p>

<h2 id="making-plots-compatible-with-powerpoint">Making plots compatible with PowerPoint</h2>

<p>PNG files exported with Matplotlib don’t look very nice in PowerPoint slides, especially when you enlarge it.
Also, you can’t, say, change the color of your lines or remove unnecessary components, because they’re all flattened into an image file.</p>

<p>Instead, export your plot in SVG as well.
All you need to do is call <code class="language-plaintext highlighter-rouge">fig.savefig</code> once more with a file path that ends with <code class="language-plaintext highlighter-rouge">.svg</code>.
Then, drag the SVG file onto PowerPoint, right click, and click <em>Convert to Shape</em>.
Now, every component (e.g., line, text) will be converted to PowerPoint-native objects that you can tweak freely.
See also <a href="https://support.microsoft.com/en-us/office/edit-svg-images-in-microsoft-365-69f29d39-194a-4072-8c35-dbe5e7ea528c">Microsoft’s documentation</a> on this.</p>

<p>Before you actually call <code class="language-plaintext highlighter-rouge">savefig</code>, make sure you have the following configuration:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">matplotlib</span> <span class="k">as</span> <span class="n">mpl</span>
<span class="n">mpl</span><span class="p">.</span><span class="n">rcParams</span><span class="p">[</span><span class="s">"svg.fonttype"</span><span class="p">]</span> <span class="o">=</span> <span class="s">"none"</span>
</code></pre></div></div>

<p>Without this, every <em>character</em> in your plot will be saved as a separate text box.
That’s beyond annoying.</p>

<h2 id="making-plot-files-git-friendly">Making plot files Git-friendly</h2>

<p>Let’s say you’re exporting your plot in PDF or SVG and committing it into a Git repository for paper-writing.
Normally, if you re-export the exact same plot (e.g., because you had to restart and re-run every Jupyter Notebook cell), <code class="language-plaintext highlighter-rouge">git</code> will recognize them as modified.
This is because by default, the contents of the PDF/SVG file will change slightly.
This is particularly bad for PDF files, because they are binaries – <code class="language-plaintext highlighter-rouge">git</code> will have to store the whole PDF file because it doesn’t know how to do line-level diff on binary files.
However, it is possible to make Matplotlib generate the <em>exact</em> same file each time deterministically.</p>

<h3 id="pdf-files">PDF files</h3>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">fig</span><span class="p">.</span><span class="n">savefig</span><span class="p">(</span><span class="s">"plot.pdf"</span><span class="p">,</span> <span class="n">metadata</span><span class="o">=</span><span class="p">{</span><span class="s">"CreationDate"</span><span class="p">:</span> <span class="bp">None</span><span class="p">})</span>
</code></pre></div></div>

<p>Notice that we’re removing the file creation date from the PDF metadata.</p>

<h3 id="svg-files">SVG files</h3>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">fig</span><span class="p">.</span><span class="n">savefig</span><span class="p">(</span><span class="s">"plot.svg"</span><span class="p">,</span> <span class="n">metadata</span><span class="o">=</span><span class="p">{</span><span class="s">"Date"</span><span class="p">:</span> <span class="bp">None</span><span class="p">})</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">savefig</code> call is basically the same for SVG, except that it needs a slightly different metadata key for the creation date.
However, we do need one more thing <em>before</em> we call <code class="language-plaintext highlighter-rouge">savefig</code>:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">matplotlib</span> <span class="k">as</span> <span class="n">mpl</span>
<span class="n">mpl</span><span class="p">.</span><span class="n">rcParams</span><span class="p">[</span><span class="s">"svg.hashsalt"</span><span class="p">]</span> <span class="o">=</span> <span class="s">"42"</span>
</code></pre></div></div>

<p>Without fixing the hash salt, SVG generation is non-deterministic and <code class="language-plaintext highlighter-rouge">git</code> will (rightfully) detect the file as modified.</p>

<h2 id="avoiding-type-3-fonts">Avoiding Type 3 fonts</h2>

<p>This may not apply to all publishers, but at least USENIX and ACM papers require final PDFs to not have any <em>Type 3</em> fonts.
They just want <em>Type 1</em> fonts.
So, when we export our plots into PDF files and embed them into our LaTeX document, it’s better to make sure they don’t contain any Type 3 fonts in the first place.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">matplotlib</span> <span class="k">as</span> <span class="n">mpl</span>
<span class="n">mpl</span><span class="p">.</span><span class="n">rcParams</span><span class="p">[</span><span class="s">"pdf.fonttype"</span><span class="p">]</span> <span class="o">=</span> <span class="s">"42"</span>
<span class="n">mpl</span><span class="p">.</span><span class="n">rcParams</span><span class="p">[</span><span class="s">"ps.fonttype"</span><span class="p">]</span> <span class="o">=</span> <span class="s">"42"</span>
</code></pre></div></div>

<p>Unlike <code class="language-plaintext highlighter-rouge">svg.hashsalt</code> where 42 was just a random number, 42 for the font type actually means TrueType fonts.
The default is 3, which means Type 3 fonts.</p>

<h2 id="an-mplstyle-file">An <code class="language-plaintext highlighter-rouge">mplstyle</code> file</h2>

<p>You will definitely forget all of these next time.
Instead of trying to remember, put everything in a style file like this (call it something like <code class="language-plaintext highlighter-rouge">paper.mplstyle</code>):</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Fonts
font.size : 9

# SVG export now doesn't render font as path, but saves fonts as text objects.
# This allows for easier integration with MS Office.
svg.fonttype : none
# Make SVG generation deterministic
svg.hashsalt : 42

# Avoid type 3 font usage
pdf.fonttype : 42
ps.fonttype : 42
</code></pre></div></div>

<p>Then, import the file with a one-liner:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="n">plt</span>
<span class="n">plt</span><span class="p">.</span><span class="n">style</span><span class="p">.</span><span class="n">use</span><span class="p">(</span><span class="s">"./paper.mplstyle"</span><span class="p">)</span>
</code></pre></div></div>]]></content><author><name>Jae-Won Chung</name></author><category term="research" /><category term="technical" /><summary type="html"><![CDATA[All about reducing headaches and mistakes.]]></summary></entry><entry><title type="html">Structured Slacking</title><link href="https://jaewonchung.me/thoughts/Structured-Slacking/" rel="alternate" type="text/html" title="Structured Slacking" /><published>2023-12-12T00:00:00-05:00</published><updated>2023-12-12T00:00:00-05:00</updated><id>https://jaewonchung.me/thoughts/Structured-Slacking</id><content type="html" xml:base="https://jaewonchung.me/thoughts/Structured-Slacking/"><![CDATA[<p>Sometimes, when I start playing a YouTube video on one of my monitors, I magically start working on the other monitor without paying attention to the video.
Why do I do this?</p>

<p>I think it’s because it gives me a sense of scoring extra points in a game.
Alas, when I played the video I have decided to spend some time chilling instead of working, but if I actually make progress in work during that bulk of time that was anyway going to be wasted, I feel like going beyond a set goal.
And that feels good.</p>

<p>However, the YouTube trick is not always useful because I can’t really accomplish challenging tasks that require full focus with a YouTube video on.
That’s how I came to think of <em>Structured Slacking</em>, designed to exploit this fake sense of extra accomplishment.</p>

<p>It works like this.
Sometimes, you don’t want to do anything today.
Then think to yourself, “Okay, then let’s actually not do anything today. After all, I can use some rest from time to time. <strong>But</strong>, I’ll just do this very small thing today. It’s like an extra point I can score on a day off to feel good about myself.”
Then suddenly you’re motivated to do that small thing.
And once you get that started, you’ll probably continue working.
That said, it’s also important to set up that tiny task to be the tip of the iceberg of a bigger set of tasks.</p>

<p>As many would guess from the name, Structured Slacking was also inspired by <a href="https://structuredprocrastination.com/">Structured Procrastination</a>.
The two are similar in that both aim to enhance the productivity of an individual and operate on top of self-deception; Deep inside your heart you know Structured Slacking is bullshit, but you manage to trick yourself to almost believe that you will take today off, and you will actually stop working after accomplishing that small task.
The difference is that Structured Procrastination haunts you with a pending <em>important</em> task that you’re procrastinating, which is honestly not the best feeling.
On the other hand, with Structured Slacking, you’re pretty chill.
Of course you are – you’re taking the day off!</p>]]></content><author><name>Jae-Won Chung</name></author><category term="thoughts" /><summary type="html"><![CDATA[A simple trick to make yourself start working.]]></summary></entry><entry><title type="html">Using Microsoft python-type-stubs with Pyright</title><link href="https://jaewonchung.me/technical/Using-Microsoft-python-type-stubs-with-Pyright/" rel="alternate" type="text/html" title="Using Microsoft python-type-stubs with Pyright" /><published>2023-09-17T00:00:00-04:00</published><updated>2023-09-17T00:00:00-04:00</updated><id>https://jaewonchung.me/technical/Using-Microsoft-python-type-stubs-with-Pyright</id><content type="html" xml:base="https://jaewonchung.me/technical/Using-Microsoft-python-type-stubs-with-Pyright/"><![CDATA[<p>Python type annotations allow static type checking, so that you can catch obvious <code class="language-plaintext highlighter-rouge">AttributeError: NoneType object has no attribute ...</code> in your editor.
They also allow better code completion, because in many cases, type checking tools can infer the type of the object based on return type annotations of functions or methods.
However, not all libraries (especially the ones that were created before Python type annotation got established) have type annotations.</p>

<p>That’s why <em>type stubs</em> exist.
They have <code class="language-plaintext highlighter-rouge">.pyi</code> extensions and are like C headers, which only declare class, function, or method names and their parameter types without implementation.
These type stubs do not have to be coupled with the actual library.
So virtually anyone can just create type stubs for an existing library and ship it separately.</p>

<p>Microsoft’s <code class="language-plaintext highlighter-rouge">pylance</code> ships with type stubs bundled for popular libraries without native type annotations.
But especially for large libraries type stubs cannot be perfect, so they have a repository called <a href="https://github.com/microsoft/python-type-stubs"><code class="language-plaintext highlighter-rouge">python-type-stubs</code></a> to collaboratively work on creating type stubs together with the community, and these stubs are bundled together with <code class="language-plaintext highlighter-rouge">pylance</code>.</p>

<p>However, <code class="language-plaintext highlighter-rouge">pylance</code> is closed source, and is only available inside VS Code.
As a Neovim person, I instead have to use the open-source version of <code class="language-plaintext highlighter-rouge">pylance</code>, which is <a href="https://github.com/microsoft/pyright"><code class="language-plaintext highlighter-rouge">pyright</code></a>.
However, by default, <code class="language-plaintext highlighter-rouge">pyright</code> doesn’t ship with <code class="language-plaintext highlighter-rouge">pylance</code>’s type stubs.</p>

<p>So the question is, <strong>how do I use <code class="language-plaintext highlighter-rouge">python-type-stubs</code> with <code class="language-plaintext highlighter-rouge">pyright</code></strong>?
It’s actually simple enough, but at the time of writing, it seems like nowhere on the Internet just has a straightforward guide on this.</p>

<p>Say you have a Python project <code class="language-plaintext highlighter-rouge">proj</code> managed with <code class="language-plaintext highlighter-rouge">git</code>.</p>

<p>Add <code class="language-plaintext highlighter-rouge">python-type-stubs</code> as a git submodule under the directory <code class="language-plaintext highlighter-rouge">stubs</code>:</p>
<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span><span class="nb">cd </span>proj
<span class="gp">#</span><span class="w"> </span>Assuming you have GitHub SSH authentication <span class="nb">set </span>up.
<span class="gp">$</span><span class="w"> </span>git submodule add git@github.com:microsoft/python-type-stubs stubs
</code></pre></div></div>

<p>Then, point <code class="language-plaintext highlighter-rouge">pyright</code> to the stubs inside the submodule.</p>

<p>If you’re using <code class="language-plaintext highlighter-rouge">pyproject.toml</code>:</p>
<div class="language-toml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">[tool.pyright]</span>
<span class="py">stubPath</span> <span class="p">=</span> <span class="s">"./stubs/stubs"</span>
</code></pre></div></div>

<p>If you’re <em>not</em> using <code class="language-plaintext highlighter-rouge">pyproject.toml</code>, you need to have <code class="language-plaintext highlighter-rouge">pyrightconfig.json</code> in the root of your workspace:</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
    </span><span class="nl">"stubPath"</span><span class="p">:</span><span class="w"> </span><span class="s2">"./stubs/stubs"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>When you see glitches in the type stubs provided by <code class="language-plaintext highlighter-rouge">python-type-stubs</code>, just post a PR fixing the issue.
When the PR gets merged, update the submodule (e.g., <code class="language-plaintext highlighter-rouge">git submodule update</code>).</p>]]></content><author><name>Jae-Won Chung</name></author><category term="technical" /><summary type="html"><![CDATA[For better type checking and completion.]]></summary></entry><entry><title type="html">Advisors are like GPT</title><link href="https://jaewonchung.me/research/thoughts/Advisors-are-like-GPT/" rel="alternate" type="text/html" title="Advisors are like GPT" /><published>2023-05-11T00:00:00-04:00</published><updated>2023-05-11T00:00:00-04:00</updated><id>https://jaewonchung.me/research/thoughts/Advisors-are-like-GPT</id><content type="html" xml:base="https://jaewonchung.me/research/thoughts/Advisors-are-like-GPT/"><![CDATA[<p>I mean, my advisor is not a GPT model of course.
However, talking with my advisor is not like just talking to my friend or colleague.
Efficiently getting advice from him within bounded time requires a certain mental model of how he thinks and acts, and I realized that it’s sort of similar to prompting GPT models.</p>

<h2 id="gpt-is-stateless">GPT is Stateless</h2>

<p>GPT will remember the details of the conversation in the same thread, but that’s only because they cram in the entire conversation in their context window.
Outside that window, they are basically stateless; when you start a new conversation with GPT, it’ll have an empty context and won’t remember anything about your previous conversations.</p>

<p>Advisors are often also stateless.
Not that they’re stateless intentionally or by design, but due to the sheer amount of things going on around them, it’s more convenient for students to assume them to be stateless and forget everything.
It’s just like how you don’t ask ChatGPT, “Hey I think I asked you something about NP-Hardness in another thread last month, do you remember that?”</p>

<h2 id="context-is-important">Context is Important</h2>

<p>That’s why initializing GPT’s context right is important.
You would have experienced some conversations with ChatGPT where you screwed up the initial description of your problem, and it takes more words to correct ChatGPT’s understanding than what would have taken if you had described it right in the first place.
In such cases you can just mutter “Crap.” and click ‘New Chat’ (because ChatGPT is stateless).
However, unfortunately, that’s not so easy if you were talking to your advisor.
Therefore, I try to make sure my advisor’s context is initialized with a concise and accurate picture of where my research is.</p>

<p>I think this is especially observable when I sometimes hear contradicting advice from my advisor.
Not contradicting with my opinion, but with his own advice in the past.
That’s probably because the contexts I gave to my advisor that led to those contradictory advices were inconsistent in some way.
Therefore, usually my next action is to prompt my advisor further to find out if there are any misunderstandings, either in the previous meeting or this one.</p>

<h2 id="fine-tuning-gpt">Fine-Tuning GPT</h2>

<p>I’ve been saying all along that advisors are stateless, but we all know that they’re not completely stateless all the time.
So, I like to think that they take one fine-tuning step at the end of every meeting, and their learning rate depends on how interesting the meeting was (and also on other things that I can’t control).
If I excite my advisor with some interesting observation or good result, they’re more likely to remember.
Otherwise, they probably won’t remember what happened during the last meeting.</p>

<p>In that sense, I think it’s an effective strategy to present my advisor with a concise summary at the end of the meeting.
That way they don’t have to summarize the entire meeting on their own for fine-tuning, but rather just directly use the takeaway messages I present.
For that, I also try to set forth a couple TODO bullets that are rooted on the core takeaways of this meeting and roughly represent what my advisor can expect for the next meeting.</p>]]></content><author><name>Jae-Won Chung</name></author><category term="research" /><category term="thoughts" /><summary type="html"><![CDATA[There are some similarities in talking with my PhD advisor and prompting ChatGPT.]]></summary></entry><entry><title type="html">The Importance of Mentoring as a PhD Student</title><link href="https://jaewonchung.me/research/thoughts/The-Importance-of-Mentoring-as-a-PhD-Student/" rel="alternate" type="text/html" title="The Importance of Mentoring as a PhD Student" /><published>2022-10-11T00:00:00-04:00</published><updated>2022-10-11T00:00:00-04:00</updated><id>https://jaewonchung.me/research/thoughts/The-Importance-of-Mentoring-as-a-PhD-Student</id><content type="html" xml:base="https://jaewonchung.me/research/thoughts/The-Importance-of-Mentoring-as-a-PhD-Student/"><![CDATA[<p>Two months ago, I began mentoring a Master’s student who reached out to my advisor asking for collaboration opportunities.
I suggested an implementation project that aims to slightly expand the scope of my previous research work <a href="https://ml.energy/zeus">Zeus</a>, and the student decided to go for it.</p>

<p>As a mentor, my task was to collaboratively design solutions with my mentee, answer technical questions, provide feedback on design decisions and code, and figure out what pieces of knowledge the student was missing and either provide study material or come up with Google search keywords.
While I wasn’t doing any <em>actual</em> work, in that I wasn’t studying relevant technology or writing and testing code myself, the sequence of tasks was very difficult to perform satisfactorily because of the very fact that I wasn’t doing any actual work.
That is, without a complete picture of what’s going on, I was supposed to have better foresight than my mentee about what would happen if we were to proceed in a certain direction, or my mentee risked hitting a hard wall.
Eventually, when we officially merged the feature into Zeus, I felt very happy and proud that our collaboration worked out.</p>

<p>While the mentorship itself did not specifically push my ongoing research project forward, it indirectly helped with doing research, because I learned two important things from this experience.</p>

<p>First, I came to respect the weight of the advice my advisor gives me and understand the mental pressure of providing advice.
My mentee and I were simply developing a moderately-sized software feature, and I could reasonably predict what would happen along the way and what things would look like in the end.
Still, sometimes I wasn’t entirely sure about the advice I was giving to my mentee, but I anyway needed to at least <em>look</em> confident in order to give faith and motivation to my mentee.
Moreover, it was obvious that if I ended up pointing my mentee to a wrong path, my mentee would face frustration.</p>

<p>What makes it more difficult for my advisor is that we are doing research, which is inherently uncertain; you never know if the hole you’re digging is your grave.
Yet, PhD students expect their advisors to still provide advice that is roughly in the right direction.
I have come to understand that not even the best professors can know with confidence that the way the student is headed is a good direction, and how incredibly good my advisor is in that he usually provides advice that ends up being correct.</p>

<p>Second, mentoring helped me ask better questions to my advisor.
Recalling my mentoring experience, when my mentee asked for clarification about my suggestion, I sometimes failed to give good answers because I myself was operating based on logical guesses and inexplicable instincts.
I figured this would be the case for my advisor, too.
Thus, instead of interrogating my advisor with a bunch of why-questions, I started to instead ask questions such as “Is it because of A and B that you asked me to do X?”, essentially putting forth my guess of the reason behind his advice.
Then, my advisor would answer whether or not he agrees with what I said, or sometimes even make better suggestions when the guess I provided sparked something, and both cases led to highly productive conversations.</p>

<p>All in all, before this mentorship experience, my perception of mentoring was that it’s only good for me if it ends with some nice tangible outcome in a reasonable amount of time.
However, now I feel like the process of mentorship taught me a lot about the relationship between me and my advisor, and allowed me to improve the productivity of the meetings with my advisor.
Moreover, mentoring itself was an extremely rewarding process, where I could interact with enthusiastic junior researchers.</p>]]></content><author><name>Jae-Won Chung</name></author><category term="research" /><category term="thoughts" /><summary type="html"><![CDATA[While mentoring is not the primary task of a PhD student, it seems to help in doing research.]]></summary></entry><entry><title type="html">On Staying Confident</title><link href="https://jaewonchung.me/research/thoughts/On-Staying-Confident/" rel="alternate" type="text/html" title="On Staying Confident" /><published>2022-09-14T00:00:00-04:00</published><updated>2022-09-14T00:00:00-04:00</updated><id>https://jaewonchung.me/research/thoughts/On-Staying-Confident</id><content type="html" xml:base="https://jaewonchung.me/research/thoughts/On-Staying-Confident/"><![CDATA[<p>Last April, I submitted the manuscript of <a href="https://ml.energy/zeus">Zeus</a> to the Spring deadline of <a href="https://www.usenix.org/conference/nsdi23">NSDI</a>.
I was fairly confident about my research capability, since I managed to submit something that looks like a good paper by a very stringent deadline.</p>

<p>After a good three-week break, I came back to research in late May, exploring potential future directions.
I suggested some ideas and directions during meetings with my advisor, and basically everything was killed.
They were not just killed, but killed with very good reasons that seemed obvious in retrospect.
Quickly in several weeks, I started to feel very unconfident to the point where I was afraid to talk with my advisor, although I knew logically that killing bad ideas in early stages is only saving me time.</p>

<p>Then suddenly in mid-July, we were notified that Zeus was accepted to appear at NSDI.
My mood swung to the other end of confidence, especially because this was our first submission of the paper to any conference.
I began to prepare the camera-ready version, together with Zeus’s open source repository and homepage.
Finding new research directions was paused for a week or two, since we wanted Zeus to be posted on arXiv as soon as possible and have it collect citations from early on.</p>

<p>While polishing Zeus, I was thinking about what could be a follow-up work of it.
Then I came up with another idea, an idea I liked no less than all the dead ideas in June, and presented that to my advisor.
And he said it was very good.
Now I’m working on that idea, and just found last week that my hypothesis was true at least for a limited set of workloads, and the potential gains can be quite large.</p>

<p>Looking back starting from April, when I submitted Zeus to NSDI, me as a researcher did not change that much.
Most of the time I was on vacation, or was pouring time into polishing Zeus.
However, my level of confidence in terms of research capability fluctuated greatly, which didn’t make any sense.
If me in April and me today are similar researchers, there is no reason to be sometimes confident and sometimes not.
Rather, my confidence level should be determined by my best times, which is currently mid-July, when Zeus was accepted.
External factors, for example whether my ideas are well accepted by people, do not change my potential to do great work.</p>]]></content><author><name>Jae-Won Chung</name></author><category term="research" /><category term="thoughts" /><summary type="html"><![CDATA[Why am I sometimes confident and sometimes not?]]></summary></entry><entry><title type="html">Appending the PhD Mindset</title><link href="https://jaewonchung.me/research/thoughts/Appending-the-PhD-Mindset/" rel="alternate" type="text/html" title="Appending the PhD Mindset" /><published>2022-05-12T00:00:00-04:00</published><updated>2022-05-12T00:00:00-04:00</updated><id>https://jaewonchung.me/research/thoughts/Appending-the-PhD-Mindset</id><content type="html" xml:base="https://jaewonchung.me/research/thoughts/Appending-the-PhD-Mindset/"><![CDATA[<p>Say that your coworker makes this statement:</p>

<blockquote>
  <p>The pizza served at Mani’s is literally the best in the world. They’re so good.</p>
</blockquote>

<p>What is the most appropriate answer?</p>

<ol>
  <li>Hmm, how do you quantify the goodness of a restaurant? Is Google Maps stars a sufficient metric?</li>
  <li>No, “good” does not mean “the best”. You should always think about the exact meaning of words when you speak.</li>
  <li>You can’t just make such a statement. Do you have an argument to back that?</li>
  <li>Lol yeah.</li>
</ol>

<p>After spending half a year as a PhD student, I start to understand when people say:</p>

<blockquote>
  <p>Getting a PhD is not about acquiring a set of technical skills, but rather a specific mindset.</p>
</blockquote>

<p>I suppose there are many elements that consist such a mindset, including but not limited to:</p>
<ul>
  <li>Excavating meaningful problems to solve and navigating the uncertain process of solving it (#1 above).</li>
  <li>Communicating facts and arguments in precise language (#2 above).</li>
  <li>Maintaining a critical view of relevant matter and accepting arguments after rigorous reasoning and observation (#3 above).</li>
</ul>

<p>I believe many will agree that none of these are neither easy nor quick to acquire.
One must imbue oneself with principles and constantly self-reflect and self-correct.
However, I think one should go one step further.
One should make a conscious effort so that no existing mindset is completely replaced by the PhD mindset; the PhD mindset must only <em>append</em> to the list of existing mindsets.
Then, one must distinguish situations when it is more appropriate to apply the PhD mindset and when it is not in a fine-grained manner.</p>

<p>Life, at least partly, can be viewed as a multi-task learning problem.
While acquiring new capabilities is important, one must make sure not to <a href="https://en.wikipedia.org/wiki/Catastrophic_interference">catastrophically forget</a> other important things in the process, which may not always be easy especially when the new capability requires an immense amount of concentrated effort to learn.
However, I believe that such an effort is meaningful in advancing one’s maturity as a person.</p>]]></content><author><name>Jae-Won Chung</name></author><category term="research" /><category term="thoughts" /><summary type="html"><![CDATA[I heard that getting a PhD is about obtaining a certain mindset. Yet, the mindset should append, not replace.]]></summary></entry></feed>