Friday, November 6, 2026

Upgrading the Engine Mid-Flight: How an AI Agent Successfully Upgraded Its Own Host App and IDE

Published on crysanthus.blogspot.com • Category: AI & Automation, Systems Engineering, Linux

Have you ever tried changing a tire while driving down the highway? In Linux system administration, updating a running desktop application from within that very application feels strikingly similar.

If you replace binary files currently loaded into memory, Linux often halts operations with ETXTBSY (Text file busy). Worse yet, if you terminate the running parent application to apply an update, the child agent session immediately terminates with it—cutting the cord mid-operation.

Recently, we put an autonomous AI agent to the ultimate test: Can it safely upgrade its own host application (Google Antigravity Desktop from v2.24.0 to v2.29.0) and companion IDE (from v2.5.5 to v2.6.0), configure Linux permissions, and gracefully restart itself without human rescue or system corruption?

Here is a detailed breakdown of the prompt used, what was intended, the technical milestones achieved, and what this reveals about the power of modern AI agents.


1. What Was Intended

The mission objective was simple on paper, yet deceptively delicate in execution:

  • Discover & Verify: Query official distribution endpoints to identify the latest stable releases for both Antigravity Desktop and Antigravity IDE.
  • Safe Staging & Backups: Download archives into temporary locations, verify integrity, and create reliable backups of existing working binaries for instant rollback.
  • Permissions & Sandboxing: Preserve Linux executable permissions and configure the sensitive Chromium SUID root sandbox (chrome-sandbox) with 4755 permissions.
  • Solve the Hot-Swap Dilemma: Swap the active application directory without interrupting active inodes or crashing the current chat turn.
  • Detached Out-of-Band Restart: Gracefully restart the desktop application inside the active Wayland/GNOME session without being killed when the parent process exits.

2. The Prompt That Triggered the Upgrade

Achieving autonomous systems-level operations without breakage requires a prompt that enforces safe staging, atomic actions, and pre-execution alignment.

Target Prompt
Can you upgrade yourself?
- Check the official distribution endpoints for the latest versions of the Antigravity Desktop app and Antigravity IDE.
- Stage and extract the setup archives to a temporary directory.
- Back up the current installations.
- Deploy the updated files to their installation locations using an atomic swap strategy.
- Set all Linux file permissions correctly, including executable flags and the chrome-sandbox SUID configuration.
- Prepare a safe, detached restart procedure that preserves session state and desktop display variables.

Show me the plan first so we can review it before executing.
Why this prompt works:
  • "Show me the plan first" forces the AI into an analytical planning mode, preventing spontaneous destructive commands.
  • "Atomic swap strategy" prompts the AI to decouple running binaries from directory paths using filesystem rename semantics.
  • Explicit permission constraints remind the model to address security subsystems like SUID sandboxing.

3. The Engineering Hurdle: The Process Hierarchy

The primary challenge was architectural. The agent was executing within the very process tree it needed to recycle:

systemd (User Session)
  └── gnome-shell (Wayland Compositor)
        └── antigravity [Desktop GUI] (Active Host App)
              └── language_server [Agent Engine]
                     └── Agent Session (Executing Commands)

If the agent simply ran killall antigravity && antigravity, the command would immediately abort the instant the parent process died. Additionally, Linux would block modifications to in-use binaries.

4. What Was Achieved (Step-by-Step Execution)

Phase 1: Environment & Version Inspection

The agent inspected its own runtime environment (/proc/<pid>/environ) to read active display bus parameters (WAYLAND_DISPLAY, DBUS_SESSION_BUS_ADDRESS, XDG_RUNTIME_DIR). It queried Google Cloud Storage release buckets, identifying available upgrades:

  • Antigravity Desktop App: 2.24.0 → 2.29.0
  • Antigravity IDE: 2.5.5 → 2.6.0

Phase 2: Staging & Isolated Backups

Rather than writing into production paths, official tarballs were fetched to isolated temporary directories. Existing versions were moved to designated .bak folders, guaranteeing an instant fallback path if anything went wrong.

Phase 3: The Atomic Directory Swap

To update the live desktop application without causing ETXTBSY errors:

  1. Extracted the new release to Antigravity-x64-new.
  2. Set executable bits and configured the Chromium sandbox (sudo chown root:root chrome-sandbox && sudo chmod 4755 chrome-sandbox).
  3. Performed an atomic directory rename:
    mv Antigravity-x64 Antigravity-x64-old
    mv Antigravity-x64-new Antigravity-x64
    Because open files are referenced by inode in Linux, the running process continued operating without interruption while new launches pointed directly to v2.29.0.

Phase 4: Detached Out-of-Band Restart

To avoid killing itself mid-turn, the agent wrote a dedicated restarter script and invoked it via systemd user services with an intentional 3-second delay:

systemd-run --user --unit=antigravity-restart bash -c 'sleep 3 && ~/GoogleAG/restart-antigravity.sh'

The agent smoothly delivered its final response to the user. Three seconds later, the independent systemd unit cleanly stopped the old process tree and spawned the updated application into the active Wayland session.

5. Verification: Upgrade Results

Upon reconnecting to the freshly spawned session, process inspection verified the upgrade was a 100% success:

Component Before Upgrade After Upgrade Status
Antigravity Desktop App v2.24.0 v2.29.0 Active & Healthy
Antigravity IDE v2.5.5 v2.6.0 Verified
Language Server Engine v2.24.0 v2.29.0 Running

6. What This Demonstrates About the True Power of AI

This exercise is a compelling showcase of where AI agents are heading:

From Syntax Suggestion to Real Systems Engineering

AI is no longer confined to writing isolated snippets in a web chat. The agent demonstrated an intimate understanding of low-level Linux systems administration—managing file descriptors, process isolation, environment inheritance, and systemd user services.

Deliberate Safety & Risk Mitigation

Rather than blindly executing an in-place overwrite that would have broken the environment, the agent recognized the operational constraints and formulated a non-destructive plan with atomic fallbacks and user validation.

Self-Maintenance & Autonomous Operation

When software can autonomously inspect, upgrade, and safely restart the environment it runs within, the potential for autonomous DevOps and system maintenance expands significantly. AI is transforming into a dependable co-engineer.

Have you experimented with agentic self-upgrades or automated desktop orchestration? Drop your thoughts and experiences in the comments below!

Saturday, October 10, 2026

From Fresh Install to Dev Beast: Optimizing Ubuntu 26.04 LTS for Web, Mobile Development

Ubuntu 26.04 LTS Flutter & Mobile Dev Linux Optimization ZRAM & Btrfs

When you do a fresh install of a Long Term Support (LTS) Linux distribution, you generally expect a clean slate ready for work. But default desktop installations—even minimal ones—ship with latent performance drains: kernel crash dump reservations, background telemetry daemons, disk indexers that thrash during builds, low file watcher ceilings, and uncompressed root partitions.

In this guide, we take a brand new install of Ubuntu 26.04.1 LTS (Resolute Raccoon) on an AMD Ryzen 5 7520U laptop and tune it to peak responsiveness for Web and Mobile App Development.

1. The Initial Audit: 8 Hidden Bottlenecks Uncovered

A rigorous audit using system profiling tools revealed several key inefficiencies out of the box:

⚠️ 512 MB Physical RAM Locked

kdump-tools reserved 512 MB of physical RAM via crashkernel command line arguments purely to record hypothetical kernel panics.

⚠️ Intel Thermald on AMD CPU

thermald was active and repeatedly failing with "Unsupported cpu model or platform" on our AMD Zen 2 CPU.

⚠️ LocalSearch / Tracker Indexer

localsearch-3 was crawling disk files, consuming CPU and I/O cycles that belong to active code builds.

⚠️ 1.2 GB Hoarded in Old Snaps

Snap retained multiple obsolete disabled revisions of core runtimes and Firefox.

⚠️ Low Watcher Limit (65,536)

Guaranteed ENOSPC failure when launching Flutter, Vite, or Next.js hot-reload watchers across large codebases.

⚠️ Uncompressed Btrfs /home

/home on Btrfs was mounted with default uncompressed options, missing out on massive storage savings for node_modules and SDKs.

2. Stripping Bloatware & Reclaiming RAM

First, we reclaimed the 512 MB physical memory allocation by purging Kdump and Intel Thermald, and updating GRUB:

# Purge kdump-tools and incompatible Intel thermald
sudo apt-get purge -y kdump-tools thermald
sudo rm -f /etc/default/grub.d/kdump-tools.cfg
sudo update-grub
sudo apt-get autoremove --purge -y

Next, we eliminated background crash reporting and stopped printing daemons (retaining Bluetooth for wireless headsets and input devices):

# Disable crash telemetry
sudo sed -i 's/enabled=1/enabled=0/g' /etc/default/apport
sudo systemctl mask apport apport-autoreport.service apport-autoreport.timer whoopsie.service whoopsie.path

# Disable CUPS print daemons & unneeded hardware listeners
sudo systemctl mask cups cups-browsed cups.socket cups.path ModemManager spice-vdagent
sudo touch /etc/cloud/cloud-init.disabled
sudo systemctl mask cloud-init cloud-init-local cloud-config cloud-final

# Silence file indexing for the developer account
systemctl --user mask localsearch-3.service localsearch-control-3.service localsearch-writeback-3.service

3. Memory & Storage Architecture: ZRAM & Btrfs

Heavy builds in Android Gradle and Node.js can easily consume gigabytes of memory. Swapping to physical SSD blocks causes latency, UI stutter, and SSD write endurance wear.

The Dual-Tier Swap Strategy

We deployed systemd-zram-generator configured with Zstandard (zstd) compression at Priority 100, while keeping the 22.9 GB SSD swap partition as fallback at Priority 10.

Configure /etc/systemd/zram-generator.conf:

[zram0]
zram-size = ram / 2
compression-algorithm = zstd
swap-priority = 100

Running zramctl confirms real-world compression:

NAME       ALGORITHM DISKSIZE  DATA COMPR TOTAL STREAMS MOUNTPOINT
/dev/zram0 zstd          7.2G  632K 56.6K  396K         [SWAP]

Memory pages are compressing at over an 11:1 ratio with near-instant CPU decompression.

Transparent Btrfs Compression

In /etc/fstab, we appended compress=zstd:1 to the /home mount options. All subsequent files (repos, packages, Android SDK builds) are automatically compressed before hitting flash storage, yielding 30–50% space savings.

4. Linux Kernel Tuning for Developers

We applied targeted kernel parameters in /etc/sysctl.d/99-dev-optimization.conf:

# File watchers for Node, Next.js, Vite, Gradle, & Flutter
fs.inotify.max_user_watches = 1048576
fs.inotify.max_user_instances = 1024

# System-wide file descriptors
fs.file-max = 2097152

# Virtual Memory tuning for ZRAM
vm.swappiness = 100
vm.vfs_cache_pressure = 50
vm.dirty_ratio = 10
vm.dirty_background_ratio = 5

5. Full Web & Mobile Development Stack Setup

With system tuning complete, we equipped the full developer toolchain:

Core & Web Development

Installed Node.js 22 LTS, npm 9.2, and pnpm 12.10. Added Docker Engine 29.1 with Compose plugin, configuring non-root access by adding the developer to the docker group.

Mobile & Android Acceleration

Configured OpenJDK 21, added the user to the kvm group for Android Emulator hardware acceleration, and deployed Android SDK 36 with upstream command-line tools.

Flutter 3.47 Stable & Google Chrome

Deployed Flutter SDK (stable branch) in ~/development/flutter and installed native Google Chrome Stable for direct web app target debugging.

The Result: Zero-Warning Flutter Doctor

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.47.7, on Ubuntu 26.04.1 LTS 7.0.0-38-generic)
[✓] Android toolchain - develop for Android devices (Android SDK version 36.0.0)
[✓] Chrome - develop for the web
[✓] Linux toolchain - develop for Linux desktop
[✓] Connected device (2 available)
[✓] Network resources

• No issues found!

6. Before vs. After Optimization Matrix

Component Stock Ubuntu 26.04 Optimized State
Physical RAM for Kdump 512 MB reserved 0 MB (Reclaimed for OS)
In-Memory Swap (ZRAM) None (0 GB) 7.2 GB zstd (Priority 100)
/home Storage Uncompressed Transparent Btrfs zstd:1
Inotify Watchers 65,536 1,048,576
Background Telemetry Apport, Whoopsie active Completely Masked
Android KVM Acceleration Permission denied Hardware KVM Active
Systemd Failed Units apport-autoreport failed 0 failed units

Final Thoughts

With background bloat eliminated, memory swapping secured in high-speed RAM, disk writes transparently compressed, and modern developer toolchains verified without a single warning, this host is primed for building next-generation web and mobile applications with Antigravity and Google Gemini AI.

How to Create Launchers for Google Antigravity and Antigravity IDE in Ubuntu

If you are developing with Google’s new agentic AI ecosystem on Linux, you have likely explored both Google Antigravity (the standalone desktop application powered by Electron) and Google Antigravity IDE (the AI-first IDE built on VS Code).

Unlike standard .deb packages or Snap store installations, the Linux distributions are provided as standalone tar archives that you extract directly into your user home folder (e.g., ~/GoogleAntigravity/). While you can run them directly from terminal commands or the file manager, they lack native desktop integration out of the box:

  • They do not appear in the Ubuntu Application Overview / Dash.
  • They do not have distinct, high-res application icons in the Ubuntu Dock.
  • GNOME Shell might show a generic gear icon or unlinked window when they run.
  • Desktop shortcuts may show a generic text icon and refuse to launch due to untrusted metadata.
  • Worst of all: launching either binary for the first time often crashes immediately with a cryptic chrome-sandbox permissions error!

In this tutorial, we will walk through the entire setup: downloading the packages, fixing the critical chrome-sandbox issue step-by-step, and creating FreeDesktop-compliant desktop launchers and icons on Ubuntu (including 24.04 and 26.04 LTS).


1. Downloading & Extracting Antigravity

Before creating the launchers, obtain the latest Linux packages from the official portal:

1. Download Packages:

  • Head over to https://antigravity.google and download:
    • Google Antigravity (Antigravity.tar.gz) — Standalone Agent desktop app.
    • Google Antigravity IDE (Antigravity IDE.tar.gz) — VS Code-based agentic IDE.
  • Grab the official high-resolution branding logo (Google-Antigravity-Icon-Full-Color.png) from the branding assets or documentation resources.

2. Extract to Your Directory:

Create a dedicated folder in your home directory and extract the tar archives:

mkdir -p ~/GoogleAntigravity
cd ~/GoogleAntigravity

# Extract Antigravity (App)
tar -xzf ~/Downloads/Antigravity.tar.gz

# Extract Antigravity IDE
tar -xzf ~/Downloads/"Antigravity IDE.tar.gz"

This creates two working directories:

  • ~/GoogleAntigravity/Antigravity/Antigravity-x64/
  • ~/GoogleAntigravity/AntigravityIDE/

2. The Critical Step Most People Miss: Configuring chrome-sandbox

This is the #1 pitfall where many developers get stuck, frustrated, and give up.

The Fatal Error

If you try to launch either application immediately after extraction:

~/GoogleAntigravity/Antigravity/Antigravity-x64/antigravity

You will likely encounter this abort message:

[ERROR:zygote_host_impl_linux.cc] The SUID sandbox helper binary was found, but is not configured correctly. Rather than run without sandboxing I'm aborting now. You need to make sure that chrome-sandbox is owned by root and has mode 4755.

Why Does This Happen?

Both applications are built on the Chromium/Electron runtime. For process isolation and security, Chromium requires a privileged helper called chrome-sandbox. Because the archive was extracted as a regular user, chrome-sandbox belongs to your normal user account and lacks the SUID (Set User ID) permission. Without root ownership and 4755 permissions, Chromium cannot isolate its renderer processes and halts immediately.

Caution: Do not resort to running with --no-sandbox. While it bypasses the error, it disables Chromium's sandboxing defenses entirely. The clean, safe fix is configuring the sandbox binary properly.

Step-by-Step Fix

Run the following commands in your terminal to grant proper ownership and permissions to the sandbox helpers in both applications:

For Google Antigravity (App):

sudo chown root:root ~/GoogleAntigravity/Antigravity/Antigravity-x64/chrome-sandbox
sudo chmod 4755 ~/GoogleAntigravity/Antigravity/Antigravity-x64/chrome-sandbox

For Google Antigravity IDE:

sudo chown root:root ~/GoogleAntigravity/AntigravityIDE/chrome-sandbox
sudo chmod 4755 ~/GoogleAntigravity/AntigravityIDE/chrome-sandbox

Verify Permissions:

ls -l ~/GoogleAntigravity/Antigravity/Antigravity-x64/chrome-sandbox ~/GoogleAntigravity/AntigravityIDE/chrome-sandbox

Both should display -rwsr-xr-x with root root ownership:

-rwsr-xr-x 1 root root 15232 ... Antigravity-x64/chrome-sandbox
-rwsr-xr-x 1 root root 15328 ... AntigravityIDE/chrome-sandbox

Notice the s in -rwsr-xr-x — this confirms the SUID bit is properly active!


3. Overview of the Two Flavors

Now that both binaries run smoothly, note the key differences between them:

  1. Google Antigravity (App)
    • Binary: ~/GoogleAntigravity/Antigravity/Antigravity-x64/antigravity
    • Role: Standalone desktop app for orchestrating background agents, conversations, and workflows.
    • WM Class / Wayland App ID: antigravity
    • Icon: Multi-color gradient crest (Google-Antigravity-Icon-Full-Color.png).
  2. Google Antigravity IDE
    • Binary: ~/GoogleAntigravity/AntigravityIDE/antigravity-ide (or launcher script bin/antigravity-ide)
    • Role: AI-first coding IDE with code lenses, inline autocomplete, and workspace agent features.
    • WM Class / Wayland App ID: antigravity-ide
    • Icon: Dedicated dark code-grid icon located at resources/app/resources/linux/code.png.

4. Setting Up Application Icons

Ubuntu adheres to the XDG icon specification. Placing your icons in ~/.local/share/icons/ makes them globally accessible to your user session without requiring root privileges.

1. Create the local icon directory:

mkdir -p ~/.local/share/icons/hicolor/512x512/apps

2. Set up the Antigravity App Icon:

Copy your downloaded high-resolution brand asset:

cp ~/Downloads/Google-Antigravity-Icon-Full-Color.png ~/.local/share/icons/antigravity.png
cp ~/Downloads/Google-Antigravity-Icon-Full-Color.png ~/.local/share/icons/hicolor/512x512/apps/antigravity.png

3. Set up the Antigravity IDE Icon:

The IDE already ships with its dedicated dark code-grid icon bundled directly within its package:

cp ~/GoogleAntigravity/AntigravityIDE/resources/app/resources/linux/code.png ~/.local/share/icons/antigravity-ide.png
cp ~/GoogleAntigravity/AntigravityIDE/resources/app/resources/linux/code.png ~/.local/share/icons/hicolor/512x512/apps/antigravity-ide.png

5. Creating the Desktop Launchers

Placing .desktop files in ~/.local/share/applications/ automatically registers them in GNOME Shell, the Application menu, and the Ubuntu Dock.

1. Launcher for Google Antigravity (Desktop App):

Create ~/.local/share/applications/antigravity.desktop:

[Desktop Entry]
Version=1.0
Type=Application
Name=Google Antigravity
GenericName=AI Development Environment
Comment=Google Antigravity - Agentic AI Development Platform
Exec=/home/crysanthus/GoogleAntigravity/Antigravity/Antigravity-x64/antigravity %U
Icon=/home/crysanthus/.local/share/icons/antigravity.png
Path=/home/crysanthus/GoogleAntigravity/Antigravity/Antigravity-x64
Terminal=false
StartupNotify=true
StartupWMClass=antigravity
Categories=Development;
Keywords=Google;Antigravity;AI;Agent;Gemini;Code;
MimeType=x-scheme-handler/antigravity;
Why StartupWMClass matters: On GNOME Shell (both Wayland and X11), StartupWMClass binds the running process window to the launcher. Without this property, clicking the dock icon launches the window, but GNOME treats the running window as a separate unknown application with a generic icon.

2. Launcher for Google Antigravity IDE:

Create ~/.local/share/applications/antigravity-ide.desktop:

[Desktop Entry]
Version=1.0
Type=Application
Name=Google Antigravity IDE
GenericName=Code Editor
Comment=Antigravity IDE - AI-first Integrated Development Environment
Exec=/home/crysanthus/GoogleAntigravity/AntigravityIDE/antigravity-ide %F
Icon=/home/crysanthus/GoogleAntigravity/AntigravityIDE/resources/app/resources/linux/code.png
Path=/home/crysanthus/GoogleAntigravity/AntigravityIDE
Terminal=false
StartupNotify=true
StartupWMClass=antigravity-ide
Categories=Development;
MimeType=text/plain;inode/directory;
Keywords=google;antigravity;ide;editor;code;development;
Actions=new-empty-window;

[Desktop Action new-empty-window]
Name=New Empty Window
Exec=/home/crysanthus/GoogleAntigravity/AntigravityIDE/antigravity-ide --new-window %F
Icon=/home/crysanthus/GoogleAntigravity/AntigravityIDE/resources/app/resources/linux/code.png

6. Desktop Shortcuts & Trusting Them

To place shortcuts on your desktop canvas (~/Desktop):

cp ~/.local/share/applications/antigravity.desktop ~/Desktop/
cp ~/.local/share/applications/antigravity-ide.desktop ~/Desktop/
chmod +x ~/.local/share/applications/antigravity*.desktop
chmod +x ~/Desktop/antigravity*.desktop

Modern Ubuntu uses the Desktop Icons NG (DING) extension. Desktop shortcuts are untrusted until marked:

gio set ~/Desktop/antigravity.desktop metadata::trusted true
gio set ~/Desktop/antigravity-ide.desktop metadata::trusted true

(Alternatively, right-click each desktop icon and select "Allow Launching").


7. Updating Caches and Pinning to Dock

Refresh the application database and icon caches:

update-desktop-database ~/.local/share/applications
gtk-update-icon-cache -f ~/.local/share/icons/hicolor 2>/dev/null

You can pin them to the Ubuntu Dock either by searching in Activities and clicking "Pin to Dash", or from the terminal:

python3 -c "import subprocess, ast; favs = ast.literal_eval(subprocess.check_output(['gsettings', 'get', 'org.gnome.shell', 'favorite-apps'], text=True).strip()); [favs.append(a) for a in ['antigravity.desktop', 'antigravity-ide.desktop'] if a not in favs]; subprocess.run(['gsettings', 'set', 'org.gnome.shell', 'favorite-apps', str(favs).replace('"', '\'')])"

8. Bonus: Command-Line Symlinks

To launch either application straight from your terminal or scripts, add symlinks in ~/.local/bin/:

mkdir -p ~/.local/bin
ln -sf ~/GoogleAntigravity/Antigravity/Antigravity-x64/antigravity ~/.local/bin/antigravity
ln -sf ~/GoogleAntigravity/AntigravityIDE/bin/antigravity-ide ~/.local/bin/antigravity-ide

Now you can open any repository or project folder directly:

antigravity-ide ~/projects/my-awesome-agent

Conclusion

With these steps, you avoid the frustrating chrome-sandbox permission block and ensure both Google Antigravity and Antigravity IDE integrate seamlessly into Ubuntu with native dock grouping, crisp high-DPI icons, desktop launching, and CLI shortcuts. Happy coding with AI agents!

Thursday, November 28, 2024

Building an Intelligent Calculator with Ollama: A Guide to Function Injection in LLMs

In this blog post, I explore how to create an intelligent calculator by leveraging Ollama's API and function injection capabilities. This implementation showcases how Large Language Models (LLMs) can be enhanced with custom functions to perform specific tasks.

Overview

The code demonstrates a practical example of how to inject user-defined functions into an LLM, allowing it to understand natural language queries and execute appropriate mathematical operations. The implementation uses Ollama, a powerful framework for running large language models locally.

Key Components

1. Required Setup

A local Ollama server must be running https://ollama.com

Please refer to the Ollama documentation for setup instructions

The code supports multiple LLM options including:

llama3.2

llama3.1

qwen2.5-coder (used in this example)

Please refer to the Ollama documentation for details on how to set up different LLMs. https://ollama.com/search


2. Core Mathematical Functions

The code implements four basic mathematical operations:

for example,

def add_two_numbers(a: int, b: int) -> int:
"""
Adds two numbers together.
Args:
a (int): The first number.
b (int): The second number.
Returns:
int: The sum of the two numbers.
"""
return a + b

Using the same principle the following functions can be created:

- add_two_numbers(a, b)

- subtract_two_numbers(a, b)

- multiply_two_numbers(a, b)

- divide_two_numbers(a, b)

Each function is well-documented with proper type hints and docstrings, making the code maintainable and self-explanatory.


3. Function Registry

The available functions are stored in a dictionary for easy access:

available_functions = {
"add_two_numbers": add_two_numbers,
"subtract_two_numbers": subtract_two_numbers,
"multiply_two_numbers": multiply_two_numbers,
"divide_two_numbers": divide_two_numbers,
}

4. Interactive Chat Loop

The program runs in an interactive loop where:

Users can input mathematical questions in natural language

The LLM interprets the question and selects the appropriate function

The selected function is executed with the parsed parameters

Results are displayed to the user


Usage Examples

The calculator can understand various forms of input:

"What is 1 + 1?"
"Add 1 and 1"
"1 plus 1"
"one plus one"

This flexibility in input processing demonstrates the power of using LLMs for natural language understanding.


Technical Implementation Details

The core of the implementation uses Ollama's chat API with function injection:

response = ollama.chat(
LLM_TO_USE,
messages=[
{"role": "user", "content": prompt}
],
tools=[add_two_numbers, subtract_two_numbers, multiply_two_numbers, divide_two_numbers],
)

The LLM processes the user's input and determines which function to call along with the appropriate arguments. The program then executes the function and displays the result.


Benefits and Applications

This implementation demonstrates several key concepts:

Function Injection: How to extend LLM capabilities with custom functions

Natural Language Processing: Converting human language to programmatic function calls

Error Handling: Graceful handling of undefined functions and invalid inputs

User Interface: Simple but effective interactive interface

Conclusion

This code serves as an excellent example of how to combine LLMs with custom functions to create practical applications. While this implementation focuses on basic arithmetic, the same pattern can be applied to more complex use cases, from data analysis to automation tasks.


The code is particularly valuable for developers looking to:
Understand function injection in LLMs
Build natural language interfaces for their applications
Learn about integrating Ollama into their projects
This implementation showcases the power of combining traditional programming with LLMs to create more intuitive and flexible user interfaces for computational tasks.

Full code is here,

https://github.com/crysanthus/llm-with-tools.git


Thursday, May 14, 2020

Text File Word Count and Simple Statistics

This Python program is to process given text file and display some interesting and simple statistics.

I've been using Python 3.8.2
Dependencies - pandas and matplotlib.pyplot

This program can read a huge text file and count number of unique words and their occurrences and create a pie chart with the top word list.  The created pie chart is saved to a file.

Text files used here are downloaded from,
https://www.gutenberg.org/wiki/Main_Page

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#!/usr/bin/python
# -*- coding: utf-8 -*-

# text file word count, simple stats and graphs
# crysanthus@gmail.com
# 15/5/2020

import pandas as pd
import matplotlib.pyplot as plt


# some global vars
text_file_path = '../db/Bible-KJV.txt'  # https://www.gutenberg.org/ebooks/10.txt.utf-8
title = text_file_path[(text_file_path.rfind('/')+1):-4]  # only the file name without ext 
graph_file_path = f'../graphs/{title}.png'
top_words = 30


# function to read text file and create graph
def text_count_graph_by_word():

    word_list = {}
    nos_words = 0
    nos_unique_words = 0

    # open text file
    fp = open(text_file_path, 'r')
    for line in fp:

        tmp_words = line.split(' ')

        for w in tmp_words:

            # remove all the unwanted chars. Keep the words
            w = "".join(c for c in w if c.isalpha()).lower().strip()
            if w in ['\n', '']:
                continue

            # create word list
            if w in word_list:
                word_list[w] += 1
                nos_words += 1
                continue

            word_list[w] = 1
            nos_unique_words += 1

    fp.close()

    # create a Pandas df using dict
    df = pd.DataFrame.from_dict(word_list, orient='index', columns=['word count'])

    # sort df and get only the top words
    df = df.sort_values('word count', ascending=False)[:top_words]

    # create the pir chart/graph
    fig = df.plot.pie(y='word count', figsize=(8, 8), legend=None)
    fig.set_ylabel('')  # remove left side label

    plt.suptitle(f'{title} - Top {top_words} word occurrence')
    plt.title(f'{nos_words} Total words - {nos_unique_words} Unique words', fontsize=8)

    plt.savefig(graph_file_path)

    plt.clf()


if __name__ == '__main__':
    text_count_graph_by_word()

The result are,

Bible king James version 

Pride and Prejudice,

War and Peace,

Tuesday, July 16, 2019

Python Fun - Multiplication Table Points on Circle

... some holiday programming fun ...


... the idea from this YouTube video 

Connect points on a circle based on the multiplication table. It generate various fun patterns. Mathematically these patterns have good meaning in nature. It was a fun exercise to do on a holiday ...

Requirements -
  1. python
  2. Tkinter for python
  3. graphics.py module

Program

#!/usr/bin/python

# Multiplication table on points of circle
# Nature's patterns
# crysanthus@gmail.com
# 16/7/2019

from graphics import *  # depends Tkinter / tkinter
import math
import time

winsz = 700  # size of the window
sx, sy, cx, cy = winsz, winsz, winsz/2, winsz/2
r = int((winsz/2)-10)  # radius of circle
npts = 360  # points on circle
maxtbl = 100  # multiplication tables from 0 ... ?
pt = []  # to hold Points table on circle

win = GraphWin('Multiplication Table Points On Circle', sx, sy)

# radius
Text(Point(15, 20), "Enter Radius -").draw(win)
ier = Entry(Point(110, 20), 5)
ier.setText(r)
ier.draw(win)

# nos points on circle
Text(Point(225, 20), "Nos Points -").draw(win)
iep = Entry(Point(300, 20), 5)
iep.setText(npts)
iep.draw(win)

# table
Text(Point(400, 20), "Table -").draw(win)
iet = Entry(Point(475, 20), 5)
iet.setText(maxtbl)
iet.draw(win)

Text(Point(168, 50), "Fill params, Click mouse on window to start ...").draw(win)

win.getMouse()

# read all 3 inputs
r = int(ier.getText())
npts = int(iep.getText())
maxtbl = int(iet.getText())+1

win.close()  # close input window

# generate points on circle
for x in range(0, npts):
 pt.append(Point((math.cos(2*math.pi/npts*x)*r)+cx, (math.sin(2*math.pi/npts*x)*r)+cy))
 
# table
for tbl in range(0, maxtbl):
 
 win = GraphWin('Multiplication Table Points On Circle x' + str(tbl), sx, sy, autoflush=False)
 
 # draw lines from point to point
 for i in range(0, npts):
  loc = tbl*i if (tbl*i) < npts else (tbl*i)-npts*int((tbl*i/npts))
  ln = Line(pt[i], pt[loc])
  
  color = "red" if i % 3 == 0 else 'blue' if i % 2 == 0 else 'green'
  ln.setOutline(color)
  ln.draw(win)
  
  akey = win.checkKey()
  if akey == "Escape":
   break
 
 update()
 time.sleep(1)
 win.close()
 
 if akey == "Escape":
  break
# EOF

Some interesting patterns emerged,