---
title: "Guida Ollama e SDK OpenAI: Configurazione Local-First e Contratti Stateless"
date: "2026-05-30"
category: "Intelligenza Artificiale"
tags: ["llm", "local-first", "ollama", "openai-sdk", "python"]
author: "Giuseppe Carruezzo"
description: "Configura un LLM locale con Ollama e SDK OpenAI. Guida pratica al contratto stateless, gestione della memoria su Mac e ottimizzazione dei prompt tokens."
source: "https://ainsights.it/blog/guida-ollama-sdk-openai-local-first"
---

# Guida Ollama e SDK OpenAI: Configurazione Local-First e Contratti Stateless

![Guida Ollama e SDK OpenAI: Configurazione Local-First e Contratti Stateless](/blogai/backend/uploads/6a1b3132c0de4.webp)

Questa guida pratica ed eseguibile accompagna il primo post della [serie Portway](https://github.com/dalenguyen/portway). L'obiettivo: configurare un singolo modello dietro un endpoint compatibile con OpenAI sul proprio hardware, chiamarlo tramite l'SDK ufficiale OpenAI e interiorizzare il contratto stateless (senza stato). Tutto funziona localmente, a costo zero.

## Cosa copre questo articolo

-   Uno script `demo.py` con due blocchi:
    1.  **Round-trip** — una chiamata chat tramite SDK OpenAI, con stampa del contenuto e dell'oggetto `usage`.
    2.  **Prova stateless** — la stessa domanda finale inviata come messaggio a 1 turno e come ultimo turno di una cronologia fabbricata a 5 turni; entrambi i valori `prompt_tokens` vengono stampati insieme a una spiegazione del delta.

## Scelta del motore su questa macchina

Mac con Apple Silicon, 48 GB di memoria unificata, **Ollama** già installato. Il demo utilizza l'endpoint compatibile con OpenAI di Ollama all'indirizzo `http://localhost:11434/v1` e il modello `gpt-oss:20b` (~14 GB).

La serie Portway più ampia utilizza `llama.cpp` su Mac (Ollama viene segnalato come problematico per Qwen3.5 nel Post 2). Per il Post 1 — un modello, dimostrare il contratto — Ollama funziona bene ed è già presente sulla macchina.

## Opzioni di modello per RAM disponibile

Lo script demo funziona con qualsiasi modello servito da Ollama — basta sostituire il nome del modello in `demo.py`. La tabella seguente copre macchine con memoria unificata a partire da 9 GB.

| Modello | Comando di pull | Dimensione approssimativa | RAM minima | Note |
| --- | --- | --- | --- | --- |
| `llama3.2:3b` | `ollama pull llama3.2:3b` | ~2 GB | 8 GB | Più veloce; ideale per testare il contratto |
| `gemma3:4b` | `ollama pull gemma3:4b` | ~3 GB | 8 GB | Di Google; solida nell'esecuzione di istruzioni |
| `mistral:7b` | `ollama pull mistral:7b` | ~4,1 GB | 8 GB | Classico baseline a 7B |
| `llama3.1:8b` | `ollama pull llama3.1:8b` | ~4,7 GB | 9 GB | Migliore qualità sotto i 10 GB |
| `qwen2.5:7b` | `ollama pull qwen2.5:7b` | ~4,4 GB | 9 GB | Ottimo per istruzioni e ragionamento |
| `gpt-oss:20b` | `ollama pull gpt-oss:20b` | ~14 GB | 24 GB | Utilizzato nell'output di esempio di questo post |

Su una macchina con 9 GB, sostituire `gpt-oss:20b` in `demo.py` con `llama3.1:8b` o `qwen2.5:7b` — la dimostrazione del contratto è identica.

## Prerequisiti

-   [Ollama](https://ollama.com) in esecuzione locale (`curl -s http://localhost:11434/api/tags` deve restituire JSON)
-   [uv](https://docs.astral.sh/uv/) installato (`uv --version`)
-   Il modello scaricato. Questo post usa `gpt-oss:20b` (richiede ~24 GB di RAM); vedi [Opzioni di modello per RAM disponibile](#opzioni-di-modello-per-ram-disponibile) per alternative più leggere su macchine con 9 GB+.

```shell
ollama pull llama3.2:3b
```

## Esecuzione

Dalla root del repository:  

```shell
uv sync                                  # crea .venv alla root, installa dipendenze
uv run --project 1-local-first python 1-local-first/demo.py
```

## Output di esempio

Un'esecuzione reale su questa macchina (Mac classe M4, 48 GB, `gpt-oss:20b` tramite Ollama). I numeri differiranno con modelli più piccoli — `prompt_tokens` per lo stesso input rimane deterministico indipendentemente dal modello:  

```plaintext
============================================================
Block 1 — round-trip tramite SDK OpenAI contro localhost
============================================================
content: Toronto, Vancouver, Montreal.
usage:   CompletionUsage(completion_tokens=43, prompt_tokens=72, total_tokens=115, ...)

============================================================
Block 2 — stessa domanda finale, 1-turn vs cronologia a 5 turni
============================================================
1-turn response: La capitale del Canada è **Ottawa**.
5-turn response: La capitale del Canada è **Ottawa**, situata nella provincia di Ontario.

1-turn prompt_tokens: 75
5-turn prompt_tokens: 139
delta:                64

Perché esiste il delta: il server NON ha stato conversazionale tra
le richieste. I prompt_tokens della chiamata a 5 turni sono superiori
solo perché il client ha ri-inviato la cronologia completa nel body
della richiesta. Ogni chiamata viene valutata da zero — la cronologia
è responsabilità del client.
```

`completion_tokens` e il testo della risposta variano da un'esecuzione all'altra (il campionamento è non-deterministico con temperatura predefinita). `prompt_tokens` per lo stesso input è deterministico — 75 e 139 dovrebbero riprodursi.

Notare come la risposta a 5 turni recepisca il contesto del viaggio su strada ("situata nella provincia di Ontario") mentre la risposta a 1 turno rielabora il semplice "Driving." nel suo prompt — stesso modello, inquadratura diversa nei messaggi forniti dal client.

![Cover image for Local-first: a Model on Your Own Machine, Zero Cloud](/blogai/backend/uploads/6a1b313318ddf.webp)

Copertina dell'articolo su Local-first: un modello sulla propria macchina, zero cloud

## Il contratto stateless spiegato

Questo è il concetto più importante della serie. Ogni richiesta a un'API LLM — locale o cloud — viene valutata da zero. Il server non ha memoria dei turni precedenti. Quando invii una conversazione multi-turno, **tu** sei quello che ri-invia la cronologia completa nel body della richiesta. Il modello vede tutto in una volta.

L'unica "memoria" del server tra le richieste è la **prefix cache** (un'optimizzazione computazionale che evita di rivalutare i token già visti), mai lo stato conversazionale. La cache è invisibile — dal punto di vista del contratto API, ogni chiamata è stateless.

Comprendere questo è il fondamento per tutto ciò che segue nella serie:

-   Perché la gestione delle conversazioni appartiene al client, non al server
-   Perché le finestre di contesto contano per costo e latenza
-   Perché lo streaming di `usage` richiede un'opt-in esplicita (`stream_options.include_usage`)

## Definizione di completato

-   Round-trip SDK OpenAI contro `localhost` — il Blocco 1 stampa un `content` reale e un oggetto `usage`.
-   Sa spiegare perché 5 turni vs 1 turno cambiano `prompt_tokens` mentre il server non ricorda nulla — il Blocco 2 stampa entrambi i numeri e la spiegazione di un paragrafo.

## Cose da notare ora

**La dimensione del contesto consuma RAM/VRAM.** La finestra di contesto predefinita di Ollama è conservativa per la maggior parte dei modelli; aumentarla (es. `ollama run llama3.2:3b` → `/set parameter num_ctx 32768`) costa memoria unificata. Non è stata modificata per questo post.

**gpt-oss emette un canale di ragionamento** (formato Harmony). Il motore applica il template; ottieni comunque un normale `message.content`. Il canale di ragionamento sarà segregato al gateway nel Post 3.

**Nessuno streaming ancora.** Il Post 5 copre la trappola dello streaming `usage` — devi optare tramite `stream_options.include_usage`, altrimenti `usage` è `null` nelle risposte in streaming.

## Cosa viene dopo

Il Post 2 passa da un singolo modello all'esecuzione simultanea di più modelli e al routing delle richieste tra di essi — il primo passo verso un gateway locale reale.

La serie completa e tutto il codice demo si trovano nel [repository Portway](https://github.com/dalenguyen/portway).

### Local-first con Ollama — 4.5/5

Guida pratica ed essenziale per chi vuole sperimentare con LLM locali usando l SDK OpenAI. Il contratto stateless è spiegato chiaramente attraverso l output reale. Ideale come punto di partenza per costruire un infrastruttura AI completamente locale.

## FAQ

### Posso usare questa guida su un PC Windows o Linux?

Sì, Ollama è disponibile anche per Windows e Linux. I comandi e lo script demo funzionano identicamente su tutti i sistemi operativi.

### Quale modello scegliere per iniziare con 8 GB di RAM?

Consigliamo llama3.2:3b (2 GB) o mistral:7b (4,1 GB). Entrambi funzionano su 8 GB e permettono di testare il contratto stateless senza problemi.

### Perché i prompt\_tokens sono deterministici?

Perché il server valuta ogni richiesta da zero senza stato conversazionale. Se invii gli stessi messaggi, il numero di token di input sarà sempre identico.

### Cosa succede se aumento la finestra di contesto?

Aumentare il contesto (es. num\_ctx 32768) consuma più RAM/VRAM. Consigliato solo se hai memoria sufficiente e necessiti di conversazioni più lunghe.

### Posso usare modelli diversi da quelli elencati?

Sì, qualsiasi modello supportato da Ollama funziona. Devi solo sostituire il nome del modello in demo.py e assicurarti di avere RAM sufficiente.

## Fonti e riferimenti

1.  [Repository Portway su GitHub](https://github.com/dalenguyen/portway)
2.  [Sito ufficiale Ollama](https://ollama.com)
3.  [Documentazione uv](https://docs.astral.sh/uv/)

---

*Fonte: [https://ainsights.it/blog/guida-ollama-sdk-openai-local-first](https://ainsights.it/blog/guida-ollama-sdk-openai-local-first)*
