Open-Source LLMs for Text Analysis#
This tutorial covers running open-source LLMs on KLC for text analysis research. Open-source models are preferable when your data is sensitive, when you need full reproducibility, or when cost at scale is a concern.
For a broader overview of why and when to use open-source models, see the Open Source LLMs guide.
Using Ollama on KLC#
Ollama provides a simple server/client interface for running open-source LLMs. On KLC, start the server with a shared launcher script.
Start the Server#
After logging onto KLC, start the server in a tmux session (the script runs in the foreground):
/kellogg/software/Modules/modulefiles/klc-main-ollama/bin/start_ollama_server.sh
When the server is ready, the script prints the node hostname and port — use those values for API calls below. For the full ready-banner reference, environment variables, and the GPU (sbatch) path, see Open Source LLMs on KLC.
Connect with Python#
module purge
module load mamba/24.3.0
eval "$('/hpc/software/mamba/24.3.0/bin/conda' 'shell.bash' 'hook' 2> /dev/null)"
source "/hpc/software/mamba/24.3.0/etc/profile.d/mamba.sh"
mamba create --prefix=./env python=3.13
mamba activate ./env
python -m pip install ollama
from ollama import Client
HOST = "localhost" # same node as the server
PORT = 8234 # from the ready banner
client = Client(host=f"http://{HOST}:{PORT}")
Browse additional models at ollama.com/search .
Running a Prompt#
import logging
from ollama import Client
logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
logger = logging.getLogger(__name__)
def ensure_model_available(client, model):
available = {m.model for m in client.list().models}
normalized = model if ":" in model else f"{model}:latest"
if model in available or normalized in available:
logger.info("Model already available: %s", model)
return
logger.info("Model not found locally: %s — pulling ...", model)
last_status = None
for progress in client.pull(model, stream=True):
if progress.status != last_status:
logger.info("pull %s: %s", model, progress.status)
last_status = progress.status
logger.info("Model pulled: %s", model)
HOST = "localhost" # same node as the server
PORT = 8234 # from the ready banner
client = Client(host=f"http://{HOST}:{PORT}")
ensure_model_available(client, "llama3.2")
response = client.chat(
model="llama3.2",
messages=[
{"role": "system", "content": "You are a helpful research assistant."},
{"role": "user", "content": "Summarize the key risks in this 10-K excerpt: ..."},
],
options={"temperature": 0, "seed": 42},
)
print(response["message"]["content"])
Reproducibility Settings#
Open-source models give you full control over reproducibility:
Setting |
What It Does |
|---|---|
|
Deterministic output |
|
Fixes random state (where supported) |
Model version pinning |
Use |
Always record the model name and tag in your logs. Unlike API providers, you can ensure the exact same model weights are used across runs.
For the broader cost, privacy, and performance comparison between open-source and paid APIs, see Open Source LLMs.
Example: Batch Classification#
from ollama import Client
HOST = "localhost" # same node as the server
PORT = 8234 # from the ready banner
client = Client(host=f"http://{HOST}:{PORT}")
def classify_text(text: str, model: str = "llama3.2") -> str:
response = client.chat(
model=model,
messages=[
{
"role": "system",
"content": (
"Classify the sentiment of the following text as one of "
"[Positive, Negative, Neutral]. Return only the label."
),
},
{"role": "user", "content": text},
],
options={"temperature": 0, "seed": 42},
)
return response["message"]["content"].strip()
# Batch process a list of documents
documents = ["Revenue exceeded expectations.", "Significant litigation risk.", "Operations were stable."]
results = [(doc, classify_text(doc)) for doc in documents]
for doc, label in results:
print(f"{label:10} | {doc}")
Using Quest OnDemand#
An alternative to the command line: open the Quest OnDemand Jupyter interactive app and select “ollama” as the pre-installed kernel. This automatically starts the Ollama server alongside JupyterHub.
Next Steps#
Tutorial 5: Validation and Rigor — ensuring your results meet academic standards
Open Source LLMs Guide — broader guide including workshop materials
Launching Jobs on KLC — running batch jobs at scale