Skip to content

Commit 8d6ed60

Browse files
committed
Add Learning Path: build a CPU-orchestrated local AI agent with Ollama and Gemma
1 parent c05d638 commit 8d6ed60

10 files changed

Lines changed: 1331 additions & 0 deletions

File tree

assets/contributors.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ author,company,github,linkedin,twitter,website
22
Jason Andrews,Arm,jasonrandrews,jason-andrews-7b05a8,,
33
Doug Anson,Arm,DougAnsonAustinTx,douganson,,
44
Pareena Verma,Arm,pareenaverma,pareena-verma-7853607,,
5+
Jaidev Singh Chadha,Arm,jaidev17,jaidevsinghchadha,,
56
Ronan Synnott,Arm,,ronansynnott,,
67
Florent Lebeau,Arm,,,,
78
Brenda Strech,Remote.It,bstrech,bstrech,@remote_it,www.remote.it
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
---
2+
title: Understand the agent and the CPU/GPU split
3+
weight: 2
4+
5+
### FIXED, DO NOT MODIFY
6+
layout: learningpathall
7+
---
8+
9+
## What you'll build
10+
11+
In this Learning Path, you'll build and run a *local concierge agent*: a terminal application that answers research-style questions, such as finding restaurants, comparing products, or summarizing a topic, by searching the web, reading multiple pages, and writing a fact-checked summary.
12+
13+
Everything runs on your own Arm machine. The agent uses a large language model (LLM) served locally by [Ollama](https://ollama.com/), so your prompts and the pages you browse never leave the device. The same code runs on an Apple silicon MacBook, an Arm Linux laptop, or an NVIDIA DGX Spark.
14+
15+
The agent is interesting not just because it runs locally, but because of *how the work is divided*. A common assumption is that an AI agent is "just the model." In practice, the model is only one stage in a longer pipeline, and most of the surrounding work runs on the CPU.
16+
17+
## The agentic loop
18+
19+
Each time you ask the agent a question, it runs through a chain of steps rather than a single model call:
20+
21+
```text
22+
Your question
23+
-> Decide what to search for (GPU: model reasoning)
24+
-> Expand into several search queries (CPU: orchestration)
25+
-> Run web searches in parallel (CPU: network I/O)
26+
-> Choose which pages to open (GPU: model reasoning)
27+
-> Scrape those pages in parallel (CPU: network I/O)
28+
-> Rank, deduplicate, extract data (CPU: text processing)
29+
-> Write a fact-checked summary (GPU: model reasoning)
30+
```
31+
32+
The model is called several times, but between every model call the CPU does a large amount of orchestration: generating query variants, dispatching parallel network requests, merging and deduplicating results, scoring pages for relevance, and extracting structured data such as phone numbers and opening hours.
33+
34+
## Why the CPU matters in an agentic workflow
35+
36+
It's easy to focus only on token generation, because that's the visible "thinking" part. But in an agent, the CPU is responsible for turning a single user request into useful, structured context for the model:
37+
38+
| Stage | Runs on | Example work |
39+
|---|---|---|
40+
| Reasoning and summarization | GPU | Choosing search terms, selecting URLs, writing the final answer |
41+
| Orchestration | CPU | Expanding queries, scheduling parallel tasks, merging results |
42+
| Web I/O | CPU | Calling the search API, downloading and parsing web pages |
43+
| Text processing | CPU | TF-IDF ranking, deduplication, entity extraction, indexing |
44+
45+
This division is a natural fit for Arm platforms. On an Apple silicon MacBook or an Arm Linux machine, the CPU handles all orchestration and I/O while the GPU accelerates the model. On an NVIDIA DGX Spark, the Arm CPU coordinates the workflow while the GPU runs inference. In every case, the model is only as good as the context the CPU prepares for it.
46+
47+
## How the agent shows you the split
48+
49+
The program is instrumented so you can see this division directly. As it runs, it prints:
50+
51+
- `[CPU]` log lines (in cyan) for every orchestration and processing step
52+
- `[GPU]` log lines (in yellow) for every model call
53+
- A timing breakdown of CPU time versus GPU input-token processing and token generation
54+
- A text-based timeline that visualizes when the CPU and GPU are each active
55+
56+
By the end of this Learning Path, you'll be able to look at a single query and see exactly how much of the work happened on the CPU before and after the model produced its answer.
57+
58+
## What's next
59+
60+
In the next section, you'll set up your environment: create a Python virtual environment, install the required packages, and get a Serper API key for web search.
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
---
2+
title: Set up your environment
3+
weight: 3
4+
5+
### FIXED, DO NOT MODIFY
6+
layout: learningpathall
7+
---
8+
9+
## Set up your environment
10+
11+
In this section, you'll prepare everything the agent needs before running it: a Serper API key for web search, a Python virtual environment, the required packages, and the agent script itself.
12+
13+
These steps are identical on an Apple silicon MacBook, an Arm Linux machine, and an NVIDIA DGX Spark.
14+
15+
## Get a Serper API key
16+
17+
The agent searches the web through [Serper](https://serper.dev/), a Google Search API. The free tier is enough to complete this Learning Path.
18+
19+
1. Go to [serper.dev](https://serper.dev/) and create a free account.
20+
2. Open your dashboard and copy your API key.
21+
22+
You'll set this key as an environment variable later in this section, so the agent can read it without the key being written into the code.
23+
24+
{{% notice Note %}}
25+
Never paste your API key directly into source code that you share or commit. Always read it from an environment variable, as shown below.
26+
{{% /notice %}}
27+
28+
## Create a project directory and virtual environment
29+
30+
A virtual environment keeps the agent's dependencies isolated from your system Python, so you always run against the right package versions.
31+
32+
Create and enter a project directory:
33+
34+
```bash
35+
mkdir concierge-agent
36+
cd concierge-agent
37+
```
38+
39+
Create and activate a virtual environment:
40+
41+
```bash
42+
python3 -m venv .venv
43+
source .venv/bin/activate
44+
```
45+
46+
Your shell prompt now shows `(.venv)`, which confirms the environment is active.
47+
48+
## Install the required packages
49+
50+
The agent uses `requests` for HTTP calls and `beautifulsoup4` to parse web pages. The remaining libraries it uses, such as `smtplib`, `json`, and `concurrent.futures`, are part of the Python standard library.
51+
52+
Install the two packages:
53+
54+
```bash
55+
pip install requests beautifulsoup4
56+
```
57+
58+
## Set your Serper API key
59+
60+
Export your API key as an environment variable in the same terminal session:
61+
62+
```bash
63+
export SERPER_API_KEY="your-serper-api-key"
64+
```
65+
66+
{{% notice Tip %}}
67+
This variable only lasts for the current terminal session. To keep it across sessions, add the same line to your shell profile, for example `~/.zshrc` on macOS or `~/.bashrc` on Linux.
68+
{{% /notice %}}
69+
70+
## Download the agent script
71+
72+
Download the complete agent script, [concierge_agent.py](concierge_agent.py), into your project directory. You'll run it at the end of this Learning Path, and the next sections walk through how the important parts work.
73+
74+
Download it directly from the command line:
75+
76+
```bash
77+
curl -O https://learn.arm.com/learning-paths/cross-platform/ai-agent-cpu-orchestration/concierge_agent.py
78+
```
79+
80+
Confirm the file is in your project directory:
81+
82+
```bash
83+
ls concierge_agent.py
84+
```
85+
86+
{{% notice Tip %}}
87+
You can also save the file using the [concierge_agent.py](concierge_agent.py) link above, then move it into your `concierge-agent` directory.
88+
{{% /notice %}}
89+
90+
With the environment ready and the script in place, the next step is to serve a model locally with Ollama.
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
---
2+
title: Serve a model locally with Ollama
3+
weight: 4
4+
5+
### FIXED, DO NOT MODIFY
6+
layout: learningpathall
7+
---
8+
9+
## Run AI models locally with Ollama
10+
11+
The agent's reasoning steps, such as choosing search terms, selecting URLs, and writing the final summary, are handled by a large language model. Instead of calling a cloud API, this Learning Path serves the model locally with [Ollama](https://ollama.com/).
12+
13+
Ollama is a lightweight runtime that downloads open models, loads them into memory, and exposes a local HTTP API at `http://localhost:11434`. When the agent calls that endpoint, the model runs directly on your machine: the CPU and GPU on your MacBook, Arm Linux laptop, or NVIDIA DGX Spark. Nothing is sent to an external service.
14+
15+
Running locally has three benefits that matter for an agent:
16+
17+
- **Privacy**: your prompts and the web content the agent reads stay on the device.
18+
- **Cost**: there are no per-token API charges, so you can run many queries freely.
19+
- **Control**: you choose the exact model and keep it resident in memory for fast repeated calls.
20+
21+
## Install Ollama
22+
23+
Install Ollama for your operating system.
24+
25+
{{< tabpane code=true >}}
26+
{{< tab header="macOS" language="bash">}}
27+
brew install ollama
28+
{{< /tab >}}
29+
{{< tab header="Linux" language="bash">}}
30+
curl -fsSL https://ollama.com/install.sh | sh
31+
{{< /tab >}}
32+
{{< /tabpane >}}
33+
34+
{{% notice Note %}}
35+
On macOS you can also download the Ollama desktop app from [ollama.com/download](https://ollama.com/download). On an NVIDIA DGX Spark, follow the Linux instructions; Ollama uses the Blackwell GPU for inference automatically.
36+
{{% /notice %}}
37+
38+
## Start the Ollama server
39+
40+
Start the Ollama background service, which hosts the local API the agent connects to:
41+
42+
```bash
43+
ollama serve
44+
```
45+
46+
Leave this running in its own terminal. Open a second terminal for the remaining commands.
47+
48+
{{% notice Tip %}}
49+
On macOS, starting the Ollama desktop app already runs the server in the background, so you can skip `ollama serve`.
50+
{{% /notice %}}
51+
52+
## Pull the Gemma model
53+
54+
This Learning Path uses [Gemma 3](https://ai.google.dev/gemma), Google's family of open models, in its 4-billion-parameter size (`gemma3:4b`). This size is a good default: it's capable enough for the agent's reasoning steps and small enough to run on a laptop.
55+
56+
Download the model:
57+
58+
```bash
59+
ollama pull gemma3:4b
60+
```
61+
62+
Confirm the model is available:
63+
64+
```bash
65+
ollama list
66+
```
67+
68+
You'll see `gemma3:4b` in the list of installed models.
69+
70+
## Choose a different model (optional)
71+
72+
The agent reads the model name from the `OLLAMA_MODEL` environment variable, so you can switch models without editing the code. The default in the script is `gemma3:4b`.
73+
74+
| Model | Size | Best for |
75+
|---|---|---|
76+
| `gemma3:4b` | 4B | Laptops and modest hardware; the default |
77+
| `gemma3:27b` | 27B | High-memory systems such as DGX Spark, for stronger reasoning |
78+
79+
To use a larger model on a DGX Spark, pull it and set the environment variable before running the agent:
80+
81+
```bash
82+
ollama pull gemma3:27b
83+
export OLLAMA_MODEL="gemma3:27b"
84+
```
85+
86+
{{% notice Note %}}
87+
Larger models produce stronger summaries but use more memory and generate tokens more slowly. Start with `gemma3:4b` to confirm everything works, then experiment with larger models if your hardware allows.
88+
{{% /notice %}}
89+
90+
## Test the model
91+
92+
Before wiring it into the agent, confirm the model responds:
93+
94+
```bash
95+
ollama run gemma3:4b
96+
```
97+
98+
Enter a short prompt:
99+
100+
```text
101+
Summarize what a local AI agent does in one sentence.
102+
```
103+
104+
Type `/bye` to exit the model session.
105+
106+
With Ollama serving `gemma3:4b`, you're ready to look at how the agent code uses it.

0 commit comments

Comments
 (0)