<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title></title>
    <link rel="self" type="application/atom+xml" href="https://www.douglas-meyer.name/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://www.douglas-meyer.name"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-10-16T00:00:00+00:00</updated>
    <id>https://www.douglas-meyer.name/atom.xml</id>
    <entry xml:lang="en">
        <title>Adding LLM integration to Rails</title>
        <published>2026-10-16T00:00:00+00:00</published>
        <updated>2026-10-16T00:00:00+00:00</updated>
        
        <author>
          <name>Douglas Meyer</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.douglas-meyer.name/ledger-llm/"/>
        <id>https://www.douglas-meyer.name/ledger-llm/</id>
        
        <content type="html" xml:base="https://www.douglas-meyer.name/ledger-llm/">&lt;p&gt;I&#39;ve had a feature for &lt;em&gt;Ledger&lt;/em&gt; conceptulaized for a while, but the barrier to get it implemented seemed to make the feature not worth it. However, with LLM models now widely available, it appears this feature might be an integration away.&lt;/p&gt;
&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Ledger&lt;/em&gt; has been a hobby project for a while, and by that I mean it serves as my testing grounds for interesting topics. When I was wanting to try out Angular, Elm, or GraphQL, &lt;em&gt;Ledger&lt;/em&gt; was the testing grounds, because it had data and was actively being used. I don&#39;t always finish these explorations, and that is how we have a Rails project with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GraphQL and a custom bulk API endpoints&lt;/li&gt;
&lt;li&gt;Most views in Angular but some in React&lt;/li&gt;
&lt;li&gt;A multi-tenant solution, that can be disabled with an environment variable&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&#39;s what &lt;em&gt;Ledger&lt;/em&gt; &lt;em&gt;is&lt;/em&gt;, but what does it &lt;em&gt;do&lt;/em&gt;? It&#39;s a zero-sum budgeting application that was written at a time when my family needed a better solution than spreadsheets and good home budgeting options weren&#39;t widely available. It allows you to divide your income into accounts, import transactions from your bank, and map what accounts those transactions come out of.
That final step is where LLMs come in, not to automate it, but to make a fair guess and have that as a shortcut to the user.&lt;/p&gt;
&lt;h2 id=&quot;what-we-want&quot;&gt;What we want&lt;/h2&gt;
&lt;p&gt;As my family has been using this application for a while, we now have a list of transactions from the bank and what account they map to. So, in the current software scene, my mind went to &quot;let&#39;s solve this with AI!&quot; and this might be a case were the tool fits the problem:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Use an LLM model to find what accounts should match to transactions, and use historical account/transaction mappings as the pattern to follow.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;taking-steps&quot;&gt;Taking steps&lt;/h2&gt;
&lt;p&gt;Now, this is my financial data, so I&#39;m not interested in sending this off to some company, but I do have an [underpowered] ollama server that I can use as a starting point.&lt;/p&gt;
&lt;p&gt;With &lt;a rel=&quot;external&quot; href=&quot;https://github.com/gbaptista/ollama-ai&quot;&gt;ollama-ai&lt;/a&gt;, the plan was underway: make a rails service to &quot;autocomplete&quot; the account for a list of transactions (&lt;code&gt;BankEntry&lt;/code&gt; in the code):&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;#39;ollama-ai&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;bank_entries&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #F9E2AF;font-style: italic;&quot;&gt; BankEntry&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;where&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #F38BA8;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;:&lt;/span&gt;&lt;span&gt; command&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;#39;ids&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;recent_bank_entries&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #F9E2AF;font-style: italic;&quot;&gt; BankEntry&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;includes&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(:&lt;/span&gt;&lt;span style=&quot;color: #F38BA8;&quot;&gt;accounts&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;limit&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt;50&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;).&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  filter&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;{|&lt;/span&gt;&lt;span&gt;be&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;|&lt;/span&gt;&lt;span&gt; be&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;amount_remaining&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prompt&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;lt;&amp;lt;~PROMPT&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;  Given this table of recent entries:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;  | amount_cents | description | accounts |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;  | --- | --- | --- |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;  #{&lt;/span&gt;&lt;span&gt;recent_bank_entries&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;{ |&lt;/span&gt;&lt;span&gt;bank_entry&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;    [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      bank_entry&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;amount_cents&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      bank_entry&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;description&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      bank_entry&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;account_entries&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #F38BA8;&quot;&gt;account_name&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;to_json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;    ].&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;then&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt; { |&lt;/span&gt;&lt;span&gt;vals&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;quot;| &lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;#{&lt;/span&gt;&lt;span&gt; vals&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;join&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;#39; | &amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;) }&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; |&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;  }.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;join&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #F5C2E7;&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;)}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;  What would the accounts look like for these entries:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;  | id | amount_cents | description |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;  | --- | --- | --- |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;  #{&lt;/span&gt;&lt;span&gt;bank_entries&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;{ |&lt;/span&gt;&lt;span&gt;bank_entry&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;    [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      bank_entry&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      bank_entry&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;amount_cents&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      bank_entry&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;description&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;    ].&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;then&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt; { |&lt;/span&gt;&lt;span&gt;vals&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;quot;| &lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;#{&lt;/span&gt;&lt;span&gt; vals&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;join&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;#39; | &amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;) }&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; |&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;  }.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;join&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #F5C2E7;&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;)}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;  Only respond with JSON, no additional formatting:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;    &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;#{&lt;/span&gt;&lt;span&gt;command&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;#39;ids&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;].&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;first&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;: [ &amp;quot;Account&amp;quot; ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;PROMPT&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;address&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;quot;http://192.168.1.1:11434&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;# This model seems to work well enough for this case,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;# but I&amp;#39;ll need to try more options as it still takes a solid minute&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;model&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;quot;hf.co/unsloth/Phi-4-mini-instruct-GGUF:Q4_K_M&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;client&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #F9E2AF;font-style: italic;&quot;&gt; Ollama&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #F38BA8;&quot;&gt;credentials&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;: {&lt;/span&gt;&lt;span style=&quot;color: #F38BA8;&quot;&gt; address&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;: })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;result&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span&gt; client&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;generate&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F38BA8;&quot;&gt;  model&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;:,&lt;/span&gt;&lt;span style=&quot;color: #F38BA8;&quot;&gt; prompt&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;:,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;  # No need to stream, I&amp;#39;m only interested in the final result&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F38BA8;&quot;&gt;  stream&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; false&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;  # This really helps some models to not respond with&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;  # &amp;quot;Here is the JSON ...&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F38BA8;&quot;&gt;  format&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;#39;json&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F9E2AF;font-style: italic;&quot;&gt;JSON&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;parse&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;first&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;#39;response&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;])&lt;/span&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt; # { &amp;quot;123&amp;quot;: [ &amp;quot;Groceries&amp;quot; ] }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It worked! Ok, not on my first attempt, it took a few iterations to correctly connect to ollama server (and I changed the gem in the process), but this approach gave me results that seemed to be a fair guess at matching accounts to transactions.&lt;/p&gt;
&lt;p&gt;Overall, this feature was quick and fun to add in, and while it works, there are more options to improve on it:&lt;/p&gt;
&lt;h2 id=&quot;next-steps&quot;&gt;Next steps&lt;/h2&gt;
&lt;p&gt;Still, there are some changes that would be good to try:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The account names read nice, but there are some cases where the name could confuse the model. It is worth trying to give it the account&#39;s ids (and this might save on tokens/time as well).&lt;/li&gt;
&lt;li&gt;There are lots of models to try out, or choose different quantization levels, or tweak the model&#39;s context length. There are a lot of LLM model/options to play with.&lt;/li&gt;
&lt;li&gt;In my setup, this is an expensive operation (takes just over a minute). I do cache the result, and try to warm the cache before this service is called. However it would probably be best to get a faster ollama server.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The real code is up on github &lt;a rel=&quot;external&quot; href=&quot;https://github.com/DouglasMeyer/ledger/blob/54b89625ad4206f32c681004ed6f0d739bee0e8d/app/controllers/api/bank_entry_autocomplete_v1.rb&quot;&gt;DouglasMeyer/ledger&lt;/a&gt;&lt;/p&gt;
</content>
        
    </entry>
</feed>
