<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<author><name>Daniel Liden</name></author>
<title>Daniel Liden's Blog</title>
<description>Data, AI, and other writing from Daniel Liden</description>
<generator>Emacs webfeeder.el</generator>
<link>https://danliden.com</link>
<atom:link href="https://danliden.com/rss.xml" rel="self" type="application/rss+xml"/>
<lastBuildDate>Fri, 17 Jul 2026 21:21:51 +0000</lastBuildDate>
<item>
  <title>Allow, ask, deny: contextual policies in Omnigent</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Allow, ask, deny: contextual policies in Omnigent</h1>
 <p class="subtitle" role="doc-subtitle">July 15, 2026</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#org68eb7d7">Example 1: Ask Before File and Shell Operations</a></li>
 <li> <a href="#org1477960">Example 2: A Custom Policy in Python</a></li>
 <li> <a href="#org2d101c4">Example 3: An Inline Policy in CEL</a></li>
 <li> <a href="#org1cd3a10">Conclusion</a></li>
</ul></div>
</nav> <div class="preview" id="org4925d27">
 <p>
If you've worked with coding agents before, you've seen them pause and ask before editing files or reading the contents of certain directories. In Omnigent, these events are governed by  <i>policies</i>. A  <a href="https://omnigent.ai/docs/policies/overview">policy</a> is a rule that runs at specified points in a session, such as when the user sends a request to the agent, when the agent replies, or when the agent attempts to use a tool, and returns one of three decisions.
</p>

</div>

 <ul class="org-ul"> <li> <code>ALLOW</code>: let the action proceed</li>
 <li> <code>ASK</code>: pause and ask the user to approve or reject it</li>
 <li> <code>DENY</code>: block the action</li>
</ul> <p>
Suppose, for example, an agent is about to use a web fetch tool on a certain site. A policy might check if that site is on an allowed list of domains before allowing the tool call to proceed.
</p>

 <p>
Omnigent policies are  <i>contextual</i>. Each policy maintains its own state throughout a session and can make decisions based on prior events and information from the whole session. For instance, a policy might block certain actions if personally identifiable information (PII) has been introduced to the chat at some point, but permit them otherwise. Or a policy might restrict access to expensive models after a session passes a set budget threshold.
</p>

 <p>
The best way to learn how policies work is to try a few of them out. Omnigent has a selection of built-in policies and lets you define your own custom policies. We'll explore both usage patterns. Policies can apply to a single session, to an agent, or across the whole server; see  <a href="https://omnigent.ai/docs/policies/overview#adding-a-policy">adding a policy</a>. By the end of this post you should understand what a policy is and how to think about implementing policies in your projects. This post is not comprehensive: consult the documentation for specific guidance on creating your own policies.
</p>

 <div id="outline-container-org68eb7d7" class="outline-2">
 <h2 id="org68eb7d7">Example 1: Ask Before File and Shell Operations</h2>
 <div class="outline-text-2" id="text-org68eb7d7">
 <p>
Suppose we want our agent to help with local development, but do not want it running shell commands or editing files without explicit permission. There is a built-in policy we can add to ask the user for approval before allowing the agent to execute any file or shell operations.
</p>

 <p>
You can add the policy to your current session from the Omnigent web app or desktop app by selecting the info button (ⓘ) in the top-right corner, clicking  <code>+</code> next to  <code>policies</code>, and selecting "Require Approval for File & Shell Operations."
</p>


 <figure id="orge96d065"> <img src="./figures/20260715-omnigent-policies/1_add_policy_dialog.png" alt="Omnigent 'Add Policy' dialog listing policies including 'Require Approval for File & Shell Operations'"></img> <figcaption> <span class="figure-number">Figure 1: </span>The Add Policy dialog, with "Require Approval for File & Shell Operations" in the list</figcaption></figure> <p>
You can also simply ask the agent to add the policy to your session—Omnigent supplies coding agents with the tools they need to add policies themselves.
</p>

 <p>
Now, whenever the agent attempts a file or shell operation, it will first ask the user for permission.
</p>


 <figure id="org14e7a0c"> <img src="./figures/20260715-omnigent-policies/2_file_write_ask.png" alt="Omnigent showing an 'Approval required' panel before a Write(test.txt) call, with Approve and Reject buttons"></img> <figcaption> <span class="figure-number">Figure 2: </span>Omnigent pausing for approval before a file write, with Approve and Reject buttons</figcaption></figure></div>
</div>

 <div id="outline-container-org1477960" class="outline-2">
 <h2 id="org1477960">Example 2: A Custom Policy in Python</h2>
 <div class="outline-text-2" id="text-org1477960">
 <p>
You may want to implement a policy over actions or session states that are not covered by built-in policies. Maybe you want to limit the use of a specific tool, or block an action once sensitive data has entered the session. With Omnigent, you can define  <a href="https://omnigent.ai/docs/policies/custom">custom policies</a> to meet your specific needs.
</p>

 <p>
Fundamentally, a custom policy is a Python function that receives a  <code>PolicyEvent</code> and returns a  <code>PolicyResponse</code> ( <code>ALLOW</code>,  <code>ASK</code>, or  <code>DENY</code>).
</p>

 <p>
A  <code>PolicyEvent</code> describes something that just happened or is about to happen, such as a message arriving, the agent about to call a tool, a tool returning a result, or the agent about to reply. In our Python code, we can match on  <code>event["type"]</code> to pick out the event we care about, and read  <code>event["session_state"]</code> to see what has already happened this session. The example below gives the agent a budget of free shell calls, then asks for approval on every one after that.
</p>

 <div class="org-src-container">
 <pre class="src src-python"> <span class="org-keyword">from</span> omnigent.policies.schema  <span class="org-keyword">import</span> PolicyEvent, PolicyResponse

 <span class="org-variable-name">FREE_SHELL_CALLS</span>  <span class="org-operator">=</span> 3

 <span class="org-keyword">def</span>  <span class="org-function-name">budget_shell_calls</span>(event: PolicyEvent)  <span class="org-operator">-></span> PolicyResponse  <span class="org-operator">|</span>  <span class="org-constant">None</span>:
     <span class="org-keyword">if</span> event.get( <span class="org-string">"type"</span>)  <span class="org-operator">!=</span>  <span class="org-string">"tool_call"</span>:
         <span class="org-keyword">return</span>  <span class="org-constant">None</span>
     <span class="org-keyword">if</span> (event.get( <span class="org-string">"data"</span>)  <span class="org-keyword">or</span> {}).get( <span class="org-string">"name"</span>)  <span class="org-operator">!=</span>  <span class="org-string">"sys_os_shell"</span>:
         <span class="org-keyword">return</span>  <span class="org-constant">None</span>

     <span class="org-variable-name">used</span>  <span class="org-operator">=</span> (event.get( <span class="org-string">"session_state"</span>)  <span class="org-keyword">or</span> {}).get( <span class="org-string">"shell_calls_used"</span>, 0)
     <span class="org-keyword">if</span> used  <span class="org-operator">>=</span> FREE_SHELL_CALLS:
         <span class="org-keyword">return</span> {
             <span class="org-string">"result"</span>:  <span class="org-string">"ASK"</span>,
             <span class="org-string">"reason"</span>: f <span class="org-string">"That's shell call #</span>{used  <span class="org-operator">+</span> 1} <span class="org-string"> this session — approve it?"</span>,
        }

     <span class="org-keyword">return</span> {
         <span class="org-string">"result"</span>:  <span class="org-string">"ALLOW"</span>,
         <span class="org-string">"state_updates"</span>: [
            { <span class="org-string">"key"</span>:  <span class="org-string">"shell_calls_used"</span>,  <span class="org-string">"action"</span>:  <span class="org-string">"increment"</span>,  <span class="org-string">"value"</span>: 1}
        ],
    }
</pre>
</div>

 <p>
This policy is  <i>stateful</i>. It reads a counter out of  <code>event["session_state"]</code> and returns a  <code>state_updates</code> list to bump that counter each time it allows a call. Omnigent persists the counter across the session, so the same  <code>echo</code> command is allowed the first three times and paused the fourth—nothing changed but the history. See  <a href="https://www.databricks.com/blog/contextual-policies-omnigent-using-session-state-better-govern-ai-agents">Contextual Policies in Omnigent</a> for deeper examples, like a running cost total.
</p>

 <p>
You can attach this custom policy directly to your  <a href="https://omnigent.ai/docs/use/custom-agents">agent config</a>, the YAML file  <code>omni run</code> reads:
</p>

 <div class="org-src-container">
 <pre class="src src-yaml">guardrails:
  policies:
    budget_shell_calls:
      type: function
      on: [tool_call]
      function:
        path: myorg_policies.budget_shell_calls
</pre>
</div>

 <p>
To use the policy, save the function in a file next to the agent config. Stop the running server if you have one, then start the agent:
</p>

 <div class="org-src-container">
 <pre class="src src-bash">omni stop
omni run agent.yaml
</pre>
</div>

 <p>
Run this from the directory where both files are located.  <code>omni run</code> resolves your module against the directory you launch from.
</p>


 <figure id="org7f5b39c"> <img src="./figures/20260715-omnigent-policies/3_shell_budget_ask.png" alt="Omnigent budget_shell_calls policy pausing for approval on the fourth shell call, 'echo 4', with Approve/Reject"></img> <figcaption> <span class="figure-number">Figure 3: </span>The budget policy pausing for approval on the fourth shell call</figcaption></figure> <p>
You can also register it on the server, which makes it selectable from the UI for everyone on that server. Add your module to the  <code>policy_modules:</code> list in the server config and export a  <code>POLICY_REGISTRY</code> list from it; the server scans that list at startup. See the  <a href="https://omnigent.ai/docs/policies/custom#2-register-on-the-server">docs</a> for the entry format.
</p>
</div>
</div>

 <div id="outline-container-org2d101c4" class="outline-2">
 <h2 id="org2d101c4">Example 3: An Inline Policy in CEL</h2>
 <div class="outline-text-2" id="text-org2d101c4">
 <p>
Not every policy needs a Python file. For simple, stateless checks you can write the whole policy as a single  <a href="https://cel.dev/overview/cel-overview">Common Expression Language (CEL)</a> expression, right in the agent config. Here's a policy that denies any shell command containing  <code>rm -rf</code>:
</p>

 <div class="org-src-container">
 <pre class="src src-yaml">guardrails:
  policies:
    block_rm_rf:
      type: function
      on: [tool_call]
      function:
        path: omnigent.policies.builtins.cel.cel_policy
        arguments:
          expression: >-
            event.type == "tool_call" && event.target == "sys_os_shell"
              && event.data.arguments.command.contains("rm -rf")
              ? {"result": "DENY", "reason": "Recursive delete is blocked."}
              : {"result": "ALLOW"}
</pre>
</div>

 <p>
Only  <code>sys_os_shell</code> calls get checked: the tool-name test comes first, so calls to other tools—which have no  <code>command</code> field to read—pass through without erroring. And unlike the Python policy above, a CEL policy is just an expression with nothing to load, so the agent can add one to a live session immediately, no restart needed.
</p>


 <figure id="orgb45a409"> <img src="./figures/20260715-omnigent-policies/4_rm_rf_deny.png" alt="Omnigent chat: 'echo hi' succeeds but 'rm -rf' is denied with 'Denied by policy: Recursive delete is blocked'"></img> <figcaption> <span class="figure-number">Figure 4: </span>The custom policy denying an rm -rf shell command with "Denied by policy: Recursive delete is blocked."</figcaption></figure></div>
</div>

 <div id="outline-container-org1cd3a10" class="outline-2">
 <h2 id="org1cd3a10">Conclusion</h2>
 <div class="outline-text-2" id="text-org1cd3a10">
 <p>
Policies look at distinct events, and optionally at tracked state, and return  <code>ALLOW</code>,  <code>ASK</code>, or  <code>DENY</code>. Omnigent ships with built-in policies for common needs like safety and cost control, and you can write your own for boundaries specific to your tools, data, and risk tolerance.
</p>

 <p>
Try it yourself: add one to a live session and watch what happens when it's triggered. Next, think about what actions you don't want your agents to take unsupervised, and make it  <code>ASK</code> first.
</p>
</div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20260715-omnigent-policies.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20260715-omnigent-policies.html</guid>
  <pubDate>Wed, 15 Jul 2026 08:00:00 +0000</pubDate>
</item>
<item>
  <title>Harness Engineering</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Harness Engineering</h1>
 <p class="subtitle" role="doc-subtitle">February 28, 2026</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#org228b874">Introduction</a></li>
 <li> <a href="#orga67ea85">A simple harness</a>
 <ul> <li> <a href="#org62b1b7e">The core loop</a></li>
 <li> <a href="#org123c3da">The execution log</a></li>
 <li> <a href="#org066de46">Build the context</a></li>
 <li> <a href="#orgc641cd3">Add tool call support</a></li>
 <li> <a href="#org2e2f1c9">LLM Support</a></li>
 <li> <a href="#orge3d08a0">Observability</a></li>
 <li> <a href="#org03041af">Big picture</a></li>
</ul></li>
 <li> <a href="#orgbd77b43">What's next</a></li>
 <li> <a href="#org879da74">Takeaways</a></li>
</ul></div>
</nav> <div class="preview" id="orgc0b7452">
 <p>
In the first couple of years of LLMs, we talked a lot about "prompt engineering": how to craft a  <i>prompt</i> just so in order to induce the LLM to do what we want. Since then, we've moved on to the more expansive "context engineering": how multiple available sources of context (chat history, file reads, web search results, etc.) should be combined to induce an agent to do what we want. Here, I'm writing about the even-more-expansive notion of "harness engineering": how do we orchestrate the whole loop of LLM invocations, tool calls, background process management, context retrieval, permission asks, etc., to get the agent to do what we want?
</p>

</div>

 <div id="outline-container-org228b874" class="outline-2">
 <h2 id="org228b874">Introduction</h2>
 <div class="outline-text-2" id="text-org228b874">
 <p>
I have been using Claude Code and OpenAI Codex for months now. The underlying models clearly drive much of the effectiveness of these tools—the  <a href="https://wtfhappened2025.com/">much commented-on</a> jumps in performance over the past few months are clear demonstrations of the centrality of model performance.
</p>

 <p>
But models frequently leapfrog each other in terms of performance (real or perceived). A new model comes out and tops leaderboards and benchmarks—but many developers tend to stick to, or adopt, a harness that enforces use of what might be considered a "lesser" model (though, at this point, we're splitting hairs. The top models are all incredibly capable).
</p>

 <p>
Right now, Claude Opus 4.6, GPT Codex 5.3, and Gemini 3.1 Pro are vying for the top positions on the  <a href="https://www.tbench.ai/leaderboard/terminal-bench/2.0">terminal bench 2 benchmark</a>, with some variations depending on the harnesses in which they are running.
</p>


 <figure id="orgc4e5eb2"> <img src="./figures/20260228-harness-engineering/terminal-bench-leaderboard.png" alt="Terminal-Bench leaderboard table; Droid/GPT-5.3-Codex ranks #1 at 77.3%, Claude Opus 4.6 at #4"></img> <figcaption> <span class="figure-number">Figure 1: </span>Terminal-Bench leaderboard (February 2026). GPT-5.3-Codex holds the top spot; Claude Opus 4.6 slots in at #4—separated by a few percentage points from the leader.</figcaption></figure> <p>
Even though Codex 5.3 currently hold the top slot, the Claude Code coding agent harness is much more popular than the OpenAI harness. Compare their npm downloads, for example—an incomplete, but directionally correct datapoint.
</p>


 <figure id="org62ba835"> <img src="./figures/20260228-harness-engineering/cc_codex_npm.png" alt="Line chart of npm downloads: Claude Code climbs to ~32M vs Codex ~6M over the past year"></img> <figcaption> <span class="figure-number">Figure 2: </span>npm downloads for @anthropic-ai/claude-code vs. @openai/codex. Claude Code's ~32M downloads are more than 5× Codex's ~6M.</figcaption></figure> <p>
All of this is to say: the harness is crucially important. The harness is more responsible for the user's experience of working with a given coding agent than the underlying intelligence is. It's  <i>also</i> much easier to modify and customize than the underlying model. More on that later. First: what is an agent harness?
</p>

 <p>
In most of the articles I've read, the term "harness" is used but not defined. I use it very broadly. The harness is the loop in which the LLM is invoked and in which it interacts with user(s) and/or its environment.
</p>

 <p>
A single API call to an LLM does not involve a harness, in this formulation. But even a simple chat loop constitutes a harness. Other features of a harness might include:
</p>
 <ul class="org-ul"> <li>tool calling (bash execution, web search, web fetch, etc.)</li>
 <li>context management (compaction, clearing, summarization, checkpointing, knowledge/discovery of tools, skills, etc.)</li>
 <li>instrumentation/observability (capturing traces, running automated evaluations)</li>
 <li>subprocess management: for when an agent launches long-running processes like web servers or subagents</li>
</ul> <p>
You probably aren't in a position to build your own Claude Opus model. But you  <i>can</i> build your own harness. If nothing else, it will help you to understand what is possible and how much control you have over your agentic coding environment. Claude Code is great. I'm almost certainly going to keep using it. But having your own agent harness gives a great platform for experimenting with different patterns of context handling, tool use—all the stuff that isn't the underlying intelligence.
</p>

 <p>
In the rest of this post, we'll make a simple extensible harness. This will be the foundation for some future experiments I have planned. More on that later.
</p>
</div>
</div>
 <div id="outline-container-orga67ea85" class="outline-2">
 <h2 id="orga67ea85">A simple harness</h2>
 <div class="outline-text-2" id="text-orga67ea85">
 <p>
My goal here was to build a very simple but extensible agent harness. I started by sketching out what this means:
</p>

 <ol class="org-ol"> <li>Simple control flow: it's just a loop.</li>
 <li>Everything (human input, tool calls, tool responses, agent responses) is an explicit, understandable event</li>
 <li>Simple defaults. I'm not doing anything clever at this phase.</li>
 <li>Provider agnostic—don't anchor to a specific model/provider.</li>
 <li>Observability is built in but non-blocking</li>
</ol> <p>
The goals, at this phase, are interpretability and transparency. Optimization and experimentation will come later.
</p>

 <div class="note" id="orgeb1aae4">
 <p>
I'm not going to show much in the way of code. Poke around  <a href="https://github.com/djliden/context-harness">here</a> if you're interested. I heavily used Claude Code and Codex to write the code (though this agent harness itself, powered by gemini-3-flash, contributed a little bit at the end!). So I'm focusing more on the high-level organization and the things I'm trying to accomplish.
</p>

 <p>
I'm new to this! I'm used to writing technical articles with a lot of code. I'd love to hear your thoughts on what worked and what didn't in this format. I don't think anyone has the answer to the question of what makes good technical writing in the age of agentic coding.
</p>

</div>
</div>


 <div id="outline-container-org62b1b7e" class="outline-3">
 <h3 id="org62b1b7e">The core loop</h3>
 <div class="outline-text-3" id="text-org62b1b7e">
 <p>
The  <code>ChatLoop</code> class is where everything happens. At its core, it's just a for loop. The user's message goes in; context is assembled from the chat history; the model is called; tools are executed if there were tool calls; tool results are returned to the model. Once there is a text result with no tool calls, that result is returned to the user. You can find the class  <a href="https://github.com/djliden/context-harness/commit/eef51a8eccc1f7fbb1c57ca37d08572cfa5a1bc8#diff-4dffee8972ca12234622b36061093a0d0beed07e5ba0a507907ec84707325ab8R14">here</a>. 
</p>
</div>
</div>
 <div id="outline-container-org123c3da" class="outline-3">
 <h3 id="org123c3da">The execution log</h3>
 <div class="outline-text-3" id="text-org123c3da">
 <p>
I wanted a durable "source of truth" event log. For this simple initial version, I opted for an append-only in-memory event log defined in the  <code>EventLog</code> class ( <a href="https://github.com/djliden/context-harness/commit/eef51a8eccc1f7fbb1c57ca37d08572cfa5a1bc8#diff-64a8fc12530c0d0b6ef710971e6d6fed48b333fe1b100b72b7e0f02ba3c29c3fR35">link</a>). Each event—user messages, model calls, errors, etc.—is logged. This  <code>EventLog</code> is used to construct the context at each turn and to simplify debugging.
</p>
</div>
</div>
 <div id="outline-container-org066de46" class="outline-3">
 <h3 id="org066de46">Build the context</h3>
 <div class="outline-text-3" id="text-org066de46">
 <p>
One of the things I really want to explore about agent harnesses is the way context is constructed and sent to the model. In this case, context assembly is, intentionally, very simple: include everything, with no pruning or compaction. We can experiment more with this later ( <a href="https://github.com/djliden/context-harness/commit/eef51a8eccc1f7fbb1c57ca37d08572cfa5a1bc8#diff-08ef332ff6f7d48abb605e670b4f550c07d70b86022f86e34151c99722edc76cR37">link</a>).
</p>
</div>
</div>
 <div id="outline-container-orgc641cd3" class="outline-3">
 <h3 id="orgc641cd3">Add tool call support</h3>
 <div class="outline-text-3" id="text-orgc641cd3">
 <p>
Tools have a very minimal protocol:  <code>name</code>,  <code>description</code>,  <code>parameters</code>, and async  <code>execute()</code>. Then I added three tools that cover a pretty substantial proportion of what we ask agents to do:  <code>bash</code>,  <code>web_search</code>,  <code>web_fetch</code>.
</p>

 <p>
Again, no magic: a tool call was just structured input, a function execution, and a structured result logged back into the loop.
</p>
</div>
</div>
 <div id="outline-container-org2e2f1c9" class="outline-3">
 <h3 id="org2e2f1c9">LLM Support</h3>
 <div class="outline-text-3" id="text-org2e2f1c9">
 <p>
Of course, the core of any agent is the intelligence powering it. I wanted this system to be model agnostic from the start. As we saw above, the "best model" for the job changes constantly.
</p>

 <p>
I used the  <a href="https://www.litellm.ai/">LiteLLM</a> library to make this agent loop provider agnostic. Provider support is handled by the  <code>LiteLLMAdapter</code> class ( <a href="https://github.com/djliden/context-harness/commit/eef51a8eccc1f7fbb1c57ca37d08572cfa5a1bc8#diff-e6cb1529cf9b6a2fbf7de1ec96a54b35d5323e364de163515cd2a08d42fd888eR21">link</a>). This is the only part of the code that should ever need to be concerned with the responses that come from particular providers. The rest of the harness only needs to worry about uniformly-formatted context, tool call and message formats, and the formatted usage record.
</p>
</div>
</div>
 <div id="outline-container-orge3d08a0" class="outline-3">
 <h3 id="orge3d08a0">Observability</h3>
 <div class="outline-text-3" id="text-orge3d08a0">
 <p>
Finally, I wired in tracing ( <code>TraceLogger</code> + MLflow autologging) and usage logging. Importantly, this component will issue a warning without blocking the agent if there are e.g. errors with the tracking server.
</p>

 <p>
Observability is important and I wanted to add it from the start. It should help me improve the system over time, but it should never become a runtime dependency for core behavior.
</p>

 <div class="tip" id="org67367c5">
 <p>
MLflow recently added the ability to group traces into  <b>sessions</b> so you can evaluate the quality of entire conversations, not just inputs and outputs.
</p>


 <figure id="orge2dd54e"> <img src="./figures/20260228-harness-engineering/mlflow-sessions.png" alt="MLflow session view for context-harness: turns 1-9 sidebar, token and latency metrics, bash tool-call trace"></img> <figcaption> <span class="figure-number">Figure 3: </span>MLflow session view for the context-harness project, showing all turns of a conversation grouped into a single session with aggregate token and latency metrics.</figcaption></figure></div>
</div>
</div>

 <div id="outline-container-org03041af" class="outline-3">
 <h3 id="org03041af">Big picture</h3>
 <div class="outline-text-3" id="text-org03041af">
 <p>
The result of all this is simple on purpose. At its core, the harness is a loop, a log, and a few translation layers. An "agent harness" is not some mystical thing. Especially with the help of  <i>other</i> agent harnesses, you can build one in an afternoon.
</p>
</div>
</div>
</div>

 <div id="outline-container-orgbd77b43" class="outline-2">
 <h2 id="orgbd77b43">What's next</h2>
 <div class="outline-text-2" id="text-orgbd77b43">
 <p>
This harness is enough of a foundation to start running some experiments on. We have the core loop. It's modular and customizable. The results are all traced in MLflow.
</p>
</div>
</div>
 <div id="outline-container-org879da74" class="outline-2">
 <h2 id="org879da74">Takeaways</h2>
 <div class="outline-text-2" id="text-org879da74">
 <p>
You might feel like this post was a little thin. And you'd be right to feel that way. That's the point. Working with the major coding agents today can feel like petitioning a genie for help and hoping that its mystical machinations return what you need. What I hope I communicated is that agent harnesses can be very simple.
</p>

 <p>
From here, we'll be doing some more experiments with features we can layer into our agent harness. I suspect, for example, that there are far better ways to handle context; that chat transcripts are extremely poor in terms of useful information density when working toward specific outcomes. I'll write about that, and some early experiments, next time.
</p>
</div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20260228-harness-engineering.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20260228-harness-engineering.html</guid>
  <pubDate>Sat, 28 Feb 2026 08:00:00 +0000</pubDate>
</item>
<item>
  <title>Saving and Restoring Window Configurations in Emacs</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Saving and Restoring Window Configurations in Emacs</h1>
 <p class="subtitle" role="doc-subtitle">November 22, 2025</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#org9489e25">The Problem</a></li>
 <li> <a href="#orgffdc4af">Window Registers</a></li>
 <li> <a href="#orgc9a9053">Persisting across Sessions</a></li>
 <li> <a href="#org81336f8">Try out window registers</a></li>
</ul></div>
</nav> <div class="preview" id="org82402e2">
 <p>
When working in emacs, I often switch between different combinations of windows with different splits. For example, I might have one configuration with an org mode buffer with some notes alongside org-agenda, and another with a Python source file and a Python REPL. Before, I was switching between them by changing buffers and splits each time, which was cumbersome. Registers make it much simpler, and  <code>desktop-save-mode</code> lets you persist window configurations across sessions.
</p>

</div>

 <div class="note" id="orgeb8fcaa">
 <p>
The definition of a "window" in emacs is not the same as a window in a graphical desktop environment. A  <i>window</i> in emacs is a part of a  <i>frame</i> that can display a  <i>buffer</i>. One  <i>frame</i> (closer to the desktop environment usage of "window") can display multiple  <i>windows</i> at once, by splitting the frame into sections.
</p>

 <p>
For more, read  <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Basic-Windows.html">Basic Concepts of Emacs Windows</a>.
</p>

</div>

 <div id="outline-container-org9489e25" class="outline-2">
 <h2 id="org9489e25">The Problem</h2>
 <div class="outline-text-2" id="text-org9489e25">
 <p>
Suppose I have the following window configurations open. When I say "window configuration," I mean "a set of visible windows in a particular arrangement."
</p>

 <ol class="org-ol"> <li> <p>
My  <code>init.el</code> file along with a docs page on  <code>desktop-save-mode</code>.
</p>


 <figure id="org67a3f0d"> <img src="./figures/20251122-emacs-window-configs/1_init_desktop_config.png" alt="Emacs frame split in two: init.el config on the left, desktop-save-mode help docs on the right"></img> <figcaption> <span class="figure-number">Figure 1: </span>My init.el next to the desktop-save-mode docs</figcaption></figure></li>

 <li> <p>
The org file for the blog I am working on now, a scratch buffer, and my blog's build script.
</p>


 <figure id="orgd7bb76d"> <img src="./figures/20251122-emacs-window-configs/2_blog_scratch_build_config.png" alt="Emacs frame: blog post Org draft on the left; build-site.el over an empty scratch buffer on the right"></img> <figcaption> <span class="figure-number">Figure 2: </span>Blog post on the left, scratch buffer and build script on the right</figcaption></figure></li>
</ol> <p>
Naively navigating from (1) to (2) requires changing the leftmost buffer to my blog draft, splitting the buffer on the right, and switching the two windows on the right to the scratch and build script buffers. Switching back requires deleting on of the windows on the right and navigating back to the original two buffers.
</p>

 <p>
This is a pain.
</p>
</div>
</div>
 <div id="outline-container-orgffdc4af" class="outline-2">
 <h2 id="orgffdc4af">Window Registers</h2>
 <div class="outline-text-2" id="text-orgffdc4af">
 <p>
I previously wrote about  <a href="https://www.danliden.com/notes/20250308-registers-1.html">navigating between points with registers</a>. You can register a point with  <code><C-x r SPC></code> and then return to it with  <code><C-x r j></code>.
</p>

 <p>
You can also register  <i>window configurations</i>. The process is essentially the same.
</p>

 <ol class="org-ol"> <li>Call  <code>window-configuration-to-register</code> with  <code><C-x r w></code>.</li>
 <li> <p>
Select a register. Any single character (including non-alphanumeric characters such as emojis) can be used to set a register. So e.g.  <code><C-x r w a></code> will save the window configuration to register  <code>a</code>.  <code><C-x r w 1></code> will save it to register  <code>1</code>. You can read more about registers  <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Registers.html">here</a>.
</p>


 <figure id="orgb67c47c"> <img src="./figures/20251122-emacs-window-configs/3_save_window_config.png" alt="Emacs Register Preview list with minibuffer prompt 'Window configuration to register: a'"></img> <figcaption> <span class="figure-number">Figure 3: </span>Saving the current setup to a register</figcaption></figure></li>

 <li> <p>
Navigate away from your saved window configuration. When you want to get back to it, you can do so with  <code><C-x r j></code> and then select the register you want to return to from the  <code>*Register Preview*</code> menu.
</p>


 <figure id="org4516deb"> <img src="./figures/20251122-emacs-window-configs/4_restore_window_config.png" alt="Emacs Register Preview listing saved window configurations with minibuffer prompt 'Jump to register: a'"></img> <figcaption> <span class="figure-number">Figure 4: </span>Jumping back to a saved configuration from the Register Preview menu</figcaption></figure> <p>
This will immediately return you to the window configuration you saved above.
</p></li>
</ol> <p>
Once we register a couple of different window configurations, it becomes very easy to swap between them!
</p>


 <figure id="orgaf2ab6e"> <img src="./figures/20251122-emacs-window-configs/5_switching_configs.gif" alt="Animated demo of swapping between saved Emacs window configurations via registers"></img> <figcaption> <span class="figure-number">Figure 5: </span>Swapping between saved configurations</figcaption></figure></div>
</div>
 <div id="outline-container-orgc9a9053" class="outline-2">
 <h2 id="orgc9a9053">Persisting across Sessions</h2>
 <div class="outline-text-2" id="text-orgc9a9053">
 <p>
Registers do not persist across emacs sessions—when you restart emacs, your registers are gone.
</p>

 <p>
One approach to persisting the state of emacs across sessions is with  <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Saving-Emacs-Sessions.html#Saving-Emacs-Sessions">desktop-save-mode</a>, which saves a  <code>.emacs.desktop</code> file to your  <code>user-emacs-directory</code> (or whatever other location you specify), and then reads from this file when emacs is restarted or when you manually call  <code>desktop-read</code>.
</p>

 <p>
In my limited testing, this approach is imperfect. Some buffers are not restored, and window registers seem to be saved in a corrupted and unusable form (even though  <code>register-alist</code> is part of the  <code>desktop-globals-to-save</code> list, which specifies what is preserved across sessions).
</p>


 <figure id="org4b89dad"> <img src="./figures/20251122-emacs-window-configs/6_corrupted_registers.png" alt="Emacs Register Preview showing window-config registers restored as 'rectangle starting with Unprintable entity'"></img> <figcaption> <span class="figure-number">Figure 6: </span>The saved window registers look a bit mangled</figcaption></figure> <p>
Still, it's better than nothing? I'm sure there are other solutions out there.
</p>

 <p>
For me, this is not much of a problem. I don't often exit emacs.
</p>
</div>
</div>
 <div id="outline-container-org81336f8" class="outline-2">
 <h2 id="org81336f8">Try out window registers</h2>
 <div class="outline-text-2" id="text-org81336f8">
 <p>
It's simple:
</p>

 <ol class="org-ol"> <li> <code><C-x r w></code> and then select the register (any single character)</li>
 <li>Navigate away from your present window configuration</li>
 <li> <p>
 <code><C-x r j></code>, choose the register to which you saved your configuration in (1)
</p>

 <p>
And you're back where you started!
</p></li>
</ol></div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20251122-emacs-window-configs.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20251122-emacs-window-configs.html</guid>
  <pubDate>Sat, 22 Nov 2025 08:00:00 +0000</pubDate>
</item>
<item>
  <title>Using MLflow&apos;s MCP Server for Conversational Trace Analysis</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Using MLflow's MCP Server for Conversational Trace Analysis</h1>
 <p class="subtitle" role="doc-subtitle">October 1, 2025</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#orgb4314cc">Introduction: MCP Server for MLflow Traces</a></li>
 <li> <a href="#org14e3ddc">MLflow Tracing Setup</a>
 <ul> <li> <a href="#org8a88909">Setting up MLflow</a></li>
 <li> <a href="#org3a225c4">Generating some Trace Data to Explore</a></li>
</ul></li>
 <li> <a href="#org41e1928">Using the MLflow MCP Server</a>
 <ul> <li> <a href="#orga3d4923">Claude Desktop</a></li>
 <li> <a href="#orgf49ce01">Claude Code</a></li>
</ul></li>
 <li> <a href="#org75086d8">Next Steps and Observations</a></li>
</ul></div>
</nav> <div class="preview" id="org41f43a5">
 <p>
MLflow 3.4 introduced an official MCP server that lets AI assistants like Claude interact directly with your MLflow traces. This post explores how to set it up when MLflow is installed in a virtual environment, and demonstrates practical usage with both Claude Desktop and Claude Code for debugging and analyzing GenAI application traces.
</p>

</div>

 <div id="outline-container-orgb4314cc" class="outline-2">
 <h2 id="orgb4314cc">Introduction: MCP Server for MLflow Traces</h2>
 <div class="outline-text-2" id="text-orgb4314cc">
 <p>
 <a href="https://mlflow.org/docs/latest/genai/tracing/">MLflow tracing</a> is a powerful AI observability tool that enables you to capture all of the inputs, outputs, and metadata associated with every step of an AI model or Agent execution chain. It works with many different providers, such as OpenAI, Anthropic, LangChain, and LlamaIndex via a single line of code. Tracing provides granular insight into the entire execution chain of AI applications, including tool calls, retrievals, AI responses, any anything else you might want to include.
</p>


 <figure id="orgf501008"> <img src="./figures/20251001-mlflow-mcp/1_trace.png" alt="MLflow UI trace detail with nested spans summarize_content, scrape_webpage, and Completions plus chat messages"></img> <figcaption> <span class="figure-number">Figure 1: </span>Example MLflow trace showing nested spans in the MLflow UI</figcaption></figure> <p>
But capturing the traces is just the first step: once we have all of the trace data, we need to  <i>use</i> it to make our AI applications better. In addition to its existing sophisticated  <a href="https://mlflow.org/docs/latest/genai/eval-monitor/">evaluation</a> functionality, which enables us to add human, AI, and programmatic assessments to traces, MLflow 3.4 introduced an  <a href="https://mlflow.org/docs/latest/genai/mcp/">MLflow MCP server</a> to give AI applications like Claude Desktop and code assistants like Cursor the ability to interact with traces.
</p>

 <div class="note" id="org872d457">
 <p>
If you're just learning about MCP servers for the first time, take a look at my Getting Started with Model Context Protocol posts:  <a href="https://www.danliden.com/posts/20250412-mcp-quickstart.html">part 1</a>,  <a href="https://www.danliden.com/posts/20250921-mcp-prompts-resources.html">part 2</a>.
</p>

</div>

 <p>
The MCP server lets these tools search and analyze trace data, log feedback, manage metadata, and delete traces and assessments.
</p>

 <p>
In the remainder of this post, we will see how to configure and use the MCP server.
</p>
</div>
</div>

 <div id="outline-container-org14e3ddc" class="outline-2">
 <h2 id="org14e3ddc">MLflow Tracing Setup</h2>
 <div class="outline-text-2" id="text-org14e3ddc">
</div>
 <div id="outline-container-org8a88909" class="outline-3">
 <h3 id="org8a88909">Setting up MLflow</h3>
 <div class="outline-text-3" id="text-org8a88909">
 <p>
In this example, we will install MLflow with the  <a href="https://astral.sh/blog/uv">uv</a> package manager. We will install it locally, in a virtual environment, and then use the MCP server to search and analyze traces saved to our local MLflow server.
</p>

 <p>
First, create a new directory for this example and install MLflow. We will also install a few additional project dependencies.
</p>

 <div class="org-src-container">
 <pre class="src src-bash">uv add mlflow openai beautifulsoup4 requests python-dotenv  <span class="org-string">'click>=7.0,<8.3.0'</span>
</pre>
</div>

 <div class="warning" id="org2ee95d3">
 <p>
Currently, the MLflow MCP server does not work correctly with  <code>click</code> version 8.3.0, so we need to manually specify a different version to use. This is a  <a href="https://github.com/mlflow/mlflow/pull/17821">known issue</a> and will be resolved in a future MLflow release.
</p>

</div>

 <p>
We will be querying OpenAI models to create some example trace data, so we need to make sure the OpenAI client can access our OpenAI API key. To do so, create a file called  <code>.env</code> with the following:
</p>

 <div class="org-src-container">
 <pre class="src src-:name">#.env
OPENAI_API_KEY=<your_openai_key>
</pre>
</div>

 <p>
Now you can start the MLflow tracking server and access the UI, where we will view our traces, with  <code>mlflow ui</code>. You can learn more about configuring the MLflow tracking server  <a href="https://mlflow.org/docs/latest/ml/tracking/server/">here</a>.
</p>
</div>
</div>
 <div id="outline-container-org3a225c4" class="outline-3">
 <h3 id="org3a225c4">Generating some Trace Data to Explore</h3>
 <div class="outline-text-3" id="text-org3a225c4">
 <div class="tip" id="orgeea9204">
 <p>
If you already have trace data you want to explore, you can skip this section!
</p>

</div>

 <p>
In order to demonstrate how the MLflow MCP server lets AI tools work with trace data, we first need to create some trace data. We will create three different example traces: one where a simple query to an OpenAI model fails, one where it succeeds, and one that includes an additional step: retrieving text from a web page.
</p>

 <p>
First, let's import our dependencies and handle a few other setup steps:
</p>

 <div class="org-src-container">
 <pre class="src src-python"> <span class="org-keyword">import</span> mlflow
 <span class="org-keyword">from</span> openai  <span class="org-keyword">import</span> OpenAI
 <span class="org-keyword">import</span> requests
 <span class="org-keyword">from</span> bs4  <span class="org-keyword">import</span> BeautifulSoup
 <span class="org-keyword">import</span> os
 <span class="org-keyword">from</span> dotenv  <span class="org-keyword">import</span> load_dotenv

 <span class="org-comment-delimiter"># </span> <span class="org-comment">Load environment variables
</span>load_dotenv()

 <span class="org-comment-delimiter"># </span> <span class="org-comment">Set up an MLflow experiment
</span> <span class="org-variable-name">experiment_name</span>  <span class="org-operator">=</span>  <span class="org-string">"mcp-server-demo"</span>
mlflow.set_experiment(experiment_name)

 <span class="org-comment-delimiter"># </span> <span class="org-comment">Enable OpenAI autologging to capture traces
</span>mlflow.openai.autolog()

 <span class="org-comment-delimiter"># </span> <span class="org-comment">Initialize OpenAI client
</span> <span class="org-variable-name">client</span>  <span class="org-operator">=</span> OpenAI(api_key <span class="org-operator">=</span>os.getenv( <span class="org-string">"OPENAI_API_KEY"</span>))
</pre>
</div>

 <p>
Running the code block above will create a new MLflow experiment called  <code>mcp-server-demo</code> where our traces will be logged. It also loads the OpenAI API key from the  <code>.env</code> file we created earlier and sets up the OpenAI client. We're now ready to query OpenAI models and log some traces!
</p>

 <p>
 <b>Example trace 1: Failed API Call</b>
</p>

 <p>
MLflow tracing captures detailed error information that can be very useful for debugging AI application failures. Here, we'll attempt to call an OpenAI model that does not exist, resulting in an error:
</p>

 <div class="org-src-container">
 <pre class="src src-python"> <span class="org-variable-name">response</span>  <span class="org-operator">=</span> client.chat.completions.create(
    model <span class="org-operator">=</span> <span class="org-string">"gpt-nonexistent-model"</span>,   <span class="org-comment-delimiter"># </span> <span class="org-comment">Invalid model name
</span>    messages <span class="org-operator">=</span>[{ <span class="org-string">"role"</span>:  <span class="org-string">"user"</span>,  <span class="org-string">"content"</span>:  <span class="org-string">"Hello, world!"</span>}],
    max_tokens <span class="org-operator">=</span>50
)
</pre>
</div>

 <p>
 <b>Example trace 2: Simple successful API call</b>
</p>

 <p>
Our second example will similarly be a single call to an OpenAI model—this time, to a model that actually exists.
</p>

 <div class="org-src-container">
 <pre class="src src-python"> <span class="org-variable-name">response</span>  <span class="org-operator">=</span> client.chat.completions.create(
    model <span class="org-operator">=</span> <span class="org-string">"gpt-5"</span>,
    messages <span class="org-operator">=</span>[{ <span class="org-string">"role"</span>:  <span class="org-string">"user"</span>,  <span class="org-string">"content"</span>:  <span class="org-string">"Explain what MLflow is in one sentence."</span>}]
)
</pre>
</div>

 <p>
 <b>Example trace 3: multi-step retrieval process</b>
</p>

 <p>
Our third example is more substantial. We will create a small script defining a workflow that extracts the text from a webpage and passes it to GPT-5 for summarization. We use the  <code>@mlflow.trace()</code> decorator to manually trace the webpage scraping function, and we wrap the whole process in a parent span so the traces for both the web scraping and the OpenAI completion are captured under one parent span.
</p>

 <div class="org-src-container">
 <pre class="src src-python"> <span class="org-type">@mlflow.trace</span>(name <span class="org-operator">=</span> <span class="org-string">"scrape_webpage"</span>, span_type <span class="org-operator">=</span> <span class="org-string">"RETRIEVER"</span>)
 <span class="org-keyword">def</span>  <span class="org-function-name">scrape_webpage</span>(url:  <span class="org-builtin">str</span>)  <span class="org-operator">-></span>  <span class="org-builtin">dict</span>:
     <span class="org-doc">"""Scrape content from a webpage - creates a nested span."""</span>
     <span class="org-variable-name">response</span>  <span class="org-operator">=</span> requests.get(url, timeout <span class="org-operator">=</span>10)
    response.raise_for_status()
    
     <span class="org-variable-name">soup</span>  <span class="org-operator">=</span> BeautifulSoup(response.content,  <span class="org-string">'html.parser'</span>)
    
     <span class="org-comment-delimiter"># </span> <span class="org-comment">Extract title and paragraphs
</span>     <span class="org-variable-name">title</span>  <span class="org-operator">=</span> soup.find( <span class="org-string">'title'</span>)
     <span class="org-variable-name">title_text</span>  <span class="org-operator">=</span> title.get_text().strip()  <span class="org-keyword">if</span> title  <span class="org-keyword">else</span>  <span class="org-string">"No title found"</span>
    
     <span class="org-variable-name">paragraphs</span>  <span class="org-operator">=</span> soup.find_all( <span class="org-string">'p'</span>)
     <span class="org-variable-name">content</span>  <span class="org-operator">=</span>  <span class="org-string">' '</span>.join([p.get_text().strip()  <span class="org-keyword">for</span> p  <span class="org-keyword">in</span> paragraphs[:5]])   <span class="org-comment-delimiter"># </span> <span class="org-comment">First 5 paragraphs
</span>    
     <span class="org-keyword">return</span> {
         <span class="org-string">"title"</span>: title_text,
         <span class="org-string">"content"</span>: content[:1000],   <span class="org-comment-delimiter"># </span> <span class="org-comment">Limit content length
</span>         <span class="org-string">"url"</span>: url,
         <span class="org-string">"status_code"</span>: response.status_code
    }

 <span class="org-keyword">def</span>  <span class="org-function-name">summarize_content</span>(content:  <span class="org-builtin">str</span>)  <span class="org-operator">-></span>  <span class="org-builtin">str</span>:
     <span class="org-doc">"""Summarize content using OpenAI - creates nested span within main trace."""</span>
     <span class="org-variable-name">prompt</span>  <span class="org-operator">=</span> f <span class="org-string">"Summarize the following content:</span> <span class="org-constant">\n\n</span>{content} <span class="org-string">"</span>
    
     <span class="org-comment-delimiter"># </span> <span class="org-comment">This OpenAI call will be automatically traced due to autologging
</span>     <span class="org-variable-name">response</span>  <span class="org-operator">=</span> client.chat.completions.create(
        model <span class="org-operator">=</span> <span class="org-string">"gpt-5"</span>,
        messages <span class="org-operator">=</span>[{ <span class="org-string">"role"</span>:  <span class="org-string">"user"</span>,  <span class="org-string">"content"</span>: prompt}],
    )
    
     <span class="org-keyword">return</span> response.choices[0].message.content

 <span class="org-keyword">def</span>  <span class="org-function-name">multi_step_retrieval_process</span>(url:  <span class="org-builtin">str</span>)  <span class="org-operator">-></span>  <span class="org-builtin">dict</span>:
     <span class="org-doc">"""Complete retrieval and summarization pipeline with nested spans."""</span>

     <span class="org-keyword">with</span> mlflow.start_span(name <span class="org-operator">=</span> <span class="org-string">"summarize_content"</span>, span_type <span class="org-operator">=</span> <span class="org-string">"CHAIN"</span>)  <span class="org-keyword">as</span> parent_span:
        parent_span.set_inputs(url)
         <span class="org-variable-name">scraped_data</span>  <span class="org-operator">=</span> scrape_webpage(url)
         <span class="org-variable-name">summary</span>  <span class="org-operator">=</span> summarize_content(scraped_data[ <span class="org-string">"content"</span>])
        parent_span.set_outputs(summary)
    
     <span class="org-keyword">return</span> {
         <span class="org-string">"url"</span>: url,
         <span class="org-string">"title"</span>: scraped_data[ <span class="org-string">"title"</span>],
         <span class="org-string">"content_length"</span>:  <span class="org-builtin">len</span>(scraped_data[ <span class="org-string">"content"</span>]),
         <span class="org-string">"summary"</span>: summary
    }
</pre>
</div>

 <p>
Now let's invoke this retrieval and summarization workflow:
</p>

 <div class="org-src-container">
 <pre class="src src-python"> <span class="org-variable-name">url</span>  <span class="org-operator">=</span>  <span class="org-string">"https://mlflow.org/docs/latest/genai/mcp/"</span>
 <span class="org-variable-name">result</span>  <span class="org-operator">=</span> multi_step_retrieval_process(url)

 <span class="org-comment-delimiter"># </span> <span class="org-comment">Print experiment ID for use with Claude
</span> <span class="org-variable-name">experiment</span>  <span class="org-operator">=</span> mlflow.get_experiment_by_name(experiment_name)
 <span class="org-builtin">print</span>(f <span class="org-string">"</span> <span class="org-constant">\n</span> <span class="org-string">Successfully generated traces in experiment: </span>{experiment.name} <span class="org-string">"</span>)
 <span class="org-builtin">print</span>(f <span class="org-string">"Use this Experiment ID with Claude: </span>{experiment.experiment_id} <span class="org-string">"</span>)
</pre>
</div>

 <p>
Save all the Python code from this section into a file (e.g.,  <code>generate_traces.py</code>) and run it with  <code>uv run python generate_traces.py</code>, or run the code cells in a Jupyter notebook. The script will print your experiment ID, which you'll need for the Claude examples below.
</p>
</div>
</div>
</div>

 <div id="outline-container-org41e1928" class="outline-2">
 <h2 id="org41e1928">Using the MLflow MCP Server</h2>
 <div class="outline-text-2" id="text-org41e1928">
 <p>
Now that we have set up MLflow and generated some sample traces, let's explore them with the help of AI models! We will show how to do this with with Claude Desktop and Claude Code.
</p>
</div>
 <div id="outline-container-orga3d4923" class="outline-3">
 <h3 id="orga3d4923">Claude Desktop</h3>
 <div class="outline-text-3" id="text-orga3d4923">
 <p>
You can connect the MLflow MCP server with Claude Desktop as follows:
</p>

 <ol class="org-ol"> <li> <b> <a href="https://claude.ai/download">Download and install the Claude Desktop app</a></b></li>
 <li> <p>
From the  <b>Settings</b> menu, click  <b>Developer</b> and then  <b>Edit Config</b>:
</p>


 <figure id="org4ad47d9"> <img src="./figures/20251001-mlflow-mcp/2_claude_settings.png" alt="Claude Desktop Developer settings Local MCP servers pane with the Edit Config button highlighted"></img> <figcaption> <span class="figure-number">Figure 2: </span>Claude Desktop settings showing the Developer menu</figcaption></figure> <p>
This will open a directory with various Claude application and configuration files. Open (or create) the one called  <code>claude_desktop_config.json</code>.
</p></li>
 <li> <p>
 <b>Copy the following</b> into  <code>claude_desktop_config.json</code>,  replacing the project directory and tracking uri with those corresponding to your project:
</p>

 <div class="org-src-container">
 <pre class="src src-json">{
    "mcpServers": {
        "mlflow-mcp": {
            "command": "uv",
            "args": ["run", "--directory", "<path-to-your-project-directory>",
                     "mlflow", "mcp", "run"],
            "env": {
                "MLFLOW_TRACKING_URI": "http://127.0.0.1:5000"
            }
        }
    }
}
</pre>
</div>

 <div class="caution" id="org798e74c">
 <p>
If the MCP server fails to connect, you may need to use the full path to the  <code>uv</code> executable instead of just  <code>"uv"</code> for the  <code>command</code> value. The conditions when this is necessary vary by system configuration. To find the full path, run  <code>which uv</code> in your terminal (e.g.,  <code>/Users/username/.cargo/bin/uv</code>).
</p>

</div>

 <p>
There are a few things here worth calling out, including some key differences from the configuration in the  <a href="https://mlflow.org/docs/latest/genai/mcp/">official docs</a>:
</p>
 <ul class="org-ul"> <li>Because we installed MLflow in a virtual environment with  <code>uv</code>, we need to make sure to call the MLflow MCP server using the correct MLflow installation. We use the  <code>--directory</code> flag to specify that  <code>uv</code> should run the  <code>mlflow</code> executable installed to the virtual environment in our project directory. If you have MLflow installed globally, you can refer to the configuration in the  <a href="https://mlflow.org/docs/latest/genai/mcp/#set-up">official docs</a> instead.</li>
 <li>If your MLflow tracking URI is running on a non-default host/port, you will need to change the  <code>MLFLOW_TRACKING_URI</code> value.</li>
</ul></li>
 <li> <p>
 <b>Restart Claude Desktop.</b> After restarting, you should see that  <code>mlflow-mcp</code> appears in the Claude Desktop connections menu:
</p>


 <figure id="orgfd498a9"> <img src="./figures/20251001-mlflow-mcp/3_claude_connections.png" alt="Claude Desktop connections menu with the mlflow-mcp server toggled on and highlighted"></img> <figcaption> <span class="figure-number">Figure 3: </span>MLflow MCP server appearing in Claude Desktop connections</figcaption></figure></li>
 <li> <p>
 <b>Try it out!</b>
</p>

 <p>
Let's ask Claude to identify and diagnose traces with errors.
</p>

 <div class="tip" id="org5df49ce">
 <p>
When asking Claude to work with traces, you will need to specify your experiment ID. Claude cannot infer the experiment ID. If you ran the trace generation code above, the experiment ID was printed to the console. You can also find it in the MLflow UI by navigating to the  <code>experiments</code> tab, clicking the experiment to which you logged your traces, and then clicking the information icon (an  <code>i</code> in a circle) next to the experiment name. Alternatively, you can add an  <code>MLFLOW_EXPERIMENT_ID</code> environment variable to the MCP server configuration to specify a default experiment.
</p>

</div>

 <p>
I asked the following:
</p>

 <blockquote>
 <p>
Please analyze and diagnose the most recent trace that resulted in an error in experiment 697822894089422973.
</p>
</blockquote>

 <p>
Claude called the  <code>Search traces</code> and  <code>get trace</code> functions to identify the relevant trace, and then responded with a diagnosis of the issue and suggested next steps:
</p>


 <figure id="org7a173e3"> <img src="./figures/20251001-mlflow-mcp/4_claude_result.png" alt="Claude Desktop diagnosing a failed trace, explaining the gpt-nonexistent-model 404 error with recommended fixes"></img> <figcaption> <span class="figure-number">Figure 4: </span>Claude Desktop analyzing a failed trace and providing diagnostic information</figcaption></figure></li>
</ol></div>
</div>
 <div id="outline-container-orgf49ce01" class="outline-3">
 <h3 id="orgf49ce01">Claude Code</h3>
 <div class="outline-text-3" id="text-orgf49ce01">
 <p>
Configuring the MLflow MCP server to work with Claude Code is almost identical to configuring it for Claude Desktop. We just need to add the JSON configuration to a different file ( <code>.mcp.json</code> in your project root directory). You can follow these steps to get started:
</p>
 <ol class="org-ol"> <li> <b> <a href="https://www.claude.com/product/claude-code">Install Claude Code</a></b></li>
 <li> <p>
 <b>Copy the configuration JSON snippet</b> from the prior section into  <code>.mcp.json</code> in your project's root directory, creating the file if necessary.
</p>

 <div class="tip" id="org940262c">
 <p>
This is one of several different ways to add MCP servers to Claude Code. See the  <a href="https://docs.claude.com/en/docs/claude-code/mcp">Claude Code docs</a> for more options.
</p>

</div></li>
 <li> <b>Run Claude Code</b> by calling  <code>claude</code> from your project's root directory.</li>
 <li> <p>
 <b>Try it out!</b> Let's ask Claude to find the trace with a retrieval step and assess whether it worked.
</p>

 <blockquote>
 <p>
Look at the traces in experiment 697822894089422973. Find the most recent one that had a retrieval component and tell me what was retrieved and whether the retrieval was successful.
</p>
</blockquote>


 <figure id="org7acc59d"> <img src="./figures/20251001-mlflow-mcp/5_claude_code_result.png" alt="Claude Code terminal calling mlflow-mcp search_traces and reporting a successful webpage retrieval from a trace"></img> <figcaption> <span class="figure-number">Figure 5: </span>Claude Code analyzing a trace with retrieval and reporting results</figcaption></figure> <p>
Claude code was able to identify the relevant trace and answer the question using the tools available through the MCP server.
</p></li>
</ol></div>
</div>
</div>

 <div id="outline-container-org75086d8" class="outline-2">
 <h2 id="org75086d8">Next Steps and Observations</h2>
 <div class="outline-text-2" id="text-org75086d8">
 <p>
There's something satisfying about using AI to debug AI. The MLflow MCP server closes the loop between capturing traces and actually using them: your AI assistant can now help you understand why your other AI assistant failed.
</p>

 <p>
The  <a href="https://mlflow.org/docs/latest/genai/mcp/#use-cases-and-examples">MLflow docs</a> suggest some use cases, but the real value comes from exploring your own patterns:
</p>
 <ul class="org-ul"> <li>Ask Claude to compare successful vs. failed traces to identify common failure modes</li>
 <li>Have it search for traces with specific token usage patterns when you're trying to optimize costs</li>
 <li>Use it to find traces where retrieval returned irrelevant content, then iterate on your chunking strategy</li>
 <li>Let it spot when certain model configurations consistently produce better results</li>
 <li>Give Claude Code access to both your agent code and its traces so it can review failures, suggest fixes, and help you iterate without leaving your editor</li>
</ul> <p>
The setup takes five minutes, but once configured, your trace data becomes something you can have a conversation with instead of handcrafting search queries or digging through the UI.
</p>
</div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20251001-mlflow-mcp-server.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20251001-mlflow-mcp-server.html</guid>
  <pubDate>Wed, 01 Oct 2025 08:00:00 +0000</pubDate>
</item>
<item>
  <title>Getting Started with Model Context Protocol Part 2: Prompts and Resources</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Getting Started with Model Context Protocol Part 2: Prompts and Resources</h1>
 <p class="subtitle" role="doc-subtitle">September 21, 2025</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#orgc5a9c7e">Review of Part 1</a></li>
 <li> <a href="#org9547638">Resources: Expose data to your LLMs</a>
 <ul> <li> <a href="#orgcbdd68b">Accessing Resource with Claude Desktop</a></li>
</ul></li>
 <li> <a href="#org3f96f4e">Prompts: Reusable prompt templates</a>
 <ul> <li> <a href="#org33824f7">Using prompts with Claude Desktop</a></li>
</ul></li>
 <li> <a href="#org019cca7">Conclusion, Observations, and Next Steps</a></li>
</ul></div>
</nav> <div class="preview" id="orge5b22c0">
 <p>
In the first part of this series on Anthropic's Model Context Protocol, I showed how to define a very simple MCP server with one tool and install it to Claude Desktop. In this post, we will look at two more MCP concepts and learn how to use them:  <b>resources</b>, which expose data and other content to models, and  <b>prompts</b>, which are intended to allow users to select reusable prompt templates suited for certain tasks or workflows.
</p>

</div>
 <div id="outline-container-orgc5a9c7e" class="outline-2">
 <h2 id="orgc5a9c7e">Review of Part 1</h2>
 <div class="outline-text-2" id="text-orgc5a9c7e">
 <p>
In the  <a href="https://www.danliden.com/posts/20250412-mcp-quickstart.html">first post</a> in this series, we learned (1) what an MCP server is, (2) how to define a simple MCP server with a single tool, and (3) how to install that server to Claude Desktop. Let's briefly recap these points.
</p>

 <ol class="org-ol"> <li>MCP servers provide a standardized interface to resources (such as databases, file systems, tools, etc.) that LLMs can access. An MCP  <i>client</i> corresponding to that server facilitates requests to the server, receives responses, and relays them to the host or user. MCP clients and servers are usually used in the context of a  <i>host</i> application such as an IDE or chat app; the host is what the end user typically interacts with.</li>
 <li> <p>
The following code snippet defines an MCP server that exposes a single tool.
</p>

 <div class="org-src-container">
 <pre class="src src-python"> <span class="org-comment-delimiter"># </span> <span class="org-comment">server.py
</span>
 <span class="org-comment-delimiter"># </span> <span class="org-comment">install the mcp sdk with pip install "mcp[cli]"
</span> <span class="org-keyword">from</span> mcp.server.fastmcp  <span class="org-keyword">import</span> FastMCP

 <span class="org-variable-name">mcp</span>  <span class="org-operator">=</span> FastMCP( <span class="org-string">"SecretServer"</span>)

 <span class="org-type">@mcp.tool</span>()
 <span class="org-keyword">def</span>  <span class="org-function-name">get_secret_number</span>()  <span class="org-operator">-></span>  <span class="org-builtin">int</span>:
     <span class="org-doc">"""Returns a predefined secret number."""</span>
     <span class="org-keyword">return</span> 13
</pre>
</div>

 <p>
The tool,  <code>get_secret_number</code>, just returns a "secret number." If you ask an LLM with access to this MCP server for the secret number, it should invoke this function in order to retrieve it.
</p></li>
 <li>We installed the server to Claude Desktop with  <code>mcp install server.py</code>.</li>
</ol> <p>
This was an example of defining and using a  <a href="https://modelcontextprotocol.io/docs/concepts/tools">tool</a> with MCP. In this post, we will learn about other MCP primitives allowing the MCP server to expose data and enable specific workflows.
</p>
</div>
</div>
 <div id="outline-container-org9547638" class="outline-2">
 <h2 id="org9547638">Resources: Expose data to your LLMs</h2>
 <div class="outline-text-2" id="text-org9547638">
 <p>
 <i>Resources</i> provide a way to give your LLMs access to data. The data can include database records, file contents, API responses, images, and more. Getting data from a resource in an MCP server is like making an HTTP GET request. The expectation is that it will return data without any side effects.
</p>

 <p>
In fact, the secret number method we defined previously would be a perfect candidate for a resource. It returns  <b>data</b> and does nothing else. Let's show how to define an equivalent resource, this time to return a secret letter.
</p>

 <p>
We can expand our MCP server with this new resource as follows:
</p>

 <div class="tip" id="org5d41d93">
 <p>
Refer to the  <a href="https://www.danliden.com/posts/20250412-mcp-quickstart.html#setup">Setup section of the previous post</a> for details on setting up your project. We will be testing our MCP server with Claude Desktop.
</p>

</div>


 <div class="org-src-container">
 <pre class="src src-python"> <span class="org-comment-delimiter"># </span> <span class="org-comment">server.py
</span>
 <span class="org-comment-delimiter"># </span> <span class="org-comment">install the mcp sdk with pip install "mcp[cli]"
</span> <span class="org-keyword">from</span> mcp.server.fastmcp  <span class="org-keyword">import</span> FastMCP

 <span class="org-variable-name">mcp</span>  <span class="org-operator">=</span> FastMCP( <span class="org-string">"SecretServer"</span>)

 <span class="org-type">@mcp.tool</span>()
 <span class="org-keyword">def</span>  <span class="org-function-name">get_secret_number</span>()  <span class="org-operator">-></span>  <span class="org-builtin">int</span>:
     <span class="org-doc">"""Returns a predefined secret number."""</span>
     <span class="org-keyword">return</span> 13

 <span class="org-type">@mcp.resource</span>( <span class="org-string">"data://secret_letter"</span>)
 <span class="org-keyword">def</span>  <span class="org-function-name">get_secret_letter</span>()  <span class="org-operator">-></span>  <span class="org-builtin">str</span>:
     <span class="org-doc">"""Returns a predefined secret letter."""</span>
     <span class="org-keyword">return</span>  <span class="org-string">"L"</span>
</pre>
</div>


 <p>
The  <code>@mcp.resource</code> decorator takes the resource's unique URI as an argument. Clients use this URI to request data.
</p>
</div>
 <div id="outline-container-orgcbdd68b" class="outline-3">
 <h3 id="orgcbdd68b">Accessing Resource with Claude Desktop</h3>
 <div class="outline-text-3" id="text-orgcbdd68b">
 <p>
We have a couple of different options for how to give Claude Desktop access to these resources. First, we can directly attach it to a chat message via the  <code>+</code> menu, where we can select  <code>add from SecretServer</code> (the name of our server). This will essentially attach the resource as a document Claude can refer to.
</p>


 <figure id="orgdf3066b"> <img src="./figures/20250921-mcp-2/1_attach_resource.png" alt="Claude Desktop with the get_secret_letter resource attached as a TXT file; Claude answers the secret letter is L"></img></figure> <p>
We can also define a  <i>tool</i> that claude can use to access the  <i>resource</i>. Let's update our server code to see this option.
</p>


 <div class="org-src-container">
 <pre class="src src-python"> <span class="org-comment-delimiter"># </span> <span class="org-comment">server.py
</span>
 <span class="org-keyword">from</span> mcp.server.fastmcp  <span class="org-keyword">import</span> FastMCP, Context

 <span class="org-variable-name">mcp</span>  <span class="org-operator">=</span> FastMCP( <span class="org-string">"SecretServer"</span>)

 <span class="org-type">@mcp.tool</span>()
 <span class="org-keyword">def</span>  <span class="org-function-name">get_secret_number</span>()  <span class="org-operator">-></span>  <span class="org-builtin">int</span>:
     <span class="org-doc">"""Returns a predefined secret number."""</span>
     <span class="org-keyword">return</span> 13

 <span class="org-type">@mcp.resource</span>( <span class="org-string">"data://secret_letter"</span>)
 <span class="org-keyword">def</span>  <span class="org-function-name">get_secret_letter</span>()  <span class="org-operator">-></span>  <span class="org-builtin">str</span>:
     <span class="org-doc">"""Returns a predefined secret letter."""</span>
     <span class="org-keyword">return</span>  <span class="org-string">"L"</span>

 <span class="org-type">@mcp.tool</span>()
 <span class="org-keyword">async def</span>  <span class="org-function-name">retrieve_secret_letter_tool</span>(ctx: Context)  <span class="org-operator">-></span>  <span class="org-builtin">str</span>:
     <span class="org-doc">"""Tool to retrieve the secret letter from the corresponding resource"""</span>
     <span class="org-variable-name">resources</span>  <span class="org-operator">=</span>  <span class="org-keyword">await</span> ctx.read_resource( <span class="org-string">"data://secret_letter"</span>)
     <span class="org-keyword">return</span> resources[0].content
</pre>
</div>

 <p>
Now, if we re-install the server with  <code>mcp install server.py</code>, Claude will be able to invoke this tool to access the secret letter resource, even if we have not explicitly added the resource to the chat.
</p>


 <figure id="org5fec31d"> <img src="./figures/20250921-mcp-2/2_secret_letter_via_tool.png" alt="Claude Desktop showing the Retrieve secret letter tool's request and response returning L"></img></figure> <p>
For a more in-depth guide on using resources, check out the  <a href="https://gofastmcp.com/servers/resources">FastMCP</a> docs. I recommend reading the section on how to  <a href="https://gofastmcp.com/servers/resources#resource-templates">parameterize resources</a> next.
</p>
</div>
</div>
</div>
 <div id="outline-container-org3f96f4e" class="outline-2">
 <h2 id="org3f96f4e">Prompts: Reusable prompt templates</h2>
 <div class="outline-text-2" id="text-org3f96f4e">
 <p>
MCP prompts let you set up parameterized prompt templates. Just like with tools and resources, we use the  <code>@mcp.prompt()</code> decorator to define prompts with the Python SDK. Let's update our server with a simple prompt that can generate a haiku on a topic.
</p>

 <div class="org-src-container">
 <pre class="src src-python"> <span class="org-comment-delimiter"># </span> <span class="org-comment">server.py
</span>
 <span class="org-keyword">from</span> mcp.server.fastmcp  <span class="org-keyword">import</span> FastMCP, Context

 <span class="org-variable-name">mcp</span>  <span class="org-operator">=</span> FastMCP( <span class="org-string">"SecretServer"</span>)

 <span class="org-type">@mcp.tool</span>()
 <span class="org-keyword">def</span>  <span class="org-function-name">get_secret_number</span>()  <span class="org-operator">-></span>  <span class="org-builtin">int</span>:
     <span class="org-doc">"""Returns a predefined secret number."""</span>
     <span class="org-keyword">return</span> 13

 <span class="org-type">@mcp.resource</span>( <span class="org-string">"data://secret_letter"</span>)
 <span class="org-keyword">def</span>  <span class="org-function-name">get_secret_letter</span>()  <span class="org-operator">-></span>  <span class="org-builtin">str</span>:
     <span class="org-doc">"""Returns a predefined secret letter."""</span>
     <span class="org-keyword">return</span>  <span class="org-string">"L"</span>

 <span class="org-type">@mcp.tool</span>()
 <span class="org-keyword">async def</span>  <span class="org-function-name">retrieve_secret_letter_tool</span>(ctx: Context)  <span class="org-operator">-></span>  <span class="org-builtin">str</span>:
     <span class="org-doc">"""Tool to retrieve the secret letter from the corresponding resource"""</span>
     <span class="org-variable-name">resources</span>  <span class="org-operator">=</span>  <span class="org-keyword">await</span> ctx.read_resource( <span class="org-string">"data://secret_letter"</span>)
     <span class="org-keyword">return</span> resources[0].content

 <span class="org-type">@mcp.prompt</span>()
 <span class="org-keyword">def</span>  <span class="org-function-name">haiku</span>(topic:  <span class="org-builtin">str</span>)  <span class="org-operator">-></span>  <span class="org-builtin">str</span>:
     <span class="org-doc">"""Generates a user message asking for an explanation of a topic."""</span>
     <span class="org-keyword">return</span> f <span class="org-string">"Can you please write a haiku about '</span>{topic} <span class="org-string">'?"</span>
</pre>
</div>
</div>

 <div id="outline-container-org33824f7" class="outline-3">
 <h3 id="org33824f7">Using prompts with Claude Desktop</h3>
 <div class="outline-text-3" id="text-org33824f7">
 <p>
Using MCP prompts with Claude Desktop is similar to using resources: you can send a custom prompt along with a message using the  <code>+</code> menu. If the prompt accepts an argument (like ours does), you will be prompted for it when adding.
</p>


 <figure id="orgbc7f8b4"> <img src="./figures/20250921-mcp-2/3_attach_prompt.png" alt="Claude Desktop 'Enter prompt inputs' dialog for the haiku prompt with a required Topic field"></img></figure> <p>
This will result in a text file containing the filled-in prompt. You can send this along with an empty message, and Claude will respond to the prompt.
</p>


 <figure id="org6ce353a"> <img src="./figures/20250921-mcp-2/4_prompt_response.png" alt="Claude Desktop responding to the attached haiku.txt prompt with a haiku about coffee"></img></figure> <p>
To learn more, check out the  <a href="https://gofastmcp.com/servers/prompts">Prompts section of the FastMCP docs</a>.
</p>
</div>
</div>
</div>
 <div id="outline-container-org019cca7" class="outline-2">
 <h2 id="org019cca7">Conclusion, Observations, and Next Steps</h2>
 <div class="outline-text-2" id="text-org019cca7">
 <p>
In this two-part series, we have seen how to set up an MCP server for use with Claude Desktop and how to define tools, resources, and prompts on that server. This should have given you what you need to take your first steps into the world of MCP servers.
</p>

 <p>
Using the MCP Python SDK makes it straightforward to define these MCP server components. As we saw above, they all follow the same general pattern: we define a function, which may or may not take arguments, and decorate it with the decorator corresponding to the component type.
</p>

 <p>
While this introduction only scratches the surface, MCP's real power comes when you start connecting your LLMs to actual systems like databases, APIs, and file systems. The standardized interface means you can combine MCP servers from different sources without worrying about compatibility issues.
</p>
</div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20250921-mcp-prompts-resources.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20250921-mcp-prompts-resources.html</guid>
  <pubDate>Sun, 21 Sep 2025 08:00:00 +0000</pubDate>
</item>
<item>
  <title>Getting Started with Model Context Protocol Part 1: Add a Simple MCP Server to Claude Desktop</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Getting Started with Model Context Protocol Part 1: Add a Simple MCP Server to Claude Desktop</h1>
 <p class="subtitle" role="doc-subtitle">April 12, 2025</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#org4886aa0">Introduction: MCP Concepts</a></li>
 <li> <a href="#org0b5f0b5">Quickstart: Set up a Simple MCP Server and Use It with Claude Desktop</a>
 <ul> <li> <a href="#org770b28b">Setup</a></li>
 <li> <a href="#org0e4facc">Define the MCP server</a></li>
 <li> <a href="#orgdaf38b1">Add the server to Claude Desktop</a>
 <ul> <li> <a href="#orgb15b5a1">Install the MCP server</a></li>
 <li> <a href="#orgfaa56b1">Configure the Claude Desktop app</a></li>
</ul></li>
 <li> <a href="#orgf9981cd">Use the tool provided by the MCP Server</a></li>
</ul></li>
 <li> <a href="#org794eda3">Recap and Next Steps</a></li>
</ul></div>
</nav> <div class="preview" id="org6a5d8d2">
 <p>
This post provides a simple, minimal example of setting up and using an MCP (model context protocol) server for use with Claude Desktop.
</p>

 <p>
There are many MCP guides and tutorials and docs out there. In this one, I attempt to start with very simple implementations with as little complexity as possible in order to get started as quickly as possible.
</p>

 <p>
Future posts will add more complexity, showing how to use additional MCP abstractions like prompts and resources, how to write an MCP client in Python, and how to use LLMs from other providers with MCPs.
</p>

</div>
 <div id="outline-container-org4886aa0" class="outline-2">
 <h2 id="org4886aa0">Introduction: MCP Concepts</h2>
 <div class="outline-text-2" id="text-org4886aa0">
 <p>
Anthropic's  <a href="https://modelcontextprotocol.io/introduction">Model Context Protocol (MCP)</a> is intended to standardize the way applications give context (data, tools, prompts, etc.) to LLMs.
</p>

 <p>
We can think of an application using MCP as having three components:
</p>
 <ol class="org-ol"> <li> <b>Host</b>: the host is the application, such as an IDE or a chat app, that manages connections to one or more MCP servers. The host application is what the end user typically interacts with.</li>
 <li> <b>MCP Server(s)</b>: MCP servers provide a standardized interface to resources (such as databases, file systems, tools, etc.) that LLMs can access.</li>
 <li> <b>Client(s)</b>: clients are components of the host application that maintain the connection with the MCP server(s). Each client corresponds to one server. A client facilitates requests to the server, receives responses, and relays them to the host or user.</li>
</ol> <p>
For example, a user might type the following into a chat app (the host): "Give me information about order ORD-1234." The client component of the application will pass this query, along with a list of available tools, to the LLM. Suppose one of the tools gives the ability to query a database of order statuses. The LLM will respond with a "tool call" specifying the tool to use (the database query tool) and the arguments to provide (the order id). The client will then invoke the tool from the MCP server, get the results of the database query, and pass them along to the next step, which might mean asking the LLM to respond to the user based on the results.
</p>
</div>
</div>

 <div id="outline-container-org0b5f0b5" class="outline-2">
 <h2 id="org0b5f0b5">Quickstart: Set up a Simple MCP Server and Use It with Claude Desktop</h2>
 <div class="outline-text-2" id="text-org0b5f0b5">
 <p>
To get started, we will set up an MCP server that exposes a single function,  <code>get_secret_number</code>, that simply returns a "secret number" to the LLM. When you ask an LLM with this capability for the secret number, it will invoke the tool and return the "secret number," verifying that it successfully used the MCP server.
</p>

 <p>
We will install this server to the Claude desktop app, allowing you to use the server without setting up a custom client.
</p>
</div>
 <div id="outline-container-org770b28b" class="outline-3">
 <h3 id="org770b28b">Setup</h3>
 <div class="outline-text-3" id="text-org770b28b">
 <p>
We will create a new Python environment using  <code>uv</code> before writing the server code. If you haven't already done so, first install uv by running the following shell script (on Mac/Linux):  <code>curl -LsSf https://astral.sh/uv/install.sh | sh</code>.
</p>

 <p>
Next, create and initialize a new project directory.
</p>

 <div class="org-src-container">
 <pre class="src src-bash">mkdir mcp-demo
 <span class="org-builtin">cd</span> mcp-demo
uv init
</pre>
</div>

 <p>
Then install the  <a href="https://github.com/modelcontextprotocol/python-sdk">MCP Python SDK</a> with  <code>uv add "mcp[cli]"</code> .This will also create a new Python virtual environment in your project directory, which you can activate with  <code>source.venv/bin/activate.</code>
</p>
</div>
</div>
 <div id="outline-container-org0e4facc" class="outline-3">
 <h3 id="org0e4facc">Define the MCP server</h3>
 <div class="outline-text-3" id="text-org0e4facc">
 <p>
Next, create a file called  <code>server.py</code> in your project directory with the following:
</p>

 <div class="org-src-container">
 <pre class="src src-python"> <span class="org-comment-delimiter"># </span> <span class="org-comment">server.py
</span> <span class="org-keyword">from</span> mcp.server.fastmcp  <span class="org-keyword">import</span> FastMCP

 <span class="org-variable-name">mcp</span>  <span class="org-operator">=</span> FastMCP( <span class="org-string">"SecretServer"</span>)

 <span class="org-type">@mcp.tool</span>()
 <span class="org-keyword">def</span>  <span class="org-function-name">get_secret_number</span>()  <span class="org-operator">-></span>  <span class="org-builtin">int</span>:
     <span class="org-doc">"""Returns a predefined secret number."""</span>
     <span class="org-keyword">return</span> 13
</pre>
</div>

 <p>
This is all we need to define an MCP server we can use with Claude Desktop. Let's walk through this.
</p>

 <ol class="org-ol"> <li> <p>
 <code>mcp = FastMCP("SecretServer")</code> initializes the server framework provided by the SDK. This handles all the core functionality, including connection management and message routing. Note that you don't  <i>have</i> to name this  <code>mcp</code>, but doing so makes it easier to install the server to Claude Desktop. If you use another name, you may get the following:
</p>

 <div class="org-src-container">
 <pre class="src src-text">[04/12/25 08:11:08] ERROR    No server object found in                    cli.py:151
                             /Users/dliden/git/mcp-examples/server.py.
                             Please either:
                             1. Use a standard variable name (mcp,
                             server, or app)
                             2. Specify the object name with file:object
                             syntax
</pre>
</div></li>
 <li> <code>@mcp.tool()</code> is a decorator that registers the function it decorates ( <code>get_secret_number</code>) to the MCP server we defined,  <code>mcp</code>.</li>
 <li>The  <code>get_secret_number</code> function just returns the number 13 when invoked. Why this function for an example? It's just an easy way to verify that everything is working correctly. We will ask Claude for the secret number, and it will need to invoke the function to get it.</li>
</ol> <p>
And that's it. This is a complete, usable MCP server that exposes one function for an LLM to use. Now let's add this to the Claude Desktop app.
</p>
</div>
</div>
 <div id="outline-container-orgdaf38b1" class="outline-3">
 <h3 id="orgdaf38b1">Add the server to Claude Desktop</h3>
 <div class="outline-text-3" id="text-orgdaf38b1">
 <p>
We can use the  <code>mcp</code> command line tool to install our new server to the Claude Desktop app (install it  <a href="https://claude.ai/download">here</a> if you haven't already).
</p>
</div>
 <div id="outline-container-orgb15b5a1" class="outline-4">
 <h4 id="orgb15b5a1">Install the MCP server</h4>
 <div class="outline-text-4" id="text-orgb15b5a1">
 <p>
Install the mcp server for use with Claude Desktop as follows:
</p>

 <div class="org-src-container">
 <pre class="src src-bash">mcp install server.py
</pre>
</div>
</div>
</div>
 <div id="outline-container-orgfaa56b1" class="outline-4">
 <h4 id="orgfaa56b1">Configure the Claude Desktop app</h4>
 <div class="outline-text-4" id="text-orgfaa56b1">
 <p>
I found that just installing the server as described above did not work without some manual adjustment of the configuration. In particular, I needed to modify the configuration to include the  <i>whole path to  <code>uv</code> executable on my system</i>. See  <a href="https://github.com/orgs/modelcontextprotocol/discussions/20">this GitHub discussion</a> for details.
</p>

 <p>
To find the configuration, go to the settings menu in the Claude Desktop app, then navigate to the Developer tab. Select your MCP server and click "edit config."
</p>


 <figure id="org483c025"> <img src="./figures/20250412-mcp-1/1-claude-config.png" alt="Claude Desktop Developer settings showing the running SecretServer MCP server and an Edit Config button"></img></figure> <p>
This will open a finder window (on MacOS) showing the directory with the configuration file,  <code>claude_desktop_config.json</code>. Open this with your preferred editor to access and update the config.
</p>

 <p>
If you ran into a similar issue with  <code>uv</code>, replace  <code>uv</code> in the  <code>Command</code> field with the full path the executable, which you can find with the  <code>which uv</code> terminal command. For example, on my system,  <code>which uv</code> returns  <code>/Users/dliden/.cargo/bin/uv</code>, so I updated my config to look like this:
</p>

 <div class="org-src-container">
 <pre class="src src-json">{
  "mcpServers": {
    "SecretServer": {
      "command": "/Users/dliden/.cargo/bin/uv",
      "args": [
        "run",
        "--with",
        "mcp[cli]",
        "mcp",
        "run",
        "/Users/dliden/git/mcp-examples/server.py"
      ]
    }
  }
}
</pre>
</div>
</div>
</div>
</div>
 <div id="outline-container-orgf9981cd" class="outline-3">
 <h3 id="orgf9981cd">Use the tool provided by the MCP Server</h3>
 <div class="outline-text-3" id="text-orgf9981cd">
 <p>
If you configured the MCP server correctly, you should now see two new icons in Claude desktop showing that Claude has access to the MCP server and to one or more tools from the server.
</p>


 <figure id="org2e1a656"> <img src="./figures/20250412-mcp-1/2-claude-icons.png" alt="Claude Desktop chat box with the tools and MCP connector icons highlighted below the message field"></img></figure> <p>
Clicking on the hammer icon will list the available tools and should show the secret number function we created.
</p>


 <figure id="org2d4a97d"> <img src="./figures/20250412-mcp-1/3-claude-tools.png" alt="Claude Desktop 'Available MCP tools' popup listing get_secret_number from SecretServer"></img></figure> <p>
After confirming that Claude has access to the MCP, we can try it out. Simply ask Claude: "what is the secret number?"
</p>

 <p>
Claude should know to use the function we created. A popup will appear asking for permission to use the function. Let's allow it.
</p>


 <figure id="org9a1e61f"> <img src="./figures/20250412-mcp-1/4-claude-permission.png" alt="Claude Desktop dialog asking permission to run get_secret_number from SecretServer, with Allow and Deny options"></img></figure> <p>
Now Claude can use the tool to retrieve the secret number.
</p>


 <figure id="orgc08fc2a"> <img src="./figures/20250412-mcp-1/5-claude-answer.png" alt="Claude Desktop replying 'The secret number is 13' after calling the get_secret_number tool"></img></figure> <p>
This demonstrates the basic pattern for setting up and MCP server and using it via the Claude Desktop app.
</p>
</div>
</div>
</div>
 <div id="outline-container-org794eda3" class="outline-2">
 <h2 id="org794eda3">Recap and Next Steps</h2>
 <div class="outline-text-2" id="text-org794eda3">
 <p>
To recap, in this post, we set up a very minimal MCP server using the  <code>FastMCP</code> method from the Python MCP SDK package. We defined a single tool that returns a "secret number" when invoked. We then installed the server to the Claude desktop app and confirmed that Claude could successfully invoke the tool via the MCP server to retrieve the secret number.
</p>

 <p>
This minimal implementation is a good starting point for further exploration with MCP. From here, you can add more components to the server and test them with the Claude Desktop app. Some suggestions for next steps:
</p>
 <ul class="org-ul"> <li>Learn about  <a href="https://modelcontextprotocol.io/docs/concepts/resources">resources</a>, a mechanism for MCP servers to expose data to clients/LLMs. You can either directly expose resources or you can add tools enabling the LLM to query resources. More on this in a future post!</li>
 <li>Define and use  <a href="https://modelcontextprotocol.io/docs/concepts/prompts">prompts</a> in your MCP server.</li>
</ul> <p>
I will discuss these additional MCP components in my next post on the topic, and then write about how to create a custom  <a href="https://modelcontextprotocol.io/quickstart/client">MCP Client</a> in Python.
</p>
</div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20250412-mcp-quickstart.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20250412-mcp-quickstart.html</guid>
  <pubDate>Sat, 12 Apr 2025 08:00:00 +0000</pubDate>
</item>
<item>
  <title>Emacs Introspection and Debugging</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Emacs Introspection and Debugging</h1>
 <p class="subtitle" role="doc-subtitle">March 23, 2025</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#org62f54f4">Introduction</a></li>
 <li> <a href="#org1f48515">Finding Relevant Variables</a></li>
 <li> <a href="#orga94dd83">Confirming the issue with error backtrace</a></li>
 <li> <a href="#org2018b57">Quick fix—bandaid approach</a></li>
 <li> <a href="#org890d013">Finding the root of the problem</a></li>
 <li> <a href="#orga7bd230">Conclusion—Emacs introspection</a></li>
</ul></div>
</nav> <div class="preview" id="org2370c10">
 <p>
If you use Emacs, you will eventually run into errors. Maybe a recent package update introduced some new issues with your system. Or some custom elisp you wrote runs into an edge case. Regardless of the cause, Emacs provides many tools for identifying the causes of errors and learning how to address them.
</p>

 <p>
This post works through a recent issue I encountered with the  <code>eglot</code> package and how I was able to identify and fix the issue using various introspection tools built into Emacs. It provides some general advice for how to use Emacs to learn about and debug issues with Emacs.
</p>

</div>

 <div id="outline-container-org62f54f4" class="outline-2">
 <h2 id="org62f54f4">Introduction</h2>
 <div class="outline-text-2" id="text-org62f54f4">
 <p>
For a while, whenever I used  <a href="https://www.gnu.org/software/emacs/manual/html_mono/eglot.html">eglot</a> (mostly for Python projects) and then shut it down with e.g.  <code>M-x eglot-shutdown</code>, all subsequent attempts to save any files in Emacs would return the following error:  <code>(jsonrpc-error-message . "No current JSON-RPC connection")</code>. The save would generally succeed, so this was more annoying than anything. But it  <i>was</i> annoying.
</p>

 <p>
Some quick searching online did not yield any useful discussions of how to fix the issue. And neither Claude nor Perplexity had much to offer, either. So I decided to use this as an excuse to learn more about built-in Emacs introspection and debugging tools.
</p>

 <p>
I went in with the following information:
</p>
 <ol class="org-ol"> <li>The issue was related to  <code>eglot</code>. Even though the error message did not reference eglot, the issue consistently appeared after using eglot and then shutting it down.</li>
 <li>The issue was triggered when I saved files.</li>
</ol> <p>
Given this pattern, I started by looking for  <a href="https://www.danliden.com/posts/20231217-emacs-hooks.html">hooks</a> related to saving.
</p>
</div>
</div>
 <div id="outline-container-org1f48515" class="outline-2">
 <h2 id="org1f48515">Finding Relevant Variables</h2>
 <div class="outline-text-2" id="text-org1f48515">
 <p>
I wasn't entirely sure what I was looking for. But I knew from previous reading that hooks are variables that, by convention, include the word  <code>hook</code> in their names. This already provides plenty to work with.
</p>

 <p>
The  <code>apropos-variable</code> function takes a pattern or a list of words and returns an  <code>*Apropos*</code> buffer with a list of matching variables. In this case, I interactively used  <code>apropos-variable</code> with  <code>M-x apropos-variable RET save hook</code> to search for variables matching  <code>save</code> and  <code>hook</code>. This returned a couple of good candidates for further exploration!
</p>


 <figure id="orgd0d3ace"> <img src="./figures/20250323-emacs-debugging/1_apropos.png" alt="Emacs *Apropos* buffer listing save-related hook variables including after-save-hook and before-save-hook"></img></figure> <p>
The  <code>after-save-hook</code> and  <code>before-save-hook</code> variables look especially promising. We can inspect those further for anything  <code>eglot</code>-related by selecting them from the  <code>*Apropos*</code> buffer or searching for them with  <code>C-h v <variable-name></code>. Following this approach showed me that:
</p>

 <ol class="org-ol"> <li>The value of  <code>before-save-hook</code> is  <code>nil</code>.</li>
 <li>The value of  <code>after-save-hook</code> is  <code>(eglot-format)</code>.</li>
</ol> <p>
This is already very useful and points toward some directions for fixing the issue!  <code>after-save-hook</code> is a "Normal hook that is run after a buffer is saved to its file." This would explain why (1) the issue is associated with saving files and (2) the saves are successful in spite of the error (the hook is run  <i>after</i> the save, not before).
</p>
</div>
</div>
 <div id="outline-container-orga94dd83" class="outline-2">
 <h2 id="orga94dd83">Confirming the issue with error backtrace</h2>
 <div class="outline-text-2" id="text-orga94dd83">
 <p>
I wanted to confirm that this hook was causing the issue so I used  <code>M-x toggle-debug-on-error</code> to get a more detailed backtrace. In reality, this is where I should have started—the error trace provides much more specific and useful information than the short error message returned in the echo area. When I tried to save a file with debugging enabled, I received the following in a  <b>Backtrace</b> buffer.
</p>

 <pre class="example">
Debugger entered--Lisp error: (jsonrpc-error "No current JSON-RPC connection" (jsonrpc-error-code . -32603) (jsonrpc-error-message . "No current JSON-RPC connection"))
  jsonrpc-error("No current JSON-RPC connection")
  eglot--current-server-or-lose()
  eglot-server-capable(:documentFormattingProvider)
  eglot-server-capable-or-lose(:documentFormattingProvider)
  eglot-format()
  run-hooks(after-save-hook)
  #<subr basic-save-buffer>(t)
  polymode-with-current-base-buffer(#<subr basic-save-buffer> t)
  apply(polymode-with-current-base-buffer #<subr basic-save-buffer> t)
  basic-save-buffer(t)
  save-buffer(1)
  funcall-interactively(save-buffer 1)
  command-execute(save-buffer)
</pre>


 <p>
You can read this backtrace from bottom to top. After saving the buffer, we see that  <code>run-hooks(after-save-hook)</code> runs, which results in  <code>eglot-format()</code> being run. The final function called before the error is  <code>eglot--current-server-or-lose()</code>. Inspecting this with  <code>C-h f RET eglot--current-server-or-lose</code> tells us that this function returns the "current logical Eglot server connection or error." If I'm saving some random file that is not going to use a Python LSP server, we would expect this to return an error.
</p>

 <p>
Now that we have some understanding of what is happening, how do we fix it?
</p>
</div>
</div>
 <div id="outline-container-org2018b57" class="outline-2">
 <h2 id="org2018b57">Quick fix—bandaid approach</h2>
 <div class="outline-text-2" id="text-org2018b57">
 <p>
My initial fix for this issue was to write a simple cleanup script to remove the offending hook function from the  <code>after-save-hook</code>.
</p>

 <div class="org-src-container">
 <pre class="src src-emacs-lisp">( <span class="org-keyword">use-package</span> eglot
   <span class="org-builtin">:straight</span>
  ( <span class="org-builtin">:type</span> built-in)
   <span class="org-builtin">:hook</span> ((python-mode . eglot-ensure))
   <span class="org-builtin">:config</span>
  ( <span class="org-keyword">setq</span> eglot-autoshutdown t)
  
  ( <span class="org-keyword">defun</span>  <span class="org-function-name">my-eglot-shutdown-cleanup</span> ( <span class="org-type">&rest</span> _)
     <span class="org-doc">"Perform thorough cleanup after Eglot shutdown."</span>
    (remove-hook 'after-save-hook #'eglot-format nil)
  (advice-add 'eglot-shutdown  <span class="org-builtin">:after</span> #'my-eglot-shutdown-cleanup))
</pre>
</div>

 <p>
This isn't perfect. It  <i>does</i> prevent saving from returning an error  <i>after</i> I've shut down eglot, resolving a significant nuisance. However, the issue remains when eglot is running and I try to save a buffer without an associated LSP server; i.e., if I am using eglot in a Python buffer but then try to save an org buffer. The  <code>eglot-format</code> hook function is still active; there is no running language server to provide formatting for org buffers, so the hook function returns an error.
</p>

 <p>
At this point, it was not yet clear to me how the hook was set in the first place. Deactivating the hook when eglot is not running resolves about 80% of the frustration for me. But I  <b>would</b> like to fully resolve the issue. I don't actually  <i>want</i> the format-on-save behavior in the first place. It has to be set  <b>somewhere</b>. In the next section, I will briefly sketch out my process for identifying the issue.
</p>
</div>
</div>

 <div id="outline-container-org890d013" class="outline-2">
 <h2 id="org890d013">Finding the root of the problem</h2>
 <div class="outline-text-2" id="text-org890d013">
 <p>
My first thought was that, perhaps, the hook was being set when  <code>eglot</code> was invoked. To check this, I:
</p>
 <ol class="org-ol"> <li>Called  <code>C-h f eglot</code> to find the documentation for the  <code>eglot</code> command</li>
 <li>Followed the link in the help buffer to  <code>eglot.el</code>, the source file where the  <code>eglot</code> command and related functions are defined.</li>
 <li>Used  <code>consult-line</code> (or, equivalently,  <code>isearch</code> or one of the many other tools available for searching buffer text) for the term  <code>hook</code>.</li>
</ol> <p>
This showed me that  <code>eglot-format</code> was not, in fact, being set as an  <code>after-save-hook</code> function by eglot itself.
</p>

 <p>
So…did I do this myself, somewhere in my config?
</p>

 <p>
I next navigated to my config folder,  <code>~/coffeemacs/</code>, and invoked  <code>lgrep</code> to search my various  <code>*.el</code> config files for anything related to  <code>eglot</code>.
</p>

 <p>
And it turns out, I set this hook myself!
</p>



 <figure id="org4962fa4"> <img src="./figures/20250323-emacs-debugging/2_grep.png" alt="Emacs *grep* buffer showing matches for 'eglot' across init.el and pyconfig.el config files"></img></figure> <p>
Once I deleted the  <code>(add-hook 'after-save-hook ...)</code> call from my config, the issue was fully resolved.
</p>
</div>
</div>

 <div id="outline-container-orga7bd230" class="outline-2">
 <h2 id="orga7bd230">Conclusion—Emacs introspection</h2>
 <div class="outline-text-2" id="text-orga7bd230">
 <p>
The approaches I used here are nowhere close to comprehensive. Emacs has countless introspection tools and a seemingly-inexhaustible collection of functions and variables that enable you to inspect everything going on in your Emacs setup. Furthermore, it provides a range of ways to search these variables and functions.
</p>

 <p>
The following tools will go a long way toward helping you debug an error in Emacs:
</p>

 <ol class="org-ol"> <li> <b>Enable debugging on error</b> with  <code>M-x toggle-debug-on-error</code>. This will provide a backtrace that will show the source of the error.</li>
 <li> <b>Search for relevant functions and variables</b> with  <code>apropos-function</code> and  <code>apropos-variable</code>. You can pass in a list of relevant terms to search for.</li>
 <li> <b>Get documentation for specific functions and variables</b> with the  <code>describe-function</code> ( <code>C-h f</code>) and  <code>describe-variable</code> ( <code>C-h v</code>) commands.</li>
</ol> <p>
Even these relatively simple tools are often enough to identify the source of an issue and do something about it.
</p>

 <p>
Lastly—we're reaching a point where you don't have to do this yourself. You can configure the  <a href="https://github.com/karthink/gptel?tab=readme-ov-file#i-want-the-window-to-scroll-automatically-as-the-response-is-inserted">gptel</a> package with a set of tools—Emacs functions—that will enable it to recursively search for information in docs, manuals, source code, etc.  <a href="https://youtu.be/JHXG225oP8E?si=6pgmR_S-Vk2QmjU9">This video</a> provides a good overview of how to get started.
</p>


 <figure id="orgdefe8ee"> <img src="./figures/20250323-emacs-debugging/3_gptel.png" alt="gptel response in Emacs explaining how gptel-tools and gptel-tool structs are defined after tool calls"></img></figure></div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20250330-emacs-debugging.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20250330-emacs-debugging.html</guid>
  <pubDate>Sun, 23 Mar 2025 08:00:00 +0000</pubDate>
</item>
<item>
  <title>Persistent Elements in Daily Journals with Org Agenda</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Persistent Elements in Daily Journals with Org Agenda</h1>
 <p class="subtitle" role="doc-subtitle">May 5, 2024</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#org917e5a1">A different way of thinking about the org agenda</a></li>
 <li> <a href="#org474987d">org-agenda-custom-commands</a></li>
 <li> <a href="#orgeb5ac08">Next Steps</a>
 <ul> <li> <a href="#org6b92b30"> <span class="done DONE">DONE</span> Add TODO entries</a>
 <ul> <li> <a href="#org2edc55c">UPDATE  <span class="timestamp-wrapper"> <span class="timestamp"><2024-05-06 Mon></span></span></a></li>
</ul></li>
 <li> <a href="#orge053a9b"> <span class="todo TODO">TODO</span> Limit the number of files searched</a></li>
 <li> <a href="#org3898469"> <span class="todo TODO">TODO</span> Add and organize tags</a></li>
 <li> <a href="#orgd349f2d"> <span class="todo TODO">TODO</span> Other</a></li>
</ul></li>
</ul></div>
</nav> <div class="preview" id="orge1b93c5">
 <p>
I use denote's  <a href="https://protesilaos.com/emacs/denote#h:4a6d92dd-19eb-4fcc-a7b5-05ce04da3a92">journaling features</a> to keep a daily project log, where I record whatever I'm working on, stray bits of knowledge, some TODOs, fleeting thoughts, etc.
</p>

 <p>
In some cases, I want to refer back to these notes. But I (will) have a lot of these journal files. I don't want to search through them manually to find the name of that article, or that recommendation I jotted down, or whatever it was.
</p>

 <p>
This post shows a quick solution to this issue using  <a href="https://orgmode.org/worg/org-tutorials/org-custom-agenda-commands.html">org-agenda-custom-commands</a> to make a custom view over specified tags in my journal files.
</p>

</div>

 <div id="outline-container-org917e5a1" class="outline-2">
 <h2 id="org917e5a1">A different way of thinking about the org agenda</h2>
 <div class="outline-text-2" id="text-org917e5a1">
 <p>
I've mostly thought of the org agenda as, well, an agenda. It's for managing todos, dates, deadlines. It's a very versatile tool for that purpose, and can pull those elements out of a bunch of different org files. This is great.
</p>

 <p>
But it's a lot more general than that. It's not just about building an agenda. We can pull all kinds of structured data out of org files with no need to conceptualize the end result as having anything to do with an agenda.
</p>

 <p>
The problem I set out to solve is simple:
</p>
 <ul class="org-ul"> <li>I keep daily journal files</li>
 <li>I seldom refer back to those files</li>
 <li>Sometimes I write something in those journal files that I want to revisit in the future.</li>
</ul> <p>
You can see the problem. I'm writing something I intend to revisit in the future in a file I tend not to revisit.
</p>

 <p>
With the org agenda, I can remedy this as follows:
</p>
 <ul class="org-ul"> <li>Apply a tag (or category, or todo status, or another searchable marker) to headers in my journal I want to see in the future</li>
 <li>Build a custom org agenda view that searches only the journal files and displays only those tagged headers.</li>
</ul></div>
</div>
 <div id="outline-container-org474987d" class="outline-2">
 <h2 id="org474987d">org-agenda-custom-commands</h2>
 <div class="outline-text-2" id="text-org474987d">
 <p>
I did this with  <a href="https://orgmode.org/worg/org-tutorials/org-custom-agenda-commands.html">org-agenda-custom-commands</a>. It looks like this in my config:
</p>

 <div class="org-src-container">
 <pre class="src src-emacs-lisp">( <span class="org-keyword">setq</span> '(( <span class="org-string">"j"</span>  <span class="org-string">"Journals"</span> ((tags  <span class="org-string">"persist"</span>)
                         (todo))
         ((org-agenda-files
           (file-expand-wildcards  <span class="org-string">"~/org/denotes/journal/*.org"</span>))
          (org-agenda-prefix-format  <span class="org-string">"%-2c:::"</span>)))))
</pre>
</div>

 <p>
This creates a custom view called "journals" that I can select with the "j" command from the agenda menu (from  <code><C-c a></code>). Any headline tagged with "persist" will appear in that agenda view. It was also updated to include all TODO entries in the journals, ensuring that I properly resolve or migrate them.
</p>
</div>
</div>
 <div id="outline-container-orgeb5ac08" class="outline-2">
 <h2 id="orgeb5ac08">Next Steps</h2>
 <div class="outline-text-2" id="text-orgeb5ac08">
 <p>
This is a very simple agenda view. There are a few improvements I intend to make in the near future (I will update this post accordingly).
</p>
</div>
 <div id="outline-container-org6b92b30" class="outline-3">
 <h3 id="org6b92b30"> <span class="done DONE">DONE</span> Add TODO entries</h3>
 <div class="outline-text-3" id="text-org6b92b30">
 <p>
I want to add TODO entries to the custom view. Any outstanding TODOs from the daily journals should either be closed out or migrated somewhere more permanent.
</p>
</div>
 <div id="outline-container-org2edc55c" class="outline-4">
 <h4 id="org2edc55c">UPDATE  <span class="timestamp-wrapper"> <span class="timestamp"><2024-05-06 Mon></span></span></h4>
 <div class="outline-text-4" id="text-org2edc55c">
 <p>
This required only very minor changes:
</p>
 <ol class="org-ol"> <li>add a  <code>(todo)</code> block to the  <code>org-agenda-custom-commands</code> specification</li>
 <li>make the configuration specifying e.g. the directory and formatting apply to the whole block rather than to individual sections.</li>
</ol></div>
</div>
</div>

 <div id="outline-container-orge053a9b" class="outline-3">
 <h3 id="orge053a9b"> <span class="todo TODO">TODO</span> Limit the number of files searched</h3>
 <div class="outline-text-3" id="text-orge053a9b">
 <p>
I am not yet entirely sure how to do this one. Org agenda is notorious for slowing down when dealing with a lot of files. The number of daily journal entries will increase in an obvious way. There are some ways to  <a href="https://orgmode.org/manual/Filtering_002flimiting-agenda-items.html">filter and limit</a> the results but I'm not sure if they will prevent the agenda from reading more files than it needs to. Something to investigate.
</p>
</div>
</div>
 <div id="outline-container-org3898469" class="outline-3">
 <h3 id="org3898469"> <span class="todo TODO">TODO</span> Add and organize tags</h3>
 <div class="outline-text-3" id="text-org3898469">
 <p>
I don't just want a catch-all tag. I'd like to have specific tags for e.g. reading lists, project ideas, recommendations, work notes to follow up on, etc.
</p>
</div>
</div>
 <div id="outline-container-orgd349f2d" class="outline-3">
 <h3 id="orgd349f2d"> <span class="todo TODO">TODO</span> Other</h3>
 <div class="outline-text-3" id="text-orgd349f2d">
 <p>
column view settings, nice date display for each entry, etc.
</p>
</div>
</div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20240505-journal-persist.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20240505-journal-persist.html</guid>
  <pubDate>Sun, 05 May 2024 08:00:00 +0000</pubDate>
</item>
<item>
  <title>Retrieving Data for the H2o RAG Benchmark</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Retrieving Data for the H2o RAG Benchmark</h1>
 <p class="subtitle" role="doc-subtitle">March 29, 2024</p>
</header> <div class="preview" id="org458bfb0">
 <p>
I was looking for a good dataset to use for comparing different models in a RAG application when I found  <a href="https://www.reddit.com/r/LocalLLaMA/comments/1bpo5uo/rag_benchmark_of_databricksdbrx/">this post</a> on Reddit. It compares a bunch of models on a collection of questions over a set of documents provided by  <a href="https://h2o.ai">H2O.ai</a>.
</p>

 <p>
I wasn't super interested in the benchmark, but the files (mostly pdfs, one mp3, jpg, other file types) interested me for use in my own testing. This short post shows how to get them using the scripts provided by h2o.ai.
</p>

</div>

 <p>
To get started with the H2O RAG benchmark, first clone the  <code>enterprise-h2ogpte</code> repo and navigate to the  <code>rag_benchmark</code> directory:
</p>

 <div class="org-src-container">
 <pre class="src src-sh">git clone https://github.com/h2oai/enterprise-h2ogpte.git
 <span class="org-builtin">cd</span> enterprise-h2ogpte/rag_benchmark
</pre>
</div>

 <p>
Next, perhaps in a notebook, instantiate each of the documents.
</p>

 <div class="org-src-container">
 <pre class="src src-python"> <span class="org-keyword">from</span> datasets  <span class="org-keyword">import</span> CachedFile

 <span class="org-variable-name">femsa</span>  <span class="org-operator">=</span> CachedFile(
     <span class="org-string">"Femsa"</span>,
     <span class="org-string">"https://enterprise-h2ogpt-public-data.s3.amazonaws.com/Coca-Cola-FEMSA-Results-1Q23-vf-2.pdf"</span>,
)
 <span class="org-variable-name">wells_fargo</span>  <span class="org-operator">=</span> CachedFile(
     <span class="org-string">"WellsFargo"</span>,
     <span class="org-string">"https://enterprise-h2ogpt-public-data.s3.amazonaws.com/wellsfargo-2022-annual-report.pdf"</span>,
)
 <span class="org-variable-name">citi_report</span>  <span class="org-operator">=</span> CachedFile(
     <span class="org-string">"CitiAnnual"</span>,
     <span class="org-string">"https://enterprise-h2ogpt-public-data.s3.amazonaws.com/citi-2022-annual-report.pdf"</span>,
)
 <span class="org-variable-name">kaiser</span>  <span class="org-operator">=</span> CachedFile(
     <span class="org-string">"Kaiser"</span>,
     <span class="org-string">"https://enterprise-h2ogpt-public-data.s3.amazonaws.com/kp-annual-report-en-2019.pdf"</span>,
)
 <span class="org-variable-name">cba</span>  <span class="org-operator">=</span> CachedFile(
     <span class="org-string">"CBA-Spreads"</span>,
     <span class="org-string">"https://enterprise-h2ogpt-public-data.s3.amazonaws.com/2023-Annual-Report-Spreads.pdf"</span>,
)
 <span class="org-variable-name">cba_fullpage</span>  <span class="org-operator">=</span> CachedFile(
     <span class="org-string">"CBA-Annual"</span>,
     <span class="org-string">"https://enterprise-h2ogpt-public-data.s3.amazonaws.com/CBA.2023.Annual.Report.pdf"</span>,
)
 <span class="org-variable-name">cba_wheel</span>  <span class="org-operator">=</span> CachedFile(
     <span class="org-string">"CBA-Wheel"</span>,
     <span class="org-string">"https://enterprise-h2ogpt-public-data.s3.amazonaws.com/CBA-1H23-Results-Presentation_wheel.pdf"</span>,
)
 <span class="org-variable-name">nyl_all</span>  <span class="org-operator">=</span> CachedFile(
     <span class="org-string">"NYL_All"</span>,
     <span class="org-string">"https://enterprise-h2ogpt-public-data.s3.amazonaws.com/2022-nyl-investment-report.pdf"</span>,
)
 <span class="org-variable-name">bradesco</span>  <span class="org-operator">=</span> CachedFile(
     <span class="org-string">"Bradesco"</span>,
     <span class="org-string">"https://enterprise-h2ogpt-public-data.s3.amazonaws.com/bradesco-2022-integrated-report.pdf"</span>,
)
 <span class="org-variable-name">tabasco</span>  <span class="org-operator">=</span> CachedFile(
     <span class="org-string">"Tabasco"</span>,
     <span class="org-string">"https://enterprise-h2ogpt-public-data.s3.amazonaws.com/Tabasco_Ingredients_Products_Guide.pdf"</span>,
)
 <span class="org-variable-name">citi_report_pg6</span>  <span class="org-operator">=</span> CachedFile(
     <span class="org-string">"Citi6"</span>,
     <span class="org-string">"https://enterprise-h2ogpt-public-data.s3.amazonaws.com/citi-2022-annual-report-page6.pdf"</span>,
)
 <span class="org-variable-name">citi_report_pg1_2</span>  <span class="org-operator">=</span> CachedFile(
     <span class="org-string">"Citi1_2"</span>,
     <span class="org-string">"https://enterprise-h2ogpt-public-data.s3.amazonaws.com/citi-2022-annual-report-pages1-2.pdf"</span>,
)
 <span class="org-variable-name">nyl_report_pg5_15</span>  <span class="org-operator">=</span> CachedFile(
     <span class="org-string">"NYL5_15"</span>,
     <span class="org-string">"https://enterprise-h2ogpt-public-data.s3.amazonaws.com/2022-nyl-investment-report-pages-5-and-15.pdf"</span>,
)
 <span class="org-variable-name">aluminum_int</span>  <span class="org-operator">=</span> CachedFile(
     <span class="org-string">"AluminumInt"</span>,
     <span class="org-string">"https://enterprise-h2ogpt-public-data.s3.amazonaws.com/Aluminum.Intelligence.Report.November.2022.pdf"</span>,
)
 <span class="org-variable-name">albumentations_markdown</span>  <span class="org-operator">=</span> CachedFile(
     <span class="org-string">"AlbumentationsREADME"</span>,
     <span class="org-string">"https://enterprise-h2ogpt-public-data.s3.amazonaws.com/albumentations-README.md"</span>,
)
 <span class="org-variable-name">best_buy</span>  <span class="org-operator">=</span> CachedFile(
     <span class="org-string">"BestBuy"</span>,
     <span class="org-string">"https://enterprise-h2ogpt-public-data.s3.amazonaws.com/Best-Buy-Investor-Event-March-2022.pdf"</span>,
)

 <span class="org-variable-name">example_rst</span>  <span class="org-operator">=</span> CachedFile(
     <span class="org-string">"ExampleRST"</span>,
     <span class="org-string">"https://enterprise-h2ogpt-public-data.s3.amazonaws.com/example-rst2.rst"</span>,
)

 <span class="org-variable-name">audio_label_genie</span>  <span class="org-operator">=</span> CachedFile(
     <span class="org-string">"AudioLabelGenie"</span>,
     <span class="org-string">"https://enterprise-h2ogpt-public-data.s3.amazonaws.com/label-genie-intro-youtube.mp3"</span>,
)

 <span class="org-variable-name">fast_food</span>  <span class="org-operator">=</span> CachedFile(
     <span class="org-string">"FastFood"</span>,
     <span class="org-string">"https://enterprise-h2ogpt-public-data.s3.amazonaws.com/fastfood.jpg"</span>,
)

 <span class="org-variable-name">sanepar_pg4</span>  <span class="org-operator">=</span> CachedFile(
     <span class="org-string">"Sanepar_4"</span>,
     <span class="org-string">"https://enterprise-h2ogpt-public-data.s3.amazonaws.com/Demonstracoes-Financeiras-Anuaanepar-2022-12-31-gmdgFjGq-page4.pdf"</span>,
)

 <span class="org-variable-name">dell_scanned_pr</span>  <span class="org-operator">=</span> CachedFile(
     <span class="org-string">"dell_scanned_pr"</span>,
     <span class="org-string">"https://enterprise-h2ogpt-public-data.s3.amazonaws.com/Q2 FY24 Financial Results Press Release.pdf"</span>,
)

 <span class="org-variable-name">jpeg_xr_image</span>  <span class="org-operator">=</span> CachedFile(
     <span class="org-string">"JPEG-XR"</span>,
     <span class="org-string">"https://enterprise-h2ogpt-public-data.s3.amazonaws.com/gilgamesh_tablet_1.jxr"</span>,
)
</pre>
</div>


 <p>
Next, use the  <code>get()</code> method from each  <code>CachedFile</code> instance to download its file.
</p>

 <div class="org-src-container">
 <pre class="src src-python"> <span class="org-variable-name">instances</span>  <span class="org-operator">=</span> [
    femsa,
    wells_fargo,
    citi_report,
    kaiser,
    cba,
    cba_fullpage,
    cba_wheel,
    nyl_all,
    bradesco,
    tabasco,
    citi_report_pg6,
    citi_report_pg1_2,
    nyl_report_pg5_15,
    aluminum_int,
    albumentations_markdown,
    best_buy,
    example_rst,
    audio_label_genie,
    fast_food,
    sanepar_pg4,
    dell_scanned_pr,
    jpeg_xr_image,
]

 <span class="org-keyword">for</span> instance  <span class="org-keyword">in</span> instances:
     <span class="org-keyword">try</span>:
         <span class="org-variable-name">result</span>  <span class="org-operator">=</span> instance.get()
         <span class="org-builtin">print</span>( <span class="org-string">"---"</span>)
     <span class="org-keyword">except</span>  <span class="org-type">Exception</span>  <span class="org-keyword">as</span> e:
         <span class="org-builtin">print</span>(f <span class="org-string">"Error occurred for instance </span>{instance} <span class="org-string">: </span>{ <span class="org-builtin">str</span>(e)} <span class="org-string">"</span>)
         <span class="org-builtin">print</span>( <span class="org-string">"---"</span>)
</pre>
</div>

 <p>
Run the notebook cells to fetch the files. They will be stored in the  <code>/data/cached</code> directory under  <code>rag_benchmark</code>. You can now use them for whatever you want.
</p>
</div>]]></description>
  <link>https://danliden.com/posts/./20240329-h2o-rag-data.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20240329-h2o-rag-data.html</guid>
  <pubDate>Fri, 29 Mar 2024 08:00:00 +0000</pubDate>
</item>
<item>
  <title>Making headings for recurring tasks in org mode</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Making headings for recurring tasks in org mode</h1>
 <p class="subtitle" role="doc-subtitle">March 25, 2024</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#orgfc054bd">How it works</a></li>
 <li> <a href="#org2890409">Limitations</a></li>
 <li> <a href="#org314e1d9">Further reading</a></li>
</ul></div>
</nav> <div class="preview" id="org39da549">
 <p>
This short post shows how to use the  <code>org-clone-subtree-with-time-shift</code> command to make org headings for recurring tasks. I was recently trying to add a five-week class to my org agenda and I didn't want to manually create each heading and add or modify the timestamp. This approach made it very easy.
</p>

</div>

 <div id="outline-container-orgfc054bd" class="outline-2">
 <h2 id="orgfc054bd">How it works</h2>
 <div class="outline-text-2" id="text-orgfc054bd">
 <p>
Suppose I have an org mode heading representing a scheduled event, like a class:
</p>

 <div class="org-src-container">
 <pre class="src src-org"> <span class="org-org-level-1">* Class</span>
 <span class="org-org-special-keyword">SCHEDULED:</span>  <span class="org-org-date"><2024-03-26 Tue></span>
</pre>
</div>

 <p>
Now suppose this class is scheduled weekly for the next five weeks. We don't necessarily want to manually copy the heading and manually update each timestamp (though, admittedly, it would only take a minute or two). This is where  <code>org-clone-subtree-with-time-shift</code> comes in.
</p>

 <p>
When we invoke this function with the cursor on the first heading, we will be prompted for (1) the number of clones to create and (2) the time shift we want to use. In this example, we specify 4 clones (for a total of 5 headings) and a  <code>+1w</code> time shift, to shift each heading by one week. 
</p>

 <div class="org-src-container">
 <pre class="src src-org"> <span class="org-org-level-1">* Class</span>
 <span class="org-org-special-keyword">SCHEDULED:</span>  <span class="org-org-date"><2024-03-26 Tue></span>
 <span class="org-org-level-1">* Class</span>
 <span class="org-org-special-keyword">SCHEDULED:</span>  <span class="org-org-date"><2024-04-02 Tue></span>
 <span class="org-org-level-1">* Class</span>
 <span class="org-org-special-keyword">SCHEDULED:</span>  <span class="org-org-date"><2024-04-09 Tue></span>
 <span class="org-org-level-1">* Class</span>
 <span class="org-org-special-keyword">SCHEDULED:</span>  <span class="org-org-date"><2024-04-16 Tue></span>
 <span class="org-org-level-1">* Class</span>
 <span class="org-org-special-keyword">SCHEDULED:</span>  <span class="org-org-date"><2024-04-23 Tue></span>
</pre>
</div>
</div>
</div>

 <div id="outline-container-org2890409" class="outline-2">
 <h2 id="org2890409">Limitations</h2>
 <div class="outline-text-2" id="text-org2890409">
 <p>
In some cases, you may want to change the names of the headers somewhat (such as by adding a counter; class 1, class 2, etc.). There are many different approaches to handle this programmatically, but it's beyond the scope of this short post. In this case, it takes just a few seconds to add a class number to each heading manually.
</p>
</div>
</div>

 <div id="outline-container-org314e1d9" class="outline-2">
 <h2 id="org314e1d9">Further reading</h2>
 <div class="outline-text-2" id="text-org314e1d9">
 <p>
Most helpfully, here is the documenation from  <code>C-h f org-clone-subtree-with-time-shift</code>:
</p>

 <blockquote>
 <p>
org-clone-subtree-with-time-shift is an interactive Lisp closure in
‘org.el’.
</p>

 <p>
It is bound to C-c C-x c.
</p>

 <p>
(org-clone-subtree-with-time-shift N &optional SHIFT)
</p>

 <p>
Clone the task (subtree) at point N times.
The clones will be inserted as siblings.
</p>

 <p>
In interactive use, the user will be prompted for the number of
clones to be produced.  If the entry has a timestamp, the user
will also be prompted for a time shift, which may be a repeater
as used in time stamps, for example ‘+3d’.  To disable this,
you can call the function with a universal prefix argument.
</p>

 <p>
When a valid repeater is given and the entry contains any time
stamps, the clones will become a sequence in time, with time
stamps in the subtree shifted for each clone produced.  If SHIFT
is nil or the empty string, time stamps will be left alone.  The
ID property of the original subtree is removed.
</p>

 <p>
In each clone, all the CLOCK entries will be removed.  This
prevents Org from considering that the clocked times overlap.
</p>

 <p>
If the original subtree did contain time stamps with a repeater,
the following will happen:
</p>
 <ul class="org-ul"> <li>the repeater will be removed in each clone</li>
 <li>an additional clone will be produced, with the current, unshifted
date(s) in the entry.</li>
 <li>the original entry will be placed  <b>after</b> all the clones, with
repeater intact.</li>
 <li>the start days in the repeater in the original entry will be shifted
to past the last clone.</li>
</ul> <p>
In this way you can spell out a number of instances of a repeating task,
and still retain the repeater to cover future instances of the task.
</p>

 <p>
As described above, N+1 clones are produced when the original
subtree has a repeater.  Setting N to 0, then, can be used to
remove the repeater from a subtree and create a shifted clone
with the original repeater.
</p>
</blockquote>

 <p>
For more, you can also consult:
</p>

 <ul class="org-ul"> <li> <a href="https://orgmode.org/manual/Structure-Editing.html#index-C_002dc-C_002dx-c">Entry in the Structure Editing docs</a></li>
 <li> <a href="https://emacs.ch/@dliden/112094606592802616">Mastodon discussion</a> on the topic, including some discussion of workarounds for the aforementioned limitations.</li>
</ul></div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20240325-org-clone-timeshift.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20240325-org-clone-timeshift.html</guid>
  <pubDate>Mon, 25 Mar 2024 08:00:00 +0000</pubDate>
</item>
<item>
  <title>Introduction to Emacs Hooks</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Introduction to Emacs Hooks</h1>
 <p class="subtitle" role="doc-subtitle">December 17, 2023</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#orgbb124e2">Emacs Hooks</a></li>
 <li> <a href="#orgc7e6fc0">What do hooks do?</a></li>
 <li> <a href="#orga426749">How do hooks work?</a>
 <ul> <li> <a href="#org0ca193a">Hooks Example</a></li>
</ul></li>
 <li> <a href="#org10d8b23">Mode Hooks</a></li>
 <li> <a href="#org818eec5">Appendix: Hooks in use-package</a></li>
 <li> <a href="#org09c7f71">Further Reading</a></li>
</ul></div>
</nav> <div id="outline-container-orgbb124e2" class="outline-2">
 <h2 id="orgbb124e2">Emacs Hooks</h2>
 <div class="outline-text-2" id="text-orgbb124e2">
 <div class="preview" id="org2243930">
 <p>
Today I was customizing the appearance of org files displayed with  <a href="https://github.com/takaxp/org-tree-slide">org-tree-slide</a>. In particular, I wanted to increase the font size and start  <a href="https://github.com/rnkn/olivetti">Olivetti mode</a> whenever I started  <code>org-tree-slide-mode</code> and return everything to normal when I was done. This, I quickly discovered, required the use of  <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Hooks.html">hooks</a>. Hooks are not especially complicated, but they are useful and worth taking a few minutes to understand. This post will cover the basics of working with hooks in emacs.
</p>

</div>
</div>
</div>
 <div id="outline-container-orgc7e6fc0" class="outline-2">
 <h2 id="orgc7e6fc0">What do hooks do?</h2>
 <div class="outline-text-2" id="text-orgc7e6fc0">
 <p>
A  <i>hook</i> is a list of functions that are run on specifically-defined occasions, triggered by calls to a  <code>run-hooks</code> or  <code>run-mode-hooks</code> function.
</p>

 <p>
Hooks are very commonly run when major modes (and, often, minor modes) are initialized in an emacs session. They provide a way to set up mode-specific configurations when a mode is initialized or when some specific action is undertaken by the user.
</p>

 <p>
For a specific example,  <code>org-tree-slide-mode</code> defines the hooks  <code>org-tree-slide-play-hook</code> and  <code>org-tree-slide-stop-hook</code>, which define what happens when a slide show is started or stopped. I wanted to increase the font size, decrease the width of the displayed text, and remove the header line when the slide show was active, and reset them when it was finished.
</p>


 <div class="org-center">

 <figure id="org8877657"> <img src="./figures/20231217-emacs-hooks/hooks_screen_capture.gif" alt="Animation of org-tree-slide-mode making an Emacs org buffer's text larger and centered via a play hook"></img> <figcaption> <span class="figure-number">Figure 1: </span>Invoking  <code>org-tree-slide-mode</code> runs  <code>org-tree-slide-play-hook</code>, a list of functions meant to run when a slide show is started in  <code>org-tree-slide-mode</code>. In this case, the hook makes the text larger and centered in the buffer.</figcaption></figure></div>
</div>
</div>
 <div id="outline-container-orga426749" class="outline-2">
 <h2 id="orga426749">How do hooks work?</h2>
 <div class="outline-text-2" id="text-orga426749">
 <p>
First, a quick glossary of terms:
</p>
 <ul class="org-ul"> <li>a  <b>hook</b> is a variable defining a list of functions. These variables typically end in  <code>-hook</code>, such as  <code>org-mode-hook</code>. Hooks may also end in  <code>-functions</code>; these so-called "abnormal hooks" are not the focus of this post. Still, if you're searching for hooks, it is good to know that this pattern exists.</li>
 <li>a  <b>hook function</b> is one of the functions that comprise the hook.</li>
 <li>There are  <i>normal</i> and  <i>abnormal</i> hooks. Most hooks are normal. For the purposes of this post, I am focusing on  <i>normal hooks</i>. In a normal hook, none of the hook functions take any arguments, and emacs calls each hook function in the list sequentially. Abnormal hooks may take arguments or exhibit other behaviors when called that require special attention/documentation.</li>
</ul> <p>
Hooks are run when specific functions call them. Such functions are often called at specific points in the initialization or use of emacs modes, but they are not limited to those circumstances. Here is a minimal example.
</p>
</div>
 <div id="outline-container-org0ca193a" class="outline-3">
 <h3 id="org0ca193a">Hooks Example</h3>
 <div class="outline-text-3" id="text-org0ca193a">
 <p>
First, we'll define the hook variable. This is the same as defining any other variable.
</p>

 <div class="org-src-container">
 <pre class="src src-emacs-lisp">( <span class="org-keyword">setq</span> my-example-hook nil)
</pre>
</div>

 <p>
Next, we'll add some hooks to this variable. These will just be simple functions that print some output.
</p>

 <div class="org-src-container">
 <pre class="src src-emacs-lisp">( <span class="org-keyword">defun</span>  <span class="org-function-name">hook-function-1</span> ()
  (message  <span class="org-string">"Output of the first hook function"</span>))

( <span class="org-keyword">defun</span>  <span class="org-function-name">hook-function-2</span> ()
  (message  <span class="org-string">"Output of the second hook function"</span>))


(add-hook 'my-example-hook 'hook-function-1)
(add-hook 'my-example-hook 'hook-function-2)
</pre>
</div>

 <p>
Now, if we inspect  <code>my-example-hook</code> (with  <code>C-h v my-example-hook</code>), we see:
</p>

 <p>
 <code>my-example-hook’s value is (hook-function-2 hook-function-1)</code>
</p>

 <p>
Now we can run the hook with the  <code>run-hooks</code> function.
</p>

 <div class="org-src-container">
 <pre class="src src-emacs-lisp">(run-hooks 'my-example-hook)
</pre>
</div>


 <p>
Which prints the following to the messages buffer:
</p>

 <pre class="example">
Output of the second hook function
Output of the first hook function
</pre>



 <p>
There are three key components to pay attention to in this example:
</p>
 <ol class="org-ol"> <li>The hook variable  <code>my-example-hook</code>. We use  <code>add-hook</code> to populate this variable with hook functions.</li>
 <li>The hook functions  <code>hook-function-1</code> and  <code>hook-function-2</code>. These functions, intended for use in a normal hook, take no arguments.</li>
 <li>The function that runs the hook; in this case  <code>run-hooks</code>. There are a few different functions for running hooks. The  <code>run-mode-hooks</code> function, for example, is specialized to the case of running mode hooks, or hooks that are associated with initializing a mode (e.g.  <code>prog-mode-hook</code>).</li>
</ol> <p>
There's nothing especially unique about any of these components. We assign the variable in (1) a name ending in  <code>-hook</code> by convention, but it works the same with any name. The hook functions defined in (2) are normal functions; the one noteworthy point is that they  <i>take no arguments</i>. The function in (3) is a built-in standard function in Emacs Lisp designed for running hook functions.
</p>

 <div class="org-center">

 <figure id="org5766bec"> <img src="./figures/20231217-emacs-hooks/hooks-diagram-2.png" alt="Hand-drawn diagram: add-hook adds no-argument hook functions to a hook variable that run-hooks calls in sequence"></img> <figcaption> <span class="figure-number">Figure 2: </span>Diagram of the basic process of working with normal hooks</figcaption></figure></div>
</div>
</div>
</div>

 <div id="outline-container-org10d8b23" class="outline-2">
 <h2 id="org10d8b23">Mode Hooks</h2>
 <div class="outline-text-2" id="text-org10d8b23">
 <p>
Hooks are most commonly encountered in the context of modes. Modes generally define hooks to which users can add functions that will be called at the end of the mode's initialization. For example, I wanted to display line numbers whenever I was in a buffer with code, so I have the following line in my config:
</p>

 <div class="org-src-container">
 <pre class="src src-emacs-lisp">(add-hook 'prog-mode-hook 'display-line-numbers-mode)
</pre>
</div>

 <p>
Inspecting the hook shows:
</p>

 <blockquote>
 <p>
prog-mode-hook is a variable defined in ‘prog-mode.el’.
</p>

 <p>
Its value is (outline-minor-mode display-line-numbers-mode)
Original value was nil
</p>

 <p>
Normal hook run when entering programming modes.
</p>

 <p>
This variable may be risky if used as a file-local variable.
You can customize this variable.
Probably introduced at or before Emacs version 24.1.
</p>
</blockquote>

 <p>
and, indeed, when I open an e.g. Python buffer, line numbers appear as desired.
</p>
</div>
</div>
 <div id="outline-container-org818eec5" class="outline-2">
 <h2 id="org818eec5">Appendix: Hooks in use-package</h2>
 <div class="outline-text-2" id="text-org818eec5">
 <p>
I use  <code>use-package</code> for managing my emacs packages.  <code>use-package</code> declarations allow users to pass a  <code>:hooks</code> option in the package declaration in order to add functions to hooks. Hooks can be configured in  <code>use-package</code> by defining a cons cell as follows.
</p>

 <div class="org-src-container">
 <pre class="src src-emacs-lisp">( <span class="org-keyword">use-package</span> package-name
   <span class="org-builtin">:hook</span>
  ('mode-name . 'function-to-add-to-hook)
  )
</pre>
</div>

 <p>
Note that we do  <i>not</i> refer to  <code>mode-name-hook</code> in the hook configuration.  <code>use-package</code> adds the  <code>-hook</code> automatically by default. The above will add  <code>function-to-add-to-hook</code> to  <code>mode-name-hook</code>.
</p>
</div>
</div>
 <div id="outline-container-org09c7f71" class="outline-2">
 <h2 id="org09c7f71">Further Reading</h2>
 <div class="outline-text-2" id="text-org09c7f71">
 <ul class="org-ul"> <li> <a href="https://gitlab.com/dliden/coffeemacs">My Emacs config</a>. This has not, admittedly, been structured for broad consumption, but with a little searching you can find how I've configured some hooks. In particular,  <a href="https://gitlab.com/dliden/coffeemacs/-/blob/master/orgconfig.el?ref_type=heads#L219">here</a> is my  <code>org-tree-slide</code> configuration, which I mentioned at the beginning.</li>
 <li> <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Hooks.html">Emacs Docs</a>, which go into some more detail on abnormal hooks among other topics.</li>
</ul></div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20231217-emacs-hooks.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20231217-emacs-hooks.html</guid>
  <pubDate>Sun, 17 Dec 2023 08:00:00 +0000</pubDate>
</item>
<item>
  <title>YASnippet for Prompt Templates for Chatgpt-Shell</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">YASnippet for Prompt Templates for Chatgpt-Shell</h1>
 <p class="subtitle" role="doc-subtitle">July 9, 2023</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#orgf42d65d">Introduction</a></li>
 <li> <a href="#org3fb9db3">Setting up ChatGPT Shell</a></li>
 <li> <a href="#org6a2edf8">YASnippet</a>
 <ul> <li> <a href="#orgbda0494">Defining a Snippet</a></li>
 <li> <a href="#org9cd8049">Using a Snippet</a></li>
 <li> <a href="#org28c7bce">Inserting the Last Item in the Kill Ring</a></li>
</ul></li>
 <li> <a href="#orga804427">Next Steps</a></li>
</ul></div>
</nav> <div id="outline-container-orgf42d65d" class="outline-2">
 <h2 id="orgf42d65d">Introduction</h2>
 <div class="outline-text-2" id="text-orgf42d65d">
 <div class="preview" id="org6354c65">
 <p>
The wonderful  <a href="https://github.com/xenodium/chatgpt-shell">chatgpt-shell</a> package by  <a href="https://github.com/xenodium">Xenodium</a> lets you interact with the gpt-3.5 and gpt-4
APIs in emacs via a handy shell built on top of  <code>comint-mode</code>. It also integrates
well with  <code>org-mode</code>.
</p>

 <p>
I find that I tend to re-use a few prompt patterns for specific tasks. Yasnippet provides a great
way to create prompt  <i>templates</i> made up of some fixed component with placeholders
for user input. I can easily insert these prompt templates when working with
 <code>chatgpt-shell</code> to gain easy access to reusable, task-specific prompts. This post
describes how to start using Yasnippet for prompt templates for use with
 <code>chatgpt-shell</code>.
</p>

</div>
</div>
</div>
 <div id="outline-container-org3fb9db3" class="outline-2">
 <h2 id="org3fb9db3">Setting up ChatGPT Shell</h2>
 <div class="outline-text-2" id="text-org3fb9db3">
 <p>
First of all, if you haven't already tried  <code>chatgpt-shell</code>, it's worth taking a
few minutes to set up and try out. If you live in emacs, you'll probably prefer
 <code>chatgpt-shell</code> to the chatgpt web interface.
</p>

 <p>
You can find the installation instructions  <a href="https://github.com/xenodium/chatgpt-shell#install">here</a>. I use straight.el for package
management, and here is my configuration:
</p>

 <div class="org-src-container">
 <pre class="src src-emacs-lisp">( <span class="org-keyword">use-package</span> shell-maker
   <span class="org-builtin">:straight</span> ( <span class="org-builtin">:host</span> github  <span class="org-builtin">:repo</span>  <span class="org-string">"xenodium/chatgpt-shell"</span>  <span class="org-builtin">:files</span> ( <span class="org-string">"shell-maker.el"</span>)
                    <span class="org-builtin">:branch</span>  <span class="org-string">"main"</span>))

( <span class="org-keyword">use-package</span> chatgpt-shell
   <span class="org-builtin">:after</span> (shell-maker)
   <span class="org-builtin">:straight</span> ( <span class="org-builtin">:host</span> github  <span class="org-builtin">:repo</span>  <span class="org-string">"xenodium/chatgpt-shell"</span>  <span class="org-builtin">:files</span> ( <span class="org-string">"chatgpt-shell.el"</span>)
                    <span class="org-builtin">:branch</span>  <span class="org-string">"main"</span>)
   <span class="org-builtin">:config</span>
  ( <span class="org-keyword">setq</span> chatgpt-shell-openai-key
      ( <span class="org-keyword">lambda</span> ()
        (auth-source-pick-first-password  <span class="org-builtin">:host</span>  <span class="org-string">"api.openai.com"</span>))))

( <span class="org-keyword">use-package</span> ob-chatgpt-shell
   <span class="org-builtin">:straight</span> ( <span class="org-builtin">:host</span> github  <span class="org-builtin">:repo</span>  <span class="org-string">"xenodium/chatgpt-shell"</span>  <span class="org-builtin">:files</span> ( <span class="org-string">"ob-chatgpt-shell.el"</span>)
                    <span class="org-builtin">:branch</span>  <span class="org-string">"main"</span>)
   <span class="org-builtin">:ensure</span> t )
</pre>
</div>

 <p>
 <code>chatgpt-shell</code> is built on  <code>shell-maker</code>, which is "a way to create shells for any
service (local or cloud)."  <code>ob-chatgpt-shell</code> provides a way to interact with
 <code>chatgpt-shell</code> via org babel source blocks. For more details on these, read the
 <a href="https://github.com/xenodium/chatgpt-shell">documentation</a> (and consider  <a href="https://github.com/sponsors/xenodium">sponsoring</a> Xenodium).
</p>
</div>
</div>
 <div id="outline-container-org6a2edf8" class="outline-2">
 <h2 id="org6a2edf8">YASnippet</h2>
 <div class="outline-text-2" id="text-org6a2edf8">
 <p>
 <a href="https://github.com/joaotavora/yasnippet">YASnippet</a> is a template system for emacs. It is very powerful, and I'm only
familiar with a small fraction of its capabilities. But when I work with
ChatGPT in other systems, I almost always use some form of templating
system. What does that mean? Suppose I'm working on some kind of text
summarization system. On the one hand, I could write a bunch of separate prompts
of the form:
</p>

 <blockquote>
 <p>
Summarize the following text:
<some text>
</p>

 <p>
Summarize the following text:
<some more text>
</p>

 <p>
Summarize the following text:
<even more text>
</p>
</blockquote>

 <p>
But the instruction, "Summarize the following text," is the same each time. So
I'd rather put that in a template, which I can fill in as many times as needed
with the part of the prompt that actually changes: the prompt to summarize.
</p>

 <p>
This might look like:
</p>

 <div class="org-src-container">
 <pre class="src src-emacs-lisp">
( <span class="org-keyword">defun</span>  <span class="org-function-name">summary_template</span> (text_to_summarize)
  ( <span class="org-keyword">interactive</span>  <span class="org-string">"sText to Summarize: "</span>)
  (concat  <span class="org-string">"Summarize the following text:\n"</span> text_to_summarize))

(print (summary_template  <span class="org-string">"Some text"</span>))
(print (summary_template  <span class="org-string">"Some more text"</span>))
(print (summary_template  <span class="org-string">"Even more text"</span>))
</pre>
</div>

 <pre class="example">

"Summarize the following text:
Some text"

"Summarize the following text:
Some more text"

"Summarize the following text:
Even more text"
</pre>


 <p>
YASnippet provides an easy way for us to define and populate templates for use
in  <code>chatgpt-shell</code> buffers.
</p>
</div>
 <div id="outline-container-orgbda0494" class="outline-3">
 <h3 id="orgbda0494">Defining a Snippet</h3>
 <div class="outline-text-3" id="text-orgbda0494">
 <p>
First, you'll need to  <a href="https://github.com/joaotavora/yasnippet/blob/master/README.mdown#installation">install YASnippet</a>.
</p>

 <p>
We can define a new snippet with  <code>M-x yas-new-snippet</code>. This will open a new
buffer for defining out snippet.
</p>

 <div class="org-center">

 <figure id="org48bfa67"> <img src="./figures/20230709-yasnippet-chatgpt-shell/yas-new-snippet.png" alt="Empty Emacs YASnippet new-snippet buffer with mode, name, key, and -- header template lines"></img> <figcaption> <span class="figure-number">Figure 1: </span>YASnippet new snippet interface</figcaption></figure></div>

 <p>
In this example, I'm only going to show how to make templates with text and
placeholders. YASnippet is incredibly powerful and supports highly complex
templates;  <a href="https://joaotavora.github.io/yasnippet/">read the documentation</a> if you want to explore further. For now, let's
just replicate the summarization template.
</p>

 <p>
We'll mostly use  <i>tab stop fields</i> and  <i>placeholder fields</i> when building our
templates. You can read more about them, and about more advanced templating,
 <a href="https://joaotavora.github.io/yasnippet/snippet-development.html">here</a>.
</p>

 <p>
Here's what a summarization snippet might look like:
</p>

 <pre class="example">
# -*- mode: snippet -*-
# name: Concise Summary
# key: gptsum
# contributor: Daniel Liden
# --
<text>$1</text>

Provide a concise summary of the above text within <text> tags.
$0
</pre>

 <p>
The  <code>$1</code> and  <code>$0</code> are called  <i>tab stop fields</i>. When inserting the snippet with
e.g.  <code>yas-insert-snippet</code> or by triggering  <a href="https://joaotavora.github.io/yasnippet/snippet-expansion.html">snippet expansion</a>, you can
interactively  <code>TAB</code> and  <code>S-TAB</code> back and forth through the various tab stop fields,
filling them in with whatever you want. In this case, you could type/yank a text
to summarize in the  <code>$1</code> position.
</p>

 <p>
 <code>$0</code> has a special meaning: it is the  <i>exit point</i>, the place the cursor ends up
after completing all of the other tab stop fields.
</p>

 <p>
If you want a default value for a given completion field, you can use a
 <i>placeholder</i>, which is formatted as  <code>${N:default value}</code>. We might modify the above
snippet, for example, to say:
</p>

 <pre class="example">
# -*- mode: snippet -*-
# name: Concise Summary
# key: gptsum
# contributor: Daniel Liden
# --
<text>${1:The user forgot to include text to summarize. Remind them!}</text>

Provide a concise summary of the above text within <text> tags.
$0
</pre>

 <p>
Once you've defined the snippet in the  <code>yas-new-snippet</code> buffer, you can save it
with  <code>C-c C-c</code>. You will then be prompted to choose a "table." This essentially
means specifying the emacs mode with which you'd like the snippet to be
associated. In this case, for  <code>chatgpt-shell</code>, it's  <code>chatgpt-shell-mode</code>. Specifying
the mode ensures the snippet will be available when you're in
 <code>chatgpt-shell-mode</code>. You will also be asked whether you want to save the snippet;
go ahead and do so if you intend to use it in the future.
</p>

 <p>
To modify a snippet, you can use  <code>yas-visit-snippet-file</code>, make changes, and again
go through the saving dialogue with  <code>C-c C-c</code>.
</p>
</div>
</div>

 <div id="outline-container-org9cd8049" class="outline-3">
 <h3 id="org9cd8049">Using a Snippet</h3>
 <div class="outline-text-3" id="text-org9cd8049">
 <p>
Note that, in the example snippets above, I've defined a  <code>key</code>: this is for
 <a href="https://joaotavora.github.io/yasnippet/snippet-expansion.html">snippet expansion</a> (follow the link for more details). With my configuration, in
a  <code>chatgpt-shell-mode</code> buffer, I can type  <code>gptsum</code> followed by  <code>TAB</code> to insert this
snippet. Alternately, I can select from all available snippets with  <code>M-x
yas-insert-snippet</code>.
</p>

 <p>
Upon inserting the snippet, my cursor will be at the first tab stop. I can then
insert whatever text I want. Upon hitting  <code>TAB</code>, the cursor will jump to the next
tab stop. In this case, there was only one, so the cursor will jump to the  <code>$0</code>
position at the end of the prompt.
</p>

 <div class="org-center">

 <figure id="org0d80676"> <img src="./figures/20230709-yasnippet-chatgpt-shell/text_summarize_snippet.gif" alt="Animation of inserting a YASnippet summary template into an empty chatgpt-shell buffer in Emacs"></img> <figcaption> <span class="figure-number">Figure 2: </span>Inserting a Snippet</figcaption></figure></div>

 <p>
With multiple tab stops (e.g.  <code>$1</code>,  <code>$2</code>, etc.), pressing  <code>TAB</code> multiple times would
move forward through each position, allowing you to fill in the desired
text.  <code>S-TAB</code> enables you to move backward through the tab stops.
</p>
</div>
</div>
 <div id="outline-container-org28c7bce" class="outline-3">
 <h3 id="org28c7bce">Inserting the Last Item in the Kill Ring</h3>
 <div class="outline-text-3" id="text-org28c7bce">
 <p>
We're unlike to ever need to summarize text that we manually type into a
 <code>chatgpt-shell</code>. But we might want to copy some text to the kill ring and ask for
a summary, or copy some code and ask for an explanation. We can write a template
to accomplish this.
</p>

 <p>
We'll use one more advanced feature of  <code>YASnippet</code> to accomplish this: we can
embed Emacs-lisp code in a snippet by enclosing it in backticks ( <code>``</code>).
</p>

 <p>
Here's a snippet for explaining code by pasting (yanking) the most recent text
from the kill ring:
</p>

 <pre class="example">
# key: gptce
# name: code-explainer
# --
Explain the following code:
`(yank)`

In particular:
- Step-by-step, what does it do?
- What are the parameters?
- Are there any other noteworthy features of this code?

Answer concisely.
$0
</pre>

 <p>
To use this template, you would first copy or kill some code from a buffer, then
navigate to your  <code>chatgpt-shell</code> buffer, then insert the snippet. The  <code>`(yank)`</code>
part will automatically be replaced by the copied code.
</p>



 <div class="org-center">

 <figure id="orga7c6f8f"> <img src="./figures/20230709-yasnippet-chatgpt-shell/code_explain.gif" alt="Animation of a chatgpt-shell code-explainer snippet yanking Python code from the kill ring in Emacs"></img> <figcaption> <span class="figure-number">Figure 3: </span>Inserting from the Kill Ring</figcaption></figure></div>
</div>
</div>
</div>
 <div id="outline-container-orga804427" class="outline-2">
 <h2 id="orga804427">Next Steps</h2>
 <div class="outline-text-2" id="text-orga804427">
 <p>
There's a lot more to explore here. YASnippet is a very powerful templating
system, and I've only scratched the surface of the ways to use it for developing
useful prompt templates for  <code>chatgpt-shell</code> (and I haven't tried any for the org
babel integration yet). Read the YASnippet manual, write some new snippets, and
let me know what you come up with!
</p>
</div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20230709-yasnippet-chatgpt-shell.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20230709-yasnippet-chatgpt-shell.html</guid>
  <pubDate>Sun, 09 Jul 2023 08:00:00 +0000</pubDate>
</item>
<item>
  <title>Writing on AI and Postgres</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Writing on AI and Postgres</h1>
 <p class="subtitle" role="doc-subtitle">June 1, 2023</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#orgb979e39">Background</a></li>
 <li> <a href="#org4ae3344">Making a Production LLM Prompt for Text-to-SQL Translation</a></li>
 <li> <a href="#orgd7faee3">Make ChatGPT Stop Chatting and Start Writing SQL</a></li>
 <li> <a href="#org2689b4d">LLM Prompt Testing Part 1: Comparing ChatGPT to Codex</a></li>
 <li> <a href="#orga88dfb7">Use LLMs with Other Tools for Better SQL Translation</a></li>
 <li> <a href="#orgfc9174e">Vector Similarity Search in Postgres with bit.io and pgvector</a></li>
 <li> <a href="#org7961ebb">Pre-Classify Tasks for Better ChatGPT Completions</a></li>
</ul></div>
</nav> <div id="outline-container-orgb979e39" class="outline-2">
 <h2 id="orgb979e39">Background</h2>
 <div class="outline-text-2" id="text-orgb979e39">
 <div class="preview" id="org2ebb421">
 <p>
Since this start of this year, I've been working on and writing about AI tools
for working with Postgres databases. Most of this work has involved finding
different ways to integrate ChatGPT (and previously Codex) with other tools and
workflows. I wanted to collect and share some of that writing here, as it's
related to a lot of the other things I write about on my personal blog.
</p>

</div>
</div>
</div>


 <div id="outline-container-org4ae3344" class="outline-2">
 <h2 id="org4ae3344"> <a href="https://innerjoin.bit.io/making-a-production-llm-prompt-for-text-to-sql-translation-b798b6e94783">Making a Production LLM Prompt for Text-to-SQL Translation</a></h2>
 <div class="outline-text-2" id="text-org4ae3344">
 <p>
This article introduces our work on AI+databases. Our original goal was simple:
make a great natural language to SQL translation system. This article talks
about some of the challenges and opportunities in that area and introduces a
 <a href="https://github.com/bitdotioinc/pg-text-query/tree/liden/test_suite/playground">Streamlit app</a> we put together for testing text-to-SQL translation prompts.
</p>
</div>
</div>
 <div id="outline-container-orgd7faee3" class="outline-2">
 <h2 id="orgd7faee3"> <a href="https://innerjoin.bit.io/make-chatgpt-stop-chatting-and-start-writing-sql-fd5560049ae4">Make ChatGPT Stop Chatting and Start Writing SQL</a></h2>
 <div class="outline-text-2" id="text-orgd7faee3">
 <p>
I wrote this article after the ChatGPT API was released. We started by using the
Codex code completion models but the much lower price of  <code>gpt-3.5-turbo</code> made a
compelling case for switching to ChatGPT. This proved to be a timely article:
shortly after we published this article, OpenAI announced that they were
discontinuing the Codex model. This article provides a useful guide for using
ChatGPT to get much of the same functionality.
</p>
</div>
</div>
 <div id="outline-container-org2689b4d" class="outline-2">
 <h2 id="org2689b4d"> <a href="https://innerjoin.bit.io/llm-sql-translation-prompt-testing-part-1-comparing-chatgpt-to-codex-78da57213ebe">LLM Prompt Testing Part 1: Comparing ChatGPT to Codex</a></h2>
 <div class="outline-text-2" id="text-org2689b4d">
 <p>
This article presents a simple suite of text-to-SQL translations and compares
the performance of the Codex and ChatGPT models.
</p>
</div>
</div>
 <div id="outline-container-orga88dfb7" class="outline-2">
 <h2 id="orga88dfb7"> <a href="https://innerjoin.bit.io/use-llms-with-other-tools-for-better-sql-translation-21e35de8f03e">Use LLMs with Other Tools for Better SQL Translation</a></h2>
 <div class="outline-text-2" id="text-orga88dfb7">
 <blockquote>
 <p>
The Unix Philosophy considers text streams a universal interface, and emphasizes
the composability of processes that act on text streams. This is what LLMs do:
they act on and return text streams.
</p>
</blockquote>

 <p>
This article urges readers to think of how LLMs might interface with other
tools. As shown by projects such as LangChain and AutoGPT, their usefulness is
multiplied when they are integrated with other projects and tools, not just used
for chatting.
</p>
</div>
</div>
 <div id="outline-container-orgfc9174e" class="outline-2">
 <h2 id="orgfc9174e"> <a href="https://innerjoin.bit.io/vector-similarity-search-in-postgres-with-bit-io-and-pgvector-c58ac34f408b">Vector Similarity Search in Postgres with bit.io and pgvector</a></h2>
 <div class="outline-text-2" id="text-orgfc9174e">
 <p>
In this article, I briefly show how to use the  <code>pgvector</code> Postgres extension for
semantic search. I exported all of bit.io's docs to a Postgres database, created
vector embeddings from the docs, and showed how to use  <code>pgvector</code> to query the
embeddings. Then I used ChatGPT to generate summaries from the results of
semantic search applied to the docs.
</p>
</div>
</div>
 <div id="outline-container-org7961ebb" class="outline-2">
 <h2 id="org7961ebb"> <a href="https://innerjoin.bit.io/pre-classify-tasks-for-better-chatgpt-completions-f197ad01618c">Pre-Classify Tasks for Better ChatGPT Completions</a></h2>
 <div class="outline-text-2" id="text-org7961ebb">
 <p>
In my most recent article, I described how we used a two-step process to
generate API calls using ChatGPT. We first used ChatGPT to identify the  <i>task</i>
that the user wanted to complete, and then we combined the user prompt with a
task-specific prompt to generate API call completions. The task-specific prompt
left much less room for error and resulted in better completion quality.
</p>
</div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20230428-ai-db-writing.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20230428-ai-db-writing.html</guid>
  <pubDate>Thu, 01 Jun 2023 08:00:00 +0000</pubDate>
</item>
<item>
  <title>Using the ChatGPT API with Julia Part 2: Defining a Chat Struct</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Using the ChatGPT API with Julia Part 2: Defining a Chat Struct</h1>
 <p class="subtitle" role="doc-subtitle">March 10, 2023</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#org99696e5">Defining the Struct</a></li>
 <li> <a href="#orga804fa1">Defining the function</a></li>
 <li> <a href="#orgaae08bb">Giving it a Try</a></li>
 <li> <a href="#org8459b16">What's next?</a></li>
</ul></div>
</nav> <div class="preview" id="org7e1d0f0">
 <p>
One of the things that makes working with the ChatGPT API a little different
from working with, e.g., the  <code>davinci-text-003</code> model api is the need to maintain
the history of a given chat session. A Julia  <code>Struct</code> containing the chat
history, coupled with a function that acts on that Struct, provides a good way
to work with the ChatGPT API.
</p>

 <p>
For the basics of working with the ChatGPT API, check out  <a href="20230303-chatgpt-julia.html">part 1</a>.
</p>

</div>

 <div id="outline-container-org99696e5" class="outline-2">
 <h2 id="org99696e5">Defining the Struct</h2>
 <div class="outline-text-2" id="text-org99696e5">
 <p>
A  <code>struct</code>, also referred to as a  <a href="https://docs.julialang.org/en/v1/manual/types/#Composite-Types">composite type</a>, is "a collection of named
fields, an instance of which can be treated as a single value." By default,
structs are immutable: they can't be modified after construction. This doesn't
work for our use case because want to keep adding messages as the chat
continues. So we'll use a  <code>mutable struct</code>.
</p>

 <p>
One obvious question: what should the named fields of the struct be? Should the
struct define all of the behavior of the model (e.g. model choice, parameters
such as  <code>temperature</code> and  <code>max_tokens</code>, etc.)? Or should it narrowly contain the
message comprising the chat?
</p>

 <p>
I think the latter approach makes the most sense. It's possible to change model
parameters, and even the model itself, mid-chat. They are features of  <i>what we
are doing to the chat</i>, not of the chat itself.
</p>

 <p>
With that in mind, here is a possible approach to a  <code>struct</code> for ChatGPT.
</p>

 <div class="org-src-container">
 <pre class="src src-julia"> <span class="org-string">"""
    struct Chat

Represents a conversation between a user and a chatbot powered by OpenAI's GPT.

# Fields

- `messages::Array{Dict{String, String}}`: An array of dictionaries representing the chat messages.

# Constructors

- `Chat(system_message::String="You are a helpful assistant")`: Create a new `Chat` object with a single system message.

# Example

```julia
chat = Chat("You are a helpful assistant.")
```
This creates a new Chat object with a single message representing the system message "You are a helpful assistant.".
"""</span>
 <span class="org-keyword">mutable struct</span>  <span class="org-type">Chat</span>
    messages:: <span class="org-type">Array</span>{Dict{String, String}}
    
     <span class="org-keyword">function</span>  <span class="org-function-name">Chat</span>(system_message= <span class="org-constant">nothing</span>)
         <span class="org-keyword">if</span> isnothing(system_message)
            system_message =  <span class="org-string">"You are a helpful assistant"</span>
         <span class="org-keyword">end</span>
        messages = [Dict( <span class="org-string">"role"</span> =>  <span class="org-string">"system"</span>,  <span class="org-string">"content"</span> => system_message)]
        new(messages)
     <span class="org-keyword">end</span>
 <span class="org-keyword">end</span>
</pre>
</div>

 <p>
This struct includes an  <i>inner constructor</i>.  <a href="https://docs.julialang.org/en/v1/manual/constructors/#man-inner-constructor-methods">Inner Constructor Methods</a> allow for
the construction of self-referential objects. In this case, we want to be able
to Initialize an instance of  <code>Chat</code> with just the system message: we don't want
to require the user to provide the whole  <code>messages</code> array. That's where the
self-referential part comes in. The inner constructor method takes an argument,
 <code>system_message</code>, nests it in a properly-formatted array of dictionaries, and,
using the  <code>new</code> function, creates a new instance of the  <code>Chat</code> struct with the
 <code>messages</code> array constructed from the  <code>system_message</code>.
</p>

 <p>
We can now make a new chat instance, initialized with a system message, with:
</p>

 <div class="org-src-container">
 <pre class="src src-julia">julia_helper = Chat( <span class="org-string">"You are a helpful assistant who knows a lot about writing Julia code"</span>)
</pre>
</div>

 <pre class="example">
Chat([Dict("role" => "system", "content" => "You are a helpful assistant who knows a lot about writing Julia code")])
</pre>


 <p>
Now that we have a method for keeping track of the chat history, we need to be
able to act on it. For that, we'll define a function.
</p>
</div>
</div>

 <div id="outline-container-orga804fa1" class="outline-2">
 <h2 id="orga804fa1">Defining the function</h2>
 <div class="outline-text-2" id="text-orga804fa1">
 <p>
The purpose of this function is to:
</p>
 <ol class="org-ol"> <li>Get a prompt from the user</li>
 <li>Append that prompt to a  <code>Chat</code> instance's  <code>messages</code> array</li>
 <li>Query the ChatGPT API with the  <code>messages</code> array, possibly with some parameters
specifying e.g. the specific model to use, temperature, etc.</li>
 <li>Append the API response message to the  <code>Chat</code> instance's  <code>messages</code> array</li>
 <li>Return the API response.</li>
</ol> <p>
This function acts on the  <code>Chat</code> type. It modifies an instance of  <code>Chat</code> in
place. Here's the function:
</p>

 <div class="org-src-container">
 <pre class="src src-julia"> <span class="org-string">"""
    chat!(chat, message::String, api_key=ENV["OPENAI_API_KEY"]; kwargs...)

Add a new message to the chat history and get a response from the OpenAI GPT-3 API.

# Arguments

- `chat`: A `Chat` object representing the chat history.
- `message`: A string representing the user's message.
- `api_key::String=ENV["OPENAI_API_KEY"]`: Your OpenAI API key. If not provided, the function will attempt to get it from the `OPENAI_API_KEY` environment variable.
- `kwargs...`: Any additional keyword arguments to pass as part of the API request body.

# Returns

A string representing the response from the chatbot.

# Example

```julia
chat = Chat("You are a helpful assistant")
response = chat!(chat, "How are you?")
```

This adds a new message to the Chat object chat, representing the user's message "How are you?", and gets a response from the OpenAI ChatGPT API. The response from the chatbot is returned as a string in the response variable.
"""</span>
 <span class="org-keyword">function</span>  <span class="org-function-name">chat!</span>(chat:: <span class="org-type">Chat</span>, message:: <span class="org-type">String</span>, api_key=ENV[ <span class="org-string">"OPENAI_API_KEY"</span>]; kwargs...)
     <span class="org-keyword">if</span> isnothing(api_key)
        error( <span class="org-string">"API key is required"</span>)
     <span class="org-keyword">end</span>
    headers = HTTP.Headers([
         <span class="org-string">"Authorization"</span> =>  <span class="org-string">"Bearer $api_key"</span>,
         <span class="org-string">"Content-Type"</span> =>  <span class="org-string">"application/json"</span>,
    ])

    formatted_query = Dict( <span class="org-string">"role"</span> =>  <span class="org-string">"user"</span>,  <span class="org-string">"content"</span> => message)

    messages = push!(chat.messages, formatted_query)

     <span class="org-comment-delimiter"># </span> <span class="org-comment">Merge the default and keyword parameters
</span>    params = merge(Dict( <span class="org-string">"model"</span> =>  <span class="org-string">"gpt-3.5-turbo"</span>,  <span class="org-string">"messages"</span> => messages), kwargs)

     <span class="org-comment-delimiter"># </span> <span class="org-comment">Convert the parameters to JSON
</span>    body = json(params)

     <span class="org-comment-delimiter"># </span> <span class="org-comment">Make a POST request to the OpenAI API endpoint with the query as data
</span>    response = HTTP.post(
         <span class="org-string">"https://api.openai.com/v1/chat/completions"</span>,
        headers,
        body;
        verbose =  <span class="org-constant">false</span>,
    )

     <span class="org-comment-delimiter"># </span> <span class="org-comment">Parse the response body as JSON
</span>    result = JSON.parse(String(response.body))

     <span class="org-comment-delimiter"># </span> <span class="org-comment">Append the response to chat.messages
</span>    push!(chat.messages, result[ <span class="org-string">"choices"</span>][1][ <span class="org-string">"message"</span>])

     <span class="org-comment-delimiter"># </span> <span class="org-comment">Return the text field of the result as a string
</span>     <span class="org-keyword">return</span> result[ <span class="org-string">"choices"</span>][1][ <span class="org-string">"message"</span>][ <span class="org-string">"content"</span>]
 <span class="org-keyword">end</span>
</pre>
</div>

 <p>
A quick note about the function name: According to the  <a href="https://docs.julialang.org/en/v1/manual/style-guide/#bang-convention">Julia style guide</a>, we append  <code>!</code>
to the names of functions that modify their arguments.  <a href="https://docs.julialang.org/en/v1/manual/style-guide/#Write-functions-with-argument-ordering-similar-to-Julia-Base">Furthermore</a>, inputs that
are mutated go before inputs that are not mutated in a function's argument
list. The  <code>chat</code> function follows both of these conventions.
</p>
</div>
</div>
 <div id="outline-container-orgaae08bb" class="outline-2">
 <h2 id="orgaae08bb">Giving it a Try</h2>
 <div class="outline-text-2" id="text-orgaae08bb">
 <p>
So, does it work? Let's try it out.
</p>

 <div class="org-src-container">
 <pre class="src src-julia">chat!(julia_helper,  <span class="org-string">"What are the main differences between a Julia Struct and a Python Class?"</span>)
</pre>
</div>

 <pre class="example">
""Both Julia `struct` and Python `class` are used for creating custom data types, but there are some differences between them:\n\n1. **Type stability:** One of the most significant differences is that Julia `structs` have a static and immutable type, which makes them more type-stable than Python `classes`. In contrast, Python classes are more dynamic, meaning that their attributes can be modified at runtime.\n\n2. **Performance:** In general, Julia `structs` have better performance than Python `classes` due to its type-stability, just-in-time (JIT) compilation, and parallel processing.\n\n3. **Syntax:** The syntax for defining a Julia `struct` is `struct Name{T<:AbstractType} a::T b::Int end`, while in Python, you define a `class` with `class MyClass: def __init__(self, a, b): self.a = a self.b = b`. \n\n4. **Inheritance:** Both Julia and Python support inheritance, but they have different syntax and behavior. In Julia, you use the keyword ` <: ` to specify that a `struct` is a subtype of another `struct`. In Python, you use parentheses after the class name to indicate which class to inherit from.\n\n5. **Typing:** Julia uses type annotations to specify the type of variables, while Python follows the duck typing philosophy, which means that the type of a variable is determined at runtime based on its behavior.\n\nIn summary, while both Julia `structs` and Python `classes` are flexible and powerful tools for creating custom data types, the main differences lie in their type stability, performance, syntax, inheritance, and typing.""
</pre>


 <p>
And does it "remember" earlier parts of the conversation correctly?
</p>

 <div class="org-src-container">
 <pre class="src src-julia">chat!(julia_helper,  <span class="org-string">"I only have the attention span for Twitter. Summarize in 280 characters."</span>)
</pre>
</div>

 <pre class="example">
"Julia structs & Python classes are used for custom data types but differ in: \n1. Type stability: Julia is static, immutable; Python is dynamic.\n2. Performance: Julia > Python due to type-stability, JIT compilation & parallel processing.\n3. Syntax: structs use \"struct Name{T} a::T end;\" & classes use \"class MyClass: def __init__(self):\".\n4. Inheritance: Julia uses \"<:\" to specify subtypes; Python uses parentheses for inheritance.\n5. Typing: Julia uses type annotation; Python uses duck-typing."
</pre>



 <p>
Well, it's a little longer than I asked for. But clearly we successfully sent
the message history in the second API request.
</p>
</div>
</div>
 <div id="outline-container-org8459b16" class="outline-2">
 <h2 id="org8459b16">What's next?</h2>
 <div class="outline-text-2" id="text-org8459b16">
 <p>
There are a few additional avenues I want to explore, in no particular order:
</p>

 <ol class="org-ol"> <li>What happens if we counterfeit a message history? That is, what if we send a
message history with fake "assistant" messages? Will the assistant mimic the
fake responses?</li>
 <li>Can we make a Julia REPL mode that gives rapid access to a ChatGPT assistant?</li>
 <li>Can we make a (private) replacement for ChatGPT Plus using the ChatGPT API?
It would likely be considerably cheaper. And doing it in Julia would be an
interesting project.</li>
 <li>Can we use the streaming output in Julia? How does that work?</li>
</ol></div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20230310-chatgpt-julia-2.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20230310-chatgpt-julia-2.html</guid>
  <pubDate>Fri, 10 Mar 2023 08:00:00 +0000</pubDate>
</item>
<item>
  <title>Using the ChatGPT API with Julia Part 1: the HTTP.jl Library</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Using the ChatGPT API with Julia Part 1: the HTTP.jl Library</h1>
 <p class="subtitle" role="doc-subtitle">March 4, 2023</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#orgc6ce554">Introduction</a></li>
 <li> <a href="#org1f1922f">curl Example</a></li>
 <li> <a href="#orga203837">Julia example</a></li>
 <li> <a href="#org083220e">A little more detail about sending messages</a></li>
 <li> <a href="#org4f7195b">Next Up…</a></li>
</ul></div>
</nav> <div id="outline-container-orgc6ce554" class="outline-2">
 <h2 id="orgc6ce554">Introduction</h2>
 <div class="outline-text-2" id="text-orgc6ce554">
 <div class="preview" id="org5f2b433">
 <p>
This brief post shows the basics of using the Julia  <code>HTTP</code> library to interact
with the OpenAI ChatGPT API, which was made public a few days ago. This post
will only include the minimum necessary detail for getting started with the
API. Future posts will go into a little more detail on how to send message
histories and engage more interactively with the API.
</p>

</div>
</div>
</div>
 <div id="outline-container-org1f1922f" class="outline-2">
 <h2 id="org1f1922f">curl Example</h2>
 <div class="outline-text-2" id="text-org1f1922f">
 <p>
 <a href="https://platform.openai.com/docs/api-reference/chat/create">Here</a> is the API documentation on OpenAI's website. An example request with  <code>curl</code>
looks like this:
</p>

 <div class="org-src-container">
 <pre class="src src-bash">curl https://api.openai.com/v1/chat/completions  <span class="org-sh-escaped-newline">\</span>
  -H  <span class="org-string">'Content-Type: application/json'</span>  <span class="org-sh-escaped-newline">\</span>
  -H  <span class="org-string">'Authorization: Bearer YOUR_API_KEY'</span>  <span class="org-sh-escaped-newline">\</span>
  -d  <span class="org-string">'{
  "model": "gpt-3.5-turbo",
  "messages": [{"role": "user", "content": "Hello!"}]
}'</span>
</pre>
</div>
</div>
</div>

 <div id="outline-container-orga203837" class="outline-2">
 <h2 id="orga203837">Julia example</h2>
 <div class="outline-text-2" id="text-orga203837">
 <p>
And here's how we can re-create this with the Julia HTTP library:
</p>

 <div class="org-src-container">
 <pre class="src src-julia">OPENAI_API_KEY = ENV[ <span class="org-string">"OPENAI_API_KEY"</span>]

 <span class="org-keyword">using</span> HTTP
 <span class="org-keyword">using</span> JSON

headers = HTTP.Headers([
     <span class="org-string">"Authorization"</span> =>  <span class="org-string">"Bearer $OPENAI_API_KEY"</span>,
     <span class="org-string">"Content-Type"</span> =>  <span class="org-string">"application/json"</span>,
])

body = json(Dict( <span class="org-string">"model"</span> =>  <span class="org-string">"gpt-3.5-turbo"</span>,
                  <span class="org-string">"messages"</span> => [Dict( <span class="org-string">"role"</span> =>  <span class="org-string">"user"</span>,  <span class="org-string">"content"</span> =>  <span class="org-string">"Hello!"</span>)]))


response = HTTP.post(
     <span class="org-string">"https://api.openai.com/v1/chat/completions"</span>,
    headers,
    body;
    verbose =  <span class="org-constant">false</span>,
)

 <span class="org-comment-delimiter"># </span> <span class="org-comment">Parse the response body as JSON
</span>result = JSON.parse(String(response.body))
print(result)
</pre>
</div>

 <pre class="example">
Dict{String, Any}("choices" => Any[Dict{String, Any}("finish_reason" => "stop", "message" => Dict{String, Any}("role" => "assistant", "content" => "\n\nHello there! How may I be of assistance?"), "index" => 0)], "model" => "gpt-3.5-turbo-0301", "usage" => Dict{String, Any}("completion_tokens" => 12, "total_tokens" => 21, "prompt_tokens" => 9), "id" => "chatcmpl-6qMM6OmdVRZ8VtdKgKFtb7aRDYWkF", "object" => "chat.completion", "created" => 1677937010)
</pre>


 <p>
Note that  <code>OPENAI_API_KEY</code> is stored as an environment variable on my system, so I
was able to access it with  <code>OPENAI_API_KEY = ENV["OPENAI_API_KEY"]</code>.
</p>

 <p>
We can extract the completion itself from the "choices" dictionary entry.
</p>

 <div class="org-src-container">
 <pre class="src src-julia">chat_response = result[ <span class="org-string">"choices"</span>]
chat_response[1][ <span class="org-string">"message"</span>][ <span class="org-string">"content"</span>]
</pre>
</div>

 <pre class="example">
"\n\nHello there! How may I be of assistance?"
</pre>
</div>
</div>
 <div id="outline-container-org083220e" class="outline-2">
 <h2 id="org083220e">A little more detail about sending messages</h2>
 <div class="outline-text-2" id="text-org083220e">
 <p>
One of the things that makes ChatGPT useful is its ability to "remember" past
parts of a conversation. We can send whole conversations to the API using the
"messages" part of the request body.  <code>messages</code> is an array of ~Dict~s, each of
which has a "role" and a "content." There are three options for "role":
</p>
 <ol class="org-ol"> <li> <code>system</code>: sets the behavior of the assistant. The  <code>content</code> might be, for
example,  <code>you are a helpful assistant</code> or  <code>you are a very polite customer
   support agent</code> or  <code>you are a senior software engineer in a mentorship role</code>.</li>
 <li> <code>user</code>: The human interacting with ChatGPT.</li>
 <li> <code>assistant</code>: the responses from ChatGPT</li>
</ol> <p>
So we can send a more complete conversation and get some richer details in
response. For example:
</p>

 <div class="org-src-container">
 <pre class="src src-julia">messages=[Dict( <span class="org-string">"role"</span> =>  <span class="org-string">"system"</span>,  <span class="org-string">"content"</span> =>  <span class="org-string">"You are a knowledgable and helpful Julia developer."</span>),
         Dict( <span class="org-string">"role"</span> =>  <span class="org-string">"user"</span>,  <span class="org-string">"content"</span> =>  <span class="org-string">"Can you show me how to make a POST request with the HTTP library?"</span>)]

body = json(Dict( <span class="org-string">"model"</span> =>  <span class="org-string">"gpt-3.5-turbo"</span>,
                  <span class="org-string">"messages"</span> => messages))

response = HTTP.post(
     <span class="org-string">"https://api.openai.com/v1/chat/completions"</span>,
    headers,
    body;
    verbose =  <span class="org-constant">false</span>,
)

 <span class="org-comment-delimiter"># </span> <span class="org-comment">Parse the response body as JSON
</span>result = JSON.parse(String(response.body))
print(result[ <span class="org-string">"choices"</span>][1][ <span class="org-string">"message"</span>][ <span class="org-string">"content"</span>])
</pre>
</div>

 <pre class="example" id="org0f5195c">

```julia
using HTTP

# URL to POST to
url = "https://httpbin.org/post"

# Data to include in the POST request (in JSON format)
data = Dict("name" => "John", "age" => 30)
json_data = JSON.json(data)

# Headers to specify that we're sending JSON data
headers = Dict("Content-Type" => "application/json")

# Make the POST request
response = HTTP.request("POST", url, headers, json_data)

# Get the response body as a string
body = String(response.body)

# Print the response status code and body
println("Status code: $(response.status)")
println("Response body: $body")
```

In this example, we're sending a JSON object with a name and age property to https://httpbin.org/post, which is an HTTP testing service. The `headers` argument specifies that we're sending JSON data, while the `json_data` argument is the actual data we want to send.

The `HTTP.request` function is called with the POST method, the URL to POST to, the headers we want to send, and the data we want to include. The response is then captured in the `response` variable.

Finally, we extract the body of the response as a string using `String(response.body)`, and print both the status code and response body to the console.Yes, I can. Here's an example code snippet that shows how to make a POST request using the HTTP library in Julia:

```julia
using HTTP

url = "https://jsonplaceholder.typicode.com/posts"
data = "{\"title\":\"foo\",\"body\":\"bar\",\"userId\":1}"

response = HTTP.post(url, data, ["Content-Type" => "application/json"])
println(String(response.body))
```

In this example, we first specify the url of the endpoint we want to send our request to. Next, we create a string representation of the JSON data we want to send in our request. We use `HTTP.post()` to send a POST request to the specified url, including the JSON data in the request body, and with a content type header that specifies that the data is JSON (application/json). Finally, we print the response contents converted to a string by the `String()` function.
</pre>

 <p>
And if we want to send a followup referring to an earlier part in the conversation, we can extend the  <code>messages</code> array as follows:
</p>

 <div class="org-src-container">
 <pre class="src src-julia"> <span class="org-comment-delimiter"># </span> <span class="org-comment">include the assistant's previous response
</span>push!(messages, result[ <span class="org-string">"choices"</span>][1][ <span class="org-string">"message"</span>])

 <span class="org-comment-delimiter"># </span> <span class="org-comment">ask a new question referring to an earlier part of the conversation
</span>push!(messages, Dict( <span class="org-string">"role"</span> =>  <span class="org-string">"user"</span>,
                      <span class="org-string">"content"</span> =>  <span class="org-string">"Can you please provide a shorter, simpler example?"</span>))

</pre>
</div>

 <pre class="example">
4-element Vector{Dict{String, String}}:
 Dict("role" => "system", "content" => "You are a knowledgable and helpful Julia developer.")
 Dict("role" => "user", "content" => "Can you show me how to make a POST request with the HTTP library?")
 Dict("role" => "assistant", "content" => "Yes, I can. Here's an example code snippet that shows how to make a POST request using the HTTP library in Julia:\n\n```julia\nusing HTTP\n\nurl = \"https://jsonplaceholder.typicode.com/posts\"\ndata = \"{\\\"title\\\":\\\"foo\\\",\\\"body\\\":\\\"bar\\\",\\\"userId\\\":1}\"\n\nresponse = HTTP.post(url, data, [\"Content-Type\" => \"application/json\"])\nprintln(String(response.body))\n```\n\nIn this example, we first specify the url of the endpoint we want to send our request to. Next, we create a string representation of the JSON data we want to send in our request. We use `HTTP.post()` to send a POST request to the specified url, including the JSON data in the request body, and with a content type header that specifies that the data is JSON (application/json). Finally, we print the response contents converted to a string by the `String()` function.")
 Dict("role" => "user", "content" => "Can you please provide a shorter, simpler example?")
</pre>


 <p>
And then request another response:
</p>

 <div class="org-src-container">
 <pre class="src src-julia">body = json(Dict( <span class="org-string">"model"</span> =>  <span class="org-string">"gpt-3.5-turbo"</span>,
                  <span class="org-string">"messages"</span> => messages))

response = HTTP.post(
     <span class="org-string">"https://api.openai.com/v1/chat/completions"</span>,
    headers,
    body;
    verbose =  <span class="org-constant">false</span>,
)

 <span class="org-comment-delimiter"># </span> <span class="org-comment">Parse the response body as JSON
</span>result = JSON.parse(String(response.body))
print(result[ <span class="org-string">"choices"</span>][1][ <span class="org-string">"message"</span>][ <span class="org-string">"content"</span>])
</pre>
</div>

 <pre class="example" id="org1a158d1">
Sure, here's a simpler example:

```julia
using HTTP

url = "https://jsonplaceholder.typicode.com/posts"

response = HTTP.post(url, form = [("title", "foo"), ("body", "bar"), ("userId", "1")])
println(String(response.body))
```

In this example, we are sending a POST request with form data rather than JSON data. We specify the form data using an array of tuples with the keys and values for the form fields. Note that we use the `form` argument to pass the form data to `HTTP.post()`. The response is then printed in the same way as before.
</pre>
</div>
</div>
 <div id="outline-container-org4f7195b" class="outline-2">
 <h2 id="org4f7195b">Next Up…</h2>
 <div class="outline-text-2" id="text-org4f7195b">
 <p>
This post showed basic usage of the ChatGPT API with Julia. In the next post,
I'll show how to make this more modular and useful. We'll create a  <code>Struct</code> for
conversations and a function to call on the API based on the conversation
history in that  <code>Struct</code>. After that, I'll write about how to make it interactive,
perhaps as a Julia REPL mode, but at least as a command line utility.
</p>
</div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20230303-chatgpt-julia.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20230303-chatgpt-julia.html</guid>
  <pubDate>Sat, 04 Mar 2023 08:00:00 +0000</pubDate>
</item>
<item>
  <title>Using Quarto Files with Denote</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Using Quarto Files with Denote</h1>
 <p class="subtitle" role="doc-subtitle">December 22, 2022</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#org2438658">Custom Filetypes in Denote</a></li>
 <li> <a href="#orge0066c1">Modifying the  <code>markdown-yaml</code> file type</a></li>
</ul></div>
</nav> <div id="outline-container-org2438658" class="outline-2">
 <h2 id="org2438658">Custom Filetypes in Denote</h2>
 <div class="outline-text-2" id="text-org2438658">
 <div class="PREVIEW" id="orge2a6b5b">
 <p>
The latest release of  <a href="https://protesilaos.com/emacs/denote">Denote</a> (by the inimitable Protesilaos Stavrou) introduced
support for  <a href="https://protesilaos.com/codelog/2022-10-30-demo-denote-custom-file-type/">custom file types</a> in addition to the defaults, Org, Markdown+YAML,
Markdown+TOML, and plain text. This post shows how to add  <a href="https://quarto.org/">Quarto</a> files
(.qmd). Quarto, the successor to R Markdown, is "an open-source scientific and
technical publishing system" with support for Python, R, Julia, and
Observable. The setup detailed here will allow one to choose the .qmd filetype
when creating a new Denote file.
</p>

</div>

 <p>
Find the code snippet  <a href="#orge0066c1">here</a>.
</p>

 <p>
All the details about creating a custom Denote filetype can be found
 <a href="https://protesilaos.com/codelog/2022-10-30-demo-denote-custom-file-type/">here</a>. First, let's inspect the  <code>denote-file-types</code> alist to understand what a file
type definition looks like.
</p>

 <div class="org-src-container">
 <pre class="src src-emacs-lisp">(print denote-file-types)
</pre>
</div>

 <pre class="example">
((quarto :extension ".qmd" :date-function denote-date-iso-8601 :front-matter denote-yaml-front-matter :title-key-regexp "^title\\s-*:" :title-value-function denote-surround-with-quotes :title-value-reverse-function denote-trim-whitespace-then-quotes :keywords-key-regexp "^tags\\s-*:" :keywords-value-function denote-format-keywords-for-md-front-matter :keywords-value-reverse-function denote-extract-keywords-from-front-matter :link denote-md-link-format :link-in-context-regexp denote-md-link-in-context-regexp) (quarto :extension ".qmd" :date-function denote-date-rfc3339 :front-matter denote-yaml-front-matter :title-key-regexp "^title\\s-*:" :title-value-function denote-surround-with-quotes :title-value-reverse-function denote-trim-whitespace-then-quotes :keywords-key-regexp "^tags\\s-*:" :keywords-value-function denote-format-keywords-for-md-front-matter :keywords-value-reverse-function denote-extract-keywords-from-front-matter :link denote-md-link-format :link-in-context-regexp denote-md-link-in-context-regexp) (org :extension ".org" :date-function denote-date-org-timestamp :front-matter denote-org-front-matter :title-key-regexp "^#\\+title\\s-*:" :title-value-function identity :title-value-reverse-function denote-trim-whitespace :keywords-key-regexp "^#\\+filetags\\s-*:" :keywords-value-function denote-format-keywords-for-org-front-matter :keywords-value-reverse-function denote-extract-keywords-from-front-matter :link denote-org-link-format :link-in-context-regexp denote-org-link-in-context-regexp) (markdown-yaml :extension ".qmd" :date-function denote-date-rfc3339 :front-matter denote-yaml-front-matter :title-key-regexp "^title\\s-*:" :title-value-function denote-surround-with-quotes :title-value-reverse-function denote-trim-whitespace-then-quotes :keywords-key-regexp "^tags\\s-*:" :keywords-value-function denote-format-keywords-for-md-front-matter :keywords-value-reverse-function denote-extract-keywords-from-front-matter :link denote-md-link-format :link-in-context-regexp denote-md-link-in-context-regexp) (markdown-toml :extension ".md" :date-function denote-date-rfc3339 :front-matter denote-toml-front-matter :title-key-regexp "^title\\s-*=" :title-value-function denote-surround-with-quotes :title-value-reverse-function denote-trim-whitespace-then-quotes :keywords-key-regexp "^tags\\s-*=" :keywords-value-function denote-format-keywords-for-md-front-matter :keywords-value-reverse-function denote-extract-keywords-from-front-matter :link denote-md-link-format :link-in-context-regexp denote-md-link-in-context-regexp) (text :extension ".txt" :date-function denote-date-iso-8601 :front-matter denote-text-front-matter :title-key-regexp "^title\\s-*:" :title-value-function identity :title-value-reverse-function denote-trim-whitespace :keywords-key-regexp "^tags\\s-*:" :keywords-value-function denote-format-keywords-for-text-front-matter :keywords-value-reverse-function denote-extract-keywords-from-front-matter :link denote-org-link-format :link-in-context-regexp denote-org-link-in-context-regexp))
</pre>


 <p>
We need to add to this list. We can define a new filetype in this alist by
defining a new element of the form  <code>(SYMBOL PROPERTY-LIST)</code>.
</p>

 <p>
Adding a basic quarto file should be very simple. We only need to duplicatge the
markdown file type definition, changing the name to  <code>quarto</code> and the extension to
 <code>".qmd"</code>. We could do this as follows.
</p>

 <div class="org-src-container">
 <pre class="src src-emacs-lisp">(add-to-list 'denote-file-types
             '(quarto
                <span class="org-builtin">:extension</span>  <span class="org-string">".qmd"</span>
                <span class="org-builtin">:date-function</span> denote-date-iso-8601
                <span class="org-builtin">:front-matter</span> denote-yaml-front-matter
                <span class="org-builtin">:title-key-regexp</span>  <span class="org-string">"^title\\s-*:"</span>
                <span class="org-builtin">:title-value-function</span> denote-surround-with-quotes
                <span class="org-builtin">:title-value-reverse-function</span> denote-trim-whitespace-then-quotes
                <span class="org-builtin">:keywords-key-regexp</span>  <span class="org-string">"^tags\\s-*:"</span>
                <span class="org-builtin">:keywords-value-function</span> denote-format-keywords-for-md-front-matter
                <span class="org-builtin">:keywords-value-reverse-function</span> denote-extract-keywords-from-front-matter
                <span class="org-builtin">:link</span> denote-md-link-format
                <span class="org-builtin">:link-in-context-regexp</span> denote-md-link-in-context-regexp))
</pre>
</div>

 <pre class="example">
((quarto :extension ".qmd" :date-function denote-date-iso-8601 :front-matter denote-yaml-front-matter :title-key-regexp "^title\\s-*:" :title-value-function denote-surround-with-quotes :title-value-reverse-function denote-trim-whitespace-then-quotes :keywords-key-regexp "^tags\\s-*:" :keywords-value-function denote-format-keywords-for-md-front-matter :keywords-value-reverse-function denote-extract-keywords-from-front-matter :link denote-md-link-format :link-in-context-regexp denote-md-link-in-context-regexp) (quarto :extension ".qmd" :date-function denote-date-rfc3339 :front-matter denote-yaml-front-matter :title-key-regexp "^title\\s-*:" :title-value-function denote-surround-with-quotes :title-value-reverse-function denote-trim-whitespace-then-quotes :keywords-key-regexp "^tags\\s-*:" :keywords-value-function denote-format-keywords-for-md-front-matter :keywords-value-reverse-function denote-extract-keywords-from-front-matter :link denote-md-link-format :link-in-context-regexp denote-md-link-in-context-regexp) (org :extension ".org" :date-function denote-date-org-timestamp :front-matter denote-org-front-matter :title-key-regexp "^#\\+title\\s-*:" :title-value-function identity :title-value-reverse-function denote-trim-whitespace :keywords-key-regexp "^#\\+filetags\\s-*:" :keywords-value-function denote-format-keywords-for-org-front-matter :keywords-value-reverse-function denote-extract-keywords-from-front-matter :link denote-org-link-format :link-in-context-regexp denote-org-link-in-context-regexp) (markdown-yaml :extension ".qmd" :date-function denote-date-rfc3339 :front-matter denote-yaml-front-matter :title-key-regexp "^title\\s-*:" :title-value-function denote-surround-with-quotes :title-value-reverse-function denote-trim-whitespace-then-quotes :keywords-key-regexp "^tags\\s-*:" :keywords-value-function denote-format-keywords-for-md-front-matter :keywords-value-reverse-function denote-extract-keywords-from-front-matter :link denote-md-link-format :link-in-context-regexp denote-md-link-in-context-regexp) (markdown-toml :extension ".md" :date-function denote-date-rfc3339 :front-matter denote-toml-front-matter :title-key-regexp "^title\\s-*=" :title-value-function denote-surround-with-quotes :title-value-reverse-function denote-trim-whitespace-then-quotes :keywords-key-regexp "^tags\\s-*=" :keywords-value-function denote-format-keywords-for-md-front-matter :keywords-value-reverse-function denote-extract-keywords-from-front-matter :link denote-md-link-format :link-in-context-regexp denote-md-link-in-context-regexp) (text :extension ".txt" :date-function denote-date-iso-8601 :front-matter denote-text-front-matter :title-key-regexp "^title\\s-*:" :title-value-function identity :title-value-reverse-function denote-trim-whitespace :keywords-key-regexp "^tags\\s-*:" :keywords-value-function denote-format-keywords-for-text-front-matter :keywords-value-reverse-function denote-extract-keywords-from-front-matter :link denote-org-link-format :link-in-context-regexp denote-org-link-in-context-regexp))
</pre>


 <p>
We can do this more concisely (and learn a litle bit of emacs lisp on the way)
by modifying the  <code>markdown-yaml</code> file type definition.
</p>
</div>
</div>

 <div id="outline-container-orge0066c1" class="outline-2">
 <h2 id="orge0066c1">Modifying the  <code>markdown-yaml</code> file type</h2>
 <div class="outline-text-2" id="text-orge0066c1">
 <p>
As noted, all we're actually doing is changing the file extension in the
existing markdown type. So instead of writing out all of the redundant details,
let's just copy them from the markdown type.
</p>

 <div class="org-src-container">
 <pre class="src src-emacs-lisp">( <span class="org-keyword">let</span> ((quarto (cdr (assoc 'markdown-yaml denote-file-types))))
  ( <span class="org-keyword">setf</span> (plist-get quarto  <span class="org-builtin">:extension</span>)  <span class="org-string">".qmd"</span>)
  (add-to-list 'denote-file-types (cons 'quarto quarto)))

(print denote-file-types)
</pre>
</div>

 <pre class="example">
((quarto :extension ".qmd" :date-function denote-date-rfc3339 :front-matter denote-yaml-front-matter :title-key-regexp "^title\\s-*:" :title-value-function denote-surround-with-quotes :title-value-reverse-function denote-trim-whitespace-then-quotes :keywords-key-regexp "^tags\\s-*:" :keywords-value-function denote-format-keywords-for-md-front-matter :keywords-value-reverse-function denote-extract-keywords-from-front-matter :link denote-md-link-format :link-in-context-regexp denote-md-link-in-context-regexp) (org :extension ".org" :date-function denote-date-org-timestamp :front-matter denote-org-front-matter :title-key-regexp "^#\\+title\\s-*:" :title-value-function identity :title-value-reverse-function denote-trim-whitespace :keywords-key-regexp "^#\\+filetags\\s-*:" :keywords-value-function denote-format-keywords-for-org-front-matter :keywords-value-reverse-function denote-extract-keywords-from-front-matter :link denote-org-link-format :link-in-context-regexp denote-org-link-in-context-regexp) (markdown-yaml :extension ".qmd" :date-function denote-date-rfc3339 :front-matter denote-yaml-front-matter :title-key-regexp "^title\\s-*:" :title-value-function denote-surround-with-quotes :title-value-reverse-function denote-trim-whitespace-then-quotes :keywords-key-regexp "^tags\\s-*:" :keywords-value-function denote-format-keywords-for-md-front-matter :keywords-value-reverse-function denote-extract-keywords-from-front-matter :link denote-md-link-format :link-in-context-regexp denote-md-link-in-context-regexp) (markdown-toml :extension ".md" :date-function denote-date-rfc3339 :front-matter denote-toml-front-matter :title-key-regexp "^title\\s-*=" :title-value-function denote-surround-with-quotes :title-value-reverse-function denote-trim-whitespace-then-quotes :keywords-key-regexp "^tags\\s-*=" :keywords-value-function denote-format-keywords-for-md-front-matter :keywords-value-reverse-function denote-extract-keywords-from-front-matter :link denote-md-link-format :link-in-context-regexp denote-md-link-in-context-regexp) (text :extension ".txt" :date-function denote-date-iso-8601 :front-matter denote-text-front-matter :title-key-regexp "^title\\s-*:" :title-value-function identity :title-value-reverse-function denote-trim-whitespace :keywords-key-regexp "^tags\\s-*:" :keywords-value-function denote-format-keywords-for-text-front-matter :keywords-value-reverse-function denote-extract-keywords-from-front-matter :link denote-org-link-format :link-in-context-regexp denote-org-link-in-context-regexp))
</pre>


 <p>
What's actually happening here? Let's go through it step by step.
</p>

 <p>
The  <code>assoc</code> function takes a key and an alist as arguments and returns the first
element of that alist whose CAR is equal to the key. In effect, we're searching
the  <code>denote-file-types</code> alist for the element whose CAR is  <code>markdown-yaml</code>.
</p>
 <div class="org-src-container">
 <pre class="src src-emacs-lisp">(assoc 'markdown-yaml denote-file-types)
</pre>
</div>

 <pre class="example">
(markdown-yaml :extension ".qmd" :date-function denote-date-rfc3339 :front-matter denote-yaml-front-matter :title-key-regexp "^title\\s-*:" :title-value-function denote-surround-with-quotes :title-value-reverse-function denote-trim-whitespace-then-quotes :keywords-key-regexp "^tags\\s-*:" :keywords-value-function denote-format-keywords-for-md-front-matter :keywords-value-reverse-function denote-extract-keywords-from-front-matter :link denote-md-link-format :link-in-context-regexp denote-md-link-in-context-regexp)
</pre>



 <p>
We only want the CDR of this element (everything but the  <code>markdown-yaml</code> at the
beginning).
</p>

 <div class="org-src-container">
 <pre class="src src-emacs-lisp">(cdr (assoc 'markdown-yaml denote-file-types))
</pre>
</div>

 <pre class="example">
(:extension ".qmd" :date-function denote-date-rfc3339 :front-matter denote-yaml-front-matter :title-key-regexp "^title\\s-*:" :title-value-function denote-surround-with-quotes :title-value-reverse-function denote-trim-whitespace-then-quotes :keywords-key-regexp "^tags\\s-*:" :keywords-value-function denote-format-keywords-for-md-front-matter :keywords-value-reverse-function denote-extract-keywords-from-front-matter :link denote-md-link-format :link-in-context-regexp denote-md-link-in-context-regexp)
</pre>



 <p>
We use  <code>let</code> to say that, for the purposes of this procedure, we want to associate
the above plist with the name  <code>quarto</code>.
</p>

 <p>
Next, we need to change the extension from  <code>.md</code> to  <code>.qmd</code>. We use  <code>plist-get</code> to get
the desired property ( <code>:extension</code>) and  <code>setf</code> to set it to  <code>".qmd"</code>.
</p>

 <div class="org-src-container">
 <pre class="src src-emacs-lisp">( <span class="org-keyword">setf</span> (plist-get (cdr (assoc 'markdown-yaml denote-file-types))  <span class="org-builtin">:extension</span>)  <span class="org-string">".qmd"</span>)
</pre>
</div>

 <pre class="example">
.qmd
</pre>


 <p>
In the end, we add the  <code>quarto</code> plist to the  <code>denote-file-types</code> alist with
 <code>(add-to-list 'denote-file-types (cons 'quarto quarto))</code>. The  <code>cons</code> function
creates a new  <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Cons-Cells.html">cons</a> from a  <code>CAR</code> and a  <code>CDR</code> (in this case,  <code>quarto</code>
and the modified copy of the   <code>markdown-yaml</code> plist with the changed extension).
</p>

 <p>
And with that, we can now create new quarto files with denote!
</p>

 <p>

 <style>
.figure-number {
    display: none;
}
</style></p>


 <figure id="orgecdb9b9"> <img src="figures/20221217-denote-quarto/quarto_denote.png" alt="Emacs minibuffer Denote 'Select file type' prompt listing org, text, quarto, markdown-toml, markdown-yaml"></img> <figcaption> <span class="figure-number">Figure 1: </span> <i>Quarto in the Denote Menu!</i></figcaption></figure> <p>
Check out  <a href="https://github.com/quarto-dev/quarto-emacs">quarto-emacs</a> if you're interested in working with quarto files in
emacs (though I have to admit that working with quarto files in RStudio is a joy
and is at least worth a try before commiting to an emacs-only workflow).
</p>
</div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20221217-denote-quarto.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20221217-denote-quarto.html</guid>
  <pubDate>Thu, 22 Dec 2022 08:00:00 +0000</pubDate>
</item>
<item>
  <title>Processing a JSON API Response with jq</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Processing a JSON API Response with jq</h1>
 <p class="subtitle" role="doc-subtitle">September 18, 2022</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#orgd77d0ab">Introduction</a></li>
 <li> <a href="#orgb901421">Download the Data</a></li>
 <li> <a href="#org747be8b">Processing the Data with  <code>jq</code></a>
 <ul> <li> <a href="#org8c2682f"> <code>jq</code> with no further arguments</a></li>
 <li> <a href="#org47f3b89">Constructing a Header Row</a></li>
 <li> <a href="#org907c89d">Extracting Data Values</a></li>
 <li> <a href="#org35d4e30">Converting the Results to CSV</a></li>
</ul></li>
</ul></div>
</nav> <div id="outline-container-orgd77d0ab" class="outline-2">
 <h2 id="orgd77d0ab">Introduction</h2>
 <div class="outline-text-2" id="text-orgd77d0ab">
 <div class="preview" id="orgb53ae06">
 <p>
There are countless ways of processing JSON data and converting it to different
formats. Historically, I've used Python and loaded the data into a Pandas
Dataframe for processing. This isn't really necessary for simple tasks,
though. Sometimes, a lightweight command line tool does the job just fine. Enter
 <code>jq</code>.  <a href="https://stedolan.github.io/jq/">jq</a> is "like  <code>sed</code> for JSON data." This post walks through an example of
downloading data from an API, extracting a few fields based on some conditions,
and converting the results to a CSV using  <code>jq</code>.
</p>

</div>

 <p>
In this example, we'll download some data from the Bureau of Labor Statistics
API, apply some minor processing, and save the results as a CSV. More
specifically, we will:
</p>

 <ol class="org-ol"> <li>Download two BLS data series from the BLS API using  <code>curl</code></li>
 <li>Extract a few different variables from different hierarchical levels of the
JSON results using  <code>jq</code></li>
 <li>Save the results as a CSV using  <code>jq</code></li>
</ol> <p>
This mirrors a common Python task in my workflow: I make an API call using the
 <code>requests</code> module, load the JSON results as a Python  <code>dict</code> type with  <code>json.load</code> from
the  <code>json</code> module, and then load the results as a pandas table with
 <code>Pandas.DataFrame.from_dict</code>. There may be more (or fewer) steps depending on the
structure of the API results, but I've repeated this broad pattern many times.
</p>

 <p>
To follow along, begin by  <a href="https://stedolan.github.io/jq/download/">installing jq</a> if you haven't already.
</p>
</div>
</div>

 <div id="outline-container-orgb901421" class="outline-2">
 <h2 id="orgb901421">Download the Data</h2>
 <div class="outline-text-2" id="text-orgb901421">
 <p>
As noted above, we use  <code>curl</code> to make a  <code>POST</code> request agains the BLS API. We're
downloading Consumer Price Index data since the start of 2022. We're downloading
data from two BLS series: one for seasonally adjusted data, and one for
unadjusted data.
</p>

 <div class="org-src-container">
 <pre class="src src-shell">curl -X POST -H  <span class="org-string">'Content-Type: application/json'</span>  <span class="org-sh-escaped-newline">\</span>
     -d  <span class="org-string">'{"seriesid": ["CUUR0000SA0","CUSR0000SA0"], "startyear":2022, "endyear":2022}'</span>  <span class="org-sh-escaped-newline">\</span>
     https://api.bls.gov/publicAPI/v2/timeseries/data/ 
</pre>
</div>

 <pre class="example" id="org0525c9b">
| status":"REQUEST_SUCCEEDED","responseTime":171,"message":[],"Results               |
| series                                                                            |
| seriesID":"CUUR0000SA0","data":[{"year":"2022","period":"M08","periodName":"August", "latest":"true","value":"296.171","footnotes":[{}]},{"year":"2022","period":"M07","periodName":"July","value":"296.276","footnotes":[{}]},{"year":"2022","period":"M06","periodName":"June","value":"296.311","footnotes":[{}]},{"year":"2022","period":"M05","periodName":"May","value":"292.296","footnotes":[{}]},{"year":"2022","period":"M04","periodName":"April","value":"289.109","footnotes":[{}]},{"year":"2022","period":"M03","periodName":"March","value":"287.504","footnotes":[{}]},{"year":"2022","period":"M02","periodName":"February","value":"283.716","footnotes":[{}]},{"year":"2022","period":"M01","periodName":"January","value":"281.148","footnotes |
| seriesID":"CUSR0000SA0","data":[{"year":"2022","period":"M08","periodName":"August", "latest":"true","value":"295.620","footnotes":[{}]},{"year":"2022","period":"M07","periodName":"July","value":"295.271","footnotes":[{}]},{"year":"2022","period":"M06","periodName":"June","value":"295.328","footnotes":[{}]},{"year":"2022","period":"M05","periodName":"May","value":"291.474","footnotes":[{}]},{"year":"2022","period":"M04","periodName":"April","value":"288.663","footnotes":[{}]},{"year":"2022","period":"M03","periodName":"March","value":"287.708","footnotes":[{}]},{"year":"2022","period":"M02","periodName":"February","value":"284.182","footnotes":[{}]},{"year":"2022","period":"M01","periodName":"January","value":"281.933","footnotes |
| }}                                                                                |
</pre>

 <p>
This is technically readable, but not very nice.
</p>
</div>
</div>
 <div id="outline-container-org747be8b" class="outline-2">
 <h2 id="org747be8b">Processing the Data with  <code>jq</code></h2>
 <div class="outline-text-2" id="text-org747be8b">
 <p>
For most use cases, the data aren't particularly usable in this format. They're
hard to read; they include metadata about the API response; and the hierarchical
structure makes them difficult to extract into a tabular format. Enter  <code>jq</code>. We'll
proceed step by step to show how we can use  <code>jq</code> to extract specific data from the
API results.
</p>
</div>
 <div id="outline-container-org8c2682f" class="outline-3">
 <h3 id="org8c2682f"> <code>jq</code> with no further arguments</h3>
 <div class="outline-text-3" id="text-org8c2682f">
 <p>
What happens if we pass the results of the API call to  <code>jq</code> with no further arguments?
</p>
 <div class="org-src-container">
 <pre class="src src-shell">curl -X POST -H  <span class="org-string">'Content-Type: application/json'</span>  <span class="org-sh-escaped-newline">\</span>
     -d  <span class="org-string">'{"seriesid": ["CUUR0000SA0","CUSR0000SA0"], "startyear":2022, "endyear":2022}'</span>  <span class="org-sh-escaped-newline">\</span>
     https://api.bls.gov/publicAPI/v2/timeseries/data/ | jq
</pre>
</div>

 <pre class="example" id="orge81546e">
{
  "status": "REQUEST_SUCCEEDED",
  "responseTime": 169,
  "message": [],
  "Results": {
    "series": [
      {
        "seriesID": "CUUR0000SA0",
        "data": [
          {
            "year": "2022",
            "period": "M08",
            "periodName": "August",
            "latest": "true",
            "value": "296.171",
            "footnotes": [
              {}
            ]
          },
          {
            "year": "2022",
            "period": "M07",
            "periodName": "July",
            "value": "296.276",
            "footnotes": [
              {}
            ]
          },
          {
            "year": "2022",
            "period": "M06",
            "periodName": "June",
            "value": "296.311",
            "footnotes": [
              {}
            ]
          },
          {
            "year": "2022",
            "period": "M05",
            "periodName": "May",
            "value": "292.296",
            "footnotes": [
              {}
            ]
          },
          {
            "year": "2022",
            "period": "M04",
            "periodName": "April",
            "value": "289.109",
            "footnotes": [
              {}
            ]
          },
          {
            "year": "2022",
            "period": "M03",
            "periodName": "March",
            "value": "287.504",
            "footnotes": [
              {}
            ]
          },
          {
            "year": "2022",
            "period": "M02",
            "periodName": "February",
            "value": "283.716",
            "footnotes": [
              {}
            ]
          },
          {
            "year": "2022",
            "period": "M01",
            "periodName": "January",
            "value": "281.148",
            "footnotes": [
              {}
            ]
          }
        ]
      },
      {
        "seriesID": "CUSR0000SA0",
        "data": [
          {
            "year": "2022",
            "period": "M08",
            "periodName": "August",
            "latest": "true",
            "value": "295.620",
            "footnotes": [
              {}
            ]
          },
          {
            "year": "2022",
            "period": "M07",
            "periodName": "July",
            "value": "295.271",
            "footnotes": [
              {}
            ]
          },
          {
            "year": "2022",
            "period": "M06",
            "periodName": "June",
            "value": "295.328",
            "footnotes": [
              {}
            ]
          },
          {
            "year": "2022",
            "period": "M05",
            "periodName": "May",
            "value": "291.474",
            "footnotes": [
              {}
            ]
          },
          {
            "year": "2022",
            "period": "M04",
            "periodName": "April",
            "value": "288.663",
            "footnotes": [
              {}
            ]
          },
          {
            "year": "2022",
            "period": "M03",
            "periodName": "March",
            "value": "287.708",
            "footnotes": [
              {}
            ]
          },
          {
            "year": "2022",
            "period": "M02",
            "periodName": "February",
            "value": "284.182",
            "footnotes": [
              {}
            ]
          },
          {
            "year": "2022",
            "period": "M01",
            "periodName": "January",
            "value": "281.933",
            "footnotes": [
              {}
            ]
          }
        ]
      }
    ]
  }
}
</pre>

 <p>
We end up with our JSON output in a much more readable format. The spacing makes
it considerably easier to visualize the data hierarchy. Looking at this, we
observe:
</p>
 <ul class="org-ul"> <li>The data we want are under the  <code>Results</code> key</li>
 <li>Each series under  <code>Results</code> has a  <code>SeriesID</code> and  <code>data</code>: we want the  <code>seriesID</code> and
the  <code>data</code> values as rows in our resulting table.</li>
</ul></div>
</div>
 <div id="outline-container-org47f3b89" class="outline-3">
 <h3 id="org47f3b89">Constructing a Header Row</h3>
 <div class="outline-text-3" id="text-org47f3b89">
 <p>
We want our resulting table to have a header row. The process of making this row
provides a lot of insight into how  <code>jq</code> works.
</p>

 <div class="org-src-container">
 <pre class="src src-shell">curl -X POST -H  <span class="org-string">'Content-Type: application/json'</span>  <span class="org-sh-escaped-newline">\</span>
     -d  <span class="org-string">'{"seriesid": ["CUUR0000SA0","CUSR0000SA0"], "startyear":2022, "endyear":2022}'</span>  <span class="org-sh-escaped-newline">\</span>
     https://api.bls.gov/publicAPI/v2/timeseries/data/  <span class="org-sh-escaped-newline">\</span>
    | jq -r  <span class="org-string">'.Results | (.series[0].data[0] | ["seriesID"] + keys_unsorted)'</span>
</pre>
</div>

 <pre class="example">
[
  "seriesID",
  "year",
  "period",
  "periodName",
  "latest",
  "value",
  "footnotes"
]
</pre>


 <p>
What's happening here?
</p>

 <ul class="org-ul"> <li>Calling  <code>jq</code> with the  <code>-r</code> argument specifies that we want raw output rather than
output formatted and quoted as a JSON string.</li>
 <li> <code>.Results</code> specifies that we're working under the  <code>Results</code> key. We aren't
interested in the  <code>status</code> or  <code>responseTime</code> or  <code>message</code> keys. The data are all
under  <code>Results</code>. If we had started with  <code>jq -r '.'</code>, we'd be starting from the top
of the hierarchy.</li>
 <li> <p>
Parentheses serve as grouping operators. In many cases, in  <code>jq</code>, parentheses are
used to specify the particular level of the data hierarchy we're working
with. For example,  <code>(.series[0].data[0]) | ...</code> specifies that we're working
with the first data entry of the first series, which looks like this:
</p>

 <div class="org-src-container">
 <pre class="src src-js">{
     <span class="org-string">"year"</span>:  <span class="org-string">"2022"</span>,
     <span class="org-string">"period"</span>:  <span class="org-string">"M08"</span>,
     <span class="org-string">"periodName"</span>:  <span class="org-string">"August"</span>,
     <span class="org-string">"latest"</span>:  <span class="org-string">"true"</span>,
     <span class="org-string">"value"</span>:  <span class="org-string">"296.171"</span>,
     <span class="org-string">"footnotes"</span>: [
        {}
    ]
}
</pre>
</div></li>
 <li>The pipe operator  <code>|</code> combines filters: it passes the output of the filter on
the left as the input to the filter on the right. This is very much like the
Unix shell pipe. Recall that, in this case, the first filter returned the JSON
object above, so subsequent filters and functions in this set of parentheses
will operate on that object.</li>
 <li> <code>keys_unsorted</code> is a function that returns the keys from a given object, sorted
"roughly in insertion order."</li>
 <li> <code>+</code> does array concatenation, so  <code>["seriesID"] + keys</code> returns a single array
containing  <code>"SeriesID"</code> and the keys returned by the  <code>keys</code> function.</li>
</ul> <p>
The most important thing to note here is how we use filters to navigate the JSON
hierarchy. We start with  <code>.Results</code> to specify that we're working in the context
of the  <code>"Results"</code> key, and then, in the parentheses, we narrow to
 <code>.series[0].data[0]</code> to specify the first entry in the first series. In the next
section, we'll see how to extract data from multiple sections.
</p>
</div>
</div>
 <div id="outline-container-org907c89d" class="outline-3">
 <h3 id="org907c89d">Extracting Data Values</h3>
 <div class="outline-text-3" id="text-org907c89d">
 <p>
Based on the header rows, we need to extract, for each data entry, the series
ID, footnotes, period, period name, year, value, and whether it's the latest
data from the BLS. We can't use the exact approach we used to construct the
headers, though, for two key reasons:
</p>
 <ul class="org-ul"> <li>We need to get data from each object, not just one</li>
 <li>We need data from different levels of the hierarchy:  <code>seriesID</code> is at a higher
level than the other values we need.</li>
</ul> <pre class="example" id="orge6236be">
"series": [
    {
        "seriesID": "CUUR0000SA0",
        "data": [
            {
                "year": "2022",
                "period": "M08",
                "periodName": "August",
                "latest": "true",
                "value": "296.171",
                "footnotes": [
                    {}
                ]
            },
            ...
        ]
</pre>

 <p>
Here's how we might start to approach this.
</p>


 <div class="org-src-container">
 <pre class="src src-shell">curl -X POST -H  <span class="org-string">'Content-Type: application/json'</span>  <span class="org-sh-escaped-newline">\</span>
     -d  <span class="org-string">'{"seriesid": ["CUUR0000SA0","CUSR0000SA0"], "startyear":2022, "endyear":2022}'</span>  <span class="org-sh-escaped-newline">\</span>
     https://api.bls.gov/publicAPI/v2/timeseries/data/  <span class="org-sh-escaped-newline">\</span>
    | jq -r  <span class="org-string">'.Results | (.series[] | [.seriesID] + (.data[] | map(.)))'</span>  
</pre>
</div>

 <pre class="example" id="org3ed9efa">
[
  "CUUR0000SA0",
  "2022",
  "M08",
  "August",
  "true",
  "296.171",
  [
    {}
  ]
]
[
  "CUUR0000SA0",
  "2022",
  "M07",
  "July",
  "296.276",
  [
    {}
  ]
]

...

[
  "CUSR0000SA0",
  "2022",
  "M01",
  "January",
  "281.933",
  [
    {}
  ]
]
</pre>

 <p>
This gets us part of the way there. We'll work through this part of the query
and show what happened:  <code>(.series[] | [.seriesID] + (.data[] | map(.)))</code>.
</p>
 <ul class="org-ul"> <li>The first filter focuses on  <code>.series[]</code>.</li>
 <li>The empty bracket  <code>[]</code> (with no index specified) returns all elements of the
array. So  <code>.series[]</code> will iterate through everything contained under
 <code>series</code>. There are two series, each with their own  <code>seriesID</code> and  <code>data</code>.</li>
 <li>The  <code>[.seriesID]</code> section after the filter will extract the ID from each series.</li>
 <li>The  <code>(.data[] | map(.))</code> section will, for each series, iterate through the  <code>data</code>
array. The  <code>map(.)</code> function says to return each value in the  <code>data</code> array without
modifying it.</li>
</ul> <p>
The main thing we've accomplished here is extracting elements from different
levels of the hierarchy: the  <code>seriesID</code> from the higher level and the  <code>data</code> values
from the lower level.
</p>

 <p>
Ultimately, we'd like to convert these data to a CSV. This is possible with  <code>jq</code>,
but there's an issue: the  <code>footnotes</code> field is itself a JSON object and cannot be
converted directly to the CSV format. So we have a little more work to do.
</p>


 <div class="org-src-container">
 <pre class="src src-shell">curl -X POST -H  <span class="org-string">'Content-Type: application/json'</span>  <span class="org-sh-escaped-newline">\</span>
     -d  <span class="org-string">'{"seriesid": ["CUUR0000SA0","CUSR0000SA0"], "startyear":2022, "endyear":2022}'</span>  <span class="org-sh-escaped-newline">\</span>
     https://api.bls.gov/publicAPI/v2/timeseries/data/  <span class="org-sh-escaped-newline">\</span>
    | jq -r  <span class="org-string">'.Results | (.series[] | [.seriesID] +
  (.data[] | [with_entries(select(.key=="footnotes" | not)) | values[]] + [.footnotes[]|join(",")]))'</span>
</pre>
</div>

 <pre class="example" id="org5b3570d">
[
  "CUUR0000SA0",
  "2022",
  "M08",
  "August",
  "true",
  "296.171",
  ""
]
[
  "CUUR0000SA0",
  "2022",
  "M07",
  "July",
  "296.276",
  ""
]

...

[
  "CUSR0000SA0",
  "2022",
  "M01",
  "January",
  "281.933",
  ""
]
</pre>

 <p>
We've made some changes in how we extract the data from the  <code>data</code> key. Before, it
was just  <code>(.data[] | map(.))</code> Now it looks like  <code>(.data[] | [with_entries(select(.key=="footnotes" | not)) | values[]] + [.footnotes[]|join(",")])</code> .
</p>

 <p>
What do these changes mean?
</p>
 <ul class="org-ul"> <li> <code>with_entries</code> converts its input to key-value pairs with the format  <code>{key: k,
  value: v}</code>. This lets us filter based on the names of the keys and to return
the values we want.</li>
 <li> <code>select()</code> takes a boolean expression and returns its input if it matches the
boolean expresison. In this case, the boolean expression is
 <code>.key=="footnotes" | not</code>, which means "key does not equal 'footnotes'". So we
are excluding the "footnotes" field for now but returning all of the others.</li>
 <li> <code>values[]</code> returns all of the values from the key-value pairs, excluding
 <code>footnotes</code>.</li>
 <li>Lastly, we re-add the "footnotes" field with  <code>+ [.footnotes[]|join(",")]</code>. This
iterates through the elements of the  <code>footnotes</code> object in each  <code>data</code> entry and
converts them into comma-separated strings, which the CSV converter can handle
without issue.</li>
</ul></div>
</div>
 <div id="outline-container-org35d4e30" class="outline-3">
 <h3 id="org35d4e30">Converting the Results to CSV</h3>
 <div class="outline-text-3" id="text-org35d4e30">
 <p>
Lastly, we convert the transformed results to a CSV using the  <code>@csv</code> formatter.
</p>

 <div class="org-src-container">
 <pre class="src src-shell">curl -X POST -H  <span class="org-string">'Content-Type: application/json'</span>  <span class="org-sh-escaped-newline">\</span>
     -d  <span class="org-string">'{"seriesid": ["CUUR0000SA0","CUSR0000SA0"], "startyear":2022, "endyear":2022}'</span>  <span class="org-sh-escaped-newline">\</span>
     https://api.bls.gov/publicAPI/v2/timeseries/data/  <span class="org-sh-escaped-newline">\</span>
    | jq -r  <span class="org-string">'.Results | (.series[0].data[0]| ["seriesID"] +
  (keys_unsorted)), (.series[] | [.seriesID] +
  (.data[] | [with_entries(select(.key=="footnotes" | not)) | values[]] + [.footnotes[]|join(",")])) | @csv'</span>
</pre>
</div>

 <pre class="example" id="org7d1071a">
"seriesID","year","period","periodName","latest","value","footnotes"
"CUUR0000SA0","2022","M08","August","true","296.171",""
"CUUR0000SA0","2022","M07","July","296.276",""
"CUUR0000SA0","2022","M06","June","296.311",""
"CUUR0000SA0","2022","M05","May","292.296",""
"CUUR0000SA0","2022","M04","April","289.109",""
"CUUR0000SA0","2022","M03","March","287.504",""
"CUUR0000SA0","2022","M02","February","283.716",""
"CUUR0000SA0","2022","M01","January","281.148",""
"CUSR0000SA0","2022","M08","August","true","295.620",""
"CUSR0000SA0","2022","M07","July","295.271",""
"CUSR0000SA0","2022","M06","June","295.328",""
"CUSR0000SA0","2022","M05","May","291.474",""
"CUSR0000SA0","2022","M04","April","288.663",""
"CUSR0000SA0","2022","M03","March","287.708",""
"CUSR0000SA0","2022","M02","February","284.182",""
"CUSR0000SA0","2022","M01","January","281.933",""
</pre>

 <p>
There is one outstanding issue: only the first row of data actually contains the
 <code>latest</code> entry; the rest are empty. There are a number of solutions to this, from
dropping that column entirely to explicitly adding a "False" value to all of the
other rows. We won't get into that here.
</p>

 <p>
Now that you've read this post, you should have a better idea of how to use  <code>jq</code>
to access and process data at different hierarchical levels of a JSON data
structure.
</p>
</div>
</div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20220918-jq-example.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20220918-jq-example.html</guid>
  <pubDate>Sun, 18 Sep 2022 08:00:00 +0000</pubDate>
</item>
<item>
  <title>Figures and Captions Don&apos;t Appear as Expected with Default Export Options</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Figures and Captions Don't Appear as Expected with Default Export Options</h1>
 <p class="subtitle" role="doc-subtitle">July 24, 2022</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#orge208ed0">The Problem</a></li>
 <li> <a href="#org2d61292">Changes to the Site Config</a></li>
 <li> <a href="#orgd48dfba">The Results</a></li>
</ul></div>
</nav> <div class="preview" id="orgf2439f2">
 <p>
I noticed that some of the formatting on this site was a little off and some of
the org-mode components weren't being translated to HTML in quite the way I
expected. Fixing this was simple, but  <i>finding</i> the solution wasn't. In short, it
was necessary to set the  <code>org-html-doctype</code> to  <code>html5</code> (the default is
 <code>xhtml-strict</code>). Furthermore, I set  <code>org-html-html5-fancy</code> to  <code>t</code>. These ensure the
org export process takes advantage of block elements offered in the  <code>html5</code>
standard.
</p>

</div>

 <p>
While that brief introduction should capture the necessary changes, we can get
into more specifics.
</p>

 <div id="outline-container-orge208ed0" class="outline-2">
 <h2 id="orge208ed0">The Problem</h2>
 <div class="outline-text-2" id="text-orge208ed0">
 <p>
If we use the default settings, figures aren't wrapped in  <code><figure></code> blocks and
captions aren't wrapped in  <code><figcaption></code> blocks, so none of the formatting we
want to see applied to those attributes is actually applied. Here's what we see:
</p>

 <div id="org7d55a3b" class="figure">
 <p> <img src="figures/20220719-julia-plots/fig5.png" alt="fig5.png" width="450px"></img></p>
 <p> <span class="figure-number">Figure 1: </span>This caption is left-aligned and has no  <code><figcaption></code> element</p>
</div>

 <p>
The image and caption appear left-aligned on the page. Here's the html:
</p>

 <div class="org-src-container">
 <pre class="src src-html">< <span class="org-function-name">div</span>  <span class="org-variable-name">id</span>= <span class="org-string">"org7d55a3b"</span>  <span class="org-variable-name">class</span>= <span class="org-string">"figure"</span>>
< <span class="org-function-name">p</span>>< <span class="org-function-name">img</span>  <span class="org-variable-name">src</span>= <span class="org-string">"figures/20220719-julia-plots/fig5.png"</span>  <span class="org-variable-name">alt</span>= <span class="org-string">"fig5.png"</span>  <span class="org-variable-name">width</span>= <span class="org-string">"450px"</span>>
</ <span class="org-function-name">p</span>>
< <span class="org-function-name">p</span>>< <span class="org-function-name">span</span>  <span class="org-variable-name">class</span>= <span class="org-string">"figure-number"</span>>Figure 1: </ <span class="org-function-name">span</span>>This caption is left-aligned and has no < <span class="org-function-name">code</span>> <span class="org-variable-name">&lt;</span>figcaption <span class="org-variable-name">&gt;</span></ <span class="org-function-name">code</span>> element</ <span class="org-function-name">p</span>>
</ <span class="org-function-name">div</span>>
</pre>
</div>
</div>
</div>

 <div id="outline-container-org2d61292" class="outline-2">
 <h2 id="org2d61292">Changes to the Site Config</h2>
 <div class="outline-text-2" id="text-org2d61292">
 <p>
To address this, we need to change the  <code>org-html-doctype</code> and  <code>org-html-html5-fancy</code>
variables. We can do this in the export configuration's
 <code>org-publish-project-alist</code>. See  <a href="https://github.com/djliden/djliden.github.io/blob/main/build-site.el">here</a> for the updated configuration file. Here is
what the updated  <code>org-publish-project-alist</code> looks like—see lines 21-22 for the
key changes.
</p>

 <div class="org-src-container">
 <pre class="src src-emacs-lisp"> <span class="linenr"> 1: </span>( <span class="org-keyword">setq</span> org-publish-project-alist
 <span class="linenr"> 2: </span>      (list
 <span class="linenr"> 3: </span>       (list  <span class="org-string">"org-site:main"</span>
 <span class="linenr"> 4: </span>              <span class="org-builtin">:recursive</span> t
 <span class="linenr"> 5: </span>              <span class="org-builtin">:base-directory</span>  <span class="org-string">"./content"</span>
 <span class="linenr"> 6: </span>              <span class="org-builtin">:publishing-directory</span>  <span class="org-string">"./public"</span>
 <span class="linenr"> 7: </span>              <span class="org-builtin">:publishing-function</span> 'org-html-publish-to-html
 <span class="linenr"> 8: </span>              <span class="org-builtin">:html-preamble</span> (file-contents  <span class="org-string">"assets/html_preamble.html"</span>)
 <span class="linenr"> 9: </span>              <span class="org-builtin">:with-author</span> nil
 <span class="linenr">10: </span>              <span class="org-builtin">:with-creator</span> t
 <span class="linenr">11: </span>              <span class="org-builtin">:with-toc</span> t
 <span class="linenr">12: </span>              <span class="org-builtin">:section-numbers</span> nil
 <span class="linenr">13: </span>              <span class="org-builtin">:time-stamp-file</span> nil
 <span class="linenr">14: </span>              <span class="org-builtin">:auto-sitemap</span> t
 <span class="linenr">15: </span>              <span class="org-builtin">:sitemap-title</span> nil <span class="org-comment-delimiter">;</span> <span class="org-comment">"Daniel Liden's Blog"
 <span class="linenr">16: </span></span>              <span class="org-builtin">:sitemap-format-entry</span> 'my/org-publish-org-sitemap-format
 <span class="linenr">17: </span>              <span class="org-builtin">:sitemap-function</span> 'my/org-publish-org-sitemap
 <span class="linenr">18: </span>              <span class="org-builtin">:sitemap-sort-files</span> 'anti-chronologically
 <span class="linenr">19: </span>              <span class="org-builtin">:sitemap-filename</span>  <span class="org-string">"sitemap.org"</span>
 <span class="linenr">20: </span>              <span class="org-builtin">:sitemap-style</span> 'tree
 <span class="linenr">21: </span>              <span class="org-builtin">:html-doctype</span>  <span class="org-string">"html5"</span>
 <span class="linenr">22: </span>              <span class="org-builtin">:html-html5-fancy</span> t)
 <span class="linenr">23: </span>       (list  <span class="org-string">"org-site:static"</span>
 <span class="linenr">24: </span>              <span class="org-builtin">:base-directory</span>  <span class="org-string">"./content/"</span>
 <span class="linenr">25: </span>              <span class="org-builtin">:base-extension</span>  <span class="org-string">"css</span> <span class="org-string"> <span class="org-regexp-grouping-backslash">\\</span></span> <span class="org-string"> <span class="org-regexp-grouping-construct">|</span></span> <span class="org-string">js</span> <span class="org-string"> <span class="org-regexp-grouping-backslash">\\</span></span> <span class="org-string"> <span class="org-regexp-grouping-construct">|</span></span> <span class="org-string">png</span> <span class="org-string"> <span class="org-regexp-grouping-backslash">\\</span></span> <span class="org-string"> <span class="org-regexp-grouping-construct">|</span></span> <span class="org-string">jpg</span> <span class="org-string"> <span class="org-regexp-grouping-backslash">\\</span></span> <span class="org-string"> <span class="org-regexp-grouping-construct">|</span></span> <span class="org-string">gif</span> <span class="org-string"> <span class="org-regexp-grouping-backslash">\\</span></span> <span class="org-string"> <span class="org-regexp-grouping-construct">|</span></span> <span class="org-string">pdf</span> <span class="org-string"> <span class="org-regexp-grouping-backslash">\\</span></span> <span class="org-string"> <span class="org-regexp-grouping-construct">|</span></span> <span class="org-string">mp3</span> <span class="org-string"> <span class="org-regexp-grouping-backslash">\\</span></span> <span class="org-string"> <span class="org-regexp-grouping-construct">|</span></span> <span class="org-string">ogg</span> <span class="org-string"> <span class="org-regexp-grouping-backslash">\\</span></span> <span class="org-string"> <span class="org-regexp-grouping-construct">|</span></span> <span class="org-string">swf</span> <span class="org-string"> <span class="org-regexp-grouping-backslash">\\</span></span> <span class="org-string"> <span class="org-regexp-grouping-construct">|</span></span> <span class="org-string">svg"</span>
 <span class="linenr">26: </span>              <span class="org-builtin">:publishing-directory</span>  <span class="org-string">"./public"</span>
 <span class="linenr">27: </span>              <span class="org-builtin">:recursive</span> t
 <span class="linenr">28: </span>              <span class="org-builtin">:publishing-function</span> 'org-publish-attachment
 <span class="linenr">29: </span>             )
 <span class="linenr">30: </span>       (list  <span class="org-string">"org-site:assets"</span>
 <span class="linenr">31: </span>              <span class="org-builtin">:base-directory</span>  <span class="org-string">"./assets/"</span>
 <span class="linenr">32: </span>              <span class="org-builtin">:base-extension</span>  <span class="org-string">"css</span> <span class="org-string"> <span class="org-regexp-grouping-backslash">\\</span></span> <span class="org-string"> <span class="org-regexp-grouping-construct">|</span></span> <span class="org-string">js</span> <span class="org-string"> <span class="org-regexp-grouping-backslash">\\</span></span> <span class="org-string"> <span class="org-regexp-grouping-construct">|</span></span> <span class="org-string">png</span> <span class="org-string"> <span class="org-regexp-grouping-backslash">\\</span></span> <span class="org-string"> <span class="org-regexp-grouping-construct">|</span></span> <span class="org-string">jpg</span> <span class="org-string"> <span class="org-regexp-grouping-backslash">\\</span></span> <span class="org-string"> <span class="org-regexp-grouping-construct">|</span></span> <span class="org-string">gif</span> <span class="org-string"> <span class="org-regexp-grouping-backslash">\\</span></span> <span class="org-string"> <span class="org-regexp-grouping-construct">|</span></span> <span class="org-string">pdf</span> <span class="org-string"> <span class="org-regexp-grouping-backslash">\\</span></span> <span class="org-string"> <span class="org-regexp-grouping-construct">|</span></span> <span class="org-string">mp3</span> <span class="org-string"> <span class="org-regexp-grouping-backslash">\\</span></span> <span class="org-string"> <span class="org-regexp-grouping-construct">|</span></span> <span class="org-string">ogg</span> <span class="org-string"> <span class="org-regexp-grouping-backslash">\\</span></span> <span class="org-string"> <span class="org-regexp-grouping-construct">|</span></span> <span class="org-string">swf"</span>
 <span class="linenr">33: </span>              <span class="org-builtin">:publishing-directory</span>  <span class="org-string">"./public/"</span>
 <span class="linenr">34: </span>              <span class="org-builtin">:recursive</span> t
 <span class="linenr">35: </span>              <span class="org-builtin">:publishing-function</span> 'org-publish-attachment)))
</pre>
</div>
</div>
</div>
 <div id="outline-container-orgd48dfba" class="outline-2">
 <h2 id="orgd48dfba">The Results</h2>
 <div class="outline-text-2" id="text-orgd48dfba">
 <p>
With these changes, our images and captions are now centered:
</p>


 <figure id="org45489f5"> <img src="figures/20220719-julia-plots/fig5.png" alt="UnicodePlots scatter plot in a Julia REPL of mtcars MPG vs HP, points colored by cylinder count" width="450px"></img> <figcaption> <span class="figure-number">Figure 1: </span>This caption is now centered and wrapped in a  <code><figcaption></code> tag!</figcaption></figure> <p>
And the html generated from the org export now looks like this:
</p>

 <div class="org-src-container">
 <pre class="src src-html">< <span class="org-function-name">figure</span>  <span class="org-variable-name">id</span>= <span class="org-string">"orgbffad64"</span>>
< <span class="org-function-name">img</span>  <span class="org-variable-name">src</span>= <span class="org-string">"figures/20220719-julia-plots/fig5.png"</span>  <span class="org-variable-name">alt</span>= <span class="org-string">"fig5.png"</span>  <span class="org-variable-name">width</span>= <span class="org-string">"450px"</span>>

< <span class="org-function-name">figcaption</span>>< <span class="org-function-name">span</span>  <span class="org-variable-name">class</span>= <span class="org-string">"figure-number"</span>>Figure 1: </ <span class="org-function-name">span</span>>This caption is now centered and wrapped in a < <span class="org-function-name">code</span>> <span class="org-variable-name">&lt;</span>figcaption <span class="org-variable-name">&gt;</span></ <span class="org-function-name">code</span>> tag!</ <span class="org-function-name">figcaption</span>>
</ <span class="org-function-name">figure</span>>
</pre>
</div>

 <p>
We now have a  <code><figure>...</figure></code> block and our caption is a  <code><figcaption></code>
element.
</p>

 <p>
As noted in  <a href="https://orgmode.org/worg/org-tutorials/images-and-xhtml-export.html">this Worg page</a>:
</p>

 <blockquote>
 <p>
There is no  <i>figure</i> element in XHTML and captions are not supported at all.
</p>
</blockquote>

 <p>
Setting the config to use  <code>html5</code> gives us access to these elements.
</p>

 <p>
 <b>Note</b>: I don't know much HTML or CSS at all. It probably shows. I was trying to
 apply some formatting to the  <code>figcaption</code> element in my stylesheet and it wasn't
 having any impact, even though I was pretty sure captions were supposed to
 export to  <code>figcaption</code>. That led me to this solution, which seems to work well
 (for now). I invite any feedback!
</p>
</div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20220724-html5.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20220724-html5.html</guid>
  <pubDate>Sun, 24 Jul 2022 08:00:00 +0000</pubDate>
</item>
<item>
  <title>Basic Plotting in Julia</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Basic Plotting in Julia</h1>
 <p class="subtitle" role="doc-subtitle">July 19, 2022</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#org9e142c5">Getting Started with Julia in Org Mode:  <code>jupyter-julia</code>.</a></li>
 <li> <a href="#org429e504">Making some Plots</a>
 <ul> <li> <a href="#orgcd04e4a">Building Plots Incrementally</a></li>
</ul></li>
 <li> <a href="#orgfdf2183">Plotting Real Data</a></li>
 <li> <a href="#orgaed7b69">Modifying Plot Visual Components</a></li>
 <li> <a href="#orgc2c8612">Different Plot Styles</a></li>
 <li> <a href="#org932148a">Conculsion</a></li>
</ul></div>
</nav> <div class="preview" id="org3a0c9e5">
 <p>
In this short post, I show one of the many ways of using Julia within emacs
org mode, and will describe some of the basic plotting functionality in Julia.
</p>

</div>

 <div id="outline-container-org9e142c5" class="outline-2">
 <h2 id="org9e142c5">Getting Started with Julia in Org Mode:  <code>jupyter-julia</code>.</h2>
 <div class="outline-text-2" id="text-org9e142c5">
 <p>
While  <a href="https://github.com/gcv/julia-snail">julia-snail</a> is my favorite Julia development environment, it's support for
org-mode is, at present, quite limited. For example, it seems to ignore the
 <code>:file</code> argument, making it difficult to save figures to specific locations. I
find that  <a href="https://github.com/nnicandro/emacs-jupyter">emacs-jupyter</a> provides the most featureful and reliable way to work
with Julia in org-mode. Read  <a href="https://github.com/nnicandro/emacs-jupyter#org-mode-source-blocks">the emacs-jupyter documentation</a> for instructions on
how to use emacs-jupyter with org-mode.
</p>
</div>
</div>

 <div id="outline-container-org429e504" class="outline-2">
 <h2 id="org429e504">Making some Plots</h2>
 <div class="outline-text-2" id="text-org429e504">
 <p>
Let's make some plots. We'll use the  <a href="https://docs.juliaplots.org/latest/tutorial/">Plots.jl</a> package and explore a few
different plotting styles. First, we load the packages we'll be using. I tend to
plot statistical distributions fairly often, so I'll load  <code>Distributions</code> and
 <code>Statplots</code> in addition to  <code>Plots</code>.
</p>

 <div class="org-src-container">
 <pre class="src src-jupyter-julia">using Plots
using Distributions
using StatsPlots
</pre>
</div>
</div>

 <div id="outline-container-orgcd04e4a" class="outline-3">
 <h3 id="orgcd04e4a">Building Plots Incrementally</h3>
 <div class="outline-text-3" id="text-orgcd04e4a">
 <p>
With these packages loaded, we'll start simply and plot a standard normal
distribution.
</p>

 <div class="org-src-container">
 <pre class="src src-jupyter-julia">plot(Normal(), fill=(0,0.5,:red))
</pre>
</div>


 <figure id="orgf51a4b7"> <img src="figures/20220719-julia-plots/fig1.svg" alt="Julia Plots.jl curve of the standard normal distribution filled in red, with an unlabeled y1 legend" class="org-svg"></img> <figcaption> <span class="figure-number">Figure 1: </span>A basic plot</figcaption></figure> <p>
The  <code>Plots.jl</code> package makes it easy to update plots after creation. A Julia
convention is that methods ending in  <code>!</code>  <a href="https://docs.julialang.org/en/v1/manual/style-guide/#bang-convention">modify their arguments in place</a>. In this
case, we can call  <code>plot!()</code> to incrementally add to our plot.
</p>

 <div class="org-src-container">
 <pre class="src src-jupyter-julia">plot!(title="Standard Normal Distribution", xlabel="x", ylabel="p(x)") # Add Labels
plot!(leg=false) # Remove the Legend
</pre>
</div>


 <figure id="orgb553ca1"> <img src="figures/20220719-julia-plots/fig2.svg" alt="Julia plot of the standard normal distribution filled red, titled with x and p(x) axis labels, no legend" class="org-svg"></img> <figcaption> <span class="figure-number">Figure 2: </span>Removing the legend and adding labels</figcaption></figure> <p>
Let's make one final set of changes and update some of the font sizes for better
readability.
</p>


 <div class="org-src-container">
 <pre class="src src-jupyter-julia">plot!(tickfont=font(18, "courier"),
      guidefont=font(18),
      titlefont=
font(18, "Computer Modern"))
</pre>
</div>


 <figure id="org7ba9949"> <img src="figures/20220719-julia-plots/fig3.svg" alt="Standard normal distribution plot filled red with larger serif fonts on the title and axis labels" class="org-svg"></img> <figcaption> <span class="figure-number">Figure 3: </span>Changing some Fonts</figcaption></figure></div>
</div>
</div>


 <div id="outline-container-orgfdf2183" class="outline-2">
 <h2 id="orgfdf2183">Plotting Real Data</h2>
 <div class="outline-text-2" id="text-orgfdf2183">
 <p>
That's enough of that. Usually we're plotting real data, not standard standard
distributions. Let's get some. First we'll pull from the  <code>RDatasets</code> package,
which is an excellent source of go-to data science and statistics examples such
as  <code>mtcars</code> and  <code>iris</code>. We'll use the venerable  <code>mtcars</code> to show how to work with data
in a basic way.
</p>

 <div class="org-src-container">
 <pre class="src src-jupyter-julia">using RDatasets, DataFrames
mtcars = dataset("datasets", "mtcars")
mtcars[1:10,:]
</pre>
</div>

 <div class="data-frame"> <p>10 rows × 12 columns (omitted printing of 3 columns)</p> <table class="data-frame"> <thead> <tr> <th></th> <th>Model</th> <th>MPG</th> <th>Cyl</th> <th>Disp</th> <th>HP</th> <th>DRat</th> <th>WT</th> <th>QSec</th> <th>VS</th></tr> <tr> <th></th> <th title="InlineStrings.String31">String31</th> <th title="Float64">Float64</th> <th title="Int64">Int64</th> <th title="Float64">Float64</th> <th title="Int64">Int64</th> <th title="Float64">Float64</th> <th title="Float64">Float64</th> <th title="Float64">Float64</th> <th title="Int64">Int64</th></tr></thead> <tbody> <tr> <th>1</th> <td>Mazda RX4</td> <td>21.0</td> <td>6</td> <td>160.0</td> <td>110</td> <td>3.9</td> <td>2.62</td> <td>16.46</td> <td>0</td></tr> <tr> <th>2</th> <td>Mazda RX4 Wag</td> <td>21.0</td> <td>6</td> <td>160.0</td> <td>110</td> <td>3.9</td> <td>2.875</td> <td>17.02</td> <td>0</td></tr> <tr> <th>3</th> <td>Datsun 710</td> <td>22.8</td> <td>4</td> <td>108.0</td> <td>93</td> <td>3.85</td> <td>2.32</td> <td>18.61</td> <td>1</td></tr> <tr> <th>4</th> <td>Hornet 4 Drive</td> <td>21.4</td> <td>6</td> <td>258.0</td> <td>110</td> <td>3.08</td> <td>3.215</td> <td>19.44</td> <td>1</td></tr> <tr> <th>5</th> <td>Hornet Sportabout</td> <td>18.7</td> <td>8</td> <td>360.0</td> <td>175</td> <td>3.15</td> <td>3.44</td> <td>17.02</td> <td>0</td></tr> <tr> <th>6</th> <td>Valiant</td> <td>18.1</td> <td>6</td> <td>225.0</td> <td>105</td> <td>2.76</td> <td>3.46</td> <td>20.22</td> <td>1</td></tr> <tr> <th>7</th> <td>Duster 360</td> <td>14.3</td> <td>8</td> <td>360.0</td> <td>245</td> <td>3.21</td> <td>3.57</td> <td>15.84</td> <td>0</td></tr> <tr> <th>8</th> <td>Merc 240D</td> <td>24.4</td> <td>4</td> <td>146.7</td> <td>62</td> <td>3.69</td> <td>3.19</td> <td>20.0</td> <td>1</td></tr> <tr> <th>9</th> <td>Merc 230</td> <td>22.8</td> <td>4</td> <td>140.8</td> <td>95</td> <td>3.92</td> <td>3.15</td> <td>22.9</td> <td>1</td></tr> <tr> <th>10</th> <td>Merc 280</td> <td>19.2</td> <td>6</td> <td>167.6</td> <td>123</td> <td>3.92</td> <td>3.44</td> <td>18.3</td> <td>1</td></tr></tbody></table></div>


 <p>
We can use the  <code>@df</code> macro and access columns by prepending them with  <code>:</code>.
</p>


 <div class="org-src-container">
 <pre class="src src-jupyter-julia">gr()
@df mtcars scatter(:MPG, :HP, group=:Cyl, background=:black, msize=8, keytitle="N Cylinders")
xlabel!("Mpg")
ylabel!("HP")
title!("Horsepower by MPG and N Cylinders")
</pre>
</div>


 <figure id="org1bc3011"> <img src="figures/20220719-julia-plots/fig4.svg" alt="Julia scatter plot of mtcars horsepower versus MPG on a black background, colored by cylinder count" class="org-svg"></img> <figcaption> <span class="figure-number">Figure 4: </span>plotting data with Plots.jl</figcaption></figure></div>
</div>

 <div id="outline-container-orgaed7b69" class="outline-2">
 <h2 id="orgaed7b69">Modifying Plot Visual Components</h2>
 <div class="outline-text-2" id="text-orgaed7b69">
 <p>
It's not always straightforward to figure out how to modify visual components of
a plot. Most of the relevant information lies in the  <a href="https://docs.juliaplots.org/latest/attributes/">Attributes</a> section of the
Plots.jl documentation (and its subsections).
</p>
</div>
</div>
 <div id="outline-container-orgc2c8612" class="outline-2">
 <h2 id="orgc2c8612">Different Plot Styles</h2>
 <div class="outline-text-2" id="text-orgc2c8612">
 <p>
One of the benefits of the Plots.jl package is its support for many different
 <a href="https://docs.juliaplots.org/latest/backends/">plotting backends</a>. The default is GR which, according to the documentation, is
</p>

 <blockquote>
 <p>
The default backend. Very fast with lots of plot types. Still actively developed and improving daily.
</p>
</blockquote>

 <p>
and it offers speed; 2D and 3D plots, and standalone or inline plotting.
</p>

 <p>
Here we'll repeat the plot above with the UnicodePlots backend. We first need to
install the package with  <code>add UnicodePlots</code> in the package manager. Note that you
can do this right from the Jupyter repl in emacs-jupyter by pressing  <code>]</code> in the
repl.
</p>

 <p>
We then specify that we'd like to use this backend with the  <code>unicodeplots()</code> function.
</p>

 <div class="org-src-container">
 <pre class="src src-jupyter-julia">unicodeplots()
# scatterplot
@df mtcars scatter(:MPG, :HP, title="HP vs MPG", xlabel="Mpg", ylabel="HP")
</pre>
</div>

 <pre class="example" id="org444ce77">
                        HP vs MPG                   
       +----------------------------------------+   
343.49 |        ⚬                               | y1
       |                                        |   
       |                                        |   
       |         ⚬                              |   
       |     ⚬ ⚬                                |   
       |        ⚬                               |   
       | ⚬                                      |   
    HP |                                        |   
       |        ⚬ ⚬ ⚬ ⚬⚬⚬                       |   
       |        ⚬⚬                              |   
       |                                        |   
       |             ⚬ ⚬  ⚬              ⚬      |   
       |                  ⚬  ⚬    ⚬             |   
       |                            ⚬       ⚬ ⚬ |   
 43.51 |                       ⚬         ⚬      |   
       +----------------------------------------+   
        9.695             Mpg             34.605    
</pre>

 <p>
I haven't yet figured out how to get the colors to appear as they are supposed
to in org mode, so for now, I'm simply showing a basic scatterplot with no grouping. I'll
update if and when I figure that out. It should look like this:
</p>


 <figure id="orgcd9b87f"> <img src="figures/20220719-julia-plots/fig5.png" alt="Terminal screenshot of a Julia UnicodePlots scatter plot of mtcars MPG versus HP colored by cylinders" width="600px"></img> <figcaption> <span class="figure-number">Figure 5: </span>screenshot of unicodeplot from vterm</figcaption></figure></div>
</div>


 <div id="outline-container-org932148a" class="outline-2">
 <h2 id="org932148a">Conculsion</h2>
 <div class="outline-text-2" id="text-org932148a">
 <p>
There's a lot more to get into with plotting in Julia and with using Julia in
emacs. This post serves as a small jumping-off point—just enough to get started,
with a few pointers to further resources, and some questions to start
pursuing. I'll write more on this topic as I learn more!
</p>
</div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20220719-julia-plots.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20220719-julia-plots.html</guid>
  <pubDate>Tue, 19 Jul 2022 08:00:00 +0000</pubDate>
</item>
<item>
  <title>Org Mode Headlines in Org Source Blocks</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Org Mode Headlines in Org Source Blocks</h1>
 <p class="subtitle" role="doc-subtitle">February 8, 2022</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#org28593c5">The Problem</a></li>
 <li> <a href="#orge586a03">This Headline Is in an Org Source Block</a></li>
 <li> <a href="#orgcf868f4">Prepend Headlines in Source Blocks with Commas</a></li>
 <li> <a href="#orgb1e96c2">An Easier Way</a></li>
</ul></div>
</nav> <p>
 <i>Note: I know the org-mode syntax highlighting in the current theme is very
low-contrast. I will update this soon.</i>
</p>

 <div id="outline-container-org28593c5" class="outline-2">
 <h2 id="org28593c5">The Problem</h2>
 <div class="outline-text-2" id="text-org28593c5">
 <div class="PREVIEW" id="orgaf49e29">
 <p>
When writing about org mode, one often wants to show what particular org
headline look like in terms of formatting, properties, tags, options,
etc,. However, even within a babel org source block, an org header will be
parsed and exported as a header. We can get around this by prepending the
headline with a comma. The comma won't show up when exported: all that is
exported is a nicely-formatted example of an org headline.
</p>

</div>

 <p>
Here is an example of the issue. Below, I inserted an org source block (defined
with  <code>#+begin_src org</code>) with a first-level org headline inside,   <i>without</i> inserting
a comma before the headline.
</p>
 <hr></hr> <p>
#+begin <sub>src</sub> org
</p>
</div>
</div>
 <div id="outline-container-orge586a03" class="outline-2">
 <h2 id="orge586a03">This Headline Is in an Org Source Block</h2>
 <div class="outline-text-2" id="text-orge586a03">
 <p>
And it is still parsed and exported as a headline, not as an example.
#+end <sub>src</sub></p>
 <hr></hr> <p>
Clearly, this isn't what we want.
</p>
</div>
</div>
 <div id="outline-container-orgcf868f4" class="outline-2">
 <h2 id="orgcf868f4">Prepend Headlines in Source Blocks with Commas</h2>
 <div class="outline-text-2" id="text-orgcf868f4">
 <p>
This issue is easily resolved: just insert a comma before the headline in the
source block (e.g.  <code>,* Headline</code>). This results in the following:
</p>

 <div class="org-src-container">
 <pre class="src src-org"> <span class="org-org-level-1">* This Headline Is in an Org Source Block</span>
and it looks like org source, not like an exported org file.
</pre>
</div>

 <p>
This approach works well with more complicated org-mode syntax, as well. For
example, the following block:
</p>

 <div class="org-src-container">
 <pre class="src src-raw_org">,* Headline 1
:PROPERTIES:
:ID:       642BF4EE-3139-4B96-97C4-D3BABD86FFD5
:END:
,** Headline 2
This headline is also prepended with a comma!
,** Even a Nested Source Block!
,#+begin_src R
1+1
,#+end_src

,#+RESULTS:
: 2
</pre>
</div>

 <p>
leads to the following (when we specify that it is an org source block).
</p>

 <div class="org-src-container">
 <pre class="src src-org"> <span class="org-org-level-1">* Headline 1</span>
 <span class="org-org-drawer">:PROPERTIES:</span>
 <span class="org-org-special-keyword">:ID:</span>        <span class="org-org-property-value">642BF4EE-3139-4B96-97C4-D3BABD86FFD5</span>
 <span class="org-org-drawer">:END:</span>
 <span class="org-org-level-2">** Headline 2</span>
This headline is also prepended with a comma!
 <span class="org-org-level-2">** Even a Nested Source Block!</span>
 <span class="org-org-block-begin-line">#+begin_src R
</span> <span class="org-org-block">1+1
</span> <span class="org-org-block-end-line">#+end_src
</span>
 <span class="org-org-meta-line">#+RESULTS:</span>
 <span class="org-org-code">: 2</span>
</pre>
</div>
</div>
</div>
 <div id="outline-container-orgb1e96c2" class="outline-2">
 <h2 id="orgb1e96c2">An Easier Way</h2>
 <div class="outline-text-2" id="text-orgb1e96c2">
 <p>
We can use the  <code>org-edit-special</code> command ( <code>C-c '</code>) within an org source block to
open a separate editing environment (in this case, another org buffer). We can
then write some org syntax. When we exit the environment (again, with  <code>C-c '</code>), it
will be properly formatted for export.
</p>

 <p>
The following block was generated using this method:
</p>

 <div class="org-src-container">
 <pre class="src src-raw_org">,* Headline 1                                                    :example_tag:
This is an org headline with a tag.
,** TODO Second Headline
SCHEDULED: <2022-02-15 Tue>
:PROPERTIES:
:CUSTOM_ID: headline_1
:END:
,** Babel

,#+begin_src jupyter-python :session datasci
import numpy as np

np.array(range(1,10))
,#+end_src

,#+RESULTS:
: array([1, 2, 3, 4, 5, 6, 7, 8, 9])
</pre>
</div>

 <p>
Which generates:
</p>

 <div class="org-src-container">
 <pre class="src src-org"> <span class="org-org-level-1">* Headline 1                                                    </span> <span class="org-org-level-1"> <span class="org-org-tag">:example_tag:</span></span>
This is an org headline with a tag.
 <span class="org-org-level-2">** </span> <span class="org-org-level-2"> <span class="org-org-todo">TODO</span></span> <span class="org-org-level-2"> Second Headline</span>
 <span class="org-org-special-keyword">SCHEDULED:</span>  <span class="org-org-date"><2022-02-15 Tue></span>
 <span class="org-org-drawer">:PROPERTIES:</span>
 <span class="org-org-special-keyword">:CUSTOM_ID:</span>  <span class="org-org-property-value">headline_1</span>
 <span class="org-org-drawer">:END:</span>
 <span class="org-org-level-2">** Babel</span>

 <span class="org-org-block-begin-line">#+begin_src jupyter-python :session datasci
</span> <span class="org-org-block">import numpy as np

np.array(range(1,10))
</span> <span class="org-org-block-end-line">#+end_src
</span>
 <span class="org-org-meta-line">#+RESULTS:</span>
 <span class="org-org-code">: array([1, 2, 3, 4, 5, 6, 7, 8, 9])</span>
</pre>
</div>

 <p>
This approach is easier because there is no need to remember or guess what,
exactly, needs to be prepended with a comma. In this case, the headlines
themselves, the nested  <code>#+begin_src</code> and  <code>#+end_src</code> lines, and the  <code>#+RESULTS:</code> line
were all escaped with commas.
</p>

 <p>
With both of these approaches available, writing about org mode with example org
source blocks should be much easier.
</p>
</div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20220208-org-source.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20220208-org-source.html</guid>
  <pubDate>Tue, 08 Feb 2022 08:00:00 +0000</pubDate>
</item>
<item>
  <title>Task Repeaters in Org Mode</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Task Repeaters in Org Mode</h1>
 <p class="subtitle" role="doc-subtitle">January 29, 2022</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#org4e398f9">Background</a></li>
 <li> <a href="#org3774701">Review: Dates, Schedules, and Deadlines in Emacs Org-Mode</a></li>
 <li> <a href="#org4964cda">Repeat Intervals</a>
 <ul> <li> <a href="#orgd85ac81">Different Types of Repeat Intervals</a>
 <ul> <li> <a href="#org846e71c">The  <code>.+</code> Repeater</a></li>
 <li> <a href="#orga10a0f8">The  <code>++</code> Repeater</a></li>
</ul></li>
 <li> <a href="#org41e3355">Marking Tasks with Repeaters  <code>DONE</code> (For Good)</a></li>
</ul></li>
 <li> <a href="#orgee526f4">Further Reading</a></li>
</ul></div>
</nav> <div id="outline-container-org4e398f9" class="outline-2">
 <h2 id="org4e398f9">Background</h2>
 <div class="outline-text-2" id="text-org4e398f9">
 <div class="PREVIEW" id="orgfab30b8">
 <p>
I recently started using org-mode to keep track of a few habits (morning
meditation, getting some sunlight and exercise before my morning coffee, etc.)
and needed to make use of org-mode's calendar features to do so. I've previously
set deadlines and scheduled dates for my  <code>TODO</code> entries, but have seldom used
repeat intervals. My early attempts (  <code>date +1d</code>) worked fine but required some
extra steps if I ever missed a day. This post discusses the  <code>.+</code> and  <code>++</code>
-style repeat intervals, which allow more control over what happens when you
complete a task after the scheduled date.
</p>

</div>
</div>
</div>
 <div id="outline-container-org3774701" class="outline-2">
 <h2 id="org3774701">Review: Dates, Schedules, and Deadlines in Emacs Org-Mode</h2>
 <div class="outline-text-2" id="text-org3774701">
 <p>
The  <a href="https://orgmode.org/manual/Dates-and-Times.html">org-mode manual</a> provides plenty of details on the basics of dates and
times. Here's a quick review:
</p>
 <ul class="org-ul"> <li> <p>
Add a  <b>timestamp</b> with only the date to an org-mode entry with  <code><C-c> .</code>. A
timestamp entry with a  <i>time</i> can be added with  <code><C-u><C-c> .</code>. While there are
 <a href="https://orgmode.org/manual/Creating-Timestamps.html">plenty of methods</a> for modifying timestamps after creation, I typically create
the timestamp and then modify it, if needed, with  <code>S-LEFT/RIGHT/UP/DOWN</code> to
change the day (forward/back) or whichever element of the timestamp the cursor
is located on (up/down).
</p>

 <p>
Another useful timestamp format is  <code><C-c> ! (org-time-stamp-inactive</code>), which
inserts an  <i>inactive</i> timestamp (represented with square rather than angled
brackets; e.g.  <code>[2022-01-16 Sun]</code> rather than  <code><2022-01-16 Sun></code>). Inactive
timestamps work the same as active timestamps, except that they do not appear
on the org-agenda.
</p></li>
 <li>Two timestamps connected by  <code>--</code> make up a  <b>range</b>
(e.g.  <code><2022-02-12 Sat>--<2022-01-16 Sun></code>). A range will appear on the agenda
on the start and stop dates and on all dates in the range.</li>
 <li> <p>
Add a  <b>scheduled</b> date to a headline with  <code><C-c><C-s></code> and a  <b>deadline</b> with
 <code><C-c><C-d></code>. Again, there are  <a href="https://orgmode.org/manual/Deadlines-and-Scheduling.html">plenty of details</a> in the manual. Both of these
types of timestamps affect how the timestamp appears in the agenda. In short,
a "scheduled" headline appears on the date of the timestamp and on every day
following until the entry is marked  <code>DONE</code>. A "deadline" timestamp on a headline
will start appearing in the agenda  <code>org-deadline-warning-days</code> before the
deadline timestamp and will appear daily until it is marked  <code>DONE</code>.
</p>

 <p>
Conceptually, a "deadline" in org mode comports with the common use of the
word: it is the date when a task is supposed to be finished. The meaning of
"scheduled," on the other hand, specifically refers to the date when a task is
to be started. It is not meant to be used in the sense of "scheduling an
appointment." A regular timestamp is better suited for this use. Recall: a
 <i>scheduled</i> headline will appear in the agenda  <i>even after the scheduled date</i>,
which is not especially useful for an event (again, like a meeting or
appointment) that occurs  <i>on</i> a given date.
</p></li>
</ul></div>
</div>
 <div id="outline-container-org4964cda" class="outline-2">
 <h2 id="org4964cda">Repeat Intervals</h2>
 <div class="outline-text-2" id="text-org4964cda">
 <p>
Org-mode makes it possible to schedule recurring events without manually
specifying each repetition date. There are three key formats for repeated
events. Regardless of the format, the main idea is to add a repetition interval
to the timestamp. A repetition interval combines a number with a unit of time to
specify how often a timestamp/schedule/deadline should be repeated. For example:
</p>
 <ul class="org-ul"> <li> <code><2022-01-16 Sun +1d></code> will repeat daily.</li>
 <li> <code><2022-01-29 Sat +5d></code> will repeat every five days.</li>
 <li> <code><2022-01-29 Sat +1y></code> will repeat yearly.</li>
</ul> <p>
When specifying repeat intervals,  <code>y</code> means "yearly",  <code>m</code> means "monthly",  <code>w</code> means
"weekly",  <code>d</code> means "daily", and  <code>h</code> means "hourly." Prepending these values with
 <code>+<number></code> tells how often the event should be repeated.
</p>
</div>
 <div id="outline-container-orgd85ac81" class="outline-3">
 <h3 id="orgd85ac81">Different Types of Repeat Intervals</h3>
 <div class="outline-text-3" id="text-orgd85ac81">
 <p>
Here's where I ran into trouble. I scheduled some events as daily "habits." For
example, I wanted to take a walk each morning, so I included the following in my
planner file:
</p>

 <div class="org-src-container">
 <pre class="src src-org"> <span class="org-org-level-1">* </span> <span class="org-org-level-1"> <span class="org-org-todo">TODO</span></span> <span class="org-org-level-1"> Walk 1000 steps before coffee</span>
 <span class="org-org-special-keyword">SCHEDULED:</span>  <span class="org-org-date"><2022-01-29 Sat></span>
</pre>
</div>

 <p>
The idea was that, each morning, I would take a walk and mark the task as  <code>DONE</code>,
at which point the date would advance to the next day. This worked fine for a
while, but eventually I missed a day. Suppose I was supposed to walk on
 <code><2022-01-25 Tue></code> but, instead, I got up and immediately started working on my
computer. Before I knew it, it was after noon and I'd only walked between the
coffeepot and the computer. But I didn't give up, and I took a morning walk
again on  <code><2022-01-29 Sat></code>. Here's what happens on  <code><2022-01-29 Sat></code>:
</p>

 <p>
 <b>State before marking  <code>DONE</code>:</b>
</p>
 <div class="org-src-container">
 <pre class="src src-org"> <span class="org-org-level-1">* </span> <span class="org-org-level-1"> <span class="org-org-todo">TODO</span></span> <span class="org-org-level-1"> Walk 1000 steps before coffee</span>
 <span class="org-org-special-keyword">SCHEDULED:</span>  <span class="org-org-date"><2022-01-25 Tue +1d></span>
</pre>
</div>

 <p>
 <b>State after marking  <code>DONE</code>:</b>
</p>

 <div class="org-src-container">
 <pre class="src src-org"> <span class="org-org-level-1">* </span> <span class="org-org-level-1"> <span class="org-org-todo">TODO</span></span> <span class="org-org-level-1"> Walk 1000 steps before coffee</span>
 <span class="org-org-special-keyword">SCHEDULED:</span>  <span class="org-org-date"><2022-01-26 Wed +1d></span>
 <span class="org-org-drawer">:PROPERTIES:</span>
 <span class="org-org-special-keyword">:LAST_REPEAT:</span>  <span class="org-org-date">[2022-01-29 Sat 09:11]</span>
 <span class="org-org-drawer">:END:</span>
- State "DONE"       from "TODO"        <span class="org-org-date">[2022-01-29 Sat 09:11]</span>
</pre>
</div>

 <p>
The scheduled date advances by one day, but that day is still in the past. If
I really,  <i>really</i> need to account for every day, maybe this is what I want. I
could fill out the rest of the days between 2022-01-25 and 2022-01-29 for the
sake of completeness. But oftentimes, if I don't mark something as done, it's
because  <i>I haven't done it</i>. I want to indicate that I completed the task  <i>today</i>
and I plan to complete the task again  <i>tomorrow</i>.
</p>

 <p>
There are two special repeaters for situations like this.
</p>
</div>
 <div id="outline-container-org846e71c" class="outline-4">
 <h4 id="org846e71c">The  <code>.+</code> Repeater</h4>
 <div class="outline-text-4" id="text-org846e71c">
 <p>
Instead of scheduling with  <code>+1d</code>, we can use  <code>.+1d</code> to specify that, after we mark a
task  <code>DONE</code> it should advance by exactly one day from the date (and time, if the
timestamp includes a time) when we marked it  <code>DONE</code>. Let's walk through an
example. Let's say I was supposed to clean the kitchen on Sunday, January 9, and
weekly thereafter. But suppose I didn't get to it until Saturday, January 29.
</p>

 <p>
 <b>State before marking  <code>DONE</code>:</b>
</p>
 <div class="org-src-container">
 <pre class="src src-org"> <span class="org-org-level-1">* </span> <span class="org-org-level-1"> <span class="org-org-todo">TODO</span></span> <span class="org-org-level-1"> Clean the Kitchen</span>
 <span class="org-org-special-keyword">SCHEDULED:</span>  <span class="org-org-date"><2022-01-09 Sun .+1w></span>
</pre>
</div>

 <p>
 <b>State after marking  <code>DONE</code>:</b>
</p>
 <div class="org-src-container">
 <pre class="src src-org"> <span class="org-org-level-1">* </span> <span class="org-org-level-1"> <span class="org-org-todo">TODO</span></span> <span class="org-org-level-1"> Clean the Kitchen</span>
 <span class="org-org-special-keyword">SCHEDULED:</span>  <span class="org-org-date"><2022-02-05 Sat .+1w></span>
 <span class="org-org-drawer">:PROPERTIES:</span>
 <span class="org-org-special-keyword">:LAST_REPEAT:</span>  <span class="org-org-date">[2022-01-29 Sat 09:28]</span>
 <span class="org-org-drawer">:END:</span>
- State "DONE"       from "TODO"        <span class="org-org-date">[2022-01-29 Sat 09:28]</span>
</pre>
</div>
 <p>
A couple of noteworthy things happened here:
</p>
 <ul class="org-ul"> <li>The next scheduled date advanced to a  <i>future</i> date one week from the
 <code>LAST_REPEAT</code> date.</li>
 <li>The next scheduled date did  <i>not</i> schedule for the next  <i>Sunday</i> but for the date
one week from when it was marked  <code>DONE</code>, a Saturday.</li>
</ul></div>
</div>
 <div id="outline-container-orga10a0f8" class="outline-4">
 <h4 id="orga10a0f8">The  <code>++</code> Repeater</h4>
 <div class="outline-text-4" id="text-orga10a0f8">
 <p>
The  <code>++</code> repeater is very similar to the  <code>.+</code> repeater insofar as it will also
advance the scheduled date into the future. However, it will  <i>also</i> match the
original scheduled time and day of the week. Here's the previous example,
updated to use the  <code>++</code> syntax.
</p>

 <p>
 <b>State before marking  <code>DONE</code>:</b>
</p>
 <div class="org-src-container">
 <pre class="src src-org"> <span class="org-org-level-1">* </span> <span class="org-org-level-1"> <span class="org-org-todo">TODO</span></span> <span class="org-org-level-1"> Clean the Kitchen</span>
 <span class="org-org-special-keyword">SCHEDULED:</span>  <span class="org-org-date"><2022-01-09 Sun ++1w></span>
</pre>
</div>

 <p>
 <b>State after marking  <code>DONE</code>:</b>
</p>
 <div class="org-src-container">
 <pre class="src src-org"> <span class="org-org-level-1">* </span> <span class="org-org-level-1"> <span class="org-org-todo">TODO</span></span> <span class="org-org-level-1"> Clean the Kitchen</span>
 <span class="org-org-special-keyword">SCHEDULED:</span>  <span class="org-org-date"><2022-01-30 Sun ++1w></span>
 <span class="org-org-drawer">:PROPERTIES:</span>
 <span class="org-org-special-keyword">:LAST_REPEAT:</span>  <span class="org-org-date">[2022-01-29 Sat 09:35]</span>
 <span class="org-org-drawer">:END:</span>
- State "DONE"       from "TODO"        <span class="org-org-date">[2022-01-29 Sat 09:35]</span>
</pre>
</div>

 <p>
It is now scheduled for the next Sunday (even though that's only one day after
the  <code>LAST_REPEAT</code> date). In other words, it will always advance into the future,
but it will match the scheduled day of the week instead of advancing the
scheduled date exactly be the repeat interval.
</p>

 <p>
One consequence of this behavior is that the next  <code>SCHEDULED</code> date might be less
than the repeater interval in the future relative to the  <code>LAST_REPEAT</code> date. For
example, if I schedule cleaning each Sunday, but I don't get to it until
Wednesday one week, the next repeat will still be scheduled for the following
Sunday, only four days later.
</p>
</div>
</div>
</div>
 <div id="outline-container-org41e3355" class="outline-3">
 <h3 id="org41e3355">Marking Tasks with Repeaters  <code>DONE</code> (For Good)</h3>
 <div class="outline-text-3" id="text-org41e3355">
 <p>
You may want to end a repeated task—stop it from appearing in your agenda and
mark it  <code>DONE</code> —without entirely deleting the task. Maybe you want to maintain the
task history or re-activate the task in the future. There are two approaches to
this.
</p>

 <ol class="org-ol"> <li>Mark the task as  <code>DONE</code> by invoking the  <code>org-todo</code> function with the numeric
prefix of  <code>-1</code>. You can do this with:
 <ul class="org-ul"> <li> <code><C-u> -1 <C-t></code> or  <code><C--1><C-t></code>, or</li>
 <li> <code><C-u> org-todo</code> or  <code><C--1> org-todo</code>,
and then changing the state to  <code>DONE</code>. ( <code><C--1></code> means to hold Control and type
 <code>-1</code>).</li>
</ul></li>
 <li>Deactivate the timestamp. Org will not repeat inactive timestamps. You can do
this by placing the cursor on one of the angle brackets  <code><,></code> on either side of
the timestamp and pressing the up arrow. This will change the angle brackets
to square brackets, indicating an inactive timestamp.</li>
</ol></div>
</div>
</div>
 <div id="outline-container-orgee526f4" class="outline-2">
 <h2 id="orgee526f4">Further Reading</h2>
 <div class="outline-text-2" id="text-orgee526f4">
 <p>
The org-mode manual is the best place to learn more about timestamps, schedules,
and deadlines in general and repeated tasks in particular. Here are some places
to start:
</p>
 <ul class="org-ul"> <li> <a href="https://orgmode.org/manual/Timestamps.html">Timestamps</a></li>
 <li> <a href="https://orgmode.org/manual/Repeated-tasks.html">Repeated Tasks</a></li>
 <li> <a href="https://orgmode.org/manual/Dates-and-Times.html">Dates and Times (Index Page)</a></li>
</ul></div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20220116-org-time.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20220116-org-time.html</guid>
  <pubDate>Sat, 29 Jan 2022 08:00:00 +0000</pubDate>
</item>
<item>
  <title>Org Babel Source Blocks for R</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Org Babel Source Blocks for R</h1>
 <p class="subtitle" role="doc-subtitle">December 11, 2021</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#org074796d">Background</a></li>
 <li> <a href="#orge6a22ba">R Source Headers</a>
 <ul> <li> <a href="#orgfdcac1e">Code</a>
 <ul> <li> <a href="#org7c0c8b9">Displaying Tabular Output</a></li>
</ul></li>
 <li> <a href="#org4eb3e35">Figures</a>
 <ul> <li> <a href="#org685d349">Base R</a></li>
 <li> <a href="#orgadf1e37">Ggplot and Lattice</a></li>
</ul></li>
</ul></li>
 <li> <a href="#orgfa31c73">An Alternative: Emacs-Jupyter</a></li>
</ul></div>
</nav> <div id="outline-container-org074796d" class="outline-2">
 <h2 id="org074796d">Background</h2>
 <div class="outline-text-2" id="text-org074796d">
 <div class="preview" id="org60f5897">
 <p>
 <a href="https://orgmode.org/worg/org-contrib/babel/intro.html">Org Babel</a> is one of the best tools available for  <a href="https://www-cs-faculty.stanford.edu/~knuth/lp.html">literate programming</a>. As a data scientist, I use it
as a plain-text alternative to Jupyter notebooks. Org-mode files are much easier to track with
version control and don't require the overhead of a browser. There are tradeoffs: Jupyter notebooks
handle the display of different types of output (text results, images, interactive figures, etc.) in
a way that is both seamless and visually appealing. Displaying figures at all can be a challenge
when getting started with org-babel. This post covers the basics of using org-babel for common data
science tasks in R.
</p>

</div>

 <p>
I will specifically talk about using org-babel in interactive (session-based) evaluation, much like
how you would use a Jupyter notebook. Each org-babel source block is executed in the same
environment, so data objects persist between source blocks. Some specific org-babel behaviors will
depend on the specifics of your org-babel configuration; you can see mine below <sup> <a id="fnr.1" class="footref" href="#fn.1" role="doc-backlink">1</a></sup>.
</p>

 <p>
 <i>For notes on setting up org-babel to work with R, read  <a href="https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-R.html">this article</a>.</i>
</p>
</div>
</div>
 <div id="outline-container-orge6a22ba" class="outline-2">
 <h2 id="orge6a22ba">R Source Headers</h2>
 <div class="outline-text-2" id="text-orge6a22ba">
 <p>
I tend to use two different header configurations, one for code output and one for figures.
</p>
</div>
 <div id="outline-container-orgfdcac1e" class="outline-3">
 <h3 id="orgfdcac1e">Code</h3>
 <div class="outline-text-3" id="text-orgfdcac1e">
 <div class="org-src-container">
 <pre class="src src-org"> <span class="org-org-block-begin-line">#+begin_src R :session mysession
</span> <span class="org-org-block"> <span class="org-comment-delimiter"># </span></span> <span class="org-org-block"> <span class="org-comment">Code goes here
</span></span> <span class="org-org-block"> <span class="org-function-name">add_1</span></span> <span class="org-org-block"> </span> <span class="org-org-block"> <span class="org-ess-assignment"><-</span></span> <span class="org-org-block"> </span> <span class="org-org-block"> <span class="org-ess-keyword">function</span></span> <span class="org-org-block">(x) {
  x + 1
}

add_1(99)
</span> <span class="org-org-block-end-line">#+end_src</span>
</pre>
</div>

 <p>
This (given my org-babel config) <sup> <a id="fnr.1.100" class="footref" href="#fn.1" role="doc-backlink">1</a></sup> will appear as follows once exported:
</p>

 <div class="org-src-container">
 <pre class="src src-R"> <span class="org-comment-delimiter"># </span> <span class="org-comment">Code goes here
</span> <span class="org-function-name">add_1</span>  <span class="org-ess-assignment"><-</span>  <span class="org-ess-keyword">function</span>(x) {
  x + 1
}

add_1(99)
</pre>
</div>

 <pre class="example">
100
</pre>
</div>
 <div id="outline-container-org7c0c8b9" class="outline-4">
 <h4 id="org7c0c8b9">Displaying Tabular Output</h4>
 <div class="outline-text-4" id="text-org7c0c8b9">
 <p>
When not dealing with plotting outputs, there are two main header options for result formatting that I tend
to use:  <code>:results output</code> and  <code>:results value</code> (the default). You can find details on these two modes
 <a href="https://orgmode.org/manual/Results-of-Evaluation.html">here</a>.
</p>

 <p>
The biggest differences between the two, in my experience, are visible when displaying or exporting
tabular data (e.g. a  <code>data.frame</code> or  <code>tibble</code>). I prefer the  <code>:results output</code> formatting for interactive
work within an org file, simply because it is more compact.  <code>:results value</code> tends to result in more
readable exports, though.
</p>
</div>
 <ul class="org-ul"> <li> <a id="org6ea3738"></a>Value <br></br> <div class="outline-text-5" id="text-org6ea3738">
 <p>
(With  <code>:results value</code> header arg).
</p>
 <div class="org-src-container">
 <pre class="src src-R">head(mtcars)
</pre>
</div>

 <table> <colgroup> <col class="org-right"></col> <col class="org-right"></col> <col class="org-right"></col> <col class="org-right"></col> <col class="org-right"></col> <col class="org-right"></col> <col class="org-right"></col> <col class="org-right"></col> <col class="org-right"></col> <col class="org-right"></col> <col class="org-right"></col></colgroup> <thead> <tr> <th scope="col" class="org-right">mpg</th>
 <th scope="col" class="org-right">cyl</th>
 <th scope="col" class="org-right">disp</th>
 <th scope="col" class="org-right">hp</th>
 <th scope="col" class="org-right">drat</th>
 <th scope="col" class="org-right">wt</th>
 <th scope="col" class="org-right">qsec</th>
 <th scope="col" class="org-right">vs</th>
 <th scope="col" class="org-right">am</th>
 <th scope="col" class="org-right">gear</th>
 <th scope="col" class="org-right">carb</th>
</tr></thead> <tbody> <tr> <td class="org-right">21</td>
 <td class="org-right">6</td>
 <td class="org-right">160</td>
 <td class="org-right">110</td>
 <td class="org-right">3.9</td>
 <td class="org-right">2.62</td>
 <td class="org-right">16.46</td>
 <td class="org-right">0</td>
 <td class="org-right">1</td>
 <td class="org-right">4</td>
 <td class="org-right">4</td>
</tr> <tr> <td class="org-right">21</td>
 <td class="org-right">6</td>
 <td class="org-right">160</td>
 <td class="org-right">110</td>
 <td class="org-right">3.9</td>
 <td class="org-right">2.875</td>
 <td class="org-right">17.02</td>
 <td class="org-right">0</td>
 <td class="org-right">1</td>
 <td class="org-right">4</td>
 <td class="org-right">4</td>
</tr> <tr> <td class="org-right">22.8</td>
 <td class="org-right">4</td>
 <td class="org-right">108</td>
 <td class="org-right">93</td>
 <td class="org-right">3.85</td>
 <td class="org-right">2.32</td>
 <td class="org-right">18.61</td>
 <td class="org-right">1</td>
 <td class="org-right">1</td>
 <td class="org-right">4</td>
 <td class="org-right">1</td>
</tr> <tr> <td class="org-right">21.4</td>
 <td class="org-right">6</td>
 <td class="org-right">258</td>
 <td class="org-right">110</td>
 <td class="org-right">3.08</td>
 <td class="org-right">3.215</td>
 <td class="org-right">19.44</td>
 <td class="org-right">1</td>
 <td class="org-right">0</td>
 <td class="org-right">3</td>
 <td class="org-right">1</td>
</tr> <tr> <td class="org-right">18.7</td>
 <td class="org-right">8</td>
 <td class="org-right">360</td>
 <td class="org-right">175</td>
 <td class="org-right">3.15</td>
 <td class="org-right">3.44</td>
 <td class="org-right">17.02</td>
 <td class="org-right">0</td>
 <td class="org-right">0</td>
 <td class="org-right">3</td>
 <td class="org-right">2</td>
</tr> <tr> <td class="org-right">18.1</td>
 <td class="org-right">6</td>
 <td class="org-right">225</td>
 <td class="org-right">105</td>
 <td class="org-right">2.76</td>
 <td class="org-right">3.46</td>
 <td class="org-right">20.22</td>
 <td class="org-right">1</td>
 <td class="org-right">0</td>
 <td class="org-right">3</td>
 <td class="org-right">1</td>
</tr></tbody></table> <p>
Note that you may also need to include  <code>:colnames yes</code> in order to ensure the column names display
correctly.
</p>
</div>
</li>

 <li> <a id="orgacccfd5"></a>Output <br></br> <div class="outline-text-5" id="text-orgacccfd5">
 <p>
(With  <code>:results output</code> header arg).
</p>
 <div class="org-src-container">
 <pre class="src src-R">head(mtcars)
</pre>
</div>

 <pre class="example">
                   mpg cyl disp  hp drat    wt  qsec vs am gear carb
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1
</pre>
</div>
</li>
</ul></div>
</div>

 <div id="outline-container-org4eb3e35" class="outline-3">
 <h3 id="org4eb3e35">Figures</h3>
 <div class="outline-text-3" id="text-org4eb3e35">
 <p>
I don't find the display and exporting of figures particularly intuitive and finding help tends to
be challening because of differences depending on the plotting system and because of changes over
time.  <i>This approach works as of December 2021</i>. Further details on exporting org source blocks can be
found  <a href="https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-R.html#org7fbd9c2">here</a>.
</p>
</div>
 <div id="outline-container-org685d349" class="outline-4">
 <h4 id="org685d349">Base R</h4>
 <div class="outline-text-4" id="text-org685d349">
 <p>
Using Base R graphics, the following header argument will produce a link to a file which can then be
previewed in your org-mode buffer and exported.
</p>

 <p>
 <code>#+begin_src R :results file graphics :file path/to/file.png</code>
</p>

 <p>
Here's an example.
</p>

 <div class="org-src-container">
 <pre class="src src-R">plot(mpg~hp, data=mtcars, main= <span class="org-string">"Sample Figure"</span>)
grid()
</pre>
</div>


 <figure id="org5547100"> <img src="./figures/20211209-R-babel/fig1.png" alt="Base R scatter plot of mtcars mpg versus hp with a gridded background, titled Sample Figure"></img></figure></div>
 <ul class="org-ul"> <li> <a id="org16139c3"></a>Setting Graphical Parameters with Header Arguments <br></br> <div class="outline-text-5" id="text-org16139c3">
 <p>
We can also set some graphical parameters such as figure height and width through the header
arguments. For example, to set the with, height, and resolution, we add  <code>:width 6 :height 3 :units in
:res 100</code>. You can find a complete list of graphical header arguments  <a href="https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-R.html#org075fa45">here</a>.
</p>

 <div class="org-src-container">
 <pre class="src src-R">plot(mpg~hp, data=mtcars, main= <span class="org-string">"Sample Figure"</span>)
grid()
</pre>
</div>


 <figure id="org4c02dd2"> <img src="./figures/20211209-R-babel/fig2.png" alt="Wider, shorter Base R scatter plot of mtcars mpg versus hp, titled Sample Figure"></img></figure></div>
</li>
</ul></div>

 <div id="outline-container-orgadf1e37" class="outline-4">
 <h4 id="orgadf1e37">Ggplot and Lattice</h4>
 <div class="outline-text-4" id="text-orgadf1e37">
 <p>
Can we just use this approach for everything? From  <a href="https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-R.html#org075fa45">the documentation</a>,
</p>

 <blockquote>
 <p>
If the source code block uses grid-based R graphics, e.g., the lattice and ggplot2 packages, then
care must be taken either to  <code>print()</code> the graphics object, specify  <code>:results</code> output, or run the code
in a  <code>:session</code>. This is because the graphics functions from lattice and ggplot2 return objects that
must be explicitly printed to see them, using the print function. This happens automatically when
run interactively, e.g.,  <code>:session</code>, but when called inside another function, it does not.
</p>
</blockquote>

 <p>
So in our case—as we're interested in  <code>:session</code> evaluation—we  <i>can</i> use this approach for
everything. But care must be taken (i.e. read the documentation) if attempting to use ggplot or
lattice graphics outside of a  <code>:session</code> context.
</p>

 <div class="org-src-container">
 <pre class="src src-R"> <span class="org-ess-modifiers">library</span>(ggplot2)
ggplot(data=mtcars, mapping=aes(x=hp, y=mpg)) + geom_point()
</pre>
</div>


 <figure id="org46a04a6"> <img src="./figures/20211209-R-babel/fig3.png" alt="ggplot2 scatter plot of mtcars mpg versus hp with black points on a gray gridded panel"></img></figure></div>
</div>
</div>
</div>

 <div id="outline-container-orgfa31c73" class="outline-2">
 <h2 id="orgfa31c73">An Alternative: Emacs-Jupyter</h2>
 <div class="outline-text-2" id="text-orgfa31c73">
 <p>
The excellent  <a href="https://github.com/nnicandro/emacs-jupyter">emacs-jupyter</a> package is a solid alternative to the approaches described above. To use
it for R, install the  <code>emacs-jupyter</code> package (e.g. with  <code>(use-package jupyter)</code>. In R, install  <code>IRkernel</code>
(make sure to follow all of the instructions  <a href="https://github.com/IRkernel/IRkernel">here</a> for registering the kernel). Update
 <code>org-babel-load-languages</code> to include  <code>jupyter</code>. E.g.:
</p>

 <div class="org-src-container">
 <pre class="src src-emacs-lisp">(org-babel-do-load-languages
 'org-babel-load-languages
 '((emacs-lisp . t)
   (julia . t)
   (python . t)
   (jupyter . t)))
</pre>
</div>

 <p>
Then you can set up R blocks with:
</p>

 <p>
 <code>#+begin_src jupyter-R :session my-jupyter-session</code>
</p>

 <p>
e.g.
</p>

 <div class="org-src-container">
 <pre class="src src-jupyter-R">1+1
</pre>
</div>

 <pre class="example">
[1] 2
</pre>


 <p>
Using  <code>emacs-jupyter</code> results in a significantly different experience, which warrants a post of its
own (especially because the documentation for using  <code>emacs-jupyter</code> with R is not easy to find or
follow).
</p>

 <p>
A couple of reasons  <code>emacs-jupyter</code> is worth considering:
</p>
 <ul class="org-ul"> <li>if a code block generates a figure, you don't need to specify a filename/path or use any fancy
header arguments to make sure the image appears in your org buffer. The image is named and saved
automatically to  <code>org-babel-jupyter-resource-directory</code>. This makes exploratory analysis
comparatively seamless. I spend much less time tripping over header args with  <code>emacs-jupyter</code>.</li>
 <li>Accessibility of help: pressing  <code><M-i></code> with the cursor over an object opens a new window with
documentation.</li>
</ul></div>
</div>
 <div id="footnotes">
 <h2 class="footnotes">Footnotes: </h2>
 <div id="text-footnotes">

 <div class="footdef"> <sup> <a id="fn.1" class="footnum" href="#fnr.1" role="doc-backlink">1</a></sup> <div class="footpara" role="doc-footnote"> <p class="footpara">
Some of the above will be affected by the specifics of my org-babel config. Here it is:
</p>

 <div class="org-src-container">
 <pre class="src src-org">;; org-babel
(org-babel-do-load-languages
'org-babel-load-languages
'(
    (emacs-lisp . t)
    (R          . t)
    (python     . t)
    (org        . t)
    (dot        . t)
    (sql        . t)
    (http       . t)
    (latex      . t)
    (js         . t)
    (shell      . t)
    (C          . t)
    (jupyter    . t)
    ))
(setq org-babel-default-header-args '((:eval . "never-export")
                                    (:exports . "both")
                                    (:cache . "no")
                                    (:results . "replace"))
    org-src-fontify-natively t
    org-src-preserve-indentation t
    org-src-tab-acts-natively t
    org-src-window-setup 'current-window
    org-confirm-babel-evaluate nil)

(eval-after-load 'org
(add-hook 'org-babel-after-execute-hook 'org-redisplay-inline-images))
</pre>
</div>

 <ul class="org-ul"> <li>I have it set to export both code and output ( <code>~:exports . "both"</code>). The  <code>"never-export"</code> part
specifies that the code should  <i>not</i> be re-run run during export. I try to ensure that the output is
what I want it to be prior to export, but that's just what works for my workflow.
 <ul class="org-ul"> <li>I noticed this was  <i>not</i> being respected when exporting to html with  <code>ox-publish</code>. It was necessary
to add  <code>(setq org-export-use-babel nil)</code> to prevent the export from triggering re-execution of all
of the source blocks.</li>
</ul></li>
 <li> <code>org-confirm-babel-evaluate-nil</code> results in org babel not asking for confirmation every time I
execute a code block ( <a href="https://orgmode.org/manual/Code-Evaluation-Security.html">details here</a>).</li>
 <li> <code>org-src-preserve-indentation</code> prevents org-babel from automatically indenting code blocks. The
auto-indentation  <i>can</i> look nice, but I found that, more often than not, it resulted in more
challenges in code intentation than it was worth.</li>
 <li>You can look up anything else you're curious about!  <code><C-h>-f</code> and  <code><C-h>-v</code> are your friends.</li>
</ul></div></div>


</div>
</div></div>]]></description>
  <link>https://danliden.com/posts/./20211209-R-babel.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20211209-R-babel.html</guid>
  <pubDate>Sat, 11 Dec 2021 08:00:00 +0000</pubDate>
</item>
<item>
  <title>Made with Org-Mode</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Made with Org-Mode</h1>
 <p class="subtitle" role="doc-subtitle">December 3, 2021</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#org3bf06d1">Background</a></li>
 <li> <a href="#org4ab6633">First Steps</a>
 <ul> <li> <a href="#orgca6f55f">Ox-Publish</a></li>
 <li> <a href="#org2f6eb6f">GitHub Pages</a></li>
</ul></li>
 <li> <a href="#org480f105">Some Simple Customization</a>
 <ul> <li> <a href="#org8149548">CSS theme</a></li>
 <li> <a href="#org9c26dde">Recent Posts</a>
 <ul> <li> <a href="#orge608a4c">Sitemap Configuration</a></li>
 <li> <a href="#orgf63564c">Sitemap Entry Formatting</a></li>
 <li> <a href="#orgd8d72ab">Sitemap List Formatting</a></li>
 <li> <a href="#org49ff97f">Previews</a></li>
</ul></li>
</ul></li>
 <li> <a href="#org8b35c37">Putting It All Together</a></li>
 <li> <a href="#orgef3db15">What's Next?</a>
 <ul> <li> <a href="#org44344d3"> <span class="done DONE">DONE</span> Add navigation buttons to return to the home page/about page/archive page/etc. from any page. (incidentally, if you want to get back home, here's the link).</a></li>
 <li> <a href="#org9a9c679"> <span class="done DONE">DONE</span> Set up a good system for managing images (e.g. for data visualizations from R/Python)</a></li>
 <li> <a href="#org3308be8"> <span class="todo TODO">TODO</span> Set up and test LaTeX exporting for formulas etc.</a></li>
 <li> <a href="#org5f6646c"> <span class="todo TODO">TODO</span> Add a portfolio page showing some of my past work</a></li>
 <li> <a href="#org924736d"> <span class="todo TODO">TODO</span> Make a more visually interesting home page</a></li>
</ul></li>
</ul></div>
</nav> <div id="outline-container-org3bf06d1" class="outline-2">
 <h2 id="org3bf06d1">Background</h2>
 <div class="outline-text-2" id="text-org3bf06d1">
 <div class="PREVIEW" id="orgb5259ec">
 <p>
I finally made a personal site using org-mode's built-in  <code>ox-publish</code> exporter.
</p>

 <p>
I've written my personal website with org-mode for years (it is, after all,  <a href="https://karl-voit.at/2017/09/23/orgmode-as-markup-only/">one of the most
reasonable markup languages to use for text</a>). But until this point, I've used Hugo (with the  <code>ox-Hugo</code>
exporter). It worked fine, but it always seemed  <i>just a little bit too complicated</i> for my needs. I
wanted to find something where I could basically understand all of the components and where the gap
between my org-mode files and the published output was as small as possible. I wanted to focus more
on the writing and less on understanding the framework.
</p>

</div>
</div>
</div>

 <div id="outline-container-org4ab6633" class="outline-2">
 <h2 id="org4ab6633">First Steps</h2>
 <div class="outline-text-2" id="text-org4ab6633">
</div>
 <div id="outline-container-orgca6f55f" class="outline-3">
 <h3 id="orgca6f55f">Ox-Publish</h3>
 <div class="outline-text-3" id="text-orgca6f55f">
 <p>
 <a href="https://systemcrafters.net/publishing-websites-with-org-mode/building-the-site/">This great guide</a> from System Crafters got me started with  <code>ox-publish</code>. The very short post
how to use  <code>ox-publish</code> to set up a basic site;  <code>htmlize</code> to correctly render code blocks, and
 <code>simple-httpd</code> to preview the site locally. I recommend starting here if you're interested in making
your own site with org-mode.
</p>
</div>
</div>

 <div id="outline-container-org2f6eb6f" class="outline-3">
 <h3 id="org2f6eb6f">GitHub Pages</h3>
 <div class="outline-text-3" id="text-org2f6eb6f">
 <p>
 <a href="https://systemcrafters.net/publishing-websites-with-org-mode/automated-site-publishing/">The followup post</a> is just as useful—it describes the process of publishing the site with GitHub
Pages (or SourceHut; I opted for GitHub Pages). There was one minor point missing from this
article. The described GitHub action runs the site's build script and commits the  <code>public</code> directory
to a new branch. It was, therefore, necessary to add the  <i>local</i> version of the public branch
(which we preview with  <code>simple-httpd</code>) to our  <code>gitignore</code> file to avoid conflicts. Otherwise, this guide
was simple to follow and worked perfectly.
</p>
</div>
</div>
</div>

 <div id="outline-container-org480f105" class="outline-2">
 <h2 id="org480f105">Some Simple Customization</h2>
 <div class="outline-text-2" id="text-org480f105">
 <p>
There were a few simple design and organization changes I wanted before I started writing: a simple
and readable theme; a list of recent posts with short "preview" snippets, and a link to a post
archive.
</p>
</div>

 <div id="outline-container-org8149548" class="outline-3">
 <h3 id="org8149548">CSS theme</h3>
 <div class="outline-text-3" id="text-org8149548">
 <p>
I opted to use  <a href="https://gongzhitaao.org/orgcss/">orgcss</a>, at least for now. It's a stylesheet explicitly designed for use with
org-exported HTML files. It looks (to me) quite a bit nicer than the default and it works well
without any additional configuration. I'm sure I'll want to make some changes in the future, but
it's a great place to start.
</p>

 <p>
I applied this stylesheet to all of the exported .org files by adding the following line to my
 <code>build-site.el</code> configuration file:
</p>

 <div class="org-src-container">
 <pre class="src src-emacs-lisp"> <span class="org-comment-delimiter">;; </span> <span class="org-comment">org-site/build-site.el
</span> <span class="org-comment-delimiter">;; </span> <span class="org-comment">...
</span>( <span class="org-keyword">setq</span> org-html-head  <span class="org-string">"<link rel=\"stylesheet\" type=\"text/css\" href=\"https://gongzhitaao.org/orgcss/org.css\"/>"</span>)
</pre>
</div>
</div>
</div>

 <div id="outline-container-org9c26dde" class="outline-3">
 <h3 id="org9c26dde">Recent Posts</h3>
 <div class="outline-text-3" id="text-org9c26dde">
 <p>
I wanted to include a few recent posts on the homepage and separately link to the post archive. I
also wanted each of these custom posts to have a short "preview"—a paragraph or so of my choosing
from the post. I adapted my approach to this from  <a href="https://thibaultmarin.github.io/blog/posts/2016-11-13-Personal_website_in_org.html#sec-org-setup">this post</a> (not sure of the author) and  <a href="https://loomcom.com/blog/0110_emacs_blogging_for_fun_and_profit.html">this post</a>
by Seth Morabito ( <a href="https://twitter.com/twylo/">@twylo</a>).
</p>

 <p>
To include the recent posts, I included the first 25 lines of the automatically-generated
 <code>sitemap.org</code> on my index page with:
</p>

 <div class="org-src-container">
 <pre class="src src-org"> <span class="org-org-meta-line">#+INCLUDE: sitemap.org::*posts :lines "-25" :only-contents t</span>
</pre>
</div>
</div>

 <div id="outline-container-orge608a4c" class="outline-4">
 <h4 id="orge608a4c">Sitemap Configuration</h4>
 <div class="outline-text-4" id="text-orge608a4c">
 <p>
I specified the generation of the sitemap using  <code>org-publish-project-alist</code> configuration variable:
</p>

 <div class="org-src-container">
 <pre class="src src-emacs-lisp"> <span class="linenr"> 1: </span> <span class="org-comment-delimiter">;; </span> <span class="org-comment">org-site/build-site.el
 <span class="linenr"> 2: </span></span>( <span class="org-keyword">setq</span> org-publish-project-alist
 <span class="linenr"> 3: </span>      (list
 <span class="linenr"> 4: </span>       (list  <span class="org-string">"org-site:main"</span>
 <span class="linenr"> 5: </span>              <span class="org-comment-delimiter">;; </span> <span class="org-comment">other configuration settings
 <span class="linenr"> 6: </span></span>              <span class="org-builtin">:base-directly:</span>  <span class="org-string">"./content"</span>
 <span class="linenr"> 7: </span>              <span class="org-builtin">:auto-sitemap</span> t
 <span class="linenr"> 8: </span>              <span class="org-builtin">:sitemap-title</span> nil
 <span class="linenr"> 9: </span>              <span class="org-builtin">:sitemap-format-entry</span> 'my/org-publish-org-sitemap-format
 <span class="linenr">10: </span>              <span class="org-builtin">:sitemap-function</span> 'my/org-publish-org-sitemap
 <span class="linenr">11: </span>              <span class="org-builtin">:sitemap-sort-files</span> 'anti-chronologically
 <span class="linenr">12: </span>              <span class="org-builtin">:sitemap-filename</span>  <span class="org-string">"sitemap.org"</span>
 <span class="linenr">13: </span>              <span class="org-builtin">:sitemap-style</span> 'tree)))
</pre>
</div>
</div>
</div>

 <div id="outline-container-orgf63564c" class="outline-4">
 <h4 id="orgf63564c">Sitemap Entry Formatting</h4>
 <div class="outline-text-4" id="text-orgf63564c">
 <p>
You'll notice two functions used to format and publish the sitemap entries.  <code>sitemap-format-entry</code>
takes three arguments ( <code>entry</code>,  <code>style</code>, and  <code>project</code>). We only need to worry about the former. Each
 <code>entry</code> is a file or directory in the  <code>base-directory</code> specified in the  <code>org-publish-project-alist</code>
above. My  <code>my/org-publish-org-sitemap-format</code> defun closely follows the one  <a href="https://thibaultmarin.github.io/blog/posts/2016-11-13-Personal_website_in_org.html#orgace8e3d">here</a>.
</p>

 <div class="org-src-container">
 <pre class="src src-emacs-lisp"> <span class="linenr"> 1: </span> <span class="org-comment-delimiter">;; </span> <span class="org-comment">org-site/build-site.el
 <span class="linenr"> 2: </span></span>( <span class="org-keyword">defun</span>  <span class="org-function-name">my/org-publish-org-sitemap-format</span> (entry style project)
 <span class="linenr"> 3: </span>   <span class="org-doc">"Custom sitemap entry formatting: add date"</span>
 <span class="linenr"> 4: </span>  ( <span class="org-keyword">cond</span> ((not (directory-name-p entry))
 <span class="linenr"> 5: </span>         ( <span class="org-keyword">let</span> ((preview ( <span class="org-keyword">if</span> (my/get-preview (concat  <span class="org-string">"content/"</span> entry))
 <span class="linenr"> 6: </span>                            (my/get-preview (concat  <span class="org-string">"content/"</span> entry))
 <span class="linenr"> 7: </span>                           <span class="org-string">"(No preview)"</span>)))
 <span class="linenr"> 8: </span>         (format  <span class="org-string">"[[file:%s][(%s) %s]]\n%s"</span>
 <span class="linenr"> 9: </span>                 entry
 <span class="linenr">10: </span>                 (format-time-string  <span class="org-string">"%Y-%m-%d"</span>
 <span class="linenr">11: </span>                                     (org-publish-find-date entry project))
 <span class="linenr">12: </span>                 (org-publish-find-title entry project)
 <span class="linenr">13: </span>                 preview)))
 <span class="linenr">14: </span>        ((eq style 'tree)
 <span class="linenr">15: </span>         (file-name-nondirectory (directory-file-name entry)))
 <span class="linenr">16: </span>        (t entry)))
</pre>
</div>

 <p>
This does the following:
</p>
 <ol class="org-ol"> <li>Read in each entry's path</li>
 <li>If the entry is  <i>not</i> a directory:
 <ul class="org-ul"> <li>Check if the  <code>my/get-preview</code> defun returns a value (more on  <code>my/get-preview</code> later)</li>
 <li>Assign the preview text to to the  <code>preview</code> variable if  <code>my/get-preview</code> is not null and assigns
 <code>"(No preview)"</code> to  <code>preview</code> otherwise</li>
 <li>Format the output as a link to the entry with  <code>(Date) Title</code> as the description (using the
 <code>org-publish-find-date</code> and  <code>org-publish-find-title</code> defuns to get the dates/titles of each
entry)</li>
 <li>include the  <code>preview</code> (defined above) after a line break</li>
</ul></li>
 <li>If the entry  <i>is</i> a directory (e.g. if the first condition returns  <code>nil</code>) and if the  <code>sitemap-style</code> is
 <code>tree</code>, return the name of the last subdirectory (e.g. the entry  <code>/projects/org-site/content/posts</code> would
return  <code>posts</code>)</li>
 <li>Otherwise, just return the entry unchanged.</li>
</ol></div>
</div>
 <div id="outline-container-orgd8d72ab" class="outline-4">
 <h4 id="orgd8d72ab">Sitemap List Formatting</h4>
 <div class="outline-text-4" id="text-orgd8d72ab">
 <p>
The entries formatted above are all added to a list (formatted in a tree style to represent the
directory structure). We simply convert this list into an org subtree and publish it to the
 <code>sitemap.org</code> file. The conversion is handled in the  <code>my/org-publish-org-sitemap</code> file (again, adapted
from  <a href="https://thibaultmarin.github.io/blog/posts/2016-11-13-Personal_website_in_org.html#orgace8e3d">here</a>).
</p>

 <div class="org-src-container">
 <pre class="src src-emacs-lisp"> <span class="linenr">1: </span> <span class="org-comment-delimiter">;; </span> <span class="org-comment">org-site/build-site.el
 <span class="linenr">2: </span></span>( <span class="org-keyword">defun</span>  <span class="org-function-name">my/org-publish-org-sitemap</span> (title list)
 <span class="linenr">3: </span>   <span class="org-doc">"Sitemap generation function."</span>
 <span class="linenr">4: </span>  (concat  <span class="org-string">"#+OPTIONS: toc:nil"</span>)
 <span class="linenr">5: </span>  (org-list-to-subtree list))
</pre>
</div>

 <p>
All this does is specify that we do not want a table of contents and that we want our formatted list
of entries (with previews) represented as an org subtree.
</p>
</div>
</div>
 <div id="outline-container-org49ff97f" class="outline-4">
 <h4 id="org49ff97f">Previews</h4>
 <div class="outline-text-4" id="text-org49ff97f">
 <p>
One part we haven't addressed yet is the generation of previews. There are different approaches out
there, but none of them did exactly what I wanted. I borrowed from posts by   <a href="https://loomcom.com/blog/0110_emacs_blogging_for_fun_and_profit.html">Seth Morabito</a> and
especially  <a href="https://ogbe.net/blog/blogging_with_org.html">Dennis Ogbe</a>. The biggest change I wanted was making sure a default "No preview" would be
inserted if there wasn't a preview. I did this by ensuring the  <code>my/get-preview</code> defun would return  <code>nil</code>
(instead of an error) without a preview, and that the entry formatting defun would return "No
preview" if  <code>my/get-preview</code> was  <code>nil</code>.
</p>

 <div class="org-src-container">
 <pre class="src src-emacs-lisp"> <span class="linenr"> 1: </span> <span class="org-comment-delimiter">;; </span> <span class="org-comment">org-site/build-site.el
 <span class="linenr"> 2: </span></span>( <span class="org-keyword">defun</span>  <span class="org-function-name">my/get-preview</span> (file)
 <span class="linenr"> 3: </span>   <span class="org-doc">"get preview text from a file
 <span class="linenr"> 4: </span>
 <span class="linenr"> 5: </span>Uses the function here as a starting point:
 <span class="linenr"> 6: </span>https://ogbe.net/blog/blogging_with_org.html"</span>
 <span class="linenr"> 7: </span>  ( <span class="org-keyword">with-temp-buffer</span>
 <span class="linenr"> 8: </span>    (insert-file-contents file)
 <span class="linenr"> 9: </span>    (goto-char (point-min))
 <span class="linenr">10: </span>    ( <span class="org-keyword">when</span> (re-search-forward  <span class="org-string">"^#\\+BEGIN_PREVIEW$"</span> nil 1)
 <span class="linenr">11: </span>      (goto-char (point-min))
 <span class="linenr">12: </span>      ( <span class="org-keyword">let</span> ((beg (+ 1 (re-search-forward  <span class="org-string">"^#\\+BEGIN_PREVIEW$"</span> nil 1)))
 <span class="linenr">13: </span>            (end ( <span class="org-keyword">progn</span> (re-search-forward  <span class="org-string">"^#\\+END_PREVIEW$"</span> nil 1)
 <span class="linenr">14: </span>                        (match-beginning 0))))
 <span class="linenr">15: </span>        (buffer-substring beg end)))))
</pre>
</div>

 <p>
This defun takes a file path as an argument and:
</p>
 <ol class="org-ol"> <li>Inserts the contents of the file into a temporary buffer</li>
 <li>Navigates to the beginning of the buffer and searches forward for the  <code>#+BEGIN_PREVIEW</code> block
pattern
 <ul class="org-ul"> <li>If it fails to locate this pattern, the defun returns  <code>nil</code></li>
 <li>If it does locate this pattern, it:
 <ol class="org-ol"> <li>Returns to the beginning of the temporary buffer and repeats the search, recording the location of the
block pattern, saving its location under the name  <code>beg</code></li>
 <li>Searches forward again for the  <code>#+END_PREVIEW</code> pattern, saving its location under the name
 <code>end</code></li>
 <li>Returns the text between  <code>beg</code> and  <code>end</code>: the user-selected preview text.</li>
</ol></li>
</ul></li>
</ol></div>
</div>
</div>
</div>
 <div id="outline-container-org8b35c37" class="outline-2">
 <h2 id="org8b35c37">Putting It All Together</h2>
 <div class="outline-text-2" id="text-org8b35c37">
 <p>
Check out the full source code for the site  <a href="https://github.com/djliden/djliden.github.io">on GitHub</a>.
</p>
</div>
</div>
 <div id="outline-container-orgef3db15" class="outline-2">
 <h2 id="orgef3db15">What's Next?</h2>
 <div class="outline-text-2" id="text-orgef3db15">
 <p>
This site now has everything I need to write more with minimal need to tweak the site configuration
every step of the way (which I found myself doing constantly when using Hugo). That said, there are
a few more things I want to do before moving this site to its permanent home under my personal
domain. These include:
</p>
</div>
 <div id="outline-container-org44344d3" class="outline-3">
 <h3 id="org44344d3"> <span class="done DONE">DONE</span> Add navigation buttons to return to the home page/about page/archive page/etc. from any page. (incidentally, if you want to get back home,  <a href="../index.html">here's the link</a>).</h3>
 <div class="outline-text-3" id="text-org44344d3">
 <p>
 <b>Update:</b> I've added this in a very simple way. I updated my  <code>org-publish-project-alist</code> with:
</p>

 <div class="org-src-container">
 <pre class="src src-emacs-lisp"> <span class="linenr"> 1: </span> <span class="org-comment-delimiter">;; </span> <span class="org-comment">org-site/build-site.el
 <span class="linenr"> 2: </span></span>( <span class="org-keyword">setq</span> org-publish-project-alist
 <span class="linenr"> 3: </span>      (list
 <span class="linenr"> 4: </span>       (list  <span class="org-string">"org-site:main"</span>
 <span class="linenr"> 5: </span>              <span class="org-comment-delimiter">;; </span> <span class="org-comment">...
 <span class="linenr"> 6: </span></span>              <span class="org-builtin">:html-preamble</span> (concat  <span class="org-string">"<div class='</span> <span class="org-string"> <span class="org-constant">topnav</span></span> <span class="org-string">'>
 <span class="linenr"> 7: </span>                                     <a href='</span> <span class="org-string"> <span class="org-constant">/index.html</span></span> <span class="org-string">'>Home</a> / 
 <span class="linenr"> 8: </span>                                     <a href='</span> <span class="org-string"> <span class="org-constant">/archive.html</span></span> <span class="org-string">'>Blog</a> /
 <span class="linenr"> 9: </span>                                     <a href='</span> <span class="org-string"> <span class="org-constant">/about.html</span></span> <span class="org-string">'>About Me</a>
 <span class="linenr">10: </span>                                     </div>"</span>)
 <span class="linenr">11: </span>              <span class="org-comment-delimiter">;; </span> <span class="org-comment">...
 <span class="linenr">12: </span></span>             )))
</pre>
</div>
</div>
</div>
 <div id="outline-container-org9a9c679" class="outline-3">
 <h3 id="org9a9c679"> <span class="done DONE">DONE</span> Set up a good system for managing images (e.g. for data visualizations from R/Python)</h3>
 <div class="outline-text-3" id="text-org9a9c679">
 <p>
I followed the guide  <a href="https://orgmode.org/worg/org-tutorials/org-publish-html-tutorial.html">here</a> to set up the export of "static" files using the  <code>org-publish-attachment</code>
publication function. The new section of my config looks like this:
</p>

 <div class="org-src-container">
 <pre class="src src-org">(setq org-publish-project-alist
      (list
       (list "org-site:main"
       ;; ...
             )
       ;; this part is new
       (list "org-site:static"
             :base-directory "./content/"
             :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf"
             :publishing-directory "./public"
             :recursive t
             :publishing-function 'org-publish-attachment
             )))
</pre>
</div>
</div>
</div>

 <div id="outline-container-org3308be8" class="outline-3">
 <h3 id="org3308be8"> <span class="todo TODO">TODO</span> Set up and test LaTeX exporting for formulas etc.</h3>
</div>
 <div id="outline-container-org5f6646c" class="outline-3">
 <h3 id="org5f6646c"> <span class="todo TODO">TODO</span> Add a portfolio page showing some of my past work</h3>
</div>
 <div id="outline-container-org924736d" class="outline-3">
 <h3 id="org924736d"> <span class="todo TODO">TODO</span> Make a more visually interesting home page</h3>
</div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20211203-this-site.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20211203-this-site.html</guid>
  <pubDate>Fri, 03 Dec 2021 08:00:00 +0000</pubDate>
</item>
<item>
  <title>Resources</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Resources</h1>
 <p class="subtitle" role="doc-subtitle">December 2, 2021</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#orgfa3456a">Personal Website in Org</a></li>
 <li> <a href="#orgc2e1cc6">OrgCSS Stylesheet</a></li>
 <li> <a href="#org549715c">loomcom</a></li>
 <li> <a href="#orgbb92b41">Blogging using org-mode (and nothing else)</a></li>
 <li> <a href="#org48b5f4f">Worg Publishing to HTML Tutorial</a></li>
 <li> <a href="#org9902572">My Site</a></li>
</ul></div>
</nav> <div class="PREVIEW" id="orge82401f">
 <p>
Here are some resources to reference for building a simple site with org-mode. I've extensively
used the sites listed as models for building the present site and expect to continue to reference
them for some time.
</p>

</div>


 <div id="outline-container-orgfa3456a" class="outline-2">
 <h2 id="orgfa3456a"> <a href="https://thibaultmarin.github.io/blog/posts/2016-11-13-Personal_website_in_org.html#html_head">Personal Website in Org</a></h2>
 <div class="outline-text-2" id="text-orgfa3456a">
 <p>
Good resoures for setting up a custom sitemap as an index page.
</p>
</div>
</div>
 <div id="outline-container-orgc2e1cc6" class="outline-2">
 <h2 id="orgc2e1cc6"> <a href="https://github.com/gongzhitaao/orgcss">OrgCSS Stylesheet</a></h2>
 <div class="outline-text-2" id="text-orgc2e1cc6">
 <p>
Nice-looking basic stylesheet for site. I likely won't stick with this forever but it looks good for
  now.
</p>
</div>
</div>
 <div id="outline-container-org549715c" class="outline-2">
 <h2 id="org549715c"> <a href="https://loomcom.com/blog/0110_emacs_blogging_for_fun_and_profit.html">loomcom</a></h2>
 <div class="outline-text-2" id="text-org549715c">
 <p>
This site includes a good overview of making list of posts with previews of the first few lines of
text.
</p>
</div>
</div>
 <div id="outline-container-orgbb92b41" class="outline-2">
 <h2 id="orgbb92b41"> <a href="https://ogbe.net/blog/blogging_with_org.html">Blogging using org-mode (and nothing else)</a></h2>
 <div class="outline-text-2" id="text-orgbb92b41">
 <p>
By Dennis Ogbe. The code I ultimately used for generating and showing previews closely followed that
from this post.
</p>
</div>
</div>
 <div id="outline-container-org48b5f4f" class="outline-2">
 <h2 id="org48b5f4f"> <a href="https://orgmode.org/worg/org-tutorials/org-publish-html-tutorial.html">Worg Publishing to HTML Tutorial</a></h2>
 <div class="outline-text-2" id="text-org48b5f4f">
 <p>
Good tutorial covering the basics of publishing org-mode projects to html.
</p>
</div>
</div>
 <div id="outline-container-org9902572" class="outline-2">
 <h2 id="org9902572"> <a href="https://djliden.github.io/">My Site</a></h2>
 <div class="outline-text-2" id="text-org9902572">
 <p>
Here is a link to the site I'm making. Ultimately I will add a custom domain.
</p>
</div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20211201-resources.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20211201-resources.html</guid>
  <pubDate>Thu, 02 Dec 2021 08:00:00 +0000</pubDate>
</item>
<item>
  <title>A Simple PyTorch Model for the Numerai Tournament</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">A Simple PyTorch Model for the Numerai Tournament</h1>
 <p class="subtitle" role="doc-subtitle">May 14, 2021</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#org56cd08e">Background</a>
 <ul> <li> <a href="#orgeca6844">Problem Setting</a></li>
</ul></li>
 <li> <a href="#org7b65a2d">Original  <code>fastai</code> model</a>
 <ul> <li> <a href="#orge3efc67">Data Setup</a></li>
 <li> <a href="#orgc3fa16d">Model Setup</a></li>
 <li> <a href="#org1939e80">Training Loop</a></li>
 <li> <a href="#orgd438234">Summary</a></li>
</ul></li>
 <li> <a href="#orgdee651d">A Simple PyTorch Model</a>
 <ul> <li> <a href="#org7568729">Data Setup</a></li>
 <li> <a href="#org395fbf0">The Model</a></li>
 <li> <a href="#org82ebe29">The Training Loop</a></li>
 <li> <a href="#orgbfa0e29">Train the Model</a></li>
</ul></li>
 <li> <a href="#org91106b9">Summary</a></li>
</ul></div>
</nav> <div class="preview" id="org1febc24">
 <p>
 <i>This is another one from the archives. It covers how to train a basic PyTorch
model for use in the Numerai tournament, at least as it was in May 2021. See the original post  <a href="https://pensive-wing-19c199.netlify.app/post/mlp-numerai-05082021/">here.</a></i>
</p>

</div>

 <div id="outline-container-org56cd08e" class="outline-2">
 <h2 id="org56cd08e">Background</h2>
 <div class="outline-text-2" id="text-org56cd08e">
 <p>
This short write up is in pursuit of a personal goal to put more of my work and thoughts to
paper. I'm sure the topic will still be useful to others, but it's not yet fully developed. It's a
sketch of a work in progress.
</p>

 <p>
Last August, I took the fast.ai  <i>Practical Deep Learning for Coders</i> online course (and worked through
the accompanying book). The course taught the fundamentals of deep learning using the  <code>fastai</code> Python
library, which offers a higher-level API (and a vast range of useful features and tools) for
 <code>PyTorch</code>. The course (and book) followed a "top-down" approach: learn how to effectively apply the
models first, and then go back and learn the more foundational concepts, math, etc., in greater
detail.
</p>

 <p>
After spending several months using  <code>fastai</code> for a number of tasks (including the  <a href="https://www.kaggle.com/c/cassava-leaf-disease-classification">Kaggle Cassava Leaf
Disease Classification competition</a>, the  <a href="https://numer.ai/tournament">numer.ai</a> tournament, and a  <a href="https://github.com/djliden/fastai-turtle-classifier">turtle classifier</a>), I decided I
wanted to "pull back the curtain" and start to learn how to use PyTorch. The numer.ai tournament
seemed like an excellent opportunity to do so. The tournament data come in a very "clean" and
ready-to-use format, so grappling with the data doesn't have to be a huge part of the modeling
process. The dataset is big enough for deep learning but not so huge that the models can't be run
locally. And I already have a working fast.ai model up and running, and I know it's running PyTorch
under the hood, so I know that it will work!
</p>

 <p>
One quick note: trying to learn PyTorch is inspired by a desire to learn more;  <i>not</i> by any serious
perceived weaknesses in  <code>fastai</code>. Many  <code>fastai</code> users and community members, such as Zachary Mueller
(see the excellent  <a href="https://walkwithfastai.com/">walk with fastai</a> project) have shown that  <code>fastai</code> is extremely flexible and
extensible. That said:
</p>
 <ul class="org-ul"> <li>Implementations of new methods often appear first as PyTorch models. Using them directly is easier
to me than translating them to a  <code>fastai</code> context.</li>
 <li> <code>fastai</code> sometimes hides so many details that I find it hard to determine what, exactly, my models
are doing. For example, it took me a while to discover that the  <code>fastai</code> tabular model I was using
for the Numerai tournament was implementing batchnorm and dropout layers. The architecture of the
model was, at least initially, opaque to me.</li>
 <li>While  <code>fastai</code>  <i>allows</i> plenty of flexibility, it isn't necessarily built for it. I often need to do
quite a bit of research to figure out how to tweak my training loop in a way that would be trivial
in a direct PyTorch implementation.</li>
 <li>Some of the other learning resources I've been using, such as the excellent  <a href="http://www.d2l.ai/">Dive into Deep
Learning</a> book, use PyTorch. Rather than translating their code into  <code>fastai</code>, I would prefer to
learn PyTorch directly.</li>
</ul> <p>
In this post, I will first briefly show the  <code>fastai</code> model I was previously using, and then introduce
a (simpler) model written in PyTorch. I will conclude with some reflections on the process.
</p>
</div>
 <div id="outline-container-orgeca6844" class="outline-3">
 <h3 id="orgeca6844">Problem Setting</h3>
 <div class="outline-text-3" id="text-orgeca6844">
 <p>
I won't go into much detail about the Numerai tournament itself – the interested reader can learn
more about it  <a href="https://docs.numer.ai/tournament/learn">here</a>. This isn't intended as an introduction to the tournament and I'm not reproducing
my whole data preparation and processing pipeline. That said, it should be very straightforward to
apply the code here to data obtained from the tournament.
</p>

 <p>
The features are all numeric and all take on values of 0, 0.25, 0.5, 0.75, or 1. The targets can
take the same values. Numerai competitors have tested and discussed the impact of treating the
targets as categorical rather than as numeric responses and have generally found that
regression approaches work better than classification approaches. So we will treat this as a
regression problem with numeric features and targets. The criterion we are trying to optimize is the
Spearman's rank correlation coefficient. That is, we want to be able to predict the  <i>order</i> of the
responses as accurately as possible. Most users approximate this by directly optimizing mean squared
error (MSE); we will do the same.
</p>

 <p>
An obvious question at this phase is: given a large number of observations but a small number of
targets (recall: all targets take values of 0, 0.25, 0.5, 0.75, or 1), how exactly are we supposed
to create a meaningful ordering? Well, there are a couple of answers to that. First and foremost:
we're only aiming for a rough ordering. If we could just make sure all of the "0" targets were
predicted lower than all of the "1" targets, we'd be off to a great start! In general, in this
problem, there is a lot of "noise" and very little "signal." We're not going to be able to
precisely order all of the observations, so having only a few targets to work with doesn't hurt as
much as it may seem.
</p>

 <p>
Second, it's possible to obtain reasonably high Spearman correlation values when "blocks" of
predictions are correctly ordered but when the observations within those blocks are completely
shuffled. The figure below shows the results of a simulation wherein 5000 observations were divided
into five targets roughly in proportion to those in the Numerai tournament. "Predictions" were
generated such that all of the predictions in the lowest category were lower than all of the
predictions in the next category for all categories. For example, any prediction in category 0.25
was guaranteed to be lower than any prediction in category 0.5. Within each category, however, the
predictions were shuffled. This experiment was repeated 5000 times. The average Spearman correlation
coefficient was 0.859 (the highest possible is 1).
</p>
 <div class="org-center">

 <figure id="org40c02f8"> <img src="./figures/20210514-pytorch-numerai/spearman-sim.png" alt="Histogram of simulated Spearman correlations after within-group shuffling, centered near 0.86"></img> <figcaption> <span class="figure-number">Figure 1: </span>Even when predictions were shuffled within "blocks," high Spearman correlation coefficients were obtained when those blocks were placed in order.</figcaption></figure></div>

 <p>
So even when large "blocks" of predictions were shuffled internally, as long as those "blocks" were
ordered correctly relative to each other, the Spearman correlation coefficients remained high.
</p>
</div>
</div>
</div>

 <div id="outline-container-org7b65a2d" class="outline-2">
 <h2 id="org7b65a2d">Original  <code>fastai</code> model</h2>
 <div class="outline-text-2" id="text-org7b65a2d">
 <p>
My original  <code>fastai</code> implementation does not differ appreciably from the implementation detailed in
the official  <a href="https://docs.fast.ai/tutorial.tabular.html">fastai Tabular Training tutorial</a>. The components are, briefly:
</p>
</div>
 <div id="outline-container-orge3efc67" class="outline-3">
 <h3 id="orge3efc67">Data Setup</h3>
 <div class="outline-text-3" id="text-orge3efc67">
 <p>
First, we use the  <a href="https://docs.fast.ai/tabular.core.html#TabularPandas">TabularPandas</a> helper to load the data and to generate our  <code>DataLoaders</code>.  <code>DataLoaders</code>
provide a convenient wrapper around the training and validation data and facilitate passing batches
of data to the model during the training loop.
</p>

 <p>
Our data (including training and validation examples) exist in a Pandas DataFrame called
 <code>training_data</code>. We have defined indices  <code>train_idx</code> and  <code>val_idx</code> corresponding to the training and
validation examples.
</p>

 <div class="org-src-container">
 <pre class="src src-python"> <span class="org-variable-name">splits</span>  <span class="org-operator">=</span> ( <span class="org-builtin">list</span>(train_idx),  <span class="org-builtin">list</span>(val_idx))
 <span class="org-variable-name">data</span>  <span class="org-operator">=</span> TabularPandas(training_data, cat_names <span class="org-operator">=</span> <span class="org-constant">None</span>,
                    cont_names <span class="org-operator">=</span> <span class="org-builtin">list</span>(feature_cols.values),
                    y_names <span class="org-operator">=</span>target_cols, splits  <span class="org-operator">=</span> splits)

 <span class="org-variable-name">dls</span>  <span class="org-operator">=</span> data.dataloaders(bs  <span class="org-operator">=</span> 2048)
</pre>
</div>
</div>
</div>

 <div id="outline-container-orgc3fa16d" class="outline-3">
 <h3 id="orgc3fa16d">Model Setup</h3>
 <div class="outline-text-3" id="text-orgc3fa16d">
 <p>
We will use a  <code>fastai</code>  <a href="https://docs.fast.ai/tabular.learner.html#tabular_learner">tabular <sub>learner</sub></a> without much modification and without adjusting many of the
possible options. As noted above, we're using the MSE loss function.  <code>fastai</code> also lets us directly
specify that we want to see the Spearman correlation coefficient as a "metric." It's not used in the
optimization process, but we get to see the change in the Spearman correlation coefficient after
each epoch.
</p>

 <div class="org-src-container">
 <pre class="src src-python"> <span class="org-variable-name">learn</span>  <span class="org-operator">=</span> tabular_learner(dls, layers <span class="org-operator">=</span>[200,200],
                        loss_func <span class="org-operator">=</span>MSELossFlat(),
                        metrics  <span class="org-operator">=</span> [SpearmanCorrCoef()])
</pre>
</div>
</div>
</div>

 <div id="outline-container-org1939e80" class="outline-3">
 <h3 id="org1939e80">Training Loop</h3>
 <div class="outline-text-3" id="text-org1939e80">
 <p>
 <code>fastai</code> handles the training loop for us – we don't need to write it out manually. Here we say to
train the model for three epochs and to apply a weight decay (l2 penalty) of 0.1.
</p>

 <div class="org-src-container">
 <pre class="src src-python">learn.fit_one_cycle(3, wd  <span class="org-operator">=</span> 0.1)
</pre>
</div>
</div>
</div>

 <div id="outline-container-orgd438234" class="outline-3">
 <h3 id="orgd438234">Summary</h3>
 <div class="outline-text-3" id="text-orgd438234">
 <p>
Without going into too much detail – this is, after all, supposed to be a post about PyTorch, which
I've scarcely mentioned so far – I want to highlight some of the key features and shortcomings of
this approach:
</p>
 <ul class="org-ul"> <li>It's concise: we've created a suitable data iterator, defined the model, and run through the
training loop in only a few lines of code. The training loop in particular took only one line!</li>
 <li>A lot of detail is hidden. We rely on "sane defaults" to a very high degree. What is the model
architecture? Which optimizer is used? How will information be presented to us throughout the
training loop?</li>
 <li>It  <i>does</i> readily expose some of the key hyperparameters we'll likely wish to experiment with, such
as weight decay and the number and size of layers. Ultimately, once we have a better understanding
of the architecture, it's also not too difficult to modify hyperparameters associated with dropout
and batchnorm.</li>
</ul> <p>
In short, this method gets you from a blank screen to a trainable deep learning model with some
easily-accessible hyperparameters to optimize about as quickly as one could ask for, but it keeps a
lot of the details hidden.
</p>
</div>
</div>
</div>

 <div id="outline-container-orgdee651d" class="outline-2">
 <h2 id="orgdee651d">A Simple PyTorch Model</h2>
 <div class="outline-text-2" id="text-orgdee651d">
 <p>
In an effort to learn some basic PyTorch, I set out to develop a very simple working model. It
doesn't have all of the bells and whistles of the fastai model – no batchnorm, no dropout, no
weight decay – but it works and it is generally easy to understand what the model is doing. This
provides a good foundation for further experimentation with more complex architectures.
</p>
</div>
 <div id="outline-container-org7568729" class="outline-3">
 <h3 id="org7568729">Data Setup</h3>
 <div class="outline-text-3" id="text-org7568729">
 <p>
A common theme throughout this section is that "It takes a bit more code to do  <code>____</code> in PyTorch than
in  <code>fastai</code>. Setting up the data is no exception. I mostly followed  <a href="https://pytorch.org/tutorials/beginner/basics/data_tutorial.html#preparing-your-data-for-training-with-dataloaders">this guide</a> for setting up the data
for use by the PyTorch model.
</p>

 <p>
The biggest additional step is that we must define a
custom class inheriting from the PyTorch  <code>DataSet</code> class. The class must define:
</p>
 <ul class="org-ul"> <li> <code>__len__()</code>: a method for finding the length of the dataset; and</li>
 <li> <code>__getitem__()</code>: a method for returning an item from the dataset given an index.</li>
</ul> <p>
I wrote the  <code>NumerData</code> class for this purpose as shown below. Note that the  <code>data</code> argument refers to
the whole training dataset;  <code>feature_cols</code> is a list of the feature column names; and  <code>target_cols</code> is a
named list of the target column names.
</p>

 <div class="org-src-container">
 <pre class="src src-python"> <span class="org-keyword">class</span>  <span class="org-type">NumerData</span>(Dataset):
     <span class="org-keyword">def</span>  <span class="org-function-name">__init__</span>( <span class="org-keyword">self</span>, data, feature_cols, target_cols):
         <span class="org-keyword">self</span>. <span class="org-variable-name">data</span>  <span class="org-operator">=</span> data
         <span class="org-keyword">self</span>. <span class="org-variable-name">features</span>  <span class="org-operator">=</span> data[feature_cols].copy().values.astype(np.float32)
         <span class="org-keyword">self</span>. <span class="org-variable-name">targets</span>  <span class="org-operator">=</span> data[target_cols].copy().values.astype(np.float32)
         <span class="org-keyword">self</span>. <span class="org-variable-name">eras</span>  <span class="org-operator">=</span> data.era.copy().values

     <span class="org-keyword">def</span>  <span class="org-function-name">__len__</span>( <span class="org-keyword">self</span>):
         <span class="org-keyword">return</span>( <span class="org-builtin">len</span>( <span class="org-keyword">self</span>.data))
    
     <span class="org-keyword">def</span>  <span class="org-function-name">__getitem__</span>( <span class="org-keyword">self</span>, idx):
         <span class="org-keyword">if</span> torch.is_tensor(idx):
             <span class="org-variable-name">idx</span>  <span class="org-operator">=</span> idx.tolist() 

         <span class="org-keyword">return</span>  <span class="org-keyword">self</span>.features[idx],  <span class="org-keyword">self</span>.targets[idx],  <span class="org-keyword">self</span>.eras[idx]
</pre>
</div>

 <p>
The dataset ended up being the biggest performance bottleneck for me, at least at first. I had
initially put off some amount of the processing to the  <code>__getitem__()</code> method, which meant that every
time the  <code>DataLoader</code> needed to return a new batch of data, it needed to do a lot more indexing and
processing than it should have. A couple of examples:
</p>
 <ul class="org-ul"> <li>I explicitly included type conversions (to tensors) in the  <code>__getitem__()</code> method. This was
unnecessary as the  <code>DataLoader</code> handles this by default. It also took time.</li>
 <li>I made the  <code>DataLoader</code> pull the features and targets from the full dataset each time instead of
storing them as separate objects. That is, instead of just  <code>return self.features[idx]</code>, I first
defined  <code>self.features = data[feature_cols]</code>. This should be handled in the  <code>__init__()</code> method, not
each time  <code>__getitem__()</code> is called.</li>
</ul> <p>
Note that the  <code>NumerData</code> class currently does not define any data. We need to instantiate an object of
type  <code>NumerData</code> with some data in order to use it. We will define separate ~DataSet~s for the
training and validation data.
</p>

 <div class="org-src-container">
 <pre class="src src-python"> <span class="org-variable-name">train_ds</span>  <span class="org-operator">=</span> NumerData(training_data.iloc[train_idx],
                     feature_cols, target_cols)

 <span class="org-variable-name">val_ds</span>  <span class="org-operator">=</span> NumerData(training_data.iloc[val_idx],
                     feature_cols, target_cols)
</pre>
</div>

 <p>
With these defined, we can use use the PyTorch  <code>DataLoader</code> to handle iteration through the ~DataSet~s
in batches. Again, we instantiate separate ~DataLoader~s for our train and validation sets:
</p>

 <div class="org-src-container">
 <pre class="src src-python"> <span class="org-variable-name">train_dl</span>  <span class="org-operator">=</span> DataLoader(train_ds, batch_size  <span class="org-operator">=</span> 2048, shuffle <span class="org-operator">=</span> <span class="org-constant">False</span>, num_workers <span class="org-operator">=</span>0)
 <span class="org-variable-name">val_dl</span>  <span class="org-operator">=</span> DataLoader(val_ds, batch_size  <span class="org-operator">=</span>  <span class="org-builtin">len</span>(val_ds), shuffle <span class="org-operator">=</span> <span class="org-constant">False</span>)
</pre>
</div>

 <p>
Now our data are ready to go and we can define the model.
</p>
</div>
</div>
 <div id="outline-container-org395fbf0" class="outline-3">
 <h3 id="org395fbf0">The Model</h3>
 <div class="outline-text-3" id="text-org395fbf0">
 <p>
The model has a few separate components – a fact that is easy to miss when working with
 <code>fastai</code>. We need to define:
</p>
 <ul class="org-ul"> <li>The model architecture itself</li>
 <li>The loss function (or criterion)</li>
 <li>The optimizer</li>
</ul> <p>
Furthermore, when defining the model, we need to be (just a little bit) mindful of the dimension of
our inputs (another thing  <code>fastai</code> takes care of automatically). Ultimately, none of this is
particularly onerous:
</p>

 <div class="org-src-container">
 <pre class="src src-python"> <span class="org-variable-name">n_feat</span>  <span class="org-operator">=</span>  <span class="org-builtin">len</span>(feature_cols)
 <span class="org-variable-name">net</span>  <span class="org-operator">=</span> nn.Sequential(nn.Linear(n_feat, 256),
                    nn.ReLU(),
                    nn.Linear(256, 1))

 <span class="org-variable-name">criterion</span>  <span class="org-operator">=</span> nn.MSELoss()
 <span class="org-variable-name">optim</span>  <span class="org-operator">=</span> torch.optim.Adam(params  <span class="org-operator">=</span> net.parameters())
</pre>
</div>

 <p>
The model we have defined is a simple multilayer perceptron (MLP). Our input batch is passed to a
linear layer with 256 "neurons." The output of this layer is passed to the  <code>ReLU()</code>, or  <i>rectified
linear unit</i>, layer. The output of this layer is passed to another linear layer, which produces the
one-dimensional output.
</p>

 <p>
As noted above, we use MSE as our loss function. We use the  <code>Adam</code> optimizer; details on this
optimizer can be found  <a href="https://pytorch.org/docs/master/generated/torch.optim.Adam.html">here</a>.
</p>
</div>
</div>
 <div id="outline-container-org82ebe29" class="outline-3">
 <h3 id="org82ebe29">The Training Loop</h3>
 <div class="outline-text-3" id="text-org82ebe29">
 <p>
The training loop represents the part of the implementation where  <code>fastai</code> provides the most help. In
 <code>fastai</code>, the whole process is largely automatic. We called  <code>learn.fit_one_cycle()</code>, specified the number
of epochs, and let the model run. But a lot is happening behind the scenes, and we need to write
that logic manually in PyTorch.
</p>

 <p>
We will write a method to train a single epoch. We can then put this in a loop to train multiple
epochs if needed.
</p>

 <div class="org-src-container">
 <pre class="src src-python"> <span class="org-keyword">def</span>  <span class="org-function-name">train</span>(epoch, model):
     <span class="org-variable-name">device</span>  <span class="org-operator">=</span> torch.device( <span class="org-string">"cuda:0"</span>  <span class="org-keyword">if</span> torch.cuda.is_available()  <span class="org-keyword">else</span>  <span class="org-string">"cpu"</span>)
     <span class="org-variable-name">model</span>  <span class="org-operator">=</span> model.to(device)
    
     <span class="org-comment-delimiter"># </span> <span class="org-comment">set up tqdm bar
</span>     <span class="org-variable-name">pbar</span>  <span class="org-operator">=</span> tqdm( <span class="org-builtin">enumerate</span>(BackgroundGenerator(train_dl)),
                total <span class="org-operator">=</span> <span class="org-builtin">len</span>(train_dl), position <span class="org-operator">=</span>0, leave <span class="org-operator">=</span> <span class="org-constant">False</span>)
    
     <span class="org-keyword">for</span> batch_idx, (data, target, era)  <span class="org-keyword">in</span> pbar:
         <span class="org-variable-name">data</span>,  <span class="org-variable-name">target</span>  <span class="org-operator">=</span> data.to(device), target.to(device)
        
         <span class="org-comment-delimiter"># </span> <span class="org-comment">reset gradients
</span>        optim.zero_grad()
        
         <span class="org-comment-delimiter"># </span> <span class="org-comment">forward pass
</span>         <span class="org-variable-name">out</span>  <span class="org-operator">=</span> model(data)

         <span class="org-comment-delimiter">#</span> <span class="org-comment">compute loss
</span>         <span class="org-variable-name">loss</span>  <span class="org-operator">=</span> criterion(out, target)

         <span class="org-comment-delimiter">#</span> <span class="org-comment">backpropagation
</span>        loss.backward()
        
         <span class="org-comment-delimiter">#</span> <span class="org-comment">update the parameters
</span>        optim.step()

         <span class="org-keyword">if</span> batch_idx  <span class="org-operator">%</span> 100  <span class="org-operator">==</span> 0:
             <span class="org-builtin">print</span>(f <span class="org-string">'Train Epoch/Batch: </span>{epoch} <span class="org-string">/</span>{batch_idx} <span class="org-constant">\t</span> <span class="org-string">Training Loss: </span>{loss.item():.4f} <span class="org-string">'</span>)
</pre>
</div>

 <p>
In this method, we:
</p>
 <ol class="org-ol"> <li>Identify whether we have a GPU available for training and, if so, pass the model to the GPU.</li>
 <li>Using the  <code>tqdm</code> package, set up a progress bar for tracking model progress.</li>
 <li>For each batch in the  <code>DataLoader</code>:
 <ol class="org-ol"> <li>Send the features/targets to the appropriate device (GPU if available)</li>
 <li>Reset the gradients</li>
 <li>Compute the forward pass: pass the batch through the model and compute the outputs for each
observation in the batch</li>
 <li>Compute the loss</li>
 <li>Back-propagate (compute the gradient of the loss function with respect to the weights)</li>
 <li>Update the weights</li>
 <li>Occasionally print the training loss</li>
</ol></li>
</ol> <p>
We can define a similar method for evaluating our model performance on the validation set (without
updating model weights). Suppose we've defined a function called  <code>era_spearman</code> to calculate the
average Spearman correlation coefficient across Numerai tournament eras in the validation data. Then
we can define a validation method as:
</p>

 <div class="org-src-container">
 <pre class="src src-python"> <span class="org-keyword">def</span>  <span class="org-function-name">test</span>(model):
     <span class="org-variable-name">device</span>  <span class="org-operator">=</span> torch.device( <span class="org-string">"cuda:0"</span>  <span class="org-keyword">if</span> torch.cuda.is_available()  <span class="org-keyword">else</span>  <span class="org-string">"cpu"</span>)

     <span class="org-variable-name">test_loss</span>  <span class="org-operator">=</span> 0
     <span class="org-keyword">with</span> torch.no_grad():
         <span class="org-keyword">for</span> data, target, era  <span class="org-keyword">in</span> val_dl:
             <span class="org-variable-name">data</span>,  <span class="org-variable-name">target</span>  <span class="org-operator">=</span> data.to(device), target.to(device)
            
             <span class="org-variable-name">out</span>  <span class="org-operator">=</span> model(data)
             <span class="org-variable-name">test_loss</span>  <span class="org-operator">+=</span> criterion(out, target).item()  <span class="org-comment-delimiter"># </span> <span class="org-comment">sum up batch loss
</span>             <span class="org-variable-name">val_corr</span>  <span class="org-operator">=</span> era_spearman(preds  <span class="org-operator">=</span> out.cpu().numpy().squeeze(),
                                    targs  <span class="org-operator">=</span> target.cpu().numpy().squeeze(),
                                    eras  <span class="org-operator">=</span> era)

         <span class="org-comment-delimiter">#</span> <span class="org-comment">test_loss /= len(val_dl.dataset)
</span>         <span class="org-builtin">print</span>(f <span class="org-string">'Test Loss: </span>{test_loss:.4f} <span class="org-string">, Test Correlation: </span>{val_corr:.4f} <span class="org-string">'</span>)
</pre>
</div>

 <p>
This follows much of the same logic as the training method, with some key exceptions:
</p>
 <ul class="org-ul"> <li>Everything happens under the  <code>torch.no_grad()</code> context handler. Why? We're only using the validation
data to assess the performance of our model; we don't want to compute any gradients and we
certainly do not want to use these data to update our model weights.</li>
 <li>We make sure to calculate the metric we're really interested in (the Spearman correlation). This
is useful to check in case the loss function (MSE) does not actually improve the Spearman
correlation.</li>
 <li>In this particular case, I did  <i>not</i> divide the validation data into batches (put differently, the
batch size is the length of the validation set). It certainly could have been divided into
batches, though, and doing so may be necessary with larger datasets or in the face of significant
memory constraints.</li>
</ul></div>
</div>
 <div id="outline-container-orgbfa0e29" class="outline-3">
 <h3 id="orgbfa0e29">Train the Model</h3>
 <div class="outline-text-3" id="text-orgbfa0e29">
 <p>
We can finally train the model! This part is a simple  <code>for</code> loop.
</p>

 <div class="org-src-container">
 <pre class="src src-python"> <span class="org-keyword">for</span> epoch  <span class="org-keyword">in</span>  <span class="org-builtin">range</span>(6):
    train(epoch, net)
    test(net)
</pre>
</div>
</div>
</div>
</div>
 <div id="outline-container-org91106b9" class="outline-2">
 <h2 id="org91106b9">Summary</h2>
 <div class="outline-text-2" id="text-org91106b9">
 <p>
I wrote a lot more code to implement a comparatively-simple PyTorch model than to implement the
 <code>fastai</code> model. The PyTorch model forces us to better understand the structure of the model and the
logic of the training loop, though it likely takes more time and more finessing to obtain an
efficiently-performing model with decent results. The  <code>fastai</code> model, on the other hand, is very quick
to implement but does not expose as many of the details. It is relatively quick and easy to get a
model running and returning decent results, but it can take a bit more work to understand the
structure of the model and of the training loop.
</p>

 <p>
I'll be writing more – and more complicated – PyTorch models in the future. I hope to add in some
of the additional features included in the  <code>fastai</code> tabular implementation, such as dropout layers. I
also want to experiment further with regularization – L2 penalization is very easy to use in
PyTorch, but I've found L1 penalization to work far better for regression models in the Numerai
tournament and I want to see if that distinction also holds true for regression models.
</p>
</div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20210514-pytorch-numerai.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20210514-pytorch-numerai.html</guid>
  <pubDate>Fri, 14 May 2021 08:00:00 +0000</pubDate>
</item>
<item>
  <title>Mapping Urban Heat by Census Tract in R</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Mapping Urban Heat by Census Tract in R</h1>
 <p class="subtitle" role="doc-subtitle">February 13, 2021</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#orgfd55b1d">Background</a></li>
 <li> <a href="#org2145a52">Getting the Data</a>
 <ul> <li> <a href="#org139e6fb">Unpacking and Visualizing the Raw Data</a></li>
</ul></li>
 <li> <a href="#org3d53c54">Mapping Heat by Census Tract</a></li>
 <li> <a href="#org574d149">Final Maps</a></li>
 <li> <a href="#org3f6fec3">Resources</a></li>
</ul></div>
</nav> <div class="preview" id="org34aa8fe">
 <p>
 <i>Another one from the archives–this is one of my projects from my time at the Guinn Center, and something I very much wish I could have developed further: an analysis of urban heat in Las Vegas.</i>
</p>

</div>

 <div id="outline-container-orgfd55b1d" class="outline-2">
 <h2 id="orgfd55b1d">Background</h2>
 <div class="outline-text-2" id="text-orgfd55b1d">
 <p>
For the past several months, I have been working on an analysis on the effects
of urban heat on vulnerable populations, particularly during a public health
crisis. For some background, I currently live in Las Vegas, where summer heat
can exceed 110 degrees. Last summer included a 45-day-long streak of
temperatures over 100 degrees.
</p>

 <p>
Urban heat is not distributed evenly within cities. Features such as parks or
ponds can lead to cooler temperatures in some areas, while areas without foliage
or with dark surfaces such as roads and buildings lead to warmer
temperatures. This effect is particularly pronounced at night: urban surfaces
absorb heat during the daytime, warming the air at night.
</p>

 <p>
An NPR Special Series titled  <a href="https://www.npr.org/series/756048128/urban-heat">Heat and Health in American Cities</a> compared urban
heat to household income in the 100 most populated cities. They found that, in
many cities, income and urban heat were inversely related: lower-income
households tended to be in the parts of cities most affected by urban heat,
while higher-income households were more often found in cooler areas.
</p>

 <p>
The key to this research was aggregating urban heat data within census
boundaries (such as tracts or blocks). I decided to recreate this analysis in
 <code>R</code>. Once urban heat data is linked to Census-designated boundaries, it can easily
be compared to metrics such as income, poverty, disability, access to health
insurance, demographics, any many other data points collected by the U.S. Census
Bureau's American Community Survey (ACS). In R, obtaining and mapping these
metrics is a relatively simple process with packages such as  <code>tidycensus</code> and
 <code>tigris</code>.
</p>

 <p>
The remainder of this post will provide a very brief overview of how to obtain
satellite surface temperature data; aggregate those data points within census
tracts; and plot the results. I don't know if this mapping exercise will make it
into the final project report, but I learned a lot from working through it, and
I wanted to make sure to document my steps here.
</p>

 <p>
Though it should be possible to follow this guide without much prior experience
working with spatial data,  <a href="https://geocompr.robinlovelace.net/">This free book</a>,  <i>Geocomputation with R</i> by Robin
Lovelace, Jakub Nowosad, Jannes Muenchow, is an excellent resource for those
interested in learning more. It is particularly useful for understanding topics
such as  <i>projections</i> and the differences between raster and vector data. The
section on  <a href="https://geocompr.robinlovelace.net/geometric-operations.html#raster-vector">Raster-vector interactions</a> is particularly relevant to this task as
we will be taking raster values (the heat map) and aggregating them within
polygon boundaries (census tracts).
</p>
</div>
</div>

 <div id="outline-container-org2145a52" class="outline-2">
 <h2 id="org2145a52">Getting the Data</h2>
 <div class="outline-text-2" id="text-org2145a52">
 <p>
I obtained surface temperature satellite data from the NASA/USGS Landsat 8
satellite. The data can be obtained through an API, though for this example, I
downloaded the data manually. I looked for data meeting the following criteria:
</p>
 <ul class="org-ul"> <li>From June-August 2020</li>
 <li>Cloud cover less than 4%</li>
 <li>Landsat C1 Analysis-Ready Data (ARD) datasets</li>
 <li>I ultimately downloaded a raster map with ID
 <code>LC08_CU_005011_20200806_20200824_C01_V01</code>. This map came from 06
August, 2020. Details, including a download link, can be found  <a href="https://earthexplorer.usgs.gov/scene/metadata/full/5e83a38b677b457d/LC08_CU_005011_20200806_C01_V01/">here</a>.</li>
</ul> <p>
So what data did we actually obtain? Downloading the "Provisional Land Surface
Temperature" file returns a  <code>.tar</code> file with a number of  <code>.tif</code> raster images. We're
interested in the one with  <code>ST.tif</code> at the end (ST for Surface Temperature). This
provides a raster map of the region, at 30-meter spatial resolution, with
surface temperatures in tenths of a degree Kelvin. That is, each 30-meter "cell"
in the map is associated with a surface temperature value.
</p>
</div>

 <div id="outline-container-org139e6fb" class="outline-3">
 <h3 id="org139e6fb">Unpacking and Visualizing the Raw Data</h3>
 <div class="outline-text-3" id="text-org139e6fb">
 <p>
This section requires the  <code>raster</code> and  <code>sf</code> packages. Below, we untar the map and
extract the map of interest.
</p>

 <div class="org-src-container">
 <pre class="src src-R"> <span class="org-ess-modifiers">library</span>(raster)
 <span class="org-ess-modifiers">library</span>(sf)

 <span class="org-comment-delimiter">## </span> <span class="org-comment">untar the data
</span>untar(tarfile =  <span class="org-string">"PATH-TO-TARFILE.tar"</span>, exdir =  <span class="org-string">"DESTINATION-DIRECTORY"</span>)
file.copy( <span class="org-string">"./data/raw/testsat/LC08_CU_005011_20200806_20200824_C01_V01_ST.tif"</span>,
           <span class="org-string">"IMAGE-DESTINATION/st_map.tif"</span>)

 <span class="org-comment-delimiter">## </span> <span class="org-comment">Access the file as a raster image, plot, and save as png
</span>st_map = raster( <span class="org-string">"./data/processed/st_map.tif"</span>)
png(file =  <span class="org-string">"./figs/st_map.png"</span>)
plot(st_map)
dev.off()
</pre>
</div>

 <div class="org-center">

 <figure id="org720b838"> <img src="./figures/20210213-urban-heat/st_map.png" alt="Raw Landsat raster map of the Las Vegas region shaded green-to-pink by surface temperature in Kelvin"></img> <figcaption> <span class="figure-number">Figure 1: </span>Raw raster map of surface temperatures around Las Vegas area</figcaption></figure></div>

 <p>
Starting from this map, we want to (1) crop to the area immediately surrounding
Las Vegas, and (2) average the temperature values within each census tract,
allowing us to compare tract-level surface temperatures to other data collected
at the census tract level.
</p>
</div>
</div>
</div>

 <div id="outline-container-org3d53c54" class="outline-2">
 <h2 id="org3d53c54">Mapping Heat by Census Tract</h2>
 <div class="outline-text-2" id="text-org3d53c54">
 <p>
First, we'll use the  <code>tigris</code> package to download the census tract boundaries in
Nevada and crop to the Las Vegas area.
</p>


 <div class="org-src-container">
 <pre class="src src-R">lv_tracts  <span class="org-ess-assignment"><-</span> tigris::tracts(state= <span class="org-string">"NV"</span>)  <span class="org-ess-XopX">%>%</span>
  st_crop(xmin=-115.38, ymin=35.92, xmax = -114.88, ymax = 36.38) 
</pre>
</div>

 <p>
Next, we'll reproject our tract-level data such that it has the same projection
as the raster data. Computationally, transforming vector data (our tract data)
is much less expensive than transforming raster data. After reprojecting, we can
use the  <code>crop</code> function from the  <code>raster</code> package to crop the raster image to the
Las Vegas area as defined in  <code>lv_tracts</code>.
</p>


 <div class="org-src-container">
 <pre class="src src-R">lv_tracts_reprojected = st_transform(lv_racts, crs(st_map))
sat_cropped = crop(st_map, lv_tracts_reprojected)
</pre>
</div>

 <p>
With this accomplished, we use the  <code>raster::extract()</code> function to extract the
mean of the raster values within the boundaries defined by
 <code>lv_tracts_reprojected</code>, which contains the census tract boundaries projected to
align with the raster map.
</p>

 <div class="org-src-container">
 <pre class="src src-R">heat_map = extract(sat_cropped,            <span class="org-comment-delimiter"># </span> <span class="org-comment">cropped raster object
</span>                   lv_tracts_reprojected,  <span class="org-comment-delimiter"># </span> <span class="org-comment">vector map of LV
</span>                   df= <span class="org-ess-constant">TRUE</span>,                <span class="org-comment-delimiter"># </span> <span class="org-comment">return as data frame
</span>                   fun=mean,               <span class="org-comment-delimiter"># </span> <span class="org-comment">return the mean of each polygon
</span>                   sp= <span class="org-ess-constant">TRUE</span>)                <span class="org-comment-delimiter"># </span> <span class="org-comment">append to lv_tracts_reprojected
</span>
 <span class="org-comment-delimiter">## </span> <span class="org-comment">Visualize
</span>sf_heat_map = st_as_sf(heat_map)           <span class="org-comment-delimiter"># </span> <span class="org-comment">Convert to simple features (sf) vector data
</span>png(file= <span class="org-string">"IMAGE_DESTINATION/heatmaptest.png"</span>)
plot(out[ <span class="org-string">"st_map"</span>])                        <span class="org-comment-delimiter"># </span> <span class="org-comment">plot the column of raster values
</span>dev.off()
</pre>
</div>

 <div class="org-center">

 <figure id="orgbac5102"> <img src="./figures/20210213-urban-heat/heatmaptest.png" alt="Rotated choropleth map of Las Vegas census tracts colored by mean surface temperature, titled STtest"></img> <figcaption> <span class="figure-number">Figure 2: </span>Average Surface Temperatures by Census Tract in Las Vegas, Nevada (tenths of a degree Kelvin)</figcaption></figure></div>

 <p>
We're closer to our goal, but not quite there yet. Our map is rotated, and the
scale (tenths of a degree Kelvin) isn't especially interpretable. First, we'll
reproject the map to the correct orientation (back to the original projection of
the census tract data).
</p>

 <div class="org-src-container">
 <pre class="src src-R">heat_tracts_transformed = st_transform(x=sf_heat_map, crs = crs(lv_tracts))
png( <span class="org-string">"tract_repro.png"</span>)
plot(heat_tracts_transformed[ <span class="org-string">"st_map"</span>])
dev.off()
</pre>
</div>

 <div class="org-center">

 <figure id="org90d4c9d"> <img src="./figures/20210213-urban-heat/tract_repro.png" alt="Re-projected choropleth of Las Vegas census tracts shaded blue-to-yellow by mean surface temperature"></img> <figcaption> <span class="figure-number">Figure 3: </span>Re-projected Map of Surface Temperatures by Census Tract</figcaption></figure></div>
</div>
</div>

 <div id="outline-container-org574d149" class="outline-2">
 <h2 id="org574d149">Final Maps</h2>
 <div class="outline-text-2" id="text-org574d149">
 <p>
Lastly, we can apply some formatting to make it more interpretable. I used
 <code>ggplot2</code> for all of the visual tweaks (details not shown).
</p>

 <div class="org-center">

 <figure id="org8c5935c"> <img src="./figures/20210213-urban-heat/ST_LV.png" alt="Labeled choropleth of Las Vegas census tracts shaded by surface temperature, hotter in the east and south"></img> <figcaption> <span class="figure-number">Figure 4: </span>Visualizing Urban Heat by Census Tract in Las Vegas, Nevada</figcaption></figure></div>

 <p>
We can now plot other metrics by census tract and visually compare them to our
urban heat map. For example, we can look at poverty by census tract:
</p>

 <div class="org-center">

 <figure id="org3612e4d"> <img src="./figures/20210213-urban-heat/poverty.png" alt="Labeled purple choropleth of Las Vegas census tracts shaded by percent of residents below the poverty line"></img> <figcaption> <span class="figure-number">Figure 5: </span>Poverty by Census Tract in Las Vegas, Nevada</figcaption></figure></div>

 <p>
A quick visual inspection of these two maps shows that the Sunrise Manor and
Winchester areas have relatively high temperatures and a high proportion of
residents living abelow the poverty line. Conversely, the Summerlin area on the
west side of Las Vegas has among the lowest temperatures and the lowest rates of
poverty.
</p>

 <p>
There are plenty of additional analyses we can conduct from here. The NPR report
linked above calculated correlations between tract-level surface temperatures
and household incomes to determine that the two were inversely correlated. There
are also a variety of  <a href="https://maczokni.github.io/crimemapping_textbook_bookdown/spatial-regression-models.html">spatial regression models</a> and  <a href="https://geocompr.robinlovelace.net/spatial-cv.html">statistical learning/machine
learning</a> techniques that can be applied to spatial data. Understanding how to
connect different sources of spatial data – such as the census tracts and heat
data above – is an important first step to conducting these analyses.
</p>
</div>
</div>

 <div id="outline-container-org3f6fec3" class="outline-2">
 <h2 id="org3f6fec3">Resources</h2>
 <div class="outline-text-2" id="text-org3f6fec3">
 <ul class="org-ul"> <li> <a href="https://cran.r-project.org/web/views/Spatial.html">CRAN Task View: Analysis
of Spatial Data</a>: A CRAN hub explaining the  <code>R</code> ecosystem of spatial data
analysis packages</li>
 <li> <a href="https://rspatial.org/raster/index.html">Spatial Data Science with R</a>: A site providing a broad overview of spatial data
science concepts and methods in  <code>R</code>.</li>
 <li> <a href="https://geocompr.robinlovelace.net/">Geocomputation with R</a>: A book by Robin Lovelace, Jakub Nowosad, and Jannes
Muenchow, now published by CRC press. I learned most of what I presented above
from this book, which provides a thorough account of the ways of manipulating,
mapping, and analyzing spatial data, with numerous excellent examples.</li>
</ul></div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20210213-urban-heat.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20210213-urban-heat.html</guid>
  <pubDate>Sat, 13 Feb 2021 08:00:00 +0000</pubDate>
</item>
<item>
  <title>Book Review: Machine Learning Yearning by Andrew Ng</title>
  <description><![CDATA[<div id="content" class="content">
 <header> <h1 class="title">Book Review: Machine Learning Yearning by Andrew Ng</h1>
 <p class="subtitle" role="doc-subtitle">June 14, 2019</p>
</header> <nav id="table-of-contents" role="doc-toc"> <h2>Table of Contents</h2>
 <div id="text-table-of-contents" role="doc-toc">
 <ul> <li> <a href="#org366ac71">Introduction and Perspective</a></li>
 <li> <a href="#orgc741767">Overview of the Book</a></li>
 <li> <a href="#orgace356c">General Thoughts on the Topic</a></li>
</ul></div>
</nav> <div class="preview" id="org4ed101b">
 <p>
 <i>This is the first of a few posts I'm migrating from my old site, which you can
still find  <a href="https://pensive-wing-19c199.netlify.app/">here</a>. This is a review of Machine Learning Yearning by Andrew Ng.</i>
</p>

</div>

 <div id="outline-container-org366ac71" class="outline-2">
 <h2 id="org366ac71">Introduction and Perspective</h2>
 <div class="outline-text-2" id="text-org366ac71">
 <p>
In this post, I am briefly reviewing the draft of Andrew Ng's  <i>Machine Learning Yearning</i>, which can currently be obtained for free  <a href="https://www.mlyearning.org/">here</a>. This is a work in progress, so my comments will be brief and not particularly critical. I obtained the copy I read on May 11; the page numbers and content may have changed since then.
</p>

 <p>
I read the book because I have not had the chance to do too much machine learning work in the recent past. I feared that my skills were getting rusty, so I wanted to "dip my toes" back in the ML water and refresh my memory of that world. This is an ongoing process.
</p>

 <p>
Most of my ML education comes from working through much of the classic  <i>Elements of Statistical Learning</i> during my Statistics MS, so my perspective is significantly influenced by my experience with that book.
</p>
</div>
</div>

 <div id="outline-container-orgc741767" class="outline-2">
 <h2 id="orgc741767">Overview of the Book</h2>
 <div class="outline-text-2" id="text-orgc741767">
 <p>
In  <i>Machine Learning Yearning</i>, Ng states that "after finishing this book, you will have a deep understanding of how to set technical direction for a machine learning project" (pg. 8). The key element of that statement is  <i>technical direction.</i> This book does not teach (and does not claim to teach) any particular ML algorithms. There is no code. There is very, very little mathematical notation. This book covers broad topics such as structuring training/dev/test sets and conducting error analyses, and it does so in a way that is largely agnostic to the ML algorithms used (though, at times, it is fairly clear that it is geared largely toward deep learning/neural networks).
</p>

 <p>
As of May 11, 2019, the book is divided into 58 chapters. Most chapters are only a page or two long. Ng states that the brevity of the chapters is such that "you can print them out and get your teammates to read just the 1-2 pages you need them to know." The short chapters did make the book easy to read as it divided the content into (very) short and easily-digestible pieces. However, I often did not find the chapters sufficiently self-contained to justify the divisions. I don't think the book would have suffered from having chapters 5-10 pages in length instead of 1-2 pages, and slightly longer chapters may have made the flow of information a little easier to follow (not that it was ever a significant challenge).
</p>

 <p>
Core topics covered include:
</p>
 <ul class="org-ul"> <li>Composition of the train/dev/test sets (chapters 5-7, 11-2)</li>
 <li>Good characteristics of optimization metrics (chapters 8-12)</li>
 <li>Error analysis (chapters 14-19)</li>
 <li>Bias-Variance Trade-off; training vs. test error (chapters 20-32)</li>
 <li>Comparisons to human-level performance (chapters 33-35)</li>
 <li>Training/Testing on different data distributions; data mismatch errors; generalization from training to dev set (chapters 36-43)</li>
 <li>Optimization Verification Testing (chapters 44-46)</li>
 <li>End-to-end learning vs. pipeline learning (chapters 47-49)</li>
 <li>Pipeline learning: choosing components; error analysis by parts (chapters 50-57)</li>
</ul></div>
</div>

 <div id="outline-container-orgace356c" class="outline-2">
 <h2 id="orgace356c">General Thoughts on the Topic</h2>
 <div class="outline-text-2" id="text-orgace356c">
 <p>
I found that this book provided a valuable supplement to my past reading and experience with machine learning insofar as it got "out of the weeds" and discussed the  <i>process</i> rather than the specific implementations. When learning specific ML techniques for the first time, it's easy to get lost in the weeds. And when something goes wrong, that's where one might look for solutions: in the weeds. Is the implementation wrong? Do I need to improve my feature selection? Is the particular method I'm using wrong? This book offers another perspective. Regardless of the techniques used, it may be possible to improve one's model by, for example, seeking out more training examples; conducting a careful error analysis; or increasing the size/complexity of the model. These "big picture" considerations are often taught as an afterthought, if at all, in more mathematically-focused ML books and courses. But they should be taught sooner as they provide an excellent framework for thinking about any given ML approach.
</p>

 <p>
The book naturally had some limitations. Once again, this is an early version; it is entirely possible that some or all of these issues will be addressed at some point in the future. I believe the book should have been clearer from the beginning that the focus was on deep learning/neural networks. Midway through the book, Ng notes that reducing the number of features is not recommended for reducing variance, as feature selection in general is de-emphasized in modern deep learning. Aside from this and the selection of examples, I don't think the deep learning focus is entirely clear. Furthermore, the prerequisites are a little vague. The book was very easy to follow, but it sometimes suffered from avoiding too much detail. Casual references to "regularization" or "early stopping," without more than a cursory explanation of those terms, may be confusing (or simply unnecessary) to some readers.
</p>

 <p>
The book would benefit greatly from a set of simple but well-implemented examples, perhaps in R Shiny or in a Jupyter notebook, of the various key points made throughout the book. This could be done without expecting much, if any, programming experience on the part of the reader, and it would go a long way toward illustrating some of the concepts that may not be entirely intuitive. For example, the reader could explore the impact of trying to generalize a cat identifying tool from pictures found online to pictures taken from smartphones, or the difference in a sentiment analyzer based in an "end-to-end" vs. learning pipeline approach. The examples in the text are certainly useful, but the ability to make changes and explore the results would significantly enhance the experience.
</p>

 <p>
The barriers to entry for ML are decreasing. Specific knowledge of the algorithms themselves is becoming less and less of a requirement (whether this  <i>should</i> be the case is a different question, and one I will not attempt to address here). Books like this will be invaluable for guiding the next generation of ML practitioners, many of whom will benefit more from a strong understanding of the big-picture process than from a more theoretical understanding of the specific methods being used. This is a good book; many will find it useful.
</p>
</div>
</div>
</div>]]></description>
  <link>https://danliden.com/posts/./20190614-ml-yearning-review.html</link>
  <guid isPermaLink="false">https://danliden.com/posts/./20190614-ml-yearning-review.html</guid>
  <pubDate>Fri, 14 Jun 2019 08:00:00 +0000</pubDate>
</item>
</channel>
</rss>
