切换语言
切换主题

LangChain + Ollama 集成实战:本地 LLM 应用开发完全指南

上个月我看了一眼 OpenAI 的账单,$52.3。说实话,当时心里有点小崩溃——我一个个人开发者,偶尔玩玩 AI,居然花了这么多钱。然后我想起了本地跑着的 Ollama,免费的 Llama 3.1 就在那里等着我用。

但问题来了:直接调用 Ollama API 写应用,代码量有点多。请求格式、响应解析、错误处理……每写一次都觉得繁琐。这时候 LangChain 就派上用场了——一套封装好的接口,Chat、RAG、Agent 全都能用,还能一行代码切换模型。

本文是 Ollama 本地 LLM 实战指南系列的框架集成篇,会带你从 langchain-ollama 包入门,一路走到 Chat、RAG、Agent 三大实战场景。如果你已经读过系列前几篇(API 调用、多模型部署),这篇会把那些零散的知识串成一个完整的开发框架。

langchain-ollama 包入门

先说说我踩过的一个坑。之前我用的是 langchain_community.llms.Ollama,代码跑起来没问题,但总觉得哪里不对劲——每次查阅文档,看到的都是 “langchain-ollama” 这个包。后来才知道,LangChain 官方把 Ollama 集成拆成了一个独立包,就是 langchain-ollama

为什么推荐用官方包?

类型提示更完善,IDE 自动补全更友好。维护节奏跟 LangChain 主版本同步,不用担心兼容问题。还有就是社区包可能随时被废弃,官方包是长期方案——这点挺重要的,我之前踩过社区包废弃的坑。

安装一行命令搞定:

pip install langchain-ollama

装好后,你会发现这个包提供了三个核心类,各自对应不同的场景:

类名用途典型场景
ChatOllama对话模型多轮聊天、问答系统
OllamaLLM文本补全单次生成、文本续写
OllamaEmbeddings向量嵌入RAG、语义搜索

我实测下来,90% 的场景用 ChatOllama 就够了。对话模型支持多轮交互,还能流式输出——那种逐字显示的效果,用户体验比一次性返回整个回答好太多了。

一个最小示例,让你感受下有多简单:

from langchain_ollama import ChatOllama

# 初始化模型
llm = ChatOllama(
    model="llama3.1:8b",  # 模型名称,需要先在 Ollama 拉取
    temperature=0.7       # 随机性参数,0-1 之间
)

# 发送消息
response = llm.invoke("你好,请介绍一下你自己")
print(response.content)

运行这段代码前,确保你已经用 ollama pull llama3.1:8b 拉取了模型。如果还没装 Ollama,可以回看系列第一篇入门文章。

嵌入模型 OllamaEmbeddings 用法类似,主要用于把文本转成向量。后面 RAG 部分会详细用到,这里先给个简单示例:

from langchain_ollama import OllamaEmbeddings

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

# 单条文本嵌入
vector = embeddings.embed_query("这是一段测试文本")
print(f"向量维度: {len(vector)}")  # 通常输出 768 或更高

# 多条文本批量嵌入
vectors = embeddings.embed_documents([
    "第一段文本",
    "第二段文本"
])

nomic-embed-text 是目前主流的嵌入模型,专门为语义检索设计。向量维度高(通常 768+),检索效果比通用模型好不少。

Chat 应用实战:多轮对话与流式输出

单独调用一次 API 很简单,但真实的聊天场景要复杂得多——用户会连续追问,模型需要记住之前的对话内容。LangChain 用消息列表来处理这个问题。

多轮对话实现

LangChain 的消息类型有三种:

  • SystemMessage:设定模型角色和行为(比如”你是一个专业的程序员助手”)
  • HumanMessage:用户输入
  • AIMessage:模型回复

看代码:

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

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

# 构建对话历史
messages = [
    SystemMessage(content="你是一个擅长解释技术概念的开发者助手,回答要简洁易懂。"),
    HumanMessage(content="什么是 REST API?"),
    AIMessage(content="REST API 是一种网络服务接口设计风格,使用 HTTP 方法(GET/POST/PUT/DELETE)操作资源。简单说,就是用 URL 访问数据。"),
    HumanMessage(content="那 GraphQL 和它有什么区别?")
]

# 模型会基于整个对话历史生成回复
response = llm.invoke(messages)
print(response.content)

这段代码里,模型能看到之前的回答,知道用户是在追问 GraphQL 和 REST 的区别。如果没有 AIMessage 那条记录,模型可能会从头解释 GraphQL,用户体验就断了。

流式输出:让响应更有”活着”的感觉

流式输出的好处是用户不用盯着空白屏幕等结果——文字一个个蹦出来,像有人在打字。这种体验对长回答尤其重要。

from langchain_ollama import ChatOllama

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

# 流式输出
print("模型回答:", end="", flush=True)
for chunk in llm.stream("用 Python 写一个快速排序算法,并解释原理"):
    print(chunk.content, end="", flush=True)
print()  # 最后换行

stream() 方法返回一个迭代器,每个 chunk 包含一小段文本。flush=True 确保内容即时显示,不会缓存到缓冲区。

我实测过,流式输出的延迟感比一次性返回低很多——尤其是回答超过 100 字的时候。用户会觉得系统”在思考”,而不是”卡住了”。

RAG 应用实战:本地知识库检索

RAG(Retrieval-Augmented Generation)是目前最实用的 LLM 应用场景之一。简单说:先从文档库检索相关内容,再让模型基于这些内容生成回答。这样模型就能”知道”它训练数据里没有的信息。

RAG 流程拆解

一个完整的 RAG 系统包含五个步骤:

  1. 加载文档 —— 把 PDF、TXT、Markdown 等文件读进来
  2. 分割文本 —— 文档太长,切成小片段方便检索
  3. 生成向量 —— 用嵌入模型把文本转成数字向量
  4. 存储索引 —— 存到向量数据库(这里用 ChromaDB)
  5. 检索生成 —— 用户提问时,检索相关片段,让模型回答

下面是完整代码,我跑过一遍,能正常工作:

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. 加载文档 ===
# 支持 PDF、TXT、Markdown 等多种格式
loader = TextLoader("./my_document.txt")  # 替换成你的文档路径
docs = loader.load()

# === 2. 分割文本 ===
# chunk_size=1000 是常用参数,每个片段约 1000 字符
# chunk_overlap=200 让片段之间有重叠,避免信息断裂
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,
    chunk_overlap=200
)
splits = text_splitter.split_documents(docs)

# === 3 & 4. 生成向量并存储 ===
embeddings = OllamaEmbeddings(model="nomic-embed-text")
vectorstore = Chroma.from_documents(
    documents=splits,
    embedding=embeddings,
    persist_directory="./chroma_db"  # 持久化存储路径
)

# === 5. 构建检索器 ===
# search_kwargs={"k": 4} 表示检索最相关的 4 个片段
retriever = vectorstore.as_retriever(search_kwargs={"k": 4})

# === 6. 构建 RAG Chain ===
template = """基于以下上下文回答问题。如果上下文中没有相关信息,请明确说明"文档中没有相关信息"。

上下文:
{context}

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

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

# LangChain 的 LCEL 语法,用 | 符号串联各个组件
rag_chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)

# === 7. 查询 ===
response = rag_chain.invoke("文档的主要内容是什么?")
print(response)

这段代码看起来有点长,但拆开看其实很清晰。关键是 rag_chain 的构建——用 LangChain 的 LCEL(LangChain Expression Language)语法,把检索器、提示模板、模型、输出解析器串联起来。

几个实用参数调整建议

chunk_size 如果文档内容密集(技术文档),可以调到 800;如果是散文类内容,1000-1500 也行。

k 值(检索片段数量)通常 3-5 个就够了,太多会稀释相关性,太少可能漏掉关键信息。

persist_directory 一定要设置,不然每次重启都要重新构建向量库,耗时又浪费。

我第一次跑 RAG 的时候没设置持久化,结果每次改代码都要重新跑嵌入,慢得让人崩溃。后来加上 persist_directory,构建完的向量库直接加载,几秒就能启动。

Agent 应用实战:JSON-based 工具调用

Agent 和普通对话最大的区别是:Agent 能调用外部工具。

举个例子,用户问”北京今天天气怎么样”,普通对话模型只能瞎编一个答案。Agent 会先调用天气查询工具,拿到真实数据后再回答。

Ollama 工具调用的坑

这里有个问题要坦诚说:Ollama 的工具调用支持不如 OpenAI 完善。OpenAI 的模型原生支持 function calling,能准确识别什么时候该调用工具、怎么传参数。Ollama 的模型(包括 Llama 3.1)在这方面还不太成熟。

怎么办?LangChain 官方给出了一个方案:JSON-based Agent

思路是让模型输出结构化的 JSON,Agent 框架解析这个 JSON 来决定调用什么工具。实测下来,效果还不错——虽然不如 OpenAI 原生工具调用那么流畅,但能完成基本的任务。

自定义工具示例

先定义几个简单的工具函数:

from langchain_ollama import ChatOllama
from langchain_core.tools import tool

# 定义工具
@tool
def get_weather(city: str) -> str:
    """获取指定城市的天气信息"""
    # 这里是模拟数据,实际可接入天气 API
    weather_data = {
        "北京": "晴朗,25°C,空气质量良好",
        "上海": "多云,22°C,有小雨可能",
        "深圳": "炎热,30°C,紫外线强"
    }
    return weather_data.get(city, f"未找到 {city} 的天气数据")

@tool
def calculate(expression: str) -> str:
    """执行数学计算"""
    try:
        result = eval(expression)  # 注意:生产环境需更安全的实现
        return f"计算结果:{result}"
    except:
        return "计算错误,请检查表达式"

@tool
def search_local_docs(query: str) -> str:
    """搜索本地文档库"""
    # 这里可以接入前面 RAG 部分的检索器
    return f"搜索 '{query}' 的结果:找到了 3 条相关记录"

@tool 装饰器把普通函数变成 LangChain 工具。函数的 docstring 会自动变成工具描述,模型根据描述判断什么时候该用哪个工具。

然后创建 JSON Agent:

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", "你是一个有用的助手,可以使用工具完成任务。"),
    ("human", "{input}"),
    ("placeholder", "{agent_scratchpad}"),
])

# 创建 Agent
agent = create_tool_calling_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# 执行任务
response = agent_executor.invoke({
    "input": "帮我查一下北京今天的天气,然后计算 23 + 45"
})

print(response["output"])

verbose=True 会打印 Agent 的思考过程,方便调试。你会看到模型输出的工具调用决策过程。

实测体验

70-80%
JSON Agent 成功率
来源: 作者实测数据

我跑了几个任务,JSON Agent 的成功率大概 70-80%。简单任务(查天气、算数)基本没问题,复杂任务(多个工具组合)偶尔会出错——比如参数格式不对,或者选错工具。这是目前本地 LLM Agent 的通病,不像 OpenAI 那样稳定。

如果你对 Agent 要求比较高,可以考虑:

  1. 用更强的模型(比如 Qwen 2.5 或 DeepSeek)
  2. 简化任务流程,减少工具数量
  3. 或者干脆用 OpenAI 的原生工具调用,成本虽然高,但稳定性好太多

OpenAI vs Ollama:一行代码切换

很多人问我:LangChain 代码写得挺好的,能不能既用 OpenAI 又用 Ollama?答案是:能,而且简单到你不敢相信。

切换方式一:改 import

假设你有一段用 OpenAI 的代码:

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4", temperature=0.7)
response = llm.invoke("解释量子计算")

切换到 Ollama,只需要改一行 import:

from langchain_ollama import ChatOllama

llm = ChatOllama(model="llama3.1:8b", temperature=0.7)
response = llm.invoke("解释量子计算")

其他代码——提示模板、Chain 构建、输出解析——全部不用改。LangChain 的抽象层做得足够好,模型切换对业务逻辑几乎透明。

切换方式二:OpenAI-Compatible API

Ollama 还提供了一个”假装自己是 OpenAI” 的方式——OpenAI-Compatible API。好处是连 import 都不用改:

from langchain_openai import ChatOpenAI

# 只改 base_url 和 api_key,其他不动
llm = ChatOpenAI(
    model="llama3.1:8b",
    base_url="http://localhost:11434/v1",  # Ollama 的 OpenAI 兼容端点
    api_key="ollama"  # 随意填,Ollama 不验证
)

response = llm.invoke("解释量子计算")

这种方式适合什么场景?你的项目已经大量用了 ChatOpenAI,不想改代码结构,但又想测试本地模型的效果。

对比总结

说了这么多切换方法,到底什么时候该用 Ollama,什么时候该用 OpenAI?我把关键差异整理成一张表:

对比项OpenAI (GPT-4)Ollama (Llama 3.1)
成本$0.03/1K input tokens免费(消耗本地 GPU 电费)
隐私数据上传云端,合规敏感场景需谨慎本地处理,数据不出门
工具调用原生支持,稳定可靠需 JSON Agent,成功率 70-80%
响应速度快(云端优化,1-3 秒首字节)取决于本地 GPU(3-10 秒不等)
模型能力GPT-4 是目前最强之一Llama 3.1 8B 属中强,够用但不如 GPT-4

我的建议是:

  • 个人学习、原型开发:用 Ollama,省钱还能随便折腾
  • 生产环境、高并发:用 OpenAI,稳定性和响应速度有保障
  • 隐私敏感数据:用 Ollama,数据不出本地
  • 复杂 Agent 任务:用 OpenAI,工具调用更稳定

最理想的状态是两者都有——开发阶段用 Ollama 省成本,上线后用 OpenAI 保稳定。切换成本只有一行代码,何乐而不为。

总结

说到这里,LangChain + Ollama 的集成路径你已经有了完整的地图。

我们从 langchain-ollama 包入门,认识了 ChatOllama、OllamaLLM、OllamaEmbeddings 三大核心类。然后分别实战了三种场景:Chat 多轮对话(流式输出让体验更流畅)、RAG 知识库检索(本地文档变智能问答)、Agent 工具调用(JSON Agent 是目前的折中方案)。最后对比了 OpenAI 和 Ollama 的切换策略——一行代码就能切换,成本从每月 $50 变成免费。

什么时候选 Ollama?

一句话:当你想省钱、保隐私、或者只是想学习 LLM 开发的时候。本地跑起来,随便折腾,不用担心账单爆炸。

什么时候还是得用 OpenAI?

复杂 Agent 任务、高并发生产环境、对响应速度和稳定性要求高的场景。本地 LLM 目前还替代不了云端后的体验。

如果你还没动手试试,建议先从 Chat 场景开始——代码最简单,效果最直观。跑通后再尝试 RAG,把本地文档接入进来,感受”模型能读懂你的资料”的那种惊喜。Agent 可以放后面,因为工具调用的坑还有点多,需要耐心调试。

系列后面还有更多内容:多模型部署(如何在 LangChain 中切换不同模型)、性能调优(让本地 LLM 跑得更快)、生产部署(把本地应用变成可用的服务)。感兴趣的话可以继续跟进。

有问题欢迎在评论区聊,或者直接去 GitHub 找我。代码示例我都跑过一遍,应该能正常工作——如果遇到报错,多半是模型没拉取或者依赖没装好,按报错信息排查就行。

LangChain + Ollama 集成开发

从安装配置到 Chat、RAG、Agent 三大场景实战,一站式掌握本地 LLM 应用开发

⏱️ 预计耗时: 60 分钟

  1. 1

    步骤1: 安装 langchain-ollama 包

    运行安装命令:

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

    确保已安装 Ollama 并拉取模型(如 `ollama pull llama3.1:8b`)。
  2. 2

    步骤2: 创建 Chat 应用

    初始化 ChatOllama 并发送消息:

    ```python
    from langchain_ollama import ChatOllama

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

    支持多轮对话和流式输出。
  3. 3

    步骤3: 构建 RAG 知识库

    五步流程:

    • 加载文档(TextLoader / PyPDFLoader)
    • 分割文本(RecursiveCharacterTextSplitter)
    • 生成向量(OllamaEmbeddings)
    • 存储索引(ChromaDB)
    • 检索生成(RAG Chain)

    关键参数:chunk_size=1000, k=4, persist_directory 必设。
  4. 4

    步骤4: 实现 Agent 工具调用

    定义工具函数并创建 JSON Agent:

    ```python
    @tool
    def get_weather(city: str) -> str:
    """获取天气信息"""
    ...

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

    成功率约 70-80%,复杂任务建议用 OpenAI。
  5. 5

    步骤5: 切换 OpenAI / Ollama

    方式一:改 import

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

    方式二:OpenAI-Compatible API(不改 import)

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

常见问题

langchain-ollama 和 langchain_community.llms.Ollama 有什么区别?
langchain-ollama 是官方独立包,类型提示更完善,维护节奏与主版本同步。langchain_community.llms.Ollama 是社区包,可能随时废弃。推荐使用官方包 langchain-ollama。
ChatOllama 和 OllamaLLM 该用哪个?
90% 的场景用 ChatOllama 就够了。它支持多轮对话、流式输出、消息历史。OllamaLLM 适合单次文本生成或续写场景。
RAG 系统中 chunk_size 和 k 值怎么设置?
chunk_size:技术文档建议 800,散文类内容可 1000-1500。k 值(检索片段数)通常 3-5 个,太多会稀释相关性,太少可能漏关键信息。务必设置 persist_directory 持久化向量库。
Ollama 的工具调用为什么不如 OpenAI 稳定?
Ollama 模型(包括 Llama 3.1)没有原生 function calling 支持,需要用 JSON Agent 方案让模型输出结构化 JSON,成功率约 70-80%。OpenAI 原生工具调用更稳定,复杂 Agent 任务建议用 OpenAI。
如何在 OpenAI 和 Ollama 之间切换?
方式一:改 import(ChatOpenAI 换成 ChatOllama)。方式二:用 OpenAI-Compatible API,只改 base_url 和 api_key。其他代码(提示模板、Chain、输出解析)完全不用改。
Ollama 适合生产环境吗?
取决于场景。个人学习、原型开发、隐私敏感数据——适合用 Ollama。高并发生产环境、复杂 Agent 任务、对响应速度要求高——建议用 OpenAI。理想方案是开发用 Ollama 省成本,上线用 OpenAI 保稳定。

12 分钟阅读 · 发布于: 2026年4月7日 · 修改于: 2026年4月8日

评论

使用 GitHub 账号登录后即可评论

相关文章