Design wechseln

LangChain + Ollama Integration: Vollständiger Leitfaden für lokale LLM-Apps

Letzten Monat habe ich mir die OpenAI-Rechnung angesehen: 52,3 $. Ehrlich gesagt war ich etwas schockiert – als Einzelentwickler, der gelegentlich mit KI spielt, so viel auszugeben. Dann fiel mir ein, dass Ollama lokal läuft – kostenloses Llama 3.1, bereit zum Einsatz.

Aber es gibt ein Problem: Direkt die Ollama-API in einer App zu nutzen, bedeutet viel Boilerplate. Request-Format, Response-Parsing, Fehlerbehandlung – bei jedem Projekt wieder von vorn. Hier kommt LangChain ins Spiel: fertige Abstraktionen für Chat, RAG und Agent – und Modelle per Zeile Code wechselbar.

Dieser Artikel ist der Framework-Integrations-Teil der Ollama Local LLM-Serie. Von langchain-ollama geht es zu Chat, RAG und Agent in der Praxis. Wer die vorherigen Teile (API-Aufruf, Multi-Modell-Deployment) kennt, findet hier das zusammenhängende Entwicklungsgerüst.

langchain-ollama: Einstieg

Zuerst ein Stolperstein, den ich selbst erlebt habe. Früher nutzte ich langchain_community.llms.Ollama – lief, fühlte sich aber falsch an. In der Doku stand überall „langchain-ollama“. LangChain hat die Ollama-Integration in ein eigenes Paket ausgelagert: langchain-ollama.

Warum das offizielle Paket?

Bessere Type Hints, IDE-Autovervollständigung. Wartung synchron zur LangChain-Hauptversion – weniger Kompatibilitätsprobleme. Community-Pakete können deprecated werden; das offizielle Paket ist die Langfrist-Option – das habe ich schmerzhaft gelernt.

Installation in einer Zeile:

pip install langchain-ollama

Das Paket liefert drei Kernklassen für unterschiedliche Szenarien:

KlasseZweckTypische Anwendung
ChatOllamaDialogmodellMehrturn-Chat, Q&A
OllamaLLMText-VervollständigungEinmal-Generierung, Fortsetzung
OllamaEmbeddingsVektor-EmbeddingsRAG, semantische Suche

In der Praxis reicht ChatOllama in 90 % der Fälle. Mehrturn-Dialog und Streaming – Zeichen für Zeichen statt eines Blocktexts – verbessern die UX deutlich.

Minimales Beispiel:

from langchain_ollama import ChatOllama

# Modell initialisieren
llm = ChatOllama(
    model="llama3.1:8b",  # Modellname – vorher mit Ollama pullen
    temperature=0.7       # Zufälligkeit, 0–1
)

# Nachricht senden
response = llm.invoke("Hallo, stell dich kurz vor")
print(response.content)

Vor dem Start: ollama pull llama3.1:8b. Ollama noch nicht installiert? Siehe den Einstiegsartikel der Serie.

OllamaEmbeddings wandelt Text in Vektoren um – ausführlich im RAG-Abschnitt. Kurzbeispiel:

from langchain_ollama import OllamaEmbeddings

embeddings = OllamaEmbeddings(model="nomic-embed-text")

# Einzeltext einbetten
vector = embeddings.embed_query("Dies ist ein Testtext")
print(f"Vektordimension: {len(vector)}")  # meist 768 oder mehr

# Batch-Einbettung
vectors = embeddings.embed_documents([
    "Erster Text",
    "Zweiter Text"
])

nomic-embed-text ist ein gängiges Embedding-Modell für semantische Suche. Hohe Dimension (meist 768+), bessere Retrieval-Qualität als generische Modelle.

Chat in der Praxis: Mehrturn-Dialog und Streaming

Ein einzelner API-Aufruf ist trivial – echte Chats brauchen Kontext über mehrere Runden. LangChain modelliert das mit Nachrichtenlisten.

Mehrturn-Dialog

Drei Nachrichtentypen:

  • SystemMessage: Rolle und Verhalten (z. B. „Du bist ein Entwickler-Assistent“)
  • HumanMessage: Nutzereingabe
  • AIMessage: Modellantwort

Code:

from langchain_ollama import ChatOllama
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage

llm = ChatOllama(model="llama3.1:8b", temperature=0.7)

# Dialogverlauf
messages = [
    SystemMessage(content="Du bist ein Entwickler-Assistent, der technische Konzepte klar erklärt."),
    HumanMessage(content="Was ist eine REST-API?"),
    AIMessage(content="Eine REST-API ist ein Architekturstil für Webservices mit HTTP-Methoden (GET/POST/PUT/DELETE) auf Ressourcen. Kurz: Daten über URLs ansprechen."),
    HumanMessage(content="Worin unterscheidet sich GraphQL davon?")
]

# Antwort basiert auf dem gesamten Verlauf
response = llm.invoke(messages)
print(response.content)

Das Modell sieht die vorherige Antwort und erkennt die Nachfrage zu GraphQL vs. REST. Ohne AIMessage würde es GraphQL von Grund auf erklären – der Faden reißt.

Streaming: Antworten wirken lebendig

Streaming vermeidet leere Wartezeit – Text erscheint Wort für Wort. Besonders bei langen Antworten wichtig.

from langchain_ollama import ChatOllama

llm = ChatOllama(model="llama3.1:8b")

# Streaming
print("Modellantwort: ", end="", flush=True)
for chunk in llm.stream("Schreibe Quicksort in Python und erkläre das Prinzip"):
    print(chunk.content, end="", flush=True)
print()  # Zeilenumbruch

stream() liefert einen Iterator; jeder Chunk ist ein Textstück. flush=True zeigt sofort an, ohne Puffer.

In Tests fühlt sich Streaming deutlich reaktiver an – ab ca. 100 Zeichen wirkt das System aktiv statt hängend.

RAG in der Praxis: Lokale Wissensbasis

RAG (Retrieval-Augmented Generation) ist einer der praktischsten LLM-Anwendungsfälle: Zuerst relevante Dokumente abrufen, dann darauf basierend antworten – Wissen jenseits der Trainingsdaten.

RAG-Ablauf

Fünf Schritte:

  1. Dokumente laden – PDF, TXT, Markdown usw.
  2. Text splitten – lange Dokumente in suchbare Chunks
  3. Vektoren erzeugen – Embedding-Modell
  4. Index speichern – Vektordatenbank (hier ChromaDB)
  5. Retrieval + Generierung – bei Fragen relevante Chunks finden und antworten

Vollständiger, getesteter Code:

from langchain_ollama import ChatOllama, OllamaEmbeddings
from langchain_chroma import Chroma
from langchain_community.document_loaders import PyPDFLoader, TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough

# === 1. Dokumente laden ===
loader = TextLoader("./my_document.txt")  # eigenen Pfad setzen
docs = loader.load()

# === 2. Text splitten ===
# chunk_size=1000: ca. 1000 Zeichen pro Chunk
# chunk_overlap=200: Überlappung gegen Informationsbrüche
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,
    chunk_overlap=200
)
splits = text_splitter.split_documents(docs)

# === 3 & 4. Vektoren erzeugen und speichern ===
embeddings = OllamaEmbeddings(model="nomic-embed-text")
vectorstore = Chroma.from_documents(
    documents=splits,
    embedding=embeddings,
    persist_directory="./chroma_db"  # Persistenzpfad
)

# === 5. Retriever ===
# k=4: die 4 relevantesten Chunks
retriever = vectorstore.as_retriever(search_kwargs={"k": 4})

# === 6. RAG Chain ===
template = """Beantworte die Frage anhand des Kontexts. Wenn keine relevanten Infos vorliegen, sage klar „Keine relevanten Informationen im Dokument".

Kontext:
{context}

Frage: {question}
"""
prompt = ChatPromptTemplate.from_template(template)

llm = ChatOllama(model="llama3.1:8b")

# LCEL-Syntax: Komponenten mit | verketten
rag_chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)

# === 7. Abfrage ===
response = rag_chain.invoke("Was sind die Hauptinhalte des Dokuments?")
print(response)

Der Kern ist rag_chain – LCEL (LangChain Expression Language) verbindet Retriever, Prompt, Modell und Parser.

Praktische Parameter:

chunk_size: Bei dichten Tech-Docs 800; Prosa 1000–1500.

k: Meist 3–5 – zu viele Chunks verwässern, zu wenige lassen Details aus.

persist_directory ist Pflicht – sonst bei jedem Neustart neu embedden, langsam und teuer.

Beim ersten RAG-Versuch ohne Persistenz musste ich nach jedem Code-Change neu embedden. Mit persist_directory lädt der Index in Sekunden.

Agent in der Praxis: JSON-basiertes Tool-Calling

Der Unterschied zum normalen Chat: Der Agent ruft externe Tools auf.

Fragt jemand „Wie ist das Wetter in Peking?“, antwortet ein reines Chat-Modell oft erfunden. Ein Agent ruft zuerst eine Wetter-API auf und antwortet mit echten Daten.

Die Ollama-Grenze bei Tool-Calling

Offen gesagt: Ollama ist hier schwächer als OpenAI. OpenAI-Modelle unterstützen Function Calling nativ – wann und mit welchen Parametern ein Tool aufgerufen wird. Llama 3.1 und Co. sind noch nicht auf dem Niveau.

LangChains Lösung: JSON-based Agent.

Das Modell gibt strukturiertes JSON aus; das Framework parst es und wählt Tools. In Tests funktioniert das brauchbar – nicht so flüssig wie OpenAI, aber für Basisaufgaben ausreichend.

Eigene Tools

from langchain_ollama import ChatOllama
from langchain_core.tools import tool

@tool
def get_weather(city: str) -> str:
    """Wetterinformationen für eine Stadt abrufen"""
    weather_data = {
        "Peking": "Sonnig, 25°C, gute Luftqualität",
        "Shanghai": "Bewölkt, 22°C, leichter Regen möglich",
        "Shenzhen": "Heiß, 30°C, starke UV-Strahlung"
    }
    return weather_data.get(city, f"Keine Wetterdaten für {city}")

@tool
def calculate(expression: str) -> str:
    """Mathematische Berechnung ausführen"""
    try:
        result = eval(expression)  # Hinweis: in Produktion sicherer implementieren
        return f"Ergebnis: {result}"
    except:
        return "Berechnungsfehler – Ausdruck prüfen"

@tool
def search_local_docs(query: str) -> str:
    """Lokale Dokumentenbibliothek durchsuchen"""
    return f"Suche nach '{query}': 3 relevante Treffer gefunden"

@tool macht aus Funktionen LangChain-Tools. Der Docstring wird zur Tool-Beschreibung – das Modell wählt danach.

JSON Agent erstellen:

from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain_ollama import ChatOllama
from langchain_core.prompts import ChatPromptTemplate

llm = ChatOllama(model="llama3.1:8b")
tools = [get_weather, calculate, search_local_docs]

prompt = ChatPromptTemplate.from_messages([
    ("system", "Du bist ein hilfreicher Assistent mit Tool-Zugriff."),
    ("human", "{input}"),
    ("placeholder", "{agent_scratchpad}"),
])

agent = create_tool_calling_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

response = agent_executor.invoke({
    "input": "Wie ist das Wetter in Peking heute? Und berechne 23 + 45"
})

print(response["output"])

verbose=True zeigt den Entscheidungsprozess – hilfreich beim Debuggen.

Praxiserfahrung:

70–80 %
JSON-Agent-Erfolgsrate
Einfache Aufgaben meist ok, komplexe gelegentlich fehlerhaft
Source: Autoren-Erfahrungswerte

JSON Agent liegt bei ca. 70–80 % Erfolg. Wetter und Rechnen klappen meist; mehrere Tools kombiniert scheitern gelegentlich – falsches Format oder falsches Tool. Typisch für lokale LLM-Agents, weniger stabil als OpenAI.

Bei hohen Anforderungen:

  1. Stärkeres Modell (z. B. Qwen 2.5 oder DeepSeek)
  2. Weniger Tools, einfachere Abläufe
  3. OpenAI Function Calling – teurer, deutlich stabiler

OpenAI vs. Ollama: Wechsel per Zeile Code

Oft gefragt: LangChain-Code für beide Backends? Ja – erstaunlich einfach.

Variante 1: Import ändern

OpenAI-Code:

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4", temperature=0.7)
response = llm.invoke("Erkläre Quantencomputing")

Zu Ollama – nur der Import:

from langchain_ollama import ChatOllama

llm = ChatOllama(model="llama3.1:8b", temperature=0.7)
response = llm.invoke("Erkläre Quantencomputing")

Prompt-Vorlagen, Chains, Parser – unverändert. LangChains Abstraktion macht den Wechsel nahezu transparent.

Variante 2: OpenAI-kompatible API

Ollama kann sich als OpenAI ausgeben – Import bleibt:

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    model="llama3.1:8b",
    base_url="http://localhost:11434/v1",
    api_key="ollama"  # beliebig – Ollama prüft nicht
)

response = llm.invoke("Erkläre Quantencomputing")

Sinnvoll, wenn das Projekt schon ChatOpenAI nutzt und lokale Modelle testen soll.

Vergleich

KriteriumOpenAI (GPT-4)Ollama (Llama 3.1)
Kosten$0,03/1K Input-TokensKostenlos (lokale GPU-Strom)
DatenschutzCloud – Compliance beachtenLokal – Daten verlassen den Rechner nicht
Tool-CallingNativ, stabilJSON Agent, ca. 70–80 %
LatenzSchnell (Cloud, 1–3 s TTFB)Abhängig von GPU (3–10 s)
ModellstärkeGPT-4 top-tierLlama 3.1 8B solide, unter GPT-4

Empfehlung:

  • Lernen, Prototypen: Ollama – günstig, experimentierfreundlich
  • Produktion, hohe Last: OpenAI – Stabilität und Geschwindigkeit
  • Sensible Daten: Ollama – alles lokal
  • Komplexe Agent-Aufgaben: OpenAI – zuverlässigeres Tool-Calling

Ideal: Beides – Ollama in der Entwicklung, OpenAI live. Wechselkosten: eine Zeile.

Fazit

LangChain + Ollama – der Integrationspfad steht.

Von langchain-ollama über ChatOllama, OllamaLLM und OllamaEmbeddings zu drei Szenarien: Chat mit Streaming, RAG für lokale Dokumente, Agent mit JSON Agent als Kompromiss. OpenAI und Ollama wechseln sich per Zeile – von ~50 $/Monat auf kostenlos lokal.

Wann Ollama?

Sparen, Datenschutz oder LLM-Entwicklung lernen – lokal ausprobieren ohne Rechnungsschock.

Wann OpenAI?

Komplexe Agents, Produktion mit hoher Last, wenn Geschwindigkeit und Stabilität zählen. Lokale LLMs ersetzen die Cloud-Erfahrung noch nicht vollständig.

Einstieg: Chat – wenig Code, schneller Effekt. Danach RAG mit eigenen Dokumenten. Agent später – mehr Feintuning nötig.

In der Serie folgen Multi-Modell-Deployment, Performance-Tuning und Produktions-Deployment. Gerne weiterlesen.

Fragen in den Kommentaren oder auf GitHub. Die Beispiele sind getestet – Fehler meist fehlendes Modell oder Dependencies; Fehlermeldung folgen reicht meist.

LangChain + Ollama Integration

Von Installation und Konfiguration bis zu Chat, RAG und Agent – alles für die lokale LLM-App-Entwicklung

⏱️ Estimated time: 60 min

  1. 1

    Step 1: langchain-ollama installieren

    Installationsbefehl ausführen:

    ```bash
    pip install langchain-ollama
    ```

    Ollama muss installiert sein und ein Modell heruntergeladen (z. B. `ollama pull llama3.1:8b`).
  2. 2

    Step 2: Chat-App erstellen

    ChatOllama initialisieren und Nachricht senden:

    ```python
    from langchain_ollama import ChatOllama

    llm = ChatOllama(model="llama3.1:8b", temperature=0.7)
    response = llm.invoke("Hallo")
    print(response.content)
    ```

    Unterstützt Mehrturn-Dialog und Streaming.
  3. 3

    Step 3: RAG-Wissensbasis aufbauen

    Fünf Schritte:

    • Dokumente laden (TextLoader / PyPDFLoader)
    • Text splitten (RecursiveCharacterTextSplitter)
    • Vektoren erzeugen (OllamaEmbeddings)
    • Index speichern (ChromaDB)
    • Retrieval-Generierung (RAG Chain)

    Wichtige Parameter: chunk_size=1000, k=4, persist_directory unbedingt setzen.
  4. 4

    Step 4: Agent-Tool-Calling implementieren

    Tool-Funktionen definieren und JSON Agent erstellen:

    ```python
    @tool
    def get_weather(city: str) -> str:
    """Wetterinformationen abrufen"""
    ...

    agent = create_tool_calling_agent(llm, tools, prompt)
    agent_executor = AgentExecutor(agent=agent, tools=tools)
    ```

    Erfolgsrate ca. 70–80 %, komplexe Aufgaben besser mit OpenAI.
  5. 5

    Step 5: OpenAI / Ollama wechseln

    Variante 1: Import ändern

    ```python
    from langchain_ollama import ChatOllama # Ollama
    from langchain_openai import ChatOpenAI # OpenAI
    ```

    Variante 2: OpenAI-kompatible API (Import unverändert)

    ```python
    llm = ChatOpenAI(
    base_url="http://localhost:11434/v1",
    api_key="ollama"
    )
    ```

FAQ

Was ist der Unterschied zwischen langchain-ollama und langchain_community.llms.Ollama?
langchain-ollama ist das offizielle eigenständige Paket mit besseren Type Hints und Wartung im Takt der Hauptversion. langchain_community.llms.Ollama ist ein Community-Paket und kann jederzeit deprecated werden. Empfehlung: langchain-ollama.
ChatOllama oder OllamaLLM – was nehmen?
In 90 % der Fälle reicht ChatOllama. Es unterstützt Mehrturn-Dialog, Streaming und Nachrichtenverlauf. OllamaLLM eignet sich für Einmal-Textgenerierung oder Fortsetzungen.
Wie setzt man chunk_size und k in RAG-Systemen?
chunk_size: Für technische Dokumentation 800, für Prosa 1000–1500. k (Anzahl abgerufener Chunks): meist 3–5 – zu viele verwässern die Relevanz, zu wenige lassen Schlüsselinfos aus. persist_directory für persistente Vektordatenbank unbedingt setzen.
Warum ist Tool-Calling bei Ollama weniger stabil als bei OpenAI?
Ollama-Modelle (einschließlich Llama 3.1) haben kein natives Function Calling – JSON Agent lässt das Modell strukturiertes JSON ausgeben, Erfolgsrate ca. 70–80 %. OpenAI ist nativ stabiler; komplexe Agent-Aufgaben besser mit OpenAI.
Wie wechselt man zwischen OpenAI und Ollama?
Variante 1: Import ändern (ChatOpenAI ↔ ChatOllama). Variante 2: OpenAI-kompatible API – nur base_url und api_key anpassen. Prompt-Vorlagen, Chains und Output-Parser bleiben unverändert.
Eignet sich Ollama für Produktion?
Je nach Szenario. Lernen, Prototypen, datenschutzsensible Daten – Ollama passt. Hohe Last, komplexe Agent-Aufgaben, schnelle Antwortzeiten – OpenAI empfohlen. Ideal: Entwicklung mit Ollama, Go-Live mit OpenAI.

8 Min. Lesezeit · Veröffentlicht am: 7. Apr. 2026 · Aktualisiert am: 9. Juli 2026

Kommentare

Melde dich mit GitHub an, um einen Kommentar zu hinterlassen

Easton BlogEaston Blog