Vai al contenuto principale

Come installare ed eseguire GPT-OSS in locale con Ollama

Scopri come installare, configurare ed eseguire GPT-OSS in locale con Ollama e creare una semplice applicazione Streamlit.
¡ 12 min leggi

Scopri con l'IA

GPT-OSS è la prima serie di modelli open‑weight di OpenAI e puoi eseguirla direttamente sul tuo computer. Progettato per un ragionamento potente, compiti agentici e casi d’uso flessibili per sviluppatori, GPT-OSS si distingue per lo sforzo di ragionamento configurabile e le capacità trasparenti di chain-of-thought.

In questo tutorial ti guiderò nella configurazione locale dei modelli GPT-OSS di OpenAI usando Ollama e ti mostrerò come creare una demo interattiva che metta in risalto le capacità uniche di ragionamento del modello. Esploreremo le funzionalità configurabili di chain-of-thought del modello e costruiremo un’app Streamlit che visualizza il processo di pensiero del modello.

Teniamo i nostri lettori aggiornati sulle ultime novità dell’AI con The Median, la nostra newsletter gratuita del venerdì che riassume le notizie chiave della settimana. Iscriviti e resta informato in pochi minuti a settimana:

Cos’è GPT-OSS di OpenAI?

La serie GPT-OSS di OpenAI segna la loro prima release open‑weight dai tempi di GPT-2, offrendo accesso a modelli di ragionamento ad alte prestazioni sotto licenza Apache 2.0. Questi modelli linguistici all’avanguardia offrono prestazioni elevate a basso costo e superano modelli open di dimensioni simili nei compiti di ragionamento.

Esistono due varianti: gpt-oss-120b e gpt-oss-20b.

Varianti GPT OSS

Fonte: OpenAI

gpt-oss-120b

gpt-oss-120b è il modello open‑weight di punta di OpenAI, con prestazioni in grado di rivaleggiare con sistemi proprietari come o4‑mini su benchmark di ragionamento impegnativi. Nonostante le sue 117 miliardi di parametri, è ottimizzato per l’esecuzione su una singola GPU da 80 GB. Questo lo rende un’opzione realistica per laboratori di ricerca e team enterprise che vogliono ospitare localmente modelli linguistici potenti.

Il modello è progettato per supportare workflow complessi come l’uso di tool, il ragionamento multi-step e un controllo fine su quanto “sforzo di pensiero” dedicare a ciascun compito. La natura open‑weight e la licenza Apache 2.0 lo rendono una scelta flessibile per i team che vogliono ispezionare a fondo, personalizzare o effettuare fine‑tuning del modello.

gpt-oss-20b

gpt-oss-20b concentra una notevole forza di ragionamento in un ingombro che entra nei laptop consumer. Con soli 21 miliardi di parametri totali, supera comunque o3-mini di OpenAI in alcuni benchmark e gira in modo efficiente su dispositivi con 16 GB di memoria. È quantizzato e pronto per un deployment locale rapido, ed è compatibile con strumenti come Ollama, vLLM e persino con la piattaforma Metal di Apple.

Questo modello è ideale per gli sviluppatori che vogliono creare app di AI reattive e private senza dipendere dall’infrastruttura cloud. Come il fratello maggiore, supporta una profondità di ragionamento regolabile e passaggi intermedi chiari—perfetto per esperimenti, assistenti leggeri e applicazioni su edge.

PerchĂŠ eseguire GPT-OSS in locale?

Eseguire GPT-OSS in locale offre diversi vantaggi convincenti rispetto alle alternative cloud:

  • Privacy e controllo: Tutta l’inferenza avviene sull’hardware locale, cioè nessuna dipendenza esterna, interruzioni o cambiamenti di API, e hai accesso completo al ragionamento interno del modello, non solo alle risposte finali.
  • Prestazioni: I modelli locali eliminano la latenza di rete per risposte istantanee, con uso illimitato (niente rate limit o limiti di token) e garantiscono disponibilitĂ  24/7.
  • Risparmio sui costi: Il modello richiede un download e una configurazione una tantum senza abbonamenti, e puoi usare le risorse di calcolo esistenti senza costi API ricorrenti.
  • Ragionamento trasparente: Puoi passare tra modalitĂ  di “sforzo” basso, medio e alto per bilanciare velocitĂ  e profonditĂ , e ispezionare l’intera chain-of-thought.
  • Personalizzazione ed estendibilitĂ : Possiamo effettuare fine‑tuning dei modelli open‑weight per i nostri task specifici, modificare i parametri di sampling e integrare strumenti agentici senza attriti.

Configurare GPT-OSS in locale con Ollama

Ollama rende sorprendentemente semplice eseguire in locale grandi modelli linguistici gestendo download, quantizzazione ed esecuzione. Ti guiderò passo per passo nella configurazione di GPT-OSS sul tuo sistema. Alla fine, la nostra app apparirà cosÏ:

App Streamlit alimentata da gpt-oss e ollama

Step 1: Installa Ollama

Per prima cosa, scarica e installa Ollama dal sito ufficiale.

Scarica ollama

Una volta installato, puoi verificare l’installazione aprendo un terminale e digitando:

ollama --version

Questo restituirĂ  la versione piĂš recente di Ollama installata sul tuo sistema.

Step 2: Scarica i modelli GPT-OSS

OpenAI fornisce due varianti di GPT-OSS ottimizzate per diversi casi d’uso, ma per questa demo scaricheremo solo la variante del modello gpt-oss-20b:

# Per produzione e compiti di ragionamento avanzati 
ollama pull gpt-oss:120b
# Per bassa latenza e deployment locale 
ollama pull gpt-oss:20b

Il modello 20B è perfetto per lo sviluppo locale e può girare su sistemi con 16 GB+ di memoria, mentre il 120B offre più capacità ma richiede 80 GB+ di memoria.

Step 3: Testa l’installazione

Verifichiamo che funzioni tutto correttamente:

ollama run gpt-oss:20b

Dovresti vedere un prompt con cui interagire direttamente con il modello. Prova a chiedere: "Dimostra che √2 è irrazionale."

Usare GPT-OSS in locale: ChatBot interattivo

Ora costruiamo rapidamente una semplice app che metta in mostra le capacitĂ  di ragionamento di GPT-OSS. La nostra applicazione includerĂ :

  • Controlli interattivi del ragionamento
  • Visualizzazione della chain-of-thought
  • Monitoraggio delle prestazioni
  • Storico della conversazione

Step 1: Installa le dipendenze

Esegui i seguenti comandi per installare le dipendenze necessarie:

pip install streamlit ollama

Il codice qui sopra installa Streamlit per costruire l’interfaccia web e il client Python di Ollama per interagire in locale con il modello GPT-OSS.

Step 2: Importa le librerie e imposta la pagina

Prima di entrare nella logica core della chat, importiamo gli strumenti e predisponiamo l’interfaccia utente.

import streamlit as st
import json
import ollama
import time
from typing import Dict, Any, List
import re
from datetime import datetime

# Configure page
st.set_page_config(
    page_title="GPT-OSS Chat Demo", 
    layout="wide",
    page_icon="💬"
)
# Custom CSS for UI
st.markdown("""
<style>
.reasoning-box {
    background-
    
    
    border-radius: 10px;
    border-left: 4px solid #00d4aa;
    
}
.answer-box {
    background-
    
    border-radius: 10px;
    border-left: 4px solid #007bff;
    
}
.metric-card {
    background-
    
    border-radius: 10px;
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    text-align: center;
    
}
.chat-message {
    
    
    border-radius: 10px;
}
.user-message {
    background-
    border-left: 4px solid #2196f3;
}
.assistant-message {
    background-
    border-left: 4px solid #9c27b0;
}
</style>
""", unsafe_allow_html=True)

Importiamo alcuni pacchetti fondamentali come Streamlit per l’interfaccia web, Ollama per chiamare il modello GPT-OSS locale, insieme a moduli utili come json, time, typing e re. Poi usiamo st.set_page_config() per impostare titolo, layout ampio e icona della pagina, e iniettiamo un po’ di CSS leggero in modo che i passaggi di ragionamento e le risposte compaiano in pannelli distinti.

Step 3: Integrazione core del modello

Con l’impalcatura UI pronta, costruiamo la nostra funzione di integrazione principale del modello call_model():

def call_model(messages: List[Dict], model_name: str = "gpt-oss:20b", temperature: float = 1.0) -> Dict[str, Any]:
    try:
        start_time = time.time()        
        # Prepare options for Ollama
        options = {
            'temperature': temperature,
            'top_p': 1.0,
        }        
        response = ollama.chat(
            model=model_name, 
            messages=messages,
            options=options
        )
        end_time = time.time()        
        if isinstance(response, dict) and 'message' in response:
            content = response['message'].get('content', '')
        elif hasattr(response, 'message'):
            content = getattr(response.message, 'content', '')
        else:
            content = str(response)         
        return {
            'content': content, 
            'response_time': end_time - start_time, 
            'success': True
        }
    except Exception as e:
        return {
            'content': f"Error: {e}", 
            'response_time': 0, 
            'success': False
        }

Il codice sopra:

  • Accetta un elenco di messaggi di chat (system + user), cosĂŹ possiamo mantenere facilmente il contesto multi‑turn.
  • Registra start_time e end_time intorno alla chiamata ollama.chat() per riportare all’utente i tempi di risposta.
  • Normalizza le risposte del client Ollama estraendo l’output testuale grezzo.
  • Infine, la funzione call_model() avvolge l’intera chiamata in un blocco try/except per intercettare gli errori.

Step 4: Parser della chain-of-thought

Per rendere davvero trasparente la nostra demo, dobbiamo separare il “monologo interiore” del modello dal suo verdetto finale. La funzione parse_reasoning_response() fa esattamente questo:

def parse_reasoning_response(content: str) -> Dict[str, str]:
    patterns = [
        r"<thinking>(.*?)</thinking>",
        r"Let me think.*?:(.*?)(?=\n\n|\nFinal|Answer:)",
        r"Reasoning:(.*?)(?=\n\n|\nAnswer:|\nConclusion:)",
    ]
    reasoning = ""
    answer = content    
    for pat in patterns:
        m = re.search(pat, content, re.DOTALL | re.IGNORECASE)
        if m:
            reasoning = m.group(1).strip()
            answer = content.replace(m.group(0), "").strip()
            break    
    if not reasoning and len(content.split('\n')) > 3:
        lines = content.split('\n')
        for i, l in enumerate(lines):
            if any(k in l.lower() for k in ['therefore', 'in conclusion', 'final answer', 'answer:']):
                reasoning = '\n'.join(lines[:i]).strip()
                answer = '\n'.join(lines[i:]).strip()
                break
    return {
        'reasoning': reasoning or "No explicit reasoning detected.", 
        'answer': answer or content
    }

Separiamo il “pensiero” nascosto del modello dal suo verdetto finale, così gli utenti possono opzionalmente ispezionare ogni passaggio di ragionamento. Ecco come viene analizzata la risposta:

  • Ricerca di marcatori espliciti: per prima cosa, il modello cerca tag <thinking>…</thinking> o frasi come “Reasoning:” e “Let me think through” con espressioni regolari.
  • Estrazione e pulizia: quando trova una corrispondenza, quel segmento diventa il ragionamento e il resto è trattato come risposta.
  • Fallback euristico: se non ci sono tag ma l’output è su piĂš righe, cerca parole chiave di conclusione (“therefore”, “in conclusion”, “final answer” o “Answer:”) e divide lĂŹ.
  • Output: a prescindere dal formato, la funzione parse_reasoning_response() restituisce sempre una risposta.

Step 5: Applicazione Streamlit completa

Ora che abbiamo costruito tutti i componenti, li assembliamo in un’app di chat interattiva. 

# Initialize history
if 'history' not in st.session_state:
    st.session_state.history = []
# Sidebar for settings
with st.sidebar:
    st.header("Configuration")    
    model_choice = st.selectbox(
        "Model", 
        ["gpt-oss:20b", "gpt-oss:120b"],
        help="Choose between 20B (faster) or 120B (more capable)"
    )    
    effort = st.selectbox(
        "Reasoning Effort", 
        ["low", "medium", "high"], 
        index=1,
        help="Controls depth of reasoning shown"
    )    
    temperature = st.slider(
        "Temperature", 
        0.0, 2.0, 1.0, 0.1,
        help="Controls response randomness"
    )    
    show_reasoning = st.checkbox(
        "Show Chain-of-Thought", 
        True,
        help="Display model's thinking process"
    )    
    show_metrics = st.checkbox(
        "Show Performance Metrics",
        True,
        help="Display response time and model info"
    )    
    st.markdown("---")        
    if st.button("Clear Conversation"):
        st.session_state.history = []
        st.rerun()  
# Main Chat Interface
st.title("💬 GPT-OSS Interactive Chat")
examples = [
    "",
    "If a train travels 120km in 1.5 hours, then 80km in 45 minutes, what's its average speed?",
    "Prove that √2 is irrational.",
    "Write a function to find the longest palindromic substring.",
    "Explain quantum entanglement in simple terms.",
    "How would you design a recommendation system?",
]
selected_from_dropdown = st.selectbox("Choose from examples:", examples)
# Get the question text
question_value = ""
if hasattr(st.session_state, 'selected_example'):
    question_value = st.session_state.selected_example
    del st.session_state.selected_example
elif selected_from_dropdown:
    question_value = selected_from_dropdown
question = st.text_area(
    "Or Enter your question:", 
    value=question_value, 
    height=100,
    placeholder="Ask anything! Try different reasoning effort levels to see how the model's thinking changes..."
)
# Submit button
col1, col2 = st.columns([1, 4])
with col1:
    submit_button = st.button("Ask GPT-OSS", type="primary")
if submit_button and question.strip():
    # System prompts 
    system_prompts = {
        'low': 'You are a helpful assistant. Provide concise, direct answers.',
        'medium': f'You are a helpful assistant. Show brief reasoning before your answer. Reasoning effort: {effort}',
        'high': f'You are a helpful assistant. Show complete chain-of-thought reasoning step by step. Think through the problem carefully before providing your final answer. Reasoning effort: {effort}'
    }    
    # Message history
    msgs = [{'role': 'system', 'content': system_prompts[effort]}]    
    msgs.extend(st.session_state.history[-6:])
    msgs.append({'role': 'user', 'content': question})    
    with st.spinner(f"GPT-OSS thinking ({effort} effort)..."):
        res = call_model(msgs, model_choice, temperature)
    if res['success']:
        parsed = parse_reasoning_response(res['content'])        
        st.session_state.history.append({'role': 'user', 'content': question})
        st.session_state.history.append({'role': 'assistant', 'content': res['content']})        
        col1, col2 = st.columns([3, 1] if show_metrics else [1])        
        with col1:
            if show_reasoning and parsed['reasoning'] != 'No explicit reasoning detected.':
                st.markdown("### Chain-of-Thought Reasoning")
                st.markdown(f"<div class='reasoning-box'>{parsed['reasoning']}</div>", unsafe_allow_html=True)            
            st.markdown("### Answer")
            st.markdown(f"<div class='answer-box'>{parsed['answer']}</div>", unsafe_allow_html=True)       
        if show_metrics:
            with col2:
                st.markdown(f"""
                <div class="metric-card">
                    <h4> Metrics</h4>
                    <p><strong>Time:</strong><br>{res['response_time']:.2f}s</p>
                    <p><strong>Model:</strong><br>{model_choice}</p>
                    <p><strong>Effort:</strong><br>{effort.title()}</p>
                </div>
                """, unsafe_allow_html=True)
    else:
        st.error(f"{res['content']}")
if st.session_state.history:
    st.markdown("---")
    st.subheader("Conversation History")    
    recent_history = st.session_state.history[-8:]  # Last 8 messages (4 exchanges)    
    for i, msg in enumerate(recent_history):
        if msg['role'] == 'user':
            st.markdown(f"""
            <div class="chat-message user-message">
                <strong>You:</strong> {msg['content']}
            </div>
            """, unsafe_allow_html=True)
        else:
            parsed_hist = parse_reasoning_response(msg['content'])
            with st.expander(f"GPT-OSS Response", expanded=False):
                if parsed_hist['reasoning'] != 'No explicit reasoning detected.':
                    st.markdown("**Reasoning Process:**")
                    st.code(parsed_hist['reasoning'], language='text')
                st.markdown("**Final Answer:**")
                st.markdown(parsed_hist['answer'])
# Footer
st.markdown("---")
st.markdown("""
<div style='text-align: center;'>
    <p><strong>Powered by GPT-OSS-20B via Ollama</strong></p>
</div>
""", unsafe_allow_html=True)

In questo passaggio finale mettiamo insieme tutti i pezzi della nostra app, inclusi stato di sessione, controlli nella sidebar, prompt di esempio, composizione dei messaggi, chiamata al modello, parsing e visualizzazione in un unico flusso:

  1. Inizializzazione dello stato di sessione: usiamo st.session_state.history per ricordare ogni scambio utente–assistant tra i vari rerun.
  2. Configurazione della sidebar: questa configurazione consente agli utenti di selezionare
    • Model: gpt-oss:20b o gpt-oss:120b
    • Reasoning Effort: low/medium/high
    • Temperature: da 0 a 2.0, che controlla la casualitĂ  del modello
    • Interruttore Chain-of-Thought: per mostrare o nascondere il ragionamento interno del modello
    • Cancella conversazione: azzera la cronologia e riavvia l’app
  3. Prompt di esempio e input: un menu a tendina con domande iniziali aiuta a far partire i nuovi utenti, e ciò che l’utente seleziona (o digita) diventa la query nell’area di testo.
  4. Costruzione della richiesta: quando si clicca Ask GPT-OSS, noi:
    • Creiamo un system prompt in base al livello di sforzo scelto.
    • Appendiamo gli ultimi sei messaggi dalla cronologia per mantenere il contesto.
    • Aggiungiamo la nuova domanda dell’utente.
  5. Invocazione del modello: usiamo la funzione call_model(), che:
    • Invia i messaggi assemblati a Ollama
    • Misura il tempo di risposta
    • Restituisce una stringa di contenuto normalizzata
  6. Parsing e visualizzazione: con la funzione parse_reasoning_response() dividiamo l’output del modello in una risposta di chain‑of‑thought chiamata “reasoning” e una risposta ripulita chiamata “answer”.
  7. Gestione della cronologia: ogni coppia domanda‑risposta viene aggiunta all’elenco st.session_state.history, così l’esecuzione successiva li include per il contesto.

Per provarlo tu stesso, salva il codice come gpt_oss_demo.py e avvia:

streamlit run gpt_oss_demo.py

Conclusione

GPT-OSS di OpenAI è uno dei migliori modelli open‑weight che puoi eseguire oggi. Combinando il deployment semplificato di Ollama con le capacità interattive di Streamlit, abbiamo creato una piattaforma che mostra:

  • ProfonditĂ  di ragionamento configurabile
  • Controllo locale completo
  • Pensiero trasparente

GPT-OSS, insieme a strumenti come Ollama, rende accessibili capacitĂ  avanzate di AI a sviluppatori, ricercatori e organizzazioni che danno prioritĂ  a privacy, controllo e comprensione.

Argomenti

Correlato