Showing posts with label ai. Show all posts
Showing posts with label ai. Show all posts

Jul 5, 2026

Installing Nanobot on WSL Ubuntu

Recently, I decided to install Nanobot on my WSL Ubuntu environment.

Step 1: Preparing the Environment

I started by updating my system and installing the necessary packages:

sudo apt update
sudo apt install python3-full python3-venv git

Step 2: Cloning Nanobot

Next, I cloned the Nanobot repository from GitHub:

git clone https://github.com/HKUDS/nanobot.git
cd nanobot

Step 3: Creating a Virtual Environment

When I tried to install Nanobot directly with pip install -e ., I hit the following error:

error: externally-managed-environment
× This environment is externally managed
╰─> To install Python packages system-wide, try apt install...

This happened because Ubuntu now protects the system Python environment (PEP 668). The solution was to create a virtual environment:

python3 -m venv .venv
source .venv/bin/activate

Step 4: Installing Nanobot

Inside the virtual environment, I upgraded pip and installed Nanobot:

pip install --upgrade pip
pip install -e .

Step 5: Configuring Nanobot

I needed to configure Nanobot with my API key. I copied my existing config file from Windows into WSL:

mkdir -p ~/.nanobot
cp /mnt/c/Users/oktay/.nanobot/config.json ~/.nanobot/

Alternatively, I could have created a symlink to always share the same config:

ln -s /mnt/c/Users/oktay/.nanobot/config.json ~/.nanobot/config.json

Step 6: Facing the API Key Error

When I ran nanobot agent, I got:

Error: No API key configured for provider 'None'.

The fix was to ensure my ~/.nanobot/config.json contained the correct key:

{
  "api_key": "YOUR_OPENAI_API_KEY",
  "model": "gpt-4o-mini",
  "webui": true
}

Step 7: Running Nanobot

Finally, I launched Nanobot inside the virtual environment:

cd ~/nanobot
source .venv/bin/activate
nanobot agent

With the correct configuration, Nanobot started successfully, and the WebUI became available at http://127.0.0.1:8765.

Conclusion

Installing Nanobot on WSL Ubuntu was straightforward once I understood the new Python environment restrictions. The key lessons were:

  • Always use a virtual environment to avoid conflicts with system Python.
  • Keep your config file in ~/.nanobot/config.json with the correct API key.
  • Symlinking the config file from Windows ensures both environments stay in sync.

Now Nanobot runs smoothly on my WSL setup, ready for experiments and development.

Jun 9, 2026

Comparing MLX and Ollama on a Base M1 Mac

A simple benchmark comparing the Qwen 3.5 4B model running on Apple MLX and Ollama on a base M1 iMac.

For this test, I ran the Qwen 3.5 4B model in two different environments: Apple's MLX framework using an 8-bit quantized model, and Ollama using a 4-bit quantized model.

Both tests used the same input and were executed on the same machine. The request contained a single prompt:

Hello!

Streaming was disabled, so each API call returned only after the entire response had been generated.

Test Environment

The benchmark was performed on the following system:

  • Hardware: Apple iMac (M1 Chip, 8 Core CPU / 8 Core GPU, Unified Memory Architecture)
  • Operating System: macOS
  • Engine A (MLX): mlx_lm.server hosting mlx-community/Qwen3.5-4B-8bit (~5.2 GB)
  • Engine B (Ollama): ollama hosting qwen3.5:4b (~3.4 GB, Q4_K_M quantization)

Test 1: MLX (8-bit)

The first test used Apple's MLX framework with the 8-bit version of the model.

Command used:

curl -X POST http://127.0.0.1:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model": "mlx-community/Qwen3.5-4B-8bit", "messages": [{"role": "user", "content": "Hello!"}]}' \
  -w "\n| Total Time: %{time_total}s |\n"

Results

  • Total Wall-Clock Time: 77.56 seconds
  • Total Generated Tokens: 866 tokens

The response took over a minute to complete. Because streaming was disabled, the client did not receive any output until generation finished. The model generated 866 tokens before returning the final response.

Test 2: Ollama (4-bit)

The second test used Ollama with the default 4-bit version of the same model.

Command used:

curl -X POST http://127.0.0.1:11434/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model": "qwen3.5:4b", "messages": [{"role": "user", "content": "Hello!"}]}' \
  -w "\n| Total Time: %{time_total}s |\n"

Results

  • Total Wall-Clock Time: 23.61 seconds
  • Total Generated Tokens: 392 tokens

The Ollama response completed much faster and generated fewer tokens than the MLX test.

Comparing the Results

Metric MLX (8-bit) Ollama (4-bit)
Response Time 77.56 s 23.61 s
Generated Tokens 866 392
Model Size ~5.2 GB ~3.4 GB

For this benchmark, Ollama completed the same request approximately 3.2× faster than MLX.

One noticeable difference was token generation. The MLX run produced 866 tokens, while the Ollama run produced 392 tokens. Processing more tokens generally takes more time, which may have contributed to the latency difference observed in this test.

Another difference was model size. The MLX model occupied approximately 5.2 GB on disk, while the Ollama model occupied approximately 3.4 GB.

Notes About This Test

This benchmark reflects a single prompt executed on a base M1 system. Results may vary depending on factors such as:

  • Prompt complexity
  • Model settings
  • Quantization format
  • Hardware configuration
  • Engine implementation
  • Whether streaming is enabled

The purpose of this test was not to determine which framework is universally better, but to compare how these two configurations behaved under the same conditions on the same machine.

Final Takeaways

  1. The Ollama 4-bit configuration responded significantly faster on this base M1 system.
  2. The Ollama run generated fewer tokens than the MLX run.
  3. The model sizes were noticeably different (3.4 GB vs 5.2 GB).
  4. Streaming can improve the user experience by displaying output as it is generated rather than waiting for the full response.

To enable streaming, add the following field to your API request payload:

"stream": true

Mar 15, 2024

AI means everyone can now be a programmer(?)

Is it that easy?

Assuming you are not a developer and want to create an app to take screenshots on macOS.

You started to ask questions to AI and installed developer tools. Now you are ready for development.

  1. Gemini
  2. How to take a screenshot on macos xcode using swift?

    You paste the code to XCode and see an error!

    Ask Gemini to provide another solution.
    The code you provided in swift didn't work. Suggest another swift way to capture a screenshot.

    Gemini gives an apology and suggests another solution.

    Let's see in XCode.

    Can you see a strange code that contains Arabic letters?

    guard let contentFilter = SCC محتوى الشاشة(sharingMode: .none) else { return nil }

    You want to switch to ChatGPT to accomplish this easy task with the same prompt. 👇

  3. ChatGPT
  4. You paste the code provided by ChatGPT. Again, there is a problem in the code!

    context.makeCurrent() didn't work. Is there any other way?

    You pasted this code, and it worked! After a few trials, now think you are a programmer.

    What will you do if you see CGDisplayCreateImage(_:) is deprecated?

    So you keep asking for alternative ways, and you learn that there is a shiny framework named ScreenCaptureKit.

    I recommend trying to ask both Gemini and ChatGPT to take a screenshot using ScreenCaptureKit. I tried, on several attempts, AI suggested wrong code each time.

    Then you will decide how easy programming is!